app: add the gradient editor submenu and a new concept of GimpRadioAction's…

… group name.

The gradient editor submenu add 2 submenus with changing names. It was using
again bogus actions: "gradient-editor-blending-func" and
"gradient-editor-coloring-type" do nothing except for being used as name
holders.

Instead I add the concept of group name for GimpRadioAction-s and when I use a
radio action attribute as <submenu>, this submenu will use the group name (and
sync with it, if it changes).
This commit is contained in:
Jehan 2023-02-28 13:51:09 +01:00
parent b1f022f144
commit 2335e14d59
6 changed files with 285 additions and 22 deletions

View file

@ -32,6 +32,7 @@
#include "widgets/gimpactiongroup.h"
#include "widgets/gimpgradienteditor.h"
#include "widgets/gimphelp-ids.h"
#include "widgets/gimpradioaction.h"
#include "data-editor-commands.h"
#include "gradient-editor-actions.h"
@ -60,6 +61,9 @@ static const GimpActionEntry gradient_editor_actions[] =
{ "gradient-editor-save-right-color", GIMP_ICON_DOCUMENT_SAVE,
NC_("gradient-editor-action", "Sa_ve Right Color To") },
/* TODO GMenu: remove these 2 bogus actions once old style XML menu files are
* deleted.
*/
{ "gradient-editor-blending-func", NULL, "blending-function" },
{ "gradient-editor-coloring-type", NULL, "coloring-type" },
@ -577,6 +581,9 @@ gradient_editor_actions_update (GimpActionGroup *group,
gimp_action_group_set_action_color (group, action, (color), (set_label))
#define SET_LABEL(action,label) \
gimp_action_group_set_action_label (group, action, (label))
#define SET_GROUP_LABEL(action,label) \
gimp_radio_action_set_group_label (GIMP_RADIO_ACTION (gimp_action_group_get_action (group, action)), \
label)
#define SET_SENSITIVE(action,condition) \
gimp_action_group_set_action_sensitive (group, action, (condition) != 0, NULL)
#define SET_VISIBLE(action,condition) \
@ -780,10 +787,10 @@ gradient_editor_actions_update (GimpActionGroup *group,
if (! selection)
{
SET_LABEL ("gradient-editor-blending-func",
_("_Blending Function for Segment"));
SET_LABEL ("gradient-editor-coloring-type",
_("Coloring _Type for Segment"));
SET_GROUP_LABEL ("gradient-editor-blending-linear",
_("_Blending Function for Segment"));
SET_GROUP_LABEL ("gradient-editor-coloring-rgb",
_("Coloring _Type for Segment"));
SET_LABEL ("gradient-editor-flip",
_("_Flip Segment"));
@ -802,10 +809,10 @@ gradient_editor_actions_update (GimpActionGroup *group,
}
else
{
SET_LABEL ("gradient-editor-blending-func",
_("_Blending Function for Selection"));
SET_LABEL ("gradient-editor-coloring-type",
_("Coloring _Type for Selection"));
SET_GROUP_LABEL ("gradient-editor-blending-linear",
_("_Blending Function for Selection"));
SET_GROUP_LABEL ("gradient-editor-coloring-rgb",
_("Coloring _Type for Selection"));
SET_LABEL ("gradient-editor-flip",
_("_Flip Selection"));

View file

@ -75,6 +75,9 @@ static void gimp_menu_shell_radio_item_toggled (GtkWidget *i
static void gimp_menu_shell_action_activate (GtkMenuItem *item,
GimpAction *action);
static void gimp_menu_shell_notify_group_label (GimpRadioAction *action,
const GParamSpec *pspec,
GtkMenuItem *item);
static void gimp_menu_shell_toggle_action_changed (GimpAction *action,
GVariant *value G_GNUC_UNUSED,
GtkCheckMenuItem *item);
@ -391,6 +394,15 @@ gimp_menu_shell_action_activate (GtkMenuItem *item,
gimp_action_activate (action);
}
static void
gimp_menu_shell_notify_group_label (GimpRadioAction *action,
const GParamSpec *pspec,
GtkMenuItem *item)
{
gtk_menu_item_set_use_underline (item, TRUE);
gtk_menu_item_set_label (item, gimp_radio_action_get_group_label (action));
}
static void
gimp_menu_shell_toggle_action_changed (GimpAction *action,
/* Unused because this is used for 2 signals
@ -509,6 +521,45 @@ gimp_menu_shell_append_model (GimpMenuShell *shell,
gtk_container_add (GTK_CONTAINER (shell), item);
gtk_widget_show (item);
}
else if (submenu != NULL && label == NULL)
{
GApplication *app;
GAction *action;
const gchar *group_label;
GtkWidget *subcontainer;
GtkWidget *item;
group = NULL;
g_return_if_fail (action_name != NULL);
app = priv->manager->gimp->app;
action = g_action_map_lookup_action (G_ACTION_MAP (app), action_name + 4);
/* As a special case, when a submenu has no label, we expect it to
* have an action attribute, which must be for a radio action. In such
* a case, we'll use the radio actions' group label as submenu title.
* See e.g.: menus/gradient-editor-menu.ui
*/
g_return_if_fail (GIMP_IS_RADIO_ACTION (action));
group_label = gimp_radio_action_get_group_label (GIMP_RADIO_ACTION (action));
item = gtk_menu_item_new_with_mnemonic (group_label);
g_signal_connect_object (action, "notify::group-label",
G_CALLBACK (gimp_menu_shell_notify_group_label),
item, 0);
gtk_container_add (GTK_CONTAINER (shell), item);
subcontainer = gimp_menu_new (priv->manager);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), subcontainer);
gimp_menu_shell_append_model (GIMP_MENU_SHELL (subcontainer), submenu);
gtk_widget_show (subcontainer);
g_tree_insert (priv->submenus,
gimp_menu_shell_make_canonical_path (group_label),
subcontainer);
}
else if (submenu != NULL)
{
GtkWidget *subcontainer;

View file

@ -49,17 +49,21 @@ enum
PROP_0 = GIMP_ACTION_PROP_LAST,
PROP_VALUE,
PROP_GROUP,
PROP_GROUP_LABEL,
PROP_CURRENT_VALUE
};
struct _GimpRadioActionPrivate
{
GSList *group;
gchar *group_label;
gint value;
};
static void gimp_radio_action_g_action_iface_init (GActionInterface *iface);
static void gimp_radio_action_finalize (GObject *object);
static void gimp_radio_action_get_property (GObject *object,
guint prop_id,
GValue *value,
@ -97,6 +101,7 @@ gimp_radio_action_class_init (GimpRadioActionClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpToggleActionClass *toggle_class = GIMP_TOGGLE_ACTION_CLASS (klass);
object_class->finalize = gimp_radio_action_finalize;
object_class->get_property = gimp_radio_action_get_property;
object_class->set_property = gimp_radio_action_set_property;
@ -133,6 +138,19 @@ gimp_radio_action_class_init (GimpRadioActionClass *klass)
"The radio action whose group this action belongs to.",
GIMP_TYPE_RADIO_ACTION,
GIMP_PARAM_WRITABLE));
/**
* GimpRadioAction:group-label:
*
* Sets the group label. It will be common to all actions in a same group.
*/
g_object_class_install_property (object_class, PROP_GROUP_LABEL,
g_param_spec_string ("group-label",
"Group string",
"The label for all the radio action in the group this action belongs to.",
NULL,
GIMP_PARAM_WRITABLE |
G_PARAM_EXPLICIT_NOTIFY));
/**
* GimpRadioAction:value:
*
@ -165,9 +183,22 @@ gimp_radio_action_init (GimpRadioAction *action)
{
action->priv = gimp_radio_action_get_instance_private (action);
action->priv->group = NULL;
action->priv->group_label = NULL;
gimp_action_init (GIMP_ACTION (action));
}
static void
gimp_radio_action_finalize (GObject *object)
{
GimpRadioAction *radio = GIMP_RADIO_ACTION (object);
g_free (radio->priv->group_label);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gimp_radio_action_get_property (GObject *object,
guint prop_id,
@ -185,6 +216,10 @@ gimp_radio_action_get_property (GObject *object,
g_value_set_int (value,
gimp_radio_action_get_current_value (action));
break;
case PROP_GROUP_LABEL:
g_value_set_string (value,
gimp_radio_action_get_group_label (action));
break;
default:
gimp_action_get_property (object, prop_id, value, pspec);
@ -219,6 +254,9 @@ gimp_radio_action_set_property (GObject *object,
}
}
break;
case PROP_GROUP_LABEL:
gimp_radio_action_set_group_label (action, g_value_get_string (value));
break;
case PROP_CURRENT_VALUE:
gimp_radio_action_set_current_value (action,
g_value_get_int (value));
@ -350,11 +388,14 @@ gimp_radio_action_set_group (GimpRadioAction *action,
}
action->priv->group = g_slist_prepend (group, action);
g_clear_pointer (&action->priv->group_label, g_free);
if (group)
{
GSList *slist;
action->priv->group_label = g_strdup (GIMP_RADIO_ACTION (group->data)->priv->group_label);
for (slist = action->priv->group; slist; slist = slist->next)
{
GimpRadioAction *tmp_action = slist->data;
@ -366,6 +407,37 @@ gimp_radio_action_set_group (GimpRadioAction *action,
{
gimp_toggle_action_set_active (GIMP_TOGGLE_ACTION (action), TRUE);
}
g_object_notify (G_OBJECT (action), "group-label");
}
void
gimp_radio_action_set_group_label (GimpRadioAction *action,
const gchar *label)
{
GSList *slist;
g_return_if_fail (GIMP_IS_RADIO_ACTION (action));
for (slist = action->priv->group; slist; slist = slist->next)
{
GimpRadioAction *tmp_action = slist->data;
g_clear_pointer (&tmp_action->priv->group_label, g_free);
if (label != NULL)
tmp_action->priv->group_label = g_strdup (label);
g_object_notify (G_OBJECT (tmp_action), "group-label");
}
}
const gchar *
gimp_radio_action_get_group_label (GimpRadioAction *action)
{
g_return_val_if_fail (GIMP_IS_RADIO_ACTION (action), NULL);
return action->priv->group_label;
}
gint

View file

@ -50,23 +50,26 @@ struct _GimpRadioActionClass
};
GType gimp_radio_action_get_type (void) G_GNUC_CONST;
GType gimp_radio_action_get_type (void) G_GNUC_CONST;
GimpAction * gimp_radio_action_new (const gchar *name,
const gchar *label,
const gchar *tooltip,
const gchar *icon_name,
const gchar *help_id,
gint value,
GimpContext *context);
GimpAction * gimp_radio_action_new (const gchar *name,
const gchar *label,
const gchar *tooltip,
const gchar *icon_name,
const gchar *help_id,
gint value,
GimpContext *context);
GSList * gimp_radio_action_get_group (GimpRadioAction *action);
void gimp_radio_action_set_group (GimpRadioAction *action,
GSList *group);
GSList * gimp_radio_action_get_group (GimpRadioAction *action);
void gimp_radio_action_set_group (GimpRadioAction *action,
GSList *group);
void gimp_radio_action_set_group_label (GimpRadioAction *action,
const gchar *label);
const gchar * gimp_radio_action_get_group_label (GimpRadioAction *action);
gint gimp_radio_action_get_current_value (GimpRadioAction *action);
void gimp_radio_action_set_current_value (GimpRadioAction *action,
gint current_value);
gint gimp_radio_action_get_current_value (GimpRadioAction *action);
void gimp_radio_action_set_current_value (GimpRadioAction *action,
gint current_value);
#endif /* __GIMP_RADIO_ACTION_H__ */

View file

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<interface>
<menu id="/gradient-editor-popup">
<submenu>
<attribute name="label" translatable="yes" context="gradient-editor-action">Gradient Editor Menu</attribute>
<attribute name="icon">gimp-tool-gradient</attribute>
<submenu>
<attribute name="label" translatable="yes" context="gradient-editor-action">Left Color Type</attribute>
<item><attribute name="action">app.gradient-editor-left-color-fixed</attribute></item>
<item><attribute name="action">app.gradient-editor-left-color-foreground</attribute></item>
<item><attribute name="action">app.gradient-editor-left-color-foreground-transparent</attribute></item>
<item><attribute name="action">app.gradient-editor-left-color-background</attribute></item>
<item><attribute name="action">app.gradient-editor-left-color-background-transparent</attribute></item>
</submenu>
<item><attribute name="action">app.gradient-editor-left-color</attribute></item>
<submenu>
<attribute name="label" translatable="yes" context="gradient-editor-action">_Load Left Color From</attribute>
<item><attribute name="action">app.gradient-editor-load-left-left-neighbor</attribute></item>
<item><attribute name="action">app.gradient-editor-load-left-right-endpoint</attribute></item>
<item><attribute name="action">app.gradient-editor-load-left-fg</attribute></item>
<item><attribute name="action">app.gradient-editor-load-left-bg</attribute></item>
<section>
<item><attribute name="action">app.gradient-editor-load-left-01</attribute></item>
<item><attribute name="action">app.gradient-editor-load-left-02</attribute></item>
<item><attribute name="action">app.gradient-editor-load-left-03</attribute></item>
<item><attribute name="action">app.gradient-editor-load-left-04</attribute></item>
<item><attribute name="action">app.gradient-editor-load-left-05</attribute></item>
<item><attribute name="action">app.gradient-editor-load-left-06</attribute></item>
<item><attribute name="action">app.gradient-editor-load-left-07</attribute></item>
<item><attribute name="action">app.gradient-editor-load-left-08</attribute></item>
<item><attribute name="action">app.gradient-editor-load-left-09</attribute></item>
<item><attribute name="action">app.gradient-editor-load-left-10</attribute></item>
</section>
</submenu>
<submenu>
<attribute name="label" translatable="yes" context="gradient-editor-action">_Save Left Color To</attribute>
<item><attribute name="action">app.gradient-editor-save-left-01</attribute></item>
<item><attribute name="action">app.gradient-editor-save-left-02</attribute></item>
<item><attribute name="action">app.gradient-editor-save-left-03</attribute></item>
<item><attribute name="action">app.gradient-editor-save-left-04</attribute></item>
<item><attribute name="action">app.gradient-editor-save-left-05</attribute></item>
<item><attribute name="action">app.gradient-editor-save-left-06</attribute></item>
<item><attribute name="action">app.gradient-editor-save-left-07</attribute></item>
<item><attribute name="action">app.gradient-editor-save-left-08</attribute></item>
<item><attribute name="action">app.gradient-editor-save-left-09</attribute></item>
<item><attribute name="action">app.gradient-editor-save-left-10</attribute></item>
</submenu>
<section>
<submenu>
<attribute name="label" translatable="yes" context="gradient-editor-action">Right Color Type</attribute>
<item><attribute name="action">app.gradient-editor-right-color-fixed</attribute></item>
<item><attribute name="action">app.gradient-editor-right-color-foreground</attribute></item>
<item><attribute name="action">app.gradient-editor-right-color-foreground-transparent</attribute></item>
<item><attribute name="action">app.gradient-editor-right-color-background</attribute></item>
<item><attribute name="action">app.gradient-editor-right-color-background-transparent</attribute></item>
</submenu>
<item><attribute name="action">app.gradient-editor-right-color</attribute></item>
<submenu>
<attribute name="label" translatable="yes" context="gradient-editor-action">Load Right Color Fr_om</attribute>
<item><attribute name="action">app.gradient-editor-load-right-right-neighbor</attribute></item>
<item><attribute name="action">app.gradient-editor-load-right-left-endpoint</attribute></item>
<item><attribute name="action">app.gradient-editor-load-right-fg</attribute></item>
<item><attribute name="action">app.gradient-editor-load-right-bg</attribute></item>
<section>
<item><attribute name="action">app.gradient-editor-load-right-01</attribute></item>
<item><attribute name="action">app.gradient-editor-load-right-02</attribute></item>
<item><attribute name="action">app.gradient-editor-load-right-03</attribute></item>
<item><attribute name="action">app.gradient-editor-load-right-04</attribute></item>
<item><attribute name="action">app.gradient-editor-load-right-05</attribute></item>
<item><attribute name="action">app.gradient-editor-load-right-06</attribute></item>
<item><attribute name="action">app.gradient-editor-load-right-07</attribute></item>
<item><attribute name="action">app.gradient-editor-load-right-08</attribute></item>
<item><attribute name="action">app.gradient-editor-load-right-09</attribute></item>
<item><attribute name="action">app.gradient-editor-load-right-10</attribute></item>
</section>
</submenu>
<submenu>
<attribute name="label" translatable="yes" context="gradient-editor-action">Sa_ve Right Color To</attribute>
<item><attribute name="action">app.gradient-editor-save-right-01</attribute></item>
<item><attribute name="action">app.gradient-editor-save-right-02</attribute></item>
<item><attribute name="action">app.gradient-editor-save-right-03</attribute></item>
<item><attribute name="action">app.gradient-editor-save-right-04</attribute></item>
<item><attribute name="action">app.gradient-editor-save-right-05</attribute></item>
<item><attribute name="action">app.gradient-editor-save-right-06</attribute></item>
<item><attribute name="action">app.gradient-editor-save-right-07</attribute></item>
<item><attribute name="action">app.gradient-editor-save-right-08</attribute></item>
<item><attribute name="action">app.gradient-editor-save-right-09</attribute></item>
<item><attribute name="action">app.gradient-editor-save-right-10</attribute></item>
</submenu>
</section>
<section>
<submenu>
<!-- Special trick: when a submenu has a radio action attribute, its label will be the group label. -->
<attribute name="action">app.gradient-editor-blending-linear</attribute>
<item><attribute name="action">app.gradient-editor-blending-linear</attribute></item>
<item><attribute name="action">app.gradient-editor-blending-curved</attribute></item>
<item><attribute name="action">app.gradient-editor-blending-sine</attribute></item>
<item><attribute name="action">app.gradient-editor-blending-sphere-increasing</attribute></item>
<item><attribute name="action">app.gradient-editor-blending-sphere-decreasing</attribute></item>
<item><attribute name="action">app.gradient-editor-blending-step</attribute></item>
<item><attribute name="action">app.gradient-editor-blending-varies</attribute></item>
</submenu>
<submenu>
<!-- Special trick: when a submenu has a radio action attribute, its label will be the group label. -->
<attribute name="action">app.gradient-editor-coloring-rgb</attribute>
<item><attribute name="action">app.gradient-editor-coloring-rgb</attribute></item>
<item><attribute name="action">app.gradient-editor-coloring-hsv-ccw</attribute></item>
<item><attribute name="action">app.gradient-editor-coloring-hsv-cw</attribute></item>
<item><attribute name="action">app.gradient-editor-coloring-varies</attribute></item>
</submenu>
</section>
<section>
<item><attribute name="action">app.gradient-editor-flip</attribute></item>
<item><attribute name="action">app.gradient-editor-replicate</attribute></item>
<item><attribute name="action">app.gradient-editor-split-midpoint</attribute></item>
<item><attribute name="action">app.gradient-editor-split-uniform</attribute></item>
<item><attribute name="action">app.gradient-editor-delete</attribute></item>
<item><attribute name="action">app.gradient-editor-recenter</attribute></item>
<item><attribute name="action">app.gradient-editor-redistribute</attribute></item>
</section>
<section>
<item><attribute name="action">app.gradient-editor-blend-color</attribute></item>
<item><attribute name="action">app.gradient-editor-blend-opacity</attribute></item>
</section>
<item><attribute name="action">app.gradient-editor-edit-active</attribute></item>
</submenu>
</menu>
</interface>

View file

@ -48,6 +48,7 @@ ui_menus_files = files(
'dynamics-menu.ui',
'error-console-menu.ui',
'fonts-menu.ui',
'gradient-editor-menu.ui',
'gradients-menu.ui',
'images-menu.ui',
'layers-menu.ui',