/* PIKA - Photo and Image Kooker Application * a rebranding of The GNU Image Manipulation Program (created with heckimp) * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio * * Original copyright, applying to most contents (license remains unchanged): * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * pikatoolgroup.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 "libpikabase/pikabase.h" #include "libpikaconfig/pikaconfig.h" #include "core-types.h" #include "pikalist.h" #include "pikatoolgroup.h" #include "pikatoolinfo.h" #include "pika-intl.h" enum { ACTIVE_TOOL_CHANGED, LAST_SIGNAL }; enum { PROP_0, PROP_ACTIVE_TOOL, PROP_CHILDREN }; struct _PikaToolGroupPrivate { gchar *active_tool; PikaContainer *children; }; /* local function prototypes */ static void pika_tool_group_finalize (GObject *object); static void pika_tool_group_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); static void pika_tool_group_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); static gint64 pika_tool_group_get_memsize (PikaObject *object, gint64 *gui_size); static gchar * pika_tool_group_get_description (PikaViewable *viewable, gchar **tooltip); static PikaContainer * pika_tool_group_get_children (PikaViewable *viewable); static void pika_tool_group_set_expanded (PikaViewable *viewable, gboolean expand); static gboolean pika_tool_group_get_expanded (PikaViewable *viewable); static void pika_tool_group_child_add (PikaContainer *container, PikaToolInfo *tool_info, PikaToolGroup *tool_group); static void pika_tool_group_child_remove (PikaContainer *container, PikaToolInfo *tool_info, PikaToolGroup *tool_group); static void pika_tool_group_shown_changed (PikaToolItem *tool_item); G_DEFINE_TYPE_WITH_PRIVATE (PikaToolGroup, pika_tool_group, PIKA_TYPE_TOOL_ITEM) #define parent_class pika_tool_group_parent_class static guint pika_tool_group_signals[LAST_SIGNAL] = { 0 }; /* private functions */ static void pika_tool_group_class_init (PikaToolGroupClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); PikaObjectClass *pika_object_class = PIKA_OBJECT_CLASS (klass); PikaViewableClass *viewable_class = PIKA_VIEWABLE_CLASS (klass); PikaToolItemClass *tool_item_class = PIKA_TOOL_ITEM_CLASS (klass); pika_tool_group_signals[ACTIVE_TOOL_CHANGED] = g_signal_new ("active-tool-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (PikaToolGroupClass, active_tool_changed), NULL, NULL, NULL, G_TYPE_NONE, 0); object_class->finalize = pika_tool_group_finalize; object_class->get_property = pika_tool_group_get_property; object_class->set_property = pika_tool_group_set_property; pika_object_class->get_memsize = pika_tool_group_get_memsize; viewable_class->default_icon_name = "folder"; viewable_class->get_description = pika_tool_group_get_description; viewable_class->get_children = pika_tool_group_get_children; viewable_class->get_expanded = pika_tool_group_get_expanded; viewable_class->set_expanded = pika_tool_group_set_expanded; tool_item_class->shown_changed = pika_tool_group_shown_changed; PIKA_CONFIG_PROP_STRING (object_class, PROP_ACTIVE_TOOL, "active-tool", NULL, NULL, NULL, PIKA_PARAM_STATIC_STRINGS); PIKA_CONFIG_PROP_OBJECT (object_class, PROP_CHILDREN, "children", NULL, NULL, PIKA_TYPE_CONTAINER, PIKA_PARAM_STATIC_STRINGS | PIKA_CONFIG_PARAM_AGGREGATE); } static void pika_tool_group_init (PikaToolGroup *tool_group) { tool_group->priv = pika_tool_group_get_instance_private (tool_group); tool_group->priv->children = g_object_new ( PIKA_TYPE_LIST, "children-type", PIKA_TYPE_TOOL_INFO, "append", TRUE, NULL); g_signal_connect (tool_group->priv->children, "add", G_CALLBACK (pika_tool_group_child_add), tool_group); g_signal_connect (tool_group->priv->children, "remove", G_CALLBACK (pika_tool_group_child_remove), tool_group); } static void pika_tool_group_finalize (GObject *object) { PikaToolGroup *tool_group = PIKA_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 pika_tool_group_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { PikaToolGroup *tool_group = PIKA_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 pika_tool_group_set_property_add_tool (PikaToolInfo *tool_info, PikaToolGroup *tool_group) { pika_container_add (tool_group->priv->children, PIKA_OBJECT (tool_info)); } static void pika_tool_group_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { PikaToolGroup *tool_group = PIKA_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: { PikaContainer *container = g_value_get_object (value); pika_container_clear (tool_group->priv->children); if (! container) break; pika_container_foreach (container, (GFunc) pika_tool_group_set_property_add_tool, tool_group); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static gint64 pika_tool_group_get_memsize (PikaObject *object, gint64 *gui_size) { PikaToolGroup *tool_group = PIKA_TOOL_GROUP (object); gint64 memsize = 0; memsize += pika_object_get_memsize (PIKA_OBJECT (tool_group->priv->children), gui_size); return memsize + PIKA_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); } static gchar * pika_tool_group_get_description (PikaViewable *viewable, gchar **tooltip) { /* Translators: this is a noun */ return g_strdup (C_("tool-item", "Group")); } static PikaContainer * pika_tool_group_get_children (PikaViewable *viewable) { PikaToolGroup *tool_group = PIKA_TOOL_GROUP (viewable); return tool_group->priv->children; } static void pika_tool_group_set_expanded (PikaViewable *viewable, gboolean expand) { if (! expand) pika_viewable_expanded_changed (viewable); } static gboolean pika_tool_group_get_expanded (PikaViewable *viewable) { return TRUE; } static void pika_tool_group_child_add (PikaContainer *container, PikaToolInfo *tool_info, PikaToolGroup *tool_group) { g_return_if_fail ( pika_viewable_get_parent (PIKA_VIEWABLE (tool_info)) == NULL); pika_viewable_set_parent (PIKA_VIEWABLE (tool_info), PIKA_VIEWABLE (tool_group)); if (! tool_group->priv->active_tool) pika_tool_group_set_active_tool_info (tool_group, tool_info); } static void pika_tool_group_child_remove (PikaContainer *container, PikaToolInfo *tool_info, PikaToolGroup *tool_group) { pika_viewable_set_parent (PIKA_VIEWABLE (tool_info), NULL); if (! g_strcmp0 (tool_group->priv->active_tool, pika_object_get_name (PIKA_OBJECT (tool_info)))) { PikaToolInfo *active_tool_info = NULL; if (! pika_container_is_empty (tool_group->priv->children)) { active_tool_info = PIKA_TOOL_INFO ( pika_container_get_first_child (tool_group->priv->children)); } pika_tool_group_set_active_tool_info (tool_group, active_tool_info); } } static void pika_tool_group_shown_changed (PikaToolItem *tool_item) { PikaToolGroup *tool_group = PIKA_TOOL_GROUP (tool_item); GList *iter; if (PIKA_TOOL_ITEM_CLASS (parent_class)->shown_changed) PIKA_TOOL_ITEM_CLASS (parent_class)->shown_changed (tool_item); for (iter = PIKA_LIST (tool_group->priv->children)->queue->head; iter; iter = g_list_next (iter)) { PikaToolItem *tool_item = iter->data; if (pika_tool_item_get_visible (tool_item)) pika_tool_item_shown_changed (tool_item); } } /* public functions */ PikaToolGroup * pika_tool_group_new (void) { PikaToolGroup *tool_group; tool_group = g_object_new (PIKA_TYPE_TOOL_GROUP, NULL); pika_object_set_static_name (PIKA_OBJECT (tool_group), "tool group"); return tool_group; } void pika_tool_group_set_active_tool (PikaToolGroup *tool_group, const gchar *tool_name) { g_return_if_fail (PIKA_IS_TOOL_GROUP (tool_group)); if (g_strcmp0 (tool_group->priv->active_tool, tool_name)) { g_return_if_fail (tool_name == NULL || pika_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, pika_tool_group_signals[ACTIVE_TOOL_CHANGED], 0); g_object_notify (G_OBJECT (tool_group), "active-tool"); } } const gchar * pika_tool_group_get_active_tool (PikaToolGroup *tool_group) { g_return_val_if_fail (PIKA_IS_TOOL_GROUP (tool_group), NULL); return tool_group->priv->active_tool; } void pika_tool_group_set_active_tool_info (PikaToolGroup *tool_group, PikaToolInfo *tool_info) { g_return_if_fail (PIKA_IS_TOOL_GROUP (tool_group)); g_return_if_fail (tool_info == NULL || PIKA_IS_TOOL_INFO (tool_info)); pika_tool_group_set_active_tool ( tool_group, tool_info ? pika_object_get_name (PIKA_OBJECT (tool_info)) : NULL); } PikaToolInfo * pika_tool_group_get_active_tool_info (PikaToolGroup *tool_group) { g_return_val_if_fail (PIKA_IS_TOOL_GROUP (tool_group), NULL); return PIKA_TOOL_INFO ( pika_container_get_child_by_name (tool_group->priv->children, tool_group->priv->active_tool)); }