app: commit ongoing tool operations on tool change instead of cancelling

On tool change, we used to simply halt tools before switching to the
new one, which meant losing ongoing live-previewed tool changes, like
transforms, warps and color corrections. This change makes them being
applied to the image instead before switching to the new tool:

Add enum value GIMP_TOOL_ACTION_COMMIT that is passed to
GimpTool::control() before tool switching. Handle the new enum value
in all tools, and actually commit the previewed stuff. This changes
the behavior of GimpCageTool, GimpImageMapTool, GimpTransformTool and
GimpWarpTool.
This commit is contained in:
Michael Natterer 2014-04-04 22:34:26 +02:00
parent 661317f74c
commit 88e4d7e468
21 changed files with 245 additions and 122 deletions

View File

@ -193,6 +193,9 @@ gimp_align_tool_control (GimpTool *tool,
case GIMP_TOOL_ACTION_HALT:
gimp_align_tool_clear_selected (align_tool);
break;
case GIMP_TOOL_ACTION_COMMIT:
break;
}
GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);

View File

@ -115,6 +115,9 @@ static void gimp_cage_tool_oper_update (GimpTool *tool
static void gimp_cage_tool_draw (GimpDrawTool *draw_tool);
static void gimp_cage_tool_halt (GimpCageTool *ct);
static void gimp_cage_tool_commit (GimpCageTool *ct);
static gint gimp_cage_tool_is_on_handle (GimpCageTool *ct,
GimpDrawTool *draw_tool,
GimpDisplay *display,
@ -220,44 +223,11 @@ gimp_cage_tool_control (GimpTool *tool,
break;
case GIMP_TOOL_ACTION_HALT:
if (ct->config)
{
g_object_unref (ct->config);
ct->config = NULL;
}
gimp_cage_tool_halt (ct);
break;
if (ct->coef)
{
g_object_unref (ct->coef);
ct->coef = NULL;
}
if (ct->render_node)
{
g_object_unref (ct->render_node);
ct->render_node = NULL;
ct->coef_node = NULL;
ct->cage_node = NULL;
}
if (ct->image_map)
{
gimp_tool_control_push_preserve (tool->control, TRUE);
gimp_image_map_abort (ct->image_map);
g_object_unref (ct->image_map);
ct->image_map = NULL;
gimp_tool_control_pop_preserve (tool->control);
gimp_image_flush (gimp_display_get_image (tool->display));
}
tool->display = NULL;
g_object_set (gimp_tool_get_options (tool),
"cage-mode", GIMP_CAGE_MODE_CAGE_CHANGE,
NULL);
case GIMP_TOOL_ACTION_COMMIT:
gimp_cage_tool_commit (ct);
break;
}
@ -425,7 +395,8 @@ gimp_cage_tool_key_press (GimpTool *tool,
case GDK_KEY_Return:
case GDK_KEY_KP_Enter:
case GDK_KEY_ISO_Enter:
if (! gimp_cage_tool_is_complete (ct) && gimp_cage_config_get_n_points (ct->config) > 2)
if (! gimp_cage_tool_is_complete (ct) &&
gimp_cage_config_get_n_points (ct->config) > 2)
{
g_object_set (gimp_tool_get_options (tool),
"cage-mode", GIMP_CAGE_MODE_DEFORM,
@ -433,17 +404,7 @@ gimp_cage_tool_key_press (GimpTool *tool,
}
else if (ct->tool_state == DEFORM_STATE_WAIT)
{
gimp_tool_control_push_preserve (tool->control, TRUE);
gimp_image_map_commit (ct->image_map,
GIMP_PROGRESS (tool));
g_object_unref (ct->image_map);
ct->image_map = NULL;
gimp_tool_control_pop_preserve (tool->control);
gimp_image_flush (gimp_display_get_image (display));
gimp_tool_control (tool, GIMP_TOOL_ACTION_COMMIT, display);
gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
}
return TRUE;
@ -931,6 +892,68 @@ gimp_cage_tool_draw (GimpDrawTool *draw_tool)
}
}
static void
gimp_cage_tool_halt (GimpCageTool *ct)
{
GimpTool *tool = GIMP_TOOL (ct);
if (ct->config)
{
g_object_unref (ct->config);
ct->config = NULL;
}
if (ct->coef)
{
g_object_unref (ct->coef);
ct->coef = NULL;
}
if (ct->render_node)
{
g_object_unref (ct->render_node);
ct->render_node = NULL;
ct->coef_node = NULL;
ct->cage_node = NULL;
}
if (ct->image_map)
{
gimp_tool_control_push_preserve (tool->control, TRUE);
gimp_image_map_abort (ct->image_map);
g_object_unref (ct->image_map);
ct->image_map = NULL;
gimp_tool_control_pop_preserve (tool->control);
gimp_image_flush (gimp_display_get_image (tool->display));
}
tool->display = NULL;
g_object_set (gimp_tool_get_options (tool),
"cage-mode", GIMP_CAGE_MODE_CAGE_CHANGE,
NULL);
}
static void
gimp_cage_tool_commit (GimpCageTool *ct)
{
GimpTool *tool = GIMP_TOOL (ct);
gimp_tool_control_push_preserve (tool->control, TRUE);
gimp_image_map_commit (ct->image_map,
GIMP_PROGRESS (tool));
g_object_unref (ct->image_map);
ct->image_map = NULL;
gimp_tool_control_pop_preserve (tool->control);
gimp_image_flush (gimp_display_get_image (tool->display));
}
static gint
gimp_cage_tool_is_on_handle (GimpCageTool *ct,
GimpDrawTool *draw_tool,

View File

@ -162,6 +162,9 @@ gimp_color_picker_tool_control (GimpTool *tool,
picker_tool->color_frame2 = NULL;
}
break;
case GIMP_TOOL_ACTION_COMMIT:
break;
}
GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);

View File

@ -171,6 +171,9 @@ gimp_draw_tool_control (GimpTool *tool,
if (gimp_draw_tool_is_active (draw_tool))
gimp_draw_tool_stop (draw_tool);
break;
case GIMP_TOOL_ACTION_COMMIT:
break;
}
GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);

View File

@ -267,13 +267,14 @@ gimp_foreground_select_tool_control (GimpTool *tool,
break;
case GIMP_TOOL_ACTION_HALT:
{
gimp_foreground_select_tool_drop_masks (fg_select, display);
tool->display = NULL;
gimp_foreground_select_tool_drop_masks (fg_select, display);
tool->display = NULL;
if (fg_select->gui)
gimp_tool_gui_hide (fg_select->gui);
}
if (fg_select->gui)
gimp_tool_gui_hide (fg_select->gui);
break;
case GIMP_TOOL_ACTION_COMMIT:
break;
}

View File

@ -1070,6 +1070,9 @@ gimp_free_select_tool_control (GimpTool *tool,
priv->n_points = 0;
priv->n_segment_indices = 0;
break;
case GIMP_TOOL_ACTION_COMMIT:
break;
}
GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);

