[gimp] app: add sliders to GimpToolLine; add slider-line controller



commit 60586a88176f138c8798b08e4cd8464c127d8471
Author: Ell <ell_se yahoo com>
Date:   Mon Jul 3 14:48:34 2017 -0400

    app: add sliders to GimpToolLine; add slider-line controller
    
    Add supprt for placing sliders on a GimpToolLine -- handles that can
    be dragged over the line.  The sliders are accesible through a new
    "sliders" property, and via the gimp_tool_line_{get,set}_sliders()
    functions.
    
    Add a slider-line controller, which works like a line controller,
    but whose callback also supplies/takes an array of sliders.
    
    Note that the data type for individual sliders is called
    GimpControllerSlider (in particular, it's not line specific), so
    that we may use it with other controller/tool-widget types in the
    future.

 app/display/gimptoolline.c         |  341 +++++++++++++++++++++++++++++++-----
 app/display/gimptoolline.h         |   18 ++-
 app/propgui/propgui-types.h        |   33 +++-
 app/tools/gimpfiltertool-widgets.c |  117 ++++++++++++-
 4 files changed, 447 insertions(+), 62 deletions(-)
---
diff --git a/app/display/gimptoolline.c b/app/display/gimptoolline.c
index 5a23d35..65ec27d 100644
--- a/app/display/gimptoolline.c
+++ b/app/display/gimptoolline.c
@@ -44,6 +44,10 @@
 
 
 #define SHOW_LINE TRUE
+#define ENDPOINT_GRIP_HANDLE_TYPE GIMP_HANDLE_CROSS
+#define ENDPOINT_GRIP_HANDLE_SIZE GIMP_CANVAS_HANDLE_SIZE_CROSS
+#define SLIDER_GRIP_HANDLE_TYPE   GIMP_HANDLE_FILLED_DIAMOND
+#define SLIDER_GRIP_HANDLE_SIZE   (ENDPOINT_GRIP_HANDLE_SIZE * 2 / 3)
 
 
 typedef enum
@@ -52,7 +56,8 @@ typedef enum
   POINT_NONE = 0,
   POINT_START,
   POINT_END,
-  POINT_BOTH
+  POINT_BOTH,
+  POINT_SLIDER
 } GimpToolLinePoint;
 
 enum
@@ -62,6 +67,7 @@ enum
   PROP_Y1,
   PROP_X2,
   PROP_Y2,
+  PROP_SLIDERS,
   PROP_STATUS_TITLE,
 };
 
@@ -71,23 +77,28 @@ struct _GimpToolLinePrivate
   gdouble            y1;
   gdouble            x2;
   gdouble            y2;
+  GArray            *sliders;
   gchar             *status_title;
 
   gdouble            saved_x1;
   gdouble            saved_y1;
   gdouble            saved_x2;
   gdouble            saved_y2;
+  gdouble            saved_slider_value;
 
   gdouble            mouse_x;
   gdouble            mouse_y;
   GimpToolLinePoint  point;
+  gint               slider_index;
   gboolean           point_grabbed;
 
   GimpCanvasItem    *line;
   GimpCanvasItem    *start_handle_circle;
-  GimpCanvasItem    *start_handle_cross;
+  GimpCanvasItem    *start_handle_grip;
   GimpCanvasItem    *end_handle_circle;
-  GimpCanvasItem    *end_handle_cross;
+  GimpCanvasItem    *end_handle_grip;
+  GArray            *slider_handle_circles;
+  GArray            *slider_handle_grips;
 };
 
 
@@ -135,7 +146,7 @@ static gboolean gimp_tool_line_get_cursor      (GimpToolWidget        *widget,
                                                 GimpCursorModifier    *modifier);
 
 static gboolean gimp_tool_line_point_motion    (GimpToolLine          *line,
-                                                gboolean               constrain_angle);
+                                                gboolean               constrain);
 
 static void     gimp_tool_line_update_handles  (GimpToolLine          *line);
 static void     gimp_tool_line_update_hilight  (GimpToolLine          *line);
