[gimp] libgimpwidgets: simplify gimp_scale_entry a lot by using GBindings



commit 0c2ec6ad86fb4c90661bd76334368591bdc86fce
Author: Michael Natterer <mitch gimp org>
Date:   Thu May 18 18:24:35 2017 +0200

    libgimpwidgets: simplify gimp_scale_entry a lot by using GBindings
    
    Always use separate GtkAdjustments for the scale and the spinbutton,
    and link them with a GBinding, either 1:1 or using logarithmic
    transform functions.
    
    This change also enables modifying both widgets' ranges independently
    after construction, thus enabling the "constrain" feature also for
    gimp_color_scale_entry_new().

 libgimpwidgets/gimpscaleentry.c |  281 ++++++++++++++++-----------------------
 1 files changed, 112 insertions(+), 169 deletions(-)
---
diff --git a/libgimpwidgets/gimpscaleentry.c b/libgimpwidgets/gimpscaleentry.c
index 76b92fe..764f917 100644
--- a/libgimpwidgets/gimpscaleentry.c
+++ b/libgimpwidgets/gimpscaleentry.c
@@ -31,90 +31,75 @@
 #include "gimpwidgets.h"
 
 
-static void gimp_scale_entry_unconstrained_adjustment_callback (GtkAdjustment *adjustment,
-                                                                GtkAdjustment *other_adj);
-static void gimp_scale_entry_exp_adjustment_callback           (GtkAdjustment *adjustment,
-                                                                GtkAdjustment *other_adj);
-static void gimp_scale_entry_log_adjustment_callback           (GtkAdjustment *adjustment,
-                                                                GtkAdjustment *other_adj);
-
-static GtkObject * gimp_scale_entry_new_internal               (gboolean       color_scale,
-                                                                GtkTable      *table,
-                                                                gint           column,
-                                                                gint           row,
-                                                                const gchar   *text,
-                                                                gint           scale_width,
-                                                                gint           spinbutton_width,
-                                                                gdouble        value,
-                                                                gdouble        lower,
-                                                                gdouble        upper,
-                                                                gdouble        step_increment,
-                                                                gdouble        page_increment,
-                                                                guint          digits,
-                                                                gboolean       constrain,
-                                                                gdouble        unconstrained_lower,
-                                                                gdouble        unconstrained_upper,
-                                                                const gchar   *tooltip,
-                                                                const gchar   *help_id);
-
-
-static void
-gimp_scale_entry_unconstrained_adjustment_callback (GtkAdjustment *adjustment,
-                                                    GtkAdjustment *other_adj)
+static gboolean    gimp_scale_entry_linear_to_log (GBinding     *binding,
+                                                   const GValue *from_value,
+                                                   GValue       *to_value,
+                                                   gpointer      user_data);
+static gboolean    gimp_scale_entry_log_to_linear (GBinding     *binding,
+                                                   const GValue *from_value,
+                                                   GValue       *to_value,
+                                                   gpointer      user_data);
+
+static GtkObject * gimp_scale_entry_new_internal  (gboolean      color_scale,
+                                                   GtkTable     *table,
+                                                   gint          column,
+                                                   gint          row,
+                                                   const gchar  *text,
+                                                   gint          scale_width,
+                                                   gint          spinbutton_width,
+                                                   gdouble       value,
+                                                   gdouble       lower,
+                                                   gdouble       upper,
+                                                   gdouble       step_increment,
+                                                   gdouble       page_increment,
+                                                   guint         digits,
+                                                   gboolean      constrain,
+                                                   gdouble       unconstrained_lower,
+                                                   gdouble       unconstrained_upper,
+                                                   const gchar  *tooltip,
+                                                   const gchar  *help_id);
+
+
+static gboolean
+gimp_scale_entry_linear_to_log (GBinding     *binding,
+                                const GValue *from_value,
+                                GValue       *to_value,
+                                gpointer      user_data)
 {
-  g_signal_handlers_block_by_func (other_adj,
-                                   gimp_scale_entry_unconstrained_adjustment_callback,
-                                   adjustment);
+  GtkAdjustment *spin_adjustment;
+  gdouble        value = g_value_get_double (from_value);
 
-  gtk_adjustment_set_value (other_adj, gtk_adjustment_get_value (adjustment));
+  spin_adjustment = GTK_ADJUSTMENT (g_binding_get_source (binding));
 
-  g_signal_handlers_unblock_by_func (other_adj,
-                                     gimp_scale_entry_unconstrained_adjustment_callback,
-                                     adjustment);
-}
-
-static void
-gimp_scale_entry_log_adjustment_callback (GtkAdjustment *adjustment,
-                                          GtkAdjustment *other_adj)
-{
-  gdouble value;
-
-  g_signal_handlers_block_by_func (other_adj,
-                                   gimp_scale_entry_exp_adjustment_callback,
-                                   adjustment);
-
-  if (gtk_adjustment_get_lower (adjustment) <= 0.0)
-    value = log (gtk_adjustment_get_value (adjustment) -
-                 gtk_adjustment_get_lower (adjustment) + 0.1);
+  if (gtk_adjustment_get_lower (spin_adjustment) <= 0.0)
+    value = log (value - gtk_adjustment_get_lower (spin_adjustment) + 0.1);
   else
-    value = log (gtk_adjustment_get_value (adjustment));
+    value = log (value);
 
-  gtk_adjustment_set_value (other_adj, value);
+  g_value_set_double (to_value, value);
 
-  g_signal_handlers_unblock_by_func (other_adj,
-                                     gimp_scale_entry_exp_adjustment_callback,
-                                     adjustment);
+  return TRUE;
 }
 
