app: move the tool swapping code to tool manager and action to tools-action.

Per review, let's avoid having all the tools history in every
GimpContext.

Also a further commit will work on special-casing filter tools, which is
why we are storing up to 3 tool infos, instead of only 2.
This commit is contained in:
Jehan 2025-08-06 19:05:50 +02:00
parent eeb419a363
commit dddca29423
11 changed files with 86 additions and 66 deletions

View file

@ -54,13 +54,7 @@ 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 },
{ "context-tools-swap", NULL,
NC_("context-action", "_Last Tool"), NULL, { "<shift>X", NULL },
NC_("context-action", "Switch back to the last activated tool"),
context_tools_swap_cmd_callback,
GIMP_HELP_TOOLBOX_SWAP_TOOLS }
GIMP_HELP_TOOLBOX_SWAP_COLORS }
};
static GimpEnumActionEntry context_palette_foreground_actions[] =

View file

@ -104,17 +104,6 @@ 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, \

View file

@ -24,9 +24,6 @@ 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,

View file

@ -42,6 +42,15 @@
#include "gimp-intl.h"
static const GimpActionEntry tools_actions[] =
{
{ "tools-swap", NULL,
NC_("tools-action", "Activate _Last Tool"), NULL, { "<shift>X", NULL },
NC_("tools-action", "Switch back to the last activated tool"),
tools_swap_cmd_callback,
GIMP_HELP_TOOLBOX_SWAP_TOOLS }
};
static const GimpStringActionEntry tools_alternative_actions[] =
{
{ "tools-by-color-select-short", GIMP_ICON_TOOL_BY_COLOR_SELECT,
@ -653,6 +662,10 @@ tools_actions_setup (GimpActionGroup *group)
{
GList *list;
gimp_action_group_add_actions (group, "tools-action",
tools_actions,
G_N_ELEMENTS (tools_actions));
gimp_action_group_add_string_actions (group, "tools-action",
tools_alternative_actions,
G_N_ELEMENTS (tools_alternative_actions),

View file

@ -65,6 +65,18 @@ static void tools_activate_enum_action (const gchar *action_desc,
/* public functions */
void
tools_swap_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
Gimp *gimp;
return_if_no_gimp (gimp, data);
tool_manager_swap_tools (gimp);
}
void
tools_select_cmd_callback (GimpAction *action,
GVariant *value,

View file

@ -18,6 +18,10 @@
#pragma once
void tools_swap_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data);
void tools_select_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data);

View file

@ -787,7 +787,6 @@ 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;
@ -999,7 +998,6 @@ 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);
}
@ -2156,14 +2154,6 @@ 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)
@ -2218,19 +2208,15 @@ gimp_context_tool_removed (GimpContainer *container,
GimpToolInfo *tool_info,
GimpContext *context)
{
if (tool_info == context->tool_info || tool_info == context->last_tool_info)
if (tool_info == 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);
}
g_signal_handlers_disconnect_by_func (context->tool_info,
gimp_context_tool_dirty,
context);
g_clear_object (&context->tool_info);
context->last_tool_info = NULL;
if (! gimp_container_frozen (container))
gimp_context_tool_list_thaw (container, context);
}
}
@ -2254,6 +2240,8 @@ gimp_context_real_set_tool (GimpContext *context,
context);
}
g_set_object (&context->tool_info, tool_info);
if (tool_info)
{
g_signal_connect_object (tool_info, "name-changed",
@ -2268,27 +2256,10 @@ 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 **************************************************************/

View file

@ -58,7 +58,6 @@ struct _GimpContext
GimpToolInfo *tool_info;
gchar *tool_name;
GimpToolInfo *last_tool_info;
GimpPaintInfo *paint_info;
gchar *paint_name;
@ -238,10 +237,8 @@ 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_swap_tools (GimpContext *context);
void gimp_context_tool_changed (GimpContext *context);

View file

@ -26,6 +26,9 @@
#include "libgimpmath/gimpmath.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "tools/tools-types.h"
#include "tools/tool_manager.h"
#include "dialogs/dialogs-types.h"
#include "display/gimpdisplay.h"
@ -480,11 +483,9 @@ swap_tools (gconstpointer data)
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);
tool_manager_swap_tools (gimp);
g_assert (gimp_context_get_tool (user_context) == first_tool_info);
g_assert (gimp_context_get_last_tool (user_context) == second_tool_info);
}
}
}

View file

@ -55,6 +55,8 @@ struct _GimpToolManager
GimpTool *active_tool;
GSList *tool_stack;
GList *history;
GimpToolGroup *active_tool_group;
GimpImage *image;
@ -119,7 +121,8 @@ tool_manager_init (Gimp *gimp)
tool_manager = g_slice_new0 (GimpToolManager);
tool_manager->gimp = gimp;
tool_manager->gimp = gimp;
tool_manager->history = NULL;
g_object_set_qdata (G_OBJECT (gimp), tool_manager_quark, tool_manager);
@ -209,6 +212,8 @@ tool_manager_exit (Gimp *gimp)
tool_manager_set_active_tool_group (tool_manager, NULL);
g_list_free (tool_manager->history);
g_slice_free (GimpToolManager, tool_manager);
g_object_set_qdata (G_OBJECT (gimp), tool_manager_quark, NULL);
@ -276,6 +281,20 @@ tool_manager_pop_tool (Gimp *gimp)
}
}
void
tool_manager_swap_tools (Gimp *gimp)
{
GimpToolManager *tool_manager;
g_return_if_fail (GIMP_IS_GIMP (gimp));
tool_manager = tool_manager_get (gimp);
if (g_list_length (tool_manager->history) > 1)
gimp_context_set_tool (tool_manager->gimp->user_context,
g_list_nth_data (tool_manager->history, 1));
}
gboolean
tool_manager_initialize_active (Gimp *gimp,
GimpDisplay *display)
@ -672,6 +691,28 @@ tool_manager_select_tool (GimpToolManager *tool_manager,
}
}
if (tool_manager->history == NULL ||
tool_manager->history->data != tool->tool_info)
{
/* Update the history up to 3 element maximum and avoiding
* duplicates.
*/
GList *found;
if ((found = g_list_find (tool_manager->history, tool->tool_info)))
{
tool_manager->history = g_list_remove_link (tool_manager->history, found);
tool_manager->history = g_list_concat (found, tool_manager->history);
}
else
{
tool_manager->history = g_list_prepend (tool_manager->history, tool->tool_info);
if (g_list_length (tool_manager->history) > 3)
tool_manager->history = g_list_delete_link (tool_manager->history,
g_list_last (tool_manager->history));
}
}
g_set_object (&tool_manager->active_tool, tool);
}

View file

@ -27,6 +27,7 @@ void tool_manager_push_tool (Gimp *gimp,
GimpTool *tool);
void tool_manager_pop_tool (Gimp *gimp);
void tool_manager_swap_tools (Gimp *gimp);
gboolean tool_manager_initialize_active (Gimp *gimp,
GimpDisplay *display);