[gimp] libgimp, libgimpbase, libgimpwidgets: new gimp_range_estimate_settings()



commit 8d5008d76f429d3f374dbaf5199dd8a34c7def66
Author: Jehan <jehan girinstud io>
Date:   Wed Nov 25 01:16:34 2020 +0100

    libgimp, libgimpbase, libgimpwidgets: new gimp_range_estimate_settings()
    
    Similar code was used in 2 places basically (GimpLabelSpin and
    GimpProcedureDialog) so just make it an utils function. It's good anyway
    to have a generic function to estimate suitable increments and decimal
    places depending on a range.
    
    As a consequence also gimp_label_spin_new() now takes a gint digits
    (instead of guint), with -1 meaning we want digits computed from the
    range.
    Similarly gimp_prop_scale_entry_new() docs adds the -1 meaning too.

 libgimp/gimpproceduredialog.c    | 100 +--------------------------------
 libgimpbase/gimpbase.def         |   1 +
 libgimpbase/gimputils.c          | 103 ++++++++++++++++++++++++++++++++++
 libgimpbase/gimputils.h          |   6 ++
 libgimpwidgets/gimplabelspin.c   | 117 +++++++++++++++------------------------
 libgimpwidgets/gimplabelspin.h   |   2 +-
 libgimpwidgets/gimppropwidgets.c |   2 +
 7 files changed, 158 insertions(+), 173 deletions(-)
