[gnome-builder/wip/gtk4-port: 47/67] core: add IDE_DEFINE_ACTION_GROUP()




commit e4b118a6bdea2ce9edde6ce30d0050ba51f671e1
Author: Christian Hergert <chergert redhat com>
Date:   Fri Sep 24 13:20:54 2021 -0700

    core: add IDE_DEFINE_ACTION_GROUP()

 src/libide/core/ide-action-group.h | 212 +++++++++++++++++++++++++++++++++++++
 src/libide/core/libide-core.h      |   1 +
 src/libide/core/meson.build        |   1 +
 3 files changed, 214 insertions(+)
---
diff --git a/src/libide/core/ide-action-group.h b/src/libide/core/ide-action-group.h
new file mode 100644
index 000000000..97cc3e398
--- /dev/null
+++ b/src/libide/core/ide-action-group.h
@@ -0,0 +1,212 @@
+/* ide-action-group.h
+ *
+ * Copyright (C) 2017 Christian Hergert <chergert redhat com>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define IDE_DEFINE_ACTION_GROUP(Type, prefix, ...)                                \
+struct _##Type##ActionEntry {                                                     \
+  const gchar *name;                                                              \
+  void (*activate) (Type *self, GVariant *param);                                 \
+  const gchar *parameter_type;                                                    \
+  const gchar *state;                                                             \
+  void (*change_state) (Type *self, GVariant *state);                             \
+} prefix##_actions[] = __VA_ARGS__;                                               \
+                                                                                  \
+typedef struct {                                                                  \
+  GVariant *state;                                                                \
+  GVariant *state_hint;                                                           \
+  guint enabled : 1;                                                              \
+} Type##ActionInfo;                                                               \
+                                                                                  \
+static gboolean                                                                   \
+_##prefix##_has_action (GActionGroup *group,                                      \
+                        const gchar *name)                                        \
+{                                                                                 \
+  for (guint i = 0; i < G_N_ELEMENTS(prefix##_actions); i++)                      \
+    {                                                                             \
+      if (g_strcmp0 (name, prefix##_actions[i].name) == 0)                        \
+        return TRUE;                                                              \
+    }                                                                             \
+  return FALSE;                                                                   \
+}                                                                                 \
+                                                                                  \
+static gchar **                                                                   \
+_##prefix##_list_actions (GActionGroup *group)                                    \
+{                                                                                 \
+  GPtrArray *ar = g_ptr_array_new ();                                             \
+                                                                                  \
+  for (guint i = 0; i < G_N_ELEMENTS(prefix##_actions); i++)                      \
+    g_ptr_array_add (ar, g_strdup (prefix##_actions[i].name));                    \
+  g_ptr_array_add (ar, NULL);                                                     \
+                                                                                  \
+  return (gchar **)g_ptr_array_free (ar, FALSE);                                  \
+}                                                                                 \
+                                                                                  \
+static void                                                                       \
+_##prefix##_action_info_free (gpointer data)                                      \
+{                                                                                 \
+  Type##ActionInfo *info = data;                                                  \
+  g_clear_pointer (&info->state, g_variant_unref);                                \
+  g_clear_pointer (&info->state_hint, g_variant_unref);                           \
+  g_slice_free (Type##ActionInfo, info);                                          \
+}                                                                                 \
+                                                                                  \
+static Type##ActionInfo *                                                         \
+_##prefix##_get_action_info (GActionGroup *group,                                 \
+                             const gchar *name)                                   \
+{                                                                                 \
+  g_autofree gchar *fullname = g_strdup_printf ("ACTION-INFO:%s", name);          \
+  Type##ActionInfo *info = g_object_get_data (G_OBJECT (group), fullname);        \
+  if (info == NULL)                                                               \
+    {                                                                             \
+      info = g_slice_new0 (Type##ActionInfo);                                     \
+      info->enabled = TRUE;                                                       \
+      for (guint i = 0; i < G_N_ELEMENTS(prefix##_actions); i++)                  \
+        {                                                                         \
+          if (g_strcmp0 (prefix##_actions[i].name, name) == 0)                    \
+            {                                                                     \
+              if (prefix##_actions[i].state != NULL)                              \
+                info->state = g_variant_parse (                                   \
+                  NULL, prefix##_actions[i].state, NULL, NULL, NULL);             \
+              break;                                                              \
+            }                                                                     \
+        }                                                                         \
+      g_object_set_data_full (G_OBJECT (group), fullname, info,                   \
+                              _##prefix##_action_info_free);                      \
+    }                                                                             \
+  return info;                                                                    \
+}                                                                                 \
+                                                                                  \
+static inline void                                                                \
+prefix##_set_action_state (Type *self,                                            \
+                           const gchar *name,                                     \
+                           GVariant *state)                                       \
+{                                                                                 \
+  Type##ActionInfo *info = _##prefix##_get_action_info (G_ACTION_GROUP (self),    \
+                                                        name);                    \
+  if (state != info->state)                                                       \
+    {                                                                             \
+      g_clear_pointer (&info->state, g_variant_unref);                            \
+      info->state = state ? g_variant_ref_sink (state) : NULL;                    \
+      g_action_group_action_state_changed (G_ACTION_GROUP (self), name, state);   \
+    }                                                                             \
+}                                                                                 \
+                                                                                  \
+static inline void                                                                \
+prefix##_set_action_enabled (Type *self,                                          \
+                             const gchar *name,                                   \
+                             gboolean enabled)                                    \
+{                                                                                 \
+  Type##ActionInfo *info = _##prefix##_get_action_info (G_ACTION_GROUP (self),    \
+                                                        name);                    \
+  if (enabled != info->enabled)                                                   \
+    {                                                                             \
+      info->enabled = !!enabled;                                                  \
+      g_action_group_action_enabled_changed (G_ACTION_GROUP (self),               \
+                                             name, enabled);                      \
+    }                                                                             \
+}                                                                                 \
+                                                                                  \
+static void                                                                       \
+_##prefix##_change_action_state (GActionGroup *group,                             \
+                                 const gchar *name,                               \
+                                 GVariant *state)                                 \
+{                                                                                 \
+  for (guint i = 0; i < G_N_ELEMENTS(prefix##_actions); i++)                      \
+    {                                                                             \
+      if (g_strcmp0 (name, prefix##_actions[i].name) == 0)                        \
+        {                                                                         \
+          if (prefix##_actions[i].change_state)                                   \
+            prefix##_actions[i].change_state ((Type*)group, state);               \
+          return;                                                                 \
+        }                                                                         \
+    }                                                                             \
+}                                                                                 \
+                                                                                  \
+static void                                                                       \
+_##prefix##_activate_action (GActionGroup *group,                                 \
+                             const gchar *name,                                   \
+                             GVariant *param)                                     \
+{                                                                                 \
+  for (guint i = 0; i < G_N_ELEMENTS(prefix##_actions); i++)                      \
+    {                                                                             \
+      if (g_strcmp0 (name, prefix##_actions[i].name) == 0)                        \
+        {                                                                         \
+          if (prefix##_actions[i].activate)                                       \
+            prefix##_actions[i].activate ((Type*)group, param);                   \
+          return;                                                                 \
+        }                                                                         \
+    }                                                                             \
+}                                                                                 \
+                                                                                  \
+static gboolean                                                                   \
+_##prefix##_query_action (GActionGroup *group,                                    \
+                          const gchar *name,                                      \
+                          gboolean *enabled,                                      \
+                          const GVariantType **parameter_type,                    \
+                          const GVariantType **state_type,                        \
+                          GVariant **state_hint,                                  \
+                          GVariant **state)                                       \
+{                                                                                 \
+  if (enabled) *enabled = FALSE;                                                  \
+  if (parameter_type) *parameter_type = NULL ;                                    \
+  if (state_type) *state_type = NULL ;                                            \
+  if (state_hint) *state_hint = NULL ;                                            \
+  if (state) *state = NULL ;                                                      \
+  for (guint i = 0; i < G_N_ELEMENTS(prefix##_actions); i++)                      \
+    {                                                                             \
+      if (g_strcmp0 (name, prefix##_actions[i].name) == 0)                        \
+        {                                                                         \
+          Type##ActionInfo *info = _##prefix##_get_action_info(group, name);      \
+          if (prefix##_actions[i].change_state && state_type)                     \
+            *state_type = prefix##_actions[i].parameter_type ?                    \
+                          G_VARIANT_TYPE(prefix##_actions[i].parameter_type) :    \
+                          NULL;                                                   \
+          else if (prefix##_actions[i].activate && parameter_type)                \
+            *parameter_type = prefix##_actions[i].parameter_type ?                \
+                              G_VARIANT_TYPE(prefix##_actions[i].parameter_type) :\
+                              NULL;                                               \
+          if (state_hint)                                                         \
+            *state_hint = info->state_hint != NULL ?                              \
+                          g_variant_ref (info->state_hint) : NULL;                \
+          if (state)                                                              \
+            *state = info->state != NULL ?                                        \
+                     g_variant_ref (info->state) : NULL;                          \
+          if (enabled)                                                            \
+            *enabled = info->enabled;                                             \
+          return TRUE;                                                            \
+        }                                                                         \
+    }                                                                             \
+  return FALSE;                                                                   \
+}                                                                                 \
+                                                                                  \
+static void                                                                       \
+prefix##_init_action_group (GActionGroupInterface *iface)                         \
+{                                                                                 \
+  iface->has_action = _##prefix##_has_action;                                     \
+  iface->list_actions = _##prefix##_list_actions;                                 \
+  iface->change_action_state = _##prefix##_change_action_state;                   \
+  iface->activate_action = _##prefix##_activate_action;                           \
+  iface->query_action = _##prefix##_query_action;                                 \
+}
+
+G_END_DECLS
diff --git a/src/libide/core/libide-core.h b/src/libide/core/libide-core.h
index 7af1f6e60..da92b41a0 100644
--- a/src/libide/core/libide-core.h
+++ b/src/libide/core/libide-core.h
@@ -24,6 +24,7 @@
 
 #define IDE_CORE_INSIDE
 
+#include "ide-action-group.h"
 #include "ide-context.h"
 #include "ide-context-addin.h"
 #include "ide-debug.h"
diff --git a/src/libide/core/meson.build b/src/libide/core/meson.build
index 6c5155aa1..32031963a 100644
--- a/src/libide/core/meson.build
+++ b/src/libide/core/meson.build
@@ -52,6 +52,7 @@ libide_core_generated_headers += [libide_debug_h]
 #
 
 libide_core_public_headers = [
+  'ide-action-group.h',
   'ide-context.h',
   'ide-context-addin.h',
   'ide-global.h',


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