-static void
-gimp_scale_entry_exp_adjustment_callback (GtkAdjustment *adjustment,
-                                          GtkAdjustment *other_adj)
+static gboolean
+gimp_scale_entry_log_to_linear (GBinding     *binding,
+                                const GValue *from_value,
+                                GValue       *to_value,
+                                gpointer      user_data)
 {
-  gdouble value;
+  GtkAdjustment *spin_adjustment;
+  gdouble        value = g_value_get_double (from_value);
 
-  g_signal_handlers_block_by_func (other_adj,
-                                   gimp_scale_entry_log_adjustment_callback,
-                                   adjustment);
+  spin_adjustment = GTK_ADJUSTMENT (g_binding_get_target (binding));
 
-  value = exp (gtk_adjustment_get_value (adjustment));
-  if (gtk_adjustment_get_lower (other_adj) <= 0.0)
-    value += gtk_adjustment_get_lower (other_adj) - 0.1;
+  value = exp (value);
 
-  gtk_adjustment_set_value (other_adj, value);
+  if (gtk_adjustment_get_lower (spin_adjustment) <= 0.0)
+    value += gtk_adjustment_get_lower (spin_adjustment) - 0.1;
 
-  g_signal_handlers_unblock_by_func (other_adj,
-                                     gimp_scale_entry_log_adjustment_callback,
-                                     adjustment);
+  g_value_set_double (to_value, value);
+
+  return TRUE;
 }
 
 static GtkObject *