---
diff --git a/libgimp/gimpproceduredialog.c b/libgimp/gimpproceduredialog.c
index 21202e50ba..74c0bbf43d 100644
--- a/libgimp/gimpproceduredialog.c
+++ b/libgimp/gimpproceduredialog.c
@@ -85,12 +85,6 @@ static void   gimp_procedure_dialog_load_defaults (GtkWidget           *button,
 static void   gimp_procedure_dialog_save_defaults (GtkWidget           *button,
                                                    GimpProcedureDialog *dialog);
 
-static void   gimp_procedure_dialog_estimate_increments (gdouble        lower,
-                                                         gdouble        upper,
-                                                         gdouble       *step,
-                                                         gdouble       *page,
-                                                         gint          *digits);
-
 static gboolean gimp_procedure_dialog_check_mnemonic    (GimpProcedureDialog *dialog,
                                                          GtkWidget           *widget,
                                                          const gchar         *id,
@@ -456,7 +450,7 @@ gimp_procedure_dialog_get_widget (GimpProcedureDialog *dialog,
           minimum = pspecdouble->minimum;
           maximum = pspecdouble->maximum;
         }
-      gimp_procedure_dialog_estimate_increments (minimum, maximum, &step, &page, &digits);
+      gimp_range_estimate_settings (minimum, maximum, &step, &page, &digits);
 
       if (widget_type == G_TYPE_NONE || widget_type == GIMP_TYPE_LABEL_SPIN)
         {
@@ -1186,98 +1180,6 @@ gimp_procedure_dialog_save_defaults (GtkWidget           *button,
     }
 }
 
-/**
- * gimp_procedure_dialog_estimate_increments:
- * @lower:
- * @upper:
- * @step:
- * @page:
- *
- * Though sometimes you might want to specify step and page increments
- * on widgets explicitly, sometimes you are fine with just anything
- * which doesn't give you absurd values. This procedure just tries to
- * return such sensible increment values.
- */
-static void
-gimp_procedure_dialog_estimate_increments (gdouble  lower,
-                                           gdouble  upper,
-                                           gdouble *step,
-                                           gdouble *page,
-                                           gint    *digits)
-{
-  gdouble range;
-
-  g_return_if_fail (upper >= lower);
-  g_return_if_fail (step || page || digits);
-
-  range = upper - lower;
-
-  if (range > 0 && range <= 1.0)
-    {
-      gdouble places = 10.0;
-
-      if (digits)
-        *digits = 3;
-
-      /* Compute some acceptable step and page increments always in the
-       * format `10**-X` where X is the rounded precision.
-       * So for instance:
-       *  0.8 will have increments 0.01 and 0.1.
-       *  0.3 will have increments 0.001 and 0.01.
-       *  0.06 will also have increments 0.001 and 0.01.
-       */
-      while (range * places < 5.0)
-        {
-          places *= 10.0;
-          if (digits)
-            (*digits)++;
-        }
-
-
-      if (step)
-        *step = 0.1 / places;
-      if (page)
-        *page = 1.0 / places;
-    }
-  else if (range <= 2.0)
-    {
-      if (step)
-        *step = 0.01;
-      if (page)
-        *page = 0.1;
-
-      if (digits)
-        *digits = 3;
-    }
-  else if (range <= 5.0)
-    {
-      if (step)
-        *step = 0.1;
-      if (page)
-        *page = 1.0;
-      if (digits)
-        *digits = 2;
-    }
-  else if (range <= 40.0)
-    {
-      if (step)
-        *step = 1.0;
-      if (page)
-        *page = 2.0;
-      if (digits)
-        *digits = 2;
-    }
-  else
-    {
-      if (step)
-        *step = 1.0;
-      if (page)
-        *page = 10.0;
-      if (digits)
-        *digits = 1;
-    }
-}
-
 static gboolean
 gimp_procedure_dialog_check_mnemonic (GimpProcedureDialog *dialog,
                                       GtkWidget           *widget,
diff --git a/libgimpbase/gimpbase.def b/libgimpbase/gimpbase.def
index 521fd8779e..f1ceead442 100644
--- a/libgimpbase/gimpbase.def
+++ b/libgimpbase/gimpbase.def
@@ -159,6 +159,7 @@ EXPORTS
        gimp_plug_in_directory_file
        gimp_precision_get_type
        gimp_progress_command_get_type
+       gimp_range_estimate_settings
        gimp_rectangle_intersect
        gimp_rectangle_union
        gimp_repeat_mode_get_type
diff --git a/libgimpbase/gimputils.c b/libgimpbase/gimputils.c
index 1f456f1a9d..03892e030e 100644
--- a/libgimpbase/gimputils.c
+++ b/libgimpbase/gimputils.c
@@ -1521,6 +1521,109 @@ gimp_stack_trace_query (const gchar *prog_name)
 #endif
 }
 
+/**
+ * gimp_range_estimate_settings:
+ * @lower: the lower value.
+ * @upper: the higher value.
+ * @step: (out) (optional): the proposed step increment.
+ * @page: (out) (optional): the proposed page increment.
+ * @digits: (out) (optional): the proposed decimal places precision.
+ *
+ * This function proposes reasonable settings for increments and display
+ * digits. These can be used for instance on #GtkRange or other widgets
+ * using a #GtkAdjustment typically.
+ * Note that it will never return @digits with value 0. If you know that
+ * your input needs to display integer values, there is no need to set
+ * @digits.
+ *
+ * There is no universal answer to the best increments and number of
+ * decimal places. It often depends on context of what the value is
+ * meant to represent. This function only tries to provide sensible
+ * generic values which can be used when it doesn't matter too much or
+ * for generated GUI for instance. If you know exactly how you want to
+ * show and interact with a given range, you don't have to use this
+ * function.
+ */
+void
+gimp_range_estimate_settings (gdouble  lower,
+                              gdouble  upper,
+                              gdouble *step,
+                              gdouble *page,
+                              gint    *digits)
+{
+  gdouble range;
+
+  g_return_if_fail (upper >= lower);
+  g_return_if_fail (step || page || digits);
+
+  range = upper - lower;
+
+  if (range > 0 && range <= 1.0)
+    {
+      gdouble places = 10.0;
+
+      if (digits)
+        *digits = 3;
+
+      /* Compute some acceptable step and page increments always in the
+       * format `10**-X` where X is the rounded precision.
+       * So for instance:
+       *  0.8 will have increments 0.01 and 0.1.
+       *  0.3 will have increments 0.001 and 0.01.
+       *  0.06 will also have increments 0.001 and 0.01.
+       */
+      while (range * places < 5.0)
+        {
+          places *= 10.0;
+          if (digits)
+            (*digits)++;
+        }
+
+
+      if (step)
+        *step = 0.1 / places;
+      if (page)
+        *page = 1.0 / places;
+    }
+  else if (range <= 2.0)
+    {
+      if (step)
+        *step = 0.01;
+      if (page)
+        *page = 0.1;
+
+      if (digits)
+        *digits = 3;
+    }
+  else if (range <= 5.0)
+    {
+      if (step)
+        *step = 0.1;
+      if (page)
+        *page = 1.0;
+      if (digits)
+        *digits = 2;
+    }
+  else if (range <= 40.0)
+    {
+      if (step)
+        *step = 1.0;
+      if (page)
+        *page = 2.0;
+      if (digits)
+        *digits = 2;
+    }
+  else
+    {
+      if (step)
+        *step = 1.0;
+      if (page)
+        *page = 10.0;
+      if (digits)
+        *digits = 1;
+    }
+}
+
 
 /* Private functions. */
 
diff --git a/libgimpbase/gimputils.h b/libgimpbase/gimputils.h
index db536658c9..fae2d9a9e6 100644
--- a/libgimpbase/gimputils.h
+++ b/libgimpbase/gimputils.h
@@ -82,6 +82,12 @@ gboolean              gimp_stack_trace_print         (const gchar       *prog_na
                                                       gchar            **trace);
 void                  gimp_stack_trace_query         (const gchar       *prog_name);
 
+void                  gimp_range_estimate_settings   (gdouble            lower,
+                                                      gdouble            upper,
+                                                      gdouble           *step,
+                                                      gdouble           *page,
+                                                      gint              *digits);
+
 
 G_END_DECLS
 
diff --git a/libgimpwidgets/gimplabelspin.c b/libgimpwidgets/gimplabelspin.c
index 55f37a24db..3c779fa1e4 100644
--- a/libgimpwidgets/gimplabelspin.c
+++ b/libgimpwidgets/gimplabelspin.c
@@ -60,6 +60,8 @@ typedef struct _GimpLabelSpinPrivate
 
   GtkWidget     *spinbutton;
   GtkAdjustment *spin_adjustment;
+
+  gint           digits;
 } GimpLabelSpinPrivate;
 
 static void        gimp_label_spin_constructed       (GObject       *object);
@@ -78,8 +80,11 @@ static GtkWidget * gimp_label_spin_populate          (GimpLabeled   *spin,
                                                       gint          *width,
                                                       gint          *height);
 
-static void        gimp_label_spin_update_spin_width (GimpLabelSpin *spin);
-static void        gimp_label_spin_update_increments (GimpLabelSpin *spin);
+static void        gimp_label_spin_update_spin_width (GimpLabelSpin *spin,
+                                                      gdouble        lower,
+                                                      gdouble        upper,
+                                                      guint          digits);
+static void        gimp_label_spin_update_settings   (GimpLabelSpin *spin);
 
 G_DEFINE_TYPE_WITH_PRIVATE (GimpLabelSpin, gimp_label_spin, GIMP_TYPE_LABELED)
 
@@ -151,15 +156,16 @@ gimp_label_spin_class_init (GimpLabelSpinClass *klass)
   /**
    * GimpLabelSpin:digits:
    *
-   * The number of decimal places to display.
+   * The number of decimal places to display. If -1, then the number is
+   * estimated.
    *
    * Since: 3.0
    **/
   g_object_class_install_property (object_class, PROP_DIGITS,
-                                   g_param_spec_uint ("digits", NULL,
-                                                      "The number of decimal places to display",
-                                                      0, G_MAXUINT, 2,
-                                                      GIMP_PARAM_READWRITE));
+                                   g_param_spec_int ("digits", NULL,
+                                                     "The number of decimal places to display",
+                                                     -1, G_MAXINT, -1,
+                                                     GIMP_PARAM_READWRITE));
 }
 
 static void