View File

@ -104,6 +104,9 @@ static void gimp_image_map_tool_color_picked (GimpColorTool *color_too
const GimpRGB *color,
gint color_index);
static void gimp_image_map_tool_halt (GimpImageMapTool *im_tool);
static void gimp_image_map_tool_commit (GimpImageMapTool *im_tool);
static void gimp_image_map_tool_map (GimpImageMapTool *im_tool);
static void gimp_image_map_tool_dialog (GimpImageMapTool *im_tool);
static void gimp_image_map_tool_dialog_unmap (GtkWidget *dialog,
@ -416,21 +419,11 @@ gimp_image_map_tool_control (GimpTool *tool,
break;
case GIMP_TOOL_ACTION_HALT:
if (image_map_tool->gui)
gimp_tool_gui_hide (image_map_tool->gui);
gimp_image_map_tool_halt (image_map_tool);
break;
if (image_map_tool->image_map)
{
gimp_tool_control_push_preserve (tool->control, TRUE);
gimp_image_map_abort (image_map_tool->image_map);
g_object_unref (image_map_tool->image_map);
image_map_tool->image_map = NULL;
gimp_tool_control_pop_preserve (tool->control);
}
tool->drawable = NULL;
case GIMP_TOOL_ACTION_COMMIT:
gimp_image_map_tool_commit (image_map_tool);
break;
}
@ -551,6 +544,67 @@ gimp_image_map_tool_color_picked (GimpColorTool *color_tool,
color);
}
static void
gimp_image_map_tool_halt (GimpImageMapTool *im_tool)
{
GimpTool *tool = GIMP_TOOL (im_tool);
if (im_tool->gui)
gimp_tool_gui_hide (im_tool->gui);
if (im_tool->image_map)
{
gimp_tool_control_push_preserve (tool->control, TRUE);
gimp_image_map_abort (im_tool->image_map);
g_object_unref (im_tool->image_map);
im_tool->image_map = NULL;
gimp_tool_control_pop_preserve (tool->control);
}
tool->drawable = NULL;
}
static void
gimp_image_map_tool_commit (GimpImageMapTool *im_tool)
{
GimpTool *tool = GIMP_TOOL (im_tool);
if (im_tool->gui)
gimp_tool_gui_hide (im_tool->gui);
if (im_tool->image_map)
{
GimpImageMapOptions *options = GIMP_IMAGE_MAP_TOOL_GET_OPTIONS (tool);
gimp_tool_control_push_preserve (tool->control, TRUE);
if (! options->preview)
gimp_image_map_tool_map (im_tool);
gimp_image_map_commit (im_tool->image_map,
GIMP_PROGRESS (tool));
g_object_unref (im_tool->image_map);
im_tool->image_map = NULL;
gimp_tool_control_pop_preserve (tool->control);
gimp_image_flush (gimp_display_get_image (tool->display));
if (im_tool->config && im_tool->settings_box)
{
GimpGuiConfig *config = GIMP_GUI_CONFIG (tool->tool_info->gimp->config);
gimp_settings_box_add_current (GIMP_SETTINGS_BOX (im_tool->settings_box),
config->image_map_tool_max_recent);
}
}
tool->display = NULL;
tool->drawable = NULL;
}
static void
gimp_image_map_tool_map (GimpImageMapTool *tool)
{
@ -661,34 +715,7 @@ gimp_image_map_tool_response (GimpToolGui *gui,
break;
case GTK_RESPONSE_OK:
if (image_map_tool->gui)
gimp_tool_gui_hide (image_map_tool->gui);
if (image_map_tool->image_map)
{
GimpImageMapOptions *options = GIMP_IMAGE_MAP_TOOL_GET_OPTIONS (tool);
gimp_tool_control_push_preserve (tool->control, TRUE);
if (! options->preview)
gimp_image_map_tool_map (image_map_tool);
gimp_image_map_commit (image_map_tool->image_map,
GIMP_PROGRESS (tool));
g_object_unref (image_map_tool->image_map);
image_map_tool->image_map = NULL;
gimp_tool_control_pop_preserve (tool->control);
gimp_image_flush (gimp_display_get_image (tool->display));
if (image_map_tool->config && image_map_tool->settings_box)
gimp_settings_box_add_current (GIMP_SETTINGS_BOX (image_map_tool->settings_box),
GIMP_GUI_CONFIG (tool->tool_info->gimp->config)->image_map_tool_max_recent);
}
tool->display = NULL;
tool->drawable = NULL;
gimp_tool_control (tool, GIMP_TOOL_ACTION_COMMIT, tool->display);
break;
default:

View File

@ -183,6 +183,9 @@ gimp_measure_tool_control (GimpTool *tool,
if (measure->gui)
g_object_unref (measure->gui);
break;
case GIMP_TOOL_ACTION_COMMIT:
break;
}
GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);

View File

@ -204,6 +204,9 @@ gimp_operation_tool_control (GimpTool *tool,
gimp_pickable_button_set_pickable (GIMP_PICKABLE_BUTTON (op_tool->aux_input_button),
NULL);
break;
case GIMP_TOOL_ACTION_COMMIT:
break;
}
GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);

