From c914aa805dc9de0157c10019d97fe64b564fe5d0 Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Mon, 12 Nov 2012 10:55:41 +0100 Subject: [PATCH] Bug 675747 - Layers with some modes get hidden in layer groups Add a boolean "is-last-node" property to GimpDrawable and set it from GimpDrawableStack, which is the place that easily has the information. In GimpLayer, connect to "notify" and make sure we use NORMAL mode unless the layer is in NORMAL or DISSOLVE mode. --- app/core/gimpdrawable-private.h | 2 + app/core/gimpdrawable.c | 84 +++++++++++++++++++++++++++++++++ app/core/gimpdrawable.h | 4 ++ app/core/gimpdrawablestack.c | 21 +++++++-- app/core/gimplayer.c | 46 ++++++++++++++++-- 5 files changed, 150 insertions(+), 7 deletions(-) diff --git a/app/core/gimpdrawable-private.h b/app/core/gimpdrawable-private.h index bfe9d3829e..b7b8754b8c 100644 --- a/app/core/gimpdrawable-private.h +++ b/app/core/gimpdrawable-private.h @@ -32,6 +32,8 @@ struct _GimpDrawablePrivate GeglNode *fs_mode_node; GeglNode *mode_node; + + gboolean is_last_node; }; #endif /* __GIMP_DRAWABLE_PRIVATE_H__ */ diff --git a/app/core/gimpdrawable.c b/app/core/gimpdrawable.c index 28b4fc1822..b34852e332 100644 --- a/app/core/gimpdrawable.c +++ b/app/core/gimpdrawable.c @@ -61,6 +61,12 @@ enum LAST_SIGNAL }; +enum +{ + PROP_0, + PROP_IS_LAST_NODE +}; + /* local function prototypes */ @@ -68,6 +74,14 @@ static void gimp_drawable_pickable_iface_init (GimpPickableInterface *iface); static void gimp_drawable_dispose (GObject *object); static void gimp_drawable_finalize (GObject *object); +static void gimp_drawable_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_drawable_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); static gint64 gimp_drawable_get_memsize (GimpObject *object, gint64 *gui_size); @@ -212,6 +226,8 @@ gimp_drawable_class_init (GimpDrawableClass *klass) object_class->dispose = gimp_drawable_dispose; object_class->finalize = gimp_drawable_finalize; + object_class->set_property = gimp_drawable_set_property; + object_class->get_property = gimp_drawable_get_property; gimp_object_class->get_memsize = gimp_drawable_get_memsize; @@ -242,6 +258,12 @@ gimp_drawable_class_init (GimpDrawableClass *klass) klass->push_undo = gimp_drawable_real_push_undo; klass->swap_pixels = gimp_drawable_real_swap_pixels; + g_object_class_install_property (object_class, PROP_IS_LAST_NODE, + g_param_spec_boolean ("is-last-node", + NULL, NULL, + FALSE, + GIMP_PARAM_READWRITE)); + g_type_class_add_private (klass, sizeof (GimpDrawablePrivate)); } @@ -298,6 +320,46 @@ gimp_drawable_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static void +gimp_drawable_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpDrawable *drawable = GIMP_DRAWABLE (object); + + switch (property_id) + { + case PROP_IS_LAST_NODE: + drawable->private->is_last_node = g_value_get_boolean (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_drawable_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpDrawable *drawable = GIMP_DRAWABLE (object); + + switch (property_id) + { + case PROP_IS_LAST_NODE: + g_value_set_boolean (value, drawable->private->is_last_node); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + static gint64 gimp_drawable_get_memsize (GimpObject *object, gint64 *gui_size) @@ -1318,6 +1380,28 @@ gimp_drawable_get_mode_node (GimpDrawable *drawable) return drawable->private->mode_node; } +void +gimp_drawable_set_is_last_node (GimpDrawable *drawable, + gboolean last_node) +{ + g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); + + if (last_node != drawable->private->is_last_node) + { + g_object_set (drawable, + "is-last-node", last_node ? TRUE : FALSE, + NULL); + } +} + +gboolean +gimp_drawable_get_is_last_node (GimpDrawable *drawable) +{ + g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE); + + return drawable->private->is_last_node; +} + void gimp_drawable_swap_pixels (GimpDrawable *drawable, GeglBuffer *buffer, diff --git a/app/core/gimpdrawable.h b/app/core/gimpdrawable.h index 06485cb958..339a6b8b89 100644 --- a/app/core/gimpdrawable.h +++ b/app/core/gimpdrawable.h @@ -180,6 +180,10 @@ void gimp_drawable_set_buffer_full (GimpDrawable *drawable, GeglNode * gimp_drawable_get_source_node (GimpDrawable *drawable); GeglNode * gimp_drawable_get_mode_node (GimpDrawable *drawable); +void gimp_drawable_set_is_last_node (GimpDrawable *drawable, + gboolean last_node); +gboolean gimp_drawable_get_is_last_node (GimpDrawable *drawable); + void gimp_drawable_swap_pixels (GimpDrawable *drawable, GeglBuffer *buffer, gint x, diff --git a/app/core/gimpdrawablestack.c b/app/core/gimpdrawablestack.c index 0d12a1fbca..33b86a49f7 100644 --- a/app/core/gimpdrawablestack.c +++ b/app/core/gimpdrawablestack.c @@ -235,6 +235,9 @@ gimp_drawable_stack_get_graph (GimpDrawableStack *stack) GimpDrawable *drawable = list->data; reverse_list = g_list_prepend (reverse_list, drawable); + + if (! g_list_next (list)) + gimp_drawable_set_is_last_node (drawable, TRUE); } stack->graph = gegl_node_new (); @@ -271,6 +274,7 @@ static void gimp_drawable_stack_add_node (GimpDrawableStack *stack, GimpDrawable *drawable) { + GimpDrawable *drawable_above = NULL; GimpDrawable *drawable_below; GeglNode *node_above; GeglNode *node; @@ -287,8 +291,6 @@ gimp_drawable_stack_add_node (GimpDrawableStack *stack, } else { - GimpDrawable *drawable_above; - drawable_above = (GimpDrawable *) gimp_container_get_child_by_index (GIMP_CONTAINER (stack), index - 1); @@ -308,12 +310,20 @@ gimp_drawable_stack_add_node (GimpDrawableStack *stack, gegl_node_connect_to (node_below, "output", node, "input"); } + else + { + if (drawable_above) + gimp_drawable_set_is_last_node (drawable_above, FALSE); + + gimp_drawable_set_is_last_node (drawable, TRUE); + } } static void gimp_drawable_stack_remove_node (GimpDrawableStack *stack, GimpDrawable *drawable) { + GimpDrawable *drawable_above = NULL; GimpDrawable *drawable_below; GeglNode *node_above; GeglNode *node; @@ -330,8 +340,6 @@ gimp_drawable_stack_remove_node (GimpDrawableStack *stack, } else { - GimpDrawable *drawable_above; - drawable_above = (GimpDrawable *) gimp_container_get_child_by_index (GIMP_CONTAINER (stack), index - 1); @@ -352,6 +360,11 @@ gimp_drawable_stack_remove_node (GimpDrawableStack *stack, else { gegl_node_disconnect (node_above, "input"); + + gimp_drawable_set_is_last_node (drawable, FALSE); + + if (drawable_above) + gimp_drawable_set_is_last_node (drawable_above, TRUE); } } diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c index 2525d20dfb..1329577969 100644 --- a/app/core/gimplayer.c +++ b/app/core/gimplayer.c @@ -85,6 +85,8 @@ static void gimp_layer_get_property (GObject *object, GParamSpec *pspec); static void gimp_layer_dispose (GObject *object); static void gimp_layer_finalize (GObject *object); +static void gimp_layer_notify (GObject *object, + GParamSpec *pspec); static void gimp_layer_name_changed (GimpObject *object); static gint64 gimp_layer_get_memsize (GimpObject *object, @@ -264,6 +266,7 @@ gimp_layer_class_init (GimpLayerClass *klass) object_class->get_property = gimp_layer_get_property; object_class->dispose = gimp_layer_dispose; object_class->finalize = gimp_layer_finalize; + object_class->notify = gimp_layer_notify; gimp_object_class->name_changed = gimp_layer_name_changed; gimp_object_class->get_memsize = gimp_layer_get_memsize; @@ -466,6 +469,39 @@ gimp_layer_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static GimpLayerModeEffects +gimp_layer_get_visible_mode (GimpLayer *layer) +{ + if (layer->mode != GIMP_DISSOLVE_MODE && + gimp_drawable_get_is_last_node (GIMP_DRAWABLE (layer))) + return GIMP_NORMAL_MODE; + + return layer->mode; +} + +static void +gimp_layer_notify (GObject *object, + GParamSpec *pspec) +{ + if (! strcmp (pspec->name, "is-last-node") && + gimp_item_peek_node (GIMP_ITEM (object))) + { + GimpLayer *layer = GIMP_LAYER (object); + GeglNode *mode_node; + + mode_node = gimp_drawable_get_mode_node (GIMP_DRAWABLE (layer)); + + gimp_gegl_mode_node_set (mode_node, + gimp_layer_get_visible_mode (layer), + layer->opacity, FALSE); + + gimp_drawable_update (GIMP_DRAWABLE (layer), + 0, 0, + gimp_item_get_width (GIMP_ITEM (layer)), + gimp_item_get_height (GIMP_ITEM (layer))); + } +} + static void gimp_layer_name_changed (GimpObject *object) { @@ -880,7 +916,9 @@ gimp_layer_get_node (GimpItem *item) */ mode_node = gimp_drawable_get_mode_node (drawable); - gimp_gegl_mode_node_set (mode_node, layer->mode, layer->opacity, FALSE); + gimp_gegl_mode_node_set (mode_node, + gimp_layer_get_visible_mode (layer), + layer->opacity, FALSE); /* the layer's offset node */ layer->layer_offset_node = gegl_node_new_child (node, @@ -1944,7 +1982,8 @@ gimp_layer_set_opacity (GimpLayer *layer, mode_node = gimp_drawable_get_mode_node (GIMP_DRAWABLE (layer)); gimp_gegl_mode_node_set (mode_node, - layer->mode, layer->opacity, FALSE); + gimp_layer_get_visible_mode (layer), + layer->opacity, FALSE); } gimp_drawable_update (GIMP_DRAWABLE (layer), @@ -1990,7 +2029,8 @@ gimp_layer_set_mode (GimpLayer *layer, mode_node = gimp_drawable_get_mode_node (GIMP_DRAWABLE (layer)); gimp_gegl_mode_node_set (mode_node, - layer->mode, layer->opacity, FALSE); + gimp_layer_get_visible_mode (layer), + layer->opacity, FALSE); } gimp_drawable_update (GIMP_DRAWABLE (layer),