[gimp] app: add a "visible" property and API to GimpCanvasItem
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: add a "visible" property and API to GimpCanvasItem
- Date: Fri, 1 Oct 2010 18:52:23 +0000 (UTC)
commit 10111126aed16c27ddf0ab24d363327054f70991
Author: Michael Natterer <mitch gimp org>
Date: Fri Oct 1 20:41:27 2010 +0200
app: add a "visible" property and API to GimpCanvasItem
and use it to set visibility of guides and sample points, so this
reression is fixed.
- return NULL extents for invisible items and never draw them
- do nothing for invisible items in more places, like the group
While hacking this, it turned out that it was a braino to collect an
item's region before and after a change in
dispatch_properties_changed(), so a new update had to be devised:
- add a "change count" and new API begin_change()/end_change()
- in begin_change(), remember the item's extents before the change
- in end_change(), combine old and current extents and emit "update"
- add some protected function to emit "update", and to figure if
it makes sense at all to emit "update" on an item.
app/display/gimpcanvasgroup.c | 31 +++--
app/display/gimpcanvasitem.c | 194 ++++++++++++++++++++++-------
app/display/gimpcanvasitem.h | 10 ++
app/display/gimpdisplayshell-appearance.c | 17 +--
app/display/gimpdisplayshell-handlers.c | 4 +
5 files changed, 186 insertions(+), 70 deletions(-)
---
diff --git a/app/display/gimpcanvasgroup.c b/app/display/gimpcanvasgroup.c
index ad123e6..75da839 100644
--- a/app/display/gimpcanvasgroup.c
+++ b/app/display/gimpcanvasgroup.c
@@ -230,7 +230,8 @@ gimp_canvas_group_child_update (GimpCanvasItem *item,
GdkRegion *region,
GimpCanvasGroup *group)
{
- g_signal_emit_by_name (group, "update", region);
+ if (_gimp_canvas_item_needs_update (GIMP_CANVAS_ITEM (group)))
+ _gimp_canvas_item_update (GIMP_CANVAS_ITEM (group), region);
}
@@ -251,7 +252,6 @@ gimp_canvas_group_add_item (GimpCanvasGroup *group,
GimpCanvasItem *item)
{
GimpCanvasGroupPrivate *private;
- GdkRegion *region;
g_return_if_fail (GIMP_IS_CANVAS_GROUP (group));
g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
@@ -267,12 +267,15 @@ gimp_canvas_group_add_item (GimpCanvasGroup *group,
private->items = g_list_append (private->items, g_object_ref (item));
- region = gimp_canvas_item_get_extents (item);
-
- if (region)
+ if (_gimp_canvas_item_needs_update (GIMP_CANVAS_ITEM (group)))
{
- g_signal_emit_by_name (group, "update", region);
- gdk_region_destroy (region);
+ GdkRegion *region = gimp_canvas_item_get_extents (item);
+
+ if (region)
+ {
+ _gimp_canvas_item_update (GIMP_CANVAS_ITEM (group), region);
+ gdk_region_destroy (region);
+ }
}
g_signal_connect (item, "update",
@@ -285,7 +288,6 @@ gimp_canvas_group_remove_item (GimpCanvasGroup *group,
GimpCanvasItem *item)
{
GimpCanvasGroupPrivate *private;
- GdkRegion *region;
g_return_if_fail (GIMP_IS_CANVAS_GROUP (group));
g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
@@ -296,12 +298,15 @@ gimp_canvas_group_remove_item (GimpCanvasGroup *group,
private->items = g_list_remove (private->items, item);
- region = gimp_canvas_item_get_extents (item);
-
- if (region)
+ if (_gimp_canvas_item_needs_update (GIMP_CANVAS_ITEM (group)))
{
- g_signal_emit_by_name (group, "update", region);
- gdk_region_destroy (region);
+ GdkRegion *region = gimp_canvas_item_get_extents (item);
+
+ if (region)
+ {
+ _gimp_canvas_item_update (GIMP_CANVAS_ITEM (group), region);
+ gdk_region_destroy (region);
+ }
}
g_signal_handlers_disconnect_by_func (item,
diff --git a/app/display/gimpcanvasitem.c b/app/display/gimpcanvasitem.c
index 6304927..ff467e6 100644
--- a/app/display/gimpcanvasitem.c
+++ b/app/display/gimpcanvasitem.c
@@ -38,6 +38,7 @@ enum
{
PROP_0,
PROP_SHELL,
+ PROP_VISIBLE,
PROP_LINE_CAP,
PROP_HIGHLIGHT
};
@@ -54,10 +55,13 @@ typedef struct _GimpCanvasItemPrivate GimpCanvasItemPrivate;
struct _GimpCanvasItemPrivate
{
GimpDisplayShell *shell;
+ gboolean visible;
cairo_line_cap_t line_cap;
gboolean highlight;
gint suspend_stroking;
gint suspend_filling;
+ gint change_count;
+ GdkRegion *change_region;
};
#define GET_PRIVATE(item) \
@@ -136,6 +140,12 @@ gimp_canvas_item_class_init (GimpCanvasItemClass *klass)
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class, PROP_VISIBLE,
+ g_param_spec_boolean ("visible",
+ NULL, NULL,
+ TRUE,
+ GIMP_PARAM_READWRITE));
+
g_object_class_install_property (object_class, PROP_LINE_CAP,
g_param_spec_int ("line-cap",
NULL, NULL,
@@ -159,10 +169,13 @@ gimp_canvas_item_init (GimpCanvasItem *item)
GimpCanvasItemPrivate *private = GET_PRIVATE (item);
private->shell = NULL;
+ private->visible = TRUE;
private->line_cap = CAIRO_LINE_CAP_ROUND;
private->highlight = FALSE;
private->suspend_stroking = 0;
private->suspend_filling = 0;
+ private->change_count = 1; /* avoid emissions during construction */
+ private->change_region = NULL;
}
static void
@@ -172,6 +185,8 @@ gimp_canvas_item_constructed (GObject *object)
g_assert (GIMP_IS_DISPLAY_SHELL (private->shell));
+ private->change_count = 0; /* undo hack from init() */
+
if (G_OBJECT_CLASS (parent_class)->constructed)
G_OBJECT_CLASS (parent_class)->constructed (object);
}
@@ -189,6 +204,9 @@ gimp_canvas_item_set_property (GObject *object,
case PROP_SHELL:
private->shell = g_value_get_object (value); /* don't ref */
break;
+ case PROP_VISIBLE:
+ private->visible = g_value_get_boolean (value);
+ break;
case PROP_LINE_CAP:
private->line_cap = g_value_get_int (value);
break;
@@ -215,6 +233,9 @@ gimp_canvas_item_get_property (GObject *object,
case PROP_SHELL:
g_value_set_object (value, private->shell);
break;
+ case PROP_VISIBLE:
+ g_value_set_boolean (value, private->visible);
+ break;
case PROP_LINE_CAP:
g_value_set_int (value, private->line_cap);
break;
@@ -235,28 +256,13 @@ gimp_canvas_item_dispatch_properties_changed (GObject *object,
{
GimpCanvasItem *item = GIMP_CANVAS_ITEM (object);
- if (g_signal_has_handler_pending (object, item_signals[UPDATE], 0, FALSE))
- {
- GdkRegion *before;
- GdkRegion *region;
+ G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object,
+ n_pspecs,
+ pspecs);
- before = gimp_canvas_item_get_extents (item);
-
- G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object,
- n_pspecs,
- pspecs);
-
- region = gimp_canvas_item_get_extents (item);
-
- if (! region)
- {
- region = before;
- }
- else if (before)
- {
- gdk_region_union (region, before);
- gdk_region_destroy (before);
- }
+ if (_gimp_canvas_item_needs_update (item))
+ {
+ GdkRegion *region = gimp_canvas_item_get_extents (item);
if (region)
{
@@ -265,12 +271,6 @@ gimp_canvas_item_dispatch_properties_changed (GObject *object,
gdk_region_destroy (region);
}
}
- else
- {
- G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object,
- n_pspecs,
- pspecs);
- }
}
static void
@@ -333,11 +333,12 @@ gimp_canvas_item_draw (GimpCanvasItem *item,
private = GET_PRIVATE (item);
- cairo_save (cr);
-
- GIMP_CANVAS_ITEM_GET_CLASS (item)->draw (item, private->shell, cr);
-
- cairo_restore (cr);
+ if (private->visible)
+ {
+ cairo_save (cr);
+ GIMP_CANVAS_ITEM_GET_CLASS (item)->draw (item, private->shell, cr);
+ cairo_restore (cr);
+ }
}
GdkRegion *
@@ -349,7 +350,42 @@ gimp_canvas_item_get_extents (GimpCanvasItem *item)
private = GET_PRIVATE (item);
- return GIMP_CANVAS_ITEM_GET_CLASS (item)->get_extents (item, private->shell);
+ if (private->visible)
+ return GIMP_CANVAS_ITEM_GET_CLASS (item)->get_extents (item, private->shell);
+
+ return NULL;
+}
+
+void
+gimp_canvas_item_set_visible (GimpCanvasItem *item,
+ gboolean visible)
+{
+ GimpCanvasItemPrivate *private;
+
+ g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
+
+ private = GET_PRIVATE (item);
+
+ if (private->visible != visible)
+ {
+ gimp_canvas_item_begin_change (item);
+ g_object_set (G_OBJECT (item),
+ "visible", visible,
+ NULL);
+ gimp_canvas_item_end_change (item);
+ }
+}
+
+gboolean
+gimp_canvas_item_get_visible (GimpCanvasItem *item)
+{
+ GimpCanvasItemPrivate *private;
+
+ g_return_val_if_fail (GIMP_IS_CANVAS_ITEM (item), FALSE);
+
+ private = GET_PRIVATE (item);
+
+ return private->visible;
}
void
@@ -362,14 +398,13 @@ gimp_canvas_item_set_line_cap (GimpCanvasItem *item,
private = GET_PRIVATE (item);
- line_cap = CLAMP (line_cap,
- CAIRO_LINE_CAP_BUTT,
- CAIRO_LINE_CAP_SQUARE);
-
if (private->line_cap != line_cap)
{
- private->line_cap = line_cap;
- g_object_notify (G_OBJECT (item), "line-cap");
+ gimp_canvas_item_begin_change (item);
+ g_object_set (G_OBJECT (item),
+ "line-cap", line_cap,
+ NULL);
+ gimp_canvas_item_end_change (item);
}
}
@@ -383,12 +418,11 @@ gimp_canvas_item_set_highlight (GimpCanvasItem *item,
private = GET_PRIVATE (item);
- highlight = highlight ? TRUE : FALSE;
-
if (private->highlight != highlight)
{
- private->highlight = highlight;
- g_object_notify (G_OBJECT (item), "highlight");
+ g_object_set (G_OBJECT (item),
+ "highlight", highlight,
+ NULL);
}
}
@@ -405,6 +439,63 @@ gimp_canvas_item_get_highlight (GimpCanvasItem *item)
}
void
+gimp_canvas_item_begin_change (GimpCanvasItem *item)
+{
+ GimpCanvasItemPrivate *private;
+
+ g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
+
+ private = GET_PRIVATE (item);
+
+ private->change_count++;
+
+ if (private->change_count == 1 &&
+ g_signal_has_handler_pending (item, item_signals[UPDATE], 0, FALSE))
+ {
+ private->change_region = gimp_canvas_item_get_extents (item);
+ }
+}
+
+void
+gimp_canvas_item_end_change (GimpCanvasItem *item)
+{
+ GimpCanvasItemPrivate *private;
+
+ g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
+
+ private = GET_PRIVATE (item);
+
+ g_return_if_fail (private->change_count > 0);
+
+ private->change_count--;
+
+ if (private->change_count == 0 &&
+ g_signal_has_handler_pending (item, item_signals[UPDATE], 0, FALSE))
+ {
+ GdkRegion *region = gimp_canvas_item_get_extents (item);
+
+ if (! region)
+ {
+ region = private->change_region;
+ }
+ else if (private->change_region)
+ {
+ gdk_region_union (region, private->change_region);
+ gdk_region_destroy (private->change_region);
+ }
+
+ private->change_region = NULL;
+
+ if (region)
+ {
+ g_signal_emit (item, item_signals[UPDATE], 0,
+ region);
+ gdk_region_destroy (region);
+ }
+ }
+}
+
+void
gimp_canvas_item_suspend_stroking (GimpCanvasItem *item)
{
GimpCanvasItemPrivate *private;
@@ -460,6 +551,23 @@ gimp_canvas_item_resume_filling (GimpCanvasItem *item)
/* protected functions */
void
+_gimp_canvas_item_update (GimpCanvasItem *item,
+ GdkRegion *region)
+{
+ g_signal_emit (item, item_signals[UPDATE], 0,
+ region);
+}
+
+gboolean
+_gimp_canvas_item_needs_update (GimpCanvasItem *item)
+{
+ GimpCanvasItemPrivate *private = GET_PRIVATE (item);
+
+ return (private->change_count == 0 &&
+ g_signal_has_handler_pending (item, item_signals[UPDATE], 0, FALSE));
+}
+
+void
_gimp_canvas_item_stroke (GimpCanvasItem *item,
cairo_t *cr)
{
diff --git a/app/display/gimpcanvasitem.h b/app/display/gimpcanvasitem.h
index 61867d4..95ea3f2 100644
--- a/app/display/gimpcanvasitem.h
+++ b/app/display/gimpcanvasitem.h
@@ -70,6 +70,10 @@ void gimp_canvas_item_draw (GimpCanvasItem *item,
cairo_t *cr);
GdkRegion * gimp_canvas_item_get_extents (GimpCanvasItem *item);
+void gimp_canvas_item_set_visible (GimpCanvasItem *item,
+ gboolean visible);
+gboolean gimp_canvas_item_get_visible (GimpCanvasItem *item);
+
void gimp_canvas_item_set_line_cap (GimpCanvasItem *item,
cairo_line_cap_t line_cap);
@@ -77,6 +81,9 @@ void gimp_canvas_item_set_highlight (GimpCanvasItem *item,
gboolean highlight);
gboolean gimp_canvas_item_get_highlight (GimpCanvasItem *item);
+void gimp_canvas_item_begin_change (GimpCanvasItem *item);
+void gimp_canvas_item_end_change (GimpCanvasItem *item);
+
void gimp_canvas_item_suspend_stroking (GimpCanvasItem *item);
void gimp_canvas_item_resume_stroking (GimpCanvasItem *item);
@@ -86,6 +93,9 @@ void gimp_canvas_item_resume_filling (GimpCanvasItem *item);
/* protected */
+void _gimp_canvas_item_update (GimpCanvasItem *item,
+ GdkRegion *region);
+gboolean _gimp_canvas_item_needs_update (GimpCanvasItem *item);
void _gimp_canvas_item_stroke (GimpCanvasItem *item,
cairo_t *cr);
void _gimp_canvas_item_fill (GimpCanvasItem *item,
diff --git a/app/display/gimpdisplayshell-appearance.c b/app/display/gimpdisplayshell-appearance.c
index e92b152..86a91ef 100644
--- a/app/display/gimpdisplayshell-appearance.c
+++ b/app/display/gimpdisplayshell-appearance.c
@@ -40,6 +40,7 @@
#include "widgets/gimpwidgets-utils.h"
#include "gimpcanvas.h"
+#include "gimpcanvasitem.h"
#include "gimpdisplay.h"
#include "gimpdisplayshell.h"
#include "gimpdisplayshell-appearance.h"
@@ -295,7 +296,6 @@ gimp_display_shell_set_show_guides (GimpDisplayShell *shell,
gboolean show)
{
GimpDisplayOptions *options;
- GimpImage *image;
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
@@ -303,12 +303,7 @@ gimp_display_shell_set_show_guides (GimpDisplayShell *shell,
g_object_set (options, "show-guides", show, NULL);
- image = gimp_display_get_image (shell->display);
-
- if (image && gimp_image_get_guides (image))
- {
- gimp_display_shell_expose_full (shell);
- }
+ gimp_canvas_item_set_visible (shell->guides, show);
appearance_set_action_active (shell, "view-show-guides", show);
}
@@ -357,7 +352,6 @@ gimp_display_shell_set_show_sample_points (GimpDisplayShell *shell,
gboolean show)
{
GimpDisplayOptions *options;
- GimpImage *image;
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
@@ -365,12 +359,7 @@ gimp_display_shell_set_show_sample_points (GimpDisplayShell *shell,
g_object_set (options, "show-sample-points", show, NULL);
- image = gimp_display_get_image (shell->display);
-
- if (image && gimp_image_get_sample_points (image))
- {
- gimp_display_shell_expose_full (shell);
- }
+ gimp_canvas_item_set_visible (shell->sample_points, show);
appearance_set_action_active (shell, "view-show-sample-points", show);
}
diff --git a/app/display/gimpdisplayshell-handlers.c b/app/display/gimpdisplayshell-handlers.c
index 6838caa..406e95b 100644
--- a/app/display/gimpdisplayshell-handlers.c
+++ b/app/display/gimpdisplayshell-handlers.c
@@ -572,10 +572,12 @@ gimp_display_shell_guide_move_handler (GimpImage *image,
item = gimp_canvas_proxy_group_get_item (group, guide);
+ gimp_canvas_item_begin_change (item);
g_object_set (item,
"orientation", gimp_guide_get_orientation (guide),
"position", gimp_guide_get_position (guide),
NULL);
+ gimp_canvas_item_end_change (item);
}
static void
@@ -647,10 +649,12 @@ gimp_display_shell_sample_point_move_handler (GimpImage *image,
item = gimp_canvas_proxy_group_get_item (group, sample_point);
+ gimp_canvas_item_begin_change (item);
g_object_set (item,
"x", sample_point->x,
"y", sample_point->y,
NULL);
+ gimp_canvas_item_end_change (item);
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]