diff --git a/app/core/Makefile.am b/app/core/Makefile.am index 5d792e9a02..ff31b8c126 100644 --- a/app/core/Makefile.am +++ b/app/core/Makefile.am @@ -346,6 +346,8 @@ libappcore_a_sources = \ gimptooloptions.h \ gimptoolpresets.c \ gimptoolpresets.h \ + gimptreehandler.c \ + gimptreehandler.h \ gimpunit.c \ gimpunit.h \ gimpundo.c \ diff --git a/app/core/core-types.h b/app/core/core-types.h index dce9853a77..5014f28c75 100644 --- a/app/core/core-types.h +++ b/app/core/core-types.h @@ -151,6 +151,7 @@ typedef struct _GimpPdbProgress GimpPdbProgress; typedef struct _GimpProjection GimpProjection; typedef struct _GimpSubProgress GimpSubProgress; typedef struct _GimpTag GimpTag; +typedef struct _GimpTreeHandler GimpTreeHandler; /* interfaces */ diff --git a/app/core/gimptreehandler.c b/app/core/gimptreehandler.c new file mode 100644 index 0000000000..1e41b35e60 --- /dev/null +++ b/app/core/gimptreehandler.c @@ -0,0 +1,240 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * GimpTreeHandler + * Copyright (C) 2009 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 3 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, see . + */ + +#include "config.h" + +#include + +#include "core-types.h" + +#include "gimpcontainer.h" +#include "gimptreehandler.h" +#include "gimpviewable.h" + + +static void gimp_tree_handler_dispose (GObject *object); + +static void gimp_tree_handler_freeze (GimpTreeHandler *handler, + GimpContainer *container); +static void gimp_tree_handler_thaw (GimpTreeHandler *handler, + GimpContainer *container); + +static void gimp_tree_handler_add_container (GimpTreeHandler *handler, + GimpContainer *container); +static void gimp_tree_handler_add_foreach (GimpViewable *viewable, + GimpTreeHandler *handler); +static void gimp_tree_handler_add (GimpTreeHandler *handler, + GimpViewable *viewable, + GimpContainer *container); + +static void gimp_tree_handler_remove_container (GimpTreeHandler *handler, + GimpContainer *container); +static void gimp_tree_handler_remove_foreach (GimpViewable *viewable, + GimpTreeHandler *handler); +static void gimp_tree_handler_remove (GimpTreeHandler *handler, + GimpViewable *viewable, + GimpContainer *container); + + +G_DEFINE_TYPE (GimpTreeHandler, gimp_tree_handler, GIMP_TYPE_OBJECT) + +#define parent_class gimp_tree_handler_parent_class + + +static void +gimp_tree_handler_class_init (GimpTreeHandlerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = gimp_tree_handler_dispose; +} + +static void +gimp_tree_handler_init (GimpTreeHandler *handler) +{ +} + +static void +gimp_tree_handler_dispose (GObject *object) +{ + GimpTreeHandler *handler = GIMP_TREE_HANDLER (object); + + if (handler->container) + { + g_signal_handlers_disconnect_by_func (handler->container, + gimp_tree_handler_freeze, + handler); + g_signal_handlers_disconnect_by_func (handler->container, + gimp_tree_handler_thaw, + handler); + + if (! gimp_container_frozen (handler->container)) + gimp_tree_handler_remove_container (handler, handler->container); + + g_object_unref (handler->container); + handler->container = NULL; + + g_free (handler->signal_name); + handler->signal_name = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + + +/* public functions */ + +GimpTreeHandler * +gimp_tree_handler_connect (GimpContainer *container, + const gchar *signal_name, + GCallback callback, + gpointer user_data) +{ + GimpTreeHandler *handler; + + g_return_val_if_fail (GIMP_IS_CONTAINER (container), NULL); + g_return_val_if_fail (signal_name != NULL, NULL); + + handler = g_object_new (GIMP_TYPE_TREE_HANDLER, NULL); + + handler->container = g_object_ref (container); + handler->signal_name = g_strdup (signal_name); + handler->callback = callback; + handler->user_data = user_data; + + if (! gimp_container_frozen (container)) + gimp_tree_handler_add_container (handler, container); + + g_signal_connect_object (container, "freeze", + G_CALLBACK (gimp_tree_handler_freeze), + handler, + G_CONNECT_SWAPPED); + g_signal_connect_object (container, "thaw", + G_CALLBACK (gimp_tree_handler_thaw), + handler, + G_CONNECT_SWAPPED); + + return handler; +} + +void +gimp_tree_handler_disconnect (GimpTreeHandler *handler) +{ + g_return_if_fail (GIMP_IS_TREE_HANDLER (handler)); + + g_object_run_dispose (G_OBJECT (handler)); + g_object_unref (handler); +} + + +/* private functions */ + +static void +gimp_tree_handler_freeze (GimpTreeHandler *handler, + GimpContainer *container) +{ + gimp_tree_handler_remove_container (handler, container); +} + +static void +gimp_tree_handler_thaw (GimpTreeHandler *handler, + GimpContainer *container) +{ + gimp_tree_handler_add_container (handler, container); +} + +static void +gimp_tree_handler_add_container (GimpTreeHandler *handler, + GimpContainer *container) +{ + gimp_container_foreach (container, + (GFunc) gimp_tree_handler_add_foreach, + handler); + + g_signal_connect_object (container, "add", + G_CALLBACK (gimp_tree_handler_add), + handler, + G_CONNECT_SWAPPED); + g_signal_connect_object (container, "remove", + G_CALLBACK (gimp_tree_handler_remove), + handler, + G_CONNECT_SWAPPED); +} + +static void +gimp_tree_handler_add_foreach (GimpViewable *viewable, + GimpTreeHandler *handler) +{ + gimp_tree_handler_add (handler, viewable, NULL); +} + +static void +gimp_tree_handler_add (GimpTreeHandler *handler, + GimpViewable *viewable, + GimpContainer *unused) +{ + GimpContainer *children = gimp_viewable_get_children (viewable); + + g_signal_connect (viewable, + handler->signal_name, + handler->callback, + handler->user_data); + + if (children) + gimp_tree_handler_add_container (handler, children); +} + +static void +gimp_tree_handler_remove_container (GimpTreeHandler *handler, + GimpContainer *container) +{ + g_signal_handlers_disconnect_by_func (container, + gimp_tree_handler_add, + handler); + g_signal_handlers_disconnect_by_func (container, + gimp_tree_handler_remove, + handler); + + gimp_container_foreach (container, + (GFunc) gimp_tree_handler_remove_foreach, + handler); +} + +static void +gimp_tree_handler_remove_foreach (GimpViewable *viewable, + GimpTreeHandler *handler) +{ + gimp_tree_handler_remove (handler, viewable, NULL); +} + +static void +gimp_tree_handler_remove (GimpTreeHandler *handler, + GimpViewable *viewable, + GimpContainer *unused) +{ + GimpContainer *children = gimp_viewable_get_children (viewable); + + if (children) + gimp_tree_handler_remove_container (handler, children); + + g_signal_handlers_disconnect_by_func (viewable, + handler->callback, + handler->user_data); +} diff --git a/app/core/gimptreehandler.h b/app/core/gimptreehandler.h new file mode 100644 index 0000000000..7e6c9750b2 --- /dev/null +++ b/app/core/gimptreehandler.h @@ -0,0 +1,64 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * GimpTreeHandler + * Copyright (C) 2009 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 3 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, see . + */ + +#ifndef __GIMP_TREE_HANDLER_H__ +#define __GIMP_TREE_HANDLER_H__ + + +#include "core/gimpobject.h" + + +#define GIMP_TYPE_TREE_HANDLER (gimp_tree_handler_get_type ()) +#define GIMP_TREE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_TREE_HANDLER, GimpTreeHandler)) +#define GIMP_TREE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_TREE_HANDLER, GimpTreeHandlerClass)) +#define GIMP_IS_TREE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_TREE_HANDLER)) +#define GIMP_IS_TREE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_TREE_HANDLER)) +#define GIMP_TREE_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_TREE_HANDLER, GimpTreeHandlerClass)) + + +typedef struct _GimpTreeHandlerClass GimpTreeHandlerClass; + +struct _GimpTreeHandler +{ + GimpObject parent_instance; + + GimpContainer *container; + + gchar *signal_name; + GCallback callback; + gpointer user_data; +}; + +struct _GimpTreeHandlerClass +{ + GimpObjectClass parent_class; +}; + + +GType gimp_tree_handler_get_type (void) G_GNUC_CONST; + +GimpTreeHandler * gimp_tree_handler_connect (GimpContainer *container, + const gchar *signal_name, + GCallback callback, + gpointer user_data); +void gimp_tree_handler_disconnect (GimpTreeHandler *handler); + + +#endif /* __GIMP_TREE_HANDLER_H__ */