app: GimpRadioAction is now a subclass of GimpRadioAction.

We now completely got rid of all GtkToggleAction and GtkRadioAction code in the
whole of GIMP!
This commit is contained in:
Jehan 2023-02-26 19:02:34 +01:00
parent a813f82252
commit 9f1fd64a41
9 changed files with 386 additions and 299 deletions

View File

@ -38,6 +38,7 @@
#include "widgets/gimpcolordialog.h"
#include "widgets/gimpdock.h"
#include "widgets/gimpdialogfactory.h"
#include "widgets/gimptoggleaction.h"
#include "widgets/gimpuimanager.h"
#include "widgets/gimpwidgets-utils.h"
#include "widgets/gimpwindowstrategy.h"
@ -295,7 +296,7 @@ view_zoom_other_cmd_callback (GimpAction *action,
* view_actions_set_zoom(), also this is really a GtkToggleAction
* NOT a GimpToggleAction
*/
if (gtk_toggle_action_get_active ((GtkToggleAction *) action) &&
if (gimp_toggle_action_get_active (GIMP_TOGGLE_ACTION (action)) &&
shell->other_scale != gimp_zoom_model_get_factor (shell->zoom))
{
gimp_display_shell_scale_dialog (shell);

View File

@ -26,6 +26,7 @@
#include "widgets/gimpactiongroup.h"
#include "widgets/gimphelp-ids.h"
#include "widgets/gimpradioaction.h"
#include "widgets/gimpwidgets-utils.h"
#include "actions.h"
@ -246,7 +247,7 @@ window_actions_display_closed (GdkDisplay *display,
{
GSList *radio_group;
radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (action));
radio_group = gimp_radio_action_get_group (GIMP_RADIO_ACTION (action));
if (radio_group->data == (gpointer) action)
radio_group = radio_group->next;

View File

@ -45,7 +45,6 @@
enum
{
ACTIVATE,
CHANGE_STATE,
ACCELS_CHANGED,
LAST_SIGNAL
};
@ -113,15 +112,6 @@ gimp_action_default_init (GimpActionInterface *iface)
G_TYPE_NONE, 1,
G_TYPE_VARIANT);
action_signals[CHANGE_STATE] =
g_signal_new ("gimp-change-state",
G_TYPE_FROM_INTERFACE (iface),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpActionInterface, change_state),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
G_TYPE_VARIANT);
action_signals[ACCELS_CHANGED] =
g_signal_new ("accels-changed",
G_TYPE_FROM_INTERFACE (iface),
@ -249,7 +239,7 @@ gimp_action_emit_change_state (GimpAction *action,
if (value)
g_variant_ref_sink (value);
g_signal_emit (action, action_signals[CHANGE_STATE], 0, value);
g_signal_emit_by_name (action, "change-state", value);
if (value)
g_variant_unref (value);

View File

@ -453,9 +453,9 @@ gimp_action_group_add_toggle_actions (GimpActionGroup *group,
for (i = 0; i < n_entries; i++)
{
GtkToggleAction *action;
const gchar *label;
const gchar *tooltip = NULL;
GimpAction *action;
const gchar *label;
const gchar *tooltip = NULL;
if (! gimp_action_group_check_unique_action (group, entries[i].name))
continue;
@ -482,7 +482,7 @@ gimp_action_group_add_toggle_actions (GimpActionGroup *group,
entries[i].is_active);
if (entries[i].callback)
g_signal_connect (action, "gimp-change-state",
g_signal_connect (action, "change-state",
G_CALLBACK (entries[i].callback),
group->user_data);
@ -503,17 +503,17 @@ gimp_action_group_add_radio_actions (GimpActionGroup *group,
gint value,
GimpActionCallback callback)
{
GtkRadioAction *first_action = NULL;
GimpContext *context = gimp_get_user_context (group->gimp);
gint i;
GimpAction *first_action = NULL;
GimpContext *context = gimp_get_user_context (group->gimp);
gint i;
g_return_val_if_fail (GIMP_IS_ACTION_GROUP (group), NULL);
for (i = 0; i < n_entries; i++)
{
GtkRadioAction *action;
const gchar *label;
const gchar *tooltip = NULL;
GimpAction *action;
const gchar *label;
const gchar *tooltip = NULL;
if (! gimp_action_group_check_unique_action (group, entries[i].name))
continue;
@ -540,21 +540,20 @@ gimp_action_group_add_radio_actions (GimpActionGroup *group,
if (i == 0)
first_action = action;
gtk_radio_action_set_group (action, radio_group);
radio_group = gtk_radio_action_get_group (action);
gimp_radio_action_set_group (GIMP_RADIO_ACTION (action), radio_group);
radio_group = gimp_radio_action_get_group (GIMP_RADIO_ACTION (action));
if (value == entries[i].value)
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
gimp_toggle_action_set_active (GIMP_TOGGLE_ACTION (action), TRUE);
gimp_action_group_add_action_with_accel (group, GIMP_ACTION (action),
entries[i].accelerator);
gimp_action_group_add_action_with_accel (group, action, entries[i].accelerator);
g_signal_emit (group, signals[ACTION_ADDED], 0, action);
g_object_unref (action);
}
if (callback && first_action)
g_signal_connect (first_action, "gimp-change-state",
g_signal_connect (first_action, "change-state",
G_CALLBACK (callback),
group->user_data);
@ -890,15 +889,12 @@ gimp_action_group_set_action_active (GimpActionGroup *group,
return;
}
if (GTK_IS_TOGGLE_ACTION (action))
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
active ? TRUE : FALSE);
else if (GIMP_IS_TOGGLE_ACTION (action))
if (GIMP_IS_TOGGLE_ACTION (action))
gimp_toggle_action_set_active (GIMP_TOGGLE_ACTION (action),
active ? TRUE : FALSE);
else
g_warning ("%s: Unable to set \"active\" of action "
"which is neither a GtkToggleAction or GimpToggleAction: %s",
"which is not a GimpToggleAction: %s",
G_STRFUNC, action_name);
}

View File

@ -354,11 +354,7 @@ gimp_menu_shell_radio_item_toggled (GtkWidget *item,
{
gboolean active = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item));
/* TODO: when we remove GtkAction dependency, GimpRadioAction should become a
* child of GimpToggleAction, and therefore, we'll be able to use
* gimp_toggle_action_set_active().
*/
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), active);
gimp_toggle_action_set_active (GIMP_TOGGLE_ACTION (action), active);
}
static void
@ -380,13 +376,7 @@ gimp_menu_shell_toggle_action_changed (GimpAction *action,
gboolean active;
action_name = g_strdup (gtk_actionable_get_action_name (GTK_ACTIONABLE (item)));
/* TODO: use gimp_toggle_action_get_active() when GimpToggleAction and
* GimpRadioAction become direct parent of each other.
*/
if (GIMP_IS_TOGGLE_ACTION (action))
active = gimp_toggle_action_get_active (GIMP_TOGGLE_ACTION (action));
else
active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
active = gimp_toggle_action_get_active (GIMP_TOGGLE_ACTION (action));
/* Make sure we don't activate the action. */
gtk_actionable_set_action_name (GTK_ACTIONABLE (item), NULL);
@ -606,24 +596,11 @@ gimp_menu_shell_add_action (GimpMenuShell *shell,
action_label = gimp_action_get_label (GIMP_ACTION (action));
g_return_if_fail (action_label != NULL);
if (GIMP_IS_TOGGLE_ACTION (action))
{
item = gtk_check_menu_item_new_with_mnemonic (action_label);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
gimp_toggle_action_get_active (GIMP_TOGGLE_ACTION (action)));
if (group)
*group = NULL;
g_signal_connect (action, "gimp-change-state",
G_CALLBACK (gimp_menu_shell_toggle_action_changed),
item);
}
else if (GIMP_IS_RADIO_ACTION (action))
if (GIMP_IS_RADIO_ACTION (action))
{
item = gtk_radio_menu_item_new_with_mnemonic_from_widget (group ? *group : NULL, action_label);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
/* TODO: see comment in gimp_menu_radio_item_toggled(). */
gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
gimp_toggle_action_get_active (GIMP_TOGGLE_ACTION (action)));
if (group)
*group = GTK_RADIO_MENU_ITEM (item);
@ -631,7 +608,19 @@ gimp_menu_shell_add_action (GimpMenuShell *shell,
g_signal_connect (item, "toggled",
G_CALLBACK (gimp_menu_shell_radio_item_toggled),
action);
g_signal_connect (action, "gimp-change-state",
g_signal_connect (action, "change-state",
G_CALLBACK (gimp_menu_shell_toggle_action_changed),
item);
}
else if (GIMP_IS_TOGGLE_ACTION (action))
{
item = gtk_check_menu_item_new_with_mnemonic (action_label);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
gimp_toggle_action_get_active (GIMP_TOGGLE_ACTION (action)));
if (group)
*group = NULL;
g_signal_connect (action, "change-state",
G_CALLBACK (gimp_menu_shell_toggle_action_changed),
item);
}

View File

@ -4,6 +4,7 @@
* gimpradioaction.c
* Copyright (C) 2004 Michael Natterer <mitch@gimp.org>
* Copyright (C) 2008 Sven Neumann <sven@gimp.org>
* Copyright (C) 2023 Jehan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -33,59 +34,56 @@
#include "gimpaction-history.h"
#include "gimpradioaction.h"
/**
* GimpRadioAction:
*
* An action which is part of a group of radio actions. It is guaranteed that at
* most one action is active in the group.
*
* The "state" in any of the actions of the group is the @value associated to
* the active action of the group.
*/
enum
{
PROP_0,
PROP_ENABLED = GIMP_ACTION_PROP_LAST + 1,
PROP_PARAMETER_TYPE,
PROP_STATE_TYPE,
PROP_STATE
PROP_0 = GIMP_ACTION_PROP_LAST,
PROP_VALUE,
PROP_GROUP,
PROP_CURRENT_VALUE
};
struct _GimpRadioActionPrivate
{
GVariantType *parameter_type;
GVariant *state;
GVariant *state_hint;
gboolean state_set_already;
GSList *group;
gint value;
};
static void gimp_radio_action_g_action_iface_init (GActionInterface *iface);
static void gimp_radio_action_g_action_iface_init (GActionInterface *iface);
static void gimp_radio_action_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void gimp_radio_action_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_radio_action_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void gimp_radio_action_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_radio_action_change_state (GAction *action,
GVariant *value);
static gboolean gimp_radio_action_get_enabled (GAction *action);
static const GVariantType *
gimp_radio_action_get_parameter_type (GAction *action);
static const GVariantType *
gimp_radio_action_get_state_type (GAction *action);
gimp_radio_action_get_state_type (GAction *action);
static GVariant *
gimp_radio_action_get_state (GAction *action);
static GVariant *
gimp_radio_action_get_state_hint (GAction *action);
gimp_radio_action_get_state (GAction *action);
static void gimp_radio_action_change_state (GAction *action,
GVariant *value);
static void gimp_radio_action_set_state (GimpAction *gimp_action,
GVariant *value);
static void gimp_radio_action_activate (GAction *action,
GVariant *parameter);
static void gimp_radio_action_g_activate (GAction *action,
GVariant *parameter);
static void gimp_radio_action_changed (GtkRadioAction *action,
GtkRadioAction *current);
static gboolean gimp_radio_action_toggle (GimpToggleAction *action);
G_DEFINE_TYPE_WITH_CODE (GimpRadioAction, gimp_radio_action,
GTK_TYPE_RADIO_ACTION,
GIMP_TYPE_TOGGLE_ACTION,
G_ADD_PRIVATE (GimpRadioAction)
G_IMPLEMENT_INTERFACE (G_TYPE_ACTION, gimp_radio_action_g_action_iface_init)
G_IMPLEMENT_INTERFACE (GIMP_TYPE_ACTION, NULL))
@ -96,89 +94,76 @@ G_DEFINE_TYPE_WITH_CODE (GimpRadioAction, gimp_radio_action,
static void
gimp_radio_action_class_init (GimpRadioActionClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkRadioActionClass *radio_class = GTK_RADIO_ACTION_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpToggleActionClass *toggle_class = GIMP_TOGGLE_ACTION_CLASS (klass);
object_class->get_property = gimp_radio_action_get_property;
object_class->set_property = gimp_radio_action_set_property;
object_class->get_property = gimp_radio_action_get_property;
object_class->set_property = gimp_radio_action_set_property;
radio_class->changed = gimp_radio_action_changed;
toggle_class->toggle = gimp_radio_action_toggle;
gimp_action_install_properties (object_class);
/**
* GimpRadioAction:enabled:
* GimpRadioAction:value:
*
* If @action is currently enabled.
*
* If the action is disabled then calls to g_action_activate() and
* g_action_change_state() have no effect.
* The value is an arbitrary integer which can be used as a convenient way to
* determine which action in the group is currently active in an ::activate
* signal handler.
* See gimp_radio_action_get_current_value() for convenient ways to get and
* set this property.
**/
g_object_class_install_property (object_class, PROP_ENABLED,
g_param_spec_boolean ("enabled",
"Enabled",
"If the action can be activated",
TRUE,
GIMP_PARAM_READWRITE));
/**
* GimpRadioAction:parameter-type:
*
* The type of the parameter that must be given when activating the
* action.
**/
g_object_class_install_property (object_class, PROP_PARAMETER_TYPE,
g_param_spec_boxed ("parameter-type",
"Parameter Type",
"The type of GVariant passed to activate()",
G_TYPE_VARIANT_TYPE,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
/**
* GimpRadioAction:state-type:
*
* The #GVariantType of the state that the action has, or %NULL if the
* action is stateless.
**/
g_object_class_install_property (object_class, PROP_STATE_TYPE,
g_param_spec_boxed ("state-type",
"State Type",
"The type of the state kept by the action",
G_TYPE_VARIANT_TYPE,
GIMP_PARAM_READABLE));
g_object_class_install_property (object_class, PROP_VALUE,
g_param_spec_int ("value",
"Value",
"The value returned by gimp_radio_action_get_current_value() when this action is the current action of its group.",
G_MININT,
G_MAXINT,
0,
GIMP_PARAM_READWRITE));
/**
* GimpRadioAction:state:
* GimpRadioAction:group:
*
* The state of the action, or %NULL if the action is stateless.
* Sets a new group for a radio action.
*/
g_object_class_install_property (object_class, PROP_GROUP,
g_param_spec_object ("group",
"Group",
"The radio action whose group this action belongs to.",
GIMP_TYPE_RADIO_ACTION,
GIMP_PARAM_WRITABLE));
/**
* GimpRadioAction:value:
*
* The value property of the currently active member of the group to which
* this action belongs.
**/
g_object_class_install_property (object_class, PROP_STATE,
g_param_spec_variant ("state",
"State",
"The state the action is in",
G_VARIANT_TYPE_ANY,
NULL,
GIMP_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class, PROP_CURRENT_VALUE,
g_param_spec_int ("current-value",
"Current value",
"The value property of the currently active member of the group to which this action belongs.",
G_MININT,
G_MAXINT,
0,
GIMP_PARAM_READWRITE));
}
static void
gimp_radio_action_g_action_iface_init (GActionInterface *iface)
{
iface->get_name = (const gchar* (*) (GAction*)) gimp_action_get_name;
iface->activate = gimp_radio_action_g_activate;
iface->get_name = (const gchar* (*) (GAction*)) gimp_action_get_name;
iface->activate = gimp_radio_action_activate;
iface->change_state = gimp_radio_action_change_state;
iface->get_enabled = gimp_radio_action_get_enabled;
iface->get_parameter_type = gimp_radio_action_get_parameter_type;
iface->get_state_type = gimp_radio_action_get_state_type;
iface->get_state = gimp_radio_action_get_state;
iface->get_state_hint = gimp_radio_action_get_state_hint;
iface->change_state = gimp_radio_action_change_state;
iface->get_state_type = gimp_radio_action_get_state_type;
iface->get_state = gimp_radio_action_get_state;
}
static void
gimp_radio_action_init (GimpRadioAction *action)
{
action->priv = gimp_radio_action_get_instance_private (action);
action->priv->state_set_already = FALSE;
action->priv = gimp_radio_action_get_instance_private (action);
gimp_action_init (GIMP_ACTION (action));
}
@ -193,17 +178,12 @@ gimp_radio_action_get_property (GObject *object,
switch (prop_id)
{
case PROP_ENABLED:
g_value_set_boolean (value, gimp_radio_action_get_enabled (G_ACTION (action)));
case PROP_VALUE:
g_value_set_int (value, action->priv->value);
break;
case PROP_PARAMETER_TYPE:
g_value_set_boxed (value, gimp_radio_action_get_parameter_type (G_ACTION (action)));
break;
case PROP_STATE_TYPE:
g_value_set_boxed (value, gimp_radio_action_get_state_type (G_ACTION (action)));
break;
case PROP_STATE:
g_value_take_variant (value, gimp_radio_action_get_state (G_ACTION (action)));
case PROP_CURRENT_VALUE:
g_value_set_int (value,
gimp_radio_action_get_current_value (action));
break;
default:
@ -222,30 +202,26 @@ gimp_radio_action_set_property (GObject *object,
switch (prop_id)
{
case PROP_ENABLED:
gimp_action_set_sensitive (GIMP_ACTION (action),
g_value_get_boolean (value), NULL);
case PROP_VALUE:
action->priv->value = g_value_get_int (value);
break;
case PROP_PARAMETER_TYPE:
action->priv->parameter_type = g_value_dup_boxed (value);
break;
case PROP_STATE:
/* The first time we see this (during construct) we should just
* take the state as it was handed to us.
*
* After that, we should make sure we go through the same checks
* as the C API.
*/
if (!action->priv->state_set_already)
{
action->priv->state = g_value_dup_variant (value);
action->priv->state_set_already = TRUE;
}
else
{
gimp_radio_action_set_state (GIMP_ACTION (action), g_value_get_variant (value));
}
case PROP_GROUP:
{
GimpRadioAction *arg;
GSList *slist = NULL;
if (G_VALUE_HOLDS_OBJECT (value))
{
arg = GIMP_RADIO_ACTION (g_value_get_object (value));
if (arg)
slist = gimp_radio_action_get_group (arg);
gimp_radio_action_set_group (action, slist);
}
}
break;
case PROP_CURRENT_VALUE:
gimp_radio_action_set_current_value (action,
g_value_get_int (value));
break;
default:
@ -258,108 +234,68 @@ static void
gimp_radio_action_change_state (GAction *action,
GVariant *value)
{
gimp_radio_action_set_state (GIMP_ACTION (action), value);
}
g_return_if_fail (GIMP_IS_ACTION (action));
g_return_if_fail (value != NULL);
g_return_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE_INT32));
static gboolean
gimp_radio_action_get_enabled (GAction *action)
{
return gimp_action_is_sensitive (GIMP_ACTION (action), NULL);
}
static const GVariantType *
gimp_radio_action_get_parameter_type (GAction *action)
{
GimpRadioAction *raction = GIMP_RADIO_ACTION (action);
return raction->priv->parameter_type;
gimp_radio_action_set_current_value (GIMP_RADIO_ACTION (action),
g_variant_get_int32 (value));
}
static const GVariantType *
gimp_radio_action_get_state_type (GAction *action)
{
GimpRadioAction *raction = GIMP_RADIO_ACTION (action);
if (raction->priv->state != NULL)
return g_variant_get_type (raction->priv->state);
else
return NULL;
return G_VARIANT_TYPE_INT32;
}
static GVariant *
gimp_radio_action_get_state (GAction *action)
{
GimpRadioAction *raction = GIMP_RADIO_ACTION (action);
GimpRadioAction *radio;
GVariant *state;
return raction->priv->state ? g_variant_ref (raction->priv->state) : NULL;
}
g_return_val_if_fail (GIMP_IS_RADIO_ACTION (action), NULL);
static GVariant *
gimp_radio_action_get_state_hint (GAction *action)
{
GimpRadioAction *raction = GIMP_RADIO_ACTION (action);
radio = GIMP_RADIO_ACTION (action);
if (raction->priv->state_hint != NULL)
return g_variant_ref (raction->priv->state_hint);
else
return NULL;
state = g_variant_new_int32 (gimp_radio_action_get_current_value (radio));
return g_variant_ref_sink (state);
}
static void
gimp_radio_action_set_state (GimpAction *gimp_action,
GVariant *value)
gimp_radio_action_activate (GAction *action,
GVariant *parameter)
{
GimpRadioAction *action;
const GVariantType *state_type;
GimpRadioAction *radio;
g_return_if_fail (GIMP_IS_ACTION (gimp_action));
g_return_if_fail (value != NULL);
g_return_if_fail (GIMP_IS_RADIO_ACTION (action));
action = GIMP_RADIO_ACTION (gimp_action);
radio = GIMP_RADIO_ACTION (action);
state_type = action->priv->state ? g_variant_get_type (action->priv->state) : NULL;
gimp_radio_action_set_current_value (radio, radio->priv->value);
}
g_return_if_fail (state_type != NULL);
g_return_if_fail (g_variant_is_of_type (value, state_type));
static gboolean
gimp_radio_action_toggle (GimpToggleAction *action)
{
gboolean active = gimp_toggle_action_get_active (action);
g_variant_ref_sink (value);
if (! action->priv->state || ! g_variant_equal (action->priv->state, value))
if (! active)
{
if (action->priv->state)
g_variant_unref (action->priv->state);
GimpRadioAction *radio = GIMP_RADIO_ACTION (action);
action->priv->state = g_variant_ref (value);
gimp_radio_action_set_current_value (radio, radio->priv->value);
g_object_notify (G_OBJECT (action), "state");
return gimp_toggle_action_get_active (action);
}
g_variant_unref (value);
}
static void
gimp_radio_action_g_activate (GAction *action,
GVariant *parameter)
{
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
gimp_action_history_action_activated (GIMP_ACTION (action));
}
static void
gimp_radio_action_changed (GtkRadioAction *action,
GtkRadioAction *current)
{
gint value = gtk_radio_action_get_current_value (action);
gimp_action_emit_change_state (GIMP_ACTION (action),
g_variant_new_int32 (value));
return FALSE;
}
/* public functions */
GtkRadioAction *
GimpAction *
gimp_radio_action_new (const gchar *name,
const gchar *label,
const gchar *tooltip,
@ -368,7 +304,7 @@ gimp_radio_action_new (const gchar *name,
gint value,
GimpContext *context)
{
GtkRadioAction *action;
GimpAction *action;
action = g_object_new (GIMP_TYPE_RADIO_ACTION,
"name", name,
@ -379,7 +315,134 @@ gimp_radio_action_new (const gchar *name,
"context", context,
NULL);
gimp_action_set_help_id (GIMP_ACTION (action), help_id);
gimp_action_set_help_id (action, help_id);
return action;
}
GSList *
gimp_radio_action_get_group (GimpRadioAction *action)
{
g_return_val_if_fail (GIMP_IS_RADIO_ACTION (action), NULL);
return action->priv->group;
}
void
gimp_radio_action_set_group (GimpRadioAction *action,
GSList *group)
{
g_return_if_fail (GIMP_IS_RADIO_ACTION (action));
g_return_if_fail (! g_slist_find (group, action));
if (action->priv->group)
{
GSList *slist;
action->priv->group = g_slist_remove (action->priv->group, action);
for (slist = action->priv->group; slist; slist = slist->next)
{
GimpRadioAction *tmp_action = slist->data;
tmp_action->priv->group = action->priv->group;
}
}
action->priv->group = g_slist_prepend (group, action);
if (group)
{
GSList *slist;
for (slist = action->priv->group; slist; slist = slist->next)
{
GimpRadioAction *tmp_action = slist->data;
tmp_action->priv->group = action->priv->group;
}
}
else
{
gimp_toggle_action_set_active (GIMP_TOGGLE_ACTION (action), TRUE);
}
}
gint
gimp_radio_action_get_current_value (GimpRadioAction *action)
{
GSList *slist;
g_return_val_if_fail (GIMP_IS_RADIO_ACTION (action), 0);
if (action->priv->group)
{
for (slist = action->priv->group; slist; slist = slist->next)
{
GimpToggleAction *toggle_action = slist->data;
if (gimp_toggle_action_get_active (toggle_action))
return GIMP_RADIO_ACTION (toggle_action)->priv->value;
}
}
return action->priv->value;
}
void
gimp_radio_action_set_current_value (GimpRadioAction *action,
gint current_value)
{
GSList *slist;
GimpToggleAction *changed1 = NULL;
GimpToggleAction *changed2 = NULL;
g_return_if_fail (GIMP_IS_RADIO_ACTION (action));
if (action->priv->group)
{
for (slist = action->priv->group; slist; slist = slist->next)
{
GimpToggleAction *toggle = slist->data;
GimpRadioAction *radio = slist->data;
if (radio->priv->value == current_value &&
! gimp_toggle_action_get_active (toggle))
{
/* Change the "active" state but don't notify the property change
* immediately. We want to notify both "active" properties
* together so that we are always in consistent state.
*/
_gimp_toggle_action_set_active (toggle, TRUE);
changed1 = toggle;
}
else if (gimp_toggle_action_get_active (toggle))
{
changed2 = toggle;
}
}
}
if (! changed1)
{
g_warning ("Radio group does not contain an action with value '%d'",
current_value);
}
else
{
if (changed2)
{
_gimp_toggle_action_set_active (changed2, FALSE);
g_object_notify (G_OBJECT (changed2), "active");
g_signal_emit_by_name (changed2, "toggled");
}
g_object_notify (G_OBJECT (changed1), "active");
for (slist = action->priv->group; slist; slist = slist->next)
{
g_object_notify (slist->data, "current-value");
gimp_action_emit_change_state (GIMP_ACTION (slist->data),
g_variant_new_int32 (current_value));
}
}
}

View File

@ -4,6 +4,7 @@
* gimpradioaction.h
* Copyright (C) 2004 Michael Natterer <mitch@gimp.org>
* Copyright (C) 2008 Sven Neumann <sven@gimp.org>
* Copyright (C) 2023 Jehan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -22,6 +23,7 @@
#ifndef __GIMP_RADIO_ACTION_H__
#define __GIMP_RADIO_ACTION_H__
#include "gimptoggleaction.h"
#define GIMP_TYPE_RADIO_ACTION (gimp_radio_action_get_type ())
#define GIMP_RADIO_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_RADIO_ACTION, GimpRadioAction))
@ -37,26 +39,34 @@ typedef struct _GimpRadioActionPrivate GimpRadioActionPrivate;
struct _GimpRadioAction
{
GtkRadioAction parent_instance;
GimpToggleAction parent_instance;
GimpRadioActionPrivate *priv;
};
struct _GimpRadioActionClass
{
GtkRadioActionClass parent_class;
GimpToggleActionClass parent_class;
};
GType gimp_radio_action_get_type (void) G_GNUC_CONST;
GType gimp_radio_action_get_type (void) G_GNUC_CONST;
GtkRadioAction * 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);
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

@ -52,27 +52,29 @@ struct _GimpToggleActionPrivate
gboolean active;
};
static void gimp_toggle_action_g_action_iface_init (GActionInterface *iface);
static void gimp_toggle_action_g_action_iface_init (GActionInterface *iface);
static void gimp_toggle_action_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void gimp_toggle_action_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_toggle_action_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void gimp_toggle_action_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static gboolean gimp_toggle_action_get_enabled (GAction *action);
static gboolean gimp_toggle_action_get_enabled (GAction *action);
static const GVariantType *
gimp_toggle_action_get_state_type (GAction *action);
gimp_toggle_action_get_state_type (GAction *action);
static GVariant *
gimp_toggle_action_get_state (GAction *action);
gimp_toggle_action_get_state (GAction *action);
static void gimp_toggle_action_g_activate (GAction *action,
GVariant *parameter);
static void gimp_toggle_action_activate (GAction *action,
GVariant *parameter);
static void gimp_toggle_action_toggle (GimpToggleAction *action);
static gboolean gimp_toggle_action_real_toggle (GimpToggleAction *action);
static void gimp_toggle_action_toggle (GimpToggleAction *action);
G_DEFINE_TYPE_WITH_CODE (GimpToggleAction, gimp_toggle_action,
@ -88,7 +90,8 @@ static guint gimp_toggle_action_signals[LAST_SIGNAL] = { 0 };
static void
gimp_toggle_action_class_init (GimpToggleActionClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpToggleActionClass *toggle_class = GIMP_TOGGLE_ACTION_CLASS (klass);
gimp_toggle_action_signals[TOGGLED] =
g_signal_new ("toggled",
@ -101,6 +104,8 @@ gimp_toggle_action_class_init (GimpToggleActionClass *klass)
object_class->get_property = gimp_toggle_action_get_property;
object_class->set_property = gimp_toggle_action_set_property;
toggle_class->toggle = gimp_toggle_action_real_toggle;
gimp_action_install_properties (object_class);
/**
@ -122,7 +127,7 @@ static void
gimp_toggle_action_g_action_iface_init (GActionInterface *iface)
{
iface->get_name = (const gchar* (*) (GAction*)) gimp_action_get_name;
iface->activate = gimp_toggle_action_g_activate;
iface->activate = gimp_toggle_action_activate;
iface->get_enabled = gimp_toggle_action_get_enabled;
iface->get_state_type = gimp_toggle_action_get_state_type;
@ -200,30 +205,42 @@ gimp_toggle_action_get_state (GAction *action)
}
static void
gimp_toggle_action_g_activate (GAction *action,
GVariant *parameter)
gimp_toggle_action_activate (GAction *action,
GVariant *parameter)
{
gimp_toggle_action_toggle (GIMP_TOGGLE_ACTION (action));
}
static void
gimp_toggle_action_toggle (GimpToggleAction *action)
static gboolean
gimp_toggle_action_real_toggle (GimpToggleAction *action)
{
gboolean value = gimp_toggle_action_get_active (action);
gimp_action_emit_change_state (GIMP_ACTION (action),
g_variant_new_boolean (! value));
action->priv->active = ! value;
g_signal_emit (action, gimp_toggle_action_signals[TOGGLED], 0);
g_object_notify (G_OBJECT (action), "state");
gimp_action_history_action_activated (GIMP_ACTION (action));
/* Toggling always works for the base class. */
return TRUE;
}
static void
gimp_toggle_action_toggle (GimpToggleAction *action)
{
if (GIMP_TOGGLE_ACTION_GET_CLASS (action)->toggle != NULL &&
GIMP_TOGGLE_ACTION_GET_CLASS (action)->toggle (action))
{
g_signal_emit (action, gimp_toggle_action_signals[TOGGLED], 0);
g_object_notify (G_OBJECT (action), "state");
gimp_action_history_action_activated (GIMP_ACTION (action));
}
}
/* public functions */
GtkToggleAction *
GimpAction *
gimp_toggle_action_new (const gchar *name,
const gchar *label,
const gchar *tooltip,
@ -231,7 +248,7 @@ gimp_toggle_action_new (const gchar *name,
const gchar *help_id,
GimpContext *context)
{
GtkToggleAction *action;
GimpAction *action;
action = g_object_new (GIMP_TYPE_TOGGLE_ACTION,
"name", name,
@ -259,3 +276,13 @@ gimp_toggle_action_get_active (GimpToggleAction *action)
{
return action->priv->active;
}
/* Protected functions. */
void
_gimp_toggle_action_set_active (GimpToggleAction *action,
gboolean active)
{
action->priv->active = active;
}

View File

@ -51,13 +51,17 @@ struct _GimpToggleActionClass
/* Signals */
void (* toggled) (GimpToggleAction *action);
void (* toggled) (GimpToggleAction *action);
/* Private methods */
gboolean (* toggle) (GimpToggleAction *action);
};
GType gimp_toggle_action_get_type (void) G_GNUC_CONST;
GtkToggleAction * gimp_toggle_action_new (const gchar *name,
GimpAction * gimp_toggle_action_new (const gchar *name,
const gchar *label,
const gchar *tooltip,
const gchar *icon_name,
@ -69,4 +73,10 @@ void gimp_toggle_action_set_active (GimpToggleAction *action,
gboolean gimp_toggle_action_get_active (GimpToggleAction *action);
/* Protected functions */
void _gimp_toggle_action_set_active (GimpToggleAction *action,
gboolean active);
#endif /* __GIMP_TOGGLE_ACTION_H__ */