diff --git a/ChangeLog b/ChangeLog index 7c7d9da383..b5e3a0b8c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2003-09-12 Michael Natterer + + Added support for permanently showing the visible vectors, not + only when the vectors tool is active: + + * app/display/gimpdisplayshell.[ch]: added + gimp_display_shell_draw_vector() which draws a single GimpVectors + object and gimp_display_shell_draw_vectors() which draws all + visible ones. Added "gint paused_count" and new functions + gimp_display_shell_paunse()/resume(). Pause/resume the active tool + and draw/undraw the visible vectors when paused_count changes from + 0 to 1 and from 1 to 0. + + * app/display/gimpdisplayshell-callbacks.c + * app/display/gimpdisplayshell-scale.c + * app/display/gimpdisplayshell-scroll.c: call the new + freeze()/thaw() functions instead of calling the tool_manager + directly. Removes the tools/ sependency from the scale and scroll + files. Also draw the vectors once when the canvas is realized so + XOR drawing is in the correct state. + + * app/display/gimpdisplayshell-handlers.c: connect to + image->vectors' "add" and "remove" signal and to the "freeze", + "thaw" and "visibility_changed" signals of all vectors in + image->vectors and update vectors drawing accordingly. + 2003-09-11 Michael Natterer * app/core/gimpdrawable.[ch]: removed "visible" and all its API... diff --git a/app/display/gimpdisplayshell-callbacks.c b/app/display/gimpdisplayshell-callbacks.c index 4209997781..495749ef20 100644 --- a/app/display/gimpdisplayshell-callbacks.c +++ b/app/display/gimpdisplayshell-callbacks.c @@ -298,6 +298,8 @@ gimp_display_shell_canvas_realize (GtkWidget *canvas, /* allow shrinking */ gtk_widget_set_size_request (GTK_WIDGET (shell), 0, 0); + + gimp_display_shell_draw_vectors (shell); } gboolean @@ -328,9 +330,7 @@ gimp_display_shell_canvas_expose (GtkWidget *widget, gint n_rects; gint i; - /* pause the currently active tool */ - tool_manager_control_active (shell->gdisp->gimage->gimp, PAUSE, - shell->gdisp); + gimp_display_shell_pause (shell); gdk_region_get_rectangles (eevent->region, &rects, &n_rects); @@ -356,9 +356,7 @@ gimp_display_shell_canvas_expose (GtkWidget *widget, /* restart (and recalculate) the selection boundaries */ gimp_display_shell_selection_start (shell->select, TRUE); - /* start the currently active tool */ - tool_manager_control_active (shell->gdisp->gimage->gimp, RESUME, - shell->gdisp); + gimp_display_shell_resume (shell); return TRUE; } diff --git a/app/display/gimpdisplayshell-draw.c b/app/display/gimpdisplayshell-draw.c index 0f537a988c..f17668919b 100644 --- a/app/display/gimpdisplayshell-draw.c +++ b/app/display/gimpdisplayshell-draw.c @@ -41,12 +41,14 @@ #include "core/gimpimage-snap.h" #include "core/gimplayer.h" #include "core/gimplayermask.h" +#include "core/gimplist.h" #include "core/gimpmarshal.h" #include "core/gimppattern.h" #include "file/file-utils.h" #include "vectors/gimpvectors.h" +#include "vectors/gimpstroke.h" #include "widgets/gimpcolorpanel.h" #include "widgets/gimpdnd.h" @@ -289,6 +291,8 @@ gimp_display_shell_init (GimpDisplayShell *shell) 0.0, 0.0, 0.0, 1.0); shell->fullscreen_appearance.padding_mode_set = FALSE; + shell->paused_count = 0; + gtk_window_set_wmclass (GTK_WINDOW (shell), "image_window", "Gimp"); gtk_window_set_resizable (GTK_WINDOW (shell), TRUE); @@ -1170,6 +1174,41 @@ gimp_display_shell_flush (GimpDisplayShell *shell) gimp_display_shell_update_title (shell); } +void +gimp_display_shell_pause (GimpDisplayShell *shell) +{ + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + + shell->paused_count++; + + if (shell->paused_count == 1) + { + /* pause the currently active tool */ + tool_manager_control_active (shell->gdisp->gimage->gimp, PAUSE, + shell->gdisp); + + gimp_display_shell_draw_vectors (shell); + } +} + +void +gimp_display_shell_resume (GimpDisplayShell *shell) +{ + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + g_return_if_fail (shell->paused_count > 0); + + shell->paused_count--; + + if (shell->paused_count == 0) + { + gimp_display_shell_draw_vectors (shell); + + /* start the currently active tool */ + tool_manager_control_active (shell->gdisp->gimage->gimp, RESUME, + shell->gdisp); + } +} + void gimp_display_shell_update_icon (GimpDisplayShell *shell) { @@ -1508,6 +1547,91 @@ gimp_display_shell_draw_grid (GimpDisplayShell *shell) } } +void +gimp_display_shell_draw_vector (GimpDisplayShell *shell, + GimpVectors *vectors) +{ + static GdkGC *xor_gc = NULL; + GimpStroke *stroke = NULL; + + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + g_return_if_fail (GIMP_IS_VECTORS (vectors)); + + if (! xor_gc) + { + GdkColor fg; + GdkColor bg; + + xor_gc = gdk_gc_new (shell->canvas->window); + + gdk_gc_set_function (xor_gc, GDK_INVERT); + fg.pixel = 0xFFFFFFFF; + bg.pixel = 0x00000000; + gdk_gc_set_foreground (xor_gc, &fg); + gdk_gc_set_background (xor_gc, &bg); + gdk_gc_set_line_attributes (xor_gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, + GDK_JOIN_MITER); + } + + while ((stroke = gimp_vectors_stroke_get_next (vectors, stroke))) + { + GArray *coords; + gboolean closed; + + coords = gimp_stroke_interpolate (stroke, 1.0, &closed); + + if (coords->len) + { + GimpCoords *coord; + GdkPoint *gdk_coords; + gint i; + gdouble sx, sy; + + gdk_coords = g_new (GdkPoint, coords->len); + + for (i = 0; i < coords->len; i++) + { + coord = &g_array_index (coords, GimpCoords, i); + + gimp_display_shell_transform_xy_f (shell, + coord->x, coord->y, + &sx, &sy, + FALSE); + gdk_coords[i].x = ROUND (sx); + gdk_coords[i].y = ROUND (sy); + } + + gdk_draw_lines (shell->canvas->window, xor_gc, + gdk_coords, coords->len); + + g_free (gdk_coords); + } + + g_array_free (coords, TRUE); + } +} + +void +gimp_display_shell_draw_vectors (GimpDisplayShell *shell) +{ + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + + if (TRUE /* gimp_display_shell_get_show_vectors (shell) */) + { + GList *list; + + for (list = GIMP_LIST (shell->gdisp->gimage->vectors)->list; + list; + list = list->next) + { + GimpVectors *vectors = list->data; + + if (gimp_item_get_visible (GIMP_ITEM (vectors))) + gimp_display_shell_draw_vector (shell, vectors); + } + } +} + void gimp_display_shell_draw_area (GimpDisplayShell *shell, gint x, diff --git a/app/display/gimpdisplayshell-draw.h b/app/display/gimpdisplayshell-draw.h index 908e1c827e..d34d034928 100644 --- a/app/display/gimpdisplayshell-draw.h +++ b/app/display/gimpdisplayshell-draw.h @@ -170,6 +170,12 @@ struct _GimpDisplayShell GimpDisplayShellAppearance appearance; GimpDisplayShellAppearance fullscreen_appearance; + + gint paused_count; + + GQuark vectors_freeze_handler; + GQuark vectors_thaw_handler; + GQuark vectors_visible_handler; }; struct _GimpDisplayShellClass @@ -222,6 +228,9 @@ void gimp_display_shell_expose_full (GimpDisplayShell *shell); void gimp_display_shell_flush (GimpDisplayShell *shell); +void gimp_display_shell_pause (GimpDisplayShell *shell); +void gimp_display_shell_resume (GimpDisplayShell *shell); + void gimp_display_shell_draw_area (GimpDisplayShell *shell, gint x, gint y, @@ -235,6 +244,10 @@ void gimp_display_shell_draw_guides (GimpDisplayShell *shell); void gimp_display_shell_draw_grid (GimpDisplayShell *shell); +void gimp_display_shell_draw_vector (GimpDisplayShell *shell, + GimpVectors *vectors); +void gimp_display_shell_draw_vectors (GimpDisplayShell *shell); + void gimp_display_shell_update_icon (GimpDisplayShell *shell); void gimp_display_shell_shrink_wrap (GimpDisplayShell *shell); diff --git a/app/display/gimpdisplayshell-handlers.c b/app/display/gimpdisplayshell-handlers.c index ba01863cc9..2799ae8303 100644 --- a/app/display/gimpdisplayshell-handlers.c +++ b/app/display/gimpdisplayshell-handlers.c @@ -27,7 +27,9 @@ #include "config/gimpdisplayconfig.h" #include "core/gimp.h" +#include "core/gimpcontainer.h" #include "core/gimpimage.h" +#include "core/gimpitem.h" #include "widgets/gimpwidgets-utils.h" @@ -73,6 +75,19 @@ static void gimp_display_shell_update_guide_handler (GimpImage *g static void gimp_display_shell_invalidate_preview_handler (GimpImage *gimage, GimpDisplayShell *shell); +static void gimp_display_shell_vectors_freeze_handler (GimpVectors *vectors, + GimpDisplayShell *shell); +static void gimp_display_shell_vectors_thaw_handler (GimpVectors *vectors, + GimpDisplayShell *shell); +static void gimp_display_shell_vectors_visible_handler (GimpVectors *vectors, + GimpDisplayShell *shell); +static void gimp_display_shell_vectors_add_handler (GimpContainer *container, + GimpVectors *vectors, + GimpDisplayShell *shell); +static void gimp_display_shell_vectors_remove_handler (GimpContainer *container, + GimpVectors *vectors, + GimpDisplayShell *shell); + static void gimp_display_shell_check_notify_handler (GObject *config, GParamSpec *param_spec, GimpDisplayShell *shell); @@ -148,6 +163,26 @@ gimp_display_shell_connect (GimpDisplayShell *shell) G_CALLBACK (gimp_display_shell_invalidate_preview_handler), shell); + shell->vectors_freeze_handler = + gimp_container_add_handler (gimage->vectors, "freeze", + G_CALLBACK (gimp_display_shell_vectors_freeze_handler), + shell); + shell->vectors_thaw_handler = + gimp_container_add_handler (gimage->vectors, "thaw", + G_CALLBACK (gimp_display_shell_vectors_thaw_handler), + shell); + shell->vectors_visible_handler = + gimp_container_add_handler (gimage->vectors, "visibility_changed", + G_CALLBACK (gimp_display_shell_vectors_visible_handler), + shell); + + g_signal_connect (gimage->vectors, "add", + G_CALLBACK (gimp_display_shell_vectors_add_handler), + shell); + g_signal_connect (gimage->vectors, "remove", + G_CALLBACK (gimp_display_shell_vectors_remove_handler), + shell); + g_signal_connect (gimage->gimp->config, "notify::transparency-size", G_CALLBACK (gimp_display_shell_check_notify_handler), @@ -241,6 +276,20 @@ gimp_display_shell_disconnect (GimpDisplayShell *shell) gimp_display_shell_check_notify_handler, shell); + g_signal_handlers_disconnect_by_func (gimage->vectors, + gimp_display_shell_vectors_remove_handler, + shell); + g_signal_handlers_disconnect_by_func (gimage->vectors, + gimp_display_shell_vectors_add_handler, + shell); + + gimp_container_remove_handler (gimage->vectors, + shell->vectors_visible_handler); + gimp_container_remove_handler (gimage->vectors, + shell->vectors_thaw_handler); + gimp_container_remove_handler (gimage->vectors, + shell->vectors_freeze_handler); + g_signal_handlers_disconnect_by_func (gimage, gimp_display_shell_invalidate_preview_handler, shell); @@ -404,6 +453,48 @@ gimp_display_shell_invalidate_preview_handler (GimpImage *gimage, NULL); } +static void +gimp_display_shell_vectors_freeze_handler (GimpVectors *vectors, + GimpDisplayShell *shell) +{ + if (shell->paused_count == 0 && gimp_item_get_visible (GIMP_ITEM (vectors))) + gimp_display_shell_draw_vector (shell, vectors); +} + +static void +gimp_display_shell_vectors_thaw_handler (GimpVectors *vectors, + GimpDisplayShell *shell) +{ + if (shell->paused_count == 0 && gimp_item_get_visible (GIMP_ITEM (vectors))) + gimp_display_shell_draw_vector (shell, vectors); +} + +static void +gimp_display_shell_vectors_visible_handler (GimpVectors *vectors, + GimpDisplayShell *shell) +{ + if (shell->paused_count == 0) + gimp_display_shell_draw_vector (shell, vectors); +} + +static void +gimp_display_shell_vectors_add_handler (GimpContainer *container, + GimpVectors *vectors, + GimpDisplayShell *shell) +{ + if (shell->paused_count == 0 && gimp_item_get_visible (GIMP_ITEM (vectors))) + gimp_display_shell_draw_vector (shell, vectors); +} + +static void +gimp_display_shell_vectors_remove_handler (GimpContainer *container, + GimpVectors *vectors, + GimpDisplayShell *shell) +{ + if (shell->paused_count == 0 && gimp_item_get_visible (GIMP_ITEM (vectors))) + gimp_display_shell_draw_vector (shell, vectors); +} + static void gimp_display_shell_check_notify_handler (GObject *config, GParamSpec *param_spec, diff --git a/app/display/gimpdisplayshell-scale.c b/app/display/gimpdisplayshell-scale.c index 11b229aacb..49b2e37f83 100644 --- a/app/display/gimpdisplayshell-scale.c +++ b/app/display/gimpdisplayshell-scale.c @@ -32,10 +32,6 @@ #include "core/gimp.h" #include "core/gimpimage.h" -#include "tools/tools-types.h" - -#include "tools/tool_manager.h" - #include "widgets/gimphelp-ids.h" #include "widgets/gimpviewabledialog.h" @@ -301,7 +297,7 @@ gimp_display_shell_scale_set_dot_for_dot (GimpDisplayShell *shell, Gimp *gimp = shell->gdisp->gimage->gimp; /* freeze the active tool */ - tool_manager_control_active (gimp, PAUSE, shell->gdisp); + gimp_display_shell_pause (shell); shell->dot_for_dot = dot_for_dot; @@ -312,7 +308,7 @@ gimp_display_shell_scale_set_dot_for_dot (GimpDisplayShell *shell, TRUE); /* re-enable the active tool */ - tool_manager_control_active (gimp, RESUME, shell->gdisp); + gimp_display_shell_resume (shell); } } @@ -402,7 +398,7 @@ gimp_display_shell_scale_by_values (GimpDisplayShell *shell, gimp = shell->gdisp->gimage->gimp; /* freeze the active tool */ - tool_manager_control_active (gimp, PAUSE, shell->gdisp); + gimp_display_shell_pause (shell); shell->scale = scale; shell->offset_x = offset_x; @@ -411,7 +407,7 @@ gimp_display_shell_scale_by_values (GimpDisplayShell *shell, gimp_display_shell_scale_resize (shell, resize_window, TRUE); /* re-enable the active tool */ - tool_manager_control_active (gimp, RESUME, shell->gdisp); + gimp_display_shell_resume (shell); } void @@ -434,7 +430,7 @@ gimp_display_shell_scale_resize (GimpDisplayShell *shell, gimp = shell->gdisp->gimage->gimp; /* freeze the active tool */ - tool_manager_control_active (gimp, PAUSE, shell->gdisp); + gimp_display_shell_pause (shell); if (resize_window) gimp_display_shell_shrink_wrap (shell); @@ -447,7 +443,7 @@ gimp_display_shell_scale_resize (GimpDisplayShell *shell, gimp_display_shell_expose_full (shell); /* re-enable the active tool */ - tool_manager_control_active (gimp, RESUME, shell->gdisp); + gimp_display_shell_resume (shell); } void diff --git a/app/display/gimpdisplayshell-scroll.c b/app/display/gimpdisplayshell-scroll.c index c570eec918..04f5557137 100644 --- a/app/display/gimpdisplayshell-scroll.c +++ b/app/display/gimpdisplayshell-scroll.c @@ -26,10 +26,6 @@ #include "core/gimpimage.h" -#include "tools/tools-types.h" - -#include "tools/tool_manager.h" - #include "gimpdisplay.h" #include "gimpdisplay-foreach.h" #include "gimpdisplayshell.h" @@ -65,8 +61,7 @@ gimp_display_shell_scroll (GimpDisplayShell *shell, shell->offset_x = old_x; shell->offset_y = old_y; - tool_manager_control_active (shell->gdisp->gimage->gimp, PAUSE, - shell->gdisp); + gimp_display_shell_pause (shell); /* set the offsets back to the new values */ shell->offset_x += x_offset; @@ -80,8 +75,7 @@ gimp_display_shell_scroll (GimpDisplayShell *shell, /* Update scrollbars and rulers */ gimp_display_shell_scale_setup (shell); - tool_manager_control_active (shell->gdisp->gimage->gimp, RESUME, - shell->gdisp); + gimp_display_shell_resume (shell); gimp_display_shell_scrolled (shell); diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c index 0f537a988c..f17668919b 100644 --- a/app/display/gimpdisplayshell.c +++ b/app/display/gimpdisplayshell.c @@ -41,12 +41,14 @@ #include "core/gimpimage-snap.h" #include "core/gimplayer.h" #include "core/gimplayermask.h" +#include "core/gimplist.h" #include "core/gimpmarshal.h" #include "core/gimppattern.h" #include "file/file-utils.h" #include "vectors/gimpvectors.h" +#include "vectors/gimpstroke.h" #include "widgets/gimpcolorpanel.h" #include "widgets/gimpdnd.h" @@ -289,6 +291,8 @@ gimp_display_shell_init (GimpDisplayShell *shell) 0.0, 0.0, 0.0, 1.0); shell->fullscreen_appearance.padding_mode_set = FALSE; + shell->paused_count = 0; + gtk_window_set_wmclass (GTK_WINDOW (shell), "image_window", "Gimp"); gtk_window_set_resizable (GTK_WINDOW (shell), TRUE); @@ -1170,6 +1174,41 @@ gimp_display_shell_flush (GimpDisplayShell *shell) gimp_display_shell_update_title (shell); } +void +gimp_display_shell_pause (GimpDisplayShell *shell) +{ + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + + shell->paused_count++; + + if (shell->paused_count == 1) + { + /* pause the currently active tool */ + tool_manager_control_active (shell->gdisp->gimage->gimp, PAUSE, + shell->gdisp); + + gimp_display_shell_draw_vectors (shell); + } +} + +void +gimp_display_shell_resume (GimpDisplayShell *shell) +{ + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + g_return_if_fail (shell->paused_count > 0); + + shell->paused_count--; + + if (shell->paused_count == 0) + { + gimp_display_shell_draw_vectors (shell); + + /* start the currently active tool */ + tool_manager_control_active (shell->gdisp->gimage->gimp, RESUME, + shell->gdisp); + } +} + void gimp_display_shell_update_icon (GimpDisplayShell *shell) { @@ -1508,6 +1547,91 @@ gimp_display_shell_draw_grid (GimpDisplayShell *shell) } } +void +gimp_display_shell_draw_vector (GimpDisplayShell *shell, + GimpVectors *vectors) +{ + static GdkGC *xor_gc = NULL; + GimpStroke *stroke = NULL; + + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + g_return_if_fail (GIMP_IS_VECTORS (vectors)); + + if (! xor_gc) + { + GdkColor fg; + GdkColor bg; + + xor_gc = gdk_gc_new (shell->canvas->window); + + gdk_gc_set_function (xor_gc, GDK_INVERT); + fg.pixel = 0xFFFFFFFF; + bg.pixel = 0x00000000; + gdk_gc_set_foreground (xor_gc, &fg); + gdk_gc_set_background (xor_gc, &bg); + gdk_gc_set_line_attributes (xor_gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, + GDK_JOIN_MITER); + } + + while ((stroke = gimp_vectors_stroke_get_next (vectors, stroke))) + { + GArray *coords; + gboolean closed; + + coords = gimp_stroke_interpolate (stroke, 1.0, &closed); + + if (coords->len) + { + GimpCoords *coord; + GdkPoint *gdk_coords; + gint i; + gdouble sx, sy; + + gdk_coords = g_new (GdkPoint, coords->len); + + for (i = 0; i < coords->len; i++) + { + coord = &g_array_index (coords, GimpCoords, i); + + gimp_display_shell_transform_xy_f (shell, + coord->x, coord->y, + &sx, &sy, + FALSE); + gdk_coords[i].x = ROUND (sx); + gdk_coords[i].y = ROUND (sy); + } + + gdk_draw_lines (shell->canvas->window, xor_gc, + gdk_coords, coords->len); + + g_free (gdk_coords); + } + + g_array_free (coords, TRUE); + } +} + +void +gimp_display_shell_draw_vectors (GimpDisplayShell *shell) +{ + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + + if (TRUE /* gimp_display_shell_get_show_vectors (shell) */) + { + GList *list; + + for (list = GIMP_LIST (shell->gdisp->gimage->vectors)->list; + list; + list = list->next) + { + GimpVectors *vectors = list->data; + + if (gimp_item_get_visible (GIMP_ITEM (vectors))) + gimp_display_shell_draw_vector (shell, vectors); + } + } +} + void gimp_display_shell_draw_area (GimpDisplayShell *shell, gint x, diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h index 908e1c827e..d34d034928 100644 --- a/app/display/gimpdisplayshell.h +++ b/app/display/gimpdisplayshell.h @@ -170,6 +170,12 @@ struct _GimpDisplayShell GimpDisplayShellAppearance appearance; GimpDisplayShellAppearance fullscreen_appearance; + + gint paused_count; + + GQuark vectors_freeze_handler; + GQuark vectors_thaw_handler; + GQuark vectors_visible_handler; }; struct _GimpDisplayShellClass @@ -222,6 +228,9 @@ void gimp_display_shell_expose_full (GimpDisplayShell *shell); void gimp_display_shell_flush (GimpDisplayShell *shell); +void gimp_display_shell_pause (GimpDisplayShell *shell); +void gimp_display_shell_resume (GimpDisplayShell *shell); + void gimp_display_shell_draw_area (GimpDisplayShell *shell, gint x, gint y, @@ -235,6 +244,10 @@ void gimp_display_shell_draw_guides (GimpDisplayShell *shell); void gimp_display_shell_draw_grid (GimpDisplayShell *shell); +void gimp_display_shell_draw_vector (GimpDisplayShell *shell, + GimpVectors *vectors); +void gimp_display_shell_draw_vectors (GimpDisplayShell *shell); + void gimp_display_shell_update_icon (GimpDisplayShell *shell); void gimp_display_shell_shrink_wrap (GimpDisplayShell *shell);