[gimp] app: improve empty-selection check in GimpSelectionTool



commit 57eaf91fbc95ea6aaa7206a882eb6d845279ae15
Author: Ell <ell_se yahoo com>
Date:   Mon Feb 3 12:14:08 2020 +0200

    app: improve empty-selection check in GimpSelectionTool
    
    Add a new GimpSelectionTool::have_selection() virtual function,
    which determines if the image has a selection (default
    implementation), or if the tool will create one upon committing
    (implemented by subclasses).  Use this function in
    gimp_selection_tool_oper_update() to determine the tool function;
    in particular, don't use SELECTION_MOVE and SELECTION_MOVE_COPY
    when there's no selection.
    
    Override have_selection() in GimpFreeSelectTool, and return TRUE if
    we have a polygon with three or more vertices, which will create a
    selection upon committing.

 app/tools/gimpfreeselecttool.c | 27 ++++++++++++
 app/tools/gimpselectiontool.c  | 99 ++++++++++++++++++++++++++----------------
 app/tools/gimpselectiontool.h  |  4 ++
 3 files changed, 93 insertions(+), 37 deletions(-)
---
diff --git a/app/tools/gimpfreeselecttool.c b/app/tools/gimpfreeselecttool.c
index 71baa00b0c..c97096fc01 100644
--- a/app/tools/gimpfreeselecttool.c
+++ b/app/tools/gimpfreeselecttool.c
@@ -73,6 +73,9 @@ static void       gimp_free_select_tool_options_notify  (GimpTool              *
                                                          GimpToolOptions       *options,
                                                          const GParamSpec      *pspec);
 
+static gboolean   gimp_free_select_tool_have_selection  (GimpSelectionTool     *sel_tool,
+                                                         GimpDisplay           *display);
+
 static void       gimp_free_select_tool_change_complete (GimpPolygonSelectTool *poly_sel,
                                                          GimpDisplay           *display);
 
@@ -112,6 +115,7 @@ static void
 gimp_free_select_tool_class_init (GimpFreeSelectToolClass *klass)
 {
   GimpToolClass              *tool_class     = GIMP_TOOL_CLASS (klass);
+  GimpSelectionToolClass     *sel_class      = GIMP_SELECTION_TOOL_CLASS (klass);
   GimpPolygonSelectToolClass *poly_sel_class = GIMP_POLYGON_SELECT_TOOL_CLASS (klass);
 
   tool_class->control             = gimp_free_select_tool_control;
@@ -119,6 +123,8 @@ gimp_free_select_tool_class_init (GimpFreeSelectToolClass *klass)
   tool_class->button_release      = gimp_free_select_tool_button_release;
   tool_class->options_notify      = gimp_free_select_tool_options_notify;
 
+  sel_class->have_selection       = gimp_free_select_tool_have_selection;
+
   poly_sel_class->change_complete = gimp_free_select_tool_change_complete;
 }
 
@@ -248,6 +254,27 @@ gimp_free_select_tool_options_notify (GimpTool         *tool,
   GIMP_TOOL_CLASS (parent_class)->options_notify (tool, options, pspec);
 }
 
+static gboolean
+gimp_free_select_tool_have_selection (GimpSelectionTool *sel_tool,
+                                      GimpDisplay       *display)
+{
+  GimpPolygonSelectTool *poly_sel = GIMP_POLYGON_SELECT_TOOL (sel_tool);
+  GimpTool              *tool     = GIMP_TOOL (sel_tool);
+
+  if (display == tool->display)
+    {
+      gint n_points;
+
+      gimp_polygon_select_tool_get_points (poly_sel, NULL, &n_points);
+
+      if (n_points > 2)
+        return TRUE;
+    }
+
+  return GIMP_SELECTION_TOOL_CLASS (parent_class)->have_selection (sel_tool,
+                                                                   display);
+}
+
 static void
 gimp_free_select_tool_change_complete (GimpPolygonSelectTool *poly_sel,
                                        GimpDisplay           *display)
diff --git a/app/tools/gimpselectiontool.c b/app/tools/gimpselectiontool.c
index ba94752f70..3029a38ac1 100644
--- a/app/tools/gimpselectiontool.c
+++ b/app/tools/gimpselectiontool.c
@@ -46,34 +46,40 @@
 #include "gimp-intl.h"
 
 
