diff options
Diffstat (limited to 'app/widgets/gimptoolpalette.c')
-rw-r--r-- | app/widgets/gimptoolpalette.c | 542 |
1 files changed, 542 insertions, 0 deletions
diff --git a/app/widgets/gimptoolpalette.c b/app/widgets/gimptoolpalette.c new file mode 100644 index 0000000..b5a27a6 --- /dev/null +++ b/app/widgets/gimptoolpalette.c @@ -0,0 +1,542 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimptoolpalette.c + * Copyright (C) 2010 Michael Natterer <mitch@gimp.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 "libgimpwidgets/gimpwidgets.h" + +#include "widgets-types.h" + +#include "config/gimpguiconfig.h" + +#include "core/gimp.h" +#include "core/gimpcontext.h" +#include "core/gimpcontainer.h" +#include "core/gimptoolitem.h" + +#include "gimptoolbox.h" +#include "gimptoolbutton.h" +#include "gimptoolpalette.h" +#include "gimpuimanager.h" +#include "gimpwidgets-utils.h" +#include "gimpwindowstrategy.h" + +#include "gimp-intl.h" + + +#define DEFAULT_TOOL_ICON_SIZE GTK_ICON_SIZE_BUTTON +#define DEFAULT_BUTTON_RELIEF GTK_RELIEF_NONE + + +typedef struct _GimpToolPalettePrivate GimpToolPalettePrivate; + +struct _GimpToolPalettePrivate +{ + GimpToolbox *toolbox; + + GtkWidget *group; + GHashTable *buttons; + + gint tool_rows; + gint tool_columns; +}; + +#define GET_PRIVATE(p) ((GimpToolPalettePrivate *) gimp_tool_palette_get_instance_private ((GimpToolPalette *) (p))) + + +static void gimp_tool_palette_finalize (GObject *object); + +static void gimp_tool_palette_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static void gimp_tool_palette_style_set (GtkWidget *widget, + GtkStyle *previous_style); + +static void gimp_tool_palette_tool_add (GimpContainer *container, + GimpToolItem *tool_item, + GimpToolPalette *palette); +static void gimp_tool_palette_tool_remove (GimpContainer *container, + GimpToolItem *tool_item, + GimpToolPalette *palette); +static void gimp_tool_palette_tool_reorder (GimpContainer *container, + GimpToolItem *tool_item, + gint index, + GimpToolPalette *palette); + +static void gimp_tool_palette_config_menu_mode_notify (GimpGuiConfig *config, + const GParamSpec *pspec, + GimpToolPalette *palette); +static void gimp_tool_palette_config_size_changed (GimpGuiConfig *config, + GimpToolPalette *palette); + +static void gimp_tool_palette_add_button (GimpToolPalette *palette, + GimpToolItem *tool_item, + gint index); + +static gboolean gimp_tool_palette_get_show_menu_on_hover (GimpToolPalette *palette); +static void gimp_tool_palette_update_show_menu_on_hover (GimpToolPalette *palette); + + +G_DEFINE_TYPE_WITH_PRIVATE (GimpToolPalette, gimp_tool_palette, + GTK_TYPE_TOOL_PALETTE) + +#define parent_class gimp_tool_palette_parent_class + + +static void +gimp_tool_palette_class_init (GimpToolPaletteClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->finalize = gimp_tool_palette_finalize; + + widget_class->size_allocate = gimp_tool_palette_size_allocate; + widget_class->style_set = gimp_tool_palette_style_set; + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_enum ("tool-icon-size", + NULL, NULL, + GTK_TYPE_ICON_SIZE, + DEFAULT_TOOL_ICON_SIZE, + GIMP_PARAM_READABLE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_enum ("button-relief", + NULL, NULL, + GTK_TYPE_RELIEF_STYLE, + DEFAULT_BUTTON_RELIEF, + GIMP_PARAM_READABLE)); +} + +static void +gimp_tool_palette_init (GimpToolPalette *palette) +{ + GimpToolPalettePrivate *private = GET_PRIVATE (palette); + + private->buttons = g_hash_table_new (g_direct_hash, g_direct_equal); + + gtk_tool_palette_set_style (GTK_TOOL_PALETTE (palette), GTK_TOOLBAR_ICONS); +} + +static void +gimp_tool_palette_finalize (GObject *object) +{ + GimpToolPalettePrivate *private = GET_PRIVATE (object); + + g_clear_pointer (&private->buttons, g_hash_table_unref); + + if (private->toolbox) + { + GimpContext *context = gimp_toolbox_get_context (private->toolbox); + + if (context) + { + g_signal_handlers_disconnect_by_func ( + context->gimp->config, + G_CALLBACK (gimp_tool_palette_config_menu_mode_notify), + object); + g_signal_handlers_disconnect_by_func ( + context->gimp->config, + G_CALLBACK (gimp_tool_palette_config_size_changed), + object); + } + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gimp_tool_palette_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GimpToolPalette *palette = GIMP_TOOL_PALETTE (widget); + GimpToolPalettePrivate *private = GET_PRIVATE (widget); + gint button_width; + gint button_height; + + GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation); + + if (gimp_tool_palette_get_button_size (palette, + &button_width, &button_height)) + { + GimpToolItem *tool_item; + GHashTableIter iter; + gint n_tools; + gint tool_rows; + gint tool_columns; + + n_tools = 0; + + g_hash_table_iter_init (&iter, private->buttons); + + while (g_hash_table_iter_next (&iter, (gpointer *) &tool_item, NULL)) + { + if (gimp_tool_item_get_visible (tool_item)) + n_tools++; + } + + tool_columns = MAX (1, (allocation->width / button_width)); + tool_rows = n_tools / tool_columns; + + if (n_tools % tool_columns) + tool_rows++; + + if (private->tool_rows != tool_rows || + private->tool_columns != tool_columns) + { + private->tool_rows = tool_rows; + private->tool_columns = tool_columns; + + gtk_widget_set_size_request (widget, -1, + tool_rows * button_height); + + gimp_tool_palette_update_show_menu_on_hover (palette); + } + } +} + +static void +gimp_tool_palette_style_set (GtkWidget *widget, + GtkStyle *previous_style) +{ + GimpToolPalettePrivate *private = GET_PRIVATE (widget); + Gimp *gimp; + GtkWidget *tool_button; + GHashTableIter iter; + GtkReliefStyle relief; + + GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style); + + if (! gimp_toolbox_get_context (private->toolbox)) + return; + + gimp = gimp_toolbox_get_context (private->toolbox)->gimp; + + gtk_widget_style_get (widget, + "button-relief", &relief, + NULL); + + gimp_tool_palette_config_size_changed (GIMP_GUI_CONFIG (gimp->config), + GIMP_TOOL_PALETTE (widget)); + + g_hash_table_iter_init (&iter, private->buttons); + + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &tool_button)) + { + GtkWidget *button = gtk_bin_get_child (GTK_BIN (tool_button)); + + gtk_button_set_relief (GTK_BUTTON (button), relief); + } + + gimp_dock_invalidate_geometry (GIMP_DOCK (private->toolbox)); +} + + +/* public functions */ + +GtkWidget * +gimp_tool_palette_new (void) +{ + return g_object_new (GIMP_TYPE_TOOL_PALETTE, NULL); +} + +void +gimp_tool_palette_set_toolbox (GimpToolPalette *palette, + GimpToolbox *toolbox) +{ + GimpToolPalettePrivate *private; + GimpContext *context; + GList *list; + + g_return_if_fail (GIMP_IS_TOOL_PALETTE (palette)); + g_return_if_fail (GIMP_IS_TOOLBOX (toolbox)); + + private = GET_PRIVATE (palette); + + if (private->toolbox) + { + context = gimp_toolbox_get_context (private->toolbox); + + g_signal_handlers_disconnect_by_func ( + GIMP_GUI_CONFIG (context->gimp->config), + G_CALLBACK (gimp_tool_palette_config_menu_mode_notify), + palette); + g_signal_handlers_disconnect_by_func ( + GIMP_GUI_CONFIG (context->gimp->config), + G_CALLBACK (gimp_tool_palette_config_size_changed), + palette); + } + + private->toolbox = toolbox; + + context = gimp_toolbox_get_context (toolbox); + + private->group = gtk_tool_item_group_new (_("Tools")); + gtk_tool_item_group_set_label_widget (GTK_TOOL_ITEM_GROUP (private->group), + NULL); + gtk_container_add (GTK_CONTAINER (palette), private->group); + gtk_widget_show (private->group); + + for (list = gimp_get_tool_item_ui_iter (context->gimp); + list; + list = g_list_next (list)) + { + GimpToolItem *tool_item = list->data; + + gimp_tool_palette_add_button (palette, tool_item, -1); + } + + g_signal_connect_object (context->gimp->tool_item_ui_list, "add", + G_CALLBACK (gimp_tool_palette_tool_add), + palette, 0); + g_signal_connect_object (context->gimp->tool_item_ui_list, "remove", + G_CALLBACK (gimp_tool_palette_tool_remove), + palette, 0); + g_signal_connect_object (context->gimp->tool_item_ui_list, "reorder", + G_CALLBACK (gimp_tool_palette_tool_reorder), + palette, 0); + + g_signal_connect (GIMP_GUI_CONFIG (context->gimp->config), + "notify::toolbox-group-menu-mode", + G_CALLBACK (gimp_tool_palette_config_menu_mode_notify), + palette); + gimp_tool_palette_update_show_menu_on_hover (palette); + + /* Update the toolbox icon size on config change. */ + g_signal_connect (GIMP_GUI_CONFIG (context->gimp->config), + "size-changed", + G_CALLBACK (gimp_tool_palette_config_size_changed), + palette); + gimp_tool_palette_config_size_changed (GIMP_GUI_CONFIG (context->gimp->config), + palette); +} + +gboolean +gimp_tool_palette_get_button_size (GimpToolPalette *palette, + gint *width, + gint *height) +{ + GimpToolPalettePrivate *private; + GHashTableIter iter; + GtkWidget *tool_button; + + g_return_val_if_fail (GIMP_IS_TOOL_PALETTE (palette), FALSE); + g_return_val_if_fail (width != NULL, FALSE); + g_return_val_if_fail (height != NULL, FALSE); + + private = GET_PRIVATE (palette); + + g_hash_table_iter_init (&iter, private->buttons); + + if (g_hash_table_iter_next (&iter, NULL, (gpointer *) &tool_button)) + { + GtkRequisition button_requisition; + + gtk_widget_size_request (tool_button, &button_requisition); + + *width = button_requisition.width; + *height = button_requisition.height; + + return TRUE; + } + + return FALSE; +} + + +/* private functions */ + +static void +gimp_tool_palette_tool_add (GimpContainer *container, + GimpToolItem *tool_item, + GimpToolPalette *palette) +{ + gimp_tool_palette_add_button ( + palette, + tool_item, + gimp_container_get_child_index (container, GIMP_OBJECT (tool_item))); +} + +static void +gimp_tool_palette_tool_remove (GimpContainer *container, + GimpToolItem *tool_item, + GimpToolPalette *palette) +{ + GimpToolPalettePrivate *private = GET_PRIVATE (palette); + GtkWidget *tool_button; + + tool_button = g_hash_table_lookup (private->buttons, tool_item); + + if (tool_button) + { + g_hash_table_remove (private->buttons, tool_item); + + gtk_container_remove (GTK_CONTAINER (private->group), tool_button); + } +} + +static void +gimp_tool_palette_tool_reorder (GimpContainer *container, + GimpToolItem *tool_item, + gint index, + GimpToolPalette *palette) +{ + GimpToolPalettePrivate *private = GET_PRIVATE (palette); + GtkWidget *tool_button; + + tool_button = g_hash_table_lookup (private->buttons, tool_item); + + if (tool_button) + { + gtk_tool_item_group_set_item_position ( + GTK_TOOL_ITEM_GROUP (private->group), + GTK_TOOL_ITEM (tool_button), index); + } +} + +static void +gimp_tool_palette_config_menu_mode_notify (GimpGuiConfig *config, + const GParamSpec *pspec, + GimpToolPalette *palette) +{ + gimp_tool_palette_update_show_menu_on_hover (palette); +} + +static void +gimp_tool_palette_config_size_changed (GimpGuiConfig *config, + GimpToolPalette *palette) +{ + GimpIconSize size; + GtkIconSize tool_icon_size; + + size = gimp_gui_config_detect_icon_size (config); + /* Match GimpIconSize with GtkIconSize for the toolbox icons. */ + switch (size) + { + case GIMP_ICON_SIZE_SMALL: + tool_icon_size = GTK_ICON_SIZE_SMALL_TOOLBAR; + break; + case GIMP_ICON_SIZE_MEDIUM: + tool_icon_size = GTK_ICON_SIZE_LARGE_TOOLBAR; + break; + case GIMP_ICON_SIZE_LARGE: + tool_icon_size = GTK_ICON_SIZE_DND; + break; + case GIMP_ICON_SIZE_HUGE: + tool_icon_size = GTK_ICON_SIZE_DIALOG; + break; + default: + /* GIMP_ICON_SIZE_DEFAULT: + * let's use the size set by the theme. */ + gtk_widget_style_get (GTK_WIDGET (palette), + "tool-icon-size", &tool_icon_size, + NULL); + break; + } + + gtk_tool_palette_set_icon_size (GTK_TOOL_PALETTE (palette), tool_icon_size); +} + +static void +gimp_tool_palette_add_button (GimpToolPalette *palette, + GimpToolItem *tool_item, + gint index) +{ + GimpToolPalettePrivate *private = GET_PRIVATE (palette); + GtkToolItem *tool_button; + GtkWidget *button; + GtkReliefStyle relief; + + tool_button = gimp_tool_button_new (private->toolbox, tool_item); + gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (private->group), + tool_button, index); + gimp_tool_button_set_show_menu_on_hover ( + GIMP_TOOL_BUTTON (tool_button), + gimp_tool_palette_get_show_menu_on_hover (palette)); + gtk_widget_show (GTK_WIDGET (tool_button)); + + g_object_bind_property (tool_item, "shown", + tool_button, "visible-horizontal", + G_BINDING_SYNC_CREATE); + g_object_bind_property (tool_item, "shown", + tool_button, "visible-vertical", + G_BINDING_SYNC_CREATE); + + button = gtk_bin_get_child (GTK_BIN (tool_button)); + + gtk_widget_style_get (GTK_WIDGET (palette), + "button-relief", &relief, + NULL); + + gtk_button_set_relief (GTK_BUTTON (button), relief); + + g_hash_table_insert (private->buttons, tool_item, tool_button); +} + +static gboolean +gimp_tool_palette_get_show_menu_on_hover (GimpToolPalette *palette) +{ + GimpToolPalettePrivate *private = GET_PRIVATE (palette); + + if (private->toolbox) + { + GimpContext *context = gimp_toolbox_get_context (private->toolbox); + + if (context) + { + GimpGuiConfig *config = GIMP_GUI_CONFIG (context->gimp->config); + + switch (config->toolbox_group_menu_mode) + { + case GIMP_TOOL_GROUP_MENU_MODE_SHOW_ON_CLICK: + return FALSE; + + case GIMP_TOOL_GROUP_MENU_MODE_SHOW_ON_HOVER: + return TRUE; + + case GIMP_TOOL_GROUP_MENU_MODE_SHOW_ON_HOVER_SINGLE_COLUMN: + return private->tool_columns == 1; + } + } + } + + return FALSE; +} + +static void +gimp_tool_palette_update_show_menu_on_hover (GimpToolPalette *palette) +{ + GimpToolPalettePrivate *private = GET_PRIVATE (palette); + GHashTableIter iter; + GimpToolButton *tool_button; + gboolean show_menu_on_hover; + + show_menu_on_hover = gimp_tool_palette_get_show_menu_on_hover (palette); + + g_hash_table_iter_init (&iter, private->buttons); + + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &tool_button)) + { + gimp_tool_button_set_show_menu_on_hover (tool_button, show_menu_on_hover); + } +} |