[gimp] app: port the rectangle and ellipse select tools to GimpToolRectangle



commit 1d33b20db6c8ea81b352a5b192dee7b250b9a617
Author: Michael Natterer <mitch gimp org>
Date:   Tue Jun 27 18:25:31 2017 +0200

    app: port the rectangle and ellipse select tools to GimpToolRectangle

 app/tools/gimpellipseselecttool.c   |   31 +-
 app/tools/gimprectangleselecttool.c |  890 +++++++++++++++++------------------
 app/tools/gimprectangleselecttool.h |   11 +-
 3 files changed, 446 insertions(+), 486 deletions(-)
---
diff --git a/app/tools/gimpellipseselecttool.c b/app/tools/gimpellipseselecttool.c
index 17f9c14..8c0ec7f 100644
--- a/app/tools/gimpellipseselecttool.c
+++ b/app/tools/gimpellipseselecttool.c
@@ -38,8 +38,6 @@
 #include "gimp-intl.h"
 
 
-static void   gimp_ellipse_select_tool_draw   (GimpDrawTool            *draw_tool);
-
 static void   gimp_ellipse_select_tool_select (GimpRectangleSelectTool *rect_tool,
                                                GimpChannelOps           operation,
                                                gint                     x,
@@ -74,12 +72,12 @@ gimp_ellipse_select_tool_register (GimpToolRegisterCallback  callback,
 static void
 gimp_ellipse_select_tool_class_init (GimpEllipseSelectToolClass *klass)
 {
-  GimpDrawToolClass            *draw_tool_class = GIMP_DRAW_TOOL_CLASS (klass);
-  GimpRectangleSelectToolClass *rect_tool_class = GIMP_RECTANGLE_SELECT_TOOL_CLASS (klass);
+  GimpRectangleSelectToolClass *rect_tool_class;
 
-  draw_tool_class->draw   = gimp_ellipse_select_tool_draw;
+  rect_tool_class = GIMP_RECTANGLE_SELECT_TOOL_CLASS (klass);
 
-  rect_tool_class->select = gimp_ellipse_select_tool_select;
+  rect_tool_class->select       = gimp_ellipse_select_tool_select;
+  rect_tool_class->draw_ellipse = TRUE;
 }
 
 static void
@@ -92,27 +90,6 @@ gimp_ellipse_select_tool_init (GimpEllipseSelectTool *ellipse_select)
 }
 
 static void
-gimp_ellipse_select_tool_draw (GimpDrawTool *draw_tool)
-{
-  gint x1, y1, x2, y2;
-
-  GIMP_DRAW_TOOL_CLASS (parent_class)->draw (draw_tool);
-
-  g_object_get (draw_tool,
-                "x1", &x1,
-                "y1", &y1,
-                "x2", &x2,
-                "y2", &y2,
-                NULL);
-
-  gimp_draw_tool_add_arc (draw_tool,
-                          FALSE,
-                          x1, y1,
-                          x2 - x1, y2 - y1,
-                          0.0, 2 * G_PI);
-}
-
-static void
 gimp_ellipse_select_tool_select (GimpRectangleSelectTool *rect_tool,
                                  GimpChannelOps           operation,
                                  gint                     x,
diff --git a/app/tools/gimprectangleselecttool.c b/app/tools/gimprectangleselecttool.c
index 933a4f1..72916b7 100644
--- a/app/tools/gimprectangleselecttool.c
+++ b/app/tools/gimprectangleselecttool.c
@@ -25,7 +25,6 @@
 
 #include "tools-types.h"
 
-#include "core/gimp-utils.h"
 #include "core/gimpchannel-select.h"
 #include "core/gimpchannel.h"
 #include "core/gimpimage.h"
@@ -34,21 +33,15 @@
 #include "core/gimppickable.h"
 #include "core/gimpundostack.h"
 
-#include "widgets/gimpdialogfactory.h"
 #include "widgets/gimphelp-ids.h"
-#include "widgets/gimpviewabledialog.h"
 #include "widgets/gimpwidgets-utils.h"
 
-#include "display/gimpcanvasgroup.h"
 #include "display/gimpdisplay.h"
 #include "display/gimpdisplayshell.h"
-#include "display/gimpdisplayshell-transform.h"
 #include "display/gimpdisplayshell-appearance.h"
+#include "display/gimptoolrectangle.h"
 
 #include "gimpeditselectiontool.h"
-#include "gimpselectiontool.h"
-#include "gimpselectionoptions.h"
-#include "gimprectangletool.h"
 #include "gimprectangleoptions.h"
 #include "gimprectangleselecttool.h"
 #include "gimprectangleselectoptions.h"
@@ -57,7 +50,7 @@
 #include "gimp-intl.h"
 
 
-typedef struct GimpRectangleSelectToolPrivate
+struct _GimpRectangleSelectToolPrivate
 {
   GimpChannelOps     operation;            /* remember for use when modifying   */
   gboolean           use_saved_op;         /* use operation or get from options */
@@ -65,21 +58,13 @@ typedef struct GimpRectangleSelectToolPrivate
   GimpUndo          *undo;
   GimpUndo          *redo;
 
-  gboolean           round_corners;
-  gdouble            corner_radius;
-
   gdouble            press_x;
   gdouble            press_y;
-} GimpRectangleSelectToolPrivate;
-
-
-#define GIMP_RECTANGLE_SELECT_TOOL_GET_PRIVATE(obj) \
-  ((GimpRectangleSelectToolPrivate *) ((GimpRectangleSelectTool *) (obj))->priv)
 
+  GimpToolWidget    *rectangle;
+  GimpToolWidget    *grab_widget;
+};
 
-static void     gimp_rectangle_select_tool_rectangle_tool_iface_init (GimpRectangleToolInterface *iface);
-
-static void     gimp_rectangle_select_tool_constructed    (GObject               *object);
 
 static void     gimp_rectangle_select_tool_control        (GimpTool              *tool,
                                                            GimpToolAction         action,
@@ -96,10 +81,9 @@ static void     gimp_rectangle_select_tool_button_release (GimpTool
                                                            GdkModifierType        state,
                                                            GimpButtonReleaseType  release_type,
                                                            GimpDisplay           *display);
-static void     gimp_rectangle_select_tool_active_modifier_key
-                                                          (GimpTool              *tool,
-                                                           GdkModifierType        key,
-                                                           gboolean               press,
+static void     gimp_rectangle_select_tool_motion         (GimpTool              *tool,
+                                                           const GimpCoords      *coords,
+                                                           guint32                time,
                                                            GdkModifierType        state,
                                                            GimpDisplay           *display);
 static gboolean gimp_rectangle_select_tool_key_press      (GimpTool              *tool,
@@ -114,42 +98,40 @@ static void     gimp_rectangle_select_tool_cursor_update  (GimpTool
                                                            const GimpCoords      *coords,
                                                            GdkModifierType        state,
                                                            GimpDisplay           *display);
-static void     gimp_rectangle_select_tool_draw           (GimpDrawTool          *draw_tool);
-static gboolean gimp_rectangle_select_tool_select         (GimpRectangleTool     *rect_tool,
-                                                           gint                   x,
-                                                           gint                   y,
-                                                           gint                   w,
-                                                           gint                   h);
-static gboolean gimp_rectangle_select_tool_execute        (GimpRectangleTool     *rect_tool,
+
+static gboolean gimp_rectangle_select_tool_select         (GimpRectangleSelectTool *rect_tool,
                                                            gint                   x,
                                                            gint                   y,
                                                            gint                   w,
                                                            gint                   h);
-static void     gimp_rectangle_select_tool_cancel         (GimpRectangleTool     *rect_tool);
-static gboolean gimp_rectangle_select_tool_rectangle_change_complete
-                                                          (GimpRectangleTool     *rect_tool);
-static void     gimp_rectangle_select_tool_real_select    (GimpRectangleSelectTool *rect_sel_tool,
+static void     gimp_rectangle_select_tool_real_select    (GimpRectangleSelectTool *rect_tool,
                                                            GimpChannelOps         operation,
                                                            gint                   x,
                                                            gint                   y,
                                                            gint                   w,
                                                            gint                   h);
+
+static void     gimp_rectangle_select_tool_rectangle_response
+                                                          (GimpToolWidget          *widget,
+                                                           gint                     response_id,
+                                                           GimpRectangleSelectTool *rect_tool);
+static void     gimp_rectangle_select_tool_rectangle_change_complete
+                                                          (GimpToolWidget          *widget,
+                                                           GimpRectangleSelectTool *rect_tool);
+
+static void     gimp_rectangle_select_tool_commit         (GimpRectangleSelectTool *rect_tool);
+static void     gimp_rectangle_select_tool_halt           (GimpRectangleSelectTool *rect_tool);
+
 static GimpChannelOps
-                gimp_rectangle_select_tool_get_operation  (GimpRectangleSelectTool    *rect_sel_tool);
+                gimp_rectangle_select_tool_get_operation  (GimpRectangleSelectTool *rect_tool);
 static void     gimp_rectangle_select_tool_update_option_defaults
-                                                          (GimpRectangleSelectTool    *rect_sel_tool,
-                                                           gboolean                    ignore_pending);
-
-static void     gimp_rectangle_select_tool_round_corners_notify
-                                                          (GimpRectangleSelectOptions *options,
-                                                           GParamSpec                 *pspec,
-                                                           GimpRectangleSelectTool    *rect_sel_tool);
+                                                          (GimpRectangleSelectTool *rect_tool,
+                                                           gboolean                 ignore_pending);
+static void     gimp_rectangle_select_tool_auto_shrink    (GimpRectangleSelectTool *rect_tool);
 
 
-G_DEFINE_TYPE_WITH_CODE (GimpRectangleSelectTool, gimp_rectangle_select_tool,
-                         GIMP_TYPE_SELECTION_TOOL,
-                         G_IMPLEMENT_INTERFACE (GIMP_TYPE_RECTANGLE_TOOL,
-                                                gimp_rectangle_select_tool_rectangle_tool_iface_init))
+G_DEFINE_TYPE (GimpRectangleSelectTool, gimp_rectangle_select_tool,
+               GIMP_TYPE_SELECTION_TOOL)
 
 #define parent_class gimp_rectangle_select_tool_parent_class
 
@@ -174,53 +156,30 @@ gimp_rectangle_select_tool_register (GimpToolRegisterCallback  callback,
 static void
 gimp_rectangle_select_tool_class_init (GimpRectangleSelectToolClass *klass)
 {
-  GObjectClass      *object_class    = G_OBJECT_CLASS (klass);
-  GimpToolClass     *tool_class      = GIMP_TOOL_CLASS (klass);
-  GimpDrawToolClass *draw_tool_class = GIMP_DRAW_TOOL_CLASS (klass);
-
-  g_type_class_add_private (klass, sizeof (GimpRectangleSelectToolPrivate));
+  GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
 
-  object_class->constructed       = gimp_rectangle_select_tool_constructed;
-  object_class->set_property      = gimp_rectangle_tool_set_property;
-  object_class->get_property      = gimp_rectangle_tool_get_property;
+  tool_class->control        = gimp_rectangle_select_tool_control;
+  tool_class->button_press   = gimp_rectangle_select_tool_button_press;
+  tool_class->button_release = gimp_rectangle_select_tool_button_release;
+  tool_class->motion         = gimp_rectangle_select_tool_motion;
+  tool_class->key_press      = gimp_rectangle_select_tool_key_press;
+  tool_class->oper_update    = gimp_rectangle_select_tool_oper_update;
+  tool_class->cursor_update  = gimp_rectangle_select_tool_cursor_update;
 
-  tool_class->control             = gimp_rectangle_select_tool_control;
-  tool_class->button_press        = gimp_rectangle_select_tool_button_press;
-  tool_class->button_release      = gimp_rectangle_select_tool_button_release;
-  tool_class->motion              = gimp_rectangle_tool_motion;
-  tool_class->key_press           = gimp_rectangle_select_tool_key_press;
-  tool_class->active_modifier_key = gimp_rectangle_select_tool_active_modifier_key;
-  tool_class->oper_update         = gimp_rectangle_select_tool_oper_update;
-  tool_class->cursor_update       = gimp_rectangle_select_tool_cursor_update;
+  klass->select              = gimp_rectangle_select_tool_real_select;
 
-  draw_tool_class->draw           = gimp_rectangle_select_tool_draw;
-
-  klass->select                   = gimp_rectangle_select_tool_real_select;
-
-  gimp_rectangle_tool_install_properties (object_class);
-}
-
-static void
-gimp_rectangle_select_tool_rectangle_tool_iface_init (GimpRectangleToolInterface *iface)
-{
-  iface->execute                   = gimp_rectangle_select_tool_execute;
-  iface->cancel                    = gimp_rectangle_select_tool_cancel;
-  iface->rectangle_change_complete = gimp_rectangle_select_tool_rectangle_change_complete;
+  g_type_class_add_private (klass, sizeof (GimpRectangleSelectToolPrivate));
 }
 
 static void
-gimp_rectangle_select_tool_init (GimpRectangleSelectTool *rect_sel_tool)
+gimp_rectangle_select_tool_init (GimpRectangleSelectTool *rect_tool)
 {
-  GimpTool                       *tool = GIMP_TOOL (rect_sel_tool);
-  GimpRectangleSelectToolPrivate *priv;
-
-  gimp_rectangle_tool_init (GIMP_RECTANGLE_TOOL (rect_sel_tool));
-
-  rect_sel_tool->priv = G_TYPE_INSTANCE_GET_PRIVATE (rect_sel_tool,
-                                                     GIMP_TYPE_RECTANGLE_SELECT_TOOL,
-                                                     GimpRectangleSelectToolPrivate);
+  GimpTool *tool = GIMP_TOOL (rect_tool);
 
-  priv = GIMP_RECTANGLE_SELECT_TOOL_GET_PRIVATE (rect_sel_tool);
+  rect_tool->private =
+    G_TYPE_INSTANCE_GET_PRIVATE (rect_tool,
+                                 GIMP_TYPE_RECTANGLE_SELECT_TOOL,
+                                 GimpRectangleSelectToolPrivate);
 
   gimp_tool_control_set_wants_click (tool->control, TRUE);
   gimp_tool_control_set_precision   (tool->control,
@@ -231,40 +190,6 @@ gimp_rectangle_select_tool_init (GimpRectangleSelectTool *rect_sel_tool)
   gimp_tool_control_set_dirty_mask  (tool->control,
                                      GIMP_DIRTY_IMAGE_SIZE |
                                      GIMP_DIRTY_SELECTION);
-
-  priv->undo    = NULL;
-  priv->redo    = NULL;
-
-  priv->press_x = 0.0;
-  priv->press_y = 0.0;
-}
-
-static void
-gimp_rectangle_select_tool_constructed (GObject *object)
-{
-  GimpRectangleSelectTool        *rect_sel_tool;
-  GimpRectangleSelectOptions     *options;
-  GimpRectangleSelectToolPrivate *priv;
-
-  G_OBJECT_CLASS (parent_class)->constructed (object);
-
-  gimp_rectangle_tool_constructor (object);
-
-  rect_sel_tool = GIMP_RECTANGLE_SELECT_TOOL (object);
-  options       = GIMP_RECTANGLE_SELECT_TOOL_GET_OPTIONS (rect_sel_tool);
-  priv          = GIMP_RECTANGLE_SELECT_TOOL_GET_PRIVATE (rect_sel_tool);
-
-  priv->round_corners = options->round_corners;
-  priv->corner_radius = options->corner_radius;
-
-  g_signal_connect_object (options, "notify::round-corners",
-                           G_CALLBACK (gimp_rectangle_select_tool_round_corners_notify),
-                           object, 0);
-  g_signal_connect_object (options, "notify::corner-radius",
-                           G_CALLBACK (gimp_rectangle_select_tool_round_corners_notify),
-                           object, 0);
-
-  gimp_rectangle_select_tool_update_option_defaults (rect_sel_tool, FALSE);
 }
 
 static void
@@ -272,73 +197,24 @@ gimp_rectangle_select_tool_control (GimpTool       *tool,
                                     GimpToolAction  action,
                                     GimpDisplay    *display)
 {
-  gimp_rectangle_tool_control (tool, action, display);
+  GimpRectangleSelectTool *rect_tool = GIMP_RECTANGLE_SELECT_TOOL (tool);
 
-  GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
-}
-
-static void
-gimp_rectangle_select_tool_draw (GimpDrawTool *draw_tool)
-{
-  GimpRectangleSelectTool        *rect_sel_tool;
-  GimpRectangleSelectToolPrivate *priv;
-  GimpCanvasGroup                *stroke_group = NULL;
-
-  rect_sel_tool = GIMP_RECTANGLE_SELECT_TOOL (draw_tool);
-  priv          = GIMP_RECTANGLE_SELECT_TOOL_GET_PRIVATE (rect_sel_tool);
-
-  if (priv->round_corners)
+  switch (action)
     {
-      GimpCanvasItem *item;
-      gint            x1, y1, x2, y2;
-      gdouble         radius;
-      gint            square_size;
-
-      g_object_get (rect_sel_tool,
-                    "x1", &x1,
-                    "y1", &y1,
-                    "x2", &x2,
-                    "y2", &y2,
-                    NULL);
+    case GIMP_TOOL_ACTION_PAUSE:
+    case GIMP_TOOL_ACTION_RESUME:
+      break;
 
-      radius = MIN (priv->corner_radius,
-                    MIN ((x2 - x1) / 2.0, (y2 - y1) / 2.0));
-
-      square_size = (int) (radius * 2);
-
-      stroke_group =
-        GIMP_CANVAS_GROUP (gimp_draw_tool_add_stroke_group (draw_tool));
-
-      item = gimp_draw_tool_add_arc (draw_tool, FALSE,
-                                     x1, y1,
-                                     square_size, square_size,
-                                     G_PI / 2.0, G_PI / 2.0);
-      gimp_canvas_group_add_item (stroke_group, item);
-      gimp_draw_tool_remove_item (draw_tool, item);
-
-      item = gimp_draw_tool_add_arc (draw_tool, FALSE,
-                                     x2 - square_size, y1,
-                                     square_size, square_size,
-                                     0.0, G_PI / 2.0);
-      gimp_canvas_group_add_item (stroke_group, item);
-      gimp_draw_tool_remove_item (draw_tool, item);
-
-      item = gimp_draw_tool_add_arc (draw_tool, FALSE,
-                                     x2 - square_size, y2 - square_size,
-                                     square_size, square_size,
-                                     G_PI * 1.5, G_PI / 2.0);
-      gimp_canvas_group_add_item (stroke_group, item);
-      gimp_draw_tool_remove_item (draw_tool, item);
-
-      item = gimp_draw_tool_add_arc (draw_tool, FALSE,
-                                     x1, y2 - square_size,
-                                     square_size, square_size,
-                                     G_PI, G_PI / 2.0);
-      gimp_canvas_group_add_item (stroke_group, item);
-      gimp_draw_tool_remove_item (draw_tool, item);
+    case GIMP_TOOL_ACTION_HALT:
+      gimp_rectangle_select_tool_halt (rect_tool);
+      break;
+
+    case GIMP_TOOL_ACTION_COMMIT:
+      gimp_rectangle_select_tool_commit (rect_tool);
+      break;
     }
 
-  gimp_rectangle_tool_draw (draw_tool, stroke_group);
+  GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
 }
 
 static void
@@ -349,17 +225,11 @@ gimp_rectangle_select_tool_button_press (GimpTool            *tool,
                                          GimpButtonPressType  press_type,
                                          GimpDisplay         *display)
 {
-  GimpRectangleTool              *rectangle;
-  GimpRectangleSelectTool        *rect_sel_tool;
-  GimpDisplayShell               *shell;
-  GimpRectangleSelectToolPrivate *priv;
+  GimpRectangleSelectTool        *rect_tool = GIMP_RECTANGLE_SELECT_TOOL (tool);
+  GimpRectangleSelectToolPrivate *private   = rect_tool->private;
+  GimpDisplayShell               *shell     = gimp_display_get_shell (display);
   GimpRectangleFunction           function;
 
-  rectangle     = GIMP_RECTANGLE_TOOL (tool);
-  rect_sel_tool = GIMP_RECTANGLE_SELECT_TOOL (tool);
-  shell         = gimp_display_get_shell (display);
-  priv          = GIMP_RECTANGLE_SELECT_TOOL_GET_PRIVATE (rect_sel_tool);
-
   if (tool->display && display != tool->display)
     gimp_tool_control (tool, GIMP_TOOL_ACTION_COMMIT, tool->display);
 
@@ -369,39 +239,114 @@ gimp_rectangle_select_tool_button_press (GimpTool            *tool,
       /* In some cases we want to finish the rectangle select tool
        * and hand over responsibility to the selection tool
        */
-      gimp_rectangle_tool_control (tool, GIMP_TOOL_ACTION_COMMIT, display);
-      gimp_rectangle_select_tool_update_option_defaults (rect_sel_tool,
-                                                         TRUE);
+      gimp_tool_control (tool, GIMP_TOOL_ACTION_COMMIT, display);
+      gimp_rectangle_select_tool_update_option_defaults (rect_tool, TRUE);
       return;
     }
 
-  gimp_tool_control_activate (tool->control);
+  if (! tool->display)
+    {
+      static const gchar *properties[] =
+      {
+        "highlight",
+        "guide",
+        "round-corners",
+        "corner-radius",
+        "x",
+        "y",
+        "width",
+        "height",
+        "fixed-rule-active",
+        "fixed-rule",
+        "desired-fixed-width",
+        "desired-fixed-height",
+        "desired-fixed-size-width",
+        "desired-fixed-size-height",
+        "aspect-numerator",
+        "aspect-denominator",
+        "fixed-center"
+      };
+
+      GimpDisplayShell           *shell = gimp_display_get_shell (display);
+      GimpRectangleSelectOptions *options;
+      GimpToolWidget             *widget;
+      gint                        i;
+
+      options = GIMP_RECTANGLE_SELECT_TOOL_GET_OPTIONS (rect_tool);
+
+      tool->display = display;
+
+      private->rectangle = widget = gimp_tool_rectangle_new (shell);
+
+      g_object_set (widget,
+                    "draw-ellipse", GIMP_RECTANGLE_SELECT_TOOL_GET_CLASS (rect_tool)->draw_ellipse,
+                    NULL);
+
+      gimp_draw_tool_set_widget (GIMP_DRAW_TOOL (tool), widget);
+
+      for (i = 0; i < G_N_ELEMENTS (properties); i++)
+        g_object_bind_property (G_OBJECT (options), properties[i],
+                                G_OBJECT (widget),  properties[i],
+                                G_BINDING_SYNC_CREATE |
+                                G_BINDING_BIDIRECTIONAL);
+
+      g_signal_connect (widget, "response",
+                        G_CALLBACK (gimp_rectangle_select_tool_rectangle_response),
+                        rect_tool);
+      g_signal_connect (widget, "change-complete",
+                        G_CALLBACK (gimp_rectangle_select_tool_rectangle_change_complete),
+                        rect_tool);
+
+      gimp_rectangle_options_connect (GIMP_RECTANGLE_OPTIONS (options),
+                                      gimp_display_get_image (shell->display),
+                                      G_CALLBACK (gimp_rectangle_select_tool_auto_shrink),
+                                      rect_tool);
+
+      gimp_rectangle_select_tool_update_option_defaults (rect_tool, FALSE);
+
+      gimp_tool_widget_hover (widget, coords, state, TRUE);
 
-  priv->saved_show_selection = gimp_display_shell_get_show_selection (shell);
+      /* HACK: force CREATING on a newly created rectangle; otherwise,
+       * the above binding of properties would cause the rectangle to
+       * start with the size from tool options.
+       */
+      gimp_tool_rectangle_set_function (GIMP_TOOL_RECTANGLE (widget),
+                                        GIMP_TOOL_RECTANGLE_CREATING);
+
+      gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), display);
+    }
+
+  private->saved_show_selection = gimp_display_shell_get_show_selection (shell);
 
   /* if the shift or ctrl keys are down, we don't want to adjust, we
-   * want to create a new rectangle, regardless of pointer loc */
+   * want to create a new rectangle, regardless of pointer loc
+   */
   if (state & (gimp_get_extend_selection_mask () |
                gimp_get_modify_selection_mask ()))
     {
-      gimp_rectangle_tool_set_function (rectangle,
-                                        GIMP_RECTANGLE_TOOL_CREATING);
+      gimp_tool_rectangle_set_function (GIMP_TOOL_RECTANGLE (private->rectangle),
+                                        GIMP_TOOL_RECTANGLE_CREATING);
     }
 
-  gimp_rectangle_tool_button_press (tool, coords, time, state, display);
+  if (gimp_tool_widget_button_press (private->rectangle, coords, time, state,
+                                     press_type))
+    {
+      private->grab_widget = private->rectangle;
+    }
 
-  priv->press_x = coords->x;
-  priv->press_y = coords->y;
+  private->press_x = coords->x;
+  private->press_y = coords->y;
 
   /* if we have an existing rectangle in the current display, then
    * we have already "executed", and need to undo at this point,
    * unless the user has done something in the meantime
    */
-  function = gimp_rectangle_tool_get_function (rectangle);
+  function =
+    gimp_tool_rectangle_get_function (GIMP_TOOL_RECTANGLE (private->rectangle));
 
-  if (function == GIMP_RECTANGLE_TOOL_CREATING)
+  if (function == GIMP_TOOL_RECTANGLE_CREATING)
     {
-      priv->use_saved_op = FALSE;
+      private->use_saved_op = FALSE;
     }
   else
     {
@@ -413,7 +358,7 @@ gimp_rectangle_select_tool_button_press (GimpTool            *tool,
 
       undo = gimp_undo_stack_peek (undo_stack);
 
-      if (undo && priv->undo == undo)
+      if (undo && private->undo == undo)
         {
           /* prevent this change from halting the tool */
           gimp_tool_control_push_preserve (tool->control, TRUE);
@@ -423,18 +368,21 @@ gimp_rectangle_select_tool_button_press (GimpTool            *tool,
           gimp_tool_control_pop_preserve (tool->control);
 
           /* we will need to redo if the user cancels or executes */
-          priv->redo = gimp_undo_stack_peek (redo_stack);
+          private->redo = gimp_undo_stack_peek (redo_stack);
         }
 
       /* if the operation is "Replace", turn off the marching ants,
-         because they are confusing */
-      operation = gimp_rectangle_select_tool_get_operation (rect_sel_tool);
+       * because they are confusing
+       */
+      operation = gimp_rectangle_select_tool_get_operation (rect_tool);
 
       if (operation == GIMP_CHANNEL_OP_REPLACE)
         gimp_display_shell_set_show_selection (shell, FALSE);
     }
 
-  priv->undo = NULL;
+  private->undo = NULL;
+
+  gimp_tool_control_activate (tool->control);
 }
 
 static void
@@ -445,13 +393,10 @@ gimp_rectangle_select_tool_button_release (GimpTool              *tool,
                                            GimpButtonReleaseType  release_type,
                                            GimpDisplay           *display)
 {
-  GimpRectangleSelectTool        *rect_sel_tool;
-  GimpRectangleSelectToolPrivate *priv;
+  GimpRectangleSelectTool        *rect_tool = GIMP_RECTANGLE_SELECT_TOOL (tool);
+  GimpRectangleSelectToolPrivate *priv      = rect_tool->private;
   GimpImage                      *image;
 
-  rect_sel_tool = GIMP_RECTANGLE_SELECT_TOOL (tool);
-  priv          = GIMP_RECTANGLE_SELECT_TOOL_GET_PRIVATE (rect_sel_tool);
-
   image = gimp_display_get_image (tool->display);
 
   gimp_tool_control_halt (tool->control);
@@ -481,8 +426,12 @@ gimp_rectangle_select_tool_button_release (GimpTool              *tool,
         }
     }
 
-  gimp_rectangle_tool_button_release (tool, coords, time, state, release_type,
-                                      display);
+  if (priv->grab_widget)
+    {
+      gimp_tool_widget_button_release (priv->grab_widget,
+                                       coords, time, state, release_type);
+      priv->grab_widget = NULL;
+    }
 
   if (release_type == GIMP_BUTTON_RELEASE_CANCEL)
     {
@@ -503,16 +452,19 @@ gimp_rectangle_select_tool_button_release (GimpTool              *tool,
 }
 
 static void
-gimp_rectangle_select_tool_active_modifier_key (GimpTool        *tool,
-                                                GdkModifierType  key,
-                                                gboolean         press,
-                                                GdkModifierType  state,
-                                                GimpDisplay     *display)
+gimp_rectangle_select_tool_motion (GimpTool         *tool,
+                                   const GimpCoords *coords,
+                                   guint32           time,
+                                   GdkModifierType   state,
+                                   GimpDisplay      *display)
 {
-  GIMP_TOOL_CLASS (parent_class)->active_modifier_key (tool, key, press, state,
-                                                       display);
+  GimpRectangleSelectTool        *rect_tool = GIMP_RECTANGLE_SELECT_TOOL (tool);
+  GimpRectangleSelectToolPrivate *priv      = rect_tool->private;
 
-  gimp_rectangle_tool_active_modifier_key (tool, key, press, state, display);
+  if (priv->grab_widget)
+    {
+      gimp_tool_widget_motion (priv->grab_widget, coords, time, state);
+    }
 }
 
 static gboolean
@@ -520,8 +472,16 @@ gimp_rectangle_select_tool_key_press (GimpTool    *tool,
                                       GdkEventKey *kevent,
                                       GimpDisplay *display)
 {
-  return (gimp_rectangle_tool_key_press (tool, kevent, display) ||
-          gimp_edit_selection_tool_key_press (tool, kevent, display));
+  GimpRectangleSelectTool        *rect_tool = GIMP_RECTANGLE_SELECT_TOOL (tool);
+  GimpRectangleSelectToolPrivate *priv      = rect_tool->private;
+
+  if (priv->rectangle && display == tool->display)
+    {
+      if (gimp_tool_widget_key_press (priv->rectangle, kevent))
+        return TRUE;
+    }
+
+  return gimp_edit_selection_tool_key_press (tool, kevent, display);
 }
 
 static void
@@ -531,7 +491,13 @@ gimp_rectangle_select_tool_oper_update (GimpTool         *tool,
                                         gboolean          proximity,
                                         GimpDisplay      *display)
 {
-  gimp_rectangle_tool_oper_update (tool, coords, state, proximity, display);
+  GimpRectangleSelectTool        *rect_tool = GIMP_RECTANGLE_SELECT_TOOL (tool);
+  GimpRectangleSelectToolPrivate *priv      = rect_tool->private;
+
+  if (priv->rectangle && display == tool->display)
+    {
+      gimp_tool_widget_hover (priv->rectangle, coords, state, proximity);
+    }
 
   GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity,
                                                display);
@@ -543,7 +509,16 @@ gimp_rectangle_select_tool_cursor_update (GimpTool         *tool,
                                           GdkModifierType   state,
                                           GimpDisplay      *display)
 {
-  gimp_rectangle_tool_cursor_update (tool, coords, state, display);
+  GimpRectangleSelectTool        *rect_tool = GIMP_RECTANGLE_SELECT_TOOL (tool);
+  GimpRectangleSelectToolPrivate *private   = rect_tool->private;
+  GimpCursorType                  cursor    = GIMP_CURSOR_CROSSHAIR_SMALL;
+  GimpCursorModifier              modifier  = GIMP_CURSOR_MODIFIER_NONE;
+
+  if (private->rectangle && display == tool->display)
+    {
+      gimp_tool_widget_get_cursor (private->rectangle, coords, state,
+                                   &cursor, NULL, &modifier);
+    }
 
   /* override the previous if shift or ctrl are down */
   if (state & (gimp_get_extend_selection_mask () |
@@ -556,24 +531,17 @@ gimp_rectangle_select_tool_cursor_update (GimpTool         *tool,
   GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
 }
 
-
 static gboolean
-gimp_rectangle_select_tool_select (GimpRectangleTool *rectangle,
-                                   gint               x,
-                                   gint               y,
-                                   gint               w,
-                                   gint               h)
+gimp_rectangle_select_tool_select (GimpRectangleSelectTool *rect_tool,
+                                   gint                     x,
+                                   gint                     y,
+                                   gint                     w,
+                                   gint                     h)
 {
-  GimpTool                *tool;
-  GimpRectangleSelectTool *rect_sel_tool;
-  GimpImage               *image;
-  gboolean                 rectangle_exists;
-  GimpChannelOps           operation;
-
-  tool          = GIMP_TOOL (rectangle);
-  rect_sel_tool = GIMP_RECTANGLE_SELECT_TOOL (rectangle);
-
-  image         = gimp_display_get_image (tool->display);
+  GimpTool       *tool  = GIMP_TOOL (rect_tool);
+  GimpImage      *image = gimp_display_get_image (tool->display);
+  gboolean        rectangle_exists;
+  GimpChannelOps  operation;
 
   gimp_tool_pop_status (tool, tool->display);
 
@@ -584,41 +552,41 @@ gimp_rectangle_select_tool_select (GimpRectangleTool *rectangle,
                       w > 0                              &&
                       h > 0);
 
-  operation = gimp_rectangle_select_tool_get_operation (rect_sel_tool);
+  operation = gimp_rectangle_select_tool_get_operation (rect_tool);
 
   /* if rectangle exists, turn it into a selection */
   if (rectangle_exists)
-    GIMP_RECTANGLE_SELECT_TOOL_GET_CLASS (rect_sel_tool)->select (rect_sel_tool,
-                                                                  operation,
-                                                                  x, y, w, h);
+    GIMP_RECTANGLE_SELECT_TOOL_GET_CLASS (rect_tool)->select (rect_tool,
+                                                              operation,
+                                                              x, y, w, h);
 
   return rectangle_exists;
 }
 
 static void
-gimp_rectangle_select_tool_real_select (GimpRectangleSelectTool *rect_sel_tool,
+gimp_rectangle_select_tool_real_select (GimpRectangleSelectTool *rect_tool,
                                         GimpChannelOps           operation,
                                         gint                     x,
                                         gint                     y,
                                         gint                     w,
                                         gint                     h)
 {
-  GimpTool                   *tool    = GIMP_TOOL (rect_sel_tool);
+  GimpTool                   *tool    = GIMP_TOOL (rect_tool);
   GimpSelectionOptions       *options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
-  GimpRectangleSelectOptions *rect_select_options;
+  GimpRectangleSelectOptions *rect_options;
   GimpChannel                *channel;
 
-  rect_select_options = GIMP_RECTANGLE_SELECT_TOOL_GET_OPTIONS (tool);
+  rect_options = GIMP_RECTANGLE_SELECT_TOOL_GET_OPTIONS (tool);
 
   channel = gimp_image_get_mask (gimp_display_get_image (tool->display));
 
-  if (rect_select_options->round_corners)
+  if (rect_options->round_corners)
     {
       /* To prevent elliptification of the rectangle,
        * we must cap the corner radius.
        */
       gdouble max    = MIN (w / 2.0, h / 2.0);
-      gdouble radius = MIN (rect_select_options->corner_radius, max);
+      gdouble radius = MIN (rect_options->corner_radius, max);
 
       gimp_channel_select_round_rect (channel,
                                       x, y, w, h,
@@ -642,72 +610,85 @@ gimp_rectangle_select_tool_real_select (GimpRectangleSelectTool *rect_sel_tool,
     }
 }
 
-static GimpChannelOps
-gimp_rectangle_select_tool_get_operation (GimpRectangleSelectTool *rect_sel_tool)
+static void
+gimp_rectangle_select_tool_rectangle_response (GimpToolWidget          *widget,
+                                               gint                     response_id,
+                                               GimpRectangleSelectTool *rect_tool)
 {
-  GimpRectangleSelectToolPrivate *priv;
-  GimpSelectionOptions           *options;
+  GimpTool *tool = GIMP_TOOL (rect_tool);
 
-  priv    = GIMP_RECTANGLE_SELECT_TOOL_GET_PRIVATE (rect_sel_tool);
-  options = GIMP_SELECTION_TOOL_GET_OPTIONS (rect_sel_tool);
+  switch (response_id)
+    {
+    case GIMP_TOOL_WIDGET_RESPONSE_CONFIRM:
+      gimp_tool_control (tool, GIMP_TOOL_ACTION_COMMIT, tool->display);
+      break;
 
-  if (priv->use_saved_op)
-    return priv->operation;
-  else
-    return options->operation;
+    case GIMP_TOOL_WIDGET_RESPONSE_CANCEL:
+      gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, tool->display);
+      break;
+    }
 }
 
-/**
- * gimp_rectangle_select_tool_update_option_defaults:
- * @crop_tool:
- * @ignore_pending: %TRUE to ignore any pending crop rectangle.
- *
- * Sets the default Fixed: Aspect ratio and Fixed: Size option
- * properties.
- */
 static void
-gimp_rectangle_select_tool_update_option_defaults (GimpRectangleSelectTool *rect_sel_tool,
-                                                   gboolean                 ignore_pending)
+gimp_rectangle_select_tool_rectangle_change_complete (GimpToolWidget          *widget,
+                                                      GimpRectangleSelectTool *rect_tool)
 {
-  GimpTool             *tool;
-  GimpRectangleTool    *rectangle_tool;
-  GimpRectangleOptions *rectangle_options;
+  GimpTool                       *tool = GIMP_TOOL (rect_tool);
+  GimpRectangleSelectToolPrivate *priv = rect_tool->private;
 
-  tool              = GIMP_TOOL (rect_sel_tool);
-  rectangle_tool    = GIMP_RECTANGLE_TOOL (tool);
-  rectangle_options = GIMP_RECTANGLE_TOOL_GET_OPTIONS (rectangle_tool);
+  /* prevent change in selection from halting the tool */
+  gimp_tool_control_push_preserve (tool->control, TRUE);
 
-  if (tool->display != NULL && !ignore_pending)
+  if (tool->display && ! gimp_tool_control_is_active (tool->control))
     {
-      /* There is a pending rectangle and we should not ignore it, so
-       * set default Fixed: Size to the same as the current pending
-       * rectangle width/height.
+      GimpImage     *image      = gimp_display_get_image (tool->display);
+      GimpUndoStack *undo_stack = gimp_image_get_undo_stack (image);
+      GimpUndo      *undo       = gimp_undo_stack_peek (undo_stack);
+      gdouble        x1, y1, x2, y2;
+
+      /* if we got here via button release, we have already undone the
+       * previous operation.  But if we got here by some other means,
+       * we need to undo it now.
        */
+      if (undo && priv->undo == undo)
+        {
+          gimp_image_undo (image);
+          priv->undo = NULL;
+        }
 
-      gimp_rectangle_tool_pending_size_set (rectangle_tool,
-                                            G_OBJECT (rectangle_options),
-                                            "default-aspect-numerator",
-                                            "default-aspect-denominator");
+      gimp_tool_rectangle_get_public_rect (GIMP_TOOL_RECTANGLE (widget),
+                                           &x1, &y1, &x2, &y2);
 
-      g_object_set (G_OBJECT (rectangle_options),
-                    "use-string-current", TRUE,
-                    NULL);
-    }
-  else
-    {
-      g_object_set (G_OBJECT (rectangle_options),
-                    "default-aspect-numerator",   1.0,
-                    "default-aspect-denominator", 1.0,
-                    NULL);
+      if (gimp_rectangle_select_tool_select (rect_tool,
+                                             x1, y1, x2 - x1, y2 - y1))
+        {
+          /* save the undo that we got when executing, but only if
+           * we actually selected something
+           */
+          priv->undo = gimp_undo_stack_peek (undo_stack);
+          priv->redo = NULL;
+        }
 
-      g_object_set (G_OBJECT (rectangle_options),
-                    "use-string-current", FALSE,
-                    NULL);
+      if (! priv->use_saved_op)
+        {
+          GimpSelectionOptions *options;
+
+          options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
+
+          /* remember the operation now in case we modify the rectangle */
+          priv->operation    = options->operation;
+          priv->use_saved_op = TRUE;
+        }
+
+      gimp_image_flush (image);
     }
+
+  gimp_tool_control_pop_preserve (tool->control);
+
+  gimp_rectangle_select_tool_update_option_defaults (rect_tool, FALSE);
 }
 
-/*
- * This function is called if the user clicks and releases the left
+/* This function is called if the user clicks and releases the left
  * button without moving it.  There are the things we might want
  * to do here:
  * 1) If there is an existing rectangle and we are inside it, we
@@ -721,111 +702,110 @@ gimp_rectangle_select_tool_update_option_defaults (GimpRectangleSelectTool *rect
  * 5) If there is no rectangle and we are outside the selection,
  *    we clear the selection.
  */
-static gboolean
-gimp_rectangle_select_tool_execute (GimpRectangleTool *rectangle,
-                                    gint               x,
-                                    gint               y,
-                                    gint               w,
-                                    gint               h)
+static void
+gimp_rectangle_select_tool_commit (GimpRectangleSelectTool *rect_tool)
 {
-  GimpTool                       *tool = GIMP_TOOL (rectangle);
-  GimpRectangleSelectTool        *rect_sel_tool;
-  GimpRectangleSelectToolPrivate *priv;
-
-  rect_sel_tool = GIMP_RECTANGLE_SELECT_TOOL (rectangle);
-  priv          = GIMP_RECTANGLE_SELECT_TOOL_GET_PRIVATE (rect_sel_tool);
+  GimpTool                       *tool = GIMP_TOOL (rect_tool);
+  GimpRectangleSelectToolPrivate *priv = rect_tool->private;
 
-  if (w == 0 && h == 0 && tool->display != NULL)
+  if (priv->rectangle)
     {
-      GimpImage   *image     = gimp_display_get_image (tool->display);
-      GimpChannel *selection = gimp_image_get_mask (image);
-      gint         pressx;
-      gint         pressy;
-
-      if (gimp_image_get_floating_selection (image))
-        {
-          floating_sel_anchor (gimp_image_get_floating_selection (image));
-          gimp_image_flush (image);
-          return TRUE;
-        }
+      gdouble x1, y1, x2, y2;
+      gint    w, h;
 
-      pressx = ROUND (priv->press_x);
-      pressy = ROUND (priv->press_y);
+      gimp_tool_rectangle_get_public_rect (GIMP_TOOL_RECTANGLE (priv->rectangle),
+                                           &x1, &y1, &x2, &y2);
+      w = x2 - x1;
+      h = y2 - y1;
 
-      /*  if the click was inside the marching ants  */
-      if (gimp_pickable_get_opacity_at (GIMP_PICKABLE (selection),
-                                        pressx, pressy) > 0.5)
+      if (w == 0 && h == 0)
         {
-          gint x, y, w, h;
+          GimpImage   *image     = gimp_display_get_image (tool->display);
+          GimpChannel *selection = gimp_image_get_mask (image);
+          gint         press_x;
+          gint         press_y;
 
-          if (gimp_item_bounds (GIMP_ITEM (selection), &x, &y, &w, &h))
+          if (gimp_image_get_floating_selection (image))
             {
-              g_object_set (rectangle,
-                            "x1", x,
-                            "y1", y,
-                            "x2", x + w,
-                            "y2", y + h,
-                            NULL);
-            }
-
-          gimp_rectangle_tool_set_function (rectangle,
-                                            GIMP_RECTANGLE_TOOL_MOVING);
-          gimp_rectangle_select_tool_update_option_defaults (rect_sel_tool,
-                                                             FALSE);
+              floating_sel_anchor (gimp_image_get_floating_selection (image));
+              gimp_image_flush (image);
 
-          return FALSE;
-        }
-      else
-        {
-          GimpTool       *tool = GIMP_TOOL (rectangle);
-          GimpChannelOps  operation;
+              return;
+            }
 
-          /* prevent this change from halting the tool */
-          gimp_tool_control_push_preserve (tool->control, TRUE);
+          press_x = ROUND (priv->press_x);
+          press_y = ROUND (priv->press_y);
 
-          /* We can conceptually think of a click outside of the
-           * selection as adding a 0px selection. Behave intuitivly
-           * for the current selection mode
-           */
-          operation = gimp_rectangle_select_tool_get_operation (rect_sel_tool);
-          switch (operation)
+          /*  if the click was inside the marching ants  */
+          if (gimp_pickable_get_opacity_at (GIMP_PICKABLE (selection),
+                                            press_x, press_y) > 0.5)
             {
-            case GIMP_CHANNEL_OP_REPLACE:
-            case GIMP_CHANNEL_OP_INTERSECT:
-              gimp_channel_clear (selection, NULL, TRUE);
-              gimp_image_flush (image);
-              break;
-
-            case GIMP_CHANNEL_OP_ADD:
-            case GIMP_CHANNEL_OP_SUBTRACT:
-            default:
-              /* Do nothing */
-              break;
+              gint x, y, w, h;
+
+              if (gimp_item_bounds (GIMP_ITEM (selection), &x, &y, &w, &h))
+                {
+                  g_object_set (priv->rectangle,
+                                "x1", (gdouble) x,
+                                "y1", (gdouble) y,
+                                "x2", (gdouble) (x + w),
+                                "y2", (gdouble) (y + h),
+                                NULL);
+                }
+
+              gimp_rectangle_select_tool_update_option_defaults (rect_tool,
+                                                                 FALSE);
+              return;
+            }
+          else
+            {
+              GimpChannelOps  operation;
+
+              /* prevent this change from halting the tool */
+              gimp_tool_control_push_preserve (tool->control, TRUE);
+
+              /* We can conceptually think of a click outside of the
+               * selection as adding a 0px selection. Behave intuitivly
+               * for the current selection mode
+               */
+              operation = gimp_rectangle_select_tool_get_operation (rect_tool);
+
+              switch (operation)
+                {
+                case GIMP_CHANNEL_OP_REPLACE:
+                case GIMP_CHANNEL_OP_INTERSECT:
+                  gimp_channel_clear (selection, NULL, TRUE);
+                  gimp_image_flush (image);
+                  break;
+
+                case GIMP_CHANNEL_OP_ADD:
+                case GIMP_CHANNEL_OP_SUBTRACT:
+                default:
+                  /* Do nothing */
+                  break;
+                }
+
+              gimp_tool_control_pop_preserve (tool->control);
             }
-
-          gimp_tool_control_pop_preserve (tool->control);
         }
-    }
 
-  gimp_rectangle_select_tool_update_option_defaults (rect_sel_tool, FALSE);
+      gimp_rectangle_select_tool_update_option_defaults (rect_tool, FALSE);
+    }
 
   /* Reset the automatic undo/redo mechanism */
   priv->undo = NULL;
   priv->redo = NULL;
 
-  return TRUE;
+  gimp_rectangle_select_tool_halt (rect_tool);
 }
 
 static void
-gimp_rectangle_select_tool_cancel (GimpRectangleTool *rectangle)
+gimp_rectangle_select_tool_halt (GimpRectangleSelectTool *rect_tool)
 {
-  GimpTool                       *tool;
-  GimpRectangleSelectTool        *rect_sel_tool;
-  GimpRectangleSelectToolPrivate *priv;
+  GimpTool                       *tool = GIMP_TOOL (rect_tool);
+  GimpRectangleSelectToolPrivate *priv = rect_tool->private;
+  GimpRectangleSelectOptions     *options;
 
-  tool          = GIMP_TOOL (rectangle);
-  rect_sel_tool = GIMP_RECTANGLE_SELECT_TOOL (rectangle);
-  priv          = GIMP_RECTANGLE_SELECT_TOOL_GET_PRIVATE (rect_sel_tool);
+  options = GIMP_RECTANGLE_SELECT_TOOL_GET_OPTIONS (rect_tool);
 
   if (tool->display)
     {
@@ -847,99 +827,99 @@ gimp_rectangle_select_tool_cancel (GimpRectangleTool *rectangle)
 
           gimp_tool_control_pop_preserve (tool->control);
         }
+
+      gimp_rectangle_options_disconnect (GIMP_RECTANGLE_OPTIONS (options),
+                                         G_CALLBACK (gimp_rectangle_select_tool_auto_shrink),
+                                         rect_tool);
     }
 
-  gimp_rectangle_select_tool_update_option_defaults (rect_sel_tool, TRUE);
+  gimp_rectangle_select_tool_update_option_defaults (rect_tool, TRUE);
 
   priv->undo = NULL;
   priv->redo = NULL;
-}
-
-static gboolean
-gimp_rectangle_select_tool_rectangle_change_complete (GimpRectangleTool *rectangle)
-{
-  GimpTool                       *tool;
-  GimpRectangleSelectTool        *rect_sel_tool;
-  GimpRectangleSelectToolPrivate *priv;
 
-  tool          = GIMP_TOOL (rectangle);
-  rect_sel_tool = GIMP_RECTANGLE_SELECT_TOOL (tool);
-  priv          = GIMP_RECTANGLE_SELECT_TOOL_GET_PRIVATE (rect_sel_tool);
+  if (gimp_draw_tool_is_active (GIMP_DRAW_TOOL (tool)))
+    gimp_draw_tool_stop (GIMP_DRAW_TOOL (tool));
 
-  /* prevent change in selection from halting the tool */
-  gimp_tool_control_push_preserve (tool->control, TRUE);
+  g_clear_object (&priv->rectangle);
 
-  if (tool->display && ! gimp_tool_control_is_active (tool->control))
-    {
-      GimpImage     *image      = gimp_display_get_image (tool->display);
-      GimpUndoStack *undo_stack = gimp_image_get_undo_stack (image);
-      GimpUndo      *undo       = gimp_undo_stack_peek (undo_stack);
-      gint           x1, y1, x2, y2;
+  tool->display = NULL;
+}
 
-      /* if we got here via button release, we have already undone the
-       * previous operation.  But if we got here by some other means,
-       * we need to undo it now.
-       */
-      if (undo && priv->undo == undo)
-        {
-          gimp_image_undo (image);
-          priv->undo = NULL;
-        }
+static GimpChannelOps
+gimp_rectangle_select_tool_get_operation (GimpRectangleSelectTool *rect_tool)
+{
+  GimpRectangleSelectToolPrivate *priv = rect_tool->private;
+  GimpSelectionOptions           *options;
 
-      g_object_get (rectangle,
-                    "x1", &x1,
-                    "y1", &y1,
-                    "x2", &x2,
-                    "y2", &y2,
-                    NULL);
+  options = GIMP_SELECTION_TOOL_GET_OPTIONS (rect_tool);
 
-      if (gimp_rectangle_select_tool_select (rectangle, x1, y1, x2 - x1, y2 - y1))
-        {
-          /* save the undo that we got when executing, but only if
-           * we actually selected something
-           */
-          priv->undo = gimp_undo_stack_peek (undo_stack);
-          priv->redo = NULL;
-        }
+  if (priv->use_saved_op)
+    return priv->operation;
+  else
+    return options->operation;
+}
 
-      if (! priv->use_saved_op)
-        {
-          GimpSelectionOptions *options;
+/**
+ * gimp_rectangle_select_tool_update_option_defaults:
+ * @crop_tool:
+ * @ignore_pending: %TRUE to ignore any pending crop rectangle.
+ *
+ * Sets the default Fixed: Aspect ratio and Fixed: Size option
+ * properties.
+ */
+static void
+gimp_rectangle_select_tool_update_option_defaults (GimpRectangleSelectTool *rect_tool,
+                                                   gboolean                 ignore_pending)
+{
+  GimpRectangleSelectToolPrivate *priv = rect_tool->private;
+  GimpTool                       *tool = GIMP_TOOL (rect_tool);
+  GimpRectangleOptions           *rect_options;
 
-          options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
+  rect_options = GIMP_RECTANGLE_OPTIONS (gimp_tool_get_options (tool));
 
-          /* remember the operation now in case we modify the rectangle */
-          priv->operation    = options->operation;
-          priv->use_saved_op = TRUE;
-        }
+  if (! priv->rectangle)
+    return;
 
-      gimp_image_flush (image);
-    }
+  if (tool->display != NULL && ! ignore_pending)
+    {
+      /* There is a pending rectangle and we should not ignore it, so
+       * set default Fixed: Size to the same as the current pending
+       * rectangle width/height.
+       */
 
-  gimp_tool_control_pop_preserve (tool->control);
+      gimp_tool_rectangle_pending_size_set (GIMP_TOOL_RECTANGLE (priv->rectangle),
+                                            G_OBJECT (rect_options),
+                                            "default-aspect-numerator",
+                                            "default-aspect-denominator");
 
-  gimp_rectangle_select_tool_update_option_defaults (rect_sel_tool, FALSE);
+      g_object_set (G_OBJECT (rect_options),
+                    "use-string-current", TRUE,
+                    NULL);
+    }
+  else
+    {
+      g_object_set (G_OBJECT (rect_options),
+                    "default-aspect-numerator",   1.0,
+                    "default-aspect-denominator", 1.0,
+                    NULL);
 
-  return TRUE;
+      g_object_set (G_OBJECT (rect_options),
+                    "use-string-current", FALSE,
+                    NULL);
+    }
 }
 
 static void
-gimp_rectangle_select_tool_round_corners_notify (GimpRectangleSelectOptions *options,
-                                                 GParamSpec                 *pspec,
-                                                 GimpRectangleSelectTool    *rect_sel_tool)
+gimp_rectangle_select_tool_auto_shrink (GimpRectangleSelectTool *rect_tool)
 {
-  GimpDrawTool                   *draw_tool = GIMP_DRAW_TOOL (rect_sel_tool);
-  GimpRectangleTool              *rect_tool = GIMP_RECTANGLE_TOOL (rect_sel_tool);
-  GimpRectangleSelectToolPrivate *priv;
-
-  priv = GIMP_RECTANGLE_SELECT_TOOL_GET_PRIVATE (rect_sel_tool);
-
-  gimp_draw_tool_pause (draw_tool);
-
-  priv->round_corners = options->round_corners;
-  priv->corner_radius = options->corner_radius;
+  GimpRectangleSelectToolPrivate *private = rect_tool->private;
+  gboolean                        shrink_merged;
 
-  gimp_rectangle_select_tool_rectangle_change_complete (rect_tool);
+  g_object_get (gimp_tool_get_options (GIMP_TOOL (rect_tool)),
+                "shrink-merged", &shrink_merged,
+                NULL);
 
-  gimp_draw_tool_resume (draw_tool);
+  gimp_tool_rectangle_auto_shrink (GIMP_TOOL_RECTANGLE (private->rectangle),
+                                   shrink_merged);
 }
diff --git a/app/tools/gimprectangleselecttool.h b/app/tools/gimprectangleselecttool.h
index 46a2c52..7d41bf2 100644
--- a/app/tools/gimprectangleselecttool.h
+++ b/app/tools/gimprectangleselecttool.h
@@ -32,14 +32,15 @@
 #define GIMP_RECTANGLE_SELECT_TOOL_GET_OPTIONS(t)  (GIMP_RECTANGLE_SELECT_OPTIONS (gimp_tool_get_options 
(GIMP_TOOL (t))))
 
 
-typedef struct _GimpRectangleSelectTool      GimpRectangleSelectTool;
-typedef struct _GimpRectangleSelectToolClass GimpRectangleSelectToolClass;
+typedef struct _GimpRectangleSelectTool        GimpRectangleSelectTool;
+typedef struct _GimpRectangleSelectToolPrivate GimpRectangleSelectToolPrivate;
+typedef struct _GimpRectangleSelectToolClass   GimpRectangleSelectToolClass;
 
 struct _GimpRectangleSelectTool
 {
-  GimpSelectionTool  parent_instance;
+  GimpSelectionTool               parent_instance;
 
-  gpointer           priv;
+  GimpRectangleSelectToolPrivate *private;
 };
 
 struct _GimpRectangleSelectToolClass
@@ -52,6 +53,8 @@ struct _GimpRectangleSelectToolClass
                    gint                     y,
                    gint                     w,
                    gint                     h);
+
+  gboolean draw_ellipse;
 };
 
 


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