-static void       gimp_selection_tool_control       (GimpTool           *tool,
-                                                     GimpToolAction      action,
-                                                     GimpDisplay        *display);
-static void       gimp_selection_tool_modifier_key  (GimpTool           *tool,
-                                                     GdkModifierType     key,
-                                                     gboolean            press,
-                                                     GdkModifierType     state,
-                                                     GimpDisplay        *display);
-static void       gimp_selection_tool_oper_update   (GimpTool           *tool,
-                                                     const GimpCoords   *coords,
-                                                     GdkModifierType     state,
-                                                     gboolean            proximity,
-                                                     GimpDisplay        *display);
-static void       gimp_selection_tool_cursor_update (GimpTool           *tool,
-                                                     const GimpCoords   *coords,
-                                                     GdkModifierType     state,
-                                                     GimpDisplay        *display);
-
-static void       gimp_selection_tool_commit        (GimpSelectionTool  *sel_tool);
-static void       gimp_selection_tool_halt          (GimpSelectionTool  *sel_tool,
-                                                     GimpDisplay        *display);
-
-static gboolean   gimp_selection_tool_check         (GimpSelectionTool  *sel_tool,
-                                                     GimpDisplay        *display,
-                                                     GError            **error);
-
-static void       gimp_selection_tool_set_undo_ptr  (GimpUndo          **undo_ptr,
-                                                     GimpUndo           *undo);
+static void       gimp_selection_tool_control             (GimpTool           *tool,
+                                                           GimpToolAction      action,
+                                                           GimpDisplay        *display);
+static void       gimp_selection_tool_modifier_key        (GimpTool           *tool,
+                                                           GdkModifierType     key,
+                                                           gboolean            press,
+                                                           GdkModifierType     state,
+                                                           GimpDisplay        *display);
+static void       gimp_selection_tool_oper_update         (GimpTool           *tool,
+                                                           const GimpCoords   *coords,
+                                                           GdkModifierType     state,
+                                                           gboolean            proximity,
+                                                           GimpDisplay        *display);
+static void       gimp_selection_tool_cursor_update       (GimpTool           *tool,
+                                                           const GimpCoords   *coords,
+                                                           GdkModifierType     state,
+                                                           GimpDisplay        *display);
+
+static gboolean   gimp_selection_tool_real_have_selection (GimpSelectionTool  *sel_tool,
+                                                           GimpDisplay        *display);
+
+static void       gimp_selection_tool_commit              (GimpSelectionTool  *sel_tool);
+static void       gimp_selection_tool_halt                (GimpSelectionTool  *sel_tool,
+                                                           GimpDisplay        *display);
+
+static gboolean   gimp_selection_tool_check               (GimpSelectionTool  *sel_tool,
+                                                           GimpDisplay        *display,
+                                                           GError            **error);
+
+static gboolean   gimp_selection_tool_have_selection      (GimpSelectionTool  *sel_tool,
+                                                           GimpDisplay        *display);
+
+static void       gimp_selection_tool_set_undo_ptr        (GimpUndo          **undo_ptr,
+                                                           GimpUndo           *undo);
 
 
 G_DEFINE_TYPE (GimpSelectionTool, gimp_selection_tool, GIMP_TYPE_DRAW_TOOL)
@@ -91,6 +97,8 @@ gimp_selection_tool_class_init (GimpSelectionToolClass *klass)
   tool_class->key_press     = gimp_edit_selection_tool_key_press;
   tool_class->oper_update   = gimp_selection_tool_oper_update;
   tool_class->cursor_update = gimp_selection_tool_cursor_update;
+
+  klass->have_selection     = gimp_selection_tool_real_have_selection;
 }
 
 static void