@@ -195,8 +201,7 @@ gimp_label_spin_constructed (GObject *object)
                           G_BINDING_BIDIRECTIONAL |
                           G_BINDING_SYNC_CREATE);
 
-  gimp_label_spin_update_spin_width (spin);
-  gimp_label_spin_update_increments (spin);
+  gimp_label_spin_update_settings (spin);
 }
 
 static void
@@ -224,8 +229,7 @@ gimp_label_spin_set_property (GObject      *object,
                                 g_value_get_double (value));
       if (priv->spinbutton)
         {
-          gimp_label_spin_update_spin_width (spin);
-          gimp_label_spin_update_increments (spin);
+          gimp_label_spin_update_settings (spin);
         }
       break;
     case PROP_UPPER:
@@ -233,18 +237,14 @@ gimp_label_spin_set_property (GObject      *object,
                                 g_value_get_double (value));
       if (priv->spinbutton)
         {
-          gimp_label_spin_update_spin_width (spin);
-          gimp_label_spin_update_increments (spin);
+          gimp_label_spin_update_settings (spin);
         }
       break;
     case PROP_DIGITS:
       if (priv->spinbutton)
         {
-          gtk_spin_button_set_digits (GTK_SPIN_BUTTON (priv->spinbutton),
-                                      g_value_get_uint (value));
-
-          gimp_label_spin_update_spin_width (spin);
-          gimp_label_spin_update_increments (spin);
+          priv->digits = g_value_get_int (value);
+          gimp_label_spin_update_settings (spin);
         }
       break;
 
