Issue #9228: make GEGL Operation tool's operations their own actions too.
Though the GEGL Operation tool is still useful as a generic dialog, let's generate also per-operation (the ones not ignored and not already special-cased in the rest of the GUI) tools and actions. These "tools" are mostly hidden (e.g. not selectable in toolbox where it would be a bit useless as they would show with the generic GEGL icon or none), but they can be searched with the action search, shortcuts can be assigned and they can be added to menus.
This commit is contained in:
parent
60354a0e59
commit
d51c64ec06
4 changed files with 169 additions and 39 deletions
|
|
@ -147,7 +147,13 @@ gimp_tool_dialog_new (GimpToolInfo *tool_info,
|
||||||
gimp_dialog_add_buttons_valist (GIMP_DIALOG (dialog), args);
|
gimp_dialog_add_buttons_valist (GIMP_DIALOG (dialog), args);
|
||||||
va_end (args);
|
va_end (args);
|
||||||
|
|
||||||
identifier = g_strconcat (gimp_object_get_name (tool_info), "-dialog", NULL);
|
/* We don't register a foreign dialog for every generated GEGL op tool. Simply
|
||||||
|
* use the base GimpGeglTool dialog for them all.
|
||||||
|
*/
|
||||||
|
if (g_str_has_prefix (gimp_object_get_name (tool_info), "gimp-gegl-op-"))
|
||||||
|
identifier = g_strdup ("gimp-gegl-tool-dialog");
|
||||||
|
else
|
||||||
|
identifier = g_strconcat (gimp_object_get_name (tool_info), "-dialog", NULL);
|
||||||
|
|
||||||
gimp_dialog_factory_add_foreign (gimp_dialog_factory_get_singleton (),
|
gimp_dialog_factory_add_foreign (gimp_dialog_factory_get_singleton (),
|
||||||
identifier,
|
identifier,
|
||||||
|
|
|
||||||
|
|
@ -748,7 +748,10 @@ gimp_tools_register (GType tool_type,
|
||||||
gimp_tool_item_set_visible (GIMP_TOOL_ITEM (tool_info), visible);
|
gimp_tool_item_set_visible (GIMP_TOOL_ITEM (tool_info), visible);
|
||||||
|
|
||||||
/* hack to hide the operation tool entirely */
|
/* hack to hide the operation tool entirely */
|
||||||
if (tool_type == GIMP_TYPE_OPERATION_TOOL)
|
if (tool_type == GIMP_TYPE_OPERATION_TOOL ||
|
||||||
|
/* Don't show the generated GEGL tools either. */
|
||||||
|
(tool_type == GIMP_TYPE_GEGL_TOOL &&
|
||||||
|
g_strcmp0 (identifier, "gimp-gegl-tool") != 0))
|
||||||
tool_info->hidden = TRUE;
|
tool_info->hidden = TRUE;
|
||||||
|
|
||||||
/* hack to not require experimental tools to be present in toolrc */
|
/* hack to not require experimental tools to be present in toolrc */
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,12 @@
|
||||||
|
|
||||||
#include "tools-types.h"
|
#include "tools-types.h"
|
||||||
|
|
||||||
|
#include "core/gimp.h"
|
||||||
|
#include "core/gimptoolinfo.h"
|
||||||
|
|
||||||
#include "widgets/gimphelp-ids.h"
|
#include "widgets/gimphelp-ids.h"
|
||||||
#include "widgets/gimppropwidgets.h"
|
#include "widgets/gimppropwidgets.h"
|
||||||
|
#include "widgets/gimpwidgets-utils.h"
|
||||||
|
|
||||||
#include "gimpfilteroptions.h"
|
#include "gimpfilteroptions.h"
|
||||||
#include "gimpgegltool.h"
|
#include "gimpgegltool.h"
|
||||||
|
|
@ -49,16 +53,18 @@ enum
|
||||||
|
|
||||||
/* local function prototypes */
|
/* local function prototypes */
|
||||||
|
|
||||||
static void gimp_gegl_tool_control (GimpTool *tool,
|
static void gimp_gegl_tool_control (GimpTool *tool,
|
||||||
GimpToolAction action,
|
GimpToolAction action,
|
||||||
GimpDisplay *display);
|
GimpDisplay *display);
|
||||||
|
|
||||||
static void gimp_gegl_tool_dialog (GimpFilterTool *filter_tool);
|
static GList * gimp_get_geglopclasses (void);
|
||||||
|
|
||||||
static void gimp_gegl_tool_halt (GimpGeglTool *gegl_tool);
|
static void gimp_gegl_tool_dialog (GimpFilterTool *filter_tool);
|
||||||
|
|
||||||
static void gimp_gegl_tool_operation_changed (GtkWidget *widget,
|
static void gimp_gegl_tool_halt (GimpGeglTool *gegl_tool);
|
||||||
GimpGeglTool *gegl_tool);
|
|
||||||
|
static void gimp_gegl_tool_operation_changed (GtkWidget *widget,
|
||||||
|
GimpGeglTool *gegl_tool);
|
||||||
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (GimpGeglTool, gimp_gegl_tool, GIMP_TYPE_OPERATION_TOOL)
|
G_DEFINE_TYPE (GimpGeglTool, gimp_gegl_tool, GIMP_TYPE_OPERATION_TOOL)
|
||||||
|
|
@ -70,6 +76,13 @@ void
|
||||||
gimp_gegl_tool_register (GimpToolRegisterCallback callback,
|
gimp_gegl_tool_register (GimpToolRegisterCallback callback,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
|
GimpGeglToolClass *klass;
|
||||||
|
Gimp *gimp = GIMP (data);
|
||||||
|
GList *opclasses;
|
||||||
|
GList *iter;
|
||||||
|
|
||||||
|
klass = g_type_class_ref (GIMP_TYPE_GEGL_TOOL);
|
||||||
|
|
||||||
(* callback) (GIMP_TYPE_GEGL_TOOL,
|
(* callback) (GIMP_TYPE_GEGL_TOOL,
|
||||||
GIMP_TYPE_FILTER_OPTIONS,
|
GIMP_TYPE_FILTER_OPTIONS,
|
||||||
gimp_color_options_gui,
|
gimp_color_options_gui,
|
||||||
|
|
@ -81,6 +94,76 @@ gimp_gegl_tool_register (GimpToolRegisterCallback callback,
|
||||||
NULL, GIMP_HELP_TOOL_GEGL,
|
NULL, GIMP_HELP_TOOL_GEGL,
|
||||||
GIMP_ICON_GEGL,
|
GIMP_ICON_GEGL,
|
||||||
data);
|
data);
|
||||||
|
|
||||||
|
/* We generate hidden tools for every non-ignored GEGL operation, allowing
|
||||||
|
* people to easily access their custom GEGL operations.
|
||||||
|
*/
|
||||||
|
opclasses = gimp_get_geglopclasses ();
|
||||||
|
|
||||||
|
for (iter = opclasses; iter; iter = iter->next)
|
||||||
|
{
|
||||||
|
GeglOperationClass *opclass = GEGL_OPERATION_CLASS (iter->data);
|
||||||
|
const gchar *icon_name = NULL;
|
||||||
|
const gchar *op_name = opclass->name;
|
||||||
|
const gchar *title;
|
||||||
|
const gchar *desc;
|
||||||
|
gchar *formatted_op_name;
|
||||||
|
gchar *action_name;
|
||||||
|
gchar *identifier;
|
||||||
|
gchar *label;
|
||||||
|
gint i = 2;
|
||||||
|
|
||||||
|
formatted_op_name = g_strdup (opclass->name);
|
||||||
|
gimp_make_valid_action_name (formatted_op_name);
|
||||||
|
action_name = g_strdup_printf ("tools-gegl-op-%s", formatted_op_name);
|
||||||
|
|
||||||
|
while (g_action_group_has_action (G_ACTION_GROUP (gimp->app), action_name))
|
||||||
|
{
|
||||||
|
/* In the off-chance that after formatting to a valid action name, 2
|
||||||
|
* operations end up generating the same action name.
|
||||||
|
*/
|
||||||
|
g_free (action_name);
|
||||||
|
action_name = g_strdup_printf ("tools-gegl-op-%s-%d", formatted_op_name, i++);
|
||||||
|
}
|
||||||
|
g_free (formatted_op_name);
|
||||||
|
|
||||||
|
/* gimp_tool_info_get_action_name() expects a name starting with "gimp-"
|
||||||
|
* and ending with "-tool".
|
||||||
|
*/
|
||||||
|
identifier = g_strdup_printf ("gimp-%s-tool", action_name + strlen ("tools-"));
|
||||||
|
g_hash_table_replace (klass->generated_ops, action_name, g_strdup (op_name));
|
||||||
|
|
||||||
|
if (g_str_has_prefix (op_name, "gegl:"))
|
||||||
|
icon_name = GIMP_ICON_GEGL;
|
||||||
|
|
||||||
|
if (g_str_has_prefix (op_name, "gegl:"))
|
||||||
|
op_name += strlen ("gegl:");
|
||||||
|
|
||||||
|
title = gegl_operation_class_get_key (opclass, "title");
|
||||||
|
desc = gegl_operation_class_get_key (opclass, "description");
|
||||||
|
|
||||||
|
if (title)
|
||||||
|
label = g_strdup_printf ("%s (%s)", title, op_name);
|
||||||
|
else
|
||||||
|
label = g_strdup (op_name);
|
||||||
|
|
||||||
|
(* callback) (GIMP_TYPE_GEGL_TOOL,
|
||||||
|
GIMP_TYPE_FILTER_OPTIONS,
|
||||||
|
gimp_color_options_gui,
|
||||||
|
0,
|
||||||
|
identifier,
|
||||||
|
label, desc ? desc : label,
|
||||||
|
label, NULL,
|
||||||
|
NULL, GIMP_HELP_TOOL_GEGL,
|
||||||
|
icon_name,
|
||||||
|
data);
|
||||||
|
|
||||||
|
g_free (label);
|
||||||
|
g_free (identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free (opclasses);
|
||||||
|
g_type_class_unref (klass);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -92,6 +175,12 @@ gimp_gegl_tool_class_init (GimpGeglToolClass *klass)
|
||||||
tool_class->control = gimp_gegl_tool_control;
|
tool_class->control = gimp_gegl_tool_control;
|
||||||
|
|
||||||
filter_tool_class->dialog = gimp_gegl_tool_dialog;
|
filter_tool_class->dialog = gimp_gegl_tool_dialog;
|
||||||
|
|
||||||
|
/* Store the mapping from tool identifier to operation name.
|
||||||
|
* This data is leaking, otherwise we'd have to register a dynamic type with a
|
||||||
|
* class_finalize() class method.
|
||||||
|
**/
|
||||||
|
klass->generated_ops = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -400,9 +489,10 @@ gimp_get_geglopclasses (void)
|
||||||
static void
|
static void
|
||||||
gimp_gegl_tool_dialog (GimpFilterTool *filter_tool)
|
gimp_gegl_tool_dialog (GimpFilterTool *filter_tool)
|
||||||
{
|
{
|
||||||
GimpGeglTool *tool = GIMP_GEGL_TOOL (filter_tool);
|
GimpGeglTool *tool = GIMP_GEGL_TOOL (filter_tool);
|
||||||
GimpOperationTool *o_tool = GIMP_OPERATION_TOOL (filter_tool);
|
GimpOperationTool *o_tool = GIMP_OPERATION_TOOL (filter_tool);
|
||||||
GtkListStore *store;
|
GimpToolInfo *tool_info = GIMP_TOOL (tool)->tool_info;
|
||||||
|
GtkListStore *store = NULL;
|
||||||
GtkCellRenderer *cell;
|
GtkCellRenderer *cell;
|
||||||
GtkWidget *main_vbox;
|
GtkWidget *main_vbox;
|
||||||
GtkWidget *hbox;
|
GtkWidget *hbox;
|
||||||
|
|
@ -411,6 +501,14 @@ gimp_gegl_tool_dialog (GimpFilterTool *filter_tool)
|
||||||
GtkWidget *options_box;
|
GtkWidget *options_box;
|
||||||
GList *opclasses;
|
GList *opclasses;
|
||||||
GList *iter;
|
GList *iter;
|
||||||
|
gchar *action_name;
|
||||||
|
gchar *show_op_name = NULL;
|
||||||
|
GimpGeglToolClass *klass;
|
||||||
|
|
||||||
|
klass = GIMP_GEGL_TOOL_GET_CLASS (tool);
|
||||||
|
action_name = gimp_tool_info_get_action_name (tool_info);
|
||||||
|
show_op_name = g_hash_table_lookup (klass->generated_ops, action_name);
|
||||||
|
g_free (action_name);
|
||||||
|
|
||||||
GIMP_FILTER_TOOL_CLASS (parent_class)->dialog (filter_tool);
|
GIMP_FILTER_TOOL_CLASS (parent_class)->dialog (filter_tool);
|
||||||
|
|
||||||
|
|
@ -425,8 +523,9 @@ gimp_gegl_tool_dialog (GimpFilterTool *filter_tool)
|
||||||
gtk_box_reorder_child (GTK_BOX (main_vbox), hbox, 0);
|
gtk_box_reorder_child (GTK_BOX (main_vbox), hbox, 0);
|
||||||
gtk_widget_show (hbox);
|
gtk_widget_show (hbox);
|
||||||
|
|
||||||
store = gtk_list_store_new (N_COLUMNS,
|
if (show_op_name == NULL)
|
||||||
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
|
store = gtk_list_store_new (N_COLUMNS,
|
||||||
|
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
|
||||||
|
|
||||||
opclasses = gimp_get_geglopclasses ();
|
opclasses = gimp_get_geglopclasses ();
|
||||||
|
|
||||||
|
|
@ -438,6 +537,9 @@ gimp_gegl_tool_dialog (GimpFilterTool *filter_tool)
|
||||||
const gchar *title;
|
const gchar *title;
|
||||||
gchar *label;
|
gchar *label;
|
||||||
|
|
||||||
|
if (show_op_name != NULL && g_strcmp0 (show_op_name, op_name) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (g_str_has_prefix (opclass->name, "gegl:"))
|
if (g_str_has_prefix (opclass->name, "gegl:"))
|
||||||
icon_name = GIMP_ICON_GEGL;
|
icon_name = GIMP_ICON_GEGL;
|
||||||
|
|
||||||
|
|
@ -451,40 +553,57 @@ gimp_gegl_tool_dialog (GimpFilterTool *filter_tool)
|
||||||
else
|
else
|
||||||
label = g_strdup (op_name);
|
label = g_strdup (op_name);
|
||||||
|
|
||||||
gtk_list_store_insert_with_values (store, NULL, -1,
|
if (store != NULL)
|
||||||
COLUMN_NAME, opclass->name,
|
gtk_list_store_insert_with_values (store, NULL, -1,
|
||||||
COLUMN_LABEL, label,
|
COLUMN_NAME, opclass->name,
|
||||||
COLUMN_ICON_NAME, icon_name,
|
COLUMN_LABEL, label,
|
||||||
-1);
|
COLUMN_ICON_NAME, icon_name,
|
||||||
|
-1);
|
||||||
|
else
|
||||||
|
gimp_operation_tool_set_operation (GIMP_OPERATION_TOOL (tool),
|
||||||
|
opclass->name,
|
||||||
|
label,
|
||||||
|
gegl_operation_class_get_key (opclass, "description"),
|
||||||
|
NULL,
|
||||||
|
icon_name,
|
||||||
|
GIMP_HELP_TOOL_GEGL);
|
||||||
|
|
||||||
g_free (label);
|
g_free (label);
|
||||||
}
|
|
||||||
|
|
||||||
|
if (show_op_name != NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
g_list_free (opclasses);
|
g_list_free (opclasses);
|
||||||
|
|
||||||
combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
|
/* We either show the full combo or we found a specific operation. */
|
||||||
g_object_unref (store);
|
g_return_if_fail (store != NULL || iter != NULL);
|
||||||
gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
|
|
||||||
gtk_widget_show (combo);
|
|
||||||
|
|
||||||
cell = gtk_cell_renderer_pixbuf_new ();
|
if (store != NULL)
|
||||||
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, FALSE);
|
{
|
||||||
gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), cell,
|
combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
|
||||||
"icon-name", COLUMN_ICON_NAME);
|
g_object_unref (store);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
|
||||||
|
gtk_widget_show (combo);
|
||||||
|
|
||||||
cell = gtk_cell_renderer_text_new ();
|
cell = gtk_cell_renderer_pixbuf_new ();
|
||||||
g_object_set (cell,
|
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, FALSE);
|
||||||
"ellipsize", PANGO_ELLIPSIZE_MIDDLE,
|
gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), cell,
|
||||||
NULL);
|
"icon-name", COLUMN_ICON_NAME);
|
||||||
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
|
|
||||||
gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), cell,
|
|
||||||
"text", COLUMN_LABEL);
|
|
||||||
|
|
||||||
g_signal_connect (combo, "changed",
|
cell = gtk_cell_renderer_text_new ();
|
||||||
G_CALLBACK (gimp_gegl_tool_operation_changed),
|
g_object_set (cell,
|
||||||
tool);
|
"ellipsize", PANGO_ELLIPSIZE_MIDDLE,
|
||||||
|
NULL);
|
||||||
|
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
|
||||||
|
gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), cell,
|
||||||
|
"text", COLUMN_LABEL);
|
||||||
|
|
||||||
tool->operation_combo = combo;
|
g_signal_connect (combo, "changed",
|
||||||
|
G_CALLBACK (gimp_gegl_tool_operation_changed),
|
||||||
|
tool);
|
||||||
|
|
||||||
|
tool->operation_combo = combo;
|
||||||
|
}
|
||||||
|
|
||||||
tool->description_label = gtk_label_new ("");
|
tool->description_label = gtk_label_new ("");
|
||||||
gtk_label_set_line_wrap (GTK_LABEL (tool->description_label), TRUE);
|
gtk_label_set_line_wrap (GTK_LABEL (tool->description_label), TRUE);
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,8 @@ struct _GimpGeglTool
|
||||||
struct _GimpGeglToolClass
|
struct _GimpGeglToolClass
|
||||||
{
|
{
|
||||||
GimpOperationToolClass parent_class;
|
GimpOperationToolClass parent_class;
|
||||||
|
|
||||||
|
GHashTable *generated_ops;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue