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.
This commit is contained in:
parent
4ced806a0a
commit
57eaf91fbc
3 changed files with 90 additions and 34 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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_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_real_have_selection (GimpSelectionTool *sel_tool,
|
||||
GimpDisplay *display);
|
||||
|
||||
static gboolean gimp_selection_tool_check (GimpSelectionTool *sel_tool,
|
||||
GimpDisplay *display,
|
||||
GError **error);
|
||||
static void gimp_selection_tool_commit (GimpSelectionTool *sel_tool);
|
||||
static void gimp_selection_tool_halt (GimpSelectionTool *sel_tool,
|
||||
GimpDisplay *display);
|
||||
|
||||
static void gimp_selection_tool_set_undo_ptr (GimpUndo **undo_ptr,
|
||||
GimpUndo *undo);
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -54,6 +54,10 @@ struct _GimpSelectionTool
|
|||
struct _GimpSelectionToolClass
|
||||
{
|
||||
GimpDrawToolClass parent_class;
|
||||
|
||||
/* virtual functions */
|
||||
gboolean (* have_selection) (GimpSelectionTool *sel_tool,
|
||||
GimpDisplay *display);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue