[gimp/wip/gradient-edit: 9/33] app: add misc. parameters to GimpControllerSlider



commit 08328ab2e4ef98dccf30165a47927463999bcb4d
Author: Ell <ell_se yahoo com>
Date:   Sun Jul 23 20:43:33 2017 -0400

    app: add misc. parameters to GimpControllerSlider
    
    Add parameters, controlling the behavior and appearance of sliders,
    to GimpControllerSlider.  The macro GIMP_CONTROLLER_SLIDER_DEFAULT
    expands to a nonmodifiable lvalue of type GimpControllerSlider,
    whose members are initialized with the most common default values.
    
    Handle the new parameters in GimpToolLine.  A slider using the new
    "autohide" mode is only visible when selected, or when the cursor
    is close enough to the line, between the slider's min and max
    values, and no other handle is grabbed or hovered-over.

 app/display/gimptoolline.c       |  171 +++++++++++++++++++++++++++++++-------
 app/propgui/gimppropgui-spiral.c |    3 +
 app/propgui/propgui-types.h      |   38 ++++++++-
 3 files changed, 178 insertions(+), 34 deletions(-)
---
diff --git a/app/display/gimptoolline.c b/app/display/gimptoolline.c
index f1b27f9..031ee25 100644
--- a/app/display/gimptoolline.c
+++ b/app/display/gimptoolline.c
@@ -185,6 +185,7 @@ static gboolean
                                                 gboolean               constrain);
 
 static void     gimp_tool_line_update_handles  (GimpToolLine          *line);