@@ -305,22 +305,16 @@ gimp_label_spin_populate (GimpLabeled *labeled,
 }
 
 static void
-gimp_label_spin_update_spin_width (GimpLabelSpin *spin)
+gimp_label_spin_update_spin_width (GimpLabelSpin *spin,
+                                   gdouble        lower,
+                                   gdouble        upper,
+                                   guint          digits)
 {
   GimpLabelSpinPrivate *priv = gimp_label_spin_get_instance_private (spin);
   gint                  width = 0;
-  gdouble               lower;
-  gdouble               upper;
-  gint                  digits;
 
   g_return_if_fail (GIMP_IS_LABEL_SPIN (spin));
 
-  g_object_get (spin,
-                "lower",  &lower,
-                "upper",  &upper,
-                "digits", &digits,
-                NULL);
-
   /* Necessary size to display the max/min integer values, with optional
    * negative sign.
    */
@@ -337,11 +331,14 @@ gimp_label_spin_update_spin_width (GimpLabelSpin *spin)
 }
 
 static void
-gimp_label_spin_update_increments (GimpLabelSpin *spin)
+gimp_label_spin_update_settings (GimpLabelSpin *spin)
 {
-  gdouble lower;
-  gdouble upper;
-  gdouble range;
+  GimpLabelSpinPrivate *priv = gimp_label_spin_get_instance_private (spin);
+  gdouble               lower;
+  gdouble               upper;
+  gdouble               step;
+  gdouble               page;
+  gint                  digits = priv->digits;
 
   g_return_if_fail (GIMP_IS_LABEL_SPIN (spin));
 
@@ -352,46 +349,11 @@ gimp_label_spin_update_increments (GimpLabelSpin *spin)
 
   g_return_if_fail (upper >= lower);
 
-  range = upper - lower;
-
-  if (range > 0 && range <= 1.0)
-    {
-      gdouble places = 10.0;
-      gdouble step;
-      gdouble page;
-
-      /* Compute some acceptable step and page increments always in the
-       * format `10**-X` where X is the rounded precision.
-       * So for instance:
-       *  0.8 will have increments 0.01 and 0.1.
-       *  0.3 will have increments 0.001 and 0.01.
-       *  0.06 will also have increments 0.001 and 0.01.
-       */
-      while (range * places < 5.0)
-        places *= 10.0;
-
-
-      step = 0.1 / places;
-      page = 1.0 / places;
-
-      gimp_label_spin_set_increments (spin, step, page);
-    }
-  else if (range <= 2.0)
-    {
-      gimp_label_spin_set_increments (spin, 0.01, 0.1);
-    }
-  else if (range <= 5.0)
-    {
-      gimp_label_spin_set_increments (spin, 0.1, 1.0);
-    }
-  else if (range <= 40.0)
-    {
-      gimp_label_spin_set_increments (spin, 1.0, 2.0);
-    }
-  else
-    {
-      gimp_label_spin_set_increments (spin, 1.0, 10.0);
-    }
+  gimp_range_estimate_settings (lower, upper, &step, &page,
+                                digits < 0 ? &digits: NULL);
+  gimp_label_spin_set_increments (spin, step, page);
+  gtk_spin_button_set_digits (GTK_SPIN_BUTTON (priv->spinbutton), (guint) digits);
+  gimp_label_spin_update_spin_width (spin, lower, upper, (guint) digits);
 }
 
 
