diff --git a/app/actions/context-actions.c b/app/actions/context-actions.c index cedc9d0bbf..c584237fa5 100644 --- a/app/actions/context-actions.c +++ b/app/actions/context-actions.c @@ -54,7 +54,13 @@ static const GimpActionEntry context_actions[] = NC_("context-action", "S_wap Colors"), NULL, { "X", NULL }, NC_("context-action", "Exchange foreground and background colors"), context_colors_swap_cmd_callback, - GIMP_HELP_TOOLBOX_SWAP_COLORS } + GIMP_HELP_TOOLBOX_SWAP_COLORS }, + + { "context-tools-swap", NULL, + NC_("context-action", "_Last Tool"), NULL, { "X", NULL }, + NC_("context-action", "Switch back to the last activated tool"), + context_tools_swap_cmd_callback, + GIMP_HELP_TOOLBOX_SWAP_TOOLS } }; static GimpEnumActionEntry context_palette_foreground_actions[] = diff --git a/app/actions/context-commands.c b/app/actions/context-commands.c index 2b2805af45..1926fbdb96 100644 --- a/app/actions/context-commands.c +++ b/app/actions/context-commands.c @@ -104,6 +104,17 @@ context_colors_swap_cmd_callback (GimpAction *action, gimp_context_swap_colors (context); } +void +context_tools_swap_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) +{ + GimpContext *context; + return_if_no_context (context, data); + + gimp_context_swap_tools (context); +} + #define SELECT_COLOR_CMD_CALLBACK(name, fgbg, use_colormap, use_palette) \ void \ context_##name##_##fgbg##ground_cmd_callback (GimpAction *action, \ diff --git a/app/actions/context-commands.h b/app/actions/context-commands.h index 284ade6b56..72de1d5067 100644 --- a/app/actions/context-commands.h +++ b/app/actions/context-commands.h @@ -24,6 +24,9 @@ void context_colors_default_cmd_callback (GimpAction *action, void context_colors_swap_cmd_callback (GimpAction *action, GVariant *value, gpointer data); +void context_tools_swap_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); void context_palette_foreground_cmd_callback (GimpAction *action, GVariant *value, diff --git a/app/core/gimpcontext.c b/app/core/gimpcontext.c index 28e5810368..440c85aa3f 100644 --- a/app/core/gimpcontext.c +++ b/app/core/gimpcontext.c @@ -787,6 +787,7 @@ gimp_context_init (GimpContext *context) context->tool_info = NULL; context->tool_name = NULL; + context->last_tool_info = NULL; context->paint_info = NULL; context->paint_name = NULL; @@ -998,6 +999,7 @@ gimp_context_dispose (GObject *object) g_clear_object (&context->buffer); g_clear_object (&context->imagefile); g_clear_object (&context->template); + g_clear_object (&context->last_tool_info); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -2154,6 +2156,14 @@ gimp_context_get_tool (GimpContext *context) return context->tool_info; } +GimpToolInfo * +gimp_context_get_last_tool (GimpContext *context) +{ + g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); + + return context->last_tool_info; +} + void gimp_context_set_tool (GimpContext *context, GimpToolInfo *tool_info) @@ -2208,15 +2218,19 @@ gimp_context_tool_removed (GimpContainer *container, GimpToolInfo *tool_info, GimpContext *context) { - if (tool_info == context->tool_info) + if (tool_info == context->tool_info || tool_info == context->last_tool_info) { - g_signal_handlers_disconnect_by_func (context->tool_info, - gimp_context_tool_dirty, - context); - g_clear_object (&context->tool_info); + /* If the removed tool is the current one, switch back to the last tool. + * This is more user-friendly than just setting to NULL. */ + if (tool_info == context->tool_info) + { + if (context->last_tool_info != NULL) + gimp_context_swap_tools (context); + else + gimp_context_set_tool (context, NULL); + } - if (! gimp_container_frozen (container)) - gimp_context_tool_list_thaw (container, context); + context->last_tool_info = NULL; } } @@ -2234,11 +2248,11 @@ gimp_context_real_set_tool (GimpContext *context, } if (context->tool_info) - g_signal_handlers_disconnect_by_func (context->tool_info, - gimp_context_tool_dirty, - context); - - g_set_object (&context->tool_info, tool_info); + { + g_signal_handlers_disconnect_by_func (context->tool_info, + G_CALLBACK (gimp_context_tool_dirty), + context); + } if (tool_info) { @@ -2254,10 +2268,27 @@ gimp_context_real_set_tool (GimpContext *context, gimp_context_real_set_paint_info (context, tool_info->paint_info); } + /* Instead of unref-ing the current tool, save it as last_tool_info + * for possible use of gimp_context_swap_tools. + */ + if (context->last_tool_info) + g_object_unref (context->last_tool_info); + + context->last_tool_info = context->tool_info; + + /* Now we set the new tool. */ + context->tool_info = tool_info ? g_object_ref (tool_info) : NULL; + g_object_notify (G_OBJECT (context), "tool"); gimp_context_tool_changed (context); } +void +gimp_context_swap_tools (GimpContext *context) +{ + if (context->last_tool_info) + gimp_context_set_tool (context, context->last_tool_info); +} /*****************************************************************************/ /* paint info **************************************************************/ diff --git a/app/core/gimpcontext.h b/app/core/gimpcontext.h index f9b01a5f0d..67b6d3c1b1 100644 --- a/app/core/gimpcontext.h +++ b/app/core/gimpcontext.h @@ -58,6 +58,7 @@ struct _GimpContext GimpToolInfo *tool_info; gchar *tool_name; + GimpToolInfo *last_tool_info; GimpPaintInfo *paint_info; gchar *paint_name; @@ -237,10 +238,12 @@ void gimp_context_display_changed (GimpContext *context); /* tool */ GimpToolInfo * gimp_context_get_tool (GimpContext *context); +GimpToolInfo * gimp_context_get_last_tool (GimpContext *context); void gimp_context_set_tool (GimpContext *context, GimpToolInfo *tool_info); -void gimp_context_tool_changed (GimpContext *context); +void gimp_context_swap_tools (GimpContext *context); +void gimp_context_tool_changed (GimpContext *context); /* paint info */ GimpPaintInfo * gimp_context_get_paint_info (GimpContext *context); diff --git a/app/tests/test-ui.c b/app/tests/test-ui.c index e48ce24908..8265ea2b4b 100644 --- a/app/tests/test-ui.c +++ b/app/tests/test-ui.c @@ -435,6 +435,61 @@ paintbrush_is_standard_tool (gconstpointer data) "gimp-tool-paintbrush"); } + +/** + * swap_tools: + * @data: + * + * Testing switchback to last used tool X. Tools are taken from gimp->tool_info_list. + * Not all possible combinations of available tools are tested though. + **/ +static void +swap_tools (gconstpointer data) +{ + Gimp *gimp = GIMP (data); + GimpContext *user_context = gimp_get_user_context (gimp); + GimpToolInfo *first_tool_info = NULL; + GimpToolInfo *second_tool_info = NULL; + GList *tool_info_list = NULL; + guint i, j = 0; + + /* Arbitrarily testing only the first 10 available tools from gimp->tool_info_list + * because there are tools which aren't settable within the reduced framework of + * gimp_init_for_gui_testing's environment! + */ + guint tool_info_list_length = 10; /* Value should actually be g_list_length (tool_info_list) */ + + tool_info_list = gimp_get_tool_info_iter (gimp); + + for (i = 0; i < tool_info_list_length; i++) + { + /* Getting the first reference tool */ + first_tool_info = g_list_nth_data (tool_info_list, i); + + for (j = 0; j < tool_info_list_length; j++) + { + /* Now get the second tool. Set both one after another and loop the second tool through + * all available tools to test switchback. + */ + second_tool_info = g_list_nth_data (tool_info_list, j); + + if (first_tool_info != second_tool_info) + { + gimp_context_set_tool (user_context, first_tool_info); + g_assert (gimp_context_get_tool (user_context) == first_tool_info); + + gimp_context_set_tool (user_context, second_tool_info); + g_assert (gimp_context_get_tool (user_context) == second_tool_info); + g_assert (gimp_context_get_last_tool (user_context) == first_tool_info); + + gimp_context_swap_tools (user_context); + g_assert (gimp_context_get_tool (user_context) == first_tool_info); + g_assert (gimp_context_get_last_tool (user_context) == second_tool_info); + } + } + } +} + /** * gimp_ui_synthesize_delete_event: * @widget: @@ -553,6 +608,7 @@ int main(int argc, char **argv) ADD_TEST (switch_back_to_multi_window_mode); ADD_TEST (close_image); ADD_TEST (window_roles); + ADD_TEST (swap_tools); /* Run the tests and return status */ g_application_run (gimp->app, 0, NULL); diff --git a/app/widgets/gimphelp-ids.h b/app/widgets/gimphelp-ids.h index 57555f433f..0164c308bb 100644 --- a/app/widgets/gimphelp-ids.h +++ b/app/widgets/gimphelp-ids.h @@ -511,6 +511,7 @@ #define GIMP_HELP_TOOLBOX_INDICATOR_AREA "gimp-toolbox-indicator-area" #define GIMP_HELP_TOOLBOX_DEFAULT_COLORS "gimp-toolbox-default-colors" #define GIMP_HELP_TOOLBOX_SWAP_COLORS "gimp-toolbox-swap-colors" +#define GIMP_HELP_TOOLBOX_SWAP_TOOLS "gimp-toolbox-swap-tools" #define GIMP_HELP_BRUSH_DIALOG "gimp-brush-dialog" #define GIMP_HELP_BRUSH_EDIT "gimp-brush-edit"