[gimp] Bug 795230 - Rename Blend tool and provide PDB compatibility



commit b0beb0197a4bd2c14ded20da976d4affd0c94729
Author: Michael Natterer <mitch gimp org>
Date:   Sat Apr 14 00:52:20 2018 +0200

    Bug 795230 - Rename Blend tool and provide PDB compatibility
    
    Rename the tool and its options, and the gradient sub-struct of paint
    options.

 app/core/gimptoolpreset.c                          |    4 +-
 app/dialogs/dialogs.c                              |    2 +-
 app/paint/gimppaintoptions.c                       |   34 +-
 app/paint/gimppaintoptions.h                       |   12 +-
 app/tools/Makefile.am                              |   12 +-
 app/tools/gimp-tools.c                             |    4 +-
 app/tools/gimpblendtool-editor.c                   | 2518 --------------------
 app/tools/gimpblendtool-editor.h                   |   48 -
 app/tools/gimpblendtool.c                          | 1073 ---------
 .../{gimpblendoptions.c => gimpgradientoptions.c}  |  109 +-
 .../{gimpblendoptions.h => gimpgradientoptions.h}  |   28 +-
 app/tools/gimpgradienttool-editor.c                | 2517 +++++++++++++++++++
 app/tools/gimpgradienttool-editor.h                |   48 +
 app/tools/gimpgradienttool.c                       | 1073 +++++++++
 app/tools/{gimpblendtool.h => gimpgradienttool.h}  |   38 +-
 app/tools/tool_manager.c                           |    2 +-
 app/widgets/gimphelp-ids.h                         |    2 +-
 data/tool-presets/FX/FX-Radial-Softlight.gtp       |    6 +-
 data/tool-presets/FX/Vignette.gtp                  |    6 +-
 menus/image-menu.xml.in                            |    2 +-
 po/POTFILES.in                                     |    6 +-
 21 files changed, 3772 insertions(+), 3772 deletions(-)
---
diff --git a/app/core/gimptoolpreset.c b/app/core/gimptoolpreset.c
index 0a1a584..d26cafd 100644
--- a/app/core/gimptoolpreset.c
+++ b/app/core/gimptoolpreset.c
@@ -36,7 +36,7 @@
 
 
 /*  The defaults are "everything except color", which is problematic
- *  with gradients, which is why we special case the blend tool in
+ *  with gradients, which is why we special case the gradient tool in
  *  gimp_tool_preset_set_options().
  */
 #define DEFAULT_USE_FG_BG    FALSE
