[gnome-builder/wip/commands2] commands: move workspace and active tab to GbCommandProvider



commit f87194e3073e4f2c0c18f38628485dfee1e03ebb
Author: Christian Hergert <christian hergert me>
Date:   Thu Oct 9 16:29:36 2014 -0700

    commands: move workspace and active tab to GbCommandProvider
    
    This refactors the workspace and active-tab properties into the
    base class, GbCommandProvider. They are likely to be needed by
    most providers, so might as well track things there.

 src/commands/gb-command-gaction-provider.c |  230 ++-------------------------
 src/commands/gb-command-gaction-provider.h |    1 -
 src/commands/gb-command-provider.c         |  197 +++++++++++++++++++++++-
 src/commands/gb-command-provider.h         |   21 ++-
 4 files changed, 224 insertions(+), 225 deletions(-)
---
diff --git a/src/commands/gb-command-gaction-provider.c b/src/commands/gb-command-gaction-provider.c
index 028b5b4..dd8c86f 100644
--- a/src/commands/gb-command-gaction-provider.c
+++ b/src/commands/gb-command-gaction-provider.c
@@ -18,28 +18,12 @@
 
 #define G_LOG_DOMAIN "gaction-commands"
 
-#include <glib/gi18n.h>
+#include <string.h>
 
 #include "gb-command-gaction-provider.h"
-#include "gb-tab.h"
 
-struct _GbCommandGactionProviderPrivate
-{
-  GbWorkbench *workbench;
-  GtkWidget   *focus;
-};
-
-G_DEFINE_TYPE_WITH_PRIVATE (GbCommandGactionProvider,
-                            gb_command_gaction_provider,
-                            GB_TYPE_COMMAND_PROVIDER)
-
-enum {
-  PROP_0,
-  PROP_WORKBENCH,
-  LAST_PROP
-};
-
-static GParamSpec *gParamSpecs [LAST_PROP];
+G_DEFINE_TYPE (GbCommandGactionProvider, gb_command_gaction_provider,
+               GB_TYPE_COMMAND_PROVIDER)
 
 GbCommandProvider *
 gb_command_gaction_provider_new (GbWorkbench *workbench)
@@ -48,127 +32,6 @@ gb_command_gaction_provider_new (GbWorkbench *workbench)
                        "workbench", workbench,
                        NULL);
 }