View File

@ -221,6 +221,9 @@ gimp_paint_tool_control (GimpTool *tool,
case GIMP_TOOL_ACTION_HALT:
gimp_paint_core_cleanup (paint_tool->core);
break;
case GIMP_TOOL_ACTION_COMMIT:
break;
}
GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);

View File

@ -285,6 +285,9 @@ gimp_perspective_clone_tool_control (GimpTool *tool,
case GIMP_TOOL_ACTION_HALT:
gimp_perspective_clone_tool_halt (clone_tool);
break;
case GIMP_TOOL_ACTION_COMMIT:
break;
}
GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);

View File

@ -246,6 +246,9 @@ gimp_seamless_clone_tool_control (GimpTool *tool,
* a good place to do so.
*/
break;
case GIMP_TOOL_ACTION_COMMIT:
break;
}
GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);

View File

@ -160,6 +160,9 @@ gimp_source_tool_control (GimpTool *tool,
"src-drawable", NULL,
NULL);
break;
case GIMP_TOOL_ACTION_COMMIT:
break;
}
GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);

View File

@ -334,6 +334,9 @@ gimp_text_tool_control (GimpTool *tool,
gimp_text_tool_editor_halt (text_tool);
gimp_text_tool_set_drawable (text_tool, NULL, FALSE);
break;
case GIMP_TOOL_ACTION_COMMIT:
break;
}
gimp_rectangle_tool_control (tool, action, display);