@@ -406,6 +368,12 @@ gimp_label_spin_update_increments (GimpLabelSpin *spin)
  * @upper:  The upper boundary.
  * @digits: The number of decimal digits.
  *
+ * Suitable increment values are estimated based on the [@lower, @upper]
+ * range.
+ * If @digits is -1, then it will also be estimated based on the same
+ * range. Digits estimation will always be at least 1, so if you want to
+ * show integer values only, set 0 explicitly.
+ *
  * Returns: (transfer full): The new #GimpLabelSpin widget.
  **/
 GtkWidget *
@@ -413,10 +381,13 @@ gimp_label_spin_new (const gchar *text,
                      gdouble      value,
                      gdouble      lower,
                      gdouble      upper,
-                     guint        digits)
+                     gint         digits)
 {
   GtkWidget *labeled;
 
+  g_return_val_if_fail (upper >= lower, NULL);
+  g_return_val_if_fail (digits >= -1, NULL);
+
   labeled = g_object_new (GIMP_TYPE_LABEL_SPIN,
                           "label",  text,
                           "value",  value,
diff --git a/libgimpwidgets/gimplabelspin.h b/libgimpwidgets/gimplabelspin.h
index 63316aa69c..62f672511c 100644
--- a/libgimpwidgets/gimplabelspin.h
+++ b/libgimpwidgets/gimplabelspin.h
@@ -55,7 +55,7 @@ GtkWidget  * gimp_label_spin_new             (const gchar   *text,
                                               gdouble        value,
                                               gdouble        lower,
                                               gdouble        upper,
-                                              guint          digits);
+                                              gint           digits);
 
 void         gimp_label_spin_set_value       (GimpLabelSpin *spin,
                                               gdouble        value);
diff --git a/libgimpwidgets/gimppropwidgets.c b/libgimpwidgets/gimppropwidgets.c
index 0352192c69..27c59b261e 100644
--- a/libgimpwidgets/gimppropwidgets.c
+++ b/libgimpwidgets/gimppropwidgets.c
@@ -1513,6 +1513,8 @@ gimp_prop_hscale_new (GObject     *config,
  * @property_name:  Name of integer or double property controlled by the scale.
  * @digits:         Number of digits after decimal point to display. For
  *                  integer properties, this will be ignored (always 0).
+ *                  If set to -1, a reasonable value will be
+ *                  approximated depending on @property_name's range.
  * @limit_scale:    %FALSE if the range of possible values of the
  *                  GtkHScale should be the same as of the GtkSpinButton.
  * @lower_limit:    The scale's lower boundary if @scale_limits is %TRUE.


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