+static void     gimp_tool_line_update_circle   (GimpToolLine          *line);
 static void     gimp_tool_line_update_hilight  (GimpToolLine          *line);
 static void     gimp_tool_line_update_status   (GimpToolLine          *line,
                                                 GdkModifierType        state,
@@ -435,21 +436,24 @@ gimp_tool_line_set_property (GObject      *object,
 
     case PROP_SLIDERS:
       {
-        GArray *sliders = g_value_dup_boxed (value);
+        GArray   *sliders = g_value_dup_boxed (value);
+        gboolean  deselect;
 
         g_return_if_fail (sliders != NULL);
 
-        if (GIMP_TOOL_LINE_HANDLE_IS_SLIDER (private->selection) &&
-            sliders->len != private->sliders->len)
-          {
-            gimp_tool_line_set_selection (line, GIMP_TOOL_LINE_HANDLE_NONE);
-          }
+        deselect =
+          GIMP_TOOL_LINE_HANDLE_IS_SLIDER (private->selection) &&
+          (sliders->len != private->sliders->len               ||
+           ! gimp_tool_line_get_slider (line, private->selection)->selectable);
+
+        g_array_unref (private->sliders);
+        private->sliders = sliders;
 
         if (GIMP_TOOL_LINE_HANDLE_IS_SLIDER (private->hover))
           private->hover = GIMP_TOOL_LINE_HANDLE_NONE;
 
-        g_array_unref (private->sliders);
-        private->sliders = sliders;
+        if (deselect)
+          gimp_tool_line_set_selection (line, GIMP_TOOL_LINE_HANDLE_NONE);
       }
       break;
 
@@ -458,6 +462,9 @@ gimp_tool_line_set_property (GObject      *object,
         gint selection = g_value_get_int (value);
 
         g_return_if_fail (selection < (gint) private->sliders->len);
+        g_return_if_fail (selection < 0 ||
+                          gimp_tool_line_get_slider (line,
+                                                     selection)->selectable);
 
         if (selection != private->selection)
           {
@@ -591,6 +598,7 @@ gimp_tool_line_changed (GimpToolWidget *widget)
     }
 
   gimp_tool_line_update_handles (line);
+  gimp_tool_line_update_circle (line);
   gimp_tool_line_update_hilight (line);
 }
 
@@ -678,6 +686,7 @@ gimp_tool_line_button_press (GimpToolWidget      *widget,
     }
 
   gimp_tool_line_update_handles (line);
+  gimp_tool_line_update_circle (line);
   gimp_tool_line_update_status (line, state, TRUE);
 
   return result;
@@ -798,6 +807,16 @@ gimp_tool_line_hover (GimpToolWidget   *widget,
         {
           GimpCanvasItem *handle;
 
+          if (GIMP_TOOL_LINE_HANDLE_IS_SLIDER (i))
+            {
+              const GimpControllerSlider *slider;
+
+              slider = gimp_tool_line_get_slider (line, i);
+
+              if (! slider->visible || ! slider->selectable)
+                continue;
+            }
+
           handle = gimp_tool_line_get_handle (line, i);
 
           if (gimp_tool_line_handle_hit (handle,
@@ -840,6 +859,7 @@ gimp_tool_line_hover (GimpToolWidget   *widget,
     }
 
   gimp_tool_line_update_handles (line);
+  gimp_tool_line_update_circle (line);
   gimp_tool_line_update_status (line, state, proximity);
 }
 
@@ -911,8 +931,14 @@ gimp_tool_line_key_press (GimpToolWidget *widget,
       /* move a slider */
       else
         {
-          gdouble dist;
-          gdouble dvalue;
+          GimpControllerSlider *slider;
+          gdouble               dist;
+          gdouble               dvalue;
+
+          slider = gimp_tool_line_get_slider (line, private->selection);
+
+          if (! slider->movable)
+            break;
 
           dist = gimp_canvas_item_transform_distance (private->line,
                                                       private->x1, private->y1,
@@ -948,10 +974,6 @@ gimp_tool_line_key_press (GimpToolWidget *widget,
 
           if (dvalue != 0.0)
             {
-              GimpControllerSlider *slider;
-
-              slider = gimp_tool_line_get_slider (line, private->selection);
-
               slider->value += dvalue;
               slider->value  = CLAMP (slider->value, slider->min, slider->max);
               slider->value  = CLAMP (slider->value, 0.0, 1.0);
@@ -967,8 +989,15 @@ gimp_tool_line_key_press (GimpToolWidget *widget,
     case GDK_KEY_Delete:
       if (GIMP_TOOL_LINE_HANDLE_IS_SLIDER (private->selection))
         {
-          g_signal_emit (line, line_signals[REMOVE_SLIDER], 0,
-                         private->selection);
+          GimpControllerSlider *slider;
+
+          slider = gimp_tool_line_get_slider (line, private->selection);
+
+          if (slider->removable)
+            {
+              g_signal_emit (line, line_signals[REMOVE_SLIDER], 0,
+                             private->selection);
+            }
         }
       return TRUE;
     }
@@ -1012,18 +1041,30 @@ gimp_tool_line_get_cursor (GimpToolWidget     *widget,
   else if (private->grab  == GRAB_SELECTION ||
            private->hover >  GIMP_TOOL_LINE_HANDLE_NONE)
     {
-      if (private->grab == GRAB_SELECTION                      &&
-          GIMP_TOOL_LINE_HANDLE_IS_SLIDER (private->selection) &&
-          private->remove_slider)
+      const GimpControllerSlider *slider = NULL;
+
+      if (private->grab == GRAB_SELECTION)
+        {
+          if (GIMP_TOOL_LINE_HANDLE_IS_SLIDER (private->selection))
+            slider = gimp_tool_line_get_slider (line, private->selection);
+        }
+      else if (GIMP_TOOL_LINE_HANDLE_IS_SLIDER (private->hover))
+        {
+          slider = gimp_tool_line_get_slider (line, private->hover);
+        }
+
+      if (private->grab == GRAB_SELECTION && slider && private->remove_slider)
         {
           *modifier = GIMP_CURSOR_MODIFIER_MINUS;
+
+          return TRUE;
         }
-      else
+      else if (! slider || slider->movable)
         {
           *modifier = GIMP_CURSOR_MODIFIER_MOVE;
-        }
 
-      return TRUE;
+          return TRUE;
+        }
     }
   else if (private->hover == HOVER_NEW_SLIDER)
     {
@@ -1178,19 +1219,24 @@ gimp_tool_line_selection_motion (GimpToolLine *line,
         /* project the cursor position onto the line */
         value = gimp_tool_line_project_point (line, x, y, constrain, &dist);
 
-        value = CLAMP (value, slider->min, slider->max);
-        value = CLAMP (value, 0.0,         1.0);
+        /* slider dragging */
+        if (slider->movable)
+          {
+            value = CLAMP (value, slider->min, slider->max);
+            value = CLAMP (value, 0.0,         1.0);
 
-        value = fabs (value); /* avoid negative zero */
+            value = fabs (value); /* avoid negative zero */
 
-        slider->value = value;
+            slider->value = value;
 
-        g_object_set (line,
-                      "sliders", private->sliders,
-                      NULL);
+            g_object_set (line,
+                          "sliders", private->sliders,
+                          NULL);
+          }
 
         /* slider tearing */
-        private->remove_slider = dist > SLIDER_TEAR_DISTANCE;
+        private->remove_slider = slider->removable &&
+                                 dist > SLIDER_TEAR_DISTANCE;
 
         /* eek! */
         {
@@ -1208,7 +1254,7 @@ gimp_tool_line_selection_motion (GimpToolLine *line,
           gimp_display_shell_set_cursor (shell, cursor, tool_cursor, modifier);
         }
 
-        gimp_tool_line_update_handles (line);
+        gimp_tool_line_update_circle (line);
 
         return TRUE;
       }
@@ -1219,6 +1265,66 @@ static void
 gimp_tool_line_update_handles (GimpToolLine *line)
 {
   GimpToolLinePrivate *private = line->private;
+  gdouble              value;
+  gdouble              dist;
+  gint                 i;
+
+  value = gimp_tool_line_project_point (line,
+                                        private->mouse_x,
+                                        private->mouse_y,
+                                        FALSE,
+                                        &dist);
+
+  for (i = 0; i < private->sliders->len; i++)
+    {
+      const GimpControllerSlider *slider;
+      GimpCanvasItem             *handle;
+      gint                        size;
+      gint                        hit_radius;
+      gboolean                    show_autohidden;
+      gboolean                    visible;
+
+      slider = gimp_tool_line_get_slider (line, i);
+      handle = gimp_tool_line_get_handle (line, i);
+
+      size = slider->size * SLIDER_HANDLE_SIZE;
+      size = MAX (size, 1);
+
+      hit_radius = (MAX (size, SLIDER_HANDLE_SIZE) * HANDLE_CIRCLE_SCALE) / 2;
+
+      /* show a autohidden slider if it's selected, or if no other handle is
+       * grabbed or hovered-over, and the cursor is close enough to the line,
+       * between the slider's min and max values.
+       */
+      show_autohidden = private->selection == i                        ||
+                        (private->grab == GRAB_NONE                    &&
+                         (private->hover <= GIMP_TOOL_LINE_HANDLE_NONE ||
+                          private->hover == i)                         &&
+                         dist <= hit_radius                            &&
+                         value >= slider->min                          &&
+                         value <= slider->max);
+
+      visible = slider->visible && (! slider->autohide || show_autohidden);
+
+      handle = gimp_tool_line_get_handle (line, i);
+
+      if (visible)
+        {
+          g_object_set (handle,
+                        "type",   slider->type,
+                        "width",  size,
+                        "height", size,
+                        NULL);
+        }
+
+      gimp_canvas_item_set_visible (handle, visible);
+    }
+}
+
+static void
+gimp_tool_line_update_circle (GimpToolLine *line)
+{
+  GimpToolLinePrivate *private = line->private;
   gboolean             visible;
 
   visible = (private->grab == GRAB_NONE                    &&
@@ -1352,6 +1458,9 @@ gimp_tool_line_handle_hit (GimpCanvasItem *handle,
   gimp_canvas_handle_get_position (handle, &handle_x,     &handle_y);
   gimp_canvas_handle_get_size     (handle, &handle_width, &handle_height);
 
+  handle_width  = MAX (handle_width,  SLIDER_HANDLE_SIZE);
+  handle_height = MAX (handle_height, SLIDER_HANDLE_SIZE);
+
   radius = ((gint) (handle_width * HANDLE_CIRCLE_SCALE)) / 2;
   radius = MAX (radius, LINE_VICINITY);
 
diff --git a/app/propgui/gimppropgui-spiral.c b/app/propgui/gimppropgui-spiral.c
index e7c57fa..8f1bf4c 100644
--- a/app/propgui/gimppropgui-spiral.c
+++ b/app/propgui/gimppropgui-spiral.c
@@ -157,6 +157,7 @@ config_notify (GObject          *config,
     n_sliders = 1;
 
     /* balance */
+    sliders[0]       = GIMP_CONTROLLER_SLIDER_DEFAULT;
     sliders[0].min   = 0.5;
     sliders[0].max   = 1.0;
     sliders[0].value = 0.5 + (1.0 - balance) / 4.0;
@@ -167,11 +168,13 @@ config_notify (GObject          *config,
     n_sliders = 2;
 
     /* balance */
+    sliders[0]       = GIMP_CONTROLLER_SLIDER_DEFAULT;
     sliders[0].min   = 1.0 / sqrt (base);
     sliders[0].max   = 1.0;
     sliders[0].value = pow (base, -(balance + 1.0) / 4.0);
 
     /* base */
+    sliders[1]       = GIMP_CONTROLLER_SLIDER_DEFAULT;
     sliders[1].min   = 0.0;
     sliders[1].max   = 1.0;
     sliders[1].value = 1.0 / base;
diff --git a/app/propgui/propgui-types.h b/app/propgui/propgui-types.h
index ce2a327..362db13 100644
--- a/app/propgui/propgui-types.h
+++ b/app/propgui/propgui-types.h
@@ -19,6 +19,8 @@
 #define __PROPGUI_TYPES_H__
 
 
+#include "display/display-enums.h"
+
 #include "widgets/widgets-types.h"
 
 
@@ -35,11 +37,41 @@ typedef enum
 
 typedef struct
 {
-  gdouble value;
-  gdouble min;
-  gdouble max;
+  gdouble        value;           /*  slider value                           */
+  gdouble        min;             /*  minimal allowable slider value         */
+  gdouble        max;             /*  maximal allowable slider value         */
+
+  gboolean       visible    : 1;  /*  slider is visible                      */
+  gboolean       selectable : 1;  /*  slider is selectable                   */
+  gboolean       movable    : 1;  /*  slider movable                         */
+  gboolean       removable  : 1;  /*  slider is removable                    */
+
+  gboolean       autohide   : 1;  /*  whether to autohide the slider         */
+  GimpHandleType type;            /*  slider handle type                     */
+  gdouble        size;            /*  slider handle size, as a fraction of   *
+                                   *  the default size                       */
+
+  gpointer       data;            /*  user data                              */
 } GimpControllerSlider;
 
+#define GIMP_CONTROLLER_SLIDER_DEFAULT                                         \
+  ((const GimpControllerSlider) {                                              \
+    .value      = 0.0,                                                         \
+    .min        = 0.0,                                                         \
+    .max        = 1.0,                                                         \
+                                                                               \
+    .visible    = TRUE,                                                        \
+    .selectable = TRUE,                                                        \
+    .movable    = TRUE,                                                        \
+    .removable  = FALSE,                                                       \
+                                                                               \
+    .autohide   = FALSE,                                                       \
+    .type       = GIMP_HANDLE_FILLED_DIAMOND,                                  \
+    .size       = 1.0,                                                         \
+                                                                               \
+    .data       = NULL                                                         \
+  })
+
 
 /*  function types  */
 


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