/* GIMP - The GNU Image Manipulation Program * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * gimptoolgroup.c * Copyright (C) 2020 Ell * * 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 #include #include "libgimpbase/gimpbase.h" #include "libgimpconfig/gimpconfig.h" #include "core-types.h" #include "gimplist.h" #include "gimpmarshal.h" #include "gimptoolgroup.h" #include "gimptoolinfo.h" #include "gimp-intl.h" enum { ACTIVE_TOOL_CHANGED, LAST_SIGNAL }; enum { PROP_0, PROP_ACTIVE_TOOL, PROP_CHILDREN }; struct _GimpToolGroupPrivate { gchar *active_tool; GimpContainer *children; }; /* local function prototypes */ static void gimp_tool_group_finalize (GObject *object); static void gimp_tool_group_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); static void gimp_tool_group_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); static gint64 gimp_tool_group_get_memsize (GimpObject *object, gint64 *gui_size); static gchar * gimp_tool_group_get_description (GimpViewable *viewable, gchar **tooltip); static GimpContainer * gimp_tool_group_get_children (GimpViewable *viewable); static void gimp_tool_group_set_expanded (GimpViewable *viewable, gboolean expand); static gboolean gimp_tool_group_get_expanded (GimpViewable *viewable); static void gimp_tool_group_child_add (GimpContainer *container, GimpToolInfo *tool_info, GimpToolGroup *tool_group); static void gimp_tool_group_child_remove (GimpContainer *container, GimpToolInfo *tool_info, GimpToolGroup *tool_group); static void gimp_tool_group_shown_changed (GimpToolItem *tool_item); G_DEFINE_TYPE_WITH_PRIVATE (GimpToolGroup, gimp_tool_group, GIMP_TYPE_TOOL_ITEM) #define parent_class gimp_tool_group_parent_class static guint gimp_tool_group_signals[LAST_SIGNAL] = { 0 }; /* private functions */ static void gimp_tool_group_class_init (GimpToolGroupClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass); GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass); GimpToolItemClass *tool_item_class = GIMP_TOOL_ITEM_CLASS (klass); gimp_tool_group_signals[ACTIVE_TOOL_CHANGED] = g_signal_new ("active-tool-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GimpToolGroupClass, active_tool_changed), NULL, NULL, gimp_marshal_VOID__VOID, G_TYPE_NONE, 0); object_class->finalize = gimp_tool_group_finalize; object_class->get_property = gimp_tool_group_get_property; object_class->set_property = gimp_tool_group_set_property; gimp_object_class->get_memsize = gimp_tool_group_get_memsize; viewable_class->default_icon_name = "folder"; viewable_class->get_description = gimp_tool_group_get_description; viewable_class->get_children = gimp_tool_group_get_children; viewable_class->get_expanded = gimp_tool_group_get_expanded; viewable_class->set_expanded = gimp_tool_group_set_expanded; tool_item_class->shown_changed = gimp_tool_group_shown_changed; GIMP_CONFIG_PROP_STRING (object_class, PROP_ACTIVE_TOOL, "active-tool", NULL, NULL, NULL, GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_PROP_OBJECT (object_class, PROP_CHILDREN, "children", NULL, NULL, GIMP_TYPE_CONTAINER, GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_AGGREGATE); } static void gimp_tool_group_init (GimpToolGroup *tool_group) { tool_group->priv = gimp_tool_group_get_instance_private (tool_group); tool_group->priv->children = g_object_new ( GIMP_TYPE_LIST, "children-type", GIMP_TYPE_TOOL_INFO, "append", TRUE, NULL); g_signal_connect (tool_group->priv->children, "add", G_CALLBACK (gimp_tool_group_child_add), tool_group); g_signal_connect (tool_group->priv->children, "remove", G_CALLBACK (gimp_tool_group_child_remove), tool_group); } static void gimp_tool_group_finalize (GObject *object) { GimpToolGroup *tool_group = GIMP_TOOL_GROUP (object); g_clear_pointer (&tool_group->priv->active_tool, g_free); g_clear_object (&tool_group->priv->children); G_OBJECT_CLASS (parent_class)->finalize (object); } static void gimp_tool_group_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GimpToolGroup *tool_group = GIMP_TOOL_GROUP (object); switch (property_id) { case PROP_ACTIVE_TOOL: g_value_set_string (value, tool_group->priv->active_tool); break; case PROP_CHILDREN: g_value_set_object (value, tool_group->priv->children); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gimp_tool_group_set_property_add_tool (GimpToolInfo *tool_info, GimpToolGroup *tool_group) { gimp_container_add (tool_group->priv->children, GIMP_OBJECT (tool_info)); } static void gimp_tool_group_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GimpToolGroup *tool_group = GIMP_TOOL_GROUP (object); switch (property_id) { case PROP_ACTIVE_TOOL: g_free (tool_group->priv->active_tool); tool_group->priv->active_tool = g_value_dup_string (value); break; case PROP_CHILDREN: { GimpContainer *container = g_value_get_object (value); gimp_container_clear (tool_group->priv->children); if (! container) break; gimp_container_foreach (container, (GFunc) gimp_tool_group_set_property_add_tool, tool_group); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static gint64 gimp_tool_group_get_memsize (GimpObject *object, gint64 *gui_size) { GimpToolGroup *tool_group = GIMP_TOOL_GROUP (object); gint64 memsize = 0; memsize += gimp_object_get_memsize (GIMP_OBJECT (tool_group->priv->children), gui_size); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); } static gchar * gimp_tool_group_get_description (GimpViewable *viewable, gchar **tooltip) { /* Translators: this is a noun */ return g_strdup (C_("tool-item", "Group")); } static GimpContainer * gimp_tool_group_get_children (GimpViewable *viewable) { GimpToolGroup *tool_group = GIMP_TOOL_GROUP (viewable); return tool_group->priv->children; } static void gimp_tool_group_set_expanded (GimpViewable *viewable, gboolean expand) { if (! expand) gimp_viewable_expanded_changed (viewable); } static gboolean gimp_tool_group_get_expanded (GimpViewable *viewable) { return TRUE; } static void gimp_tool_group_child_add (GimpContainer *container, GimpToolInfo *tool_info, GimpToolGroup *tool_group) { g_return_if_fail ( gimp_viewable_get_parent (GIMP_VIEWABLE (tool_info)) == NULL); gimp_viewable_set_parent (GIMP_VIEWABLE (tool_info), GIMP_VIEWABLE (tool_group)); if (! tool_group->priv->active_tool) gimp_tool_group_set_active_tool_info (tool_group, tool_info); } static void gimp_tool_group_child_remove (GimpContainer *container, GimpToolInfo *tool_info, GimpToolGroup *tool_group) { gimp_viewable_set_parent (GIMP_VIEWABLE (tool_info), NULL); if (! g_strcmp0 (tool_group->priv->active_tool, gimp_object_get_name (GIMP_OBJECT (tool_info)))) { GimpToolInfo *active_tool_info = NULL; if (! gimp_container_is_empty (tool_group->priv->children)) { active_tool_info = GIMP_TOOL_INFO ( gimp_container_get_first_child (tool_group->priv->children)); } gimp_tool_group_set_active_tool_info (tool_group, active_tool_info); } } static void gimp_tool_group_shown_changed (GimpToolItem *tool_item) { GimpToolGroup *tool_group = GIMP_TOOL_GROUP (tool_item); GList *iter; if (GIMP_TOOL_ITEM_CLASS (parent_class)->shown_changed) GIMP_TOOL_ITEM_CLASS (parent_class)->shown_changed (tool_item); for (iter = GIMP_LIST (tool_group->priv->children)->queue->head; iter; iter = g_list_next (iter)) { GimpToolItem *tool_item = iter->data; if (gimp_tool_item_get_visible (tool_item)) gimp_tool_item_shown_changed (tool_item); } } /* public functions */ GimpToolGroup * gimp_tool_group_new (void) { GimpToolGroup *tool_group; tool_group = g_object_new (GIMP_TYPE_TOOL_GROUP, NULL); gimp_object_set_static_name (GIMP_OBJECT (tool_group), "tool group"); return tool_group; } void gimp_tool_group_set_active_tool (GimpToolGroup *tool_group, const gchar *tool_name) { g_return_if_fail (GIMP_IS_TOOL_GROUP (tool_group)); if (g_strcmp0 (tool_group->priv->active_tool, tool_name)) { g_return_if_fail (tool_name == NULL || gimp_container_get_child_by_name ( tool_group->priv->children, tool_name) != NULL); g_free (tool_group->priv->active_tool); tool_group->priv->active_tool = g_strdup (tool_name);; g_signal_emit (tool_group, gimp_tool_group_signals[ACTIVE_TOOL_CHANGED], 0); g_object_notify (G_OBJECT (tool_group), "active-tool"); } } const gchar * gimp_tool_group_get_active_tool (GimpToolGroup *tool_group) { g_return_val_if_fail (GIMP_IS_TOOL_GROUP (tool_group), NULL); return tool_group->priv->active_tool; } void gimp_tool_group_set_active_tool_info (GimpToolGroup *tool_group, GimpToolInfo *tool_info) { g_return_if_fail (GIMP_IS_TOOL_GROUP (tool_group)); g_return_if_fail (tool_info == NULL || GIMP_IS_TOOL_INFO (tool_info)); gimp_tool_group_set_active_tool ( tool_group, tool_info ? gimp_object_get_name (GIMP_OBJECT (tool_info)) : NULL); } GimpToolInfo * gimp_tool_group_get_active_tool_info (GimpToolGroup *tool_group) { g_return_val_if_fail (GIMP_IS_TOOL_GROUP (tool_group), NULL); return GIMP_TOOL_INFO ( gimp_container_get_child_by_name (tool_group->priv->children, tool_group->priv->active_tool)); }