diff --git a/app/core/gimpchannelundo.c b/app/core/gimpchannelundo.c index c4ca9aa0b1..1d51e15b4e 100644 --- a/app/core/gimpchannelundo.c +++ b/app/core/gimpchannelundo.c @@ -34,11 +34,12 @@ enum PROP_0, PROP_PREV_PARENT, PROP_PREV_POSITION, - PROP_PREV_CHANNEL + PROP_PREV_CHANNELS }; static void gimp_channel_undo_constructed (GObject *object); +static void gimp_channel_undo_finalize (GObject *object); static void gimp_channel_undo_set_property (GObject *object, guint property_id, const GValue *value, @@ -69,6 +70,7 @@ gimp_channel_undo_class_init (GimpChannelUndoClass *klass) GimpUndoClass *undo_class = GIMP_UNDO_CLASS (klass); object_class->constructed = gimp_channel_undo_constructed; + object_class->finalize = gimp_channel_undo_finalize; object_class->set_property = gimp_channel_undo_set_property; object_class->get_property = gimp_channel_undo_get_property; @@ -90,17 +92,17 @@ gimp_channel_undo_class_init (GimpChannelUndoClass *klass) GIMP_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - g_object_class_install_property (object_class, PROP_PREV_CHANNEL, - g_param_spec_object ("prev-channel", - NULL, NULL, - GIMP_TYPE_CHANNEL, - GIMP_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, PROP_PREV_CHANNELS, + g_param_spec_pointer ("prev-channels", + NULL, NULL, + GIMP_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); } static void gimp_channel_undo_init (GimpChannelUndo *undo) { + undo->prev_channels = NULL; } static void @@ -111,6 +113,16 @@ gimp_channel_undo_constructed (GObject *object) gimp_assert (GIMP_IS_CHANNEL (GIMP_ITEM_UNDO (object)->item)); } +static void +gimp_channel_undo_finalize (GObject *object) +{ + GimpChannelUndo *channel_undo = GIMP_CHANNEL_UNDO (object); + + g_clear_pointer (&channel_undo->prev_channels, g_list_free); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + static void gimp_channel_undo_set_property (GObject *object, guint property_id, @@ -127,8 +139,8 @@ gimp_channel_undo_set_property (GObject *object, case PROP_PREV_POSITION: channel_undo->prev_position = g_value_get_int (value); break; - case PROP_PREV_CHANNEL: - channel_undo->prev_channel = g_value_get_object (value); + case PROP_PREV_CHANNELS: + channel_undo->prev_channels = g_list_copy (g_value_get_pointer (value)); break; default: @@ -153,8 +165,8 @@ gimp_channel_undo_get_property (GObject *object, case PROP_PREV_POSITION: g_value_set_int (value, channel_undo->prev_position); break; - case PROP_PREV_CHANNEL: - g_value_set_object (value, channel_undo->prev_channel); + case PROP_PREV_CHANNELS: + g_value_set_pointer (value, channel_undo->prev_channels); break; default: @@ -200,14 +212,15 @@ gimp_channel_undo_pop (GimpUndo *undo, channel_undo->prev_position = gimp_item_get_index (GIMP_ITEM (channel)); gimp_image_remove_channel (undo->image, channel, FALSE, - channel_undo->prev_channel); + channel_undo->prev_channels); } else { /* restore channel */ /* record the active channel */ - channel_undo->prev_channel = gimp_image_get_active_channel (undo->image); + g_clear_pointer (&channel_undo->prev_channels, g_list_free); + channel_undo->prev_channels = g_list_copy (gimp_image_get_selected_channels (undo->image)); gimp_image_add_channel (undo->image, channel, channel_undo->prev_parent, diff --git a/app/core/gimpchannelundo.h b/app/core/gimpchannelundo.h index 7bfceb96d8..985114c92e 100644 --- a/app/core/gimpchannelundo.h +++ b/app/core/gimpchannelundo.h @@ -38,8 +38,8 @@ struct _GimpChannelUndo GimpItemUndo parent_instance; GimpChannel *prev_parent; - gint prev_position; /* former position in list */ - GimpChannel *prev_channel; /* previous active channel */ + gint prev_position; /* former position in list */ + GList *prev_channels; /* previous selected channels */ }; struct _GimpChannelUndoClass diff --git a/app/core/gimpimage-duplicate.c b/app/core/gimpimage-duplicate.c index 857b71bb3f..e013cb3cb4 100644 --- a/app/core/gimpimage-duplicate.c +++ b/app/core/gimpimage-duplicate.c @@ -57,11 +57,11 @@ static void gimp_image_duplicate_colormap (GimpImage *image, GimpImage *new_image); static GimpItem * gimp_image_duplicate_item (GimpItem *item, GimpImage *new_image); -static GimpLayer * gimp_image_duplicate_layers (GimpImage *image, +static GList * gimp_image_duplicate_layers (GimpImage *image, GimpImage *new_image); -static GimpChannel * gimp_image_duplicate_channels (GimpImage *image, +static GList * gimp_image_duplicate_channels (GimpImage *image, GimpImage *new_image); -static GimpVectors * gimp_image_duplicate_vectors (GimpImage *image, +static GList * gimp_image_duplicate_vectors (GimpImage *image, GimpImage *new_image); static void gimp_image_duplicate_floating_sel (GimpImage *image, GimpImage *new_image); @@ -89,9 +89,9 @@ GimpImage * gimp_image_duplicate (GimpImage *image) { GimpImage *new_image; - GimpLayer *active_layer; - GimpChannel *active_channel; - GimpVectors *active_vectors; + GList *active_layers; + GList *active_channels; + GList *active_vectors; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); @@ -120,10 +120,10 @@ gimp_image_duplicate (GimpImage *image) gimp_image_duplicate_colormap (image, new_image); /* Copy the layers */ - active_layer = gimp_image_duplicate_layers (image, new_image); + active_layers = gimp_image_duplicate_layers (image, new_image); /* Copy the channels */ - active_channel = gimp_image_duplicate_channels (image, new_image); + active_channels = gimp_image_duplicate_channels (image, new_image); /* Copy any vectors */ active_vectors = gimp_image_duplicate_vectors (image, new_image); @@ -135,14 +135,14 @@ gimp_image_duplicate (GimpImage *image) gimp_image_duplicate_mask (image, new_image); /* Set active layer, active channel, active vectors */ - if (active_layer) - gimp_image_set_active_layer (new_image, active_layer); + if (active_layers) + gimp_image_set_selected_layers (new_image, active_layers); - if (active_channel) - gimp_image_set_active_channel (new_image, active_channel); + if (active_channels) + gimp_image_set_selected_channels (new_image, active_channels); if (active_vectors) - gimp_image_set_active_vectors (new_image, active_vectors); + gimp_image_set_selected_vectors (new_image, active_vectors); /* Copy state of all color components */ gimp_image_duplicate_components (image, new_image); @@ -221,13 +221,16 @@ gimp_image_duplicate_item (GimpItem *item, return new_item; } -static GimpLayer * +static GList * gimp_image_duplicate_layers (GimpImage *image, GimpImage *new_image) { - GimpLayer *active_layer = NULL; - GList *list; - gint count; + GList *new_selected_layers = NULL; + GList *selected_layers; + GList *list; + gint count; + + selected_layers = gimp_image_get_selected_layers (image); for (list = gimp_image_get_layer_iter (image), count = 0; list; @@ -249,23 +252,26 @@ gimp_image_duplicate_layers (GimpImage *image, gimp_object_set_name (GIMP_OBJECT (new_layer->mask), gimp_object_get_name (layer->mask)); - if (gimp_image_get_active_layer (image) == layer) - active_layer = new_layer; + if (g_list_find (selected_layers, layer)) + new_selected_layers = g_list_prepend (new_selected_layers, new_layer); gimp_image_add_layer (new_image, new_layer, NULL, count++, FALSE); } - return active_layer; + return new_selected_layers; } -static GimpChannel * +static GList * gimp_image_duplicate_channels (GimpImage *image, GimpImage *new_image) { - GimpChannel *active_channel = NULL; - GList *list; - gint count; + GList *new_selected_channels = NULL; + GList *selected_channels; + GList *list; + gint count; + + selected_channels = gimp_image_get_selected_channels (image); for (list = gimp_image_get_channel_iter (image), count = 0; list; @@ -277,23 +283,26 @@ gimp_image_duplicate_channels (GimpImage *image, new_channel = GIMP_CHANNEL (gimp_image_duplicate_item (GIMP_ITEM (channel), new_image)); - if (gimp_image_get_active_channel (image) == channel) - active_channel = new_channel; + if (g_list_find (selected_channels, channel)) + new_selected_channels = g_list_prepend (new_selected_channels, new_channel); gimp_image_add_channel (new_image, new_channel, NULL, count++, FALSE); } - return active_channel; + return new_selected_channels; } -static GimpVectors * +static GList * gimp_image_duplicate_vectors (GimpImage *image, GimpImage *new_image) { - GimpVectors *active_vectors = NULL; - GList *list; - gint count; + GList *new_selected_vectors = NULL; + GList *selected_vectors; + GList *list; + gint count; + + selected_vectors = gimp_image_get_selected_vectors (image); for (list = gimp_image_get_vectors_iter (image), count = 0; list; @@ -305,14 +314,15 @@ gimp_image_duplicate_vectors (GimpImage *image, new_vectors = GIMP_VECTORS (gimp_image_duplicate_item (GIMP_ITEM (vectors), new_image)); - if (gimp_image_get_active_vectors (image) == vectors) - active_vectors = new_vectors; + if (g_list_find (selected_vectors, vectors)) + new_selected_vectors = g_list_prepend (new_selected_vectors, new_vectors); + gimp_image_add_vectors (new_image, new_vectors, NULL, count++, FALSE); } - return active_vectors; + return new_selected_vectors; } static void diff --git a/app/core/gimpimage-quick-mask.c b/app/core/gimpimage-quick-mask.c index 9473bdee07..d9ad50319e 100644 --- a/app/core/gimpimage-quick-mask.c +++ b/app/core/gimpimage-quick-mask.c @@ -132,7 +132,7 @@ gimp_image_set_quick_mask_state (GimpImage *image, gimp_image_remove_channel (image, mask, TRUE, NULL); if (! channel_was_active) - gimp_image_unset_active_channel (image); + gimp_image_unset_selected_channels (image); gimp_image_undo_group_end (image); } diff --git a/app/core/gimpimage-undo-push.c b/app/core/gimpimage-undo-push.c index 75a08d1f64..bcde9c4173 100644 --- a/app/core/gimpimage-undo-push.c +++ b/app/core/gimpimage-undo-push.c @@ -529,19 +529,22 @@ GimpUndo * gimp_image_undo_push_layer_add (GimpImage *image, const gchar *undo_desc, GimpLayer *layer, - GimpLayer *prev_layer) + GList *prev_layers) { + GList *iter; + g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_LAYER (layer), NULL); g_return_val_if_fail (! gimp_item_is_attached (GIMP_ITEM (layer)), NULL); - g_return_val_if_fail (prev_layer == NULL || GIMP_IS_LAYER (prev_layer), - NULL); + + for (iter = prev_layers; iter; iter = iter->next) + g_return_val_if_fail (GIMP_IS_LAYER (iter->data), NULL); return gimp_image_undo_push (image, GIMP_TYPE_LAYER_UNDO, GIMP_UNDO_LAYER_ADD, undo_desc, GIMP_DIRTY_IMAGE_STRUCTURE, - "item", layer, - "prev-layer", prev_layer, + "item", layer, + "prev-layers", prev_layers, NULL); } @@ -551,15 +554,18 @@ gimp_image_undo_push_layer_remove (GimpImage *image, GimpLayer *layer, GimpLayer *prev_parent, gint prev_position, - GimpLayer *prev_layer) + GList *prev_layers) { + GList *iter; + g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_LAYER (layer), NULL); g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (layer)), NULL); g_return_val_if_fail (prev_parent == NULL || GIMP_IS_LAYER (prev_parent), NULL); - g_return_val_if_fail (prev_layer == NULL || GIMP_IS_LAYER (prev_layer), - NULL); + + for (iter = prev_layers; iter; iter = iter->next) + g_return_val_if_fail (GIMP_IS_LAYER (iter->data), NULL); return gimp_image_undo_push (image, GIMP_TYPE_LAYER_UNDO, GIMP_UNDO_LAYER_REMOVE, undo_desc, @@ -567,7 +573,7 @@ gimp_image_undo_push_layer_remove (GimpImage *image, "item", layer, "prev-parent", prev_parent, "prev-position", prev_position, - "prev-layer", prev_layer, + "prev-layers", prev_layers, NULL); } @@ -879,19 +885,22 @@ GimpUndo * gimp_image_undo_push_channel_add (GimpImage *image, const gchar *undo_desc, GimpChannel *channel, - GimpChannel *prev_channel) + GList *prev_channels) { + GList *iter; + g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_CHANNEL (channel), NULL); g_return_val_if_fail (! gimp_item_is_attached (GIMP_ITEM (channel)), NULL); - g_return_val_if_fail (prev_channel == NULL || GIMP_IS_CHANNEL (prev_channel), - NULL); + + for (iter = prev_channels; iter; iter = iter->next) + g_return_val_if_fail (GIMP_IS_CHANNEL (iter->data), NULL); return gimp_image_undo_push (image, GIMP_TYPE_CHANNEL_UNDO, GIMP_UNDO_CHANNEL_ADD, undo_desc, GIMP_DIRTY_IMAGE_STRUCTURE, - "item", channel, - "prev-channel", prev_channel, + "item", channel, + "prev-channels", prev_channels, NULL); } @@ -901,15 +910,18 @@ gimp_image_undo_push_channel_remove (GimpImage *image, GimpChannel *channel, GimpChannel *prev_parent, gint prev_position, - GimpChannel *prev_channel) + GList *prev_channels) { + GList *iter; + g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_CHANNEL (channel), NULL); g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)), NULL); g_return_val_if_fail (prev_parent == NULL || GIMP_IS_CHANNEL (prev_parent), NULL); - g_return_val_if_fail (prev_channel == NULL || GIMP_IS_CHANNEL (prev_channel), - NULL); + + for (iter = prev_channels; iter; iter = iter->next) + g_return_val_if_fail (GIMP_IS_CHANNEL (iter->data), NULL); return gimp_image_undo_push (image, GIMP_TYPE_CHANNEL_UNDO, GIMP_UNDO_CHANNEL_REMOVE, undo_desc, @@ -917,7 +929,7 @@ gimp_image_undo_push_channel_remove (GimpImage *image, "item", channel, "prev-parent", prev_parent, "prev-position", prev_position, - "prev-channel", prev_channel, + "prev-channels", prev_channels, NULL); } @@ -946,13 +958,16 @@ GimpUndo * gimp_image_undo_push_vectors_add (GimpImage *image, const gchar *undo_desc, GimpVectors *vectors, - GimpVectors *prev_vectors) + GList *prev_vectors) { + GList *iter; + g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_VECTORS (vectors), NULL); g_return_val_if_fail (! gimp_item_is_attached (GIMP_ITEM (vectors)), NULL); - g_return_val_if_fail (prev_vectors == NULL || GIMP_IS_VECTORS (prev_vectors), - NULL); + + for (iter = prev_vectors; iter; iter = iter->next) + g_return_val_if_fail (GIMP_IS_VECTORS (iter->data), NULL); return gimp_image_undo_push (image, GIMP_TYPE_VECTORS_UNDO, GIMP_UNDO_VECTORS_ADD, undo_desc, @@ -968,15 +983,18 @@ gimp_image_undo_push_vectors_remove (GimpImage *image, GimpVectors *vectors, GimpVectors *prev_parent, gint prev_position, - GimpVectors *prev_vectors) + GList *prev_vectors) { + GList *iter; + g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_VECTORS (vectors), NULL); g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (vectors)), NULL); g_return_val_if_fail (prev_parent == NULL || GIMP_IS_VECTORS (prev_parent), NULL); - g_return_val_if_fail (prev_vectors == NULL || GIMP_IS_VECTORS (prev_vectors), - NULL); + + for (iter = prev_vectors; iter; iter = iter->next) + g_return_val_if_fail (GIMP_IS_VECTORS (iter->data), NULL); return gimp_image_undo_push (image, GIMP_TYPE_VECTORS_UNDO, GIMP_UNDO_VECTORS_REMOVE, undo_desc, diff --git a/app/core/gimpimage-undo-push.h b/app/core/gimpimage-undo-push.h index 6215b0d5c9..3aea6e4a1f 100644 --- a/app/core/gimpimage-undo-push.h +++ b/app/core/gimpimage-undo-push.h @@ -128,13 +128,13 @@ GimpUndo * gimp_image_undo_push_item_parasite_remove(GimpImage *image, GimpUndo * gimp_image_undo_push_layer_add (GimpImage *image, const gchar *undo_desc, GimpLayer *layer, - GimpLayer *prev_layer); + GList *prev_layers); GimpUndo * gimp_image_undo_push_layer_remove (GimpImage *image, const gchar *undo_desc, GimpLayer *layer, GimpLayer *prev_parent, gint prev_position, - GimpLayer *prev_layer); + GList *prev_layers); GimpUndo * gimp_image_undo_push_layer_mode (GimpImage *image, const gchar *undo_desc, GimpLayer *layer); @@ -214,13 +214,13 @@ GimpUndo * gimp_image_undo_push_layer_mask_show (GimpImage *image, GimpUndo * gimp_image_undo_push_channel_add (GimpImage *image, const gchar *undo_desc, GimpChannel *channel, - GimpChannel *prev_channel); + GList *prev_channels); GimpUndo * gimp_image_undo_push_channel_remove (GimpImage *image, const gchar *undo_desc, GimpChannel *channel, GimpChannel *prev_parent, gint prev_position, - GimpChannel *prev_channel); + GList *prev_channels); GimpUndo * gimp_image_undo_push_channel_color (GimpImage *image, const gchar *undo_desc, GimpChannel *channel); @@ -231,13 +231,13 @@ GimpUndo * gimp_image_undo_push_channel_color (GimpImage *image, GimpUndo * gimp_image_undo_push_vectors_add (GimpImage *image, const gchar *undo_desc, GimpVectors *vectors, - GimpVectors *prev_vectors); + GList *prev_vectors); GimpUndo * gimp_image_undo_push_vectors_remove (GimpImage *image, const gchar *undo_desc, GimpVectors *vectors, GimpVectors *prev_parent, gint prev_position, - GimpVectors *prev_vectors); + GList *prev_vectors); GimpUndo * gimp_image_undo_push_vectors_mod (GimpImage *image, const gchar *undo_desc, GimpVectors *vectors); diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c index 09d970f9d5..234cfc29eb 100644 --- a/app/core/gimpimage.c +++ b/app/core/gimpimage.c @@ -99,8 +99,8 @@ enum PRECISION_CHANGED, ALPHA_CHANGED, FLOATING_SELECTION_CHANGED, - ACTIVE_CHANNEL_CHANGED, - ACTIVE_VECTORS_CHANGED, + SELECTED_CHANNELS_CHANGED, + SELECTED_VECTORS_CHANGED, SELECTED_LAYERS_CHANGED, LINKED_ITEMS_CHANGED, COMPONENT_VISIBILITY_CHANGED, @@ -255,20 +255,27 @@ static void gimp_image_channel_name_changed (GimpChannel *channel, GimpImage *image); static void gimp_image_channel_color_changed (GimpChannel *channel, GimpImage *image); -static void gimp_image_active_layer_notify (GimpItemTree *tree, - const GParamSpec *pspec, - GimpImage *image); -static void gimp_image_active_channel_notify (GimpItemTree *tree, - const GParamSpec *pspec, - GimpImage *image); -static void gimp_image_active_vectors_notify (GimpItemTree *tree, - const GParamSpec *pspec, - GimpImage *image); + +static void gimp_image_selected_layers_notify (GimpItemTree *tree, + const GParamSpec *pspec, + GimpImage *image); +static void gimp_image_selected_channels_notify (GimpItemTree *tree, + const GParamSpec *pspec, + GimpImage *image); +static void gimp_image_selected_vectors_notify (GimpItemTree *tree, + const GParamSpec *pspec, + GimpImage *image); static void gimp_image_freeze_bounding_box (GimpImage *image); static void gimp_image_thaw_bounding_box (GimpImage *image); static void gimp_image_update_bounding_box (GimpImage *image); +static gint gimp_image_layer_stack_cmp (GList *layers1, + GList *layers2); +static void gimp_image_remove_from_layer_stack (GimpImage *image, + GimpLayer *layer); +static gint gimp_image_selected_is_descendant (GimpViewable *selected, + GimpViewable *viewable); G_DEFINE_TYPE_WITH_CODE (GimpImage, gimp_image, GIMP_TYPE_VIEWABLE, G_ADD_PRIVATE (GimpImage) @@ -331,19 +338,19 @@ gimp_image_class_init (GimpImageClass *klass) NULL, NULL, NULL, G_TYPE_NONE, 0); - gimp_image_signals[ACTIVE_CHANNEL_CHANGED] = - g_signal_new ("active-channel-changed", + gimp_image_signals[SELECTED_CHANNELS_CHANGED] = + g_signal_new ("selected-channels-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (GimpImageClass, active_channel_changed), + G_STRUCT_OFFSET (GimpImageClass, selected_channels_changed), NULL, NULL, NULL, G_TYPE_NONE, 0); - gimp_image_signals[ACTIVE_VECTORS_CHANGED] = - g_signal_new ("active-vectors-changed", + gimp_image_signals[SELECTED_VECTORS_CHANGED] = + g_signal_new ("selected-vectors-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (GimpImageClass, active_vectors_changed), + G_STRUCT_OFFSET (GimpImageClass, selected_vectors_changed), NULL, NULL, NULL, G_TYPE_NONE, 0); @@ -584,8 +591,9 @@ gimp_image_class_init (GimpImageClass *klass) klass->precision_changed = gimp_image_real_precision_changed; klass->alpha_changed = NULL; klass->floating_selection_changed = NULL; - klass->active_channel_changed = NULL; - klass->active_vectors_changed = NULL; + klass->selected_layers_changed = NULL; + klass->selected_channels_changed = NULL; + klass->selected_vectors_changed = NULL; klass->linked_items_changed = NULL; klass->component_visibility_changed = NULL; klass->component_active_changed = NULL; @@ -770,13 +778,13 @@ gimp_image_init (GimpImage *image) image); g_signal_connect (private->layers, "notify::selected-items", - G_CALLBACK (gimp_image_active_layer_notify), + G_CALLBACK (gimp_image_selected_layers_notify), image); g_signal_connect (private->channels, "notify::selected-items", - G_CALLBACK (gimp_image_active_channel_notify), + G_CALLBACK (gimp_image_selected_channels_notify), image); g_signal_connect (private->vectors, "notify::selected-items", - G_CALLBACK (gimp_image_active_vectors_notify), + G_CALLBACK (gimp_image_selected_vectors_notify), image); g_signal_connect_swapped (private->layers->container, "update", @@ -1110,7 +1118,8 @@ gimp_image_finalize (GObject *object) if (private->layer_stack) { - g_slist_free (private->layer_stack); + g_slist_free_full (private->layer_stack, + (GDestroyNotify) g_list_free); private->layer_stack = NULL; } @@ -1721,45 +1730,56 @@ gimp_image_channel_color_changed (GimpChannel *channel, } static void -gimp_image_active_layer_notify (GimpItemTree *tree, - const GParamSpec *pspec, - GimpImage *image) +gimp_image_selected_layers_notify (GimpItemTree *tree, + const GParamSpec *pspec, + GimpImage *image) { GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image); - GimpLayer *layer = gimp_image_get_active_layer (image); + GList *layers = gimp_image_get_selected_layers (image); - if (layer) + if (layers) { /* Configure the layer stack to reflect this change */ - private->layer_stack = g_slist_remove (private->layer_stack, layer); - private->layer_stack = g_slist_prepend (private->layer_stack, layer); + GSList *prev_layers; + + prev_layers = g_slist_find_custom (private->layer_stack, layers, + (GCompareFunc) gimp_image_layer_stack_cmp); + + if (prev_layers) + { + g_list_free (prev_layers->data); + private->layer_stack = g_slist_delete_link (private->layer_stack, + prev_layers); + } + private->layer_stack = g_slist_prepend (private->layer_stack, + g_list_copy (layers)); } g_signal_emit (image, gimp_image_signals[SELECTED_LAYERS_CHANGED], 0); - if (layer && gimp_image_get_active_channel (image)) - gimp_image_set_active_channel (image, NULL); + if (layers && gimp_image_get_selected_channels (image)) + gimp_image_set_selected_channels (image, NULL); } static void -gimp_image_active_channel_notify (GimpItemTree *tree, - const GParamSpec *pspec, - GimpImage *image) +gimp_image_selected_channels_notify (GimpItemTree *tree, + const GParamSpec *pspec, + GimpImage *image) { - GimpChannel *channel = gimp_image_get_active_channel (image); + GList *channels = gimp_image_get_selected_channels (image); - g_signal_emit (image, gimp_image_signals[ACTIVE_CHANNEL_CHANGED], 0); + g_signal_emit (image, gimp_image_signals[SELECTED_CHANNELS_CHANGED], 0); - if (channel && gimp_image_get_active_layer (image)) - gimp_image_set_active_layer (image, NULL); + if (channels && gimp_image_get_selected_layers (image)) + gimp_image_set_selected_layers (image, NULL); } static void -gimp_image_active_vectors_notify (GimpItemTree *tree, - const GParamSpec *pspec, - GimpImage *image) +gimp_image_selected_vectors_notify (GimpItemTree *tree, + const GParamSpec *pspec, + GimpImage *image) { - g_signal_emit (image, gimp_image_signals[ACTIVE_VECTORS_CHANGED], 0); + g_signal_emit (image, gimp_image_signals[SELECTED_VECTORS_CHANGED], 0); } static void @@ -1838,6 +1858,96 @@ gimp_image_update_bounding_box (GimpImage *image) } } +static gint +gimp_image_layer_stack_cmp (GList *layers1, + GList *layers2) +{ + if (g_list_length (layers1) != g_list_length (layers2)) + { + /* We don't really need to order lists of layers, and only care + * about identity. + */ + return 1; + } + else + { + GList *iter; + + for (iter = layers1; iter; iter = iter->next) + { + if (! g_list_find (layers2, iter)) + return 1; + } + return 0; + } +} + +static void +gimp_image_remove_from_layer_stack (GimpImage *image, + GimpLayer *layer) +{ + GimpImagePrivate *private; + GSList *slist; + + g_return_if_fail (GIMP_IS_IMAGE (image)); + g_return_if_fail (GIMP_IS_LAYER (layer)); + + private = GIMP_IMAGE_GET_PRIVATE (image); + + /* Remove layer itself from the MRU layer stack. */ + for (slist = private->layer_stack; slist; slist = slist->next) + { + GList *layers = slist->data; + + layers = g_list_remove (layers, layer); + if (layers == NULL) + private->layer_stack = g_slist_delete_link (private->layer_stack, slist); + else + slist->data = layers; + } + + /* Also remove all children of a group layer from the layer_stack */ + if (gimp_viewable_get_children (GIMP_VIEWABLE (layer))) + { + GimpContainer *stack = gimp_viewable_get_children (GIMP_VIEWABLE (layer)); + GList *children; + GList *list; + + children = gimp_item_stack_get_item_list (GIMP_ITEM_STACK (stack)); + + for (list = children; list; list = g_list_next (list)) + { + GimpLayer *child = list->data; + + for (slist = private->layer_stack; slist; slist = slist->next) + { + GList *layers = slist->data; + + layers = g_list_remove (layers, child); + if (layers == NULL) + private->layer_stack = g_slist_delete_link (private->layer_stack, slist); + else + slist->data = layers; + } + } + + g_list_free (children); + } +} + +static gint +gimp_image_selected_is_descendant (GimpViewable *selected, + GimpViewable *viewable) +{ + /* Used as a GCompareFunc to g_list_find_custom() in order to know if + * one of the selected items is a descendant to @viewable. + */ + if (gimp_viewable_is_ancestor (viewable, selected)) + return 0; + else + return 1; +} + /* public functions */ @@ -3076,7 +3186,7 @@ gimp_image_set_component_active (GimpImage *image, /* If there is an active channel and we mess with the components, * the active channel gets unset... */ - gimp_image_unset_active_channel (image); + gimp_image_unset_selected_channels (image); g_signal_emit (image, gimp_image_signals[COMPONENT_ACTIVE_CHANGED], 0, @@ -4266,7 +4376,6 @@ gimp_image_set_active_layer (GimpImage *image, GimpLayer *layer) { GList *layers = NULL; - GList *new_layers; GimpLayer *active_layer; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); @@ -4278,11 +4387,11 @@ gimp_image_set_active_layer (GimpImage *image, if (layer) layers = g_list_prepend (NULL, layer); - new_layers = gimp_image_set_selected_layers (image, layers); + gimp_image_set_selected_layers (image, layers); g_list_free (layers); - active_layer = g_list_length (new_layers) == 1 ? new_layers->data : NULL; - g_list_free (new_layers); + layers = gimp_image_get_selected_layers (image); + active_layer = g_list_length (layers) == 1 ? layers->data : NULL; return active_layer; } @@ -4293,7 +4402,6 @@ gimp_image_set_active_channel (GimpImage *image, { GimpChannel *active_channel; GList *channels = NULL; - GList *new_channels; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (channel == NULL || GIMP_IS_CHANNEL (channel), NULL); @@ -4309,36 +4417,34 @@ gimp_image_set_active_channel (GimpImage *image, if (channel) channels = g_list_prepend (NULL, channel); - new_channels = gimp_image_set_selected_channels (image, channels); + gimp_image_set_selected_channels (image, channels); g_list_free (channels); - active_channel = g_list_length (new_channels) == 1 ? new_channels->data : NULL; - g_list_free (new_channels); + channels = gimp_image_get_selected_channels (image); + active_channel = g_list_length (channels) == 1 ? channels->data : NULL; return active_channel; } -GimpChannel * -gimp_image_unset_active_channel (GimpImage *image) +void +gimp_image_unset_selected_channels (GimpImage *image) { GimpImagePrivate *private; - GimpChannel *channel; + GList *channels; - g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); + g_return_if_fail (GIMP_IS_IMAGE (image)); private = GIMP_IMAGE_GET_PRIVATE (image); - channel = gimp_image_get_active_channel (image); + channels = gimp_image_get_selected_channels (image); - if (channel) + if (channels) { - gimp_image_set_active_channel (image, NULL); + gimp_image_set_selected_channels (image, NULL); if (private->layer_stack) - gimp_image_set_active_layer (image, private->layer_stack->data); + gimp_image_set_selected_layers (image, private->layer_stack->data); } - - return channel; } GimpVectors * @@ -4346,7 +4452,6 @@ gimp_image_set_active_vectors (GimpImage *image, GimpVectors *vectors) { GList *all_vectors = NULL; - GList *new_vectors; GimpVectors *active_vectors; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); @@ -4358,11 +4463,11 @@ gimp_image_set_active_vectors (GimpImage *image, if (vectors) all_vectors = g_list_prepend (NULL, vectors); - new_vectors = gimp_image_set_selected_vectors (image, all_vectors); + gimp_image_set_selected_vectors (image, all_vectors); g_list_free (all_vectors); - active_vectors = (g_list_length (new_vectors) == 1 ? new_vectors->data : NULL); - g_list_free (new_vectors); + all_vectors = gimp_image_get_selected_vectors (image); + active_vectors = (g_list_length (all_vectors) == 1 ? all_vectors->data : NULL); return active_vectors; } @@ -4403,25 +4508,24 @@ gimp_image_get_selected_vectors (GimpImage *image) return gimp_item_tree_get_selected_items (private->vectors); } -GList * +void gimp_image_set_selected_layers (GimpImage *image, GList *layers) { GimpImagePrivate *private; GimpLayer *floating_sel; - GimpLayer *active_layer; GList *selected_layers; GList *layers2; GList *iter; gboolean selection_changed = TRUE; - g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); + g_return_if_fail (GIMP_IS_IMAGE (image)); layers2 = g_list_copy (layers); for (iter = layers; iter; iter = iter->next) { - g_return_val_if_fail (GIMP_IS_LAYER (iter->data), NULL); - g_return_val_if_fail (gimp_item_get_image (GIMP_ITEM (iter->data)) == image, NULL); + g_return_if_fail (GIMP_IS_LAYER (iter->data)); + g_return_if_fail (gimp_item_get_image (GIMP_ITEM (iter->data)) == image); /* Silently remove non-attached layers from selection. Do not * error out on it as it may happen for instance when selection @@ -4437,10 +4541,9 @@ gimp_image_set_selected_layers (GimpImage *image, /* Make sure the floating_sel always is the active layer */ if (floating_sel && (g_list_length (layers2) != 1 || layers2->data != floating_sel)) - return g_list_prepend (NULL, floating_sel); + return; selected_layers = gimp_image_get_selected_layers (image); - active_layer = gimp_image_get_active_layer (image); if (g_list_length (layers2) == g_list_length (selected_layers)) { @@ -4458,8 +4561,8 @@ gimp_image_set_selected_layers (GimpImage *image, if (selection_changed) { /* Don't cache selection info for the previous active layer */ - if (active_layer) - gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (active_layer)); + if (selected_layers) + gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (selected_layers->data)); gimp_item_tree_set_selected_items (private->layers, layers2); } @@ -4467,57 +4570,51 @@ gimp_image_set_selected_layers (GimpImage *image, { g_list_free (layers2); } - - return g_list_copy (gimp_image_get_selected_layers (image)); } -GList * +void gimp_image_set_selected_channels (GimpImage *image, GList *channels) { GimpImagePrivate *private; GList *iter; - g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); + g_return_if_fail (GIMP_IS_IMAGE (image)); for (iter = channels; iter; iter = iter->next) { - g_return_val_if_fail (GIMP_IS_CHANNEL (iter->data), NULL); - g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (iter->data)) && - gimp_item_get_image (GIMP_ITEM (iter->data)) == image, NULL); + g_return_if_fail (GIMP_IS_CHANNEL (iter->data)); + g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (iter->data)) && + gimp_item_get_image (GIMP_ITEM (iter->data)) == image); } private = GIMP_IMAGE_GET_PRIVATE (image); /* Not if there is a floating selection */ if (g_list_length (channels) > 0 && gimp_image_get_floating_selection (image)) - return NULL; + return; gimp_item_tree_set_selected_items (private->channels, g_list_copy (channels)); - - return g_list_copy (gimp_image_get_selected_channels (image)); } -GList * +void gimp_image_set_selected_vectors (GimpImage *image, GList *vectors) { GimpImagePrivate *private; GList *iter; - g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); + g_return_if_fail (GIMP_IS_IMAGE (image)); for (iter = vectors; iter; iter = iter->next) { - g_return_val_if_fail (GIMP_IS_VECTORS (iter->data), NULL); - g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (iter->data)) && - gimp_item_get_image (GIMP_ITEM (iter->data)) == image, NULL); + g_return_if_fail (GIMP_IS_VECTORS (iter->data)); + g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (iter->data)) && + gimp_item_get_image (GIMP_ITEM (iter->data)) == image); } private = GIMP_IMAGE_GET_PRIVATE (image); gimp_item_tree_set_selected_items (private->vectors, g_list_copy (vectors)); - - return g_list_copy (gimp_image_get_selected_vectors (image)); } @@ -4759,6 +4856,7 @@ gimp_image_add_layer (GimpImage *image, gboolean push_undo) { GimpImagePrivate *private; + GList *selected_layers; gboolean old_has_alpha; g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); @@ -4787,12 +4885,14 @@ gimp_image_add_layer (GimpImage *image, if (push_undo) gimp_image_undo_push_layer_add (image, C_("undo-type", "Add Layer"), layer, - gimp_image_get_active_layer (image)); + gimp_image_get_selected_layers (image)); gimp_item_tree_add_item (private->layers, GIMP_ITEM (layer), GIMP_ITEM (parent), position); - gimp_image_set_active_layer (image, layer); + selected_layers = g_list_prepend (NULL, layer); + gimp_image_set_selected_layers (image, selected_layers); + g_list_free (selected_layers); /* If the layer is a floating selection, attach it to the drawable */ if (gimp_layer_is_floating_sel (layer)) @@ -4809,10 +4909,10 @@ void gimp_image_remove_layer (GimpImage *image, GimpLayer *layer, gboolean push_undo, - GimpLayer *new_active) + GList *new_selected) { GimpImagePrivate *private; - GimpLayer *active_layer; + GList *selected_layers; gboolean old_has_alpha; const gchar *undo_desc; @@ -4846,7 +4946,7 @@ gimp_image_remove_layer (GimpImage *image, TRUE, NULL); } - active_layer = gimp_image_get_active_layer (image); + selected_layers = g_list_copy (gimp_image_get_selected_layers (image)); old_has_alpha = gimp_image_has_alpha (image); @@ -4865,38 +4965,20 @@ gimp_image_remove_layer (GimpImage *image, gimp_image_undo_push_layer_remove (image, undo_desc, layer, gimp_layer_get_parent (layer), gimp_item_get_index (GIMP_ITEM (layer)), - active_layer); + selected_layers); g_object_ref (layer); /* Make sure we're not caching any old selection info */ - if (layer == active_layer) + if (g_list_find (selected_layers, layer)) gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (layer)); - private->layer_stack = g_slist_remove (private->layer_stack, layer); + /* Remove layer and its children from the MRU layer stack. */ + gimp_image_remove_from_layer_stack (image, layer); - /* Also remove all children of a group layer from the layer_stack */ - if (gimp_viewable_get_children (GIMP_VIEWABLE (layer))) - { - GimpContainer *stack = gimp_viewable_get_children (GIMP_VIEWABLE (layer)); - GList *children; - GList *list; - - children = gimp_item_stack_get_item_list (GIMP_ITEM_STACK (stack)); - - for (list = children; list; list = g_list_next (list)) - { - private->layer_stack = g_slist_remove (private->layer_stack, - list->data); - } - - g_list_free (children); - } - - new_active = - GIMP_LAYER (gimp_item_tree_remove_item (private->layers, - GIMP_ITEM (layer), - GIMP_ITEM (new_active))); + new_selected = gimp_item_tree_remove_item (private->layers, + GIMP_ITEM (layer), + new_selected); if (gimp_layer_is_floating_sel (layer)) { @@ -4904,17 +4986,20 @@ gimp_image_remove_layer (GimpImage *image, */ floating_sel_activate_drawable (layer); } - else if (active_layer && - (layer == active_layer || - gimp_viewable_is_ancestor (GIMP_VIEWABLE (layer), - GIMP_VIEWABLE (active_layer)))) + else if (selected_layers && + (g_list_find (selected_layers, layer) || + g_list_find_custom (selected_layers, layer, + (GCompareFunc) gimp_image_selected_is_descendant))) { - gimp_image_set_active_layer (image, new_active); + gimp_image_set_selected_layers (image, new_selected); } gimp_item_end_move (GIMP_ITEM (layer), push_undo); g_object_unref (layer); + g_list_free (selected_layers); + if (new_selected) + g_list_free (new_selected); if (old_has_alpha != gimp_image_has_alpha (image)) private->flush_accum.alpha_changed = TRUE; @@ -4989,7 +5074,7 @@ gimp_image_add_layers (GimpImage *image, } if (layers) - gimp_image_set_active_layer (image, layers->data); + gimp_image_set_selected_layers (image, layers); gimp_image_undo_group_end (image); } @@ -5005,6 +5090,7 @@ gimp_image_add_channel (GimpImage *image, gboolean push_undo) { GimpImagePrivate *private; + GList *channels; g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); @@ -5021,12 +5107,14 @@ gimp_image_add_channel (GimpImage *image, if (push_undo) gimp_image_undo_push_channel_add (image, C_("undo-type", "Add Channel"), channel, - gimp_image_get_active_channel (image)); + gimp_image_get_selected_channels (image)); gimp_item_tree_add_item (private->channels, GIMP_ITEM (channel), GIMP_ITEM (parent), position); - gimp_image_set_active_channel (image, channel); + channels = g_list_prepend (NULL, channel); + gimp_image_set_selected_channels (image, channels); + g_list_free (channels); return TRUE; } @@ -5035,10 +5123,10 @@ void gimp_image_remove_channel (GimpImage *image, GimpChannel *channel, gboolean push_undo, - GimpChannel *new_active) + GList *new_selected) { GimpImagePrivate *private; - GimpChannel *active_channel; + GList *selected_channels; g_return_if_fail (GIMP_IS_IMAGE (image)); g_return_if_fail (GIMP_IS_CHANNEL (channel)); @@ -5068,35 +5156,36 @@ gimp_image_remove_channel (GimpImage *image, private = GIMP_IMAGE_GET_PRIVATE (image); - active_channel = gimp_image_get_active_channel (image); + selected_channels = gimp_image_get_selected_channels (image); if (push_undo) gimp_image_undo_push_channel_remove (image, C_("undo-type", "Remove Channel"), channel, gimp_channel_get_parent (channel), gimp_item_get_index (GIMP_ITEM (channel)), - active_channel); + selected_channels); g_object_ref (channel); - new_active = - GIMP_CHANNEL (gimp_item_tree_remove_item (private->channels, - GIMP_ITEM (channel), - GIMP_ITEM (new_active))); + new_selected = gimp_item_tree_remove_item (private->channels, + GIMP_ITEM (channel), + new_selected); - if (active_channel && - (channel == active_channel || - gimp_viewable_is_ancestor (GIMP_VIEWABLE (channel), - GIMP_VIEWABLE (active_channel)))) + if (selected_channels && + (g_list_find (selected_channels, channel) || + g_list_find_custom (selected_channels, channel, + (GCompareFunc) gimp_image_selected_is_descendant))) { - if (new_active) - gimp_image_set_active_channel (image, new_active); + if (new_selected) + gimp_image_set_selected_channels (image, new_selected); else - gimp_image_unset_active_channel (image); + gimp_image_unset_selected_channels (image); } gimp_item_end_move (GIMP_ITEM (channel), push_undo); g_object_unref (channel); + if (new_selected) + g_list_free (new_selected); if (push_undo) gimp_image_undo_group_end (image); @@ -5129,7 +5218,7 @@ gimp_image_add_vectors (GimpImage *image, if (push_undo) gimp_image_undo_push_vectors_add (image, C_("undo-type", "Add Path"), vectors, - gimp_image_get_active_vectors (image)); + gimp_image_get_selected_vectors (image)); gimp_item_tree_add_item (private->vectors, GIMP_ITEM (vectors), GIMP_ITEM (parent), position); @@ -5143,10 +5232,10 @@ void gimp_image_remove_vectors (GimpImage *image, GimpVectors *vectors, gboolean push_undo, - GimpVectors *new_active) + GList *new_selected) { GimpImagePrivate *private; - GimpVectors *active_vectors; + GList *selected_vectors; g_return_if_fail (GIMP_IS_IMAGE (image)); g_return_if_fail (GIMP_IS_VECTORS (vectors)); @@ -5161,32 +5250,33 @@ gimp_image_remove_vectors (GimpImage *image, gimp_item_start_move (GIMP_ITEM (vectors), push_undo); - active_vectors = gimp_image_get_active_vectors (image); + selected_vectors = gimp_image_get_selected_vectors (image); if (push_undo) gimp_image_undo_push_vectors_remove (image, C_("undo-type", "Remove Path"), vectors, gimp_vectors_get_parent (vectors), gimp_item_get_index (GIMP_ITEM (vectors)), - active_vectors); + selected_vectors); g_object_ref (vectors); - new_active = - GIMP_VECTORS (gimp_item_tree_remove_item (private->vectors, - GIMP_ITEM (vectors), - GIMP_ITEM (new_active))); + new_selected = gimp_item_tree_remove_item (private->vectors, + GIMP_ITEM (vectors), + new_selected); - if (active_vectors && - (vectors == active_vectors || - gimp_viewable_is_ancestor (GIMP_VIEWABLE (vectors), - GIMP_VIEWABLE (active_vectors)))) + if (selected_vectors && + (g_list_find (selected_vectors, vectors) || + g_list_find_custom (selected_vectors, vectors, + (GCompareFunc) gimp_image_selected_is_descendant))) { - gimp_image_set_active_vectors (image, new_active); + gimp_image_set_selected_vectors (image, new_selected); } gimp_item_end_move (GIMP_ITEM (vectors), push_undo); g_object_unref (vectors); + if (new_selected) + g_list_free (new_selected); if (push_undo) gimp_image_undo_group_end (image); diff --git a/app/core/gimpimage.h b/app/core/gimpimage.h index fc09fe5f80..33d973a3ba 100644 --- a/app/core/gimpimage.h +++ b/app/core/gimpimage.h @@ -54,8 +54,8 @@ struct _GimpImageClass void (* precision_changed) (GimpImage *image); void (* alpha_changed) (GimpImage *image); void (* floating_selection_changed) (GimpImage *image); - void (* active_channel_changed) (GimpImage *image); - void (* active_vectors_changed) (GimpImage *image); + void (* selected_channels_changed) (GimpImage *image); + void (* selected_vectors_changed) (GimpImage *image); void (* selected_layers_changed) (GimpImage *image); void (* linked_items_changed) (GimpImage *image); void (* component_visibility_changed) (GimpImage *image, @@ -375,7 +375,7 @@ GimpLayer * gimp_image_set_active_layer (GimpImage *image, GimpLayer *layer); GimpChannel * gimp_image_set_active_channel (GimpImage *image, GimpChannel *channel); -GimpChannel * gimp_image_unset_active_channel (GimpImage *image); +void gimp_image_unset_selected_channels (GimpImage *image); GimpVectors * gimp_image_set_active_vectors (GimpImage *image, GimpVectors *vectors); @@ -383,11 +383,11 @@ GList * gimp_image_get_selected_layers (GimpImage *image); GList * gimp_image_get_selected_channels (GimpImage *image); GList * gimp_image_get_selected_vectors (GimpImage *image); -GList * gimp_image_set_selected_layers (GimpImage *image, +void gimp_image_set_selected_layers (GimpImage *image, GList *layers); -GList * gimp_image_set_selected_channels (GimpImage *image, +void gimp_image_set_selected_channels (GimpImage *image, GList *channels); -GList * gimp_image_set_selected_vectors (GimpImage *image, +void gimp_image_set_selected_vectors (GimpImage *image, GList *vectors); GimpLayer * gimp_image_get_layer_by_tattoo (GimpImage *image, @@ -429,7 +429,7 @@ gboolean gimp_image_add_layer (GimpImage *image, void gimp_image_remove_layer (GimpImage *image, GimpLayer *layer, gboolean push_undo, - GimpLayer *new_active); + GList *new_selected); void gimp_image_add_layers (GimpImage *image, GList *layers, @@ -449,7 +449,7 @@ gboolean gimp_image_add_channel (GimpImage *image, void gimp_image_remove_channel (GimpImage *image, GimpChannel *channel, gboolean push_undo, - GimpChannel *new_active); + GList *new_selected); gboolean gimp_image_add_vectors (GimpImage *image, GimpVectors *vectors, @@ -459,7 +459,7 @@ gboolean gimp_image_add_vectors (GimpImage *image, void gimp_image_remove_vectors (GimpImage *image, GimpVectors *vectors, gboolean push_undo, - GimpVectors *new_active); + GList *new_selected); gboolean gimp_image_coords_in_active_pickable (GimpImage *image, const GimpCoords *coords, diff --git a/app/core/gimpitemtree.c b/app/core/gimpitemtree.c index 4cceaaf2cc..c83821d927 100644 --- a/app/core/gimpitemtree.c +++ b/app/core/gimpitemtree.c @@ -565,10 +565,10 @@ gimp_item_tree_add_item (GimpItemTree *tree, gimp_item_unset_removed (item); } -GimpItem * +GList * gimp_item_tree_remove_item (GimpItemTree *tree, GimpItem *item, - GimpItem *new_active) + GList *new_selected) { GimpItemTreePrivate *private; GimpItem *parent; @@ -615,26 +615,34 @@ gimp_item_tree_remove_item (GimpItemTree *tree, gimp_item_removed (item); - if (! new_active) + if (! new_selected) { - gint n_children = gimp_container_get_n_children (container); + GimpItem *selected = NULL; + gint n_children = gimp_container_get_n_children (container); if (n_children > 0) { index = CLAMP (index, 0, n_children - 1); - new_active = + selected = GIMP_ITEM (gimp_container_get_child_by_index (container, index)); } else if (parent) { - new_active = parent; + selected = parent; } + + if (selected) + new_selected = g_list_prepend (NULL, selected); + } + else + { + new_selected = g_list_copy (new_selected); } g_object_unref (item); - return new_active; + return new_selected; } gboolean diff --git a/app/core/gimpitemtree.h b/app/core/gimpitemtree.h index 0678999826..2367a9b9b8 100644 --- a/app/core/gimpitemtree.h +++ b/app/core/gimpitemtree.h @@ -72,9 +72,9 @@ void gimp_item_tree_add_item (GimpItemTree *tree, GimpItem *item, GimpItem *parent, gint position); -GimpItem * gimp_item_tree_remove_item (GimpItemTree *tree, +GList * gimp_item_tree_remove_item (GimpItemTree *tree, GimpItem *item, - GimpItem *new_active); + GList *new_selected); gboolean gimp_item_tree_reorder_item (GimpItemTree *tree, GimpItem *item, diff --git a/app/core/gimplayer-floating-selection.c b/app/core/gimplayer-floating-selection.c index 80222a2b0c..cb0a482cdf 100644 --- a/app/core/gimplayer-floating-selection.c +++ b/app/core/gimplayer-floating-selection.c @@ -228,11 +228,19 @@ floating_sel_activate_drawable (GimpLayer *layer) } else if (GIMP_IS_CHANNEL (drawable)) { - gimp_image_set_active_channel (image, GIMP_CHANNEL (drawable)); + GList *channels = g_list_prepend (NULL, drawable); + + gimp_image_set_selected_channels (image, channels); + + g_list_free (channels); } else { - gimp_image_set_active_layer (image, GIMP_LAYER (drawable)); + GList *layers = g_list_prepend (NULL, drawable); + + gimp_image_set_selected_layers (image, layers); + + g_list_free (layers); } } diff --git a/app/core/gimplayerundo.c b/app/core/gimplayerundo.c index 66abf8b208..2cae9ce81c 100644 --- a/app/core/gimplayerundo.c +++ b/app/core/gimplayerundo.c @@ -34,11 +34,12 @@ enum PROP_0, PROP_PREV_PARENT, PROP_PREV_POSITION, - PROP_PREV_LAYER + PROP_PREV_LAYERS }; static void gimp_layer_undo_constructed (GObject *object); +static void gimp_layer_undo_finalize (GObject *object); static void gimp_layer_undo_set_property (GObject *object, guint property_id, const GValue *value, @@ -69,6 +70,7 @@ gimp_layer_undo_class_init (GimpLayerUndoClass *klass) GimpUndoClass *undo_class = GIMP_UNDO_CLASS (klass); object_class->constructed = gimp_layer_undo_constructed; + object_class->finalize = gimp_layer_undo_finalize; object_class->set_property = gimp_layer_undo_set_property; object_class->get_property = gimp_layer_undo_get_property; @@ -89,16 +91,16 @@ gimp_layer_undo_class_init (GimpLayerUndoClass *klass) GIMP_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - g_object_class_install_property (object_class, PROP_PREV_LAYER, - g_param_spec_object ("prev-layer", NULL, NULL, - GIMP_TYPE_LAYER, - GIMP_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, PROP_PREV_LAYERS, + g_param_spec_pointer ("prev-layers", NULL, NULL, + GIMP_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); } static void gimp_layer_undo_init (GimpLayerUndo *undo) { + undo->prev_layers = NULL; } static void @@ -109,6 +111,15 @@ gimp_layer_undo_constructed (GObject *object) gimp_assert (GIMP_IS_LAYER (GIMP_ITEM_UNDO (object)->item)); } +static void +gimp_layer_undo_finalize (GObject *object) +{ + GimpLayerUndo *undo = GIMP_LAYER_UNDO (object); + + g_clear_pointer (&undo->prev_layers, g_list_free); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} static void gimp_layer_undo_set_property (GObject *object, guint property_id, @@ -125,8 +136,8 @@ gimp_layer_undo_set_property (GObject *object, case PROP_PREV_POSITION: layer_undo->prev_position = g_value_get_int (value); break; - case PROP_PREV_LAYER: - layer_undo->prev_layer = g_value_get_object (value); + case PROP_PREV_LAYERS: + layer_undo->prev_layers = g_list_copy (g_value_get_pointer (value)); break; default: @@ -151,8 +162,8 @@ gimp_layer_undo_get_property (GObject *object, case PROP_PREV_POSITION: g_value_set_int (value, layer_undo->prev_position); break; - case PROP_PREV_LAYER: - g_value_set_object (value, layer_undo->prev_layer); + case PROP_PREV_LAYERS: + g_value_set_pointer (value, layer_undo->prev_layers); break; default: @@ -198,14 +209,15 @@ gimp_layer_undo_pop (GimpUndo *undo, layer_undo->prev_position = gimp_item_get_index (GIMP_ITEM (layer)); gimp_image_remove_layer (undo->image, layer, FALSE, - layer_undo->prev_layer); + layer_undo->prev_layers); } else { /* restore layer */ /* record the active layer */ - layer_undo->prev_layer = gimp_image_get_active_layer (undo->image); + g_clear_pointer (&layer_undo->prev_layers, g_list_free); + layer_undo->prev_layers = g_list_copy (gimp_image_get_selected_layers (undo->image)); gimp_image_add_layer (undo->image, layer, layer_undo->prev_parent, diff --git a/app/core/gimplayerundo.h b/app/core/gimplayerundo.h index 700fce87ae..5d99b2773d 100644 --- a/app/core/gimplayerundo.h +++ b/app/core/gimplayerundo.h @@ -39,7 +39,7 @@ struct _GimpLayerUndo GimpLayer *prev_parent; gint prev_position; /* former position in list */ - GimpLayer *prev_layer; /* previous active layer */ + GList *prev_layers; /* previous selected layers */ }; struct _GimpLayerUndoClass diff --git a/app/display/gimpdisplayshell-handlers.c b/app/display/gimpdisplayshell-handlers.c index 2d7e65e89b..f1d340f913 100644 --- a/app/display/gimpdisplayshell-handlers.c +++ b/app/display/gimpdisplayshell-handlers.c @@ -295,7 +295,7 @@ gimp_display_shell_connect (GimpDisplayShell *shell) G_CALLBACK (gimp_display_shell_exported_handler), shell); - g_signal_connect (image, "active-vectors-changed", + g_signal_connect (image, "selected-vectors-changed", G_CALLBACK (gimp_display_shell_active_vectors_handler), shell); diff --git a/app/pdb/image-cmds.c b/app/pdb/image-cmds.c index 1ab6ce4bdc..2d814403e3 100644 --- a/app/pdb/image-cmds.c +++ b/app/pdb/image-cmds.c @@ -593,7 +593,7 @@ image_unset_active_channel_invoker (GimpProcedure *procedure, if (success) { - gimp_image_unset_active_channel (image); + gimp_image_unset_selected_channels (image); } return gimp_procedure_get_return_values (procedure, success, diff --git a/app/tools/gimpbucketfilltool.c b/app/tools/gimpbucketfilltool.c index acab6f2d03..3c988f6af0 100644 --- a/app/tools/gimpbucketfilltool.c +++ b/app/tools/gimpbucketfilltool.c @@ -961,7 +961,7 @@ gimp_bucket_fill_tool_reset_line_art (GimpBucketFillTool *tool) g_signal_connect_swapped (image, "selected-layers-changed", G_CALLBACK (gimp_bucket_fill_tool_reset_line_art), tool); - g_signal_connect_swapped (image, "active-channel-changed", + g_signal_connect_swapped (image, "selected-channels-changed", G_CALLBACK (gimp_bucket_fill_tool_reset_line_art), tool); diff --git a/app/tools/gimpmovetool.c b/app/tools/gimpmovetool.c index 8d1d617199..0b750a252b 100644 --- a/app/tools/gimpmovetool.c +++ b/app/tools/gimpmovetool.c @@ -155,8 +155,8 @@ gimp_move_tool_init (GimpMoveTool *move_tool) move_tool->saved_type = GIMP_TRANSFORM_TYPE_LAYER; - move_tool->old_active_layer = NULL; - move_tool->old_active_vectors = NULL; + move_tool->old_selected_layers = NULL; + move_tool->old_selected_vectors = NULL; } static void @@ -165,6 +165,8 @@ gimp_move_tool_finalize (GObject *object) GimpMoveTool *move = GIMP_MOVE_TOOL (object); g_clear_pointer (&move->guides, g_list_free); + g_clear_pointer (&move->old_selected_layers, g_list_free); + g_clear_pointer (&move->old_selected_vectors, g_list_free); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -206,10 +208,13 @@ gimp_move_tool_button_press (GimpTool *tool, FUNSCALEY (shell, snap_distance)); if (vectors) { - move->old_active_vectors = - gimp_image_get_active_vectors (image); + GList *new_selected_vectors = g_list_prepend (NULL, vectors); - gimp_image_set_active_vectors (image, vectors); + move->old_selected_vectors = + g_list_copy (gimp_image_get_selected_vectors (image)); + + gimp_image_set_selected_vectors (image, new_selected_vectors); + g_list_free (new_selected_vectors); } else { @@ -254,9 +259,12 @@ gimp_move_tool_button_press (GimpTool *tool, } else { - move->old_active_layer = gimp_image_get_active_layer (image); + GList *new_selected_layers = g_list_prepend (NULL, layer); - gimp_image_set_active_layer (image, layer); + move->old_selected_layers = g_list_copy (gimp_image_get_selected_layers (image)); + + gimp_image_set_selected_layers (image, new_selected_layers); + g_list_free (new_selected_layers); } } else @@ -388,18 +396,18 @@ gimp_move_tool_button_release (GimpTool *tool, if (! config->move_tool_changes_active || (release_type == GIMP_BUTTON_RELEASE_CANCEL)) { - if (move->old_active_layer) + if (move->old_selected_layers) { - gimp_image_set_active_layer (image, move->old_active_layer); - move->old_active_layer = NULL; + gimp_image_set_selected_layers (image, move->old_selected_layers); + g_clear_pointer (&move->old_selected_layers, g_list_free); flush = TRUE; } - if (move->old_active_vectors) + if (move->old_selected_vectors) { - gimp_image_set_active_vectors (image, move->old_active_vectors); - move->old_active_vectors = NULL; + gimp_image_set_selected_vectors (image, move->old_selected_vectors); + g_clear_pointer (&move->old_selected_vectors, g_list_free); flush = TRUE; } diff --git a/app/tools/gimpmovetool.h b/app/tools/gimpmovetool.h index a597e0124f..5f51b7f510 100644 --- a/app/tools/gimpmovetool.h +++ b/app/tools/gimpmovetool.h @@ -44,8 +44,8 @@ struct _GimpMoveTool GimpTransformType saved_type; - GimpLayer *old_active_layer; - GimpVectors *old_active_vectors; + GList *old_selected_layers; + GList *old_selected_vectors; }; struct _GimpMoveToolClass diff --git a/app/tools/gimptexttool.c b/app/tools/gimptexttool.c index b5172c17d0..37d0d4ca7d 100644 --- a/app/tools/gimptexttool.c +++ b/app/tools/gimptexttool.c @@ -487,12 +487,15 @@ gimp_text_tool_button_press (GimpTool *tool, if (text_layer && text_layer != text_tool->layer) { + GList *selection = g_list_prepend (NULL, text_layer); + if (text_tool->image == image) g_signal_handlers_block_by_func (image, gimp_text_tool_layer_changed, text_tool); - gimp_image_set_active_layer (image, GIMP_LAYER (text_layer)); + gimp_image_set_selected_layers (image, selection); + g_list_free (selection); if (text_tool->image == image) g_signal_handlers_unblock_by_func (image, @@ -1806,18 +1809,27 @@ static void gimp_text_tool_layer_changed (GimpImage *image, GimpTextTool *text_tool) { - GimpLayer *layer = gimp_image_get_active_layer (image); + GList *layers = gimp_image_get_selected_layers (image); - if (layer != GIMP_LAYER (text_tool->layer)) + if (g_list_length (layers) != 1 || layers->data != text_tool->layer) { GimpTool *tool = GIMP_TOOL (text_tool); GimpDisplay *display = tool->display; if (display) { + GimpLayer *layer = NULL; + gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display); - if (gimp_text_tool_set_drawable (text_tool, GIMP_DRAWABLE (layer), + if (g_list_length (layers) == 1) + layer = layers->data; + + /* The tool can only be started when a single layer is + * selected and this is a text layer. + */ + if (layer && + gimp_text_tool_set_drawable (text_tool, GIMP_DRAWABLE (layer), FALSE) && GIMP_LAYER (text_tool->layer) == layer) { diff --git a/app/tools/gimpvectortool.c b/app/tools/gimpvectortool.c index 3040a2a25a..76789cfd45 100644 --- a/app/tools/gimpvectortool.c +++ b/app/tools/gimpvectortool.c @@ -609,7 +609,7 @@ gimp_vector_tool_set_vectors (GimpVectorTool *vector_tool, vector_tool->vectors = g_object_ref (vectors); - g_signal_connect_object (gimp_item_get_image (item), "active-vectors-changed", + g_signal_connect_object (gimp_item_get_image (item), "selected-vectors-changed", G_CALLBACK (gimp_vector_tool_vectors_changed), vector_tool, 0); g_signal_connect_object (vectors, "removed", diff --git a/app/vectors/gimpvectorsundo.c b/app/vectors/gimpvectorsundo.c index 39857ecf60..e947fd59ff 100644 --- a/app/vectors/gimpvectorsundo.c +++ b/app/vectors/gimpvectorsundo.c @@ -40,6 +40,7 @@ enum static void gimp_vectors_undo_constructed (GObject *object); +static void gimp_vectors_undo_finalize (GObject *object); static void gimp_vectors_undo_set_property (GObject *object, guint property_id, const GValue *value, @@ -70,6 +71,7 @@ gimp_vectors_undo_class_init (GimpVectorsUndoClass *klass) GimpUndoClass *undo_class = GIMP_UNDO_CLASS (klass); object_class->constructed = gimp_vectors_undo_constructed; + object_class->finalize = gimp_vectors_undo_finalize; object_class->set_property = gimp_vectors_undo_set_property; object_class->get_property = gimp_vectors_undo_get_property; @@ -91,15 +93,15 @@ gimp_vectors_undo_class_init (GimpVectorsUndoClass *klass) G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_PREV_VECTORS, - g_param_spec_object ("prev-vectors", NULL, NULL, - GIMP_TYPE_VECTORS, - GIMP_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY)); + g_param_spec_pointer ("prev-vectors", NULL, NULL, + GIMP_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); } static void gimp_vectors_undo_init (GimpVectorsUndo *undo) { + undo->prev_vectors = NULL; } static void @@ -110,6 +112,16 @@ gimp_vectors_undo_constructed (GObject *object) gimp_assert (GIMP_IS_VECTORS (GIMP_ITEM_UNDO (object)->item)); } +static void +gimp_vectors_undo_finalize (GObject *object) +{ + GimpVectorsUndo *undo = GIMP_VECTORS_UNDO (object); + + g_clear_pointer (&undo->prev_vectors, g_list_free); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + static void gimp_vectors_undo_set_property (GObject *object, guint property_id, @@ -127,7 +139,7 @@ gimp_vectors_undo_set_property (GObject *object, vectors_undo->prev_position = g_value_get_int (value); break; case PROP_PREV_VECTORS: - vectors_undo->prev_vectors = g_value_get_object (value); + vectors_undo->prev_vectors = g_list_copy (g_value_get_pointer (value)); break; default: @@ -153,7 +165,7 @@ gimp_vectors_undo_get_property (GObject *object, g_value_set_int (value, vectors_undo->prev_position); break; case PROP_PREV_VECTORS: - g_value_set_object (value, vectors_undo->prev_vectors); + g_value_set_pointer (value, vectors_undo->prev_vectors); break; default: @@ -206,7 +218,8 @@ gimp_vectors_undo_pop (GimpUndo *undo, /* restore vectors */ /* record the active vectors */ - vectors_undo->prev_vectors = gimp_image_get_active_vectors (undo->image); + g_clear_pointer (&vectors_undo->prev_vectors, g_list_free); + vectors_undo->prev_vectors = g_list_copy (gimp_image_get_selected_vectors (undo->image)); gimp_image_add_vectors (undo->image, vectors, vectors_undo->prev_parent, diff --git a/app/vectors/gimpvectorsundo.h b/app/vectors/gimpvectorsundo.h index 9b5434669b..3df54f2228 100644 --- a/app/vectors/gimpvectorsundo.h +++ b/app/vectors/gimpvectorsundo.h @@ -38,8 +38,8 @@ struct _GimpVectorsUndo GimpItemUndo parent_instance; GimpVectors *prev_parent; - gint prev_position; /* former position in list */ - GimpVectors *prev_vectors; /* previous active vectors */ + gint prev_position; /* former position in list */ + GList *prev_vectors; /* previous selected vectors */ }; struct _GimpVectorsUndoClass diff --git a/app/widgets/gimpchanneltreeview.c b/app/widgets/gimpchanneltreeview.c index a6fb415fe4..4f97fb090b 100644 --- a/app/widgets/gimpchanneltreeview.c +++ b/app/widgets/gimpchanneltreeview.c @@ -105,7 +105,7 @@ gimp_channel_tree_view_class_init (GimpChannelTreeViewClass *klass) iv_class->set_image = gimp_channel_tree_view_set_image; iv_class->item_type = GIMP_TYPE_CHANNEL; - iv_class->signal_name = "active-channel-changed"; + iv_class->signal_name = "selected-channels-changed"; iv_class->get_container = gimp_image_get_channels; iv_class->get_active_item = (GimpGetItemFunc) gimp_image_get_active_channel; diff --git a/app/widgets/gimpvectorstreeview.c b/app/widgets/gimpvectorstreeview.c index d1e9fb6496..6b4d2eedfc 100644 --- a/app/widgets/gimpvectorstreeview.c +++ b/app/widgets/gimpvectorstreeview.c @@ -88,7 +88,7 @@ gimp_vectors_tree_view_class_init (GimpVectorsTreeViewClass *klass) view_class->drop_svg = gimp_vectors_tree_view_drop_svg; iv_class->item_type = GIMP_TYPE_VECTORS; - iv_class->signal_name = "active-vectors-changed"; + iv_class->signal_name = "selected-vectors-changed"; iv_class->get_container = gimp_image_get_vectors; iv_class->get_active_item = (GimpGetItemFunc) gimp_image_get_active_vectors; diff --git a/pdb/groups/image.pdb b/pdb/groups/image.pdb index bf94632432..9b5011aa94 100644 --- a/pdb/groups/image.pdb +++ b/pdb/groups/image.pdb @@ -387,7 +387,7 @@ HELP %invoke = ( code => <<'CODE' { - gimp_image_unset_active_channel (image); + gimp_image_unset_selected_channels (image); } CODE );