@@ -196,6 +207,11 @@ gimp_tool_line_class_init (GimpToolLineClass *klass)
                                                         GIMP_PARAM_READWRITE |
                                                         G_PARAM_CONSTRUCT));
 
+  g_object_class_install_property (object_class, PROP_SLIDERS,
+                                   g_param_spec_boxed ("sliders", NULL, NULL,
+                                                       G_TYPE_ARRAY,
+                                                       GIMP_PARAM_READWRITE));
+
   g_object_class_install_property (object_class, PROP_STATUS_TITLE,
                                    g_param_spec_string ("status-title",
                                                         NULL, NULL,
@@ -209,9 +225,18 @@ gimp_tool_line_class_init (GimpToolLineClass *klass)
 static void
 gimp_tool_line_init (GimpToolLine *line)
 {
-  line->private = G_TYPE_INSTANCE_GET_PRIVATE (line,
-                                               GIMP_TYPE_TOOL_LINE,
-                                               GimpToolLinePrivate);
+  GimpToolLinePrivate *private;
+  
+  private = line->private = G_TYPE_INSTANCE_GET_PRIVATE (line,
+                                                         GIMP_TYPE_TOOL_LINE,
+                                                         GimpToolLinePrivate);
+
+  private->sliders = g_array_new (FALSE, FALSE, sizeof (GimpControllerSlider));
+
+  private->slider_handle_circles = g_array_new (FALSE, TRUE,
+                                                sizeof (GimpCanvasItem *));
+  private->slider_handle_grips   = g_array_new (FALSE, TRUE,
+                                                sizeof (GimpCanvasItem *));
 }
 
 static void
@@ -236,17 +261,17 @@ gimp_tool_line_constructed (GObject *object)
                                  GIMP_HANDLE_CIRCLE,
                                  private->x1,
                                  private->y1,
-                                 2 * GIMP_CANVAS_HANDLE_SIZE_CROSS,
-                                 2 * GIMP_CANVAS_HANDLE_SIZE_CROSS,
+                                 2 * ENDPOINT_GRIP_HANDLE_SIZE,
+                                 2 * ENDPOINT_GRIP_HANDLE_SIZE,
                                  GIMP_HANDLE_ANCHOR_CENTER);
 
-  private->start_handle_cross =
+  private->start_handle_grip =
     gimp_tool_widget_add_handle (widget,
-                                 GIMP_HANDLE_CROSS,
+                                 ENDPOINT_GRIP_HANDLE_TYPE,
                                  private->x1,
                                  private->y1,
-                                 GIMP_CANVAS_HANDLE_SIZE_CROSS,
-                                 GIMP_CANVAS_HANDLE_SIZE_CROSS,
+                                 ENDPOINT_GRIP_HANDLE_SIZE,
+                                 ENDPOINT_GRIP_HANDLE_SIZE,
                                  GIMP_HANDLE_ANCHOR_CENTER);
 
   private->end_handle_circle =
@@ -254,17 +279,17 @@ gimp_tool_line_constructed (GObject *object)
                                  GIMP_HANDLE_CIRCLE,
                                  private->x2,
                                  private->y2,
-                                 2 * GIMP_CANVAS_HANDLE_SIZE_CROSS,
-                                 2 * GIMP_CANVAS_HANDLE_SIZE_CROSS,
+                                 2 * ENDPOINT_GRIP_HANDLE_SIZE,
+                                 2 * ENDPOINT_GRIP_HANDLE_SIZE,
                                  GIMP_HANDLE_ANCHOR_CENTER);
 