-
-GbWorkbench *
-gb_command_gaction_provider_get_workbench (GbCommandGactionProvider *provider)
-{
-  g_return_val_if_fail (GB_IS_COMMAND_GACTION_PROVIDER (provider), NULL);
-
-  return provider->priv->workbench;
-}
-
-static void
-gb_command_gaction_provider_update_focus (GbCommandGactionProvider *provider,
-                                          GtkWidget                *focus)
-{
-  GbCommandGactionProviderPrivate *priv;
-
-  g_return_if_fail (GB_IS_COMMAND_GACTION_PROVIDER (provider));
-  g_return_if_fail (!focus || GTK_IS_WIDGET (focus));
-
-  priv = provider->priv;
-
-  if (priv->focus)
-    {
-      g_object_remove_weak_pointer (G_OBJECT (priv->focus),
-                                    (gpointer *)&priv->focus);
-      priv->focus = NULL;
-    }
-
-  if (focus)
-    {
-      priv->focus = focus;
-      g_object_add_weak_pointer (G_OBJECT (priv->focus),
-                                 (gpointer *)&priv->focus);
-    }
-}
-
-static void
-on_workbench_set_focus (GbCommandGactionProvider *provider,
-                        GtkWidget                *widget,
-                        GbWorkbench              *workbench)
-{
-  GtkWidget *parent = widget;
-
-  g_return_if_fail (GB_IS_COMMAND_GACTION_PROVIDER (provider));
-  g_return_if_fail (GTK_IS_WIDGET (widget));
-
-  /*
-   * Try to locate the nearest GbTab in the widget hierarchy starting from
-   * the new focus widget. If this widget is not a decendent of a tab, we
-   * will just ignore things.
-   */
-  while (!GB_IS_TAB (parent))
-    {
-      parent = gtk_widget_get_parent (parent);
-      if (!parent)
-        break;
-    }
-
-  if (GB_IS_TAB (parent))
-    gb_command_gaction_provider_update_focus (provider, parent);
-}
-
-static void
-gb_command_gaction_provider_connect (GbCommandGactionProvider *provider,
-                                     GbWorkbench              *workbench)
-{
-  g_return_if_fail (GB_IS_COMMAND_GACTION_PROVIDER (provider));
-  g_return_if_fail (GB_IS_WORKBENCH (workbench));
-
-  g_signal_connect_object (workbench,
-                           "set-focus",
-                           G_CALLBACK (on_workbench_set_focus),
-                           provider,
-                           G_CONNECT_SWAPPED);
-}
-
-static void
-gb_command_gaction_provider_disconnect (GbCommandGactionProvider *provider,
-                                        GbWorkbench              *workbench)
-{
-  g_return_if_fail (GB_IS_COMMAND_GACTION_PROVIDER (provider));
-  g_return_if_fail (GB_IS_WORKBENCH (workbench));
-
-  g_signal_handlers_disconnect_by_func (workbench,
-                                        G_CALLBACK (on_workbench_set_focus),
-                                        provider);
-}
-
-void
-gb_command_gaction_provider_set_workbench (GbCommandGactionProvider *provider,
-                                           GbWorkbench              *workbench)
-{
-  GbCommandGactionProviderPrivate *priv;
-
-  g_return_if_fail (GB_IS_COMMAND_GACTION_PROVIDER (provider));
-  g_return_if_fail (!workbench || GB_IS_WORKBENCH (workbench));
-
-  priv = provider->priv;
-
-  if (workbench != priv->workbench)
-    {
-      if (priv->workbench)
-        {
-          gb_command_gaction_provider_disconnect (provider, workbench);
-          g_object_remove_weak_pointer (G_OBJECT (priv->workbench),
-                                        (gpointer *)&priv->workbench);
-          priv->workbench = NULL;
-        }
-
-      if (workbench)
-        {
-          gb_command_gaction_provider_connect (provider, workbench);
-          priv->workbench = workbench;
-          g_object_add_weak_pointer (G_OBJECT (workbench),
-                                     (gpointer *)&priv->workbench);
-        }
-
-      g_object_notify_by_pspec (G_OBJECT (provider),
-                                gParamSpecs [PROP_WORKBENCH]);
-    }
-}
-
 static GAction *
 gb_command_gaction_provider_lookup (GbCommandProvider  *provider,
                                     const gchar        *command_text,
@@ -183,11 +46,6 @@ gb_command_gaction_provider_lookup (GbCommandProvider  *provider,
 
   g_return_val_if_fail (GB_IS_COMMAND_GACTION_PROVIDER (self), NULL);
 
-  if (!self->priv->focus)
-    return NULL;
-
-  widget = self->priv->focus;
-
   /* Determine the command name */
   tmp = g_strdelimit (g_strdup (command_text), "(", ' ');
   parts = g_strsplit (tmp, " ", 2);
@@ -222,6 +80,7 @@ gb_command_gaction_provider_lookup (GbCommandProvider  *provider,
    *       ApplicationWindow which is a GActionMap.
    */
 
+  widget = GTK_WIDGET (gb_command_provider_get_active_tab (provider));
   while (widget)
     {
       if (G_IS_ACTION_MAP (widget))
@@ -234,6 +93,18 @@ gb_command_gaction_provider_lookup (GbCommandProvider  *provider,
       widget = gtk_widget_get_parent (widget);
     }
 
+  /*
+   * Now try to lookup the action inside of the GApplication.
+   * This is useful for stuff like "quit", and "preferences".
+   */
+  if (!action)
+    {
+      GApplication *app;
+
+      app = g_application_get_default ();
+      action = g_action_map_lookup_action (G_ACTION_MAP (app), name);
+    }
+
   if (!action && *parameters)
     {
       g_variant_unref (*parameters);
@@ -243,85 +114,18 @@ gb_command_gaction_provider_lookup (GbCommandProvider  *provider,
 cleanup:
   g_free (name);
 
-  return action;
-}
-
-static void
-gb_command_gaction_provider_dispose (GObject *object)
-{
-  GbCommandGactionProvider *provider = (GbCommandGactionProvider *)object;
-
-  gb_command_gaction_provider_update_focus (provider, NULL);
-  gb_command_gaction_provider_set_workbench (provider, NULL);
-
-  G_OBJECT_CLASS (gb_command_gaction_provider_parent_class)->dispose (object);
-}
-
-static void
-gb_command_gaction_provider_get_property (GObject    *object,
-                                          guint       prop_id,
-                                          GValue     *value,
-                                          GParamSpec *pspec)
-{
-  GbCommandGactionProvider *self = GB_COMMAND_GACTION_PROVIDER (object);
-
-  switch (prop_id)
-    {
-    case PROP_WORKBENCH:
-      g_value_set_object (value,
-                          gb_command_gaction_provider_get_workbench (self));
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-    }
-}
-
-static void
-gb_command_gaction_provider_set_property (GObject      *object,
-                                          guint         prop_id,
-                                          const GValue *value,
-                                          GParamSpec   *pspec)
-{
-  GbCommandGactionProvider *self = GB_COMMAND_GACTION_PROVIDER (object);
-
-  switch (prop_id)
-    {
-    case PROP_WORKBENCH:
-      gb_command_gaction_provider_set_workbench (self,
-                                                 g_value_get_object (value));
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-    }
+  return action ? g_object_ref (action) : NULL;
 }
 
 static void
 gb_command_gaction_provider_class_init (GbCommandGactionProviderClass *klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GbCommandProviderClass *provider_class = GB_COMMAND_PROVIDER_CLASS (klass);
 
-  object_class->dispose = gb_command_gaction_provider_dispose;
-  object_class->get_property = gb_command_gaction_provider_get_property;
-  object_class->set_property = gb_command_gaction_provider_set_property;
-
   provider_class->lookup = gb_command_gaction_provider_lookup;
-
-  gParamSpecs [PROP_WORKBENCH] =
-    g_param_spec_object ("workbench",
-                         _("Workbench"),
-                         _("The workbench containing the actions."),
-                         GB_TYPE_WORKBENCH,
-                         (G_PARAM_READWRITE |
-                          G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (object_class, PROP_WORKBENCH,
-                                   gParamSpecs [PROP_WORKBENCH]);
 }
 
 static void
 gb_command_gaction_provider_init (GbCommandGactionProvider *self)
 {
-  self->priv = gb_command_gaction_provider_get_instance_private (self);
 }
diff --git a/src/commands/gb-command-gaction-provider.h b/src/commands/gb-command-gaction-provider.h
index d7dc040..622700d 100644
--- a/src/commands/gb-command-gaction-provider.h
+++ b/src/commands/gb-command-gaction-provider.h
@@ -20,7 +20,6 @@
 #define GB_COMMAND_GACTION_PROVIDER_H
 
 #include "gb-command-provider.h"
-#include "gb-workbench.h"
 
 G_BEGIN_DECLS
 
diff --git a/src/commands/gb-command-provider.c b/src/commands/gb-command-provider.c
index c7ff6bd..575d85f 100644
--- a/src/commands/gb-command-provider.c
+++ b/src/commands/gb-command-provider.c
@@ -22,7 +22,9 @@
 
 struct _GbCommandProviderPrivate
 {
-  gint priority;
+  GbWorkbench *workbench;
+  GbTab       *active_tab;
+  gint         priority;
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (GbCommandProvider, gb_command_provider,
@@ -30,7 +32,9 @@ G_DEFINE_TYPE_WITH_PRIVATE (GbCommandProvider, gb_command_provider,
 
 enum {
   PROP_0,
+  PROP_ACTIVE_TAB,
   PROP_PRIORITY,
+  PROP_WORKBENCH,
   LAST_PROP
 };
 
@@ -43,9 +47,143 @@ static GParamSpec *gParamSpecs [LAST_PROP];
 static guint gSignals [LAST_SIGNAL];
 
 GbCommandProvider *
-gb_command_provider_new (void)
+gb_command_provider_new (GbWorkbench *workbench)
 {
-  return g_object_new (GB_TYPE_COMMAND_PROVIDER, NULL);
+  return g_object_new (GB_TYPE_COMMAND_PROVIDER,
+                       "workbench", workbench,
+                       NULL);
+}
+
+/**
+ * gb_command_provider_get_active_tab:
+ *
+ * Returns the "active-tab" property. The active-tab is the last tab that
+ * was focused in the workbench.
+ *
+ * Returns: (transfer none): A #GbTab or %NULL.
+ */
+GbTab *
+gb_command_provider_get_active_tab (GbCommandProvider *provider)
+{
+  g_return_val_if_fail (GB_IS_COMMAND_PROVIDER (provider), NULL);
+
+  return provider->priv->active_tab;
+}
+
+static void
+gb_command_provider_set_active_tab (GbCommandProvider *provider,
+                                    GbTab             *tab)
+{
+  GbCommandProviderPrivate *priv;
+
+  g_return_if_fail (GB_IS_COMMAND_PROVIDER (provider));
+  g_return_if_fail (!tab || GB_IS_TAB (tab));
+
+  priv = provider->priv;
+
+  if (priv->active_tab)
+    {
+      g_object_remove_weak_pointer (G_OBJECT (priv->active_tab),
+                                    (gpointer *)&priv->active_tab);
+      priv->active_tab = NULL;
+    }
+
+  if (tab)
+    {
+      priv->active_tab = tab;
+      g_object_add_weak_pointer (G_OBJECT (priv->active_tab),
+                                 (gpointer *)&priv->active_tab);
+    }
+
+  g_object_notify_by_pspec (G_OBJECT (provider),
+                            gParamSpecs [PROP_ACTIVE_TAB]);
+}
+
+static void
+on_workbench_set_focus (GbCommandProvider *provider,
+                        GtkWidget         *widget,
+                        GbWorkbench       *workbench)
+{
+  g_return_if_fail (GB_IS_COMMAND_PROVIDER (provider));
+  g_return_if_fail (GB_IS_WORKBENCH (workbench));
+  g_return_if_fail (!widget || GTK_IS_WIDGET (widget));
+
+  /* walk the hierarchy to find a tab */
+  if (widget)
+    while (!GB_IS_TAB (widget))
+      if (!(widget = gtk_widget_get_parent (widget)))
+        break;
+
+  if (GB_IS_TAB (widget))
+    gb_command_provider_set_active_tab (provider, GB_TAB (widget));
+}
+
+static void
+gb_command_provider_connect (GbCommandProvider *provider,
+                             GbWorkbench       *workbench)
+{
+  g_return_if_fail (GB_IS_COMMAND_PROVIDER (provider));
+  g_return_if_fail (GB_IS_WORKBENCH (workbench));
+
+  g_signal_connect_object (workbench,
+                           "set-focus",
+                           G_CALLBACK (on_workbench_set_focus),
+                           provider,
+                           G_CONNECT_SWAPPED);
+}
+
+static void
+gb_command_provider_disconnect (GbCommandProvider *provider,
+                                GbWorkbench       *workbench)
+{
+  g_return_if_fail (GB_IS_COMMAND_PROVIDER (provider));
+  g_return_if_fail (GB_IS_WORKBENCH (workbench));
+
+  g_signal_handlers_disconnect_by_func (workbench,
+                                        G_CALLBACK (on_workbench_set_focus),
+                                        provider);
+}
+
+GbWorkbench *
+gb_command_provider_get_workbench (GbCommandProvider *provider)
+{
+  g_return_val_if_fail (GB_IS_COMMAND_PROVIDER (provider), NULL);
+
+  return provider->priv->workbench;
+}
+
+static void
+gb_command_provider_set_workbench (GbCommandProvider *provider,
+                                   GbWorkbench       *workbench)
+{
+  GbCommandProviderPrivate *priv;
+
+  g_return_if_fail (GB_IS_COMMAND_PROVIDER (provider));
+  g_return_if_fail (!workbench || GB_IS_WORKBENCH (workbench));
+
+  priv = provider->priv;
+
+  if (priv->workbench != workbench)
+    {
+      if (priv->workbench)
+        {
+          gb_command_provider_disconnect (provider, workbench);
+          g_object_remove_weak_pointer (G_OBJECT (priv->workbench),
+                                        (gpointer *)&priv->workbench);
+          priv->workbench = NULL;
+        }
+    
+      if (workbench)
+        {
+          priv->workbench = workbench;
+          g_object_add_weak_pointer (G_OBJECT (priv->workbench),
+                                     (gpointer *)&priv->workbench);
+          gb_command_provider_connect (provider, workbench);
+        }
+    
+      g_object_notify_by_pspec (G_OBJECT (provider),
+                                gParamSpecs [PROP_WORKBENCH]);
+  }
 }
 
 gint
@@ -70,6 +208,19 @@ gb_command_provider_set_priority (GbCommandProvider *provider,
     }
 }
 
+/**
+ * gb_command_provider_lookup:
+ * @provider: (in): The #GbCommandProvider
+ * @command_text: (in): Command text to be parsed
+ * @parameter: (allow-none) (out): location for a resulting #GVariant parameter
+ *
+ * This function causes the provider to attept to parse @command_text and
+ * generate a GAction to execute the command. If the @command_text could not
+ * be parsed, then %NULL is returned.
+ *
+ * Returns: (transfer full): A #GAction that should be freed with
+ *   g_object_unref().
+ */
 GAction *
 gb_command_provider_lookup (GbCommandProvider  *provider,
                             const gchar        *command_text,
@@ -98,10 +249,18 @@ gb_command_provider_get_property (GObject    *object,
 
   switch (prop_id)
     {
+    case PROP_ACTIVE_TAB:
+      g_value_set_object (value, gb_command_provider_get_active_tab (self));
+      break;
+
     case PROP_PRIORITY:
       g_value_set_int (value, gb_command_provider_get_priority (self));
       break;
 
+    case PROP_WORKBENCH:
+      g_value_set_object (value, gb_command_provider_get_workbench (self));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -121,6 +280,10 @@ gb_command_provider_set_property (GObject      *object,
       gb_command_provider_set_priority (self, g_value_get_int (value));
       break;
 
+    case PROP_WORKBENCH:
+      gb_command_provider_set_workbench (self, g_value_get_object (value));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -134,6 +297,16 @@ gb_command_provider_class_init (GbCommandProviderClass *klass)
   object_class->get_property = gb_command_provider_get_property;
   object_class->set_property = gb_command_provider_set_property;
 
+  gParamSpecs [PROP_ACTIVE_TAB] =
+    g_param_spec_object ("active-tab",
+                         _("Active Tab"),
+                         _("The last focused GbTab widget."),
+                         GB_TYPE_TAB,
+                         (G_PARAM_READABLE |
+                          G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (object_class, PROP_ACTIVE_TAB,
+                                   gParamSpecs [PROP_ACTIVE_TAB]);
+
   /**
    * GbCommandProvider:priority:
    *
@@ -158,6 +331,24 @@ gb_command_provider_class_init (GbCommandProviderClass *klass)
                                    gParamSpecs [PROP_PRIORITY]);
 
   /**
+   * GbCommandProvider:workbench:
+   * 
+   * The "workbench" property is the top-level window containing our project
+   * and the workbench to work on it. It keeps track of the last focused tab
+   * for convenience by action providers.
+   */
+  gParamSpecs [PROP_WORKBENCH] =
+    g_param_spec_object ("workbench",
+                         _("Workbench"),
+                         _("The target workbench."),
+                         GB_TYPE_WORKBENCH,
+                         (G_PARAM_READWRITE |
+                          G_PARAM_CONSTRUCT_ONLY |
+                          G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (object_class, PROP_WORKBENCH,
+                                   gParamSpecs [PROP_WORKBENCH]);
+
+  /**
    * GbCommandProvider::lookup:
    * @command_text: (in): the command line text to be processed.
    * @parameter: (out): a location to store any parsed parameters.
diff --git a/src/commands/gb-command-provider.h b/src/commands/gb-command-provider.h
index 3540530..2398515 100644
--- a/src/commands/gb-command-provider.h
+++ b/src/commands/gb-command-provider.h
@@ -21,6 +21,9 @@
 
 #include <gio/gio.h>
 
+#include "gb-tab.h"
+#include "gb-workbench.h"
+
 G_BEGIN_DECLS
 
 #define GB_TYPE_COMMAND_PROVIDER            (gb_command_provider_get_type())
@@ -58,14 +61,16 @@ struct _GbCommandProviderClass
   gpointer _padding5;
 };
 
-GType              gb_command_provider_get_type     (void) G_GNUC_CONST;
-GbCommandProvider *gb_command_provider_new          (void);
-gint               gb_command_provider_get_priority (GbCommandProvider  *provider);
-void               gb_command_provider_set_priority (GbCommandProvider  *provider,
-                                                     gint                priority);
-GAction           *gb_command_provider_lookup       (GbCommandProvider  *provider,
-                                                     const gchar        *command_text,
-                                                     GVariant          **parameters);
+GType              gb_command_provider_get_type       (void) G_GNUC_CONST;
+GbCommandProvider *gb_command_provider_new            (GbWorkbench        *workbench);
+GbWorkbench       *gb_command_provider_get_workbench  (GbCommandProvider  *provider);
+GbTab             *gb_command_provider_get_active_tab (GbCommandProvider  *provider);
+gint               gb_command_provider_get_priority   (GbCommandProvider  *provider);
+void               gb_command_provider_set_priority   (GbCommandProvider  *provider,
+                                                       gint                priority);
+GAction           *gb_command_provider_lookup         (GbCommandProvider  *provider,
+                                                       const gchar        *command_text,
+                                                       GVariant          **parameters);
 
 G_END_DECLS
 


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