@@ -541,7 +541,7 @@ gimp_tool_preset_set_options (GimpToolPreset  *preset,
         g_object_set (preset, "use-font", FALSE, NULL);
 
       /*  see comment above the DEFAULT defines at the top of the file  */
-      if (! g_strcmp0 ("gimp-blend-tool",
+      if (! g_strcmp0 ("gimp-gradient-tool",
                        gimp_object_get_name (preset->tool_options->tool_info)))
         g_object_set (preset, "use-gradient", TRUE, NULL);
 
diff --git a/app/dialogs/dialogs.c b/app/dialogs/dialogs.c
index 9e36d5b..0445962 100644
--- a/app/dialogs/dialogs.c
+++ b/app/dialogs/dialogs.c
@@ -223,7 +223,6 @@ static GtkWidget * dialogs_restore_window (GimpDialogFactory *factory,
 static const GimpDialogFactoryEntry entries[] =
 {
   /*  foreign toplevels without constructor  */
-  FOREIGN ("gimp-blend-tool-dialog",               TRUE,  FALSE),
   FOREIGN ("gimp-brightness-contrast-tool-dialog", TRUE,  FALSE),
   FOREIGN ("gimp-color-balance-tool-dialog",       TRUE,  FALSE),
   FOREIGN ("gimp-color-picker-tool-dialog",        TRUE,  TRUE),
@@ -233,6 +232,7 @@ static const GimpDialogFactoryEntry entries[] =
   FOREIGN ("gimp-desaturate-tool-dialog",          TRUE,  FALSE),
   FOREIGN ("gimp-foreground-select-tool-dialog",   TRUE,  FALSE),
   FOREIGN ("gimp-gegl-tool-dialog",                TRUE,  FALSE),
+  FOREIGN ("gimp-gradient-tool-dialog",            TRUE,  FALSE),
   FOREIGN ("gimp-hue-saturation-tool-dialog",      TRUE,  FALSE),
   FOREIGN ("gimp-levels-tool-dialog",              TRUE,  TRUE),
   FOREIGN ("gimp-measure-tool-dialog",             TRUE,  FALSE),
diff --git a/app/paint/gimppaintoptions.c b/app/paint/gimppaintoptions.c
index de5d219..0c13501 100644
--- a/app/paint/gimppaintoptions.c
+++ b/app/paint/gimppaintoptions.c
@@ -445,7 +445,7 @@ gimp_paint_options_init (GimpPaintOptions *options)
 
   options->jitter_options    = g_slice_new0 (GimpJitterOptions);
   options->fade_options      = g_slice_new0 (GimpFadeOptions);
-  options->gradient_options  = g_slice_new0 (GimpGradientOptions);
+  options->gradient_options  = g_slice_new0 (GimpGradientPaintOptions);
   options->smoothing_options = g_slice_new0 (GimpSmoothingOptions);
 }
 
@@ -468,10 +468,10 @@ gimp_paint_options_finalize (GObject *object)
 {
   GimpPaintOptions *options = GIMP_PAINT_OPTIONS (object);
 
-  g_slice_free (GimpJitterOptions,    options->jitter_options);
-  g_slice_free (GimpFadeOptions,      options->fade_options);
-  g_slice_free (GimpGradientOptions,  options->gradient_options);
-  g_slice_free (GimpSmoothingOptions, options->smoothing_options);
+  g_slice_free (GimpJitterOptions,        options->jitter_options);
+  g_slice_free (GimpFadeOptions,          options->fade_options);
+  g_slice_free (GimpGradientPaintOptions, options->gradient_options);
+  g_slice_free (GimpSmoothingOptions,     options->smoothing_options);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -482,11 +482,11 @@ gimp_paint_options_set_property (GObject      *object,
                                  const GValue *value,
                                  GParamSpec   *pspec)
 {
-  GimpPaintOptions     *options           = GIMP_PAINT_OPTIONS (object);
-  GimpFadeOptions      *fade_options      = options->fade_options;
-  GimpJitterOptions    *jitter_options    = options->jitter_options;
-  GimpGradientOptions  *gradient_options  = options->gradient_options;
-  GimpSmoothingOptions *smoothing_options = options->smoothing_options;
+  GimpPaintOptions         *options           = GIMP_PAINT_OPTIONS (object);
+  GimpFadeOptions          *fade_options      = options->fade_options;
+  GimpJitterOptions        *jitter_options    = options->jitter_options;
+  GimpGradientPaintOptions *gradient_options  = options->gradient_options;
+  GimpSmoothingOptions     *smoothing_options = options->smoothing_options;
 
   switch (property_id)
     {
@@ -645,11 +645,11 @@ gimp_paint_options_get_property (GObject    *object,
                                  GValue     *value,
                                  GParamSpec *pspec)
 {
-  GimpPaintOptions     *options           = GIMP_PAINT_OPTIONS (object);
-  GimpFadeOptions      *fade_options      = options->fade_options;
-  GimpJitterOptions    *jitter_options    = options->jitter_options;
-  GimpGradientOptions  *gradient_options  = options->gradient_options;
-  GimpSmoothingOptions *smoothing_options = options->smoothing_options;
+  GimpPaintOptions         *options           = GIMP_PAINT_OPTIONS (object);
+  GimpFadeOptions          *fade_options      = options->fade_options;
+  GimpJitterOptions        *jitter_options    = options->jitter_options;
+  GimpGradientPaintOptions *gradient_options  = options->gradient_options;
+  GimpSmoothingOptions     *smoothing_options = options->smoothing_options;
 
   switch (property_id)
     {
@@ -958,8 +958,8 @@ gimp_paint_options_get_gradient_color (GimpPaintOptions *paint_options,
 
   if (gimp_dynamics_is_output_enabled (dynamics, GIMP_DYNAMICS_OUTPUT_COLOR))
     {
-      GimpGradientOptions *gradient_options = paint_options->gradient_options;
-      GimpGradient        *gradient;
+      GimpGradientPaintOptions *gradient_options = paint_options->gradient_options;
+      GimpGradient             *gradient;
 
       gradient = gimp_context_get_gradient (GIMP_CONTEXT (paint_options));
 
diff --git a/app/paint/gimppaintoptions.h b/app/paint/gimppaintoptions.h
index 19b18e5..7933d64 100644
--- a/app/paint/gimppaintoptions.h
+++ b/app/paint/gimppaintoptions.h
@@ -31,10 +31,10 @@
                                         GIMP_CONTEXT_PROP_MASK_PALETTE
 
 
-typedef struct _GimpJitterOptions   GimpJitterOptions;
-typedef struct _GimpFadeOptions     GimpFadeOptions;
-typedef struct _GimpGradientOptions GimpGradientOptions;
-typedef struct _GimpSmoothingOptions GimpSmoothingOptions;
+typedef struct _GimpJitterOptions        GimpJitterOptions;
+typedef struct _GimpFadeOptions          GimpFadeOptions;
+typedef struct _GimpGradientPaintOptions GimpGradientPaintOptions;
+typedef struct _GimpSmoothingOptions     GimpSmoothingOptions;
 
 struct _GimpJitterOptions
 {
@@ -50,7 +50,7 @@ struct _GimpFadeOptions
   GimpRepeatMode  fade_repeat;
 };
 
-struct _GimpGradientOptions
+struct _GimpGradientPaintOptions
 {
   gboolean                    gradient_reverse;
   GimpGradientBlendColorSpace gradient_blend_color_space;
@@ -109,7 +109,7 @@ struct _GimpPaintOptions
 
   gboolean                  dynamics_expanded;
   GimpFadeOptions          *fade_options;
-  GimpGradientOptions      *gradient_options;
+  GimpGradientPaintOptions *gradient_options;
   GimpSmoothingOptions     *smoothing_options;
 
   GimpViewType              brush_view_type;
diff --git a/app/tools/Makefile.am b/app/tools/Makefile.am
index b4e3cbe..46770cd 100644
--- a/app/tools/Makefile.am
+++ b/app/tools/Makefile.am
@@ -26,12 +26,6 @@ libapptools_a_sources = \
        gimpalignoptions.h              \
        gimpaligntool.c                 \
        gimpaligntool.h                 \
-       gimpblendoptions.c              \
-       gimpblendoptions.h              \
-       gimpblendtool.c                 \
-       gimpblendtool.h                 \
-       gimpblendtool-editor.c          \
-       gimpblendtool-editor.h          \
        gimpbrightnesscontrasttool.c    \
        gimpbrightnesscontrasttool.h    \
        gimpbrushtool.c                 \
@@ -102,6 +96,12 @@ libapptools_a_sources = \
        gimpgegltool.h                  \
        gimpgenerictransformtool.c      \
        gimpgenerictransformtool.h      \
+       gimpgradientoptions.c           \
+       gimpgradientoptions.h           \
+       gimpgradienttool.c              \
+       gimpgradienttool.h              \
+       gimpgradienttool-editor.c       \
+       gimpgradienttool-editor.h       \
        gimpguidetool.c                 \
        gimpguidetool.h                 \
        gimphandletransformoptions.c    \
diff --git a/app/tools/gimp-tools.c b/app/tools/gimp-tools.c
index 9b9c4d0..d511e74 100644
--- a/app/tools/gimp-tools.c
+++ b/app/tools/gimp-tools.c
@@ -41,7 +41,6 @@
 
 #include "gimpairbrushtool.h"
 #include "gimpaligntool.h"
-#include "gimpblendtool.h"
 #include "gimpbrightnesscontrasttool.h"
 #include "gimpbucketfilltool.h"
 #include "gimpbycolorselecttool.h"
@@ -59,6 +58,7 @@
 #include "gimpforegroundselecttool.h"
 #include "gimpfuzzyselecttool.h"
 #include "gimpgegltool.h"
+#include "gimpgradienttool.h"
 #include "gimphandletransformtool.h"
 #include "gimphealtool.h"
 #include "gimpinktool.h"
@@ -159,7 +159,7 @@ gimp_tools_init (Gimp *gimp)
     gimp_seamless_clone_tool_register,
     gimp_text_tool_register,
     gimp_bucket_fill_tool_register,
-    gimp_blend_tool_register,
+    gimp_gradient_tool_register,
     gimp_pencil_tool_register,
     gimp_paintbrush_tool_register,
     gimp_eraser_tool_register,
diff --git a/app/tools/gimpblendoptions.c b/app/tools/gimpgradientoptions.c
similarity index 77%
rename from app/tools/gimpblendoptions.c
rename to app/tools/gimpgradientoptions.c
index 7ef1d99..391db53 100644
--- a/app/tools/gimpblendoptions.c
+++ b/app/tools/gimpgradientoptions.c
@@ -33,7 +33,7 @@
 #include "widgets/gimpviewablebox.h"
 #include "widgets/gimpwidgets-utils.h"
 
-#include "gimpblendoptions.h"
+#include "gimpgradientoptions.h"
 #include "gimppaintoptions-gui.h"
 
 #include "gimp-intl.h"
@@ -55,33 +55,34 @@ enum
 };
 
 
-static void   gimp_blend_options_set_property           (GObject          *object,
-                                                         guint             property_id,
-                                                         const GValue     *value,
-                                                         GParamSpec       *pspec);
-static void   gimp_blend_options_get_property           (GObject          *object,
-                                                         guint             property_id,
-                                                         GValue           *value,
-                                                         GParamSpec       *pspec);
+static void   gimp_gradient_options_set_property           (GObject             *object,
+                                                            guint                property_id,
+                                                            const GValue        *value,
+                                                            GParamSpec          *pspec);
+static void   gimp_gradient_options_get_property           (GObject             *object,
+                                                            guint                property_id,
+                                                            GValue              *value,
+                                                            GParamSpec          *pspec);
 
-static void   blend_options_repeat_gradient_type_notify (GimpBlendOptions *options,
-                                                         GParamSpec       *pspec,
-                                                         GtkWidget        *repeat_combo);
-static void   blend_options_metric_gradient_type_notify (GimpBlendOptions *options,
-                                                         GParamSpec       *pspec,
-                                                         GtkWidget        *repeat_combo);
+static void   gradient_options_repeat_gradient_type_notify (GimpGradientOptions *options,
+                                                            GParamSpec          *pspec,
+                                                            GtkWidget           *repeat_combo);
+static void   gradient_options_metric_gradient_type_notify (GimpGradientOptions *options,
+                                                            GParamSpec          *pspec,
+                                                            GtkWidget           *repeat_combo);
 
 
-G_DEFINE_TYPE (GimpBlendOptions, gimp_blend_options, GIMP_TYPE_PAINT_OPTIONS)
+G_DEFINE_TYPE (GimpGradientOptions, gimp_gradient_options,
+               GIMP_TYPE_PAINT_OPTIONS)
 
 
 static void
-gimp_blend_options_class_init (GimpBlendOptionsClass *klass)
+gimp_gradient_options_class_init (GimpGradientOptionsClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  object_class->set_property = gimp_blend_options_set_property;
-  object_class->get_property = gimp_blend_options_get_property;
+  object_class->set_property = gimp_gradient_options_set_property;
+  object_class->get_property = gimp_gradient_options_get_property;
 
   GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_OFFSET,
                            "offset",
@@ -153,17 +154,17 @@ gimp_blend_options_class_init (GimpBlendOptionsClass *klass)
 }
 
 static void
-gimp_blend_options_init (GimpBlendOptions *options)
+gimp_gradient_options_init (GimpGradientOptions *options)
 {
 }
 
 static void
-gimp_blend_options_set_property (GObject      *object,
-                                 guint         property_id,
-                                 const GValue *value,
-                                 GParamSpec   *pspec)
+gimp_gradient_options_set_property (GObject      *object,
+                                    guint         property_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
 {
-  GimpBlendOptions *options = GIMP_BLEND_OPTIONS (object);
+  GimpGradientOptions *options = GIMP_GRADIENT_OPTIONS (object);
 
   switch (property_id)
     {
@@ -209,12 +210,12 @@ gimp_blend_options_set_property (GObject      *object,
 }
 
 static void
-gimp_blend_options_get_property (GObject    *object,
-                                 guint       property_id,
-                                 GValue     *value,
-                                 GParamSpec *pspec)
+gimp_gradient_options_get_property (GObject    *object,
+                                    guint       property_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
 {
-  GimpBlendOptions *options = GIMP_BLEND_OPTIONS (object);
+  GimpGradientOptions *options = GIMP_GRADIENT_OPTIONS (object);
 
   switch (property_id)
     {
@@ -260,21 +261,21 @@ gimp_blend_options_get_property (GObject    *object,
 }
 
 GtkWidget *
-gimp_blend_options_gui (GimpToolOptions *tool_options)
+gimp_gradient_options_gui (GimpToolOptions *tool_options)
 {
-  GObject          *config  = G_OBJECT (tool_options);
-  GimpContext      *context = GIMP_CONTEXT (tool_options);
-  GimpBlendOptions *options = GIMP_BLEND_OPTIONS (tool_options);
-  GtkWidget        *vbox    = gimp_paint_options_gui (tool_options);
-  GtkWidget        *vbox2;
-  GtkWidget        *frame;
-  GtkWidget        *scale;
-  GtkWidget        *combo;
-  GtkWidget        *button;
-  GtkWidget        *label;
-  gchar            *str;
-  GdkModifierType   extend_mask;
-  GimpGradient     *gradient;
+  GObject             *config  = G_OBJECT (tool_options);
+  GimpContext         *context = GIMP_CONTEXT (tool_options);
+  GimpGradientOptions *options = GIMP_GRADIENT_OPTIONS (tool_options);
+  GtkWidget           *vbox    = gimp_paint_options_gui (tool_options);
+  GtkWidget           *vbox2;
+  GtkWidget           *frame;
+  GtkWidget           *scale;
+  GtkWidget           *combo;
+  GtkWidget           *button;
+  GtkWidget           *label;
+  gchar               *str;
+  GdkModifierType      extend_mask;
+  GimpGradient        *gradient;
 
   extend_mask = gimp_get_extend_selection_mask ();
 
@@ -316,9 +317,9 @@ gimp_blend_options_gui (GimpToolOptions *tool_options)
   gtk_widget_show (combo);
 
   g_signal_connect (config, "notify::gradient-type",
-                    G_CALLBACK (blend_options_metric_gradient_type_notify),
+                    G_CALLBACK (gradient_options_metric_gradient_type_notify),
                     combo);
-  blend_options_metric_gradient_type_notify (options, NULL, combo);
+  gradient_options_metric_gradient_type_notify (options, NULL, combo);
 
   /*  the repeat option  */
   combo = gimp_prop_enum_combo_box_new (config, "gradient-repeat", 0, 0);
@@ -328,9 +329,9 @@ gimp_blend_options_gui (GimpToolOptions *tool_options)
   gtk_widget_show (combo);
 
   g_signal_connect (config, "notify::gradient-type",
-                    G_CALLBACK (blend_options_repeat_gradient_type_notify),
+                    G_CALLBACK (gradient_options_repeat_gradient_type_notify),
                     combo);
-  blend_options_repeat_gradient_type_notify (options, NULL, combo);
+  gradient_options_repeat_gradient_type_notify (options, NULL, combo);
 
   /*  the offset scale  */
   scale = gimp_prop_spin_scale_new (config, "offset", NULL,
@@ -410,18 +411,18 @@ gimp_blend_options_gui (GimpToolOptions *tool_options)
 }
 
 static void
-blend_options_repeat_gradient_type_notify (GimpBlendOptions *options,
-                                           GParamSpec       *pspec,
-                                           GtkWidget        *repeat_combo)
+gradient_options_repeat_gradient_type_notify (GimpGradientOptions *options,
+                                              GParamSpec       *pspec,
+                                              GtkWidget        *repeat_combo)
 {
   gtk_widget_set_sensitive (repeat_combo,
                             options->gradient_type < GIMP_GRADIENT_SHAPEBURST_ANGULAR);
 }
 
 static void
-blend_options_metric_gradient_type_notify (GimpBlendOptions *options,
-                                           GParamSpec       *pspec,
-                                           GtkWidget        *repeat_combo)
+gradient_options_metric_gradient_type_notify (GimpGradientOptions *options,
+                                              GParamSpec       *pspec,
+                                              GtkWidget        *repeat_combo)
 {
   gtk_widget_set_sensitive (repeat_combo,
                             options->gradient_type >= GIMP_GRADIENT_SHAPEBURST_ANGULAR &&
diff --git a/app/tools/gimpblendoptions.h b/app/tools/gimpgradientoptions.h
similarity index 53%
rename from app/tools/gimpblendoptions.h
rename to app/tools/gimpgradientoptions.h
index 53a02f5..0a6e596 100644
--- a/app/tools/gimpblendoptions.h
+++ b/app/tools/gimpgradientoptions.h
@@ -15,25 +15,25 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef  __GIMP_BLEND_OPTIONS_H__
-#define  __GIMP_BLEND_OPTIONS_H__
+#ifndef  __GIMP_GRADIENT_OPTIONS_H__
+#define  __GIMP_GRADIENT_OPTIONS_H__
 
 
 #include "paint/gimppaintoptions.h"
 
 
-#define GIMP_TYPE_BLEND_OPTIONS            (gimp_blend_options_get_type ())
-#define GIMP_BLEND_OPTIONS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_BLEND_OPTIONS, 
GimpBlendOptions))
-#define GIMP_BLEND_OPTIONS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_BLEND_OPTIONS, 
GimpBlendOptionsClass))
-#define GIMP_IS_BLEND_OPTIONS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_BLEND_OPTIONS))
-#define GIMP_IS_BLEND_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_BLEND_OPTIONS))
-#define GIMP_BLEND_OPTIONS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_BLEND_OPTIONS, 
GimpBlendOptionsClass))
+#define GIMP_TYPE_GRADIENT_OPTIONS            (gimp_gradient_options_get_type ())
+#define GIMP_GRADIENT_OPTIONS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GIMP_TYPE_GRADIENT_OPTIONS, GimpGradientOptions))
+#define GIMP_GRADIENT_OPTIONS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_GRADIENT_OPTIONS, 
GimpGradientOptionsClass))
+#define GIMP_IS_GRADIENT_OPTIONS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
GIMP_TYPE_GRADIENT_OPTIONS))
+#define GIMP_IS_GRADIENT_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_GRADIENT_OPTIONS))
+#define GIMP_GRADIENT_OPTIONS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_GRADIENT_OPTIONS, 
GimpGradientOptionsClass))
 
 
-typedef struct _GimpBlendOptions      GimpBlendOptions;
-typedef struct _GimpPaintOptionsClass GimpBlendOptionsClass;
+typedef struct _GimpGradientOptions   GimpGradientOptions;
+typedef struct _GimpPaintOptionsClass GimpGradientOptionsClass;
 
-struct _GimpBlendOptions
+struct _GimpGradientOptions
 {
   GimpPaintOptions   paint_options;
 
@@ -57,9 +57,9 @@ struct _GimpBlendOptions
 };
 
 
-GType       gimp_blend_options_get_type (void) G_GNUC_CONST;
+GType       gimp_gradient_options_get_type (void) G_GNUC_CONST;
 
-GtkWidget * gimp_blend_options_gui      (GimpToolOptions *tool_options);
+GtkWidget * gimp_gradient_options_gui      (GimpToolOptions *tool_options);
 
 
-#endif  /*  __GIMP_BLEND_OPTIONS_H__  */
+#endif  /*  __GIMP_GRADIENT_OPTIONS_H__  */
diff --git a/app/tools/gimpgradienttool-editor.c b/app/tools/gimpgradienttool-editor.c
new file mode 100644
index 0000000..37b7c81
--- /dev/null
+++ b/app/tools/gimpgradienttool-editor.c
@@ -0,0 +1,2517 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpmath/gimpmath.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "tools-types.h"
+
+#include "operations/gimp-operation-config.h"
+
+#include "core/gimpdata.h"
+#include "core/gimpgradient.h"
+#include "core/gimp-gradients.h"
+#include "core/gimpimage.h"
+
+#include "widgets/gimpcolorpanel.h"
+#include "widgets/gimpeditor.h"
+#include "widgets/gimpwidgets-utils.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+#include "display/gimptoolgui.h"
+#include "display/gimptoolline.h"
+
+#include "gimpgradientoptions.h"
+#include "gimpgradienttool.h"
+#include "gimpgradienttool-editor.h"
+
+#include "gimp-intl.h"
+
+
+#define EPSILON 2e-10
+
+
+typedef enum
+{
+  DIRECTION_NONE,
+  DIRECTION_LEFT,
+  DIRECTION_RIGHT
+} Direction;
+
+
+typedef struct
+{
+  /* line endpoints at the beginning of the operation */
+  gdouble       start_x;
+  gdouble       start_y;
+  gdouble       end_x;
+  gdouble       end_y;
+
+  /* copy of the gradient at the beginning of the operation, owned by the gradient
+   * info, or NULL, if the gradient isn't affected
+   */
+  GimpGradient *gradient;
+
+  /* handle added by the operation, or HANDLE_NONE */
+  gint          added_handle;
+  /* handle removed by the operation, or HANDLE_NONE */
+  gint          removed_handle;
+  /* selected handle at the end of the operation, or HANDLE_NONE */
+  gint          selected_handle;
+} GradientInfo;
+
+
+/*  local function prototypes  */
+
+static gboolean              gimp_gradient_tool_editor_line_can_add_slider           (GimpToolLine          
*line,
+                                                                                      gdouble                
value,
+                                                                                      GimpGradientTool      
*gradient_tool);
+static gint                  gimp_gradient_tool_editor_line_add_slider               (GimpToolLine          
*line,
+                                                                                      gdouble                
value,
+                                                                                      GimpGradientTool      
*gradient_tool);
+static void                  gimp_gradient_tool_editor_line_prepare_to_remove_slider (GimpToolLine          
*line,
+                                                                                      gint                   
slider,
+                                                                                      gboolean               
remove,
+                                                                                      GimpGradientTool      
*gradient_tool);
+static void                  gimp_gradient_tool_editor_line_remove_slider            (GimpToolLine          
*line,
+                                                                                      gint                   
slider,
+                                                                                      GimpGradientTool      
*gradient_tool);
+static void                  gimp_gradient_tool_editor_line_selection_changed        (GimpToolLine          
*line,
+                                                                                      GimpGradientTool      
*gradient_tool);
+static gboolean              gimp_gradient_tool_editor_line_handle_clicked           (GimpToolLine          
*line,
+                                                                                      gint                   
handle,
+                                                                                      GdkModifierType        
state,
+                                                                                      GimpButtonPressType    
press_type,
+                                                                                      GimpGradientTool      
*gradient_tool);
+
+static void                  gimp_gradient_tool_editor_gui_response                  (GimpToolGui           
*gui,
+                                                                                      gint                   
response_id,
+                                                                                      GimpGradientTool      
*gradient_tool);
+
+static void                  gimp_gradient_tool_editor_color_entry_color_clicked     (GimpColorButton       
*button,
+                                                                                      GimpGradientTool      
*gradient_tool);
+static void                  gimp_gradient_tool_editor_color_entry_color_changed     (GimpColorButton       
*button,
+                                                                                      GimpGradientTool      
*gradient_tool);
+static void                  gimp_gradient_tool_editor_color_entry_color_response    (GimpColorButton       
*button,
+                                                                                      GimpColorDialogState   
state,
+                                                                                      GimpGradientTool      
*gradient_tool);
+
+static void                  gimp_gradient_tool_editor_color_entry_type_changed      (GtkComboBox           
*combo,
+                                                                                      GimpGradientTool      
*gradient_tool);
+
+static void                  gimp_gradient_tool_editor_endpoint_se_value_changed     (GimpSizeEntry         
*se,
+                                                                                      GimpGradientTool      
*gradient_tool);
+
+static void                  gimp_gradient_tool_editor_stop_se_value_changed         (GimpSizeEntry        
*se,
+                                                                                      GimpGradientTool     
*gradient_tool);
+
+static void                  gimp_gradient_tool_editor_stop_delete_clicked           (GtkWidget             
*button,
+                                                                                      GimpGradientTool      
*gradient_tool);
+
+static void                  gimp_gradient_tool_editor_midpoint_se_value_changed     (GimpSizeEntry        
*se,
+                                                                                      GimpGradientTool     
*gradient_tool);
+
+static void                  gimp_gradient_tool_editor_midpoint_type_changed         (GtkComboBox           
*combo,
+                                                                                      GimpGradientTool      
*gradient_tool);
+
+static void                  gimp_gradient_tool_editor_midpoint_color_changed        (GtkComboBox           
*combo,
+                                                                                      GimpGradientTool      
*gradient_tool);
+
+static void                  gimp_gradient_tool_editor_midpoint_new_stop_clicked     (GtkWidget             
*button,
+                                                                                      GimpGradientTool      
*gradient_tool);
+static void                  gimp_gradient_tool_editor_midpoint_center_clicked       (GtkWidget             
*button,
+                                                                                      GimpGradientTool      
*gradient_tool);
+
+static gboolean              gimp_gradient_tool_editor_flush_idle                    (GimpGradientTool      
*gradient_tool);
+
+static gboolean              gimp_gradient_tool_editor_is_gradient_editable          (GimpGradientTool      
*gradient_tool);
+
+static gboolean              gimp_gradient_tool_editor_handle_is_endpoint            (GimpGradientTool      
*gradient_tool,
+                                                                                      gint                   
handle);
+static gboolean              gimp_gradient_tool_editor_handle_is_stop                (GimpGradientTool      
*gradient_tool,
+                                                                                      gint                   
handle);
+static gboolean              gimp_gradient_tool_editor_handle_is_midpoint            (GimpGradientTool      
*gradient_tool,
+                                                                                      gint                   
handle);
+static GimpGradientSegment * gimp_gradient_tool_editor_handle_get_segment            (GimpGradientTool      
*gradient_tool,
+                                                                                      gint                   
handle);
+
+static void                  gimp_gradient_tool_editor_block_handlers                (GimpGradientTool      
*gradient_tool);
+static void                  gimp_gradient_tool_editor_unblock_handlers              (GimpGradientTool      
*gradient_tool);
+static gboolean              gimp_gradient_tool_editor_are_handlers_blocked          (GimpGradientTool      
*gradient_tool);
+
+static void                  gimp_gradient_tool_editor_freeze_gradient               (GimpGradientTool      
*gradient_tool);
+static void                  gimp_gradient_tool_editor_thaw_gradient                 (GimpGradientTool      
*gradient_tool);
+
+static gint                  gimp_gradient_tool_editor_add_stop                      (GimpGradientTool      
*gradient_tool,
+                                                                                      gdouble                
value);
+static void                  gimp_gradient_tool_editor_delete_stop                   (GimpGradientTool      
*gradient_tool,
+                                                                                      gint                   
slider);
+static gint                  gimp_gradient_tool_editor_midpoint_to_stop              (GimpGradientTool      
*gradient_tool,
+                                                                                      gint                   
slider);
+
+static void                  gimp_gradient_tool_editor_update_sliders                (GimpGradientTool      
*gradient_tool);
+
+static void                  gimp_gradient_tool_editor_purge_gradient_history        (GSList               
**stack);
+static void                  gimp_gradient_tool_editor_purge_gradient                (GimpGradientTool      
*gradient_tool);
+
+static GtkWidget           * gimp_gradient_tool_editor_color_entry_new               (GimpGradientTool      
*gradient_tool,
+                                                                                      const gchar           
*title,
+                                                                                      Direction              
direction,
+                                                                                      GtkWidget             
*chain_button,
+                                                                                      GtkWidget            
**color_panel,
+                                                                                      GtkWidget            
**type_combo);
+static void                  gimp_gradient_tool_editor_init_endpoint_gui             (GimpGradientTool      
*gradient_tool);
+static void                  gimp_gradient_tool_editor_init_stop_gui                 (GimpGradientTool      
*gradient_tool);
+static void                  gimp_gradient_tool_editor_init_midpoint_gui             (GimpGradientTool      
*gradient_tool);
+static void                  gimp_gradient_tool_editor_update_endpoint_gui           (GimpGradientTool      
*gradient_tool,
+                                                                                      gint                   
selection);
+static void                  gimp_gradient_tool_editor_update_stop_gui               (GimpGradientTool      
*gradient_tool,
+                                                                                      gint                   
selection);
+static void                  gimp_gradient_tool_editor_update_midpoint_gui           (GimpGradientTool      
*gradient_tool,
+                                                                                      gint                   
selection);
+static void                  gimp_gradient_tool_editor_update_gui                    (GimpGradientTool      
*gradient_tool);
+
+static GradientInfo        * gimp_gradient_tool_editor_gradient_info_new             (GimpGradientTool      
*gradient_tool);
+static void                  gimp_gradient_tool_editor_gradient_info_free            (GradientInfo          
*info);
+static void                  gimp_gradient_tool_editor_gradient_info_apply           (GimpGradientTool      
*gradient_tool,
+                                                                                      const GradientInfo    
*info,
+                                                                                      gboolean               
set_selection);
+static gboolean              gimp_gradient_tool_editor_gradient_info_is_trivial      (GimpGradientTool      
*gradient_tool,
+                                                                                      const GradientInfo    
*info);
+
+
+/*  private functions  */
+
+
+static gboolean
+gimp_gradient_tool_editor_line_can_add_slider (GimpToolLine  *line,
+                                               gdouble        value,
+                                               GimpGradientTool *gradient_tool)
+{
+  GimpGradientOptions *options = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+  gdouble              offset  = options->offset / 100.0;
+
+  return gimp_gradient_tool_editor_is_gradient_editable (gradient_tool) &&
+         value >= offset;
+}
+
+static gint
+gimp_gradient_tool_editor_line_add_slider (GimpToolLine     *line,
+                                           gdouble           value,
+                                           GimpGradientTool *gradient_tool)
+{
+  GimpGradientOptions *options       = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+  GimpPaintOptions    *paint_options = GIMP_PAINT_OPTIONS (options);
+  gdouble              offset        = options->offset / 100.0;
+
+  /* adjust slider value according to the offset */
+  value = (value - offset) / (1.0 - offset);
+
+  /* flip the slider value, if necessary */
+  if (paint_options->gradient_options->gradient_reverse)
+    value = 1.0 - value;
+
+  return gimp_gradient_tool_editor_add_stop (gradient_tool, value);
+}
+
+static void
+gimp_gradient_tool_editor_line_prepare_to_remove_slider (GimpToolLine     *line,
+                                                         gint              slider,
+                                                         gboolean          remove,
+                                                         GimpGradientTool *gradient_tool)
+{
+  if (remove)
+    {
+      GradientInfo *info;
+      GimpGradient *tentative_gradient;
+
+      /* show a tentative gradient, demonstrating the result of actually
+       * removing the slider
+       */
+
+      info = gradient_tool->undo_stack->data;
+
+      if (info->added_handle == slider)
+        {
+          /* see comment in gimp_gradient_tool_editor_delete_stop() */
+
+          gimp_assert (info->gradient != NULL);
+
+          tentative_gradient = g_object_ref (info->gradient);
+        }
+      else
+        {
+          GimpGradientSegment *seg;
+          gint                 i;
+
+          tentative_gradient =
+            GIMP_GRADIENT (gimp_data_duplicate (GIMP_DATA (gradient_tool->gradient)));
+
+          seg = gimp_gradient_tool_editor_handle_get_segment (gradient_tool, slider);
+
+          i = gimp_gradient_segment_range_get_n_segments (gradient_tool->gradient,
+                                                          gradient_tool->gradient->segments,
+                                                          seg) - 1;
+
+          seg = gimp_gradient_segment_get_nth (tentative_gradient->segments, i);
+
+          gimp_gradient_segment_range_merge (tentative_gradient,
+                                             seg, seg->next, NULL, NULL);
+        }
+
+      gimp_gradient_tool_set_tentative_gradient (gradient_tool, tentative_gradient);
+
+      g_object_unref (tentative_gradient);
+    }
+  else
+    {
+      gimp_gradient_tool_set_tentative_gradient (gradient_tool, NULL);
+    }
+}
+
+static void
+gimp_gradient_tool_editor_line_remove_slider (GimpToolLine     *line,
+                                              gint              slider,
+                                              GimpGradientTool *gradient_tool)
+{
+  gimp_gradient_tool_editor_delete_stop (gradient_tool, slider);
+  gimp_gradient_tool_set_tentative_gradient (gradient_tool, NULL);
+}
+
+static void
+gimp_gradient_tool_editor_line_selection_changed (GimpToolLine     *line,
+                                                  GimpGradientTool *gradient_tool)
+{
+  gint selection;
+
+  selection =
+    gimp_tool_line_get_selection (GIMP_TOOL_LINE (gradient_tool->widget));
+
+  if (gradient_tool->gui)
+    {
+      /* hide all color dialogs */
+      gimp_color_panel_dialog_response (
+        GIMP_COLOR_PANEL (gradient_tool->endpoint_color_panel),
+        GIMP_COLOR_DIALOG_OK);
+      gimp_color_panel_dialog_response (
+        GIMP_COLOR_PANEL (gradient_tool->stop_left_color_panel),
+        GIMP_COLOR_DIALOG_OK);
+      gimp_color_panel_dialog_response (
+        GIMP_COLOR_PANEL (gradient_tool->stop_right_color_panel),
+        GIMP_COLOR_DIALOG_OK);
+
+      /* reset the stop colors chain button */
+      if (gimp_gradient_tool_editor_handle_is_stop (gradient_tool, selection))
+        {
+          const GimpGradientSegment *seg;
+          gboolean                   homogeneous;
+
+          seg = gimp_gradient_tool_editor_handle_get_segment (gradient_tool,
+                                                              selection);
+
+          homogeneous = seg->right_color.r    == seg->next->left_color.r &&
+                        seg->right_color.g    == seg->next->left_color.g &&
+                        seg->right_color.b    == seg->next->left_color.b &&
+                        seg->right_color.a    == seg->next->left_color.a &&
+                        seg->right_color_type == seg->next->left_color_type;
+
+          gimp_chain_button_set_active (
+            GIMP_CHAIN_BUTTON (gradient_tool->stop_chain_button), homogeneous);
+        }
+    }
+
+  gimp_gradient_tool_editor_update_gui (gradient_tool);
+}
+
+static gboolean
+gimp_gradient_tool_editor_line_handle_clicked (GimpToolLine        *line,
+                                               gint                 handle,
+                                               GdkModifierType      state,
+                                               GimpButtonPressType  press_type,
+                                               GimpGradientTool    *gradient_tool)
+{
+  if (gimp_gradient_tool_editor_handle_is_midpoint (gradient_tool, handle))
+    {
+      if (press_type == GIMP_BUTTON_PRESS_DOUBLE &&
+          gimp_gradient_tool_editor_is_gradient_editable (gradient_tool))
+        {
+          gint stop;
+
+          stop = gimp_gradient_tool_editor_midpoint_to_stop (gradient_tool, handle);
+
+          gimp_tool_line_set_selection (line, stop);
+
+          /* return FALSE, so that the new slider can be dragged immediately */
+          return FALSE;
+        }
+    }
+
+  return FALSE;
+}
+
+
+static void
+gimp_gradient_tool_editor_gui_response (GimpToolGui      *gui,
+                                        gint              response_id,
+                                        GimpGradientTool *gradient_tool)
+{
+  switch (response_id)
+    {
+    default:
+      gimp_tool_line_set_selection (GIMP_TOOL_LINE (gradient_tool->widget),
+                                    GIMP_TOOL_LINE_HANDLE_NONE);
+      break;
+    }
+}
+
+static void
+gimp_gradient_tool_editor_color_entry_color_clicked (GimpColorButton  *button,
+                                                     GimpGradientTool *gradient_tool)
+{
+  gimp_gradient_tool_editor_start_edit (gradient_tool);
+}
+
+static void
+gimp_gradient_tool_editor_color_entry_color_changed (GimpColorButton  *button,
+                                                     GimpGradientTool *gradient_tool)
+{
+  GimpGradientOptions *options       = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+  GimpPaintOptions    *paint_options = GIMP_PAINT_OPTIONS (options);
+  gint                 selection;
+  GimpRGB              color;
+  Direction            direction;
+  GtkWidget           *chain_button;
+  GimpGradientSegment *seg;
+
+  if (gimp_gradient_tool_editor_are_handlers_blocked (gradient_tool))
+    return;
+
+  selection =
+    gimp_tool_line_get_selection (GIMP_TOOL_LINE (gradient_tool->widget));
+
+  gimp_color_button_get_color (button, &color);
+
+  direction =
+    GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),
+                                        "gimp-gradient-tool-editor-direction"));
+  chain_button = g_object_get_data (G_OBJECT (button),
+                                    "gimp-gradient-tool-editor-chain-button");
+
+  gimp_gradient_tool_editor_start_edit (gradient_tool);
+  gimp_gradient_tool_editor_freeze_gradient (gradient_tool);
+
+  /* swap the endpoint handles, if necessary */
+  if (paint_options->gradient_options->gradient_reverse)
+    {
+      switch (selection)
+        {
+        case GIMP_TOOL_LINE_HANDLE_START:
+          selection = GIMP_TOOL_LINE_HANDLE_END;
+          break;
+
+        case GIMP_TOOL_LINE_HANDLE_END:
+          selection = GIMP_TOOL_LINE_HANDLE_START;
+          break;
+        }
+    }
+
+  seg = gimp_gradient_tool_editor_handle_get_segment (gradient_tool, selection);
+
+  switch (selection)
+    {
+    case GIMP_TOOL_LINE_HANDLE_START:
+      seg->left_color      = color;
+      seg->left_color_type = GIMP_GRADIENT_COLOR_FIXED;
+      break;
+
+    case GIMP_TOOL_LINE_HANDLE_END:
+      seg->right_color      = color;
+      seg->right_color_type = GIMP_GRADIENT_COLOR_FIXED;
+      break;
+
+    default:
+      if (direction == DIRECTION_LEFT ||
+          (chain_button               &&
+           gimp_chain_button_get_active (GIMP_CHAIN_BUTTON (chain_button))))
+        {
+          seg->right_color      = color;
+          seg->right_color_type = GIMP_GRADIENT_COLOR_FIXED;
+        }
+
+      if (direction == DIRECTION_RIGHT ||
+          (chain_button                &&
+           gimp_chain_button_get_active (GIMP_CHAIN_BUTTON (chain_button))))
+        {
+          seg->next->left_color      = color;
+          seg->next->left_color_type = GIMP_GRADIENT_COLOR_FIXED;
+        }
+    }
+
+  gimp_gradient_tool_editor_thaw_gradient (gradient_tool);
+  gimp_gradient_tool_editor_end_edit (gradient_tool, FALSE);
+}
+
+static void
+gimp_gradient_tool_editor_color_entry_color_response (GimpColorButton      *button,
+                                                      GimpColorDialogState  state,
+                                                      GimpGradientTool     *gradient_tool)
+{
+  gimp_gradient_tool_editor_end_edit (gradient_tool, FALSE);
+}
+
+static void
+gimp_gradient_tool_editor_color_entry_type_changed (GtkComboBox      *combo,
+                                                    GimpGradientTool *gradient_tool)
+{
+  GimpGradientOptions *options       = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+  GimpPaintOptions    *paint_options = GIMP_PAINT_OPTIONS (options);
+  gint                 selection;
+  gint                 color_type;
+  Direction            direction;
+  GtkWidget           *chain_button;
+  GimpGradientSegment *seg;
+
+  if (gimp_gradient_tool_editor_are_handlers_blocked (gradient_tool))
+    return;
+
+  selection =
+    gimp_tool_line_get_selection (GIMP_TOOL_LINE (gradient_tool->widget));
+
+  if (! gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (combo), &color_type))
+    return;
+
+  direction =
+    GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo),
+                                        "gimp-gradient-tool-editor-direction"));
+  chain_button = g_object_get_data (G_OBJECT (combo),
+                                    "gimp-gradient-tool-editor-chain-button");
+
+  gimp_gradient_tool_editor_start_edit (gradient_tool);
+  gimp_gradient_tool_editor_freeze_gradient (gradient_tool);
+
+  /* swap the endpoint handles, if necessary */
+  if (paint_options->gradient_options->gradient_reverse)
+    {
+      switch (selection)
+        {
+        case GIMP_TOOL_LINE_HANDLE_START:
+          selection = GIMP_TOOL_LINE_HANDLE_END;
+          break;
+
+        case GIMP_TOOL_LINE_HANDLE_END:
+          selection = GIMP_TOOL_LINE_HANDLE_START;
+          break;
+        }
+    }
+
+  seg = gimp_gradient_tool_editor_handle_get_segment (gradient_tool, selection);
+
+  switch (selection)
+    {
+    case GIMP_TOOL_LINE_HANDLE_START:
+      seg->left_color_type = color_type;
+      break;
+
+    case GIMP_TOOL_LINE_HANDLE_END:
+      seg->right_color_type = color_type;
+      break;
+
+    default:
+      if (direction == DIRECTION_LEFT ||
+          (chain_button               &&
+           gimp_chain_button_get_active (GIMP_CHAIN_BUTTON (chain_button))))
+        {
+          seg->right_color_type = color_type;
+        }
+
+      if (direction == DIRECTION_RIGHT ||
+          (chain_button                &&
+           gimp_chain_button_get_active (GIMP_CHAIN_BUTTON (chain_button))))
+        {
+          seg->next->left_color_type = color_type;
+        }
+    }
+
+  gimp_gradient_tool_editor_thaw_gradient (gradient_tool);
+  gimp_gradient_tool_editor_end_edit (gradient_tool, FALSE);
+}
+
+static void
+gimp_gradient_tool_editor_endpoint_se_value_changed (GimpSizeEntry    *se,
+                                                     GimpGradientTool *gradient_tool)
+{
+  gint    selection;
+  gdouble x;
+  gdouble y;
+
+  if (gimp_gradient_tool_editor_are_handlers_blocked (gradient_tool))
+    return;
+
+  selection =
+    gimp_tool_line_get_selection (GIMP_TOOL_LINE (gradient_tool->widget));
+
+  x = gimp_size_entry_get_refval (se, 0);
+  y = gimp_size_entry_get_refval (se, 1);
+
+  gimp_gradient_tool_editor_start_edit (gradient_tool);
+  gimp_gradient_tool_editor_block_handlers (gradient_tool);
+
+  switch (selection)
+    {
+    case GIMP_TOOL_LINE_HANDLE_START:
+      g_object_set (gradient_tool->widget,
+                    "x1", x,
+                    "y1", y,
+                    NULL);
+      break;
+
+    case GIMP_TOOL_LINE_HANDLE_END:
+      g_object_set (gradient_tool->widget,
+                    "x2", x,
+                    "y2", y,
+                    NULL);
+      break;
+
+    default:
+      gimp_assert_not_reached ();
+    }
+
+  gimp_gradient_tool_editor_unblock_handlers (gradient_tool);
+  gimp_gradient_tool_editor_end_edit (gradient_tool, FALSE);
+}
+
+static void
+gimp_gradient_tool_editor_stop_se_value_changed (GimpSizeEntry    *se,
+                                                 GimpGradientTool *gradient_tool)
+{
+  gint                 selection;
+  gdouble              value;
+  GimpGradientSegment *seg;
+
+  if (gimp_gradient_tool_editor_are_handlers_blocked (gradient_tool))
+    return;
+
+  selection =
+    gimp_tool_line_get_selection (GIMP_TOOL_LINE (gradient_tool->widget));
+
+  if (selection == GIMP_TOOL_LINE_HANDLE_NONE)
+    return;
+
+  value = gimp_size_entry_get_refval (se, 0) / 100.0;
+
+  gimp_gradient_tool_editor_start_edit (gradient_tool);
+  gimp_gradient_tool_editor_freeze_gradient (gradient_tool);
+
+  seg = gimp_gradient_tool_editor_handle_get_segment (gradient_tool, selection);
+
+  gimp_gradient_segment_range_compress (gradient_tool->gradient,
+                                        seg, seg,
+                                        seg->left, value);
+  gimp_gradient_segment_range_compress (gradient_tool->gradient,
+                                        seg->next, seg->next,
+                                        value, seg->next->right);
+
+  gimp_gradient_tool_editor_thaw_gradient (gradient_tool);
+  gimp_gradient_tool_editor_end_edit (gradient_tool, FALSE);
+}
+
+static void
+gimp_gradient_tool_editor_stop_delete_clicked (GtkWidget        *button,
+                                               GimpGradientTool *gradient_tool)
+{
+  gint selection;
+
+  selection =
+    gimp_tool_line_get_selection (GIMP_TOOL_LINE (gradient_tool->widget));
+
+  gimp_gradient_tool_editor_delete_stop (gradient_tool, selection);
+}
+
+static void
+gimp_gradient_tool_editor_midpoint_se_value_changed (GimpSizeEntry    *se,
+                                                     GimpGradientTool *gradient_tool)
+{
+  gint                 selection;
+  gdouble              value;
+  GimpGradientSegment *seg;
+
+  if (gimp_gradient_tool_editor_are_handlers_blocked (gradient_tool))
+    return;
+
+  selection =
+    gimp_tool_line_get_selection (GIMP_TOOL_LINE (gradient_tool->widget));
+
+  if (selection == GIMP_TOOL_LINE_HANDLE_NONE)
+    return;
+
+  value = gimp_size_entry_get_refval (se, 0) / 100.0;
+
+  gimp_gradient_tool_editor_start_edit (gradient_tool);
+  gimp_gradient_tool_editor_freeze_gradient (gradient_tool);
+
+  seg = gimp_gradient_tool_editor_handle_get_segment (gradient_tool, selection);
+
+  seg->middle = value;
+
+  gimp_gradient_tool_editor_thaw_gradient (gradient_tool);
+  gimp_gradient_tool_editor_end_edit (gradient_tool, FALSE);
+}
+
+static void
+gimp_gradient_tool_editor_midpoint_type_changed (GtkComboBox      *combo,
+                                                 GimpGradientTool *gradient_tool)
+{
+  gint                 selection;
+  gint                 type;
+  GimpGradientSegment *seg;
+
+  if (gimp_gradient_tool_editor_are_handlers_blocked (gradient_tool))
+    return;
+
+  selection =
+    gimp_tool_line_get_selection (GIMP_TOOL_LINE (gradient_tool->widget));
+
+  if (! gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (combo), &type))
+    return;
+
+  gimp_gradient_tool_editor_start_edit (gradient_tool);
+  gimp_gradient_tool_editor_freeze_gradient (gradient_tool);
+
+  seg = gimp_gradient_tool_editor_handle_get_segment (gradient_tool, selection);
+
+  seg->type = type;
+
+  gimp_gradient_tool_editor_thaw_gradient (gradient_tool);
+  gimp_gradient_tool_editor_end_edit (gradient_tool, FALSE);
+}
+
+static void
+gimp_gradient_tool_editor_midpoint_color_changed (GtkComboBox      *combo,
+                                                  GimpGradientTool *gradient_tool)
+{
+  gint                 selection;
+  gint                 color;
+  GimpGradientSegment *seg;
+
+  if (gimp_gradient_tool_editor_are_handlers_blocked (gradient_tool))
+    return;
+
+  selection =
+    gimp_tool_line_get_selection (GIMP_TOOL_LINE (gradient_tool->widget));
+
+  if (! gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (combo), &color))
+    return;
+
+  gimp_gradient_tool_editor_start_edit (gradient_tool);
+  gimp_gradient_tool_editor_freeze_gradient (gradient_tool);
+
+  seg = gimp_gradient_tool_editor_handle_get_segment (gradient_tool, selection);
+
+  seg->color = color;
+
+  gimp_gradient_tool_editor_thaw_gradient (gradient_tool);
+  gimp_gradient_tool_editor_end_edit (gradient_tool, FALSE);
+}
+
+static void
+gimp_gradient_tool_editor_midpoint_new_stop_clicked (GtkWidget        *button,
+                                                     GimpGradientTool *gradient_tool)
+{
+  gint selection;
+  gint stop;
+
+  selection =
+    gimp_tool_line_get_selection (GIMP_TOOL_LINE (gradient_tool->widget));
+
+  stop = gimp_gradient_tool_editor_midpoint_to_stop (gradient_tool, selection);
+
+  gimp_tool_line_set_selection (GIMP_TOOL_LINE (gradient_tool->widget), stop);
+}
+
+static void
+gimp_gradient_tool_editor_midpoint_center_clicked (GtkWidget        *button,
+                                                   GimpGradientTool *gradient_tool)
+{
+  gint                 selection;
+  GimpGradientSegment *seg;
+
+  selection =
+    gimp_tool_line_get_selection (GIMP_TOOL_LINE (gradient_tool->widget));
+
+  gimp_gradient_tool_editor_start_edit (gradient_tool);
+  gimp_gradient_tool_editor_freeze_gradient (gradient_tool);
+
+  seg = gimp_gradient_tool_editor_handle_get_segment (gradient_tool, selection);
+
+  gimp_gradient_segment_range_recenter_handles (gradient_tool->gradient, seg, seg);
+
+  gimp_gradient_tool_editor_thaw_gradient (gradient_tool);
+  gimp_gradient_tool_editor_end_edit (gradient_tool, FALSE);
+}
+
+static gboolean
+gimp_gradient_tool_editor_flush_idle (GimpGradientTool *gradient_tool)
+{
+  GimpDisplay *display = GIMP_TOOL (gradient_tool)->display;
+
+  gimp_image_flush (gimp_display_get_image (display));
+
+  gradient_tool->flush_idle_id = 0;
+
+  return G_SOURCE_REMOVE;
+}
+
+static gboolean
+gimp_gradient_tool_editor_is_gradient_editable (GimpGradientTool *gradient_tool)
+{
+  GimpGradientOptions *options = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+
+  return ! options->modify_active ||
+         gimp_data_is_writable (GIMP_DATA (gradient_tool->gradient));
+}
+
+static gboolean
+gimp_gradient_tool_editor_handle_is_endpoint (GimpGradientTool *gradient_tool,
+                                              gint              handle)
+{
+  return handle == GIMP_TOOL_LINE_HANDLE_START ||
+         handle == GIMP_TOOL_LINE_HANDLE_END;
+}
+
+static gboolean
+gimp_gradient_tool_editor_handle_is_stop (GimpGradientTool *gradient_tool,
+                                          gint              handle)
+{
+  gint n_sliders;
+
+  gimp_tool_line_get_sliders (GIMP_TOOL_LINE (gradient_tool->widget), &n_sliders);
+
+  return handle >= 0 && handle < n_sliders / 2;
+}
+
+static gboolean
+gimp_gradient_tool_editor_handle_is_midpoint (GimpGradientTool *gradient_tool,
+                                              gint              handle)
+{
+  gint n_sliders;
+
+  gimp_tool_line_get_sliders (GIMP_TOOL_LINE (gradient_tool->widget), &n_sliders);
+
+  return handle >= n_sliders / 2;
+}
+
+static GimpGradientSegment *
+gimp_gradient_tool_editor_handle_get_segment (GimpGradientTool *gradient_tool,
+                                              gint              handle)
+{
+  switch (handle)
+    {
+    case GIMP_TOOL_LINE_HANDLE_START:
+      return gradient_tool->gradient->segments;
+
+    case GIMP_TOOL_LINE_HANDLE_END:
+      return gimp_gradient_segment_get_last (gradient_tool->gradient->segments);
+
+    default:
+      {
+        const GimpControllerSlider *sliders;
+        gint                        n_sliders;
+        gint                        seg_i;
+
+        sliders = gimp_tool_line_get_sliders (GIMP_TOOL_LINE (gradient_tool->widget),
+                                              &n_sliders);
+
+        gimp_assert (handle >= 0 && handle < n_sliders);
+
+        seg_i = GPOINTER_TO_INT (sliders[handle].data);
+
+        return gimp_gradient_segment_get_nth (gradient_tool->gradient->segments,
+                                              seg_i);
+      }
+    }
+}
+
+static void
+gimp_gradient_tool_editor_block_handlers (GimpGradientTool *gradient_tool)
+{
+  gradient_tool->block_handlers_count++;
+}
+
+static void
+gimp_gradient_tool_editor_unblock_handlers (GimpGradientTool *gradient_tool)
+{
+  gimp_assert (gradient_tool->block_handlers_count > 0);
+
+  gradient_tool->block_handlers_count--;
+}
+
+static gboolean
+gimp_gradient_tool_editor_are_handlers_blocked (GimpGradientTool *gradient_tool)
+{
+  return gradient_tool->block_handlers_count > 0;
+}
+
+static void
+gimp_gradient_tool_editor_freeze_gradient (GimpGradientTool *gradient_tool)
+{
+  GimpGradientOptions *options = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+  GimpGradient        *custom;
+  GradientInfo           *info;
+
+  gimp_gradient_tool_editor_block_handlers (gradient_tool);
+
+  custom = gimp_gradients_get_custom (GIMP_CONTEXT (options)->gimp);
+
+  if (gradient_tool->gradient == custom || options->modify_active)
+    {
+      gimp_assert (gimp_gradient_tool_editor_is_gradient_editable (gradient_tool));
+
+      gimp_data_freeze (GIMP_DATA (gradient_tool->gradient));
+    }
+  else
+    {
+      /* copy the active gradient to the custom gradient, and make the custom
+       * gradient active.
+       */
+      gimp_data_freeze (GIMP_DATA (custom));
+
+      gimp_data_copy (GIMP_DATA (custom), GIMP_DATA (gradient_tool->gradient));
+
+      gimp_context_set_gradient (GIMP_CONTEXT (options), custom);
+
+      gimp_assert (gradient_tool->gradient == custom);
+      gimp_assert (gimp_gradient_tool_editor_is_gradient_editable (gradient_tool));
+    }
+
+  if (gradient_tool->edit_count > 0)
+    {
+      info = gradient_tool->undo_stack->data;
+
+      if (! info->gradient)
+        {
+          info->gradient =
+            GIMP_GRADIENT (gimp_data_duplicate (GIMP_DATA (gradient_tool->gradient)));
+        }
+    }
+}
+
+static void
+gimp_gradient_tool_editor_thaw_gradient (GimpGradientTool *gradient_tool)
+{
+  gimp_data_thaw (GIMP_DATA (gradient_tool->gradient));
+
+  gimp_gradient_tool_editor_update_sliders (gradient_tool);
+  gimp_gradient_tool_editor_update_gui (gradient_tool);
+
+  gimp_gradient_tool_editor_unblock_handlers (gradient_tool);
+}
+
+static gint
+gimp_gradient_tool_editor_add_stop (GimpGradientTool *gradient_tool,
+                                    gdouble           value)
+{
+  GimpGradientOptions *options       = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+  GimpPaintOptions    *paint_options = GIMP_PAINT_OPTIONS (options);
+  GimpGradientSegment *seg;
+  gint                 stop;
+  GradientInfo           *info;
+
+  gimp_gradient_tool_editor_start_edit (gradient_tool);
+  gimp_gradient_tool_editor_freeze_gradient (gradient_tool);
+
+  gimp_gradient_split_at (gradient_tool->gradient,
+                          GIMP_CONTEXT (options), NULL, value,
+                          paint_options->gradient_options->gradient_blend_color_space,
+                          &seg, NULL);
+
+  stop =
+    gimp_gradient_segment_range_get_n_segments (gradient_tool->gradient,
+                                                gradient_tool->gradient->segments,
+                                                seg) - 1;
+
+  info               = gradient_tool->undo_stack->data;
+  info->added_handle = stop;
+
+  gimp_gradient_tool_editor_thaw_gradient (gradient_tool);
+  gimp_gradient_tool_editor_end_edit (gradient_tool, FALSE);
+
+  return stop;
+}
+
+static void
+gimp_gradient_tool_editor_delete_stop (GimpGradientTool *gradient_tool,
+                                       gint              slider)
+{
+  GradientInfo *info;
+
+  gimp_assert (gimp_gradient_tool_editor_handle_is_stop (gradient_tool, slider));
+
+  gimp_gradient_tool_editor_start_edit (gradient_tool);
+  gimp_gradient_tool_editor_freeze_gradient (gradient_tool);
+
+  info = gradient_tool->undo_stack->data;
+
+  if (info->added_handle == slider)
+    {
+      /* when removing a stop that was added as part of the current action,
+       * restore the original gradient at the beginning of the action, rather
+       * than deleting the stop from the current gradient, so that the affected
+       * midpoint returns to its state at the beginning of the action, instead
+       * of being reset.
+       *
+       * note that this assumes that the gradient hasn't changed in any other
+       * way during the action, which is ugly, but currently always true.
+       */
+
+      gimp_assert (info->gradient != NULL);
+
+      gimp_data_copy (GIMP_DATA (gradient_tool->gradient),
+                      GIMP_DATA (info->gradient));
+
+      g_clear_object (&info->gradient);
+
+      info->added_handle = GIMP_TOOL_LINE_HANDLE_NONE;
+    }
+  else
+    {
+      GimpGradientSegment *seg;
+
+      seg = gimp_gradient_tool_editor_handle_get_segment (gradient_tool, slider);
+
+      gimp_gradient_segment_range_merge (gradient_tool->gradient,
+                                         seg, seg->next, NULL, NULL);
+
+      info->removed_handle = slider;
+    }
+
+  gimp_gradient_tool_editor_thaw_gradient (gradient_tool);
+  gimp_gradient_tool_editor_end_edit (gradient_tool, FALSE);
+}
+
+static gint
+gimp_gradient_tool_editor_midpoint_to_stop (GimpGradientTool *gradient_tool,
+                                            gint              slider)
+{
+  const GimpControllerSlider *sliders;
+
+  gimp_assert (gimp_gradient_tool_editor_handle_is_midpoint (gradient_tool, slider));
+
+  sliders = gimp_tool_line_get_sliders (GIMP_TOOL_LINE (gradient_tool->widget),
+                                        NULL);
+
+  if (sliders[slider].value > sliders[slider].min + EPSILON &&
+      sliders[slider].value < sliders[slider].max - EPSILON)
+    {
+      const GimpGradientSegment *seg;
+      gint                       stop;
+      GradientInfo                 *info;
+
+      seg = gimp_gradient_tool_editor_handle_get_segment (gradient_tool, slider);
+
+      stop = gimp_gradient_tool_editor_add_stop (gradient_tool, seg->middle);
+
+      info                 = gradient_tool->undo_stack->data;
+      info->removed_handle = slider;
+
+      slider = stop;
+    }
+
+  return slider;
+}
+
+static void
+gimp_gradient_tool_editor_update_sliders (GimpGradientTool *gradient_tool)
+{
+  GimpGradientOptions  *options       = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+  GimpPaintOptions     *paint_options = GIMP_PAINT_OPTIONS (options);
+  gdouble               offset        = options->offset / 100.0;
+  gboolean              editable;
+  GimpControllerSlider *sliders;
+  gint                  n_sliders;
+  gint                  n_segments;
+  GimpGradientSegment  *seg;
+  GimpControllerSlider *slider;
+  gint                  i;
+
+  if (! gradient_tool->widget || options->instant)
+    return;
+
+  editable = gimp_gradient_tool_editor_is_gradient_editable (gradient_tool);
+
+  n_segments = gimp_gradient_segment_range_get_n_segments (
+    gradient_tool->gradient, gradient_tool->gradient->segments, NULL);
+
+  n_sliders = (n_segments - 1) + /* gradient stops, between each adjacent
+                                  * pair of segments */
+              (n_segments);      /* midpoints, inside each segment */
+
+  sliders = g_new (GimpControllerSlider, n_sliders);
+
+  slider = sliders;
+
+  /* initialize the gradient-stop sliders */
+  for (seg = gradient_tool->gradient->segments, i = 0;
+       seg->next;
+       seg = seg->next, i++)
+    {
+      *slider = GIMP_CONTROLLER_SLIDER_DEFAULT;
+
+      slider->value     = seg->right;
+      slider->min       = seg->left;
+      slider->max       = seg->next->right;
+
+      slider->movable   = editable;
+      slider->removable = editable;
+
+      slider->data      = GINT_TO_POINTER (i);
+
+      slider++;
+    }
+
+  /* initialize the midpoint sliders */
+  for (seg = gradient_tool->gradient->segments, i = 0;
+       seg;
+       seg = seg->next, i++)
+    {
+      *slider = GIMP_CONTROLLER_SLIDER_DEFAULT;
+
+      slider->value    = seg->middle;
+      slider->min      = seg->left;
+      slider->max      = seg->right;
+
+      /* hide midpoints of zero-length segments, since they'd otherwise
+       * prevent the segment's endpoints from being selected
+       */
+      slider->visible  = fabs (slider->max - slider->min) > EPSILON;
+      slider->movable  = editable;
+
+      slider->autohide = TRUE;
+      slider->type     = GIMP_HANDLE_FILLED_CIRCLE;
+      slider->size     = 0.6;
+
+      slider->data     = GINT_TO_POINTER (i);
+
+      slider++;
+    }
+
+  /* flip the slider limits and values, if necessary */
+  if (paint_options->gradient_options->gradient_reverse)
+    {
+      for (i = 0; i < n_sliders; i++)
+        {
+          gdouble temp;
+
+          sliders[i].value = 1.0 - sliders[i].value;
+          temp             = sliders[i].min;
+          sliders[i].min   = 1.0 - sliders[i].max;
+          sliders[i].max   = 1.0 - temp;
+        }
+    }
+
+  /* adjust the sliders according to the offset */
+  for (i = 0; i < n_sliders; i++)
+    {
+      sliders[i].value = (1.0 - offset) * sliders[i].value + offset;
+      sliders[i].min   = (1.0 - offset) * sliders[i].min   + offset;
+      sliders[i].max   = (1.0 - offset) * sliders[i].max   + offset;
+    }
+
+  /* avoid updating the gradient in gimp_gradient_tool_editor_line_changed() */
+  gimp_gradient_tool_editor_block_handlers (gradient_tool);
+
+  gimp_tool_line_set_sliders (GIMP_TOOL_LINE (gradient_tool->widget),
+                              sliders, n_sliders);
+
+  gimp_gradient_tool_editor_unblock_handlers (gradient_tool);
+
+  g_free (sliders);
+}
+
+static void
+gimp_gradient_tool_editor_purge_gradient_history (GSList **stack)
+{
+  GSList *link;
+
+  /* eliminate all history steps that modify the gradient */
+  while ((link = *stack))
+    {
+      GradientInfo *info = link->data;
+
+      if (info->gradient)
+        {
+          gimp_gradient_tool_editor_gradient_info_free (info);
+
+          *stack = g_slist_delete_link (*stack, link);
+        }
+      else
+        {
+          stack = &link->next;
+        }
+    }
+}
+
+static void
+gimp_gradient_tool_editor_purge_gradient (GimpGradientTool *gradient_tool)
+{
+  if (gradient_tool->widget)
+    {
+      gimp_gradient_tool_editor_update_sliders (gradient_tool);
+
+      gimp_tool_line_set_selection (GIMP_TOOL_LINE (gradient_tool->widget),
+                                    GIMP_TOOL_LINE_HANDLE_NONE);
+    }
+
+  gimp_gradient_tool_editor_purge_gradient_history (&gradient_tool->undo_stack);
+  gimp_gradient_tool_editor_purge_gradient_history (&gradient_tool->redo_stack);
+}
+
+static GtkWidget *
+gimp_gradient_tool_editor_color_entry_new (GimpGradientTool  *gradient_tool,
+                                           const gchar       *title,
+                                           Direction          direction,
+                                           GtkWidget         *chain_button,
+                                           GtkWidget        **color_panel,
+                                           GtkWidget        **type_combo)
+{
+  GimpContext *context = GIMP_CONTEXT (GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool));
+  GtkWidget   *hbox;
+  GtkWidget   *button;
+  GtkWidget   *combo;
+  GimpRGB      color   = {};
+
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
+
+  /* the color panel */
+  *color_panel = button = gimp_color_panel_new (title, &color,
+                                                GIMP_COLOR_AREA_SMALL_CHECKS,
+                                                24, 24);
+  gimp_color_button_set_update (GIMP_COLOR_BUTTON (button), TRUE);
+  gimp_color_panel_set_context (GIMP_COLOR_PANEL (button), context);
+  gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+  gtk_widget_show (button);
+
+  g_object_set_data (G_OBJECT (button),
+                     "gimp-gradient-tool-editor-direction",
+                     GINT_TO_POINTER (direction));
+  g_object_set_data (G_OBJECT (button),
+                     "gimp-gradient-tool-editor-chain-button",
+                     chain_button);
+
+  g_signal_connect (button, "clicked",
+                    G_CALLBACK (gimp_gradient_tool_editor_color_entry_color_clicked),
+                    gradient_tool);
+  g_signal_connect (button, "color-changed",
+                    G_CALLBACK (gimp_gradient_tool_editor_color_entry_color_changed),
+                    gradient_tool);
+  g_signal_connect (button, "response",
+                    G_CALLBACK (gimp_gradient_tool_editor_color_entry_color_response),
+                    gradient_tool);
+
+  /* the color type combo */
+  *type_combo = combo = gimp_enum_combo_box_new (GIMP_TYPE_GRADIENT_COLOR);
+  gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, TRUE, 0);
+  gtk_widget_show (combo);
+
+  g_object_set_data (G_OBJECT (combo),
+                     "gimp-gradient-tool-editor-direction",
+                     GINT_TO_POINTER (direction));
+  g_object_set_data (G_OBJECT (combo),
+                     "gimp-gradient-tool-editor-chain-button",
+                     chain_button);
+
+  g_signal_connect (combo, "changed",
+                    G_CALLBACK (gimp_gradient_tool_editor_color_entry_type_changed),
+                    gradient_tool);
+
+  return hbox;
+}
+
+static void
+gimp_gradient_tool_editor_init_endpoint_gui (GimpGradientTool *gradient_tool)
+{
+  GimpDisplay      *display = GIMP_TOOL (gradient_tool)->display;
+  GimpDisplayShell *shell   = gimp_display_get_shell (display);
+  GimpImage        *image   = gimp_display_get_image (display);
+  gdouble           xres;
+  gdouble           yres;
+  GtkWidget        *editor;
+  GtkWidget        *table;
+  GtkWidget        *label;
+  GtkWidget        *spinbutton;
+  GtkWidget        *se;
+  GtkWidget        *hbox;
+  gint              row     = 0;
+
+  gimp_image_get_resolution (image, &xres, &yres);
+
+  /* the endpoint editor */
+  gradient_tool->endpoint_editor =
+  editor                         = gimp_editor_new ();
+  gtk_box_pack_start (GTK_BOX (gimp_tool_gui_get_vbox (gradient_tool->gui)),
+                      editor, FALSE, TRUE, 0);
+
+  /* the main table */
+  table = gtk_table_new (1, 2, FALSE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 4);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 4);
+  gtk_box_pack_start (GTK_BOX (editor), table, FALSE, TRUE, 0);
+  gtk_widget_show (table);
+
+  /* the position labels */
+  label = gtk_label_new (_("X:"));
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+  gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
+                    GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
+  gtk_widget_show (label);
+
+  label = gtk_label_new (_("Y:"));
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+  gtk_table_attach (GTK_TABLE (table), label, 0, 1, row + 1, row + 2,
+                    GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
+  gtk_widget_show (label);
+
+  /* the position size entry */
+  spinbutton = gtk_spin_button_new_with_range (0.0, 0.0, 1.0);
+  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
+  gtk_entry_set_width_chars (GTK_ENTRY (spinbutton), 6);
+
+  gradient_tool->endpoint_se =
+  se                         = gimp_size_entry_new (1, GIMP_UNIT_PIXEL, "%a",
+                                                    TRUE, TRUE, FALSE, 6,
+                                                    GIMP_SIZE_ENTRY_UPDATE_SIZE);
+  gtk_table_set_row_spacings (GTK_TABLE (se), 4);
+  gtk_table_set_col_spacings (GTK_TABLE (se), 2);
+
+  gimp_size_entry_add_field (GIMP_SIZE_ENTRY (se),
+                             GTK_SPIN_BUTTON (spinbutton), NULL);
+  gtk_table_attach_defaults (GTK_TABLE (se), spinbutton, 1, 2, 0, 1);
+  gtk_widget_show (spinbutton);
+
+  gtk_table_attach (GTK_TABLE (table), se, 1, 2, row, row + 2,
+                    GTK_SHRINK | GTK_FILL | GTK_EXPAND,
+                    GTK_SHRINK | GTK_FILL,
+                    0, 0);
+  gtk_widget_show (se);
+
+  gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (se), shell->unit);
+
+  gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (se), 0, xres, FALSE);
+  gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (se), 1, yres, FALSE);
+
+  gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (se), 0,
+                                         -GIMP_MAX_IMAGE_SIZE,
+                                         GIMP_MAX_IMAGE_SIZE);
+  gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (se), 1,
+                                         -GIMP_MAX_IMAGE_SIZE,
+                                         GIMP_MAX_IMAGE_SIZE);
+
+  gimp_size_entry_set_size (GIMP_SIZE_ENTRY (se), 0,
+                            0, gimp_image_get_width (image));
+  gimp_size_entry_set_size (GIMP_SIZE_ENTRY (se), 1,
+                            0, gimp_image_get_height (image));
+
+  g_signal_connect (se, "value-changed",
+                    G_CALLBACK (gimp_gradient_tool_editor_endpoint_se_value_changed),
+                    gradient_tool);
+
+  row += 2;
+
+  /* the color label */
+  label = gtk_label_new (_("Color:"));
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+  gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
+                    GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
+  gtk_widget_show (label);
+
+  /* the color entry */
+  hbox = gimp_gradient_tool_editor_color_entry_new (
+    gradient_tool, _("Change Endpoint Color"), DIRECTION_NONE, NULL,
+    &gradient_tool->endpoint_color_panel, &gradient_tool->endpoint_type_combo);
+  gtk_table_attach (GTK_TABLE (table), hbox, 1, 2, row, row + 1,
+                    GTK_SHRINK | GTK_FILL | GTK_EXPAND,
+                    GTK_SHRINK | GTK_FILL,
+                    0, 0);
+  gtk_widget_show (hbox);
+
+  row++;
+}
+
+static void
+gimp_gradient_tool_editor_init_stop_gui (GimpGradientTool *gradient_tool)
+{
+  GtkWidget *editor;
+  GtkWidget *table;
+  GtkWidget *label;
+  GtkWidget *se;
+  GtkWidget *table2;
+  GtkWidget *button;
+  GtkWidget *hbox;
+  GtkWidget *separator;
+  gint       row = 0;
+
+  /* the stop editor */
+  gradient_tool->stop_editor =
+  editor                     = gimp_editor_new ();
+  gtk_box_pack_start (GTK_BOX (gimp_tool_gui_get_vbox (gradient_tool->gui)),
+                      editor, FALSE, TRUE, 0);
+
+  /* the main table */
+  table = gtk_table_new (1, 2, FALSE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 4);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 4);
+  gtk_box_pack_start (GTK_BOX (editor), table, FALSE, TRUE, 0);
+  gtk_widget_show (table);
+
+  /* the position label */
+  label = gtk_label_new (_("Position:"));
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+  gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
+                    GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
+  gtk_widget_show (label);
+
+  /* the position size entry */
+  gradient_tool->stop_se =
+  se                     = gimp_size_entry_new (1, GIMP_UNIT_PERCENT, "%a",
+                                                FALSE, TRUE, FALSE, 6,
+                                                GIMP_SIZE_ENTRY_UPDATE_SIZE);
+  gimp_size_entry_show_unit_menu (GIMP_SIZE_ENTRY (se), FALSE);
+  gtk_table_attach (GTK_TABLE (table), se, 1, 2, row, row + 1,
+                    GTK_SHRINK | GTK_FILL | GTK_EXPAND,
+                    GTK_SHRINK | GTK_FILL,
+                    0, 0);
+  gtk_widget_show (se);
+
+  g_signal_connect (se, "value-changed",
+                    G_CALLBACK (gimp_gradient_tool_editor_stop_se_value_changed),
+                    gradient_tool);
+
+  row++;
+
+  /* the color labels */
+  label = gtk_label_new (_("Left color:"));
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+  gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
+                    GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
+  gtk_widget_show (label);
+
+  label = gtk_label_new (_("Right color:"));
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+  gtk_table_attach (GTK_TABLE (table), label, 0, 1, row + 1, row + 2,
+                    GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
+  gtk_widget_show (label);
+
+  /* the color entries table */
+  table2 = gtk_table_new (1, 2, FALSE);
+  gtk_table_set_row_spacings (GTK_TABLE (table2), 4);
+  gtk_table_set_col_spacings (GTK_TABLE (table2), 2);
+  gtk_table_attach (GTK_TABLE (table), table2, 1, 2, row, row + 2,
+                    GTK_SHRINK | GTK_FILL | GTK_EXPAND,
+                    GTK_SHRINK | GTK_FILL,
+                    0, 0);
+  gtk_widget_show (table2);
+
+  /* the color entries chain button */
+  gradient_tool->stop_chain_button =
+  button                           = gimp_chain_button_new (GIMP_CHAIN_RIGHT);
+  gtk_table_attach (GTK_TABLE (table2), button, 1, 2, 0, 2,
+                    GTK_SHRINK | GTK_FILL,
+                    GTK_SHRINK | GTK_FILL | GTK_EXPAND,
+                    0, 0);
+  gtk_widget_show (button);
+
+  /* the color entries */
+  hbox = gimp_gradient_tool_editor_color_entry_new (
+    gradient_tool, _("Change Stop Color"), DIRECTION_LEFT, button,
+    &gradient_tool->stop_left_color_panel, &gradient_tool->stop_left_type_combo);
+  gtk_table_attach (GTK_TABLE (table2), hbox, 0, 1, 0, 1,
+                    GTK_SHRINK | GTK_FILL | GTK_EXPAND,
+                    GTK_SHRINK | GTK_FILL,
+                    0, 0);
+  gtk_widget_show (hbox);
+
+  hbox = gimp_gradient_tool_editor_color_entry_new (
+    gradient_tool, _("Change Stop Color"), DIRECTION_RIGHT, button,
+    &gradient_tool->stop_right_color_panel, &gradient_tool->stop_right_type_combo);
+  gtk_table_attach (GTK_TABLE (table2), hbox, 0, 1, 1, 2,
+                    GTK_SHRINK | GTK_FILL | GTK_EXPAND,
+                    GTK_SHRINK | GTK_FILL,
+                    0, 0);
+  gtk_widget_show (hbox);
+
+  row += 2;
+
+  /* the action buttons separator */
+  separator = gtk_hseparator_new ();
+  gtk_table_attach (GTK_TABLE (table), separator, 0, 2, row, row + 1,
+                    GTK_SHRINK | GTK_FILL | GTK_EXPAND,
+                    GTK_SHRINK | GTK_FILL,
+                    0, 0);
+  gtk_widget_show (separator);
+
+  row++;
+
+  /* the delete button */
+  gimp_editor_add_button (GIMP_EDITOR (editor),
+                          GIMP_ICON_EDIT_DELETE, _("Delete stop"),
+                          NULL,
+                          G_CALLBACK (gimp_gradient_tool_editor_stop_delete_clicked),
+                          NULL, gradient_tool);
+}
+
+static void
+gimp_gradient_tool_editor_init_midpoint_gui (GimpGradientTool *gradient_tool)
+{
+  GtkWidget *editor;
+  GtkWidget *table;
+  GtkWidget *label;
+  GtkWidget *se;
+  GtkWidget *combo;
+  GtkWidget *separator;
+  gint       row = 0;
+
+  /* the stop editor */
+  gradient_tool->midpoint_editor =
+  editor                         = gimp_editor_new ();
+  gtk_box_pack_start (GTK_BOX (gimp_tool_gui_get_vbox (gradient_tool->gui)),
+                      editor, FALSE, TRUE, 0);
+
+  /* the main table */
+  table = gtk_table_new (1, 2, FALSE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 4);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 4);
+  gtk_box_pack_start (GTK_BOX (editor), table, FALSE, TRUE, 0);
+  gtk_widget_show (table);
+
+  /* the position label */
+  label = gtk_label_new (_("Position:"));
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+  gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
+                    GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
+  gtk_widget_show (label);
+
+  /* the position size entry */
+  gradient_tool->midpoint_se =
+  se                         = gimp_size_entry_new (1, GIMP_UNIT_PERCENT, "%a",
+                                                    FALSE, TRUE, FALSE, 6,
+                                                    GIMP_SIZE_ENTRY_UPDATE_SIZE);
+  gimp_size_entry_show_unit_menu (GIMP_SIZE_ENTRY (se), FALSE);
+  gtk_table_attach (GTK_TABLE (table), se, 1, 2, row, row + 1,
+                    GTK_SHRINK | GTK_FILL | GTK_EXPAND,
+                    GTK_SHRINK | GTK_FILL,
+                    0, 0);
+  gtk_widget_show (se);
+
+  g_signal_connect (se, "value-changed",
+                    G_CALLBACK (gimp_gradient_tool_editor_midpoint_se_value_changed),
+                    gradient_tool);
+
+  row++;
+
+  /* the type label */
+  label = gtk_label_new (_("Gradienting:"));
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+  gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
+                    GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
+  gtk_widget_show (label);
+
+  /* the type combo */
+  gradient_tool->midpoint_type_combo =
+  combo                              = gimp_enum_combo_box_new (GIMP_TYPE_GRADIENT_SEGMENT_TYPE);
+  gtk_table_attach (GTK_TABLE (table), combo, 1, 2, row, row + 1,
+                    GTK_SHRINK | GTK_FILL | GTK_EXPAND,
+                    GTK_SHRINK | GTK_FILL,
+                    0, 0);
+  gtk_widget_show (combo);
+
+  g_signal_connect (combo, "changed",
+                    G_CALLBACK (gimp_gradient_tool_editor_midpoint_type_changed),
+                    gradient_tool);
+
+  row++;
+
+  /* the color label */
+  label = gtk_label_new (_("Coloring:"));
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+  gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
+                    GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
+  gtk_widget_show (label);
+
+  /* the color combo */
+  gradient_tool->midpoint_color_combo =
+  combo                              = gimp_enum_combo_box_new (GIMP_TYPE_GRADIENT_SEGMENT_COLOR);
+  gtk_table_attach (GTK_TABLE (table), combo, 1, 2, row, row + 1,
+                    GTK_SHRINK | GTK_FILL | GTK_EXPAND,
+                    GTK_SHRINK | GTK_FILL,
+                    0, 0);
+  gtk_widget_show (combo);
+
+  g_signal_connect (combo, "changed",
+                    G_CALLBACK (gimp_gradient_tool_editor_midpoint_color_changed),
+                    gradient_tool);
+
+  row++;
+
+  /* the action buttons separator */
+  separator = gtk_hseparator_new ();
+  gtk_table_attach (GTK_TABLE (table), separator, 0, 2, row, row + 1,
+                    GTK_SHRINK | GTK_FILL | GTK_EXPAND,
+                    GTK_SHRINK | GTK_FILL,
+                    0, 0);
+  gtk_widget_show (separator);
+
+  row++;
+
+  /* the new stop button */
+  gradient_tool->midpoint_new_stop_button =
+    gimp_editor_add_button (GIMP_EDITOR (editor),
+                            GIMP_ICON_DOCUMENT_NEW, _("New stop at midpoint"),
+                            NULL,
+                            G_CALLBACK (gimp_gradient_tool_editor_midpoint_new_stop_clicked),
+                            NULL, gradient_tool);
+
+  /* the center button */
+  gradient_tool->midpoint_center_button =
+    gimp_editor_add_button (GIMP_EDITOR (editor),
+                            GIMP_ICON_CENTER_HORIZONTAL, _("Center midpoint"),
+                            NULL,
+                            G_CALLBACK (gimp_gradient_tool_editor_midpoint_center_clicked),
+                            NULL, gradient_tool);
+}
+
+static void
+gimp_gradient_tool_editor_update_endpoint_gui (GimpGradientTool *gradient_tool,
+                                               gint              selection)
+{
+  GimpGradientOptions *options       = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+  GimpPaintOptions    *paint_options = GIMP_PAINT_OPTIONS (options);
+  GimpContext         *context       = GIMP_CONTEXT (options);
+  gboolean             editable;
+  GimpGradientSegment *seg;
+  const gchar         *title;
+  gdouble              x;
+  gdouble              y;
+  GimpRGB              color;
+  GimpGradientColor    color_type;
+
+  editable = gimp_gradient_tool_editor_is_gradient_editable (gradient_tool);
+
+  switch (selection)
+    {
+    case GIMP_TOOL_LINE_HANDLE_START:
+      g_object_get (gradient_tool->widget,
+                    "x1", &x,
+                    "y1", &y,
+                    NULL);
+      break;
+
+    case GIMP_TOOL_LINE_HANDLE_END:
+      g_object_get (gradient_tool->widget,
+                    "x2", &x,
+                    "y2", &y,
+                    NULL);
+      break;
+
+    default:
+      gimp_assert_not_reached ();
+    }
+
+  /* swap the endpoint handles, if necessary */
+  if (paint_options->gradient_options->gradient_reverse)
+    {
+      switch (selection)
+        {
+        case GIMP_TOOL_LINE_HANDLE_START:
+          selection = GIMP_TOOL_LINE_HANDLE_END;
+          break;
+
+        case GIMP_TOOL_LINE_HANDLE_END:
+          selection = GIMP_TOOL_LINE_HANDLE_START;
+          break;
+        }
+    }
+
+  seg = gimp_gradient_tool_editor_handle_get_segment (gradient_tool, selection);
+
+  switch (selection)
+    {
+    case GIMP_TOOL_LINE_HANDLE_START:
+      title = _("Start Endpoint");
+
+      gimp_gradient_segment_get_left_flat_color (gradient_tool->gradient, context,
+                                                 seg, &color);
+      color_type = seg->left_color_type;
+      break;
+
+    case GIMP_TOOL_LINE_HANDLE_END:
+      title = _("End Endpoint");
+
+      gimp_gradient_segment_get_right_flat_color (gradient_tool->gradient, context,
+                                                  seg, &color);
+      color_type = seg->right_color_type;
+      break;
+
+    default:
+      gimp_assert_not_reached ();
+    }
+
+  gimp_tool_gui_set_title (gradient_tool->gui, title);
+
+  gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (gradient_tool->endpoint_se), 0, x);
+  gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (gradient_tool->endpoint_se), 1, y);
+
+  gimp_color_button_set_color (
+    GIMP_COLOR_BUTTON (gradient_tool->endpoint_color_panel), &color);
+  gimp_int_combo_box_set_active (
+    GIMP_INT_COMBO_BOX (gradient_tool->endpoint_type_combo), color_type);
+
+  gtk_widget_set_sensitive (gradient_tool->endpoint_color_panel, editable);
+  gtk_widget_set_sensitive (gradient_tool->endpoint_type_combo,  editable);
+
+  gtk_widget_show (gradient_tool->endpoint_editor);
+}
+
+static void
+gimp_gradient_tool_editor_update_stop_gui (GimpGradientTool *gradient_tool,
+                                           gint              selection)
+{
+  GimpGradientOptions *options = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+  GimpContext         *context = GIMP_CONTEXT (options);
+  gboolean             editable;
+  GimpGradientSegment *seg;
+  gint                 index;
+  gchar               *title;
+  gdouble              min;
+  gdouble              max;
+  gdouble              value;
+  GimpRGB              left_color;
+  GimpGradientColor    left_color_type;
+  GimpRGB              right_color;
+  GimpGradientColor    right_color_type;
+
+  editable = gimp_gradient_tool_editor_is_gradient_editable (gradient_tool);
+
+  seg = gimp_gradient_tool_editor_handle_get_segment (gradient_tool, selection);
+
+  index = GPOINTER_TO_INT (
+    gimp_tool_line_get_sliders (GIMP_TOOL_LINE (gradient_tool->widget),
+                                NULL)[selection].data);
+
+  title = g_strdup_printf (_("Stop %d"), index + 1);
+
+  min   = seg->left;
+  max   = seg->next->right;
+  value = seg->right;
+
+  gimp_gradient_segment_get_right_flat_color (gradient_tool->gradient, context,
+                                              seg, &left_color);
+  left_color_type = seg->right_color_type;
+
+  gimp_gradient_segment_get_left_flat_color (gradient_tool->gradient, context,
+                                             seg->next, &right_color);
+  right_color_type = seg->next->left_color_type;
+
+  gimp_tool_gui_set_title (gradient_tool->gui, title);
+
+  gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (gradient_tool->stop_se),
+                                         0, 100.0 * min, 100.0 * max);
+  gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (gradient_tool->stop_se),
+                              0, 100.0 * value);
+
+  gimp_color_button_set_color (
+    GIMP_COLOR_BUTTON (gradient_tool->stop_left_color_panel), &left_color);
+  gimp_int_combo_box_set_active (
+    GIMP_INT_COMBO_BOX (gradient_tool->stop_left_type_combo), left_color_type);
+
+  gimp_color_button_set_color (
+    GIMP_COLOR_BUTTON (gradient_tool->stop_right_color_panel), &right_color);
+  gimp_int_combo_box_set_active (
+    GIMP_INT_COMBO_BOX (gradient_tool->stop_right_type_combo), right_color_type);
+
+  gtk_widget_set_sensitive (gradient_tool->stop_se,                editable);
+  gtk_widget_set_sensitive (gradient_tool->stop_left_color_panel,  editable);
+  gtk_widget_set_sensitive (gradient_tool->stop_left_type_combo,   editable);
+  gtk_widget_set_sensitive (gradient_tool->stop_right_color_panel, editable);
+  gtk_widget_set_sensitive (gradient_tool->stop_right_type_combo,  editable);
+  gtk_widget_set_sensitive (gradient_tool->stop_chain_button,      editable);
+  gtk_widget_set_sensitive (
+    GTK_WIDGET (gimp_editor_get_button_box (GIMP_EDITOR (gradient_tool->stop_editor))),
+    editable);
+
+  g_free (title);
+
+  gtk_widget_show (gradient_tool->stop_editor);
+}
+
+static void
+gimp_gradient_tool_editor_update_midpoint_gui (GimpGradientTool *gradient_tool,
+                                               gint              selection)
+{
+  gboolean                    editable;
+  const GimpGradientSegment  *seg;
+  gint                        index;
+  gchar                      *title;
+  gdouble                     min;
+  gdouble                     max;
+  gdouble                     value;
+  GimpGradientSegmentType     type;
+  GimpGradientSegmentColor    color;
+
+  editable = gimp_gradient_tool_editor_is_gradient_editable (gradient_tool);
+
+  seg = gimp_gradient_tool_editor_handle_get_segment (gradient_tool, selection);
+
+  index = GPOINTER_TO_INT (
+    gimp_tool_line_get_sliders (GIMP_TOOL_LINE (gradient_tool->widget),
+                                NULL)[selection].data);
+
+  title = g_strdup_printf (_("Midpoint %d"), index + 1);
+
+  min   = seg->left;
+  max   = seg->right;
+  value = seg->middle;
+  type  = seg->type;
+  color = seg->color;
+
+  gimp_tool_gui_set_title (gradient_tool->gui, title);
+
+  gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (gradient_tool->midpoint_se),
+                                         0, 100.0 * min, 100.0 * max);
+  gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (gradient_tool->midpoint_se),
+                              0, 100.0 * value);
+
+  gimp_int_combo_box_set_active (
+    GIMP_INT_COMBO_BOX (gradient_tool->midpoint_type_combo), type);
+
+  gimp_int_combo_box_set_active (
+    GIMP_INT_COMBO_BOX (gradient_tool->midpoint_color_combo), color);
+
+  gtk_widget_set_sensitive (gradient_tool->midpoint_new_stop_button,
+                            value > min + EPSILON && value < max - EPSILON);
+  gtk_widget_set_sensitive (gradient_tool->midpoint_center_button,
+                            fabs (value - (min + max) / 2.0) > EPSILON);
+
+  gtk_widget_set_sensitive (gradient_tool->midpoint_se,          editable);
+  gtk_widget_set_sensitive (gradient_tool->midpoint_type_combo,  editable);
+  gtk_widget_set_sensitive (gradient_tool->midpoint_color_combo, editable);
+  gtk_widget_set_sensitive (
+    GTK_WIDGET (gimp_editor_get_button_box (GIMP_EDITOR (gradient_tool->midpoint_editor))),
+    editable);
+
+  g_free (title);
+
+  gtk_widget_show (gradient_tool->midpoint_editor);
+}
+
+static void
+gimp_gradient_tool_editor_update_gui (GimpGradientTool *gradient_tool)
+{
+  GimpGradientOptions *options = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+
+  if (gradient_tool->gradient && gradient_tool->widget && ! options->instant)
+    {
+      gint selection;
+
+      selection =
+        gimp_tool_line_get_selection (GIMP_TOOL_LINE (gradient_tool->widget));
+
+      if (selection != GIMP_TOOL_LINE_HANDLE_NONE)
+        {
+          if (! gradient_tool->gui)
+            {
+              GimpDisplayShell *shell;
+
+              shell = gimp_tool_widget_get_shell (gradient_tool->widget);
+
+              gradient_tool->gui =
+                gimp_tool_gui_new (GIMP_TOOL (gradient_tool)->tool_info,
+                                   NULL, NULL, NULL, NULL,
+                                   gtk_widget_get_screen (GTK_WIDGET (shell)),
+                                   gimp_widget_get_monitor (GTK_WIDGET (shell)),
+                                   TRUE,
+
+                                   _("_Close"), GTK_RESPONSE_CLOSE,
+
+                                   NULL);
+
+              gimp_tool_gui_set_shell (gradient_tool->gui, shell);
+              gimp_tool_gui_set_viewable (gradient_tool->gui,
+                                          GIMP_VIEWABLE (gradient_tool->gradient));
+              gimp_tool_gui_set_auto_overlay (gradient_tool->gui, TRUE);
+
+              g_signal_connect (gradient_tool->gui, "response",
+                                G_CALLBACK (gimp_gradient_tool_editor_gui_response),
+                                gradient_tool);
+
+              gimp_gradient_tool_editor_init_endpoint_gui (gradient_tool);
+              gimp_gradient_tool_editor_init_stop_gui     (gradient_tool);
+              gimp_gradient_tool_editor_init_midpoint_gui (gradient_tool);
+            }
+
+          gimp_gradient_tool_editor_block_handlers (gradient_tool);
+
+          if (gimp_gradient_tool_editor_handle_is_endpoint (gradient_tool, selection))
+            gimp_gradient_tool_editor_update_endpoint_gui (gradient_tool, selection);
+          else
+            gtk_widget_hide (gradient_tool->endpoint_editor);
+
+          if (gimp_gradient_tool_editor_handle_is_stop (gradient_tool, selection))
+            gimp_gradient_tool_editor_update_stop_gui (gradient_tool, selection);
+          else
+            gtk_widget_hide (gradient_tool->stop_editor);
+
+          if (gimp_gradient_tool_editor_handle_is_midpoint (gradient_tool, selection))
+            gimp_gradient_tool_editor_update_midpoint_gui (gradient_tool, selection);
+          else
+            gtk_widget_hide (gradient_tool->midpoint_editor);
+
+          gimp_gradient_tool_editor_unblock_handlers (gradient_tool);
+
+          gimp_tool_gui_show (gradient_tool->gui);
+
+          return;
+        }
+    }
+
+  if (gradient_tool->gui)
+    gimp_tool_gui_hide (gradient_tool->gui);
+}
+
+static GradientInfo *
+gimp_gradient_tool_editor_gradient_info_new (GimpGradientTool *gradient_tool)
+{
+  GradientInfo *info = g_slice_new (GradientInfo);
+
+  info->start_x         = gradient_tool->start_x;
+  info->start_y         = gradient_tool->start_y;
+  info->end_x           = gradient_tool->end_x;
+  info->end_y           = gradient_tool->end_y;
+
+  info->gradient        = NULL;
+
+  info->added_handle    = GIMP_TOOL_LINE_HANDLE_NONE;
+  info->removed_handle  = GIMP_TOOL_LINE_HANDLE_NONE;
+  info->selected_handle = GIMP_TOOL_LINE_HANDLE_NONE;
+
+  return info;
+}
+
+static void
+gimp_gradient_tool_editor_gradient_info_free (GradientInfo *info)
+{
+  if (info->gradient)
+    g_object_unref (info->gradient);
+
+  g_slice_free (GradientInfo, info);
+}
+
+static void
+gimp_gradient_tool_editor_gradient_info_apply (GimpGradientTool   *gradient_tool,
+                                               const GradientInfo *info,
+                                               gboolean            set_selection)
+{
+  gint selection;
+
+  gimp_assert (gradient_tool->widget   != NULL);
+  gimp_assert (gradient_tool->gradient != NULL);
+
+  /* pick the handle to select */
+  if (info->gradient)
+    {
+      if (info->removed_handle != GIMP_TOOL_LINE_HANDLE_NONE)
+        {
+          /* we're undoing a stop-deletion or midpoint-to-stop operation;
+           * select the removed handle
+           */
+          selection = info->removed_handle;
+        }
+      else if (info->added_handle != GIMP_TOOL_LINE_HANDLE_NONE)
+        {
+          /* we're undoing a stop addition operation */
+          gimp_assert (gimp_gradient_tool_editor_handle_is_stop (gradient_tool,
+                                                                 info->added_handle));
+
+          selection =
+            gimp_tool_line_get_selection (GIMP_TOOL_LINE (gradient_tool->widget));
+
+          /* if the selected handle is a stop... */
+          if (gimp_gradient_tool_editor_handle_is_stop (gradient_tool, selection))
+            {
+              /* if the added handle is selected, clear the selection */
+              if (selection == info->added_handle)
+                selection = GIMP_TOOL_LINE_HANDLE_NONE;
+              /* otherwise, keep the currently selected stop, possibly
+               * adjusting its handle index
+               */
+              else if (selection > info->added_handle)
+                selection--;
+            }
+          /* otherwise, if the selected handle is a midpoint... */
+          else if (gimp_gradient_tool_editor_handle_is_midpoint (gradient_tool, selection))
+            {
+              const GimpControllerSlider *sliders;
+              gint                        seg_i;
+
+              sliders =
+                gimp_tool_line_get_sliders (GIMP_TOOL_LINE (gradient_tool->widget),
+                                            NULL);
+
+              seg_i = GPOINTER_TO_INT (sliders[selection].data);
+
+              /* if the midpoint belongs to one of the two segments incident to
+               * the added stop, clear the selection
+               */
+              if (seg_i == info->added_handle ||
+                  seg_i == info->added_handle + 1)
+                {
+                  selection = GIMP_TOOL_LINE_HANDLE_NONE;
+                }
+              /* otherwise, keep the currently selected stop, adjusting its
+               * handle index
+               */
+              else
+                {
+                  /* midpoint handles follow stop handles; since we removed a
+                   * stop, we must decrement the handle index
+                   */
+                  selection--;
+
+                  if (seg_i > info->added_handle)
+                    selection--;
+                }
+            }
+          /* otherwise, don't change the selection */
+          else
+            {
+              set_selection = FALSE;
+            }
+        }
+      else if (info->selected_handle != GIMP_TOOL_LINE_HANDLE_NONE)
+        {
+          /* we're undoing a property change operation; select the handle
+           * corresponding to the affected object
+           */
+          selection = info->selected_handle;
+        }
+      else
+        {
+          /* something went wrong... */
+          g_warn_if_reached ();
+
+          set_selection = FALSE;
+        }
+    }
+  else if ((info->start_x != gradient_tool->start_x  ||
+            info->start_y != gradient_tool->start_y) &&
+           (info->end_x   == gradient_tool->end_x    &&
+            info->end_y   == gradient_tool->end_y))
+    {
+      /* we're undoing a start-endpoint move operation; select the start
+       * endpoint
+       */
+      selection = GIMP_TOOL_LINE_HANDLE_START;
+    }
+  else if ((info->end_x   != gradient_tool->end_x    ||
+            info->end_y   != gradient_tool->end_y)   &&
+           (info->start_x == gradient_tool->start_x  &&
+            info->start_y == gradient_tool->start_y))
+
+    {
+      /* we're undoing am end-endpoint move operation; select the end
+       * endpoint
+       */
+      selection = GIMP_TOOL_LINE_HANDLE_END;
+    }
+  else
+    {
+      /* we're undoing a line move operation; don't change the selection */
+      set_selection = FALSE;
+    }
+
+  gimp_gradient_tool_editor_block_handlers (gradient_tool);
+
+  g_object_set (gradient_tool->widget,
+                "x1", info->start_x,
+                "y1", info->start_y,
+                "x2", info->end_x,
+                "y2", info->end_y,
+                NULL);
+
+  if (info->gradient)
+    {
+      gimp_gradient_tool_editor_freeze_gradient (gradient_tool);
+
+      gimp_data_copy (GIMP_DATA (gradient_tool->gradient),
+                      GIMP_DATA (info->gradient));
+
+      gimp_gradient_tool_editor_thaw_gradient (gradient_tool);
+    }
+
+  if (set_selection)
+    {
+      gimp_tool_line_set_selection (GIMP_TOOL_LINE (gradient_tool->widget),
+                                    selection);
+    }
+
+  gimp_gradient_tool_editor_update_gui (gradient_tool);
+
+  gimp_gradient_tool_editor_unblock_handlers (gradient_tool);
+}
+
+static gboolean
+gimp_gradient_tool_editor_gradient_info_is_trivial (GimpGradientTool   *gradient_tool,
+                                                    const GradientInfo *info)
+{
+  const GimpGradientSegment *seg1;
+  const GimpGradientSegment *seg2;
+
+  if (info->start_x != gradient_tool->start_x ||
+      info->start_y != gradient_tool->start_y ||
+      info->end_x   != gradient_tool->end_x   ||
+      info->end_y   != gradient_tool->end_y)
+    {
+      return FALSE;
+    }
+
+  if (info->gradient)
+    {
+      for (seg1 = info->gradient->segments, seg2 = gradient_tool->gradient->segments;
+           seg1 && seg2;
+           seg1 = seg1->next, seg2 = seg2->next)
+        {
+          if (memcmp (seg1, seg2, G_STRUCT_OFFSET (GimpGradientSegment, prev)))
+            return FALSE;
+        }
+
+      if (seg1 || seg2)
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+
+/*  public functions  */
+
+void
+gimp_gradient_tool_editor_options_notify (GimpGradientTool *gradient_tool,
+                                          GimpToolOptions  *options,
+                                          const GParamSpec *pspec)
+{
+  if (! strcmp (pspec->name, "modify-active"))
+    {
+      gimp_gradient_tool_editor_update_sliders (gradient_tool);
+      gimp_gradient_tool_editor_update_gui (gradient_tool);
+    }
+  else if (! strcmp (pspec->name, "gradient-reverse"))
+    {
+      gimp_gradient_tool_editor_update_sliders (gradient_tool);
+
+      /* if an endpoint is selected, swap the selected endpoint */
+      if (gradient_tool->widget)
+        {
+          gint selection;
+
+          selection =
+            gimp_tool_line_get_selection (GIMP_TOOL_LINE (gradient_tool->widget));
+
+          switch (selection)
+            {
+            case GIMP_TOOL_LINE_HANDLE_START:
+              gimp_tool_line_set_selection (GIMP_TOOL_LINE (gradient_tool->widget),
+                                            GIMP_TOOL_LINE_HANDLE_END);
+              break;
+
+            case GIMP_TOOL_LINE_HANDLE_END:
+              gimp_tool_line_set_selection (GIMP_TOOL_LINE (gradient_tool->widget),
+                                            GIMP_TOOL_LINE_HANDLE_START);
+              break;
+            }
+        }
+    }
+  else if (gradient_tool->render_node &&
+           gegl_node_find_property (gradient_tool->render_node, pspec->name))
+    {
+      gimp_gradient_tool_editor_update_sliders (gradient_tool);
+    }
+}
+
+void
+gimp_gradient_tool_editor_start (GimpGradientTool *gradient_tool)
+{
+  g_signal_connect (gradient_tool->widget, "can-add-slider",
+                    G_CALLBACK (gimp_gradient_tool_editor_line_can_add_slider),
+                    gradient_tool);
+  g_signal_connect (gradient_tool->widget, "add-slider",
+                    G_CALLBACK (gimp_gradient_tool_editor_line_add_slider),
+                    gradient_tool);
+  g_signal_connect (gradient_tool->widget, "prepare-to-remove-slider",
+                    G_CALLBACK (gimp_gradient_tool_editor_line_prepare_to_remove_slider),
+                    gradient_tool);
+  g_signal_connect (gradient_tool->widget, "remove-slider",
+                    G_CALLBACK (gimp_gradient_tool_editor_line_remove_slider),
+                    gradient_tool);
+  g_signal_connect (gradient_tool->widget, "selection-changed",
+                    G_CALLBACK (gimp_gradient_tool_editor_line_selection_changed),
+                    gradient_tool);
+  g_signal_connect (gradient_tool->widget, "handle-clicked",
+                    G_CALLBACK (gimp_gradient_tool_editor_line_handle_clicked),
+                    gradient_tool);
+}
+
+void
+gimp_gradient_tool_editor_halt (GimpGradientTool *gradient_tool)
+{
+  g_clear_object (&gradient_tool->gui);
+
+  gradient_tool->edit_count = 0;
+
+  if (gradient_tool->undo_stack)
+    {
+      g_slist_free_full (gradient_tool->undo_stack,
+                         (GDestroyNotify) gimp_gradient_tool_editor_gradient_info_free);
+      gradient_tool->undo_stack = NULL;
+    }
+
+  if (gradient_tool->redo_stack)
+    {
+      g_slist_free_full (gradient_tool->redo_stack,
+                         (GDestroyNotify) gimp_gradient_tool_editor_gradient_info_free);
+      gradient_tool->redo_stack = NULL;
+    }
+
+  if (gradient_tool->flush_idle_id)
+    {
+      g_source_remove (gradient_tool->flush_idle_id);
+      gradient_tool->flush_idle_id = 0;
+    }
+}
+
+gboolean
+gimp_gradient_tool_editor_line_changed (GimpGradientTool *gradient_tool)
+{
+  GimpGradientOptions        *options       = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+  GimpPaintOptions           *paint_options = GIMP_PAINT_OPTIONS (options);
+  gdouble                     offset        = options->offset / 100.0;
+  const GimpControllerSlider *sliders;
+  gint                        n_sliders;
+  gint                        i;
+  GimpGradientSegment        *seg;
+  gboolean                    changed       = FALSE;
+
+  if (gimp_gradient_tool_editor_are_handlers_blocked (gradient_tool))
+    return FALSE;
+
+  if (! gradient_tool->gradient || offset == 1.0)
+    return FALSE;
+
+  sliders = gimp_tool_line_get_sliders (GIMP_TOOL_LINE (gradient_tool->widget),
+                                        &n_sliders);
+
+  if (n_sliders == 0)
+    return FALSE;
+
+  /* update the midpoints first, since moving the gradient stops may change the
+   * gradient's midpoints w.r.t. the sliders, but not the other way around.
+   */
+  for (seg = gradient_tool->gradient->segments, i = n_sliders / 2;
+       seg;
+       seg = seg->next, i++)
+    {
+      gdouble value;
+
+      value = sliders[i].value;
+
+      /* adjust slider value according to the offset */
+      value = (value - offset) / (1.0 - offset);
+
+      /* flip the slider value, if necessary */
+      if (paint_options->gradient_options->gradient_reverse)
+        value = 1.0 - value;
+
+      if (fabs (value - seg->middle) > EPSILON)
+        {
+          if (! changed)
+            {
+              gimp_gradient_tool_editor_start_edit (gradient_tool);
+              gimp_gradient_tool_editor_freeze_gradient (gradient_tool);
+
+              /* refetch the segment, since the gradient might have changed */
+              seg = gimp_gradient_tool_editor_handle_get_segment (gradient_tool, i);
+
+              changed = TRUE;
+            }
+
+          seg->middle = value;
+        }
+    }
+
+  /* update the gradient stops */
+  for (seg = gradient_tool->gradient->segments, i = 0;
+       seg->next;
+       seg = seg->next, i++)
+    {
+      gdouble value;
+
+      value = sliders[i].value;
+
+      /* adjust slider value according to the offset */
+      value = (value - offset) / (1.0 - offset);
+
+      /* flip the slider value, if necessary */
+      if (paint_options->gradient_options->gradient_reverse)
+        value = 1.0 - value;
+
+      if (fabs (value - seg->right) > EPSILON)
+        {
+          if (! changed)
+            {
+              gimp_gradient_tool_editor_start_edit (gradient_tool);
+              gimp_gradient_tool_editor_freeze_gradient (gradient_tool);
+
+              /* refetch the segment, since the gradient might have changed */
+              seg = gimp_gradient_tool_editor_handle_get_segment (gradient_tool, i);
+
+              changed = TRUE;
+            }
+
+          gimp_gradient_segment_range_compress (gradient_tool->gradient,
+                                                seg, seg,
+                                                seg->left, value);
+          gimp_gradient_segment_range_compress (gradient_tool->gradient,
+                                                seg->next, seg->next,
+                                                value, seg->next->right);
+        }
+    }
+
+  if (changed)
+    {
+      gimp_gradient_tool_editor_thaw_gradient (gradient_tool);
+      gimp_gradient_tool_editor_end_edit (gradient_tool, FALSE);
+    }
+
+  gimp_gradient_tool_editor_update_gui (gradient_tool);
+
+  return changed;
+}
+
+void
+gimp_gradient_tool_editor_fg_bg_changed (GimpGradientTool *gradient_tool)
+{
+  gimp_gradient_tool_editor_update_gui (gradient_tool);
+}
+
+void
+gimp_gradient_tool_editor_gradient_dirty (GimpGradientTool *gradient_tool)
+{
+  if (gimp_gradient_tool_editor_are_handlers_blocked (gradient_tool))
+    return;
+
+  gimp_gradient_tool_editor_purge_gradient (gradient_tool);
+}
+
+void
+gimp_gradient_tool_editor_gradient_changed (GimpGradientTool *gradient_tool)
+{
+  GimpGradientOptions *options = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+  GimpContext         *context = GIMP_CONTEXT (options);
+
+  if (options->modify_active_frame)
+    {
+      gtk_widget_set_sensitive (options->modify_active_frame,
+                                gradient_tool->gradient !=
+                                gimp_gradients_get_custom (context->gimp));
+    }
+
+  if (options->modify_active_hint)
+    {
+      gtk_widget_set_visible (options->modify_active_hint,
+                              gradient_tool->gradient &&
+                              ! gimp_data_is_writable (GIMP_DATA (gradient_tool->gradient)));
+    }
+
+  if (gimp_gradient_tool_editor_are_handlers_blocked (gradient_tool))
+    return;
+
+  gimp_gradient_tool_editor_purge_gradient (gradient_tool);
+}
+
+const gchar *
+gimp_gradient_tool_editor_can_undo (GimpGradientTool *gradient_tool)
+{
+  if (! gradient_tool->undo_stack || gradient_tool->edit_count > 0)
+    return NULL;
+
+  return _("Gradient Step");
+}
+
+const gchar *
+gimp_gradient_tool_editor_can_redo (GimpGradientTool *gradient_tool)
+{
+  if (! gradient_tool->redo_stack || gradient_tool->edit_count > 0)
+    return NULL;
+
+  return _("Gradient Step");
+}
+
+gboolean
+gimp_gradient_tool_editor_undo (GimpGradientTool *gradient_tool)
+{
+  GimpTool  *tool = GIMP_TOOL (gradient_tool);
+  GradientInfo *info;
+  GradientInfo *new_info;
+
+  gimp_assert (gradient_tool->undo_stack != NULL);
+  gimp_assert (gradient_tool->edit_count == 0);
+
+  info = gradient_tool->undo_stack->data;
+
+  new_info = gimp_gradient_tool_editor_gradient_info_new (gradient_tool);
+
+  if (info->gradient)
+    {
+      new_info->gradient =
+        GIMP_GRADIENT (gimp_data_duplicate (GIMP_DATA (gradient_tool->gradient)));
+
+      /* swap the added and removed handles, so that gradient_info_apply() does
+       * the right thing on redo
+       */
+      new_info->added_handle    = info->removed_handle;
+      new_info->removed_handle  = info->added_handle;
+      new_info->selected_handle = info->selected_handle;
+    }
+
+  gradient_tool->undo_stack = g_slist_remove (gradient_tool->undo_stack, info);
+  gradient_tool->redo_stack = g_slist_prepend (gradient_tool->redo_stack, new_info);
+
+  gimp_gradient_tool_editor_gradient_info_apply (gradient_tool, info, TRUE);
+  gimp_gradient_tool_editor_gradient_info_free (info);
+
+  /* the initial state of the gradient tool is not useful; we might as well halt */
+  if (! gradient_tool->undo_stack)
+    gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, tool->display);
+
+  return TRUE;
+}
+
+gboolean
+gimp_gradient_tool_editor_redo (GimpGradientTool *gradient_tool)
+{
+  GradientInfo *info;
+  GradientInfo *new_info;
+
+  gimp_assert (gradient_tool->redo_stack != NULL);
+  gimp_assert (gradient_tool->edit_count == 0);
+
+  info = gradient_tool->redo_stack->data;
+
+  new_info = gimp_gradient_tool_editor_gradient_info_new (gradient_tool);
+
+  if (info->gradient)
+    {
+      new_info->gradient =
+        GIMP_GRADIENT (gimp_data_duplicate (GIMP_DATA (gradient_tool->gradient)));
+
+      /* swap the added and removed handles, so that gradient_info_apply() does
+       * the right thing on undo
+       */
+      new_info->added_handle    = info->removed_handle;
+      new_info->removed_handle  = info->added_handle;
+      new_info->selected_handle = info->selected_handle;
+    }
+
+  gradient_tool->redo_stack = g_slist_remove (gradient_tool->redo_stack, info);
+  gradient_tool->undo_stack = g_slist_prepend (gradient_tool->undo_stack, new_info);
+
+  gimp_gradient_tool_editor_gradient_info_apply (gradient_tool, info, TRUE);
+  gimp_gradient_tool_editor_gradient_info_free (info);
+
+  return TRUE;
+}
+
+void
+gimp_gradient_tool_editor_start_edit (GimpGradientTool *gradient_tool)
+{
+  if (gradient_tool->edit_count++ == 0)
+    {
+      GradientInfo *info;
+
+      info = gimp_gradient_tool_editor_gradient_info_new (gradient_tool);
+
+      gradient_tool->undo_stack = g_slist_prepend (gradient_tool->undo_stack, info);
+
+      /*  update the undo actions / menu items  */
+      if (! gradient_tool->flush_idle_id)
+        {
+          gradient_tool->flush_idle_id =
+            g_idle_add ((GSourceFunc) gimp_gradient_tool_editor_flush_idle,
+                        gradient_tool);
+        }
+    }
+}
+
+void
+gimp_gradient_tool_editor_end_edit (GimpGradientTool *gradient_tool,
+                                    gboolean          cancel)
+{
+  /* can happen when halting using esc */
+  if (gradient_tool->edit_count == 0)
+    return;
+
+  if (--gradient_tool->edit_count == 0)
+    {
+      GradientInfo *info = gradient_tool->undo_stack->data;
+
+      info->selected_handle =
+        gimp_tool_line_get_selection (GIMP_TOOL_LINE (gradient_tool->widget));
+
+      if (cancel ||
+          gimp_gradient_tool_editor_gradient_info_is_trivial (gradient_tool, info))
+        {
+          /* if the edit is canceled, or if nothing changed, undo the last
+           * step
+           */
+          gimp_gradient_tool_editor_gradient_info_apply (gradient_tool, info, FALSE);
+
+          gradient_tool->undo_stack = g_slist_remove (gradient_tool->undo_stack,
+                                                   info);
+          gimp_gradient_tool_editor_gradient_info_free (info);
+        }
+      else
+        {
+          /* otherwise, blow the redo stack */
+          g_slist_free_full (gradient_tool->redo_stack,
+                             (GDestroyNotify) gimp_gradient_tool_editor_gradient_info_free);
+          gradient_tool->redo_stack = NULL;
+        }
+
+      /*  update the undo actions / menu items  */
+      if (! gradient_tool->flush_idle_id)
+        {
+          gradient_tool->flush_idle_id =
+            g_idle_add ((GSourceFunc) gimp_gradient_tool_editor_flush_idle,
+                        gradient_tool);
+        }
+    }
+}
diff --git a/app/tools/gimpgradienttool-editor.h b/app/tools/gimpgradienttool-editor.h
new file mode 100644
index 0000000..d27a2fd
--- /dev/null
+++ b/app/tools/gimpgradienttool-editor.h
@@ -0,0 +1,48 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef  __GIMP_GRADIENT_TOOL_EDITOR_H__
+#define  __GIMP_GRADIENT_TOOL_EDITOR_H__
+
+
+void          gimp_gradient_tool_editor_options_notify   (GimpGradientTool *gradient_tool,
+                                                          GimpToolOptions  *options,
+                                                          const GParamSpec *pspec);
+
+void          gimp_gradient_tool_editor_start            (GimpGradientTool *gradient_tool);
+void          gimp_gradient_tool_editor_halt             (GimpGradientTool *gradient_tool);
+
+gboolean      gimp_gradient_tool_editor_line_changed     (GimpGradientTool *gradient_tool);
+
+void          gimp_gradient_tool_editor_fg_bg_changed    (GimpGradientTool *gradient_tool);
+
+void          gimp_gradient_tool_editor_gradient_dirty   (GimpGradientTool *gradient_tool);
+
+void          gimp_gradient_tool_editor_gradient_changed (GimpGradientTool *gradient_tool);
+
+const gchar * gimp_gradient_tool_editor_can_undo         (GimpGradientTool *gradient_tool);
+const gchar * gimp_gradient_tool_editor_can_redo         (GimpGradientTool *gradient_tool);
+
+gboolean      gimp_gradient_tool_editor_undo             (GimpGradientTool *gradient_tool);
+gboolean      gimp_gradient_tool_editor_redo             (GimpGradientTool *gradient_tool);
+
+void          gimp_gradient_tool_editor_start_edit       (GimpGradientTool *gradient_tool);
+void          gimp_gradient_tool_editor_end_edit         (GimpGradientTool *gradient_tool,
+                                                          gboolean          cancel);
+
+
+#endif  /*  __GIMP_GRADIENT_TOOL_EDITOR_H__  */
diff --git a/app/tools/gimpgradienttool.c b/app/tools/gimpgradienttool.c
new file mode 100644
index 0000000..e71a01c
--- /dev/null
+++ b/app/tools/gimpgradienttool.c
@@ -0,0 +1,1073 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * Major improvements for interactivity
+ * Copyright (C) 2014 Michael Henning <drawoc darkrefraction com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "tools-types.h"
+
+#include "operations/gimp-operation-config.h"
+
+#include "core/gimpdrawable.h"
+#include "core/gimpdrawable-gradient.h"
+#include "core/gimpdrawablefilter.h"
+#include "core/gimperror.h"
+#include "core/gimpgradient.h"
+#include "core/gimpimage.h"
+#include "core/gimpprogress.h"
+#include "core/gimpprojection.h"
+
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpwidgets-utils.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimptoolline.h"
+
+#include "gimpgradientoptions.h"
+#include "gimpgradienttool.h"
+#include "gimpgradienttool-editor.h"
+#include "gimptoolcontrol.h"
+
+#include "gimp-intl.h"
+
+
+/*  local function prototypes  */
+
+static void   gimp_gradient_tool_dispose             (GObject               *object);
+
+static gboolean gimp_gradient_tool_initialize        (GimpTool              *tool,
+                                                      GimpDisplay           *display,
+                                                      GError               **error);
+static void   gimp_gradient_tool_control             (GimpTool              *tool,
+                                                      GimpToolAction         action,
+                                                      GimpDisplay           *display);
+static void   gimp_gradient_tool_button_press        (GimpTool              *tool,
+                                                      const GimpCoords      *coords,
+                                                      guint32                time,
+                                                      GdkModifierType        state,
+                                                      GimpButtonPressType    press_type,
+                                                      GimpDisplay           *display);
+static void   gimp_gradient_tool_button_release      (GimpTool              *tool,
+                                                      const GimpCoords      *coords,
+                                                      guint32                time,
+                                                      GdkModifierType        state,
+                                                      GimpButtonReleaseType  release_type,
+                                                      GimpDisplay           *display);
+static void   gimp_gradient_tool_motion              (GimpTool              *tool,
+                                                      const GimpCoords      *coords,
+                                                      guint32                time,
+                                                      GdkModifierType        state,
+                                                      GimpDisplay           *display);
+static gboolean gimp_gradient_tool_key_press         (GimpTool              *tool,
+                                                      GdkEventKey           *kevent,
+                                                      GimpDisplay           *display);
+static void   gimp_gradient_tool_modifier_key        (GimpTool              *tool,
+                                                      GdkModifierType        key,
+                                                      gboolean               press,
+                                                      GdkModifierType        state,
+                                                      GimpDisplay           *display);
+static void   gimp_gradient_tool_cursor_update       (GimpTool              *tool,
+                                                      const GimpCoords      *coords,
+                                                      GdkModifierType        state,
+                                                      GimpDisplay           *display);
+static const gchar * gimp_gradient_tool_can_undo     (GimpTool              *tool,
+                                                      GimpDisplay           *display);
+static const gchar * gimp_gradient_tool_can_redo     (GimpTool              *tool,
+                                                      GimpDisplay           *display);
+static gboolean  gimp_gradient_tool_undo             (GimpTool              *tool,
+                                                      GimpDisplay           *display);
+static gboolean  gimp_gradient_tool_redo             (GimpTool              *tool,
+                                                      GimpDisplay           *display);
+static void   gimp_gradient_tool_options_notify      (GimpTool              *tool,
+                                                      GimpToolOptions       *options,
+                                                      const GParamSpec      *pspec);
+
+static void   gimp_gradient_tool_start               (GimpGradientTool         *gradient_tool,
+                                                      const GimpCoords      *coords,
+                                                      GimpDisplay           *display);
+static void   gimp_gradient_tool_halt                (GimpGradientTool         *gradient_tool);
+static void   gimp_gradient_tool_commit              (GimpGradientTool         *gradient_tool);
+
+static void   gimp_gradient_tool_line_changed        (GimpToolWidget        *widget,
+                                                      GimpGradientTool         *gradient_tool);
+static void   gimp_gradient_tool_line_response       (GimpToolWidget        *widget,
+                                                      gint                   response_id,
+                                                      GimpGradientTool         *gradient_tool);
+
+static void   gimp_gradient_tool_precalc_shapeburst  (GimpGradientTool         *gradient_tool);
+
+static void   gimp_gradient_tool_create_graph        (GimpGradientTool         *gradient_tool);
+static void   gimp_gradient_tool_update_graph        (GimpGradientTool         *gradient_tool);
+
+static void   gimp_gradient_tool_fg_bg_changed       (GimpGradientTool         *gradient_tool);
+
+static void   gimp_gradient_tool_gradient_dirty      (GimpGradientTool         *gradient_tool);
+static void   gimp_gradient_tool_set_gradient        (GimpGradientTool         *gradient_tool,
+                                                      GimpGradient          *gradient);
+
+static gboolean gimp_gradient_tool_is_shapeburst     (GimpGradientTool         *gradient_tool);
+
+static void   gimp_gradient_tool_create_filter       (GimpGradientTool         *gradient_tool,
+                                                      GimpDrawable          *drawable);
+static void   gimp_gradient_tool_filter_flush        (GimpDrawableFilter    *filter,
+                                                      GimpTool              *tool);
+
+
+G_DEFINE_TYPE (GimpGradientTool, gimp_gradient_tool, GIMP_TYPE_DRAW_TOOL)
+
+#define parent_class gimp_gradient_tool_parent_class
+
+
+void
+gimp_gradient_tool_register (GimpToolRegisterCallback  callback,
+                             gpointer                  data)
+{
+  (* callback) (GIMP_TYPE_GRADIENT_TOOL,
+                GIMP_TYPE_GRADIENT_OPTIONS,
+                gimp_gradient_options_gui,
+                GIMP_CONTEXT_PROP_MASK_FOREGROUND |
+                GIMP_CONTEXT_PROP_MASK_BACKGROUND |
+                GIMP_CONTEXT_PROP_MASK_OPACITY    |
+                GIMP_CONTEXT_PROP_MASK_PAINT_MODE |
+                GIMP_CONTEXT_PROP_MASK_GRADIENT,
+                "gimp-gradient-tool",
+                _("Gradient"),
+                _("Gradient Tool: Fill selected area with a color gradient"),
+                N_("Blen_d"), "L",
+                NULL, GIMP_HELP_TOOL_GRADIENT,
+                GIMP_ICON_TOOL_GRADIENT,
+                data);
+}
+
+static void
+gimp_gradient_tool_class_init (GimpGradientToolClass *klass)
+{
+  GObjectClass  *object_class = G_OBJECT_CLASS (klass);
+  GimpToolClass *tool_class   = GIMP_TOOL_CLASS (klass);
+
+  object_class->dispose      = gimp_gradient_tool_dispose;
+
+  tool_class->initialize     = gimp_gradient_tool_initialize;
+  tool_class->control        = gimp_gradient_tool_control;
+  tool_class->button_press   = gimp_gradient_tool_button_press;
+  tool_class->button_release = gimp_gradient_tool_button_release;
+  tool_class->motion         = gimp_gradient_tool_motion;
+  tool_class->key_press      = gimp_gradient_tool_key_press;
+  tool_class->modifier_key   = gimp_gradient_tool_modifier_key;
+  tool_class->cursor_update  = gimp_gradient_tool_cursor_update;
+  tool_class->can_undo       = gimp_gradient_tool_can_undo;
+  tool_class->can_redo       = gimp_gradient_tool_can_redo;
+  tool_class->undo           = gimp_gradient_tool_undo;
+  tool_class->redo           = gimp_gradient_tool_redo;
+  tool_class->options_notify = gimp_gradient_tool_options_notify;
+}
+
+static void
+gimp_gradient_tool_init (GimpGradientTool *gradient_tool)
+{
+  GimpTool *tool = GIMP_TOOL (gradient_tool);
+
+  gimp_tool_control_set_scroll_lock        (tool->control, TRUE);
+  gimp_tool_control_set_preserve           (tool->control, FALSE);
+  gimp_tool_control_set_dirty_mask         (tool->control,
+                                            GIMP_DIRTY_IMAGE           |
+                                            GIMP_DIRTY_IMAGE_STRUCTURE |
+                                            GIMP_DIRTY_DRAWABLE        |
+                                            GIMP_DIRTY_ACTIVE_DRAWABLE);
+  gimp_tool_control_set_wants_click        (tool->control, TRUE);
+  gimp_tool_control_set_wants_double_click (tool->control, TRUE);
+  gimp_tool_control_set_active_modifiers   (tool->control,
+                                            GIMP_TOOL_ACTIVE_MODIFIERS_SEPARATE);
+  gimp_tool_control_set_precision          (tool->control,
+                                            GIMP_CURSOR_PRECISION_SUBPIXEL);
+  gimp_tool_control_set_tool_cursor        (tool->control,
+                                            GIMP_TOOL_CURSOR_GRADIENT);
+  gimp_tool_control_set_action_opacity     (tool->control,
+                                            "context/context-opacity-set");
+  gimp_tool_control_set_action_object_1    (tool->control,
+                                            "context/context-gradient-select-set");
+
+  gimp_draw_tool_set_default_status (GIMP_DRAW_TOOL (tool),
+                                     _("Click-Drag to draw a gradient"));
+}
+
+static void
+gimp_gradient_tool_dispose (GObject *object)
+{
+  GimpGradientTool *gradient_tool = GIMP_GRADIENT_TOOL (object);
+
+  gimp_gradient_tool_set_gradient (gradient_tool, NULL);
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static gboolean
+gimp_gradient_tool_initialize (GimpTool     *tool,
+                               GimpDisplay  *display,
+                               GError      **error)
+{
+  GimpImage           *image    = gimp_display_get_image (display);
+  GimpDrawable        *drawable = gimp_image_get_active_drawable (image);
+  GimpGradientOptions *options  = GIMP_GRADIENT_TOOL_GET_OPTIONS (tool);
+
+  if (! GIMP_TOOL_CLASS (parent_class)->initialize (tool, display, error))
+    {
+      return FALSE;
+    }
+
+  if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
+    {
+      g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
+                           _("Cannot modify the pixels of layer groups."));
+      return FALSE;
+    }
+
+  if (gimp_item_is_content_locked (GIMP_ITEM (drawable)))
+    {
+      g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
+                           _("The active layer's pixels are locked."));
+      return FALSE;
+    }
+
+  if (! gimp_item_is_visible (GIMP_ITEM (drawable)))
+    {
+      g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
+                           _("The active layer is not visible."));
+      return FALSE;
+    }
+
+  if (! gimp_context_get_gradient (GIMP_CONTEXT (options)))
+    {
+      g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
+                           _("No gradient available for use with this tool."));
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static void
+gimp_gradient_tool_control (GimpTool       *tool,
+                            GimpToolAction  action,
+                            GimpDisplay    *display)
+{
+  GimpGradientTool *gradient_tool = GIMP_GRADIENT_TOOL (tool);
+
+  switch (action)
+    {
+    case GIMP_TOOL_ACTION_PAUSE:
+    case GIMP_TOOL_ACTION_RESUME:
+      break;
+
+    case GIMP_TOOL_ACTION_HALT:
+      gimp_gradient_tool_halt (gradient_tool);
+      break;
+
+    case GIMP_TOOL_ACTION_COMMIT:
+      gimp_gradient_tool_commit (gradient_tool);
+      break;
+    }
+
+  GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
+}
+
+static void
+gimp_gradient_tool_button_press (GimpTool            *tool,
+                                 const GimpCoords    *coords,
+                                 guint32              time,
+                                 GdkModifierType      state,
+                                 GimpButtonPressType  press_type,
+                                 GimpDisplay         *display)
+{
+  GimpGradientTool *gradient_tool = GIMP_GRADIENT_TOOL (tool);
+
+  if (tool->display && display != tool->display)
+    gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, tool->display);
+
+  if (! gradient_tool->widget)
+    {
+      gimp_gradient_tool_start (gradient_tool, coords, display);
+
+      gimp_tool_widget_hover (gradient_tool->widget, coords, state, TRUE);
+    }
+
+  /* call start_edit() before widget_button_press(), because we need to record
+   * the undo state before widget_button_press() potentially changes it.  note
+   * that if widget_button_press() return FALSE, nothing changes and no undo
+   * step is created.
+   */
+  if (press_type == GIMP_BUTTON_PRESS_NORMAL)
+    gimp_gradient_tool_editor_start_edit (gradient_tool);
+
+  if (gimp_tool_widget_button_press (gradient_tool->widget, coords, time, state,
+                                     press_type))
+    {
+      gradient_tool->grab_widget = gradient_tool->widget;
+    }
+
+  if (press_type == GIMP_BUTTON_PRESS_NORMAL)
+    gimp_tool_control_activate (tool->control);
+}
+
+static void
+gimp_gradient_tool_button_release (GimpTool              *tool,
+                                   const GimpCoords      *coords,
+                                   guint32                time,
+                                   GdkModifierType        state,
+                                   GimpButtonReleaseType  release_type,
+                                   GimpDisplay           *display)
+{
+  GimpGradientTool    *gradient_tool = GIMP_GRADIENT_TOOL (tool);
+  GimpGradientOptions *options       = GIMP_GRADIENT_TOOL_GET_OPTIONS (tool);
+
+  gimp_tool_pop_status (tool, display);
+
+  gimp_tool_control_halt (tool->control);
+
+  if (gradient_tool->grab_widget)
+    {
+      gimp_tool_widget_button_release (gradient_tool->grab_widget,
+                                       coords, time, state, release_type);
+      gradient_tool->grab_widget = NULL;
+
+      if (options->instant)
+        {
+          if (release_type == GIMP_BUTTON_RELEASE_CANCEL)
+            gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
+          else
+            gimp_tool_control (tool, GIMP_TOOL_ACTION_COMMIT, display);
+        }
+    }
+
+  if (! options->instant)
+    {
+      gimp_gradient_tool_editor_end_edit (gradient_tool,
+                                          release_type ==
+                                          GIMP_BUTTON_RELEASE_CANCEL);
+    }
+}
+
+static void
+gimp_gradient_tool_motion (GimpTool         *tool,
+                           const GimpCoords *coords,
+                           guint32           time,
+                           GdkModifierType   state,
+                           GimpDisplay      *display)
+{
+  GimpGradientTool *gradient_tool = GIMP_GRADIENT_TOOL (tool);
+
+  if (gradient_tool->grab_widget)
+    {
+      gimp_tool_widget_motion (gradient_tool->grab_widget, coords, time, state);
+    }
+}
+
+static gboolean
+gimp_gradient_tool_key_press (GimpTool    *tool,
+                              GdkEventKey *kevent,
+                              GimpDisplay *display)
+{
+  GimpGradientTool *gradient_tool = GIMP_GRADIENT_TOOL (tool);
+  GimpDrawTool     *draw_tool     = GIMP_DRAW_TOOL (tool);
+  gboolean          result;
+
+  /* call start_edit() before widget_key_press(), because we need to record the
+   * undo state before widget_key_press() potentially changes it.  note that if
+   * widget_key_press() return FALSE, nothing changes and no undo step is
+   * created.
+   */
+  if (display == draw_tool->display)
+    gimp_gradient_tool_editor_start_edit (gradient_tool);
+
+  result = GIMP_TOOL_CLASS (parent_class)->key_press (tool, kevent, display);
+
+  if (display == draw_tool->display)
+    gimp_gradient_tool_editor_end_edit (gradient_tool, FALSE);
+
+  return result;
+}
+
+static void
+gimp_gradient_tool_modifier_key (GimpTool        *tool,
+                                 GdkModifierType  key,
+                                 gboolean         press,
+                                 GdkModifierType  state,
+                                 GimpDisplay     *display)
+{
+  GimpGradientOptions *options = GIMP_GRADIENT_TOOL_GET_OPTIONS (tool);
+
+  if (key == gimp_get_extend_selection_mask ())
+    {
+      if (options->instant_toggle &&
+          gtk_widget_get_sensitive (options->instant_toggle))
+        {
+          g_object_set (options,
+                        "instant", ! options->instant,
+                        NULL);
+        }
+    }
+}
+
+static void
+gimp_gradient_tool_cursor_update (GimpTool         *tool,
+                                  const GimpCoords *coords,
+                                  GdkModifierType   state,
+                                  GimpDisplay      *display)
+{
+  GimpImage    *image    = gimp_display_get_image (display);
+  GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+
+  if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) ||
+      gimp_item_is_content_locked (GIMP_ITEM (drawable))    ||
+      ! gimp_item_is_visible (GIMP_ITEM (drawable)))
+    {
+      gimp_tool_set_cursor (tool, display,
+                            gimp_tool_control_get_cursor (tool->control),
+                            gimp_tool_control_get_tool_cursor (tool->control),
+                            GIMP_CURSOR_MODIFIER_BAD);
+      return;
+    }
+
+  GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
+}
+
+static const gchar *
+gimp_gradient_tool_can_undo (GimpTool    *tool,
+                             GimpDisplay *display)
+{
+  return gimp_gradient_tool_editor_can_undo (GIMP_GRADIENT_TOOL (tool));
+}
+
+static const gchar *
+gimp_gradient_tool_can_redo (GimpTool    *tool,
+                             GimpDisplay *display)
+{
+  return gimp_gradient_tool_editor_can_redo (GIMP_GRADIENT_TOOL (tool));
+}
+
+static gboolean
+gimp_gradient_tool_undo (GimpTool    *tool,
+                         GimpDisplay *display)
+{
+  return gimp_gradient_tool_editor_undo (GIMP_GRADIENT_TOOL (tool));
+}
+
+static gboolean
+gimp_gradient_tool_redo (GimpTool    *tool,
+                         GimpDisplay *display)
+{
+  return gimp_gradient_tool_editor_redo (GIMP_GRADIENT_TOOL (tool));
+}
+
+static void
+gimp_gradient_tool_options_notify (GimpTool         *tool,
+                                   GimpToolOptions  *options,
+                                   const GParamSpec *pspec)
+{
+  GimpContext   *context    = GIMP_CONTEXT (options);
+  GimpGradientTool *gradient_tool = GIMP_GRADIENT_TOOL (tool);
+
+  if (! strcmp (pspec->name, "gradient"))
+    {
+      gimp_gradient_tool_set_gradient (gradient_tool, context->gradient);
+
+      if (gradient_tool->filter)
+        gimp_drawable_filter_apply (gradient_tool->filter, NULL);
+    }
+  else if (gradient_tool->render_node &&
+           gegl_node_find_property (gradient_tool->render_node, pspec->name))
+    {
+      /* Sync any property changes on the config object that match the op */
+      GValue value = G_VALUE_INIT;
+
+      g_value_init (&value, pspec->value_type);
+
+      g_object_get_property (G_OBJECT (options), pspec->name, &value);
+      gegl_node_set_property (gradient_tool->render_node, pspec->name, &value);
+
+      g_value_unset (&value);
+
+      if (! strcmp (pspec->name, "gradient-type"))
+        {
+          GimpRepeatMode   gradient_repeat;
+          GimpRepeatMode   node_repeat;
+          GimpGradientType gradient_type;
+
+          gradient_repeat = GIMP_PAINT_OPTIONS (options)->gradient_options->gradient_repeat;
+          gradient_type   = GIMP_GRADIENT_OPTIONS (options)->gradient_type;
+          gegl_node_get (gradient_tool->render_node,
+                         "gradient-repeat", &node_repeat,
+                         NULL);
+
+          if (gradient_type >= GIMP_GRADIENT_SHAPEBURST_ANGULAR)
+            {
+              /* These gradient types are only meant to work with repeat
+               * value of "none" so these are the only ones where we
+               * don't keep the render node and the gradient options in
+               * sync.
+               * We could instead reset the "gradient-repeat" value on
+               * GimpGradientOptions, but I assume one would want to revert
+               * back to the last set value if changing back the
+               * gradient type. So instead we just make the option
+               * insensitive (both in GUI and in render).
+               */
+              if (node_repeat != GIMP_REPEAT_NONE)
+                gegl_node_set (gradient_tool->render_node,
+                               "gradient-repeat", GIMP_REPEAT_NONE,
+                               NULL);
+            }
+          else if (node_repeat != gradient_repeat)
+            {
+              gegl_node_set (gradient_tool->render_node,
+                             "gradient-repeat", gradient_repeat,
+                             NULL);
+            }
+
+          if (gimp_gradient_tool_is_shapeburst (gradient_tool))
+            gimp_gradient_tool_precalc_shapeburst (gradient_tool);
+
+          gimp_gradient_tool_update_graph (gradient_tool);
+        }
+
+      gimp_drawable_filter_apply (gradient_tool->filter, NULL);
+    }
+  else if (gradient_tool->render_node                    &&
+           gimp_gradient_tool_is_shapeburst (gradient_tool) &&
+           g_strcmp0 (pspec->name, "distance-metric") == 0)
+    {
+      g_clear_object (&gradient_tool->dist_buffer);
+      gimp_gradient_tool_precalc_shapeburst (gradient_tool);
+      gimp_gradient_tool_update_graph (gradient_tool);
+      gimp_drawable_filter_apply (gradient_tool->filter, NULL);
+    }
+  else if (gradient_tool->filter &&
+           ! strcmp (pspec->name, "opacity"))
+    {
+      gimp_drawable_filter_set_opacity (gradient_tool->filter,
+                                        gimp_context_get_opacity (context));
+    }
+  else if (gradient_tool->filter &&
+           ! strcmp (pspec->name, "paint-mode"))
+    {
+      gimp_drawable_filter_set_mode (gradient_tool->filter,
+                                     gimp_context_get_paint_mode (context),
+                                     GIMP_LAYER_COLOR_SPACE_AUTO,
+                                     GIMP_LAYER_COLOR_SPACE_AUTO,
+                                     GIMP_LAYER_COMPOSITE_AUTO);
+    }
+
+  gimp_gradient_tool_editor_options_notify (gradient_tool, options, pspec);
+}
+
+static void
+gimp_gradient_tool_start (GimpGradientTool *gradient_tool,
+                          const GimpCoords *coords,
+                          GimpDisplay      *display)
+{
+  GimpTool            *tool     = GIMP_TOOL (gradient_tool);
+  GimpDisplayShell    *shell    = gimp_display_get_shell (display);
+  GimpImage           *image    = gimp_display_get_image (display);
+  GimpDrawable        *drawable = gimp_image_get_active_drawable (image);
+  GimpGradientOptions *options  = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+  GimpContext         *context  = GIMP_CONTEXT (options);
+
+  if (options->instant_toggle)
+    gtk_widget_set_sensitive (options->instant_toggle, FALSE);
+
+  tool->display  = display;
+  tool->drawable = drawable;
+
+  gradient_tool->start_x = coords->x;
+  gradient_tool->start_y = coords->y;
+  gradient_tool->end_x   = coords->x;
+  gradient_tool->end_y   = coords->y;
+
+  gradient_tool->widget = gimp_tool_line_new (shell,
+                                              gradient_tool->start_x,
+                                              gradient_tool->start_y,
+                                              gradient_tool->end_x,
+                                              gradient_tool->end_y);
+
+  g_object_set (gradient_tool->widget,
+                "status-title", _("Gradient: "),
+                NULL);
+
+  gimp_draw_tool_set_widget (GIMP_DRAW_TOOL (tool), gradient_tool->widget);
+
+  g_signal_connect (gradient_tool->widget, "changed",
+                    G_CALLBACK (gimp_gradient_tool_line_changed),
+                    gradient_tool);
+  g_signal_connect (gradient_tool->widget, "response",
+                    G_CALLBACK (gimp_gradient_tool_line_response),
+                    gradient_tool);
+
+  g_signal_connect_swapped (context, "background-changed",
+                            G_CALLBACK (gimp_gradient_tool_fg_bg_changed),
+                            gradient_tool);
+  g_signal_connect_swapped (context, "foreground-changed",
+                            G_CALLBACK (gimp_gradient_tool_fg_bg_changed),
+                            gradient_tool);
+
+  gimp_gradient_tool_create_filter (gradient_tool, drawable);
+
+  /* Initially sync all of the properties */
+  gimp_operation_config_sync_node (G_OBJECT (options),
+                                   gradient_tool->render_node);
+
+  /* We don't allow repeat values for some shapes. */
+  if (options->gradient_type >= GIMP_GRADIENT_SHAPEBURST_ANGULAR)
+    gegl_node_set (gradient_tool->render_node,
+                   "gradient-repeat", GIMP_REPEAT_NONE,
+                   NULL);
+
+  /* Connect signal handlers for the gradient */
+  gimp_gradient_tool_set_gradient (gradient_tool, context->gradient);
+
+  if (gimp_gradient_tool_is_shapeburst (gradient_tool))
+    gimp_gradient_tool_precalc_shapeburst (gradient_tool);
+
+  gimp_draw_tool_start (GIMP_DRAW_TOOL (gradient_tool), display);
+
+  gimp_gradient_tool_editor_start (gradient_tool);
+}
+
+static void
+gimp_gradient_tool_halt (GimpGradientTool *gradient_tool)
+{
+  GimpTool            *tool    = GIMP_TOOL (gradient_tool);
+  GimpGradientOptions *options = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+  GimpContext         *context = GIMP_CONTEXT (options);
+
+  gimp_gradient_tool_editor_halt (gradient_tool);
+
+  if (gradient_tool->graph)
+    {
+      g_clear_object (&gradient_tool->graph);
+      gradient_tool->render_node    = NULL;
+#if 0
+      gradient_tool->subtract_node  = NULL;
+      gradient_tool->divide_node    = NULL;
+#endif
+      gradient_tool->dist_node      = NULL;
+    }
+
+  g_clear_object (&gradient_tool->dist_buffer);
+
+  if (gradient_tool->filter)
+    {
+      gimp_tool_control_push_preserve (tool->control, TRUE);
+
+      gimp_drawable_filter_abort (gradient_tool->filter);
+      g_object_unref (gradient_tool->filter);
+      gradient_tool->filter = NULL;
+
+      gimp_tool_control_pop_preserve (tool->control);
+
+      gimp_image_flush (gimp_display_get_image (tool->display));
+    }
+
+  gimp_gradient_tool_set_tentative_gradient (gradient_tool, NULL);
+
+  g_signal_handlers_disconnect_by_func (context,
+                                        G_CALLBACK (gimp_gradient_tool_fg_bg_changed),
+                                        gradient_tool);
+
+  if (tool->display)
+    gimp_tool_pop_status (tool, tool->display);
+
+  if (gimp_draw_tool_is_active (GIMP_DRAW_TOOL (gradient_tool)))
+    gimp_draw_tool_stop (GIMP_DRAW_TOOL (gradient_tool));
+
+  gimp_draw_tool_set_widget (GIMP_DRAW_TOOL (tool), NULL);
+  g_clear_object (&gradient_tool->widget);
+
+  tool->display  = NULL;
+  tool->drawable = NULL;
+
+  if (options->instant_toggle)
+    gtk_widget_set_sensitive (options->instant_toggle, TRUE);
+}
+
+static void
+gimp_gradient_tool_commit (GimpGradientTool *gradient_tool)
+{
+  GimpTool *tool = GIMP_TOOL (gradient_tool);
+
+  if (gradient_tool->filter)
+    {
+      gimp_tool_control_push_preserve (tool->control, TRUE);
+
+      gimp_drawable_filter_commit (gradient_tool->filter,
+                                   GIMP_PROGRESS (tool), FALSE);
+      g_clear_object (&gradient_tool->filter);
+
+      gimp_tool_control_pop_preserve (tool->control);
+
+      gimp_image_flush (gimp_display_get_image (tool->display));
+    }
+}
+
+static void
+gimp_gradient_tool_line_changed (GimpToolWidget   *widget,
+                                 GimpGradientTool *gradient_tool)
+{
+  gdouble  start_x;
+  gdouble  start_y;
+  gdouble  end_x;
+  gdouble  end_y;
+  gboolean update = FALSE;
+
+  g_object_get (widget,
+                "x1", &start_x,
+                "y1", &start_y,
+                "x2", &end_x,
+                "y2", &end_y,
+                NULL);
+
+  if (start_x != gradient_tool->start_x ||
+      start_y != gradient_tool->start_y ||
+      end_x   != gradient_tool->end_x   ||
+      end_y   != gradient_tool->end_y)
+    {
+      gradient_tool->start_x = start_x;
+      gradient_tool->start_y = start_y;
+      gradient_tool->end_x   = end_x;
+      gradient_tool->end_y   = end_y;
+
+      update = TRUE;
+    }
+
+  if (gimp_gradient_tool_editor_line_changed (gradient_tool))
+    update = TRUE;
+
+  if (update)
+    {
+      gimp_gradient_tool_update_graph (gradient_tool);
+      gimp_drawable_filter_apply (gradient_tool->filter, NULL);
+    }
+}
+
+static void
+gimp_gradient_tool_line_response (GimpToolWidget *widget,
+                                  gint            response_id,
+                                  GimpGradientTool  *gradient_tool)
+{
+  GimpTool *tool = GIMP_TOOL (gradient_tool);
+
+  switch (response_id)
+    {
+    case GIMP_TOOL_WIDGET_RESPONSE_CONFIRM:
+      gimp_tool_control (tool, GIMP_TOOL_ACTION_COMMIT, tool->display);
+      break;
+
+    case GIMP_TOOL_WIDGET_RESPONSE_CANCEL:
+      gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, tool->display);
+      break;
+    }
+}
+
+static void
+gimp_gradient_tool_precalc_shapeburst (GimpGradientTool *gradient_tool)
+{
+  GimpGradientOptions *options = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+  GimpTool            *tool    = GIMP_TOOL (gradient_tool);
+  gint                 x, y, width, height;
+
+  if (gradient_tool->dist_buffer || ! tool->drawable)
+    return;
+
+  if (! gimp_item_mask_intersect (GIMP_ITEM (tool->drawable),
+                                  &x, &y, &width, &height))
+    return;
+
+  gradient_tool->dist_buffer =
+    gimp_drawable_gradient_shapeburst_distmap (tool->drawable,
+                                               options->distance_metric,
+                                               GEGL_RECTANGLE (x, y, width, height),
+                                               GIMP_PROGRESS (gradient_tool));
+
+  if (gradient_tool->dist_node)
+    gegl_node_set (gradient_tool->dist_node,
+                   "buffer", gradient_tool->dist_buffer,
+                   NULL);
+
+  gimp_progress_end (GIMP_PROGRESS (gradient_tool));
+}
+
+
+/* gegl graph stuff */
+
+static void
+gimp_gradient_tool_create_graph (GimpGradientTool *gradient_tool)
+{
+  GimpGradientOptions *options = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+  GimpContext         *context = GIMP_CONTEXT (options);
+  GeglNode            *output;
+
+  /* render_node is not supposed to be recreated */
+  g_return_if_fail (gradient_tool->graph == NULL);
+
+  gradient_tool->graph = gegl_node_new ();
+
+  gradient_tool->dist_node =
+    gegl_node_new_child (gradient_tool->graph,
+                         "operation", "gegl:buffer-source",
+                         "buffer",    gradient_tool->dist_buffer,
+                         NULL);
+
+#if 0
+  gradient_tool->subtract_node =
+    gegl_node_new_child (gradient_tool->graph,
+                         "operation", "gegl:subtract",
+                         NULL);
+
+  gradient_tool->divide_node =
+    gegl_node_new_child (gradient_tool->graph,
+                         "operation", "gegl:divide",
+                         NULL);
+#endif
+
+  gradient_tool->render_node =
+    gegl_node_new_child (gradient_tool->graph,
+                         "operation", "gimp:gradient",
+                         "context", context,
+                         NULL);
+
+  output = gegl_node_get_output_proxy (gradient_tool->graph, "output");
+
+  gegl_node_link_many (gradient_tool->dist_node,
+#if 0
+                       gradient_tool->subtract_node,
+                       gradient_tool->divide_node,
+#endif
+                       gradient_tool->render_node,
+                       output,
+                       NULL);
+
+  gimp_gradient_tool_update_graph (gradient_tool);
+}
+
+static void
+gimp_gradient_tool_update_graph (GimpGradientTool *gradient_tool)
+{
+  GimpTool *tool = GIMP_TOOL (gradient_tool);
+  gint      off_x, off_y;
+
+  gimp_item_get_offset (GIMP_ITEM (tool->drawable), &off_x, &off_y);
+
+#if 0
+  if (gimp_gradient_tool_is_shapeburst (gradient_tool))
+    {
+      gfloat start, end;
+
+      gegl_buffer_get (gradient_tool->dist_buffer,
+                       GEGL_RECTANGLE (gradient_tool->start_x - off_x,
+                                       gradient_tool->start_y - off_y,
+                                       1, 1),
+                       1.0, babl_format("Y float"), &start,
+                       GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+
+      gegl_buffer_get (gradient_tool->dist_buffer,
+                       GEGL_RECTANGLE (gradient_tool->end_x - off_x,
+                                       gradient_tool->end_y - off_y,
+                                       1, 1),
+                       1.0, babl_format("Y float"), &end,
+                       GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+
+      if (start != end)
+        {
+          gegl_node_set (gradient_tool->subtract_node,
+                         "value", (gdouble) start,
+                         NULL);
+          gegl_node_set (gradient_tool->divide_node,
+                         "value", (gdouble) (end - start),
+                         NULL);
+        }
+    }
+  else
+#endif
+    {
+      gegl_node_set (gradient_tool->render_node,
+                     "start_x", gradient_tool->start_x - off_x,
+                     "start_y", gradient_tool->start_y - off_y,
+                     "end_x",   gradient_tool->end_x - off_x,
+                     "end_y",   gradient_tool->end_y - off_y,
+                     NULL);
+    }
+}
+
+static void
+gimp_gradient_tool_fg_bg_changed (GimpGradientTool *gradient_tool)
+{
+  if (! gradient_tool->filter || ! gradient_tool->gradient)
+    return;
+
+  if (gimp_gradient_has_fg_bg_segments (gradient_tool->gradient))
+    {
+      /* Set a property on the node. Otherwise it will cache and refuse to update */
+      gegl_node_set (gradient_tool->render_node,
+                     "gradient", gradient_tool->gradient,
+                     NULL);
+
+      /* Update the filter */
+      gimp_drawable_filter_apply (gradient_tool->filter, NULL);
+
+      gimp_gradient_tool_editor_fg_bg_changed (gradient_tool);
+    }
+}
+
+static void
+gimp_gradient_tool_gradient_dirty (GimpGradientTool *gradient_tool)
+{
+  if (! gradient_tool->filter)
+    return;
+
+  if (! gradient_tool->tentative_gradient)
+    {
+      /* Set a property on the node. Otherwise it will cache and refuse to update */
+      gegl_node_set (gradient_tool->render_node,
+                     "gradient", gradient_tool->gradient,
+                     NULL);
+
+      /* Update the filter */
+      gimp_drawable_filter_apply (gradient_tool->filter, NULL);
+    }
+
+  gimp_gradient_tool_editor_gradient_dirty (gradient_tool);
+}
+
+static void
+gimp_gradient_tool_set_gradient (GimpGradientTool *gradient_tool,
+                                 GimpGradient     *gradient)
+{
+  if (gradient_tool->gradient)
+    {
+      g_signal_handlers_disconnect_by_func (gradient_tool->gradient,
+                                            G_CALLBACK (gimp_gradient_tool_gradient_dirty),
+                                            gradient_tool);
+
+      g_object_unref (gradient_tool->gradient);
+    }
+
+  gradient_tool->gradient = gradient;
+
+  if (gradient_tool->gradient)
+    {
+      g_object_ref (gradient);
+
+      g_signal_connect_swapped (gradient_tool->gradient, "dirty",
+                                G_CALLBACK (gimp_gradient_tool_gradient_dirty),
+                                gradient_tool);
+
+      if (gradient_tool->render_node)
+        gegl_node_set (gradient_tool->render_node,
+                       "gradient", gradient_tool->gradient,
+                       NULL);
+    }
+
+  gimp_gradient_tool_editor_gradient_changed (gradient_tool);
+}
+
+static gboolean
+gimp_gradient_tool_is_shapeburst (GimpGradientTool *gradient_tool)
+{
+  GimpGradientOptions *options = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+
+  return options->gradient_type >= GIMP_GRADIENT_SHAPEBURST_ANGULAR &&
+         options->gradient_type <= GIMP_GRADIENT_SHAPEBURST_DIMPLED;
+}
+
+
+/* image map stuff */
+
+static void
+gimp_gradient_tool_create_filter (GimpGradientTool *gradient_tool,
+                                  GimpDrawable     *drawable)
+{
+  GimpGradientOptions *options = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
+  GimpContext         *context = GIMP_CONTEXT (options);
+
+  if (! gradient_tool->graph)
+    gimp_gradient_tool_create_graph (gradient_tool);
+
+  gradient_tool->filter = gimp_drawable_filter_new (drawable,
+                                                 C_("undo-type", "Gradient"),
+                                                 gradient_tool->graph,
+                                                 GIMP_ICON_TOOL_GRADIENT);
+
+  gimp_drawable_filter_set_region (gradient_tool->filter,
+                                   GIMP_FILTER_REGION_DRAWABLE);
+  gimp_drawable_filter_set_opacity (gradient_tool->filter,
+                                    gimp_context_get_opacity (context));
+  gimp_drawable_filter_set_mode (gradient_tool->filter,
+                                 gimp_context_get_paint_mode (context),
+                                 GIMP_LAYER_COLOR_SPACE_AUTO,
+                                 GIMP_LAYER_COLOR_SPACE_AUTO,
+                                 GIMP_LAYER_COMPOSITE_AUTO);
+
+  g_signal_connect (gradient_tool->filter, "flush",
+                    G_CALLBACK (gimp_gradient_tool_filter_flush),
+                    gradient_tool);
+}
+
+static void
+gimp_gradient_tool_filter_flush (GimpDrawableFilter *filter,
+                                 GimpTool           *tool)
+{
+  GimpImage *image = gimp_display_get_image (tool->display);
+
+  gimp_projection_flush (gimp_image_get_projection (image));
+}
+
+
+/*  protected functions  */
+
+
+void
+gimp_gradient_tool_set_tentative_gradient (GimpGradientTool *gradient_tool,
+                                           GimpGradient     *gradient)
+{
+  g_return_if_fail (GIMP_IS_GRADIENT_TOOL (gradient_tool));
+  g_return_if_fail (gradient == NULL || GIMP_IS_GRADIENT (gradient));
+
+  if (gradient != gradient_tool->tentative_gradient)
+    {
+      g_clear_object (&gradient_tool->tentative_gradient);
+
+      gradient_tool->tentative_gradient = gradient;
+
+      if (gradient)
+        g_object_ref (gradient);
+
+      if (gradient_tool->render_node)
+        {
+          gegl_node_set (gradient_tool->render_node,
+                         "gradient", gradient ? gradient : gradient_tool->gradient,
+                         NULL);
+
+          gimp_drawable_filter_apply (gradient_tool->filter, NULL);
+        }
+    }
+}
diff --git a/app/tools/gimpblendtool.h b/app/tools/gimpgradienttool.h
similarity index 62%
rename from app/tools/gimpblendtool.h
rename to app/tools/gimpgradienttool.h
index 08862bc..23d6855 100644
--- a/app/tools/gimpblendtool.h
+++ b/app/tools/gimpgradienttool.h
@@ -15,27 +15,27 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef  __GIMP_BLEND_TOOL_H__
-#define  __GIMP_BLEND_TOOL_H__
+#ifndef  __GIMP_GRADIENT_TOOL_H__
+#define  __GIMP_GRADIENT_TOOL_H__
 
 
 #include "gimpdrawtool.h"
 
 
-#define GIMP_TYPE_BLEND_TOOL            (gimp_blend_tool_get_type ())
-#define GIMP_BLEND_TOOL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_BLEND_TOOL, 
GimpBlendTool))
-#define GIMP_BLEND_TOOL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_BLEND_TOOL, 
GimpBlendToolClass))
-#define GIMP_IS_BLEND_TOOL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_BLEND_TOOL))
-#define GIMP_IS_BLEND_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_BLEND_TOOL))
-#define GIMP_BLEND_TOOL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_BLEND_TOOL, 
GimpBlendToolClass))
+#define GIMP_TYPE_GRADIENT_TOOL            (gimp_gradient_tool_get_type ())
+#define GIMP_GRADIENT_TOOL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_GRADIENT_TOOL, 
GimpGradientTool))
+#define GIMP_GRADIENT_TOOL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_GRADIENT_TOOL, 
GimpGradientToolClass))
+#define GIMP_IS_GRADIENT_TOOL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_GRADIENT_TOOL))
+#define GIMP_IS_GRADIENT_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_GRADIENT_TOOL))
+#define GIMP_GRADIENT_TOOL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_GRADIENT_TOOL, 
GimpGradientToolClass))
 