@@ -140,8 +125,9 @@ gimp_scale_entry_new_internal (gboolean     color_scale,
   GtkWidget     *label;
   GtkWidget     *scale;
   GtkWidget     *spinbutton;
-  GtkAdjustment *adjustment;
-  GtkAdjustment *return_adj;
+  GtkAdjustment *scale_adjustment;
+  GtkAdjustment *spin_adjustment;
+  GBinding      *binding;
 
   label = gtk_label_new_with_mnemonic (text);
   gtk_label_set_xalign (GTK_LABEL (label), 0.0);
@@ -150,50 +136,35 @@ gimp_scale_entry_new_internal (gboolean     color_scale,
                     GTK_FILL, GTK_FILL, 0, 0);
   gtk_widget_show (label);
 
+  scale_adjustment = (GtkAdjustment *)
+    gtk_adjustment_new (value, lower, upper,
+                        step_increment, page_increment, 0.0);
+
   if (! constrain &&
       unconstrained_lower <= lower &&
       unconstrained_upper >= upper)
     {
-      GtkAdjustment *constrained_adj;
-
-      constrained_adj = (GtkAdjustment *)
-        gtk_adjustment_new (value, lower, upper,
-                            step_increment, page_increment,
-                            0.0);
-
-      adjustment = (GtkAdjustment *)
+      spin_adjustment = (GtkAdjustment *)
         gtk_adjustment_new (value,
                             unconstrained_lower,
                             unconstrained_upper,
                             step_increment, page_increment, 0.0);
-      spinbutton = gtk_spin_button_new (adjustment, step_increment, digits);
-      gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
-
-      g_signal_connect
-        (constrained_adj, "value-changed",
-         G_CALLBACK (gimp_scale_entry_unconstrained_adjustment_callback),
-         adjustment);
-
-      g_signal_connect
-        (adjustment, "value-changed",
-         G_CALLBACK (gimp_scale_entry_unconstrained_adjustment_callback),
-         constrained_adj);
-
-      return_adj = adjustment;
-
-      adjustment = constrained_adj;
     }
   else
     {
-      adjustment = (GtkAdjustment *)
+      spin_adjustment = (GtkAdjustment *)
         gtk_adjustment_new (value, lower, upper,
                             step_increment, page_increment, 0.0);
-      spinbutton = gtk_spin_button_new (adjustment, step_increment, digits);
-      gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
-
-      return_adj = adjustment;
     }
 
+  binding = g_object_bind_property (G_OBJECT (spin_adjustment),  "value",
+                                    G_OBJECT (scale_adjustment), "value",
+                                    G_BINDING_BIDIRECTIONAL |
+                                    G_BINDING_SYNC_CREATE);
+
+  spinbutton = gtk_spin_button_new (spin_adjustment, step_increment, digits);
+  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
+
   gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
 
   if (spinbutton_width > 0)
@@ -209,11 +180,11 @@ gimp_scale_entry_new_internal (gboolean     color_scale,
       scale = gimp_color_scale_new (GTK_ORIENTATION_HORIZONTAL,
                                     GIMP_COLOR_SELECTOR_VALUE);
 
-      gtk_range_set_adjustment (GTK_RANGE (scale), adjustment);
+      gtk_range_set_adjustment (GTK_RANGE (scale), scale_adjustment);
     }
   else
     {
-      scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, adjustment);
+      scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, scale_adjustment);
     }
 
   if (scale_width > 0)
@@ -237,11 +208,12 @@ gimp_scale_entry_new_internal (gboolean     color_scale,
       gimp_help_set_help_data (spinbutton, tooltip, help_id);
     }
 
-  g_object_set_data (G_OBJECT (return_adj), "label",      label);
-  g_object_set_data (G_OBJECT (return_adj), "scale",      scale);
-  g_object_set_data (G_OBJECT (return_adj), "spinbutton", spinbutton);
+  g_object_set_data (G_OBJECT (spin_adjustment), "label",      label);
+  g_object_set_data (G_OBJECT (spin_adjustment), "scale",      scale);
+  g_object_set_data (G_OBJECT (spin_adjustment), "spinbutton", spinbutton);
+  g_object_set_data (G_OBJECT (spin_adjustment), "binding",    binding);
 