@@ -210,18 +218,16 @@ gimp_selection_tool_oper_update (GimpTool         *tool,
   GimpSelectionTool    *selection_tool = GIMP_SELECTION_TOOL (tool);
   GimpSelectionOptions *options        = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
   GimpImage            *image;
-  GimpChannel          *selection;
   GimpDrawable         *drawable;
   GimpLayer            *layer;
   GimpLayer            *floating_sel;
   GdkModifierType       extend_mask;
   GdkModifierType       modify_mask;
+  gboolean              have_selection;
   gboolean              move_layer        = FALSE;
   gboolean              move_floating_sel = FALSE;
-  gboolean              selection_empty;
 
   image        = gimp_display_get_image (display);
-  selection    = gimp_image_get_mask (image);
   drawable     = gimp_image_get_active_drawable (image);
   layer        = gimp_image_pick_layer (image, coords->x, coords->y, NULL);
   floating_sel = gimp_image_get_floating_selection (image);
@@ -229,6 +235,8 @@ gimp_selection_tool_oper_update (GimpTool         *tool,
   extend_mask = gimp_get_extend_selection_mask ();
   modify_mask = gimp_get_modify_selection_mask ();
 
+  have_selection = gimp_selection_tool_have_selection (selection_tool, display);
+
   if (drawable)
     {
       if (floating_sel)
@@ -236,15 +244,14 @@ gimp_selection_tool_oper_update (GimpTool         *tool,
           if (layer == floating_sel)
             move_floating_sel = TRUE;
         }
-      else if (gimp_item_mask_intersect (GIMP_ITEM (drawable),
+      else if (have_selection &&
+               gimp_item_mask_intersect (GIMP_ITEM (drawable),
                                          NULL, NULL, NULL, NULL))
         {
           move_layer = TRUE;
         }
     }
 
-  selection_empty = gimp_channel_is_empty (selection);
-
   selection_tool->function = SELECTION_SELECT;
 
   if (selection_tool->allow_move &&
@@ -260,7 +267,7 @@ gimp_selection_tool_oper_update (GimpTool         *tool,
       selection_tool->function = SELECTION_MOVE_COPY;
     }
   else if (selection_tool->allow_move &&
-           (state & GDK_MOD1_MASK) && ! selection_empty)
+           (state & GDK_MOD1_MASK) && have_selection)
     {
       /* move the selection mask */
       selection_tool->function = SELECTION_MOVE_MASK;
@@ -291,7 +298,7 @@ gimp_selection_tool_oper_update (GimpTool         *tool,
       gboolean         free_status = FALSE;
       GdkModifierType  modifiers   = (extend_mask | modify_mask);
 
-      if (! selection_empty)
+      if (have_selection)
         modifiers |= GDK_MOD1_MASK;
 
       switch (selection_tool->function)
@@ -300,7 +307,7 @@ gimp_selection_tool_oper_update (GimpTool         *tool,
           switch (options->operation)
             {
             case GIMP_CHANNEL_OP_REPLACE:
-              if (! selection_empty)
+              if (have_selection)
                 {
                   status = gimp_suggest_modifiers (_("Click-Drag to replace the "
                                                      "current selection"),
@@ -439,6 +446,16 @@ gimp_selection_tool_cursor_update (GimpTool         *tool,
                         modifier);
 }
 
+static gboolean
+gimp_selection_tool_real_have_selection (GimpSelectionTool *sel_tool,
+                                         GimpDisplay       *display)
+{
+  GimpImage   *image     = gimp_display_get_image (display);
+  GimpChannel *selection = gimp_image_get_mask (image);
+
+  return ! gimp_channel_is_empty (selection);
+}
+
 static void
 gimp_selection_tool_commit (GimpSelectionTool *sel_tool)
 {
@@ -550,6 +567,14 @@ gimp_selection_tool_check (GimpSelectionTool  *sel_tool,
   return TRUE;
 }
 
+static gboolean
+gimp_selection_tool_have_selection (GimpSelectionTool *sel_tool,
+                                    GimpDisplay       *display)
+{
+  return GIMP_SELECTION_TOOL_GET_CLASS (sel_tool)->have_selection (sel_tool,
+                                                                   display);
+}
+
 static void
 gimp_selection_tool_set_undo_ptr (GimpUndo **undo_ptr,
                                   GimpUndo  *undo)
diff --git a/app/tools/gimpselectiontool.h b/app/tools/gimpselectiontool.h
index e56db3c679..077605691c 100644
--- a/app/tools/gimpselectiontool.h
+++ b/app/tools/gimpselectiontool.h
@@ -54,6 +54,10 @@ struct _GimpSelectionTool
 struct _GimpSelectionToolClass
 {
   GimpDrawToolClass  parent_class;
+
+  /*  virtual functions  */
+  gboolean (* have_selection) (GimpSelectionTool *sel_tool,
+                               GimpDisplay       *display);
 };
 
 


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