[gimp/wip/gum-lang] app: add ui_meta keys for controlling some ui properties dynamically



commit 4cce512699601ca6e12bb0c272f2b0287b93163d
Author: Ell <ell_se yahoo com>
Date:   Sun Apr 30 16:07:38 2017 -0400

    app: add ui_meta keys for controlling some ui properties dynamically
    
    Add support for the "sensitive", "visible", "label", and "description"
    property keys for gegl ops.
    
    The "sensitive" and "visible" keys should be boolean GUM expressions,
    and the "label" and "description" keys should be string GUM
    expressions, controlling the sensitivity, visibility, label, and tool-
    tip of the corresponding prop gui widget, respectively.

 app/widgets/gimppropgui-constructors.c |    8 ++
 app/widgets/gimppropgui.c              |  189 +++++++++++++++++++++++++++-----
 app/widgets/gimppropgui.h              |    4 +
 3 files changed, 174 insertions(+), 27 deletions(-)
---
diff --git a/app/widgets/gimppropgui-constructors.c b/app/widgets/gimppropgui-constructors.c
index 6f786b6..a7a8b7c 100644
--- a/app/widgets/gimppropgui-constructors.c
+++ b/app/widgets/gimppropgui-constructors.c
@@ -119,6 +119,8 @@ _gimp_prop_gui_new_generic (GObject              *config,
           gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
           gtk_widget_show (hbox);
 
+          gimp_prop_gui_bind_container (widget_x, hbox);
+
           vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
           gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
           gtk_widget_show (vbox);
@@ -199,6 +201,8 @@ _gimp_prop_gui_new_generic (GObject              *config,
               gtk_label_set_xalign (GTK_LABEL (l), 0.0);
               gtk_widget_show (l);
 
+              gimp_prop_gui_bind_label (widget, l);
+
               if (GTK_IS_SCROLLED_WINDOW (widget))
                 {
                   GtkWidget *frame;
@@ -212,6 +216,8 @@ _gimp_prop_gui_new_generic (GObject              *config,
 
                   gtk_container_add (GTK_CONTAINER (frame), widget);
                   gtk_widget_show (widget);
+
+                  gimp_prop_gui_bind_container (widget, frame);
                 }
               else
                 {
@@ -227,6 +233,8 @@ _gimp_prop_gui_new_generic (GObject              *config,
 
                   gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
                   gtk_widget_show (widget);
+
+                  gimp_prop_gui_bind_container (widget, hbox);
                 }
             }
           else if (widget)
diff --git a/app/widgets/gimppropgui.c b/app/widgets/gimppropgui.c
index e147e16..24156a4 100644
--- a/app/widgets/gimppropgui.c
+++ b/app/widgets/gimppropgui.c
@@ -44,6 +44,7 @@
 #include "gimpspinscale.h"
 #include "gimppropgui.h"
 #include "gimppropgui-constructors.h"
+#include "gimppropgui-eval.h"
 #include "gimppropwidgets.h"
 #include "gimpwidgets-utils.h"
 
@@ -53,14 +54,19 @@
 #define HAS_KEY(p,k,v) gimp_gegl_param_spec_has_key (p, k, v)
 
 
-static GtkWidget * gimp_prop_kelvin_presets_new      (GObject       *config,
-                                                      const gchar   *property_name);
-static void        gimp_prop_widget_new_seed_clicked (GtkButton     *button,
-                                                      GtkAdjustment *adj);
-static gboolean    gimp_prop_string_to_boolean       (GBinding      *binding,
-                                                      const GValue  *from_value,
-                                                      GValue        *to_value,
-                                                      gpointer       user_data);
+static GtkWidget   * gimp_prop_kelvin_presets_new      (GObject        *config,
+                                                        const gchar    *property_name);
+static void          gimp_prop_widget_new_seed_clicked (GtkButton      *button,
+                                                        GtkAdjustment  *adj);
+static gboolean      gimp_prop_string_to_boolean       (GBinding       *binding,
+                                                        const GValue   *from_value,
+                                                        GValue         *to_value,
+                                                        gpointer        user_data);
+static void          gimp_prop_config_notify           (GObject        *config,
+                                                        GParamSpec     *pspec,
+                                                        GtkWidget      *widget);
+static void          gimp_prop_widget_show             (GtkWidget      *widget,
+                                                        GObject        *config);
 
 /*  public functions  */
 
@@ -213,6 +219,8 @@ gimp_prop_widget_new_from_pspec (GObject               *config,
           gtk_box_pack_start (GTK_BOX (hbox), dial, FALSE, FALSE, 0);
           gtk_widget_show (dial);
 
+          gimp_prop_gui_bind_label (hbox, widget);
+
           widget = hbox;
         }
       else if (HAS_KEY (pspec, "unit", "kelvin"))
@@ -229,30 +237,39 @@ gimp_prop_widget_new_from_pspec (GObject               *config,
           gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
           gtk_widget_show (button);
 
+          gimp_prop_gui_bind_label (hbox, widget);
+
           widget = hbox;
         }
-      else if (area)
+      else
         {
-          if (HAS_KEY (pspec, "unit", "pixel-coordinate") ||
-              HAS_KEY (pspec, "unit", "pixel-distance"))
-            {
-              if (HAS_KEY (pspec, "axis", "x"))
-                {
-                  g_printerr ("XXX setting width %d on %s\n",
-                              area->width, pspec->name);
+          g_object_bind_property (widget, "name",
+                                  widget, "label",
+                                  G_BINDING_DEFAULT);
 
-                  gimp_spin_scale_set_scale_limits (GIMP_SPIN_SCALE (widget),
-                                                    area->x,
-                                                    area->x + area->width);
-                }
-              else if (HAS_KEY (pspec, "axis","y"))
+          if (area)
+            {
+              if (HAS_KEY (pspec, "unit", "pixel-coordinate") ||
+                  HAS_KEY (pspec, "unit", "pixel-distance"))
                 {
-                  g_printerr ("XXX setting height %d on %s\n",
-                              area->height, pspec->name);
-
-                  gimp_spin_scale_set_scale_limits (GIMP_SPIN_SCALE (widget),
-                                                    area->y,
-                                                    area->y + area->height);
+                  if (HAS_KEY (pspec, "axis", "x"))
+                    {
+                      g_printerr ("XXX setting width %d on %s\n",
+                                  area->width, pspec->name);
+
+                      gimp_spin_scale_set_scale_limits (GIMP_SPIN_SCALE (widget),
+                                                        area->x,
+                                                        area->x + area->width);
+                    }
+                  else if (HAS_KEY (pspec, "axis","y"))
+                    {
+                      g_printerr ("XXX setting height %d on %s\n",
+                                  area->height, pspec->name);
+
+                      gimp_spin_scale_set_scale_limits (GIMP_SPIN_SCALE (widget),
+                                                        area->y,
+                                                        area->y + area->height);
+                    }
                 }
             }
         }
@@ -316,12 +333,20 @@ gimp_prop_widget_new_from_pspec (GObject               *config,
     {
       widget = gimp_prop_check_button_new (config, pspec->name,
                                            g_param_spec_get_nick (pspec));
+
+      g_object_bind_property (widget, "name",
+                              widget, "label",
+                              G_BINDING_DEFAULT);
     }
   else if (G_IS_PARAM_SPEC_ENUM (pspec))
     {
       widget = gimp_prop_enum_combo_box_new (config, pspec->name, 0, 0);
       gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (widget),
                                     g_param_spec_get_nick (pspec));
+
+      g_object_bind_property (widget, "name",
+                              widget, "label",
+                              G_BINDING_DEFAULT);
     }
   else if (GIMP_IS_PARAM_SPEC_RGB (pspec))
     {
@@ -356,6 +381,43 @@ gimp_prop_widget_new_from_pspec (GObject               *config,
                  g_type_name (G_TYPE_FROM_INSTANCE (pspec)), pspec->name);
     }
 
+  /* we use the widget's "name" property to store its label, so that we can
+   * bind the label widget's "label" property to it, in
+   * gimp_prop_gui_bind_label().
+   */
+  gtk_widget_set_name (widget, g_param_spec_get_nick (pspec));
+  gimp_help_set_help_data (widget, g_param_spec_get_blurb (pspec), NULL);
+
+  /* if we have any keys for dynamic properties, listen to config's notify
+   * signal, and update the properties accordingly.
+   */
+  if (gegl_param_spec_get_property_key (pspec, "sensitive") ||
+      gegl_param_spec_get_property_key (pspec, "visible")   ||
+      gegl_param_spec_get_property_key (pspec, "label")     ||
+      gegl_param_spec_get_property_key (pspec, "description"))
+    {
+      g_object_set_data (G_OBJECT (widget), "gimp-prop-pspec", pspec);
+
+      g_signal_connect_object (config, "notify",
+                               G_CALLBACK (gimp_prop_config_notify),
+                               widget, 0);
+
+      if (gegl_param_spec_get_property_key (pspec, "visible"))
+        {
+          /* a bit of a hack: if we have a dynamic "visible" property key,
+           * connect to the widget's "show" signal, so that we can intercept
+           * our caller's gtk_widget_show() call, and keep the widget hidden if
+           * necessary.
+           */
+          g_signal_connect (widget, "show",
+                            G_CALLBACK (gimp_prop_widget_show),
+                            config);
+        }
+
+      /* update all the properties now */
+      gimp_prop_config_notify (config, NULL, widget);
+    }
+
   return widget;
 }
 
@@ -466,6 +528,30 @@ gimp_prop_gui_new (GObject              *config,
   return gui;
 }
 
+void
+gimp_prop_gui_bind_container (GtkWidget *source,
+                              GtkWidget *target)
+{
+  g_object_bind_property (source, "sensitive",
+                          target, "sensitive",
+                          G_BINDING_SYNC_CREATE);
+  g_object_bind_property (source, "visible",
+                          target, "visible",
+                          G_BINDING_SYNC_CREATE);
+}
+
+void
+gimp_prop_gui_bind_label (GtkWidget *source,
+                          GtkWidget *target)
+{
+  g_object_bind_property (source, "name",
+                          target, "label",
+                          G_BINDING_SYNC_CREATE);
+  g_object_bind_property (source, "tooltip-text",
+                          target, "tooltip-text",
+                          G_BINDING_SYNC_CREATE);
+}
+
 
 /*  private functions  */
 
@@ -607,3 +693,52 @@ gimp_prop_string_to_boolean (GBinding     *binding,
 
   return TRUE;
 }
+
+static void
+gimp_prop_config_notify (GObject    *config,
+                         GParamSpec *pspec,
+                         GtkWidget  *widget)
+{
+  GParamSpec *widget_pspec;
+  gboolean    sensitive;
+  gboolean    visible;
+  gchar      *label;
+  gchar      *description;
+
+  widget_pspec = g_object_get_data (G_OBJECT (widget), "gimp-prop-pspec");
+
+  sensitive   = gimp_prop_eval_boolean (config, widget_pspec, "sensitive", TRUE);
+  visible     = gimp_prop_eval_boolean (config, widget_pspec, "visible", TRUE);
+  label       = gimp_prop_eval_string (config, widget_pspec, "label",
+                                       g_param_spec_get_nick (widget_pspec));
+  description = gimp_prop_eval_string (config, widget_pspec, "description",
+                                       g_param_spec_get_blurb (widget_pspec));
+
+  g_signal_handlers_block_by_func (widget,
+                                   gimp_prop_widget_show, config);
+
+  gtk_widget_set_sensitive (widget, sensitive);
+  gtk_widget_set_visible (widget, visible);
+  gtk_widget_set_name (widget, label);
+  gimp_help_set_help_data (widget, description, NULL);
+
+  g_signal_handlers_unblock_by_func (widget,
+                                     gimp_prop_widget_show, config);
+
+  g_free (description);
+  g_free (label);
+}
+
+static void
+gimp_prop_widget_show (GtkWidget *widget,
+                       GObject   *config)
+{
+  GParamSpec *widget_pspec;
+  gboolean    visible;
+
+  widget_pspec = g_object_get_data (G_OBJECT (widget), "gimp-prop-pspec");
+
+  visible = gimp_prop_eval_boolean (config, widget_pspec, "visible", TRUE);
+
+  gtk_widget_set_visible (widget, visible);
+}
diff --git a/app/widgets/gimppropgui.h b/app/widgets/gimppropgui.h
index 7aebeac..627cc25 100644
--- a/app/widgets/gimppropgui.h
+++ b/app/widgets/gimppropgui.h
@@ -51,6 +51,10 @@ GtkWidget * gimp_prop_gui_new               (GObject              *config,
                                              GimpCreatePickerFunc  create_picker,
                                              gpointer              picker_creator);
 
+void        gimp_prop_gui_bind_container    (GtkWidget            *source,
+                                             GtkWidget            *target);
+void        gimp_prop_gui_bind_label        (GtkWidget            *source,
+                                             GtkWidget            *target);
 
 
 #endif /* __GIMP_PROP_GUI_H__ */


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