-  private->end_handle_cross =
+  private->end_handle_grip =
     gimp_tool_widget_add_handle (widget,
-                                 GIMP_HANDLE_CROSS,
+                                 ENDPOINT_GRIP_HANDLE_TYPE,
                                  private->x2,
                                  private->y2,
-                                 GIMP_CANVAS_HANDLE_SIZE_CROSS,
-                                 GIMP_CANVAS_HANDLE_SIZE_CROSS,
+                                 ENDPOINT_GRIP_HANDLE_SIZE,
+                                 ENDPOINT_GRIP_HANDLE_SIZE,
                                  GIMP_HANDLE_ANCHOR_CENTER);
 
   gimp_tool_line_changed (widget);
@@ -276,12 +301,30 @@ gimp_tool_line_finalize (GObject *object)
   GimpToolLine        *line    = GIMP_TOOL_LINE (object);
   GimpToolLinePrivate *private = line->private;
 
+  if (private->sliders)
+    {
+      g_array_unref (private->sliders);
+      private->sliders = NULL;
+    }
+
   if (private->status_title)
     {
       g_free (private->status_title);
       private->status_title = NULL;
     }
 
+  if (private->slider_handle_circles)
+    {
+      g_array_unref (private->slider_handle_circles);
+      private->slider_handle_circles = NULL;
+    }
+
+  if (private->slider_handle_grips)
+    {
+      g_array_unref (private->slider_handle_grips);
+      private->slider_handle_grips = NULL;
+    }
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -309,6 +352,13 @@ gimp_tool_line_set_property (GObject      *object,
       private->y2 = g_value_get_double (value);
       break;
 
+    case PROP_SLIDERS:
+      g_return_if_fail (g_value_get_boxed (value) != NULL);
+
+      g_array_unref (private->sliders);
+      private->sliders = g_value_dup_boxed (value);
+      break;
+
     case PROP_STATUS_TITLE:
       g_free (private->status_title);
       private->status_title = g_value_dup_string (value);
@@ -346,6 +396,10 @@ gimp_tool_line_get_property (GObject    *object,
       g_value_set_double (value, private->y2);
       break;
 
+    case PROP_SLIDERS:
+      g_value_set_boxed (value, private->sliders);
+      break;
+
     case PROP_STATUS_TITLE:
       g_value_set_string (value, private->status_title);
       break;
@@ -361,6 +415,7 @@ gimp_tool_line_changed (GimpToolWidget *widget)
 {
   GimpToolLine        *line    = GIMP_TOOL_LINE (widget);
   GimpToolLinePrivate *private = line->private;
+  gint                 i;
 
   gimp_canvas_line_set (private->line,
                         private->x1,
@@ -371,17 +426,73 @@ gimp_tool_line_changed (GimpToolWidget *widget)
   gimp_canvas_handle_set_position (private->start_handle_circle,
                                    private->x1,
                                    private->y1);
-  gimp_canvas_handle_set_position (private->start_handle_cross,
+  gimp_canvas_handle_set_position (private->start_handle_grip,
                                    private->x1,
                                    private->y1);
 
   gimp_canvas_handle_set_position (private->end_handle_circle,
                                    private->x2,
                                    private->y2);
-  gimp_canvas_handle_set_position (private->end_handle_cross,
+  gimp_canvas_handle_set_position (private->end_handle_grip,
                                    private->x2,
                                    private->y2);
 
+  /* remove excessive slider handles */
+  for (i = private->sliders->len; i < private->slider_handle_circles->len; i++)
+    {
+      gimp_tool_widget_remove_item (widget,
+                                    g_array_index (private->slider_handle_circles,
+                                                   GimpCanvasItem *, i));
+      gimp_tool_widget_remove_item (widget,
+                                    g_array_index (private->slider_handle_grips,
+                                                   GimpCanvasItem *, i));
+    }
+
+  g_array_set_size (private->slider_handle_circles, private->sliders->len);
+  g_array_set_size (private->slider_handle_grips,   private->sliders->len);
+
+  for (i = 0; i < private->sliders->len; i++)
+    {
+      gdouble          t;
+      gdouble          x;
+      gdouble          y;
+      GimpCanvasItem **circle;
+      GimpCanvasItem **grip;
+
+      t = g_array_index (private->sliders, GimpControllerSlider, i).value;
+
+      x = private->x1 + (private->x2 - private->x1) * t;
+      y = private->y1 + (private->y2 - private->y1) * t;
+
+      circle = &g_array_index (private->slider_handle_circles,
+                               GimpCanvasItem *, i);
+      grip   = &g_array_index (private->slider_handle_grips,
+                               GimpCanvasItem *, i);
+
+      if (*circle)
+        {
+          gimp_canvas_handle_set_position (*circle, x, y);
+          gimp_canvas_handle_set_position (*grip,   x, y);
+        }
+      else
+        {
+          *circle = gimp_tool_widget_add_handle (widget,
+                                                 GIMP_HANDLE_CIRCLE,
+                                                 x,
+                                                 y,
+                                                 2 * SLIDER_GRIP_HANDLE_SIZE,
+                                                 2 * SLIDER_GRIP_HANDLE_SIZE,
+                                                 GIMP_HANDLE_ANCHOR_CENTER);
+          *grip   = gimp_tool_widget_add_handle (widget,
+                                                 SLIDER_GRIP_HANDLE_TYPE,
+                                                 x,
+                                                 y,
+                                                 SLIDER_GRIP_HANDLE_SIZE,
+                                                 SLIDER_GRIP_HANDLE_SIZE,
+                                                 GIMP_HANDLE_ANCHOR_CENTER);
+        }
+    }
+
   gimp_tool_line_update_handles (line);
   gimp_tool_line_update_hilight (line);
 }
@@ -403,6 +514,13 @@ gimp_tool_line_button_press (GimpToolWidget      *widget,
       private->saved_x2 = private->x2;
       private->saved_y2 = private->y2;
 
+      if (private->point == POINT_SLIDER)
+        {
+          private->saved_slider_value =
+            g_array_index (private->sliders,
+                           GimpControllerSlider, private->slider_index).value;
+        }
+
       private->point_grabbed = TRUE;
 
       gimp_tool_line_point_motion (line,
@@ -428,6 +546,13 @@ gimp_tool_line_button_release (GimpToolWidget        *widget,
 
   if (release_type == GIMP_BUTTON_RELEASE_CANCEL)
     {
+      if (private->point == POINT_SLIDER)
+        {
+          g_array_index (private->sliders,
+                         GimpControllerSlider, private->slider_index).value =
+            private->saved_slider_value;
+        }
+
       g_object_set (line,
                     "x1", private->saved_x1,
                     "y1", private->saved_y1,
@@ -480,31 +605,53 @@ gimp_tool_line_hover (GimpToolWidget   *widget,
 {
   GimpToolLine        *line    = GIMP_TOOL_LINE (widget);
   GimpToolLinePrivate *private = line->private;
+  gint                 i;
 
   private->mouse_x = coords->x;
   private->mouse_y = coords->y;
 
   gimp_tool_line_update_handles (line);
 
+  private->point = POINT_NONE;
+
   if (state & GDK_MOD1_MASK)
     {
       private->point = POINT_BOTH;
     }
-  else if (gimp_canvas_item_hit (private->end_handle_circle,
-                                 private->mouse_x,
-                                 private->mouse_y))
-    {
-      private->point = POINT_END;
-    }
-  else if (gimp_canvas_item_hit (private->start_handle_circle,
-                                 private->mouse_x,
-                                 private->mouse_y))
-    {
-      private->point = POINT_START;
-    }
   else
     {
-      private->point = POINT_NONE;
+      /* give sliders precedence over the endpoints, since they're smaller */
+      for (i = private->sliders->len - 1; i >= 0; i--)
+        {
+          GimpCanvasItem *circle;
+
+          circle = g_array_index (private->slider_handle_circles,
+                                  GimpCanvasItem *, i);
+
+          if (gimp_canvas_item_hit (circle, private->mouse_x, private->mouse_y))
+            {
+              private->point        = POINT_SLIDER;
+              private->slider_index = i;
+
+              break;
+            }
+        }
+
+      if (private->point == POINT_NONE)
+        {
+          if (gimp_canvas_item_hit (private->end_handle_circle,
+                                    private->mouse_x,
+                                    private->mouse_y))
+            {
+              private->point = POINT_END;
+            }
+          else if (gimp_canvas_item_hit (private->start_handle_circle,
+                                         private->mouse_x,
+                                         private->mouse_y))
+            {
+              private->point = POINT_START;
+            }
+        }
     }
 
   gimp_tool_line_update_hilight (line);
@@ -550,7 +697,7 @@ gimp_tool_line_get_cursor (GimpToolWidget     *widget,
 
 static gboolean
 gimp_tool_line_point_motion (GimpToolLine *line,
-                             gboolean      constrain_angle)
+                             gboolean      constrain)
 {
   GimpToolLinePrivate *private = line->private;
   gdouble              x       = private->mouse_x;
@@ -559,7 +706,7 @@ gimp_tool_line_point_motion (GimpToolLine *line,
   switch (private->point)
     {
     case POINT_START:
-      if (constrain_angle)
+      if (constrain)
         gimp_constrain_line (private->x2, private->y2,
                              &x, &y,
                              GIMP_CONSTRAIN_LINE_15_DEGREES);
@@ -571,7 +718,7 @@ gimp_tool_line_point_motion (GimpToolLine *line,
       return TRUE;
 
     case POINT_END:
-      if (constrain_angle)
+      if (constrain)
         gimp_constrain_line (private->x1, private->y1,
                              &x, &y,
                              GIMP_CONSTRAIN_LINE_15_DEGREES);
@@ -582,6 +729,34 @@ gimp_tool_line_point_motion (GimpToolLine *line,
                     NULL);
       return TRUE;
 
+    case POINT_SLIDER:
+      {
+        GimpControllerSlider *slider;
+        gdouble               t;
+
+        slider = &g_array_index (private->sliders,
+                                 GimpControllerSlider, private->slider_index);
+
+        /* project the cursor position onto the line */
+        t  = (private->x2 - private->x1) * (x - private->x1) +
+             (private->y2 - private->y1) * (y - private->y1);
+        t /= SQR (private->x2 - private->x1) + SQR (private->y2 - private->y1);
+
+        t = CLAMP (t, slider->min, slider->max);
+        t = CLAMP (t, 0.0, 1.0);
+
+        if (constrain)
+          t = RINT (24.0 * t) / 24.0;
+
+        slider->value = t;
+
+        g_object_set (line,
+                      "sliders", private->sliders,
+                      NULL);
+
+        return TRUE;
+      }
+
     default:
       break;
     }
@@ -595,6 +770,7 @@ gimp_tool_line_update_handles (GimpToolLine *line)
   GimpToolLinePrivate *private = line->private;
   gboolean             start_visible,  end_visible;
   gint                 start_diameter, end_diameter;
+  gint                 i;
 
   /* Calculate handle visibility */
   if (private->point_grabbed)
@@ -608,14 +784,14 @@ gimp_tool_line_update_handles (GimpToolLine *line)
                                                      private->mouse_x,
                                                      private->mouse_y,
                                                      0,
-                                                     2 * GIMP_CANVAS_HANDLE_SIZE_CROSS);
+                                                     2 * ENDPOINT_GRIP_HANDLE_SIZE);
       start_visible = start_diameter > 2;
 
       end_diameter = gimp_canvas_handle_calc_size (private->end_handle_circle,
                                                    private->mouse_x,
                                                    private->mouse_y,
                                                    0,
-                                                   2 * GIMP_CANVAS_HANDLE_SIZE_CROSS);
+                                                   2 * ENDPOINT_GRIP_HANDLE_SIZE);
       end_visible = end_diameter > 2;
     }
 
@@ -629,22 +805,68 @@ gimp_tool_line_update_handles (GimpToolLine *line)
   if (end_visible)
     gimp_canvas_handle_set_size (private->end_handle_circle,
                                  end_diameter, end_diameter);
+
+  for (i = 0; i < private->sliders->len; i++)
+    {
+      GimpCanvasItem *circle;
+      gboolean        visible;
+      gint            diameter;
+
+      circle = g_array_index (private->slider_handle_circles,
+                              GimpCanvasItem *, i);
+
+      if (private->point_grabbed)
+        visible = FALSE;
+      else
+        {
+          diameter = gimp_canvas_handle_calc_size (circle,
+                                                   private->mouse_x,
+                                                   private->mouse_y,
+                                                   0,
+                                                   2 * SLIDER_GRIP_HANDLE_SIZE);
+          visible = diameter > 2;
+        }
+
+      gimp_canvas_item_set_visible (circle, visible);
+
+      if (visible)
+        gimp_canvas_handle_set_size (circle, diameter, diameter);
+    }
 }
 
 static void
 gimp_tool_line_update_hilight (GimpToolLine *line)
 {
   GimpToolLinePrivate *private = line->private;
+  gint                 i;
 
   gimp_canvas_item_set_highlight (private->start_handle_circle,
                                   private->point == POINT_START);
-  gimp_canvas_item_set_highlight (private->start_handle_cross,
+  gimp_canvas_item_set_highlight (private->start_handle_grip,
                                   private->point == POINT_START);
 
   gimp_canvas_item_set_highlight (private->end_handle_circle,
                                   private->point == POINT_END);
-  gimp_canvas_item_set_highlight (private->end_handle_cross,
+  gimp_canvas_item_set_highlight (private->end_handle_grip,
                                   private->point == POINT_END);
+
+  for (i = 0; i < private->sliders->len; i++)
+    {
+      GimpCanvasItem *circle;
+      GimpCanvasItem *grip;
+      gboolean        highlight;
+
+      circle = g_array_index (private->slider_handle_circles,
+                              GimpCanvasItem *, i);
+      grip   = g_array_index (private->slider_handle_grips,
+                              GimpCanvasItem *, i);
+
+      highlight =
+        (private->point == POINT_SLIDER && private->slider_index == i);
+
+      gimp_canvas_item_set_highlight (circle, highlight);
+      gimp_canvas_item_set_highlight (grip,   highlight);
+    }
 }
 
 static void
@@ -700,3 +922,40 @@ gimp_tool_line_new (GimpDisplayShell *shell,
                        "y2",    y2,
                        NULL);
 }
+
+void
+gimp_tool_line_set_sliders (GimpToolLine               *line,
+                            const GimpControllerSlider *sliders,
+                            gint                        slider_count)
+{
+  GimpToolLinePrivate *private;
+
+  g_return_if_fail (GIMP_IS_TOOL_LINE (line));
+  g_return_if_fail (slider_count == 0 || (slider_count > 0 && sliders != NULL));
+
+  private = line->private;
+
+  g_array_set_size (private->sliders, slider_count);
+
+  memcpy (private->sliders->data, sliders,
+          slider_count * sizeof (GimpControllerSlider));
+
+  g_object_set (line,
+                "sliders", private->sliders,
+                NULL);
+}
+
+const GimpControllerSlider *
+gimp_tool_line_get_sliders (GimpToolLine *line,
+                            gint         *slider_count)
+{
+  GimpToolLinePrivate *private;
+
+  g_return_val_if_fail (GIMP_IS_TOOL_LINE (line), NULL);
+
+  private = line->private;
+
+  if (slider_count) *slider_count = private->sliders->len;
+
+  return (const GimpControllerSlider *) private->sliders->data;
+}
diff --git a/app/display/gimptoolline.h b/app/display/gimptoolline.h
index 1ce6b28..dfad2af 100644
--- a/app/display/gimptoolline.h
+++ b/app/display/gimptoolline.h
@@ -50,13 +50,19 @@ struct _GimpToolLineClass
 };
 
 
-GType            gimp_tool_line_get_type (void) G_GNUC_CONST;
+GType                        gimp_tool_line_get_type    (void) G_GNUC_CONST;
 
-GimpToolWidget * gimp_tool_line_new      (GimpDisplayShell *shell,
-                                          gdouble           x1,
-                                          gdouble           y1,
-                                          gdouble           x2,
-                                          gdouble           y2);
+GimpToolWidget             * gimp_tool_line_new         (GimpDisplayShell           *shell,
+                                                         gdouble                     x1,
+                                                         gdouble                     y1,
+                                                         gdouble                     x2,
+                                                         gdouble                     y2);
+
+void                         gimp_tool_line_set_sliders (GimpToolLine               *line,
+                                                         const GimpControllerSlider *sliders,
+                                                         gint                        slider_count);
+const GimpControllerSlider * gimp_tool_line_get_sliders (GimpToolLine               *line,
+                                                         gint                       *slider_count);
 
 
 #endif /* __GIMP_TOOL_LINE_H__ */
diff --git a/app/propgui/propgui-types.h b/app/propgui/propgui-types.h
index aae7fb4..94cb395 100644
--- a/app/propgui/propgui-types.h
+++ b/app/propgui/propgui-types.h
@@ -26,18 +26,37 @@
 
 typedef enum
 {
-  GIMP_CONTROLLER_TYPE_LINE
+  GIMP_CONTROLLER_TYPE_LINE,
+  GIMP_CONTROLLER_TYPE_SLIDER_LINE
 } GimpControllerType;
 
 
+/*  structs  */
+
+typedef struct
+{
+  gdouble value;
+  gdouble min;
+  gdouble max;
+} GimpControllerSlider;
+
+
 /*  function types  */
 
-typedef void (* GimpControllerLineCallback) (gpointer        data,
-                                             GeglRectangle  *area,
-                                             gdouble         x1,
-                                             gdouble         y1,
-                                             gdouble         x2,
-                                             gdouble         y2);
+typedef void (* GimpControllerLineCallback)       (gpointer                    data,
+                                                   GeglRectangle              *area,
+                                                   gdouble                     x1,
+                                                   gdouble                     y1,
+                                                   gdouble                     x2,
+                                                   gdouble                     y2);
+typedef void (* GimpControllerSliderLineCallback) (gpointer                    data,
+                                                   GeglRectangle              *area,
+                                                   gdouble                     x1,
+                                                   gdouble                     y1,
+                                                   gdouble                     x2,
+                                                   gdouble                     y2,
+                                                   const GimpControllerSlider *sliders,
+                                                   gint                        slider_count);
 
 
 typedef GtkWidget * (* GimpCreatePickerFunc)     (gpointer            creator,
diff --git a/app/tools/gimpfiltertool-widgets.c b/app/tools/gimpfiltertool-widgets.c
index c841a36..9b08dbb 100644
--- a/app/tools/gimpfiltertool-widgets.c
+++ b/app/tools/gimpfiltertool-widgets.c
@@ -48,14 +48,25 @@ struct _Controller
 
 /*  local function prototypes  */
 
-static void   gimp_filter_tool_set_line     (Controller     *controller,
-                                             GeglRectangle  *area,
-                                             gdouble         x1,
-                                             gdouble         y1,
-                                             gdouble         x2,
-                                             gdouble         y2);
-static void   gimp_filter_tool_line_changed (GimpToolWidget *widget,
-                                             Controller     *controller);
+static void   gimp_filter_tool_set_line            (Controller                 *controller,
+                                                    GeglRectangle              *area,
+                                                    gdouble                     x1,
+                                                    gdouble                     y1,
+                                                    gdouble                     x2,
+                                                    gdouble                     y2);
+static void   gimp_filter_tool_line_changed        (GimpToolWidget             *widget,
+                                                    Controller                 *controller);
+
+static void   gimp_filter_tool_set_slider_line     (Controller                 *controller,
+                                                    GeglRectangle              *area,
+                                                    gdouble                     x1,
+                                                    gdouble                     y1,
+                                                    gdouble                     x2,
+                                                    gdouble                     y2,
+                                                    const GimpControllerSlider *sliders,
+                                                    gint                        slider_count);
+static void   gimp_filter_tool_slider_line_changed (GimpToolWidget             *widget,
+                                                    Controller                 *controller);
 
 
 /*  public functions  */
@@ -99,6 +110,17 @@ gimp_filter_tool_create_widget (GimpFilterTool     *filter_tool,
       *set_func      = (GCallback) gimp_filter_tool_set_line;
       *set_func_data = controller;
       break;
+
+    case GIMP_CONTROLLER_TYPE_SLIDER_LINE:
+      controller->widget = gimp_tool_line_new (shell, 100, 100, 500, 500);
+
+      g_signal_connect (controller->widget, "changed",
+                        G_CALLBACK (gimp_filter_tool_slider_line_changed),
+                        controller);
+
+      *set_func      = (GCallback) gimp_filter_tool_set_slider_line;
+      *set_func_data = controller;
+      break;
     }
 
   g_object_set_data_full (G_OBJECT (controller->widget),
@@ -178,3 +200,82 @@ gimp_filter_tool_line_changed (GimpToolWidget *widget,
   line_callback (controller->creator_data,
                  &area, x1, y1, x2, y2);
 }
+
+static void
+gimp_filter_tool_set_slider_line (Controller                 *controller,
+                                  GeglRectangle              *area,
+                                  gdouble                     x1,
+                                  gdouble                     y1,
+                                  gdouble                     x2,
+                                  gdouble                     y2,
+                                  const GimpControllerSlider *sliders,
+                                  gint                        slider_count)
+{
+  GimpDrawable *drawable = controller->filter_tool->drawable;
+
+  if (drawable)
+    {
+      gint off_x, off_y;
+
+      gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
+
+      x1 += off_x + area->x;
+      y1 += off_y + area->y;
+      x2 += off_x + area->x;
+      y2 += off_y + area->y;
+    }
+
+  g_signal_handlers_block_by_func (controller->widget,
+                                   gimp_filter_tool_slider_line_changed,
+                                   controller);
+
+  g_object_set (controller->widget,
+                "x1", x1,
+                "y1", y1,
+                "x2", x2,
+                "y2", y2,
+                NULL);
+
+  gimp_tool_line_set_sliders (GIMP_TOOL_LINE (controller->widget),
+                              sliders, slider_count);
+
+  g_signal_handlers_unblock_by_func (controller->widget,
+                                     gimp_filter_tool_slider_line_changed,
+                                     controller);
+}
+
+static void
+gimp_filter_tool_slider_line_changed (GimpToolWidget *widget,
+                                      Controller     *controller)
+{
+  GimpFilterTool                   *filter_tool = controller->filter_tool;
+  GimpControllerSliderLineCallback  slider_line_callback;
+  gdouble                           x1, y1, x2, y2;
+  const GimpControllerSlider       *sliders;
+  gint                              slider_count;
+  gint                              off_x, off_y;
+  GeglRectangle                     area;
+
+  slider_line_callback =
+    (GimpControllerSliderLineCallback) controller->creator_callback;
+
+  g_object_get (widget,
+                "x1", &x1,
+                "y1", &y1,
+                "x2", &x2,
+                "y2", &y2,
+                NULL);
+
+  sliders = gimp_tool_line_get_sliders (GIMP_TOOL_LINE (controller->widget),
+                                        &slider_count);
+
+  gimp_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
+
+  x1 -= off_x + area.x;
+  y1 -= off_y + area.y;
+  x2 -= off_x + area.x;
+  y2 -= off_y + area.y;
+
+  slider_line_callback (controller->creator_data,
+                        &area, x1, y1, x2, y2, sliders, slider_count);
+}


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