diff --git a/ChangeLog b/ChangeLog index 76a2450db3..de097e0854 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,52 @@ +2004-05-24 Michael Natterer + + Long overdue core container cleanup: + + * app/core/gimplist.[ch]: added "unique-names" and "sort-func" + properties and merged the resp. code from GimpDataList into + GimpList. Removed "policy" parameters from gimp_list_new() and + added "unique_names". Added new constructor gimp_list_new_weak(). + Made public function gimp_list_uniquefy_name() private. + + * app/core/Makefile.am + * app/core/core-types.h + * app/core/gimpdatalist.[ch]: removed. Its functionality is + entirely in GimpList now. + + * app/core/gimpdata.[ch]: added gimp_data_name_compare() which + used to live in GimpDataList. + + * app/core/gimp.c + * app/core/gimpdatafactory.c + * app/core/gimpimage.c + * app/core/gimptoolinfo.c + * app/core/gimpundostack.c + * app/paint/gimp-paint.c + * app/tools/gimp-tools.c + * app/widgets/gimpdevices.c + * app/widgets/gimptemplateeditor.c + * app/widgets/gimpundoeditor.c: changed list creation accordingly. + + Made gimp->templates, gimp->named_buffers, tool_info->presets and + the image's lists of layers, channels and vectors automatically + ensure unique names. + + * app/widgets/gimptemplateview.c + * app/actions/file-commands.c + * app/actions/templates-commands.c + * app/actions/tool-options-commands.c: removed calls to + gimp_list_uniquefy_name(). + + * app/core/gimpitem.c: removed major insanity where the items + themselves where ensuring their unique names. Bah! + + * app/core/gimplayer.c (gimp_layer_name_changed): chain up + conditionally. + + * app/core/gimplayermask.c (gimp_layer_mask_name_changed): removed + because there is no need any more to keep the parent + implementation from being invoked. + 2004-05-23 Sven Neumann More fixes for bug #142996: diff --git a/app/actions/file-commands.c b/app/actions/file-commands.c index 0de6d5697b..d48008aa3d 100644 --- a/app/actions/file-commands.c +++ b/app/actions/file-commands.c @@ -31,7 +31,6 @@ #include "core/gimp.h" #include "core/gimpcontainer.h" #include "core/gimpcontext.h" -#include "core/gimplist.h" #include "core/gimpimage.h" #include "core/gimptemplate.h" @@ -344,11 +343,7 @@ file_new_template_callback (GtkWidget *widget, template = gimp_template_new (name); gimp_template_set_from_image (template, gimage); - - gimp_list_uniquefy_name (GIMP_LIST (gimage->gimp->templates), - GIMP_OBJECT (template), TRUE); - gimp_container_add (gimage->gimp->templates, - GIMP_OBJECT (template)); + gimp_container_add (gimage->gimp->templates, GIMP_OBJECT (template)); g_object_unref (template); } diff --git a/app/actions/templates-commands.c b/app/actions/templates-commands.c index 71a5659474..5018d6d570 100644 --- a/app/actions/templates-commands.c +++ b/app/actions/templates-commands.c @@ -29,8 +29,8 @@ #include "config/gimpcoreconfig.h" #include "core/gimp.h" +#include "core/gimpcontainer.h" #include "core/gimpcontext.h" -#include "core/gimplist.h" #include "core/gimptemplate.h" #include "widgets/gimpcontainerview.h" @@ -111,8 +111,6 @@ templates_duplicate_template_cmd_callback (GtkAction *action, new_template = gimp_config_duplicate (GIMP_CONFIG (template)); - gimp_list_uniquefy_name (GIMP_LIST (container), - GIMP_OBJECT (new_template), TRUE); gimp_container_add (container, GIMP_OBJECT (new_template)); gimp_context_set_by_type (context, container->children_type, @@ -306,9 +304,6 @@ templates_edit_template_response (GtkWidget *widget, gimp_config_sync (GIMP_CONFIG (editor->template), GIMP_CONFIG (template), 0); - - gimp_list_uniquefy_name (GIMP_LIST (gimp->templates), - GIMP_OBJECT (template), TRUE); } gtk_widget_destroy (dialog); diff --git a/app/actions/tool-options-commands.c b/app/actions/tool-options-commands.c index 20d2c1c2a6..a2ecb164f5 100644 --- a/app/actions/tool-options-commands.c +++ b/app/actions/tool-options-commands.c @@ -241,8 +241,6 @@ tool_options_save_callback (GtkWidget *widget, copy = gimp_config_duplicate (GIMP_CONFIG (tool_info->tool_options)); gimp_object_set_name (GIMP_OBJECT (copy), name); - gimp_list_uniquefy_name (GIMP_LIST (tool_info->options_presets), - GIMP_OBJECT (copy), TRUE); gimp_container_insert (tool_info->options_presets, GIMP_OBJECT (copy), -1); g_object_unref (copy); @@ -259,6 +257,4 @@ tool_options_rename_callback (GtkWidget *widget, name = _("Saved Options"); gimp_object_set_name (GIMP_OBJECT (options), name); - gimp_list_uniquefy_name (GIMP_LIST (options->tool_info->options_presets), - GIMP_OBJECT (options), TRUE); } diff --git a/app/core/Makefile.am b/app/core/Makefile.am index 541c348437..f187c90ccd 100644 --- a/app/core/Makefile.am +++ b/app/core/Makefile.am @@ -65,8 +65,6 @@ libappcore_a_sources = \ gimpdata.h \ gimpdatafactory.c \ gimpdatafactory.h \ - gimpdatalist.c \ - gimpdatalist.h \ gimpdocumentlist.c \ gimpdocumentlist.h \ gimpdrawable.c \ diff --git a/app/core/core-types.h b/app/core/core-types.h index 675f3ce971..1af5108ede 100644 --- a/app/core/core-types.h +++ b/app/core/core-types.h @@ -58,7 +58,6 @@ typedef struct _GimpParasiteList GimpParasiteList; typedef struct _GimpContainer GimpContainer; typedef struct _GimpList GimpList; -typedef struct _GimpDataList GimpDataList; typedef struct _GimpDataFactory GimpDataFactory; diff --git a/app/core/gimp.c b/app/core/gimp.c index a9411471c1..b0aeb1dbd5 100644 --- a/app/core/gimp.c +++ b/app/core/gimp.c @@ -257,8 +257,7 @@ gimp_init (Gimp *gimp) gimp->plug_in_debug = NULL; - gimp->images = gimp_list_new (GIMP_TYPE_IMAGE, - GIMP_CONTAINER_POLICY_WEAK); + gimp->images = gimp_list_new_weak (GIMP_TYPE_IMAGE, FALSE); gimp_object_set_name (GIMP_OBJECT (gimp->images), "images"); gimp->next_image_ID = 1; @@ -268,15 +267,13 @@ gimp_init (Gimp *gimp) gimp->next_item_ID = 1; gimp->item_table = g_hash_table_new (g_direct_hash, NULL); - gimp->displays = gimp_list_new (GIMP_TYPE_OBJECT, - GIMP_CONTAINER_POLICY_WEAK); + gimp->displays = gimp_list_new_weak (GIMP_TYPE_OBJECT, FALSE); gimp_object_set_name (GIMP_OBJECT (gimp->displays), "displays"); gimp->next_display_ID = 1; gimp->global_buffer = NULL; - gimp->named_buffers = gimp_list_new (GIMP_TYPE_BUFFER, - GIMP_CONTAINER_POLICY_STRONG); + gimp->named_buffers = gimp_list_new (GIMP_TYPE_BUFFER, TRUE); gimp_object_set_name (GIMP_OBJECT (gimp->named_buffers), "named buffers"); gimp->fonts = NULL; @@ -292,16 +289,15 @@ gimp_init (Gimp *gimp) xcf_init (gimp); - gimp->tool_info_list = gimp_list_new (GIMP_TYPE_TOOL_INFO, - GIMP_CONTAINER_POLICY_STRONG); + gimp->tool_info_list = gimp_list_new (GIMP_TYPE_TOOL_INFO, FALSE); gimp_object_set_name (GIMP_OBJECT (gimp->tool_info_list), "tool infos"); gimp->standard_tool_info = NULL; gimp->documents = gimp_document_list_new (gimp); - gimp->templates = gimp_list_new (GIMP_TYPE_TEMPLATE, - GIMP_CONTAINER_POLICY_STRONG); + gimp->templates = gimp_list_new (GIMP_TYPE_TEMPLATE, TRUE); + gimp->image_new_last_template = NULL; gimp->have_current_cut_buffer = FALSE; diff --git a/app/core/gimpdata.c b/app/core/gimpdata.c index f14ff44075..93e811c62e 100644 --- a/app/core/gimpdata.c +++ b/app/core/gimpdata.c @@ -384,6 +384,18 @@ gimp_data_make_internal (GimpData *data) data->deletable = FALSE; } +gint +gimp_data_name_compare (GimpData *data1, + GimpData *data2) +{ + /* move the internal objects (like the FG -> BG) gradient) to the top */ + if (data1->internal != data2->internal) + return data1->internal ? -1 : 1; + + return gimp_object_name_collate ((GimpObject *) data1, + (GimpObject *) data2); +} + GQuark gimp_data_error_quark (void) { diff --git a/app/core/gimpdata.h b/app/core/gimpdata.h index 5de33a0146..a1ebf515ed 100644 --- a/app/core/gimpdata.h +++ b/app/core/gimpdata.h @@ -68,7 +68,7 @@ struct _GimpDataClass GError **error); gchar * (* get_extension) (GimpData *data); GimpData * (* duplicate) (GimpData *data, - gboolean stingy_memory_use); + gboolean stingy_memory_use); }; @@ -95,6 +95,8 @@ GimpData * gimp_data_duplicate (GimpData *data, void gimp_data_make_internal (GimpData *data); +gint gimp_data_name_compare (GimpData *data1, + GimpData *data2); #define GIMP_DATA_ERROR (gimp_data_error_quark ()) diff --git a/app/core/gimpdatafactory.c b/app/core/gimpdatafactory.c index 6acfdbb911..95d0049628 100644 --- a/app/core/gimpdatafactory.c +++ b/app/core/gimpdatafactory.c @@ -37,7 +37,7 @@ #include "gimpcontext.h" #include "gimpdata.h" #include "gimpdatafactory.h" -#include "gimpdatalist.h" +#include "gimplist.h" #include "gimp-intl.h" @@ -92,11 +92,8 @@ gimp_data_factory_get_type (void) static void gimp_data_factory_class_init (GimpDataFactoryClass *klass) { - GObjectClass *object_class; - GimpObjectClass *gimp_object_class; - - object_class = G_OBJECT_CLASS (klass); - gimp_object_class = GIMP_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); @@ -121,9 +118,7 @@ gimp_data_factory_init (GimpDataFactory *factory) static void gimp_data_factory_finalize (GObject *object) { - GimpDataFactory *factory; - - factory = GIMP_DATA_FACTORY (object); + GimpDataFactory *factory = GIMP_DATA_FACTORY (object); if (factory->container) { @@ -150,11 +145,9 @@ static gint64 gimp_data_factory_get_memsize (GimpObject *object, gint64 *gui_size) { - GimpDataFactory *factory; + GimpDataFactory *factory = GIMP_DATA_FACTORY (object); gint64 memsize = 0; - factory = GIMP_DATA_FACTORY (object); - memsize += gimp_object_get_memsize (GIMP_OBJECT (factory->container), gui_size); @@ -184,7 +177,9 @@ gimp_data_factory_new (Gimp *gimp, factory = g_object_new (GIMP_TYPE_DATA_FACTORY, NULL); factory->gimp = gimp; - factory->container = gimp_data_list_new (data_type); + factory->container = gimp_list_new (data_type, TRUE); + gimp_list_set_sort_func (GIMP_LIST (factory->container), + (GCompareFunc) gimp_data_name_compare); factory->path_property_name = g_strdup (path_property_name); factory->writable_property_name = g_strdup (writable_property_name); diff --git a/app/core/gimpdatalist.c b/app/core/gimpdatalist.c deleted file mode 100644 index 4e84f4c840..0000000000 --- a/app/core/gimpdatalist.c +++ /dev/null @@ -1,188 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * gimpdatalist.c - * Copyright (C) 2001 Michael Natterer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "core-types.h" - -#include "gimpdata.h" -#include "gimpdatalist.h" - - -static void gimp_data_list_class_init (GimpDataListClass *klass); -static void gimp_data_list_init (GimpDataList *list); - -static void gimp_data_list_add (GimpContainer *container, - GimpObject *object); -static void gimp_data_list_remove (GimpContainer *container, - GimpObject *object); - -static void gimp_data_list_object_renamed (GimpObject *object, - GimpDataList *data_list); -static gint gimp_data_list_data_compare_func (gconstpointer first, - gconstpointer second); - - -static GimpListClass *parent_class = NULL; - - -GType -gimp_data_list_get_type (void) -{ - static GType list_type = 0; - - if (! list_type) - { - static const GTypeInfo list_info = - { - sizeof (GimpDataListClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gimp_data_list_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GimpDataList), - 0, /* n_preallocs */ - (GInstanceInitFunc) gimp_data_list_init, - }; - - list_type = g_type_register_static (GIMP_TYPE_LIST, - "GimpDataList", - &list_info, 0); - } - - return list_type; -} - -static void -gimp_data_list_class_init (GimpDataListClass *klass) -{ - GimpContainerClass *container_class = GIMP_CONTAINER_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - container_class->add = gimp_data_list_add; - container_class->remove = gimp_data_list_remove; -} - -static void -gimp_data_list_init (GimpDataList *list) -{ -} - -static void -gimp_data_list_add (GimpContainer *container, - GimpObject *object) -{ - GimpList *list = GIMP_LIST (container); - - gimp_list_uniquefy_name (GIMP_LIST (container), object, TRUE); - - g_signal_connect (object, "name_changed", - G_CALLBACK (gimp_data_list_object_renamed), - container); - - list->list = g_list_insert_sorted (list->list, object, - gimp_data_list_data_compare_func); -} - -static void -gimp_data_list_remove (GimpContainer *container, - GimpObject *object) -{ - GimpList *list = GIMP_LIST (container); - - g_signal_handlers_disconnect_by_func (object, - gimp_data_list_object_renamed, - container); - - list->list = g_list_remove (list->list, object); -} - -GimpContainer * -gimp_data_list_new (GType children_type) -{ - GimpDataList *list; - - g_return_val_if_fail (g_type_is_a (children_type, GIMP_TYPE_DATA), NULL); - - list = g_object_new (GIMP_TYPE_DATA_LIST, - "children_type", children_type, - "policy", GIMP_CONTAINER_POLICY_STRONG, - NULL); - - return GIMP_CONTAINER (list); -} - -static void -gimp_data_list_object_renamed (GimpObject *object, - GimpDataList *data_list) -{ - GimpList *gimp_list = GIMP_LIST (data_list); - GList *list; - gint old_index; - gint new_index = 0; - - g_signal_handlers_block_by_func (object, - gimp_data_list_object_renamed, - data_list); - - gimp_list_uniquefy_name (gimp_list, object, TRUE); - - g_signal_handlers_unblock_by_func (object, - gimp_data_list_object_renamed, - data_list); - - old_index = g_list_index (gimp_list->list, object); - - for (list = gimp_list->list; list; list = g_list_next (list)) - { - GimpObject *object2 = GIMP_OBJECT (list->data); - - if (object == object2) - continue; - - if (gimp_data_list_data_compare_func (object, object2) > 0) - new_index++; - else - break; - } - - if (new_index != old_index) - gimp_container_reorder (GIMP_CONTAINER (data_list), object, new_index); -} - -static gint -gimp_data_list_data_compare_func (gconstpointer first, - gconstpointer second) -{ - GimpData *first_data = (GimpData *) first; - GimpData *second_data = (GimpData *) second; - - /* move the internal objects (like the FG -> BG) gradient) to the top */ - if (first_data->internal != second_data->internal) - return first_data->internal ? -1 : 1; - - return gimp_object_name_collate ((GimpObject *) first, - (GimpObject *) second); -} diff --git a/app/core/gimpdatalist.h b/app/core/gimpdatalist.h deleted file mode 100644 index e13f56b5a0..0000000000 --- a/app/core/gimpdatalist.h +++ /dev/null @@ -1,55 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * gimpdatalist.h - * Copyright (C) 2001 Michael Natterer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __GIMP_DATA_LIST_H__ -#define __GIMP_DATA_LIST_H__ - - -#include "gimplist.h" - - -#define GIMP_TYPE_DATA_LIST (gimp_data_list_get_type ()) -#define GIMP_DATA_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_DATA_LIST, GimpDataList)) -#define GIMP_DATA_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_DATA_LIST, GimpDataListClass)) -#define GIMP_IS_DATA_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_DATA_LIST)) -#define GIMP_IS_DATA_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_DATA_LIST)) -#define GIMP_DATA_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_DATA_LIST, GimpDataListClass)) - - -typedef struct _GimpDataListClass GimpDataListClass; - -struct _GimpDataList -{ - GimpList parent_instance; -}; - -struct _GimpDataListClass -{ - GimpListClass parent_class; -}; - - -GType gimp_data_list_get_type (void) G_GNUC_CONST; - -GimpContainer * gimp_data_list_new (GType children_type); - - -#endif /* __GIMP_DATA_LIST_H__ */ diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c index 3efb51b733..013b9989da 100644 --- a/app/core/gimpimage.c +++ b/app/core/gimpimage.c @@ -492,12 +492,9 @@ gimp_image_init (GimpImage *gimage) gimage->grid = NULL; - gimage->layers = gimp_list_new (GIMP_TYPE_LAYER, - GIMP_CONTAINER_POLICY_STRONG); - gimage->channels = gimp_list_new (GIMP_TYPE_CHANNEL, - GIMP_CONTAINER_POLICY_STRONG); - gimage->vectors = gimp_list_new (GIMP_TYPE_VECTORS, - GIMP_CONTAINER_POLICY_STRONG); + gimage->layers = gimp_list_new (GIMP_TYPE_LAYER, TRUE); + gimage->channels = gimp_list_new (GIMP_TYPE_CHANNEL, TRUE); + gimage->vectors = gimp_list_new (GIMP_TYPE_VECTORS, TRUE); gimage->layer_stack = NULL; gimage->layer_update_handler = diff --git a/app/core/gimpitem.c b/app/core/gimpitem.c index be7d00e104..d362ad3451 100644 --- a/app/core/gimpitem.c +++ b/app/core/gimpitem.c @@ -29,21 +29,18 @@ #include "gimp.h" #include "gimp-parasites.h" -#include "gimpchannel.h" +#include "gimpdrawable.h" #include "gimpimage.h" #include "gimpimage-undo.h" #include "gimpimage-undo-push.h" #include "gimpitem.h" #include "gimpitem-preview.h" -#include "gimplayer.h" #include "gimplist.h" #include "gimpmarshal.h" #include "gimppaintinfo.h" #include "gimpparasitelist.h" #include "gimpstrokeoptions.h" -#include "vectors/gimpvectors.h" - #include "gimp-intl.h" @@ -63,7 +60,6 @@ static void gimp_item_init (GimpItem *item); static void gimp_item_finalize (GObject *object); -static void gimp_item_name_changed (GimpObject *object); static gint64 gimp_item_get_memsize (GimpObject *object, gint64 *gui_size); @@ -174,7 +170,6 @@ gimp_item_class_init (GimpItemClass *klass) object_class->finalize = gimp_item_finalize; - gimp_object_class->name_changed = gimp_item_name_changed; gimp_object_class->get_memsize = gimp_item_get_memsize; viewable_class->get_preview_size = gimp_item_get_preview_size; @@ -244,27 +239,6 @@ gimp_item_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } -static void -gimp_item_name_changed (GimpObject *object) -{ - GimpItem *item = GIMP_ITEM (object); - GimpList *list = NULL; - - /* if no other items to check name against */ - if (item->gimage == NULL) - return; - - if (GIMP_IS_LAYER (item)) - list = GIMP_LIST (item->gimage->layers); - else if (GIMP_IS_CHANNEL (item)) - list = GIMP_LIST (item->gimage->channels); - else if (GIMP_IS_VECTORS (item)) - list = GIMP_LIST (item->gimage->vectors); - - if (list) - gimp_list_uniquefy_name (list, object, FALSE); -} - static gint64 gimp_item_get_memsize (GimpObject *object, gint64 *gui_size) @@ -505,12 +479,7 @@ gimp_item_convert (GimpItem *item, new_type, add_alpha); if (dest_image != item->gimage) - { - gimp_item_set_image (new_item, dest_image); - - /* force a unique name */ - gimp_object_name_changed (GIMP_OBJECT (new_item)); - } + gimp_item_set_image (new_item, dest_image); return new_item; } diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c index 2629813aa2..1a158c3e95 100644 --- a/app/core/gimplayer.c +++ b/app/core/gimplayer.c @@ -331,7 +331,8 @@ gimp_layer_name_changed (GimpObject *object) { GimpLayer *layer = GIMP_LAYER (object); - GIMP_OBJECT_CLASS (parent_class)->name_changed (object); + if (GIMP_OBJECT_CLASS (parent_class)->name_changed) + GIMP_OBJECT_CLASS (parent_class)->name_changed (object); if (layer->mask) { diff --git a/app/core/gimplayermask.c b/app/core/gimplayermask.c index d4e3f6e923..74be69c4f6 100644 --- a/app/core/gimplayermask.c +++ b/app/core/gimplayermask.c @@ -47,8 +47,6 @@ enum static void gimp_layer_mask_class_init (GimpLayerMaskClass *klass); static void gimp_layer_mask_init (GimpLayerMask *layer_mask); -static void gimp_layer_mask_name_changed (GimpObject *object); - static gboolean gimp_layer_mask_is_attached (GimpItem *item); static GimpItem * gimp_layer_mask_duplicate (GimpItem *item, GType new_type, @@ -94,9 +92,8 @@ gimp_layer_mask_get_type (void) static void gimp_layer_mask_class_init (GimpLayerMaskClass *klass) { - GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass); - GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass); - GimpItemClass *item_class = GIMP_ITEM_CLASS (klass); + GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass); + GimpItemClass *item_class = GIMP_ITEM_CLASS (klass); parent_class = g_type_class_peek_parent (klass); @@ -127,8 +124,6 @@ gimp_layer_mask_class_init (GimpLayerMaskClass *klass) gimp_marshal_VOID__VOID, G_TYPE_NONE, 0); - gimp_object_class->name_changed = gimp_layer_mask_name_changed; - viewable_class->default_stock_id = "gimp-layer-mask"; item_class->is_attached = gimp_layer_mask_is_attached; @@ -146,12 +141,6 @@ gimp_layer_mask_init (GimpLayerMask *layer_mask) layer_mask->show_mask = FALSE; } -static void -gimp_layer_mask_name_changed (GimpObject *object) -{ - /* skip unique name logic by not chaining up */ -} - static gboolean gimp_layer_mask_is_attached (GimpItem *item) { diff --git a/app/core/gimplist.c b/app/core/gimplist.c index 9585c0e59b..8dc45d9c4a 100644 --- a/app/core/gimplist.c +++ b/app/core/gimplist.c @@ -31,9 +31,26 @@ #include "gimplist.h" +enum +{ + PROP_0, + PROP_UNIQUE_NAMES, + PROP_SORT_FUNC +}; + + static void gimp_list_class_init (GimpListClass *klass); static void gimp_list_init (GimpList *list); +static void gimp_list_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_list_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + static gint64 gimp_list_get_memsize (GimpObject *object, gint64 *gui_size); @@ -57,6 +74,11 @@ static GimpObject * gimp_list_get_child_by_index (const GimpContainer *container static gint gimp_list_get_child_index (const GimpContainer *container, const GimpObject *object); +static void gimp_list_uniquefy_name (GimpList *gimp_list, + GimpObject *object); +static void gimp_list_object_renamed (GimpObject *object, + GimpList *list); + static GimpContainerClass *parent_class = NULL; @@ -92,11 +114,15 @@ gimp_list_get_type (void) static void gimp_list_class_init (GimpListClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS (klass); GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass); GimpContainerClass *container_class = GIMP_CONTAINER_CLASS (klass); parent_class = g_type_class_peek_parent (klass); + object_class->set_property = gimp_list_set_property; + object_class->get_property = gimp_list_get_property; + gimp_object_class->get_memsize = gimp_list_get_memsize; container_class->add = gimp_list_add; @@ -108,12 +134,71 @@ gimp_list_class_init (GimpListClass *klass) container_class->get_child_by_name = gimp_list_get_child_by_name; container_class->get_child_by_index = gimp_list_get_child_by_index; container_class->get_child_index = gimp_list_get_child_index; + + g_object_class_install_property (object_class, PROP_UNIQUE_NAMES, + g_param_spec_boolean ("unique-names", + NULL, NULL, + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_SORT_FUNC, + g_param_spec_pointer ("sort-func", + NULL, NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); } static void gimp_list_init (GimpList *list) { - list->list = NULL; + list->list = NULL; + list->unique_names = FALSE; + list->sort_func = NULL; +} + +static void +gimp_list_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpList *list = GIMP_LIST (object); + + switch (property_id) + { + case PROP_UNIQUE_NAMES: + list->unique_names = g_value_get_boolean (value); + break; + case PROP_SORT_FUNC: + gimp_list_set_sort_func (list, g_value_get_pointer (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_list_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpList *list = GIMP_LIST (object); + + switch (property_id) + { + case PROP_UNIQUE_NAMES: + g_value_set_boolean (value, list->unique_names); + break; + case PROP_SORT_FUNC: + g_value_set_pointer (value, list->sort_func); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } } static gint64 @@ -145,7 +230,18 @@ gimp_list_add (GimpContainer *container, { GimpList *list = GIMP_LIST (container); - list->list = g_list_prepend (list->list, object); + if (list->unique_names) + gimp_list_uniquefy_name (list, object); + + if (list->unique_names || list->sort_func) + g_signal_connect (object, "name-changed", + G_CALLBACK (gimp_list_object_renamed), + list); + + if (list->sort_func) + list->list = g_list_insert_sorted (list->list, object, list->sort_func); + else + list->list = g_list_prepend (list->list, object); } static void @@ -154,6 +250,11 @@ gimp_list_remove (GimpContainer *container, { GimpList *list = GIMP_LIST (container); + if (list->unique_names || list->sort_func) + g_signal_handlers_disconnect_by_func (object, + gimp_list_object_renamed, + list); + list->list = g_list_remove (list->list, object); } @@ -245,27 +346,60 @@ gimp_list_get_child_index (const GimpContainer *container, /** * gimp_list_new: * @children_type: the #GType of objects the list is going to hold - * @policy: the #GimpContainerPolicy for the new list + * @unique_names: if the list should ensure that all its children + * have unique names. * * Creates a new #GimpList object. Since #GimpList is a #GimpContainer * implementation, it holds GimpObjects. Thus @children_type must be * GIMP_TYPE_OBJECT or a type derived from it. * + * The returned list has the #GIMP_CONTAINER_POLICY_STRONG. + * * Return value: a new #GimpList object **/ GimpContainer * -gimp_list_new (GType children_type, - GimpContainerPolicy policy) +gimp_list_new (GType children_type, + gboolean unique_names) { GimpList *list; g_return_val_if_fail (g_type_is_a (children_type, GIMP_TYPE_OBJECT), NULL); - g_return_val_if_fail (policy == GIMP_CONTAINER_POLICY_STRONG || - policy == GIMP_CONTAINER_POLICY_WEAK, NULL); list = g_object_new (GIMP_TYPE_LIST, "children_type", children_type, - "policy", policy, + "policy", GIMP_CONTAINER_POLICY_STRONG, + "unique-names", unique_names ? TRUE : FALSE, + NULL); + + return GIMP_CONTAINER (list); +} + +/** + * gimp_list_new_weak: + * @children_type: the #GType of objects the list is going to hold + * @unique_names: if the list should ensure that all its children + * have unique names. + * + * Creates a new #GimpList object. Since #GimpList is a #GimpContainer + * implementation, it holds GimpObjects. Thus @children_type must be + * GIMP_TYPE_OBJECT or a type derived from it. + * + * The returned list has the #GIMP_CONTAINER_POLICY_WEAK. + * + * Return value: a new #GimpList object + **/ +GimpContainer * +gimp_list_new_weak (GType children_type, + gboolean unique_names) +{ + GimpList *list; + + g_return_val_if_fail (g_type_is_a (children_type, GIMP_TYPE_OBJECT), NULL); + + list = g_object_new (GIMP_TYPE_LIST, + "children_type", children_type, + "policy", GIMP_CONTAINER_POLICY_WEAK, + "unique-names", unique_names ? TRUE : FALSE, NULL); return GIMP_CONTAINER (list); @@ -290,25 +424,50 @@ gimp_list_reverse (GimpList *list) } } +/** + * gimp_list_set_sort_func: + * @list: a #GimpList + * @sort_func: a #GCompareFunc + * + * Sorts the elements of @list using gimp_list_sort() and remembers the + * passed @sort_func in order to keep the list ordered across inserting + * or renaming children. + **/ +void +gimp_list_set_sort_func (GimpList *list, + GCompareFunc sort_func) +{ + g_return_if_fail (GIMP_IS_LIST (list)); + + if (sort_func != list->sort_func) + { + if (sort_func) + gimp_list_sort (list, sort_func); + + list->sort_func = sort_func; + g_object_notify (G_OBJECT (list), "sort-func"); + } +} + /** * gimp_list_sort: * @list: a #GimpList - * @compare_func: a #GCompareFunc + * @sort_func: a #GCompareFunc * - * Sorts the elements of a #GimpList according to the given @compare_func. + * Sorts the elements of a #GimpList according to the given @sort_func. * See g_list_sort() for a detailed description of this function. **/ void gimp_list_sort (GimpList *list, - GCompareFunc compare_func) + GCompareFunc sort_func) { g_return_if_fail (GIMP_IS_LIST (list)); - g_return_if_fail (compare_func != NULL); + g_return_if_fail (sort_func != NULL); if (GIMP_CONTAINER (list)->num_children > 1) { gimp_container_freeze (GIMP_CONTAINER (list)); - list->list = g_list_sort (list->list, compare_func); + list->list = g_list_sort (list->list, sort_func); gimp_container_thaw (GIMP_CONTAINER (list)); } } @@ -327,23 +486,12 @@ gimp_list_sort_by_name (GimpList *list) gimp_list_sort (list, (GCompareFunc) gimp_object_name_collate); } -/** - * gimp_list_uniquefy_name: - * @gimp_list: a #GimpList - * @object: a #GimpObject - * @notify: whether to notify listeners about the name change - * - * This function ensures that @object has a name that isn't already - * used by another object in @gimp_list. If the name of @object needs - * to be changed, the value of @notify decides if the "name_changed" - * signal should be emitted or if the name should be changed silently. - * The latter might be useful under certain circumstances in order to - * avoid recursion. - **/ -void + +/* private functions */ + +static void gimp_list_uniquefy_name (GimpList *gimp_list, - GimpObject *object, - gboolean notify) + GimpObject *object) { GList *list; GList *list2; @@ -410,18 +558,52 @@ gimp_list_uniquefy_name (GimpList *gimp_list, } while (list2); - if (notify) - { - gimp_object_set_name (object, new_name); - g_free (new_name); - } - else - { - gimp_object_name_free (object); - object->name = new_name; - } - + gimp_object_set_name (object, new_name); + g_free (new_name); break; } } } + +static void +gimp_list_object_renamed (GimpObject *object, + GimpList *list) +{ + if (list->unique_names) + { + g_signal_handlers_block_by_func (object, + gimp_list_object_renamed, + list); + + gimp_list_uniquefy_name (list, object); + + g_signal_handlers_unblock_by_func (object, + gimp_list_object_renamed, + list); + } + + if (list->sort_func) + { + GList *glist; + gint old_index; + gint new_index = 0; + + old_index = g_list_index (list->list, object); + + for (glist = list->list; glist; glist = g_list_next (glist)) + { + GimpObject *object2 = GIMP_OBJECT (glist->data); + + if (object == object2) + continue; + + if (list->sort_func (object, object2) > 0) + new_index++; + else + break; + } + + if (new_index != old_index) + gimp_container_reorder (GIMP_CONTAINER (list), object, new_index); + } +} diff --git a/app/core/gimplist.h b/app/core/gimplist.h index 72bbe685f1..596413978d 100644 --- a/app/core/gimplist.h +++ b/app/core/gimplist.h @@ -41,6 +41,8 @@ struct _GimpList GimpContainer parent_instance; GList *list; + gboolean unique_names; + GCompareFunc sort_func; }; struct _GimpListClass @@ -52,14 +54,16 @@ struct _GimpListClass GType gimp_list_get_type (void) G_GNUC_CONST; GimpContainer * gimp_list_new (GType children_type, - GimpContainerPolicy policy); + gboolean unique_names); +GimpContainer * gimp_list_new_weak (GType children_type, + gboolean unique_names); + void gimp_list_reverse (GimpList *list); +void gimp_list_set_sort_func (GimpList *list, + GCompareFunc sort_func); void gimp_list_sort (GimpList *list, - GCompareFunc compare_func); + GCompareFunc sort_func); void gimp_list_sort_by_name (GimpList *list); -void gimp_list_uniquefy_name (GimpList *gimp_list, - GimpObject *object, - gboolean notify); #endif /* __GIMP_LIST_H__ */ diff --git a/app/core/gimptoolinfo.c b/app/core/gimptoolinfo.c index 0ccc4a03c0..a5a0b4dfd4 100644 --- a/app/core/gimptoolinfo.c +++ b/app/core/gimptoolinfo.c @@ -306,7 +306,7 @@ gimp_tool_info_new (Gimp *gimp, if (tool_info->tool_options_type != GIMP_TYPE_TOOL_OPTIONS) { tool_info->options_presets = gimp_list_new (tool_info->tool_options_type, - GIMP_CONTAINER_POLICY_STRONG); + TRUE); } return tool_info; diff --git a/app/core/gimpundostack.c b/app/core/gimpundostack.c index 35ecffbd50..59bd69cae4 100644 --- a/app/core/gimpundostack.c +++ b/app/core/gimpundostack.c @@ -56,19 +56,19 @@ gimp_undo_stack_get_type (void) static const GTypeInfo undo_stack_info = { sizeof (GimpUndoStackClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gimp_undo_stack_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GimpUndoStack), - 0, /* n_preallocs */ - (GInstanceInitFunc) gimp_undo_stack_init, + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gimp_undo_stack_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GimpUndoStack), + 0, /* n_preallocs */ + (GInstanceInitFunc) gimp_undo_stack_init, }; undo_stack_type = g_type_register_static (GIMP_TYPE_UNDO, - "GimpUndoStack", - &undo_stack_info, 0); + "GimpUndoStack", + &undo_stack_info, 0); } return undo_stack_type; @@ -77,13 +77,9 @@ gimp_undo_stack_get_type (void) static void gimp_undo_stack_class_init (GimpUndoStackClass *klass) { - GObjectClass *object_class; - GimpObjectClass *gimp_object_class; - GimpUndoClass *undo_class; - - object_class = G_OBJECT_CLASS (klass); - gimp_object_class = GIMP_OBJECT_CLASS (klass); - undo_class = GIMP_UNDO_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass); + GimpUndoClass *undo_class = GIMP_UNDO_CLASS (klass); parent_class = g_type_class_peek_parent (klass); @@ -98,16 +94,13 @@ gimp_undo_stack_class_init (GimpUndoStackClass *klass) static void gimp_undo_stack_init (GimpUndoStack *stack) { - stack->undos = gimp_list_new (GIMP_TYPE_UNDO, - GIMP_CONTAINER_POLICY_STRONG); + stack->undos = gimp_list_new (GIMP_TYPE_UNDO, FALSE); } static void gimp_undo_stack_finalize (GObject *object) { - GimpUndoStack *stack; - - stack = GIMP_UNDO_STACK (object); + GimpUndoStack *stack = GIMP_UNDO_STACK (object); if (stack->undos) { @@ -122,11 +115,9 @@ static gint64 gimp_undo_stack_get_memsize (GimpObject *object, gint64 *gui_size) { - GimpUndoStack *stack; + GimpUndoStack *stack = GIMP_UNDO_STACK (object); gint64 memsize = 0; - stack = GIMP_UNDO_STACK (object); - if (stack->undos) memsize += gimp_object_get_memsize (GIMP_OBJECT (stack->undos), gui_size); @@ -139,18 +130,14 @@ gimp_undo_stack_pop (GimpUndo *undo, GimpUndoMode undo_mode, GimpUndoAccumulator *accum) { - GimpUndoStack *stack; + GimpUndoStack *stack = GIMP_UNDO_STACK (undo); GList *list; - stack = GIMP_UNDO_STACK (undo); - for (list = GIMP_LIST (stack->undos)->list; list; list = g_list_next (list)) { - GimpUndo *child; - - child = GIMP_UNDO (list->data); + GimpUndo *child = list->data; gimp_undo_pop (child, undo_mode, accum); } @@ -160,18 +147,14 @@ static void gimp_undo_stack_free (GimpUndo *undo, GimpUndoMode undo_mode) { - GimpUndoStack *stack; + GimpUndoStack *stack = GIMP_UNDO_STACK (undo); GList *list; - stack = GIMP_UNDO_STACK (undo); - for (list = GIMP_LIST (stack->undos)->list; list; list = g_list_next (list)) { - GimpUndo *child; - - child = GIMP_UNDO (list->data); + GimpUndo *child = list->data; gimp_undo_free (child, undo_mode); g_object_unref (child); @@ -179,7 +162,7 @@ gimp_undo_stack_free (GimpUndo *undo, while (GIMP_LIST (stack->undos)->list) gimp_container_remove (GIMP_CONTAINER (stack->undos), - GIMP_OBJECT (GIMP_LIST (stack->undos)->list->data)); + GIMP_LIST (stack->undos)->list->data); } GimpUndoStack * diff --git a/app/paint/gimp-paint.c b/app/paint/gimp-paint.c index 3b812cc15c..141ab0d9f1 100644 --- a/app/paint/gimp-paint.c +++ b/app/paint/gimp-paint.c @@ -66,8 +66,7 @@ gimp_paint_init (Gimp *gimp) g_return_if_fail (GIMP_IS_GIMP (gimp)); - gimp->paint_info_list = gimp_list_new (GIMP_TYPE_PAINT_INFO, - GIMP_CONTAINER_POLICY_STRONG); + gimp->paint_info_list = gimp_list_new (GIMP_TYPE_PAINT_INFO, FALSE); gimp_object_set_name (GIMP_OBJECT (gimp->paint_info_list), "paint infos"); for (i = 0; i < G_N_ELEMENTS (register_funcs); i++) diff --git a/app/tools/gimp-tools.c b/app/tools/gimp-tools.c index 3bee9ea1ea..e1f483a30a 100644 --- a/app/tools/gimp-tools.c +++ b/app/tools/gimp-tools.c @@ -215,7 +215,8 @@ gimp_tools_restore (Gimp *gimp) g_return_if_fail (GIMP_IS_GIMP (gimp)); - gimp_list = gimp_list_new (GIMP_TYPE_TOOL_INFO, GIMP_CONTAINER_POLICY_STRONG); + gimp_list = gimp_list_new (GIMP_TYPE_TOOL_INFO, FALSE); + filename = gimp_personal_rc_file ("toolrc"); if (gimp_config_deserialize_file (GIMP_CONFIG (gimp_list), filename, diff --git a/app/widgets/gimpdevices.c b/app/widgets/gimpdevices.c index eafb5ea08f..d4100c5023 100644 --- a/app/widgets/gimpdevices.c +++ b/app/widgets/gimpdevices.c @@ -79,8 +79,7 @@ gimp_devices_init (Gimp *gimp, display = gdk_display_get_default (); - manager->device_info_list = gimp_list_new (GIMP_TYPE_DEVICE_INFO, - GIMP_CONTAINER_POLICY_STRONG); + manager->device_info_list = gimp_list_new (GIMP_TYPE_DEVICE_INFO, FALSE); manager->current_device = gdk_display_get_core_pointer (display); manager->change_notify = change_notify; diff --git a/app/widgets/gimptemplateeditor.c b/app/widgets/gimptemplateeditor.c index f81c0fa54f..ffcd992a59 100644 --- a/app/widgets/gimptemplateeditor.c +++ b/app/widgets/gimptemplateeditor.c @@ -490,8 +490,7 @@ gimp_template_editor_new (GimpTemplate *template, stock_id = gimp_viewable_get_stock_id (GIMP_VIEWABLE (editor->template)); - editor->stock_id_container = gimp_list_new (GIMP_TYPE_TEMPLATE, - GIMP_CONTAINER_POLICY_STRONG); + editor->stock_id_container = gimp_list_new (GIMP_TYPE_TEMPLATE, FALSE); editor->stock_id_context = gimp_context_new (gimp, "foo", NULL); g_signal_connect (editor->stock_id_context, "template_changed", diff --git a/app/widgets/gimptemplateview.c b/app/widgets/gimptemplateview.c index 7561eab260..0344132747 100644 --- a/app/widgets/gimptemplateview.c +++ b/app/widgets/gimptemplateview.c @@ -34,7 +34,6 @@ #include "core/gimp.h" #include "core/gimpcontainer.h" #include "core/gimpcontext.h" -#include "core/gimplist.h" #include "core/gimpimage.h" #include "core/gimptemplate.h" @@ -245,7 +244,6 @@ gimp_template_view_tree_name_edited (GtkCellRendererText *cell, object = GIMP_OBJECT (renderer->viewable); gimp_object_set_name (object, new_name); - gimp_list_uniquefy_name (GIMP_LIST (container), object, TRUE); g_object_unref (renderer); } diff --git a/app/widgets/gimpundoeditor.c b/app/widgets/gimpundoeditor.c index 29440f3e75..f455bee83c 100644 --- a/app/widgets/gimpundoeditor.c +++ b/app/widgets/gimpundoeditor.c @@ -248,10 +248,8 @@ gimp_undo_editor_fill (GimpUndoEditor *editor) gimage = GIMP_IMAGE_EDITOR (editor)->gimage; /* create a container as model for the undo history list */ - editor->container = gimp_list_new (GIMP_TYPE_UNDO, - GIMP_CONTAINER_POLICY_STRONG); - editor->base_item = gimp_undo_new (gimage, - GIMP_UNDO_GROUP_NONE, + editor->container = gimp_list_new (GIMP_TYPE_UNDO, FALSE); + editor->base_item = gimp_undo_new (gimage, GIMP_UNDO_GROUP_NONE, _("[ Base Image ]"), NULL, 0, FALSE, NULL, NULL);