-#define GIMP_BLEND_TOOL_GET_OPTIONS(t)  (GIMP_BLEND_OPTIONS (gimp_tool_get_options (GIMP_TOOL (t))))
+#define GIMP_GRADIENT_TOOL_GET_OPTIONS(t)  (GIMP_GRADIENT_OPTIONS (gimp_tool_get_options (GIMP_TOOL (t))))
 
 
-typedef struct _GimpBlendTool      GimpBlendTool;
-typedef struct _GimpBlendToolClass GimpBlendToolClass;
+typedef struct _GimpGradientTool      GimpGradientTool;
+typedef struct _GimpGradientToolClass GimpGradientToolClass;
 
-struct _GimpBlendTool
+struct _GimpGradientTool
 {
   GimpDrawTool        parent_instance;
 
@@ -90,22 +90,22 @@ struct _GimpBlendTool
   GtkWidget          *midpoint_center_button;
 };
 
-struct _GimpBlendToolClass
+struct _GimpGradientToolClass
 {
   GimpDrawToolClass  parent_class;
 };
 
 
-void    gimp_blend_tool_register               (GimpToolRegisterCallback  callback,
-                                                gpointer                  data);
+void    gimp_gradient_tool_register               (GimpToolRegisterCallback  callback,
+                                                   gpointer                  data);
 