-  return GTK_OBJECT (return_adj);
+  return GTK_OBJECT (spin_adjustment);
 }
 
 /**
@@ -370,17 +342,26 @@ void
 gimp_scale_entry_set_logarithmic (GtkObject *adjustment,
                                   gboolean   logarithmic)
 {
-  GtkAdjustment *adj;
+  GtkAdjustment *spin_adj;
   GtkAdjustment *scale_adj;
+  GBinding      *binding;
 
   g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
 
-  adj       = GTK_ADJUSTMENT (adjustment);
+  spin_adj  = GTK_ADJUSTMENT (adjustment);
   scale_adj = GIMP_SCALE_ENTRY_SCALE_ADJ (adjustment);
+  binding   = g_object_get_data (G_OBJECT (adjustment), "binding");
+
+  g_return_if_fail (GTK_IS_ADJUSTMENT (scale_adj));
+  g_return_if_fail (G_IS_BINDING (binding));
+
+  logarithmic = logarithmic ? TRUE : FALSE;
 
   if (logarithmic == gimp_scale_entry_get_logarithmic (adjustment))
     return;
 
+  g_object_unref (binding);
+
   if (logarithmic)
     {
       gdouble correction;
@@ -402,86 +383,48 @@ gimp_scale_entry_set_logarithmic (GtkObject *adjustment,
                                     gtk_adjustment_get_lower (scale_adj)) /
                                    gtk_adjustment_get_page_increment (scale_adj));
 
-      if (scale_adj == adj)
-        {
-          GtkObject *new_adj;
-
-          new_adj = gtk_adjustment_new (gtk_adjustment_get_value (scale_adj),
-                                        gtk_adjustment_get_lower (scale_adj),
-                                        gtk_adjustment_get_upper (scale_adj),
-                                        gtk_adjustment_get_step_increment (scale_adj),
-                                        gtk_adjustment_get_page_increment (scale_adj),
-                                        0.0);
-          gtk_range_set_adjustment (GTK_RANGE (GIMP_SCALE_ENTRY_SCALE (adj)),
-                                    GTK_ADJUSTMENT (new_adj));
-
-          scale_adj = (GtkAdjustment *) new_adj;
-        }
-      else
-        {
-          g_signal_handlers_disconnect_by_func (adj,
-                                                gimp_scale_entry_unconstrained_adjustment_callback,
-                                                scale_adj);
-
-          g_signal_handlers_disconnect_by_func (scale_adj,
-                                                gimp_scale_entry_unconstrained_adjustment_callback,
-                                                adj);
-        }
-
       gtk_adjustment_configure (scale_adj,
                                 log_value, log_lower, log_upper,
                                 log_step_increment, log_page_increment, 0.0);
 
-      g_signal_connect (scale_adj, "value-changed",
-                        G_CALLBACK (gimp_scale_entry_exp_adjustment_callback),
-                        adj);
-
-      g_signal_connect (adj, "value-changed",
-                        G_CALLBACK (gimp_scale_entry_log_adjustment_callback),
-                        scale_adj);
-
-      g_object_set_data (G_OBJECT (adjustment),
-                         "logarithmic", GINT_TO_POINTER (TRUE));
+      binding = g_object_bind_property_full (G_OBJECT (spin_adj),  "value",
+                                             G_OBJECT (scale_adj), "value",
+                                             G_BINDING_BIDIRECTIONAL |
+                                             G_BINDING_SYNC_CREATE,
+                                             gimp_scale_entry_linear_to_log,
+                                             gimp_scale_entry_log_to_linear,
+                                             NULL, NULL);
     }
   else
     {
       gdouble lower, upper;
 
-      g_signal_handlers_disconnect_by_func (adj,
-                                            gimp_scale_entry_log_adjustment_callback,
-                                            scale_adj);
-
-      g_signal_handlers_disconnect_by_func (scale_adj,
-                                            gimp_scale_entry_exp_adjustment_callback,
-                                            adj);
-
       lower = exp (gtk_adjustment_get_lower (scale_adj));
       upper = exp (gtk_adjustment_get_upper (scale_adj));
 
-      if (gtk_adjustment_get_lower (adj) <= 0.0)
+      if (gtk_adjustment_get_lower (spin_adj) <= 0.0)
         {
-          lower += - 0.1 + gtk_adjustment_get_lower (adj);
-          upper += - 0.1 + gtk_adjustment_get_lower (adj);
+          lower += - 0.1 + gtk_adjustment_get_lower (spin_adj);
+          upper += - 0.1 + gtk_adjustment_get_lower (spin_adj);
         }
 
       gtk_adjustment_configure (scale_adj,
-                                gtk_adjustment_get_value (adj),
+                                gtk_adjustment_get_value (spin_adj),
                                 lower, upper,
-                                gtk_adjustment_get_step_increment (adj),
-                                gtk_adjustment_get_page_increment (adj),
+                                gtk_adjustment_get_step_increment (spin_adj),
+                                gtk_adjustment_get_page_increment (spin_adj),
                                 0.0);
 
-      g_signal_connect (scale_adj, "value-changed",
-                        G_CALLBACK (gimp_scale_entry_unconstrained_adjustment_callback),
-                        adj);
+      binding = g_object_bind_property (G_OBJECT (spin_adj),  "value",
+                                        G_OBJECT (scale_adj), "value",
+                                        G_BINDING_BIDIRECTIONAL |
+                                        G_BINDING_SYNC_CREATE);
+    }
 
-      g_signal_connect (adj, "value-changed",
-                        G_CALLBACK (gimp_scale_entry_unconstrained_adjustment_callback),
-                        scale_adj);
+  g_object_set_data (G_OBJECT (spin_adj), "binding", binding);
 
-      g_object_set_data (G_OBJECT (adjustment),
-                         "logarithmic", GINT_TO_POINTER (FALSE));
-    }
+  g_object_set_data (G_OBJECT (adjustment), "logarithmic",
+                     GINT_TO_POINTER (logarithmic));
 }
 
 /**


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