View File

@ -333,6 +333,9 @@ gimp_tool_real_control (GimpTool *tool,
case GIMP_TOOL_ACTION_HALT:
tool->display = NULL;
break;
case GIMP_TOOL_ACTION_COMMIT:
break;
}
}
@ -595,6 +598,10 @@ gimp_tool_control (GimpTool *tool,
gimp_tool_clear_status (tool);
break;
case GIMP_TOOL_ACTION_COMMIT:
GIMP_TOOL_GET_CLASS (tool)->control (tool, action, display);
break;
}
}

View File

@ -347,6 +347,10 @@ gimp_transform_tool_control (GimpTool *tool,
case GIMP_TOOL_ACTION_HALT:
gimp_transform_tool_halt (tr_tool);
break;
case GIMP_TOOL_ACTION_COMMIT:
gimp_transform_tool_transform (tr_tool, display);
break;
}
GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
@ -1352,7 +1356,6 @@ gimp_transform_tool_transform (GimpTransformTool *tr_tool,
{
gimp_tool_message_literal (tool, display, error->message);
g_clear_error (&error);
gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
return;
}
@ -1450,8 +1453,6 @@ gimp_transform_tool_transform (GimpTransformTool *tr_tool,
*/
gimp_tool_control_pop_preserve (tool->control);
gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
gimp_unset_busy (display->gimp);
gimp_image_flush (image);
@ -1754,8 +1755,9 @@ gimp_transform_tool_response (GimpToolGui *gui,
case GTK_RESPONSE_OK:
g_return_if_fail (display != NULL);
gimp_transform_tool_transform (tr_tool, display);
break;
gimp_tool_control (tool, GIMP_TOOL_ACTION_COMMIT, display);
gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
break;
default:
gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);

View File

@ -235,6 +235,9 @@ gimp_vector_tool_control (GimpTool *tool,
case GIMP_TOOL_ACTION_HALT:
gimp_vector_tool_set_vectors (vector_tool, NULL);
break;
case GIMP_TOOL_ACTION_COMMIT:
break;
}
GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);

View File

@ -95,6 +95,7 @@ static void gimp_warp_tool_draw (GimpDrawTool *draw
static void gimp_warp_tool_start (GimpWarpTool *wt,
GimpDisplay *display);
static void gimp_warp_tool_halt (GimpWarpTool *wt);
static void gimp_warp_tool_commit (GimpWarpTool *wt);
static gboolean gimp_warp_tool_stroke_timer (GimpWarpTool *wt);
@ -188,6 +189,10 @@ gimp_warp_tool_control (GimpTool *tool,
case GIMP_TOOL_ACTION_HALT:
gimp_warp_tool_halt (wt);
break;
case GIMP_TOOL_ACTION_COMMIT:
gimp_warp_tool_commit (wt);
break;
}
GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
@ -321,8 +326,6 @@ gimp_warp_tool_key_press (GimpTool *tool,
GdkEventKey *kevent,
GimpDisplay *display)
{
GimpWarpTool *wt = GIMP_WARP_TOOL (tool);
switch (kevent->keyval)
{
case GDK_KEY_BackSpace:
@ -331,18 +334,7 @@ gimp_warp_tool_key_press (GimpTool *tool,
case GDK_KEY_Return:
case GDK_KEY_KP_Enter:
case GDK_KEY_ISO_Enter:
if (wt->image_map)
{
gimp_tool_control_push_preserve (tool->control, TRUE);
gimp_image_map_commit (wt->image_map, GIMP_PROGRESS (tool));
g_object_unref (wt->image_map);
wt->image_map = NULL;
gimp_tool_control_pop_preserve (tool->control);
gimp_image_flush (gimp_display_get_image (display));
}
gimp_tool_control (tool, GIMP_TOOL_ACTION_COMMIT, display);
/* fall thru */
case GDK_KEY_Escape:
@ -593,6 +585,25 @@ gimp_warp_tool_halt (GimpWarpTool *wt)
gimp_draw_tool_stop (GIMP_DRAW_TOOL (wt));
}
static void
gimp_warp_tool_commit (GimpWarpTool *wt)
{
GimpTool *tool = GIMP_TOOL (wt);
if (wt->image_map)
{
gimp_tool_control_push_preserve (tool->control, TRUE);
gimp_image_map_commit (wt->image_map, GIMP_PROGRESS (tool));
g_object_unref (wt->image_map);
wt->image_map = NULL;
gimp_tool_control_pop_preserve (tool->control);
gimp_image_flush (gimp_display_get_image (tool->display));
}
}
static gboolean
gimp_warp_tool_stroke_timer (GimpWarpTool *wt)
{

View File

@ -686,12 +686,25 @@ tool_manager_tool_changed (GimpContext *user_context,
return;
}
/* disconnect the old tool's context */
if (tool_manager->active_tool &&
tool_manager->active_tool->tool_info)
if (tool_manager->active_tool)
{
tool_manager_disconnect_options (tool_manager, user_context,
tool_manager->active_tool->tool_info);
GimpTool *active_tool = tool_manager->active_tool;
GimpDisplay *display;
/* NULL image returns any display (if there is any) */
display = gimp_tool_has_image (active_tool, NULL);
/* commit the old tool's operation */
if (display)
tool_manager_control_active (user_context->gimp, GIMP_TOOL_ACTION_COMMIT,
display);
/* disconnect the old tool's context */
if (active_tool->tool_info)
{
tool_manager_disconnect_options (tool_manager, user_context,
active_tool->tool_info);
}
}
/* connect the new tool's context */

View File

@ -267,6 +267,7 @@ gimp_tool_action_get_type (void)
{ GIMP_TOOL_ACTION_PAUSE, "GIMP_TOOL_ACTION_PAUSE", "pause" },
{ GIMP_TOOL_ACTION_RESUME, "GIMP_TOOL_ACTION_RESUME", "resume" },
{ GIMP_TOOL_ACTION_HALT, "GIMP_TOOL_ACTION_HALT", "halt" },
{ GIMP_TOOL_ACTION_COMMIT, "GIMP_TOOL_ACTION_COMMIT", "commit" },
{ 0, NULL, NULL }
};
@ -275,6 +276,7 @@ gimp_tool_action_get_type (void)
{ GIMP_TOOL_ACTION_PAUSE, "GIMP_TOOL_ACTION_PAUSE", NULL },
{ GIMP_TOOL_ACTION_RESUME, "GIMP_TOOL_ACTION_RESUME", NULL },
{ GIMP_TOOL_ACTION_HALT, "GIMP_TOOL_ACTION_HALT", NULL },
{ GIMP_TOOL_ACTION_COMMIT, "GIMP_TOOL_ACTION_COMMIT", NULL },
{ 0, NULL, NULL }
};

View File

@ -127,7 +127,8 @@ typedef enum
{
GIMP_TOOL_ACTION_PAUSE,
GIMP_TOOL_ACTION_RESUME,
GIMP_TOOL_ACTION_HALT
GIMP_TOOL_ACTION_HALT,
GIMP_TOOL_ACTION_COMMIT
} GimpToolAction;