[gimp] app: add GimpToolGroup as a subclass of GimpToolItem



commit 49196140e2a9ec4fbde82c770cd2afd49b7973b4
Author: Ell <ell_se yahoo com>
Date:   Wed Jan 29 19:55:49 2020 +0200

    app: add GimpToolGroup as a subclass of GimpToolItem
    
    Add GimpToolGroup as a new subclass of GimpToolItem, representing a
    collection of tools.  The end goal is to display tool groups using
    a single button in the toolbox.
    
    Tool groups are not recursive: they can only contain individual
    tools, not other groups.  Each group has a single "active tool",
    normally the most-recently-used tool of the group, which is
    activated when clicking on the tool's button.

 app/core/Makefile.am     |   2 +
 app/core/core-types.h    |   1 +
 app/core/gimptoolgroup.c | 385 +++++++++++++++++++++++++++++++++++++++++++++++
 app/core/gimptoolgroup.h |  68 +++++++++
 app/core/meson.build     |   1 +
 po/POTFILES.in           |   1 +
 6 files changed, 458 insertions(+)
---
diff --git a/app/core/Makefile.am b/app/core/Makefile.am
index cc09265741..90188d7249 100644
--- a/app/core/Makefile.am
+++ b/app/core/Makefile.am
@@ -467,6 +467,8 @@ libappcore_a_sources = \
        gimptemplate.h                          \
        gimptilehandlerprojectable.c            \
        gimptilehandlerprojectable.h            \
+       gimptoolgroup.c                         \
+       gimptoolgroup.h                         \
        gimptoolinfo.c                          \
        gimptoolinfo.h                          \
        gimptoolitem.c                          \
diff --git a/app/core/core-types.h b/app/core/core-types.h
index 12bfd7361c..f99f1d1ecd 100644
--- a/app/core/core-types.h
+++ b/app/core/core-types.h
@@ -128,6 +128,7 @@ typedef struct _GimpToolOptions                 GimpToolOptions;
 /*  info objects  */
 
 typedef struct _GimpPaintInfo                   GimpPaintInfo;
+typedef struct _GimpToolGroup                   GimpToolGroup;
 typedef struct _GimpToolInfo                    GimpToolInfo;
 typedef struct _GimpToolItem                    GimpToolItem;
 
diff --git a/app/core/gimptoolgroup.c b/app/core/gimptoolgroup.c
new file mode 100644
index 0000000000..b9a412ee68
--- /dev/null
+++ b/app/core/gimptoolgroup.c
@@ -0,0 +1,385 @@
+/* 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gegl.h>
+
+#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);
+
+
+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);
+
+  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;
+
+  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)
+{
+  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);
+    }
+}
+
+
+/*  public functions  */
+
+GimpToolGroup *
+gimp_tool_group_new (void)
+{
+  GimpToolGroup *group;
+
+  group = g_object_new (GIMP_TYPE_TOOL_GROUP, NULL);
+
+  gimp_object_set_static_name (GIMP_OBJECT (group), "tool group");
+
+  return 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));
+}
diff --git a/app/core/gimptoolgroup.h b/app/core/gimptoolgroup.h
new file mode 100644
index 0000000000..ef4d979b5e
--- /dev/null
+++ b/app/core/gimptoolgroup.h
@@ -0,0 +1,68 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimptoolgroup.h
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_TOOL_GROUP_H__
+#define __GIMP_TOOL_GROUP_H__
+
+
+#include "gimptoolitem.h"
+
+
+#define GIMP_TYPE_TOOL_GROUP            (gimp_tool_group_get_type ())
+#define GIMP_TOOL_GROUP(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_TOOL_GROUP, 
GimpToolGroup))
+#define GIMP_TOOL_GROUP_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_TOOL_GROUP, 
GimpToolGroupClass))
+#define GIMP_IS_TOOL_GROUP(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_TOOL_GROUP))
+#define GIMP_IS_TOOL_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_TOOL_GROUP))
+#define GIMP_TOOL_GROUP_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_TOOL_GROUP, 
GimpToolGroupClass))
+
+
+typedef struct _GimpToolGroupPrivate GimpToolGroupPrivate;
+typedef struct _GimpToolGroupClass   GimpToolGroupClass;
+
+struct _GimpToolGroup
+{
+  GimpToolItem          parent_instance;
+
+  GimpToolGroupPrivate *priv;
+};
+
+struct _GimpToolGroupClass
+{
+  GimpToolItemClass  parent_class;
+
+  /*  signals  */
+  void (* active_tool_changed) (GimpToolGroup *tool_group);
+};
+
+
+GType           gimp_tool_group_get_type             (void) G_GNUC_CONST;
+
+GimpToolGroup * gimp_tool_group_new                  (void);
+
+void            gimp_tool_group_set_active_tool      (GimpToolGroup *tool_group,
+                                                      const gchar   *tool_name);
+const gchar   * gimp_tool_group_get_active_tool      (GimpToolGroup *tool_group);
+
+void            gimp_tool_group_set_active_tool_info (GimpToolGroup *tool_group,
+                                                      GimpToolInfo  *tool_info);
+GimpToolInfo  * gimp_tool_group_get_active_tool_info (GimpToolGroup *tool_group);
+
+
+#endif  /*  __GIMP_TOOL_GROUP_H__  */
diff --git a/app/core/meson.build b/app/core/meson.build
index 5d6a75d43e..1ee94b6926 100644
--- a/app/core/meson.build
+++ b/app/core/meson.build
@@ -233,6 +233,7 @@ libappcore_sources = [
   'gimptempbuf.c',
   'gimptemplate.c',
   'gimptilehandlerprojectable.c',
+  'gimptoolgroup.c',
   'gimptoolinfo.c',
   'gimptoolitem.c',
   'gimptooloptions.c',
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 18aeb7f458..ee3e0da3b8 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -197,6 +197,7 @@ app/core/gimpsymmetry-mirror.c
 app/core/gimpsymmetry-tiling.c
 app/core/gimptagcache.c
 app/core/gimptemplate.c
+app/core/gimptoolgroup.c
 app/core/gimptooloptions.c
 app/core/gimptoolpreset.c
 app/core/gimptoolpreset-load.c


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]