-GType   gimp_blend_tool_get_type               (void) G_GNUC_CONST;
+GType   gimp_gradient_tool_get_type               (void) G_GNUC_CONST;
 
 
 /*  protected functions  */
 
-void    gimp_blend_tool_set_tentative_gradient (GimpBlendTool            *blend_tool,
-                                                GimpGradient             *gradient);
+void    gimp_gradient_tool_set_tentative_gradient (GimpGradientTool         *gradient_tool,
+                                                   GimpGradient             *gradient);
 
 
-#endif  /*  __GIMP_BLEND_TOOL_H__  */
+#endif  /*  __GIMP_GRADIENT_TOOL_H__  */
diff --git a/app/tools/tool_manager.c b/app/tools/tool_manager.c
index 53f75be..3bd698b 100644
--- a/app/tools/tool_manager.c
+++ b/app/tools/tool_manager.c
@@ -894,7 +894,7 @@ tool_manager_cast_spell (GimpToolInfo *tool_info)
   {
     { .sequence = "gimp-warp-tool\0"
                   "gimp-iscissors-tool\0"
-                  "gimp-blend-tool\0"
+                  "gimp-gradient-tool\0"
                   "gimp-vector-tool\0"
                   "gimp-ellipse-select-tool\0"
                   "gimp-rect-select-tool\0",
diff --git a/app/widgets/gimphelp-ids.h b/app/widgets/gimphelp-ids.h
index b71df70..254e939 100644
--- a/app/widgets/gimphelp-ids.h
+++ b/app/widgets/gimphelp-ids.h
@@ -287,7 +287,6 @@
 
 #define GIMP_HELP_TOOL_AIRBRUSH                   "gimp-tool-airbrush"
 #define GIMP_HELP_TOOL_ALIGN                      "gimp-tool-align"
-#define GIMP_HELP_TOOL_BLEND                      "gimp-tool-blend"
 #define GIMP_HELP_TOOL_BRIGHTNESS_CONTRAST        "gimp-tool-brightness-contrast"
 #define GIMP_HELP_TOOL_BUCKET_FILL                "gimp-tool-bucket-fill"
 #define GIMP_HELP_TOOL_BY_COLOR_SELECT            "gimp-tool-by-color-select"
@@ -308,6 +307,7 @@
 #define GIMP_HELP_TOOL_FOREGROUND_SELECT          "gimp-tool-foreground-select"
 #define GIMP_HELP_TOOL_FUZZY_SELECT               "gimp-tool-fuzzy-select"
 #define GIMP_HELP_TOOL_GEGL                       "gimp-tool-gegl"
+#define GIMP_HELP_TOOL_GRADIENT                   "gimp-tool-gradient"
 #define GIMP_HELP_TOOL_HANDLE_TRANSFORM           "gimp-tool-handle-transform"
 #define GIMP_HELP_TOOL_HEAL                       "gimp-tool-heal"
 #define GIMP_HELP_TOOL_HUE_SATURATION             "gimp-tool-hue-saturation"
diff --git a/data/tool-presets/FX/FX-Radial-Softlight.gtp b/data/tool-presets/FX/FX-Radial-Softlight.gtp
index 3d642bf..8c277af 100644
--- a/data/tool-presets/FX/FX-Radial-Softlight.gtp
+++ b/data/tool-presets/FX/FX-Radial-Softlight.gtp
@@ -1,9 +1,9 @@
 # GIMP tool preset file
 
-(icon-name "gimp-tool-blend")
+(icon-name "gimp-tool-gradient")
 (name "FX Radial Softlight")
-(tool-options "GimpBlendOptions"
-    (tool "gimp-blend-tool")
+(tool-options "GimpGradientOptions"
+    (tool "gimp-gradient-tool")
     (foreground (color-rgb 0.102075 0.183901 0.594317))
     (paint-mode softlight-mode)
     (gradient "FG to Transparent")
diff --git a/data/tool-presets/FX/Vignette.gtp b/data/tool-presets/FX/Vignette.gtp
index 3494836..476312a 100644
--- a/data/tool-presets/FX/Vignette.gtp
+++ b/data/tool-presets/FX/Vignette.gtp
@@ -1,9 +1,9 @@
 # GIMP tool preset file
 
-(icon-name "gimp-tool-blend")
+(icon-name "gimp-tool-gradient")
 (name "Vignette")
-(tool-options "GimpBlendOptions"
-    (tool "gimp-blend-tool")
+(tool-options "GimpGradientOptions"
+    (tool "gimp-gradient-tool")
     (opacity 0.750000)
     (paint-mode multiply-mode)
     (gradient "FG to Transparent")
diff --git a/menus/image-menu.xml.in b/menus/image-menu.xml.in
index 47553b6..13e6560 100644
--- a/menus/image-menu.xml.in
+++ b/menus/image-menu.xml.in
@@ -637,7 +637,7 @@
       </menu>
       <menu action="tools-paint-menu" name="Paint Tools">
         <menuitem action="tools-bucket-fill" />
-        <menuitem action="tools-blend" />
+        <menuitem action="tools-gradient" />
         <menuitem action="tools-pencil" />
         <menuitem action="tools-paintbrush" />
         <menuitem action="tools-eraser" />
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 8678079..ae06cdb 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -405,9 +405,6 @@ app/tools/gimp-tools.c
 app/tools/gimpairbrushtool.c
 app/tools/gimpalignoptions.c
 app/tools/gimpaligntool.c
-app/tools/gimpblendoptions.c
-app/tools/gimpblendtool.c
-app/tools/gimpblendtool-editor.c
 app/tools/gimpbrightnesscontrasttool.c
 app/tools/gimpbucketfilloptions.c
 app/tools/gimpbucketfilltool.c
@@ -439,6 +436,9 @@ app/tools/gimpfreeselecttool.c
 app/tools/gimpfuzzyselecttool.c
 app/tools/gimpgegltool.c
 app/tools/gimpgenerictransformtool.c
+app/tools/gimpgradientptions.c
+app/tools/gimpgradienttool.c
+app/tools/gimpgradienttool-editor.c
 app/tools/gimpguidetool.c
 app/tools/gimphandletransformoptions.c
 app/tools/gimphandletransformtool.c


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