diff options
Diffstat (limited to '')
-rw-r--r-- | app/widgets/gimpdockcolumns.c | 490 |
1 files changed, 490 insertions, 0 deletions
diff --git a/app/widgets/gimpdockcolumns.c b/app/widgets/gimpdockcolumns.c new file mode 100644 index 0000000..c113c4b --- /dev/null +++ b/app/widgets/gimpdockcolumns.c @@ -0,0 +1,490 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpdockcolumns.c + * Copyright (C) 2009 Martin Nordholts <martinn@src.gnome.org> + * + * 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 <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <gegl.h> +#include <gtk/gtk.h> + +#include "widgets-types.h" + +#include "core/gimp.h" +#include "core/gimpcontext.h" +#include "core/gimpmarshal.h" + +#include "gimpdialogfactory.h" +#include "gimpdock.h" +#include "gimpdockable.h" +#include "gimpdockbook.h" +#include "gimpdockcolumns.h" +#include "gimpmenudock.h" +#include "gimppanedbox.h" +#include "gimptoolbox.h" +#include "gimpuimanager.h" + +#include "gimp-log.h" + + +enum +{ + PROP_0, + PROP_CONTEXT, + PROP_DIALOG_FACTORY, + PROP_UI_MANAGER +}; + +enum +{ + DOCK_ADDED, + DOCK_REMOVED, + LAST_SIGNAL +}; + + +struct _GimpDockColumnsPrivate +{ + GimpContext *context; + GimpDialogFactory *dialog_factory; + GimpUIManager *ui_manager; + + GList *docks; + + GtkWidget *paned_hbox; +}; + + +static void gimp_dock_columns_dispose (GObject *object); +static void gimp_dock_columns_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_dock_columns_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); +static gboolean gimp_dock_columns_dropped_cb (GtkWidget *source, + gint insert_index, + gpointer data); +static void gimp_dock_columns_real_dock_added (GimpDockColumns *dock_columns, + GimpDock *dock); +static void gimp_dock_columns_real_dock_removed (GimpDockColumns *dock_columns, + GimpDock *dock); +static void gimp_dock_columns_dock_book_removed (GimpDockColumns *dock_columns, + GimpDockbook *dockbook, + GimpDock *dock); + + +G_DEFINE_TYPE_WITH_PRIVATE (GimpDockColumns, gimp_dock_columns, GTK_TYPE_BOX) + +#define parent_class gimp_dock_columns_parent_class + +static guint dock_columns_signals[LAST_SIGNAL] = { 0 }; + + +static void +gimp_dock_columns_class_init (GimpDockColumnsClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = gimp_dock_columns_dispose; + object_class->set_property = gimp_dock_columns_set_property; + object_class->get_property = gimp_dock_columns_get_property; + + klass->dock_added = gimp_dock_columns_real_dock_added; + klass->dock_removed = gimp_dock_columns_real_dock_removed; + + g_object_class_install_property (object_class, PROP_CONTEXT, + g_param_spec_object ("context", + NULL, NULL, + GIMP_TYPE_CONTEXT, + GIMP_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_DIALOG_FACTORY, + g_param_spec_object ("dialog-factory", + NULL, NULL, + GIMP_TYPE_DIALOG_FACTORY, + GIMP_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_UI_MANAGER, + g_param_spec_object ("ui-manager", + NULL, NULL, + GIMP_TYPE_UI_MANAGER, + GIMP_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY)); + + dock_columns_signals[DOCK_ADDED] = + g_signal_new ("dock-added", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpDockColumnsClass, dock_added), + NULL, NULL, + gimp_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + GIMP_TYPE_DOCK); + + dock_columns_signals[DOCK_REMOVED] = + g_signal_new ("dock-removed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpDockColumnsClass, dock_removed), + NULL, NULL, + gimp_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + GIMP_TYPE_DOCK); +} + +static void +gimp_dock_columns_init (GimpDockColumns *dock_columns) +{ + gtk_orientable_set_orientation (GTK_ORIENTABLE (dock_columns), + GTK_ORIENTATION_HORIZONTAL); + + dock_columns->p = gimp_dock_columns_get_instance_private (dock_columns); + + dock_columns->p->paned_hbox = gimp_paned_box_new (FALSE, 0, + GTK_ORIENTATION_HORIZONTAL); + gimp_paned_box_set_dropped_cb (GIMP_PANED_BOX (dock_columns->p->paned_hbox), + gimp_dock_columns_dropped_cb, + dock_columns); + gtk_box_pack_start (GTK_BOX (dock_columns), dock_columns->p->paned_hbox, + TRUE, TRUE, 0); + gtk_widget_show (dock_columns->p->paned_hbox); +} + +static void +gimp_dock_columns_dispose (GObject *object) +{ + GimpDockColumns *dock_columns = GIMP_DOCK_COLUMNS (object); + + while (dock_columns->p->docks) + { + GimpDock *dock = dock_columns->p->docks->data; + + g_object_ref (dock); + gimp_dock_columns_remove_dock (dock_columns, dock); + gtk_widget_destroy (GTK_WIDGET (dock)); + g_object_unref (dock); + } + + if (dock_columns->p->context) + { + g_object_remove_weak_pointer (G_OBJECT (dock_columns->p->context), + (gpointer) &dock_columns->p->context); + dock_columns->p->context = NULL; + } + + if (dock_columns->p->dialog_factory) + { + g_object_remove_weak_pointer (G_OBJECT (dock_columns->p->dialog_factory), + (gpointer) &dock_columns->p->dialog_factory); + dock_columns->p->dialog_factory = NULL; + } + + if (dock_columns->p->ui_manager) + { + g_object_remove_weak_pointer (G_OBJECT (dock_columns->p->ui_manager), + (gpointer)&dock_columns->p->ui_manager); + dock_columns->p->ui_manager = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gimp_dock_columns_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpDockColumns *dock_columns = GIMP_DOCK_COLUMNS (object); + + switch (property_id) + { + case PROP_CONTEXT: + if (dock_columns->p->context) + g_object_remove_weak_pointer (G_OBJECT (dock_columns->p->context), + (gpointer) &dock_columns->p->context); + dock_columns->p->context = g_value_get_object (value); + if (dock_columns->p->context) + g_object_add_weak_pointer (G_OBJECT (dock_columns->p->context), + (gpointer) &dock_columns->p->context); + break; + + case PROP_DIALOG_FACTORY: + if (dock_columns->p->dialog_factory) + g_object_remove_weak_pointer (G_OBJECT (dock_columns->p->dialog_factory), + (gpointer) &dock_columns->p->dialog_factory); + dock_columns->p->dialog_factory = g_value_get_object (value); + if (dock_columns->p->dialog_factory) + g_object_add_weak_pointer (G_OBJECT (dock_columns->p->dialog_factory), + (gpointer) &dock_columns->p->dialog_factory); + break; + + case PROP_UI_MANAGER: + if (dock_columns->p->ui_manager) + g_object_remove_weak_pointer (G_OBJECT (dock_columns->p->ui_manager), + (gpointer) &dock_columns->p->ui_manager); + dock_columns->p->ui_manager = g_value_get_object (value); + if (dock_columns->p->ui_manager) + g_object_add_weak_pointer (G_OBJECT (dock_columns->p->ui_manager), + (gpointer) &dock_columns->p->ui_manager); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_dock_columns_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpDockColumns *dock_columns = GIMP_DOCK_COLUMNS (object); + + switch (property_id) + { + case PROP_CONTEXT: + g_value_set_object (value, dock_columns->p->context); + break; + case PROP_DIALOG_FACTORY: + g_value_set_object (value, dock_columns->p->dialog_factory); + break; + case PROP_UI_MANAGER: + g_value_set_object (value, dock_columns->p->ui_manager); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static gboolean +gimp_dock_columns_dropped_cb (GtkWidget *source, + gint insert_index, + gpointer data) +{ + GimpDockColumns *dock_columns = GIMP_DOCK_COLUMNS (data); + GimpDockable *dockable = gimp_dockbook_drag_source_to_dockable (source); + GtkWidget *dockbook = NULL; + + if (! dockable) + return FALSE; + + /* Create a new dock (including a new dockbook) */ + gimp_dock_columns_prepare_dockbook (dock_columns, + insert_index, + &dockbook); + + /* Move the dockable to the new dockbook */ + g_object_ref (dockbook); + g_object_ref (dockable); + gimp_dockbook_remove (gimp_dockable_get_dockbook (dockable), dockable); + gimp_dockbook_add (GIMP_DOCKBOOK (dockbook), dockable, -1); + g_object_unref (dockable); + g_object_unref (dockbook); + + return TRUE; +} + +static void +gimp_dock_columns_real_dock_added (GimpDockColumns *dock_columns, + GimpDock *dock) +{ +} + +static void +gimp_dock_columns_real_dock_removed (GimpDockColumns *dock_columns, + GimpDock *dock) +{ +} + +static void +gimp_dock_columns_dock_book_removed (GimpDockColumns *dock_columns, + GimpDockbook *dockbook, + GimpDock *dock) +{ + g_return_if_fail (GIMP_IS_DOCK (dock)); + + if (gimp_dock_get_dockbooks (dock) == NULL && + ! GIMP_IS_TOOLBOX (dock) && + gtk_widget_get_parent (GTK_WIDGET (dock)) != NULL) + gimp_dock_columns_remove_dock (dock_columns, dock); +} + + +/** + * gimp_dock_columns_new: + * @context: + * + * Returns: A new #GimpDockColumns. + **/ +GtkWidget * +gimp_dock_columns_new (GimpContext *context, + GimpDialogFactory *dialog_factory, + GimpUIManager *ui_manager) +{ + g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); + g_return_val_if_fail (GIMP_IS_DIALOG_FACTORY (dialog_factory), NULL); + g_return_val_if_fail (GIMP_IS_UI_MANAGER (ui_manager), NULL); + + return g_object_new (GIMP_TYPE_DOCK_COLUMNS, + "context", context, + "dialog-factory", dialog_factory, + "ui-manager", ui_manager, + NULL); +} + +/** + * gimp_dock_columns_add_dock: + * @dock_columns: + * @dock: + * + * Add a dock, added to a horizontal GimpPanedBox. + **/ +void +gimp_dock_columns_add_dock (GimpDockColumns *dock_columns, + GimpDock *dock, + gint index) +{ + g_return_if_fail (GIMP_IS_DOCK_COLUMNS (dock_columns)); + g_return_if_fail (GIMP_IS_DOCK (dock)); + + GIMP_LOG (DND, "Adding GimpDock %p to GimpDockColumns %p", dock, dock_columns); + + dock_columns->p->docks = g_list_insert (dock_columns->p->docks, dock, index); + + gimp_dock_update_with_context (dock, dock_columns->p->context); + + gimp_paned_box_add_widget (GIMP_PANED_BOX (dock_columns->p->paned_hbox), + GTK_WIDGET (dock), + index); + + g_signal_connect_object (dock, "book-removed", + G_CALLBACK (gimp_dock_columns_dock_book_removed), + dock_columns, + G_CONNECT_SWAPPED); + + g_signal_emit (dock_columns, dock_columns_signals[DOCK_ADDED], 0, dock); +} + +/** + * gimp_dock_columns_prepare_dockbook: + * @dock_columns: + * @dock_index: + * @dockbook_p: + * + * Create a new dock and add it to the dock columns with the given + * dock_index insert index, then create and add a dockbook and put it + * in the dock. + **/ +void +gimp_dock_columns_prepare_dockbook (GimpDockColumns *dock_columns, + gint dock_index, + GtkWidget **dockbook_p) +{ + GimpMenuFactory *menu_factory; + GtkWidget *dock; + GtkWidget *dockbook; + + dock = gimp_menu_dock_new (); + gimp_dock_columns_add_dock (dock_columns, GIMP_DOCK (dock), dock_index); + + menu_factory = gimp_dialog_factory_get_menu_factory (dock_columns->p->dialog_factory); + dockbook = gimp_dockbook_new (menu_factory); + gimp_dock_add_book (GIMP_DOCK (dock), GIMP_DOCKBOOK (dockbook), -1); + + gtk_widget_show (GTK_WIDGET (dock)); + + if (dockbook_p) + *dockbook_p = dockbook; +} + + +void +gimp_dock_columns_remove_dock (GimpDockColumns *dock_columns, + GimpDock *dock) +{ + g_return_if_fail (GIMP_IS_DOCK_COLUMNS (dock_columns)); + g_return_if_fail (GIMP_IS_DOCK (dock)); + + GIMP_LOG (DND, "Removing GimpDock %p from GimpDockColumns %p", dock, dock_columns); + + dock_columns->p->docks = g_list_remove (dock_columns->p->docks, dock); + + gimp_dock_update_with_context (dock, NULL); + + g_signal_handlers_disconnect_by_func (dock, + gimp_dock_columns_dock_book_removed, + dock_columns); + + g_object_ref (dock); + gimp_paned_box_remove_widget (GIMP_PANED_BOX (dock_columns->p->paned_hbox), + GTK_WIDGET (dock)); + + g_signal_emit (dock_columns, dock_columns_signals[DOCK_REMOVED], 0, dock); + g_object_unref (dock); +} + +GList * +gimp_dock_columns_get_docks (GimpDockColumns *dock_columns) +{ + g_return_val_if_fail (GIMP_IS_DOCK_COLUMNS (dock_columns), NULL); + + return dock_columns->p->docks; +} + +GimpContext * +gimp_dock_columns_get_context (GimpDockColumns *dock_columns) +{ + g_return_val_if_fail (GIMP_IS_DOCK_COLUMNS (dock_columns), NULL); + + return dock_columns->p->context; +} + +void +gimp_dock_columns_set_context (GimpDockColumns *dock_columns, + GimpContext *context) +{ + g_return_if_fail (GIMP_IS_DOCK_COLUMNS (dock_columns)); + + dock_columns->p->context = context; +} + +GimpDialogFactory * +gimp_dock_columns_get_dialog_factory (GimpDockColumns *dock_columns) +{ + g_return_val_if_fail (GIMP_IS_DOCK_COLUMNS (dock_columns), NULL); + + return dock_columns->p->dialog_factory; +} + +GimpUIManager * +gimp_dock_columns_get_ui_manager (GimpDockColumns *dock_columns) +{ + g_return_val_if_fail (GIMP_IS_DOCK_COLUMNS (dock_columns), NULL); + + return dock_columns->p->ui_manager; +} |