Compare commits

...

9 Commits

Author SHA1 Message Date
Alexander Larsson
5f62ba2693 Convert the "group" property on radio widgets to a GtkRadioGroup
The various radio widgets all have a write-only "group" property
of the same type as the widget. This let you set the group in a
bindable way, but is quite weird when we have a real GtkRadioGroup
object.

We convert this to a real read-write GtkRadioGroup type. Additionally
we make it CONSTRUCT and use it in the various constructors instead
of hand-rolling the set_group call.
2010-11-05 14:25:12 +01:00
Alexander Larsson
f03481c4f2 Remove gtk_radio_..._join_group methods that were added for 3.0
These versions were added in order to have a bindable version of
_set_group, but with GtkRadioGroup _set_group is already bindable,
so we remove it.
2010-11-05 14:25:12 +01:00
Alexander Larsson
5324e62ab0 Deprecate gtk_radio_..._from_widget
The _from_widget versions of the radio group constructors are really
only useful in e.g. bindings where the old GSList group did not bind
well. They have no use now that we have a proper GtkRagioGroup object.
2010-11-05 14:25:12 +01:00
Alexander Larsson
9631d82de8 Replace use of gtk_radio_..._from_widget with GtkRadioGroup use
The _from_widget stuff is really not needed when we have a proper
group object.
2010-11-05 14:25:12 +01:00
Alexander Larsson
8e0cb2ad30 Convert GtkRadioAction to use GtkRadioGroup 2010-11-05 14:25:12 +01:00
Alexander Larsson
67ced1e28a Convert GtkRadioMenuItem to GtkRadioGroup 2010-11-05 14:25:12 +01:00
Alexander Larsson
f26f253118 Update the general docs and examples to use GtkRadioGroup 2010-11-05 14:25:12 +01:00
Alexander Larsson
ac63f89763 Convert GtkRadioButton and GtkRadioToolButton to use GtkRadioGroup
This changes the API by changing the GSList group in the constructors
and the _set_group/_get_group calls to a GtkRadioGroup.
2010-11-05 14:25:12 +01:00
Alexander Larsson
ba3590f770 Add GtkRadioGroup 2010-11-05 14:25:12 +01:00
29 changed files with 942 additions and 652 deletions

View File

@@ -35,7 +35,7 @@ create_menu (gint depth,
{ {
GtkWidget *menu; GtkWidget *menu;
GtkWidget *menuitem; GtkWidget *menuitem;
GSList *group; GtkRadioGroup *group;
char buf[32]; char buf[32];
int i, j; int i, j;
@@ -52,11 +52,11 @@ create_menu (gint depth,
gtk_widget_show (menuitem); gtk_widget_show (menuitem);
} }
group = gtk_radio_group_new ();
for (i = 0, j = 1; i < 5; i++, j++) for (i = 0, j = 1; i < 5; i++, j++)
{ {
sprintf (buf, "item %2d - %d", depth, j); sprintf (buf, "item %2d - %d", depth, j);
menuitem = gtk_radio_menu_item_new_with_label (group, buf); menuitem = gtk_radio_menu_item_new_with_label (group, buf);
group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem); gtk_widget_show (menuitem);

View File

@@ -690,7 +690,7 @@ load_stock_items (GtkToolPalette *palette)
static void static void
load_toggle_items (GtkToolPalette *palette) load_toggle_items (GtkToolPalette *palette)
{ {
GSList *toggle_group = NULL; GtkRadioGroup *toggle_group;
GtkToolItem *item; GtkToolItem *item;
GtkWidget *group; GtkWidget *group;
char *label; char *label;
@@ -699,6 +699,7 @@ load_toggle_items (GtkToolPalette *palette)
group = gtk_tool_item_group_new ("Radio Item"); group = gtk_tool_item_group_new ("Radio Item");
gtk_container_add (GTK_CONTAINER (palette), group); gtk_container_add (GTK_CONTAINER (palette), group);
toggle_group = gtk_radio_group_new ();
for (i = 1; i <= 10; ++i) for (i = 1; i <= 10; ++i)
{ {
label = g_strdup_printf ("#%d", i); label = g_strdup_printf ("#%d", i);
@@ -707,7 +708,6 @@ load_toggle_items (GtkToolPalette *palette)
g_free (label); g_free (label);
gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1); gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1);
toggle_group = gtk_radio_tool_button_get_group (GTK_RADIO_TOOL_BUTTON (item));
} }
} }

View File

@@ -221,13 +221,15 @@ create_radio (void)
GtkWidget *widget; GtkWidget *widget;
GtkWidget *radio; GtkWidget *radio;
GtkWidget *align; GtkWidget *align;
GtkRadioGroup *group;
widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3); widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3);
radio = gtk_radio_button_new_with_mnemonic (NULL, "Radio Button _One"); group = gtk_radio_group_new ();
radio = gtk_radio_button_new_with_mnemonic (group, "Radio Button _One");
gtk_box_pack_start (GTK_BOX (widget), radio, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (widget), radio, FALSE, FALSE, 0);
radio = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (radio), "Radio Button _Two"); radio = gtk_radio_button_new_with_mnemonic (group, "Radio Button _Two");
gtk_box_pack_start (GTK_BOX (widget), radio, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (widget), radio, FALSE, FALSE, 0);
radio = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (radio), "Radio Button T_hree"); radio = gtk_radio_button_new_with_mnemonic (group, "Radio Button T_hree");
gtk_box_pack_start (GTK_BOX (widget), radio, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (widget), radio, FALSE, FALSE, 0);
align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
gtk_container_add (GTK_CONTAINER (align), widget); gtk_container_add (GTK_CONTAINER (align), widget);

View File

@@ -18,7 +18,7 @@ int main( int argc,
GtkWidget *box2; GtkWidget *box2;
GtkWidget *button; GtkWidget *button;
GtkWidget *separator; GtkWidget *separator;
GSList *group; GtkRadioGroup *group;
gtk_init (&argc, &argv); gtk_init (&argc, &argv);
@@ -40,18 +40,17 @@ int main( int argc,
gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
gtk_widget_show (box2); gtk_widget_show (box2);
button = gtk_radio_button_new_with_label (NULL, "button1"); group = gtk_radio_group_new ();
button = gtk_radio_button_new_with_label (group, "button1");
gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
gtk_widget_show (button); gtk_widget_show (button);
group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
button = gtk_radio_button_new_with_label (group, "button2"); button = gtk_radio_button_new_with_label (group, "button2");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
gtk_widget_show (button); gtk_widget_show (button);
button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (button), button = gtk_radio_button_new_with_label (group, "button3");
"button3");
gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
gtk_widget_show (button); gtk_widget_show (button);

View File

@@ -258,6 +258,7 @@ gtk_public_h_sources = \
gtkprogressbar.h \ gtkprogressbar.h \
gtkradioaction.h \ gtkradioaction.h \
gtkradiobutton.h \ gtkradiobutton.h \
gtkradiogroup.h \
gtkradiomenuitem.h \ gtkradiomenuitem.h \
gtkradiotoolbutton.h \ gtkradiotoolbutton.h \
gtkrange.h \ gtkrange.h \
@@ -378,6 +379,7 @@ gtk_private_h_sources = \
gtkprintoperation-private.h\ gtkprintoperation-private.h\
gtkprintutils.h \ gtkprintutils.h \
gtkprivate.h \ gtkprivate.h \
gtkradiogroupprivate.h \
gtkrbtree.h \ gtkrbtree.h \
gtkrecentchooserdefault.h \ gtkrecentchooserdefault.h \
gtkrecentchooserprivate.h \ gtkrecentchooserprivate.h \
@@ -530,6 +532,7 @@ gtk_base_c_sources = \
gtkprogressbar.c \ gtkprogressbar.c \
gtkradioaction.c \ gtkradioaction.c \
gtkradiobutton.c \ gtkradiobutton.c \
gtkradiogroup.c \
gtkradiomenuitem.c \ gtkradiomenuitem.c \
gtkradiotoolbutton.c \ gtkradiotoolbutton.c \
gtkrange.c \ gtkrange.c \

View File

@@ -1304,11 +1304,12 @@ gtk_action_group_add_radio_actions_full (GtkActionGroup *action_group
* gtk_action_group_add_..._actions_full() functions. * gtk_action_group_add_..._actions_full() functions.
*/ */
guint i; guint i;
GSList *group = NULL; GtkRadioGroup *radio_group = NULL;
GtkRadioAction *first_action = NULL; GtkRadioAction *first_action = NULL;
g_return_if_fail (GTK_IS_ACTION_GROUP (action_group)); g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
radio_group = gtk_radio_group_new ();
for (i = 0; i < n_entries; i++) for (i = 0; i < n_entries; i++)
{ {
GtkRadioAction *action; GtkRadioAction *action;
@@ -1338,8 +1339,7 @@ gtk_action_group_add_radio_actions_full (GtkActionGroup *action_group
if (i == 0) if (i == 0)
first_action = action; first_action = action;
gtk_radio_action_set_group (action, group); gtk_radio_action_set_group (action, radio_group);
group = gtk_radio_action_get_group (action);
if (value == entries[i].value) if (value == entries[i].value)
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);

View File

@@ -580,15 +580,15 @@ gtk_im_multicontext_append_menuitems (GtkIMMulticontext *context,
GtkIMMulticontextPrivate *priv = context->priv; GtkIMMulticontextPrivate *priv = context->priv;
const GtkIMContextInfo **contexts; const GtkIMContextInfo **contexts;
guint n_contexts, i; guint n_contexts, i;
GSList *group = NULL; GtkRadioGroup *group;
GtkWidget *menuitem, *system_menuitem; GtkWidget *menuitem, *system_menuitem;
const char *system_context_id; const char *system_context_id;
group = gtk_radio_group_new ();
system_context_id = _gtk_im_module_get_default_context_id (priv->client_window); system_context_id = _gtk_im_module_get_default_context_id (priv->client_window);
system_menuitem = menuitem = gtk_radio_menu_item_new_with_label (group, C_("input method menu", "System")); system_menuitem = menuitem = gtk_radio_menu_item_new_with_label (group, C_("input method menu", "System"));
if (!priv->context_id_aux) if (!priv->context_id_aux)
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem), TRUE); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem), TRUE);
group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
g_object_set_data (G_OBJECT (menuitem), I_("gtk-context-id"), NULL); g_object_set_data (G_OBJECT (menuitem), I_("gtk-context-id"), NULL);
g_signal_connect (menuitem, "activate", G_CALLBACK (activate_cb), context); g_signal_connect (menuitem, "activate", G_CALLBACK (activate_cb), context);
@@ -602,7 +602,6 @@ gtk_im_multicontext_append_menuitems (GtkIMMulticontext *context,
g_signal_connect (menuitem, "activate", G_CALLBACK (activate_cb), context); g_signal_connect (menuitem, "activate", G_CALLBACK (activate_cb), context);
gtk_widget_show (menuitem); gtk_widget_show (menuitem);
gtk_menu_shell_append (menushell, menuitem); gtk_menu_shell_append (menushell, menuitem);
group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
menuitem = gtk_separator_menu_item_new (); menuitem = gtk_separator_menu_item_new ();
gtk_widget_show (menuitem); gtk_widget_show (menuitem);
@@ -683,8 +682,6 @@ gtk_im_multicontext_append_menuitems (GtkIMMulticontext *context,
g_free (text); g_free (text);
} }
group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
g_object_set_data (G_OBJECT (menuitem), I_("gtk-context-id"), g_object_set_data (G_OBJECT (menuitem), I_("gtk-context-id"),
(char *)contexts[i]->context_id); (char *)contexts[i]->context_id);
g_signal_connect (menuitem, "activate", g_signal_connect (menuitem, "activate",

View File

@@ -549,7 +549,7 @@ gtk_mount_operation_ask_password (GMountOperation *mount_op,
{ {
GtkWidget *anon_box; GtkWidget *anon_box;
GtkWidget *choice; GtkWidget *choice;
GSList *group; GtkRadioGroup *group;
anon_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); anon_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
gtk_box_pack_start (GTK_BOX (vbox), anon_box, gtk_box_pack_start (GTK_BOX (vbox), anon_box,
@@ -622,7 +622,7 @@ gtk_mount_operation_ask_password (GMountOperation *mount_op,
{ {
GtkWidget *choice; GtkWidget *choice;
GtkWidget *remember_box; GtkWidget *remember_box;
GSList *group; GtkRadioGroup *group;
GPasswordSave password_save; GPasswordSave password_save;
remember_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); remember_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
@@ -650,7 +650,6 @@ gtk_mount_operation_ask_password (GMountOperation *mount_op,
G_CALLBACK (remember_button_toggled), operation); G_CALLBACK (remember_button_toggled), operation);
gtk_box_pack_start (GTK_BOX (remember_box), choice, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (remember_box), choice, FALSE, FALSE, 0);
group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (choice));
choice = gtk_radio_button_new_with_mnemonic (group, _("Remember _forever")); choice = gtk_radio_button_new_with_mnemonic (group, _("Remember _forever"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (choice), gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (choice),
password_save == G_PASSWORD_SAVE_PERMANENTLY); password_save == G_PASSWORD_SAVE_PERMANENTLY);

View File

@@ -860,7 +860,7 @@ page_name_func (GtkCellLayout *cell_layout,
} }
static GtkWidget * static GtkWidget *
create_radio_button (GSList *group, create_radio_button (GtkRadioGroup *group,
const gchar *stock_id) const gchar *stock_id)
{ {
GtkWidget *radio_button, *image, *label, *hbox; GtkWidget *radio_button, *image, *label, *hbox;

View File

@@ -645,12 +645,12 @@ alternative_set (GtkWidget *box,
(gpointer) value); (gpointer) value);
} }
static GSList * static GtkRadioGroup *
alternative_append (GtkWidget *box, alternative_append (GtkWidget *box,
const gchar *label, const gchar *label,
const gchar *value, const gchar *value,
GtkPrinterOptionWidget *widget, GtkPrinterOptionWidget *widget,
GSList *group) GtkRadioGroup *group)
{ {
GtkWidget *button; GtkWidget *button;
@@ -672,7 +672,7 @@ construct_widgets (GtkPrinterOptionWidget *widget)
GtkPrinterOption *source; GtkPrinterOption *source;
char *text; char *text;
int i; int i;
GSList *group; GtkRadioGroup *group;
source = priv->source; source = priv->source;

View File

@@ -32,6 +32,7 @@
#include "gtkradioaction.h" #include "gtkradioaction.h"
#include "gtkradiomenuitem.h" #include "gtkradiomenuitem.h"
#include "gtkradiogroupprivate.h"
#include "gtktoggletoolbutton.h" #include "gtktoggletoolbutton.h"
#include "gtkintl.h" #include "gtkintl.h"
#include "gtkprivate.h" #include "gtkprivate.h"
@@ -49,7 +50,7 @@
struct _GtkRadioActionPrivate struct _GtkRadioActionPrivate
{ {
GSList *group; GtkRadioGroup *group;
gint value; gint value;
}; };
@@ -133,9 +134,9 @@ gtk_radio_action_class_init (GtkRadioActionClass *klass)
PROP_GROUP, PROP_GROUP,
g_param_spec_object ("group", g_param_spec_object ("group",
P_("Group"), P_("Group"),
P_("The radio action whose group this action belongs to."), P_("The radio group this action belongs to."),
GTK_TYPE_RADIO_ACTION, GTK_TYPE_RADIO_GROUP,
GTK_PARAM_WRITABLE)); GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
/** /**
* GtkRadioAction:current-value: * GtkRadioAction:current-value:
@@ -184,7 +185,7 @@ gtk_radio_action_init (GtkRadioAction *action)
GTK_TYPE_RADIO_ACTION, GTK_TYPE_RADIO_ACTION,
GtkRadioActionPrivate); GtkRadioActionPrivate);
action->private_data->group = g_slist_prepend (NULL, action); action->private_data->group = NULL;
action->private_data->value = 0; action->private_data->value = 0;
gtk_toggle_action_set_draw_as_radio (GTK_TOGGLE_ACTION (action), TRUE); gtk_toggle_action_set_draw_as_radio (GTK_TOGGLE_ACTION (action), TRUE);
@@ -230,20 +231,18 @@ static void
gtk_radio_action_finalize (GObject *object) gtk_radio_action_finalize (GObject *object)
{ {
GtkRadioAction *action; GtkRadioAction *action;
GSList *tmp_list; GtkRadioActionPrivate *priv;
action = GTK_RADIO_ACTION (object); action = GTK_RADIO_ACTION (object);
priv = action->private_data;
action->private_data->group = g_slist_remove (action->private_data->group, action); if (priv->group)
tmp_list = action->private_data->group;
while (tmp_list)
{ {
GtkRadioAction *tmp_action = tmp_list->data; _gtk_radio_group_remove_item (priv->group, object);
tmp_list = tmp_list->next; /* this action is no longer in the group */
tmp_action->private_data->group = action->private_data->group; g_object_unref (priv->group);
priv->group = NULL;
} }
G_OBJECT_CLASS (gtk_radio_action_parent_class)->finalize (object); G_OBJECT_CLASS (gtk_radio_action_parent_class)->finalize (object);
@@ -266,16 +265,10 @@ gtk_radio_action_set_property (GObject *object,
break; break;
case PROP_GROUP: case PROP_GROUP:
{ {
GtkRadioAction *arg; GtkRadioGroup *group;
GSList *slist = NULL;
if (G_VALUE_HOLDS_OBJECT (value)) group = g_value_get_object (value);
{ gtk_radio_action_set_group (radio_action, group);
arg = GTK_RADIO_ACTION (g_value_get_object (value));
if (arg)
slist = gtk_radio_action_get_group (arg);
gtk_radio_action_set_group (radio_action, slist);
}
} }
break; break;
case PROP_CURRENT_VALUE: case PROP_CURRENT_VALUE:
@@ -300,6 +293,9 @@ gtk_radio_action_get_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_GROUP:
g_value_set_object (value, gtk_radio_action_get_group (radio_action));
break;
case PROP_VALUE: case PROP_VALUE:
g_value_set_int (value, radio_action->private_data->value); g_value_set_int (value, radio_action->private_data->value);
break; break;
@@ -313,70 +309,78 @@ gtk_radio_action_get_property (GObject *object,
} }
} }
static void
gtk_radio_action_ensure_group (GtkRadioAction *radio_action)
{
GtkRadioActionPrivate *priv = radio_action->private_data;
if (priv->group == NULL)
{
priv->group = g_object_ref_sink (gtk_radio_group_new ());
_gtk_radio_group_add_item (priv->group, G_OBJECT (radio_action));
}
}
static void static void
gtk_radio_action_activate (GtkAction *action) gtk_radio_action_activate (GtkAction *action)
{ {
GtkRadioAction *radio_action; GtkRadioAction *radio_action;
GtkToggleAction *toggle_action; GtkToggleAction *toggle_action;
GtkRadioActionPrivate *priv;
GtkToggleAction *tmp_action; GtkToggleAction *tmp_action;
GSList *tmp_list; GObject *active_item;
GSList *list, *l;
gboolean active; gboolean active;
gint toggled;
radio_action = GTK_RADIO_ACTION (action); radio_action = GTK_RADIO_ACTION (action);
toggle_action = GTK_TOGGLE_ACTION (action); toggle_action = GTK_TOGGLE_ACTION (action);
priv = radio_action->private_data;
gtk_radio_action_ensure_group (radio_action);
toggled = FALSE;
active = gtk_toggle_action_get_active (toggle_action); active = gtk_toggle_action_get_active (toggle_action);
if (active) if (active)
{ {
tmp_list = radio_action->private_data->group; active_item = gtk_radio_group_get_active_item (priv->group);
while (tmp_list) if (action != GTK_ACTION (active_item))
{ {
tmp_action = tmp_list->data; toggled = TRUE;
tmp_list = tmp_list->next; _gtk_toggle_action_set_active (toggle_action, !active);
if (gtk_toggle_action_get_active (tmp_action) &&
(tmp_action != toggle_action))
{
_gtk_toggle_action_set_active (toggle_action, !active);
break;
}
} }
g_object_notify (G_OBJECT (action), "active"); g_object_notify (G_OBJECT (action), "active");
} }
else else
{ {
toggled = TRUE;
_gtk_toggle_action_set_active (toggle_action, !active); _gtk_toggle_action_set_active (toggle_action, !active);
g_object_notify (G_OBJECT (action), "active"); g_object_notify (G_OBJECT (action), "active");
tmp_list = radio_action->private_data->group; active_item = gtk_radio_group_get_active_item (priv->group);
while (tmp_list) _gtk_radio_group_set_active_item (priv->group, G_OBJECT (action));
if (active_item != G_OBJECT (action))
_gtk_action_emit_activate (GTK_ACTION (active_item));
list = gtk_radio_group_get_items (priv->group);
for (l = list; l != NULL; l = l->next)
{ {
tmp_action = tmp_list->data; tmp_action = l->data;
tmp_list = tmp_list->next;
if (gtk_toggle_action_get_active (tmp_action) && g_object_notify (G_OBJECT (tmp_action), "current-value");
(tmp_action != toggle_action))
{
_gtk_action_emit_activate (GTK_ACTION (tmp_action));
break;
}
}
tmp_list = radio_action->private_data->group;
while (tmp_list)
{
tmp_action = tmp_list->data;
tmp_list = tmp_list->next;
g_object_notify (G_OBJECT (tmp_action), "current-value");
g_signal_emit (tmp_action, radio_action_signals[CHANGED], 0, radio_action); g_signal_emit (tmp_action, radio_action_signals[CHANGED], 0, radio_action);
} }
g_slist_free (list);
_gtk_radio_group_emit_active_changed (priv->group);
} }
gtk_toggle_action_toggled (toggle_action); if (toggled)
gtk_toggle_action_toggled (toggle_action);
} }
static GtkWidget * static GtkWidget *
@@ -391,40 +395,29 @@ create_menu_item (GtkAction *action)
* gtk_radio_action_get_group: * gtk_radio_action_get_group:
* @action: the action object * @action: the action object
* *
* Returns the list representing the radio group for this object. * Retrieves the radio group this object is part of.
* Note that the returned list is only valid until the next change
* to the group.
* *
* A common way to set up a group of radio group is the following: * Return value: (transfer none): a #GtkRadioGroup
* |[ * containing all the radio buttons in the same group
* GSList *group = NULL; * as @radio_action.
* GtkRadioAction *action;
*
* while (/&ast; more actions to add &ast;/)
* {
* action = gtk_radio_action_new (...);
*
* gtk_radio_action_set_group (action, group);
* group = gtk_radio_action_get_group (action);
* }
* ]|
*
* Returns: (element-type GtkRadioAction) (transfer none): the list representing the radio group for this object
* *
* Since: 2.4 * Since: 2.4
*/ */
GSList * GtkRadioGroup *
gtk_radio_action_get_group (GtkRadioAction *action) gtk_radio_action_get_group (GtkRadioAction *action)
{ {
g_return_val_if_fail (GTK_IS_RADIO_ACTION (action), NULL); g_return_val_if_fail (GTK_IS_RADIO_ACTION (action), NULL);
gtk_radio_action_ensure_group (action);
return action->private_data->group; return action->private_data->group;
} }
/** /**
* gtk_radio_action_set_group: * gtk_radio_action_set_group:
* @action: the action object * @action: the action object
* @group: (element-type GtkRadioAction): a list representing a radio group * @group: (allow-none): an existing #GtkRadioGroup or %NULL
* to remove the radio button from its current group
* *
* Sets the radio group for the radio action object. * Sets the radio group for the radio action object.
* *
@@ -432,97 +425,31 @@ gtk_radio_action_get_group (GtkRadioAction *action)
*/ */
void void
gtk_radio_action_set_group (GtkRadioAction *action, gtk_radio_action_set_group (GtkRadioAction *action,
GSList *group) GtkRadioGroup *group)
{ {
GtkRadioActionPrivate *priv;
gboolean is_active;
g_return_if_fail (GTK_IS_RADIO_ACTION (action)); g_return_if_fail (GTK_IS_RADIO_ACTION (action));
g_return_if_fail (!g_slist_find (group, action));
if (action->private_data->group) priv = action->private_data;
{
GSList *slist;
action->private_data->group = g_slist_remove (action->private_data->group, action); if (priv->group == group)
return;
for (slist = action->private_data->group; slist; slist = slist->next) if (group == NULL)
{ group = gtk_radio_group_new ();
GtkRadioAction *tmp_action = slist->data;
tmp_action->private_data->group = action->private_data->group; if (priv->group)
} _gtk_radio_group_remove_item (priv->group, G_OBJECT (action));
}
action->private_data->group = g_slist_prepend (group, action); priv->group = g_object_ref_sink (group);
_gtk_radio_group_add_item (group, G_OBJECT (action));
if (group) is_active = gtk_radio_group_get_active_item (group) == G_OBJECT (action);
{ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), is_active);
GSList *slist; if (is_active)
_gtk_radio_group_emit_active_changed (group);
for (slist = action->private_data->group; slist; slist = slist->next)
{
GtkRadioAction *tmp_action = slist->data;
tmp_action->private_data->group = action->private_data->group;
}
}
else
{
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
}
}
/**
* gtk_radio_action_join_group:
* @action: the action object
* @group_source: (allow-none): a radio action object whos group we are
* joining, or %NULL to remove the radio action from its group
*
* Joins a radio action object to the group of another radio action object.
*
* Use this in language bindings instead of the gtk_radio_action_get_group()
* and gtk_radio_action_set_group() methods
*
* A common way to set up a group of radio actions is the following:
* |[
* GtkRadioAction *action;
* GtkRadioAction *last_action;
*
* while (/&ast; more actions to add &ast;/)
* {
* action = gtk_radio_action_new (...);
*
* gtk_radio_action_join_group (action, last_action);
* last_action = action;
* }
* ]|
*
* Since: 3.0
*/
void
gtk_radio_action_join_group (GtkRadioAction *action,
GtkRadioAction *group_source)
{
g_return_if_fail (GTK_IS_RADIO_ACTION (action));
g_return_if_fail (group_source == NULL || GTK_IS_RADIO_ACTION (group_source));
if (group_source)
{
GSList *group;
group = gtk_radio_action_get_group (group_source);
if (!group)
{
/* if we are not already part of a group we need to set up a new one
and then get the newly created group */
gtk_radio_action_set_group (group_source, NULL);
group = gtk_radio_action_get_group (group_source);
}
gtk_radio_action_set_group (action, group);
}
else
{
gtk_radio_action_set_group (action, NULL);
}
} }
/** /**
@@ -539,22 +466,15 @@ gtk_radio_action_join_group (GtkRadioAction *action,
gint gint
gtk_radio_action_get_current_value (GtkRadioAction *action) gtk_radio_action_get_current_value (GtkRadioAction *action)
{ {
GSList *slist; GObject *active_action;
g_return_val_if_fail (GTK_IS_RADIO_ACTION (action), 0); g_return_val_if_fail (GTK_IS_RADIO_ACTION (action), 0);
if (action->private_data->group) gtk_radio_action_ensure_group (action);
{
for (slist = action->private_data->group; slist; slist = slist->next)
{
GtkToggleAction *toggle_action = slist->data;
if (gtk_toggle_action_get_active (toggle_action)) active_action = gtk_radio_group_get_active_item (action->private_data->group);
return GTK_RADIO_ACTION (toggle_action)->private_data->value;
}
}
return action->private_data->value; return GTK_RADIO_ACTION (active_action)->private_data->value;
} }
/** /**
@@ -571,15 +491,16 @@ void
gtk_radio_action_set_current_value (GtkRadioAction *action, gtk_radio_action_set_current_value (GtkRadioAction *action,
gint current_value) gint current_value)
{ {
GSList *slist; GSList *slist, *l;
g_return_if_fail (GTK_IS_RADIO_ACTION (action)); g_return_if_fail (GTK_IS_RADIO_ACTION (action));
if (action->private_data->group) if (action->private_data->group)
{ {
for (slist = action->private_data->group; slist; slist = slist->next) slist = gtk_radio_group_get_items (action->private_data->group);
for (l = slist; l; l = l->next)
{ {
GtkRadioAction *radio_action = slist->data; GtkRadioAction *radio_action = l->data;
if (radio_action->private_data->value == current_value) if (radio_action->private_data->value == current_value)
{ {
@@ -588,6 +509,7 @@ gtk_radio_action_set_current_value (GtkRadioAction *action,
return; return;
} }
} }
g_slist_free (slist);
} }
if (action->private_data->value == current_value) if (action->private_data->value == current_value)

View File

@@ -36,6 +36,7 @@
#define __GTK_RADIO_ACTION_H__ #define __GTK_RADIO_ACTION_H__
#include <gtk/gtktoggleaction.h> #include <gtk/gtktoggleaction.h>
#include <gtk/gtkradiogroup.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@@ -77,11 +78,9 @@ GtkRadioAction *gtk_radio_action_new (const gchar *name,
const gchar *tooltip, const gchar *tooltip,
const gchar *stock_id, const gchar *stock_id,
gint value); gint value);
GSList *gtk_radio_action_get_group (GtkRadioAction *action); GtkRadioGroup *gtk_radio_action_get_group (GtkRadioAction *action);
void gtk_radio_action_set_group (GtkRadioAction *action, void gtk_radio_action_set_group (GtkRadioAction *action,
GSList *group); GtkRadioGroup *group);
void gtk_radio_action_join_group (GtkRadioAction *action,
GtkRadioAction *group_source);
gint gtk_radio_action_get_current_value (GtkRadioAction *action); gint gtk_radio_action_get_current_value (GtkRadioAction *action);
void gtk_radio_action_set_current_value (GtkRadioAction *action, void gtk_radio_action_set_current_value (GtkRadioAction *action,
gint current_value); gint current_value);

View File

@@ -28,6 +28,7 @@
#include "gtklabel.h" #include "gtklabel.h"
#include "gtkmarshalers.h" #include "gtkmarshalers.h"
#include "gtkradiobutton.h" #include "gtkradiobutton.h"
#include "gtkradiogroupprivate.h"
#include "gtkprivate.h" #include "gtkprivate.h"
#include "gtkintl.h" #include "gtkintl.h"
@@ -46,11 +47,10 @@
* selected, all other radio buttons in the same group are deselected. A * selected, all other radio buttons in the same group are deselected. A
* #GtkRadioButton is one way of giving the user a choice from many options. * #GtkRadioButton is one way of giving the user a choice from many options.
* *
* Radio button widgets are created with gtk_radio_button_new(), passing %NULL * Radio button widgets are created with gtk_radio_button_new(), passing in a
* as the argument if this is the first radio button in a group. In subsequent * #GtkRadioGroup created with gtk_radio_group_new() (or %NULL to automatically
* calls, the group you wish to add this button to should be passed as an * create a new group for the button). Optionally, gtk_radio_button_new_with_label()
* argument. Optionally, gtk_radio_button_new_with_label() can be used if you * can be used if you want a text label on the radio button.
* want a text label on the radio button.
* *
* Alternatively, when adding widgets to an existing group of radio buttons, * Alternatively, when adding widgets to an existing group of radio buttons,
* use gtk_radio_button_new_from_widget() with a #GtkRadioButton that already * use gtk_radio_button_new_from_widget() with a #GtkRadioButton that already
@@ -72,18 +72,21 @@
* void create_radio_buttons (void) { * void create_radio_buttons (void) {
* *
* GtkWidget *window, *radio1, *radio2, *box, *entry; * GtkWidget *window, *radio1, *radio2, *box, *entry;
* GtkRadioGroup *group;
*
* window = gtk_window_new (GTK_WINDOW_TOPLEVEL); * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
* box = gtk_box_new (GTK_ORIENTATION_VERTICAL, TRUE, 2); * box = gtk_box_new (GTK_ORIENTATION_VERTICAL, TRUE, 2);
* *
* /&ast; Create a radio button with a GtkEntry widget &ast;/ * /&ast; Create a radio button with a GtkEntry widget &ast;/
* radio1 = gtk_radio_button_new (NULL); * group = gtk_radio_group_new ();
* radio1 = gtk_radio_button_new (group);
* entry = gtk_entry_new (<!-- -->); * entry = gtk_entry_new (<!-- -->);
* gtk_container_add (GTK_CONTAINER (radio1), entry); * gtk_container_add (GTK_CONTAINER (radio1), entry);
* *
* *
* /&ast; Create a radio button with a label &ast;/ * /&ast; Create a radio button with a label &ast;/
* radio2 = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio1), * radio2 = gtk_radio_button_new_with_label (group,
* "I'm the second radio button."); * "I'm the second radio button.");
* *
* /&ast; Pack them into a box, then show all the widgets &ast;/ * /&ast; Pack them into a box, then show all the widgets &ast;/
* gtk_box_pack_start (GTK_BOX (box), radio1, TRUE, TRUE, 2); * gtk_box_pack_start (GTK_BOX (box), radio1, TRUE, TRUE, 2);
@@ -100,12 +103,14 @@
* selected button. * selected button.
* Inside the #GtkToggleButton::toggled handler, gtk_toggle_button_get_active() * Inside the #GtkToggleButton::toggled handler, gtk_toggle_button_get_active()
* can be used to determine if the button has been selected or deselected. * can be used to determine if the button has been selected or deselected.
* Additionally the #GtkRadioGroup::active-changed signal is emitted whenever
* a button is toggled, with the current active button given as an argument.
*/ */
struct _GtkRadioButtonPrivate struct _GtkRadioButtonPrivate
{ {
GSList *group; GtkRadioGroup *group;
}; };
enum { enum {
@@ -158,9 +163,9 @@ gtk_radio_button_class_init (GtkRadioButtonClass *class)
PROP_GROUP, PROP_GROUP,
g_param_spec_object ("group", g_param_spec_object ("group",
P_("Group"), P_("Group"),
P_("The radio button whose group this widget belongs to."), P_("The radio group this button belongs to."),
GTK_TYPE_RADIO_BUTTON, GTK_TYPE_RADIO_GROUP,
GTK_PARAM_WRITABLE)); GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
widget_class->destroy = gtk_radio_button_destroy; widget_class->destroy = gtk_radio_button_destroy;
widget_class->focus = gtk_radio_button_focus; widget_class->focus = gtk_radio_button_focus;
@@ -211,7 +216,7 @@ gtk_radio_button_init (GtkRadioButton *radio_button)
GTK_BUTTON (radio_button)->depress_on_activate = FALSE; GTK_BUTTON (radio_button)->depress_on_activate = FALSE;
priv->group = g_slist_prepend (NULL, radio_button); priv->group = NULL;
_gtk_button_set_depressed (GTK_BUTTON (radio_button), TRUE); _gtk_button_set_depressed (GTK_BUTTON (radio_button), TRUE);
gtk_widget_set_state (GTK_WIDGET (radio_button), GTK_STATE_ACTIVE); gtk_widget_set_state (GTK_WIDGET (radio_button), GTK_STATE_ACTIVE);
@@ -229,17 +234,11 @@ gtk_radio_button_set_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
GSList *slist; GtkRadioGroup *group;
GtkRadioButton *button;
case PROP_GROUP: case PROP_GROUP:
button = g_value_get_object (value); group = g_value_get_object (value);
gtk_radio_button_set_group (radio_button, group);
if (button)
slist = gtk_radio_button_get_group (button);
else
slist = NULL;
gtk_radio_button_set_group (radio_button, slist);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -253,19 +252,38 @@ gtk_radio_button_get_property (GObject *object,
GValue *value, GValue *value,
GParamSpec *pspec) GParamSpec *pspec)
{ {
GtkRadioButton *radio_button;
radio_button = GTK_RADIO_BUTTON (object);
switch (prop_id) switch (prop_id)
{ {
case PROP_GROUP:
g_value_set_object (value, gtk_radio_button_get_group (radio_button));
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
static void
gtk_radio_button_ensure_group (GtkRadioButton *radio_button)
{
GtkRadioButtonPrivate *priv = radio_button->priv;
if (priv->group == NULL)
{
priv->group = g_object_ref_sink (gtk_radio_group_new ());
_gtk_radio_group_add_item (priv->group, G_OBJECT (radio_button));
}
}
/** /**
* gtk_radio_button_set_group: * gtk_radio_button_set_group:
* @radio_button: a #GtkRadioButton. * @radio_button: a #GtkRadioButton.
* @group: (transfer none) (element-type GtkRadioButton): an existing radio * @group: (allow-none): an existing #GtkRadioGroup or %NULL
* button group, such as one returned from gtk_radio_button_get_group(). * to remove the radio button from its current group
* *
* Sets a #GtkRadioButton's group. It should be noted that this does not change * Sets a #GtkRadioButton's group. It should be noted that this does not change
* the layout of your interface in any way, so if you are changing the group, * the layout of your interface in any way, so if you are changing the group,
@@ -274,54 +292,41 @@ gtk_radio_button_get_property (GObject *object,
*/ */
void void
gtk_radio_button_set_group (GtkRadioButton *radio_button, gtk_radio_button_set_group (GtkRadioButton *radio_button,
GSList *group) GtkRadioGroup *group)
{ {
GtkRadioButtonPrivate *priv; GtkRadioButtonPrivate *priv;
GtkWidget *old_group_singleton = NULL; GObject *old_group_singleton = NULL;
GtkWidget *new_group_singleton = NULL; GObject *new_group_singleton;
GObject *old_group_active;
gboolean is_active;
g_return_if_fail (GTK_IS_RADIO_BUTTON (radio_button)); g_return_if_fail (GTK_IS_RADIO_BUTTON (radio_button));
g_return_if_fail (!g_slist_find (group, radio_button));
priv = radio_button->priv; priv = radio_button->priv;
if (priv->group == group)
return;
if (group == NULL)
group = gtk_radio_group_new ();
if (priv->group) if (priv->group)
{ {
GSList *slist; _gtk_radio_group_remove_item (priv->group, G_OBJECT (radio_button));
old_group_singleton = _gtk_radio_group_get_singleton (priv->group);
priv->group = g_slist_remove (priv->group, radio_button); /* Ensure some widget is active in the old group */
old_group_active = gtk_radio_group_get_active_item (priv->group);
if (old_group_active)
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (old_group_active), TRUE);
if (priv->group && !priv->group->next) g_object_unref (priv->group);
old_group_singleton = g_object_ref (priv->group->data);
for (slist = priv->group; slist; slist = slist->next)
{
GtkRadioButton *tmp_button;
tmp_button = slist->data;
tmp_button->priv->group = priv->group;
}
} }
if (group && !group->next) priv->group = g_object_ref_sink (group);
new_group_singleton = g_object_ref (group->data); new_group_singleton = _gtk_radio_group_get_singleton (group);
priv->group = g_slist_prepend (group, radio_button); _gtk_radio_group_add_item (group, G_OBJECT (radio_button));
if (group)
{
GSList *slist;
for (slist = group; slist; slist = slist->next)
{
GtkRadioButton *tmp_button;
tmp_button = slist->data;
tmp_button->priv->group = priv->group;
}
}
g_object_ref (radio_button); g_object_ref (radio_button);
@@ -338,66 +343,15 @@ gtk_radio_button_set_group (GtkRadioButton *radio_button,
g_object_unref (new_group_singleton); g_object_unref (new_group_singleton);
} }
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_button), group == NULL); is_active = gtk_radio_group_get_active_item (group) == G_OBJECT (radio_button);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_button),
is_active);
if (is_active)
_gtk_radio_group_emit_active_changed (group);
g_object_unref (radio_button); g_object_unref (radio_button);
} }
/**
* gtk_radio_button_join_group:
* @radio_button: the #GtkRadioButton object
* @group_source: (allow-none): a radio button object whos group we are
* joining, or %NULL to remove the radio button from its group
*
* Joins a #GtkRadioButton object to the group of another #GtkRadioButton object
*
* Use this in language bindings instead of the gtk_radio_button_get_group()
* and gtk_radio_button_set_group() methods
*
* A common way to set up a group of radio buttons is the following:
* |[
* GtkRadioButton *radio_button;
* GtkRadioButton *last_button;
*
* while (/&ast; more buttons to add &ast;/)
* {
* radio_button = gtk_radio_button_new (...);
*
* gtk_radio_button_join_group (radio_button, last_button);
* last_button = radio_button;
* }
* ]|
*
* Since: 3.0
*/
void
gtk_radio_button_join_group (GtkRadioButton *radio_button,
GtkRadioButton *group_source)
{
g_return_if_fail (GTK_IS_RADIO_BUTTON (radio_button));
g_return_if_fail (group_source == NULL || GTK_IS_RADIO_BUTTON (group_source));
if (group_source)
{
GSList *group;
group = gtk_radio_button_get_group (group_source);
if (!group)
{
/* if we are not already part of a group we need to set up a new one
and then get the newly created group */
gtk_radio_button_set_group (group_source, NULL);
group = gtk_radio_button_get_group (group_source);
}
gtk_radio_button_set_group (radio_button, group);
}
else
{
gtk_radio_button_set_group (radio_button, NULL);
}
}
/** /**
* gtk_radio_button_new: * gtk_radio_button_new:
* @group: an existing radio button group, or %NULL if you are creating a new group. * @group: an existing radio button group, or %NULL if you are creating a new group.
@@ -408,14 +362,11 @@ gtk_radio_button_join_group (GtkRadioButton *radio_button,
* Returns: a new radio button * Returns: a new radio button
*/ */
GtkWidget* GtkWidget*
gtk_radio_button_new (GSList *group) gtk_radio_button_new (GtkRadioGroup *group)
{ {
GtkRadioButton *radio_button; GtkRadioButton *radio_button;
radio_button = g_object_new (GTK_TYPE_RADIO_BUTTON, NULL); radio_button = g_object_new (GTK_TYPE_RADIO_BUTTON, "group", group, NULL);
if (group)
gtk_radio_button_set_group (radio_button, group);
return GTK_WIDGET (radio_button); return GTK_WIDGET (radio_button);
} }
@@ -431,16 +382,12 @@ gtk_radio_button_new (GSList *group)
* Returns: (transfer full): a new radio button. * Returns: (transfer full): a new radio button.
*/ */
GtkWidget* GtkWidget*
gtk_radio_button_new_with_label (GSList *group, gtk_radio_button_new_with_label (GtkRadioGroup *group,
const gchar *label) const gchar *label)
{ {
GtkWidget *radio_button; GtkWidget *radio_button;
radio_button = g_object_new (GTK_TYPE_RADIO_BUTTON, "label", label, NULL) ; radio_button = g_object_new (GTK_TYPE_RADIO_BUTTON, "group", group, "label", label, NULL) ;
if (group)
gtk_radio_button_set_group (GTK_RADIO_BUTTON (radio_button), group);
return radio_button; return radio_button;
} }
@@ -459,19 +406,17 @@ gtk_radio_button_new_with_label (GSList *group,
* Returns: (transfer full): a new #GtkRadioButton * Returns: (transfer full): a new #GtkRadioButton
*/ */
GtkWidget* GtkWidget*
gtk_radio_button_new_with_mnemonic (GSList *group, gtk_radio_button_new_with_mnemonic (GtkRadioGroup *group,
const gchar *label) const gchar *label)
{ {
GtkWidget *radio_button; GtkWidget *radio_button;
radio_button = g_object_new (GTK_TYPE_RADIO_BUTTON, radio_button = g_object_new (GTK_TYPE_RADIO_BUTTON,
"group", group,
"label", label, "label", label,
"use-underline", TRUE, "use-underline", TRUE,
NULL); NULL);
if (group)
gtk_radio_button_set_group (GTK_RADIO_BUTTON (radio_button), group);
return radio_button; return radio_button;
} }
@@ -488,10 +433,10 @@ gtk_radio_button_new_with_mnemonic (GSList *group,
GtkWidget* GtkWidget*
gtk_radio_button_new_from_widget (GtkRadioButton *radio_group_member) gtk_radio_button_new_from_widget (GtkRadioButton *radio_group_member)
{ {
GSList *l = NULL; GtkRadioGroup *group = NULL;
if (radio_group_member) if (radio_group_member)
l = gtk_radio_button_get_group (radio_group_member); group = gtk_radio_button_get_group (radio_group_member);
return gtk_radio_button_new (l); return gtk_radio_button_new (group);
} }
/** /**
@@ -508,10 +453,10 @@ GtkWidget*
gtk_radio_button_new_with_label_from_widget (GtkRadioButton *radio_group_member, gtk_radio_button_new_with_label_from_widget (GtkRadioButton *radio_group_member,
const gchar *label) const gchar *label)
{ {
GSList *l = NULL; GtkRadioGroup *group = NULL;
if (radio_group_member) if (radio_group_member)
l = gtk_radio_button_get_group (radio_group_member); group = gtk_radio_button_get_group (radio_group_member);
return gtk_radio_button_new_with_label (l, label); return gtk_radio_button_new_with_label (group, label);
} }
/** /**
@@ -530,10 +475,10 @@ GtkWidget*
gtk_radio_button_new_with_mnemonic_from_widget (GtkRadioButton *radio_group_member, gtk_radio_button_new_with_mnemonic_from_widget (GtkRadioButton *radio_group_member,
const gchar *label) const gchar *label)
{ {
GSList *l = NULL; GtkRadioGroup *group = NULL;
if (radio_group_member) if (radio_group_member)
l = gtk_radio_button_get_group (radio_group_member); group = gtk_radio_button_get_group (radio_group_member);
return gtk_radio_button_new_with_mnemonic (l, label); return gtk_radio_button_new_with_mnemonic (group, label);
} }
@@ -543,16 +488,17 @@ gtk_radio_button_new_with_mnemonic_from_widget (GtkRadioButton *radio_group_memb
* *
* Retrieves the group assigned to a radio button. * Retrieves the group assigned to a radio button.
* *
* Return value: (element-type GtkRadioButton) (transfer none): a linked list * Return value: (transfer none): a #GtkRadioGroup
* containing all the radio buttons in the same group * containing all the radio buttons in the same group
* as @radio_button. The returned list is owned by the radio button * as @radio_button.
* and must not be modified or freed.
*/ */
GSList* GtkRadioGroup *
gtk_radio_button_get_group (GtkRadioButton *radio_button) gtk_radio_button_get_group (GtkRadioButton *radio_button)
{ {
g_return_val_if_fail (GTK_IS_RADIO_BUTTON (radio_button), NULL); g_return_val_if_fail (GTK_IS_RADIO_BUTTON (radio_button), NULL);
gtk_radio_button_ensure_group (radio_button);
return radio_button->priv->group; return radio_button->priv->group;
} }
@@ -560,32 +506,22 @@ gtk_radio_button_get_group (GtkRadioButton *radio_button)
static void static void
gtk_radio_button_destroy (GtkWidget *widget) gtk_radio_button_destroy (GtkWidget *widget)
{ {
GtkWidget *old_group_singleton = NULL; GObject *old_group_singleton = NULL;
GtkRadioButton *radio_button = GTK_RADIO_BUTTON (widget); GtkRadioButton *radio_button = GTK_RADIO_BUTTON (widget);
GtkRadioButtonPrivate *priv = radio_button->priv; GtkRadioButtonPrivate *priv = radio_button->priv;
GtkRadioButton *tmp_button; gboolean was_in_group = FALSE;
GSList *tmp_list;
gboolean was_in_group;
was_in_group = priv->group && priv->group->next; if (priv->group)
priv->group = g_slist_remove (priv->group, radio_button);
if (priv->group && !priv->group->next)
old_group_singleton = priv->group->data;
tmp_list = priv->group;
while (tmp_list)
{ {
tmp_button = tmp_list->data; _gtk_radio_group_remove_item (priv->group, G_OBJECT (radio_button));
tmp_list = tmp_list->next; was_in_group = !_gtk_radio_group_is_empty (priv->group);
old_group_singleton = _gtk_radio_group_get_singleton (priv->group);
tmp_button->priv->group = priv->group; /* this button is no longer in the group */
g_object_unref (priv->group);
priv->group = NULL;
} }
/* this button is no longer in the group */
priv->group = NULL;
if (old_group_singleton) if (old_group_singleton)
g_signal_emit (old_group_singleton, group_changed_signal, 0); g_signal_emit (old_group_singleton, group_changed_signal, 0);
if (was_in_group) if (was_in_group)
@@ -647,7 +583,6 @@ gtk_radio_button_focus (GtkWidget *widget,
{ {
GtkRadioButton *radio_button = GTK_RADIO_BUTTON (widget); GtkRadioButton *radio_button = GTK_RADIO_BUTTON (widget);
GtkRadioButtonPrivate *priv = radio_button->priv; GtkRadioButtonPrivate *priv = radio_button->priv;
GSList *tmp_slist;
/* Radio buttons with draw_indicator unset focus "normally", since /* Radio buttons with draw_indicator unset focus "normally", since
* they look like buttons to the user. * they look like buttons to the user.
@@ -655,6 +590,8 @@ gtk_radio_button_focus (GtkWidget *widget,
if (!gtk_toggle_button_get_mode (GTK_TOGGLE_BUTTON (widget))) if (!gtk_toggle_button_get_mode (GTK_TOGGLE_BUTTON (widget)))
return GTK_WIDGET_CLASS (gtk_radio_button_parent_class)->focus (widget, direction); return GTK_WIDGET_CLASS (gtk_radio_button_parent_class)->focus (widget, direction);
gtk_radio_button_ensure_group (radio_button);
if (gtk_widget_is_focus (widget)) if (gtk_widget_is_focus (widget))
{ {
GtkSettings *settings = gtk_widget_get_settings (widget); GtkSettings *settings = gtk_widget_get_settings (widget);
@@ -668,12 +605,12 @@ gtk_radio_button_focus (GtkWidget *widget,
{ {
case GTK_DIR_LEFT: case GTK_DIR_LEFT:
case GTK_DIR_RIGHT: case GTK_DIR_RIGHT:
focus_list = g_slist_copy (priv->group); focus_list = gtk_radio_group_get_items (priv->group);
focus_list = g_slist_sort_with_data (focus_list, left_right_compare, toplevel); focus_list = g_slist_sort_with_data (focus_list, left_right_compare, toplevel);
break; break;
case GTK_DIR_UP: case GTK_DIR_UP:
case GTK_DIR_DOWN: case GTK_DIR_DOWN:
focus_list = g_slist_copy (priv->group); focus_list = gtk_radio_group_get_items (priv->group);
focus_list = g_slist_sort_with_data (focus_list, up_down_compare, toplevel); focus_list = g_slist_sort_with_data (focus_list, up_down_compare, toplevel);
break; break;
case GTK_DIR_TAB_FORWARD: case GTK_DIR_TAB_FORWARD:
@@ -756,22 +693,15 @@ gtk_radio_button_focus (GtkWidget *widget,
} }
else else
{ {
GtkRadioButton *selected_button = NULL; GObject *selected_button;
/* We accept the focus if, we don't have the focus and /* We accept the focus if, we don't have the focus and
* - we are the currently active button in the group * - we are the currently active button in the group
* - there is no currently active radio button. * - there is no currently active radio button.
*/ */
tmp_slist = priv->group; selected_button = gtk_radio_group_get_active_item (priv->group);
while (tmp_slist) if (selected_button && selected_button != G_OBJECT (radio_button))
{
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (tmp_slist->data)))
selected_button = tmp_slist->data;
tmp_slist = tmp_slist->next;
}
if (selected_button && selected_button != radio_button)
return FALSE; return FALSE;
gtk_widget_grab_focus (widget); gtk_widget_grab_focus (widget);
@@ -785,34 +715,22 @@ gtk_radio_button_clicked (GtkButton *button)
GtkRadioButton *radio_button = GTK_RADIO_BUTTON (button); GtkRadioButton *radio_button = GTK_RADIO_BUTTON (button);
GtkRadioButtonPrivate *priv = radio_button->priv; GtkRadioButtonPrivate *priv = radio_button->priv;
GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (button); GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (button);
GtkToggleButton *tmp_button; GObject *active_item;
GtkStateType new_state; GtkStateType new_state;
GSList *tmp_list;
gint toggled; gint toggled;
gboolean depressed; gboolean depressed;
gtk_radio_button_ensure_group (radio_button);
toggled = FALSE; toggled = FALSE;
g_object_ref (GTK_WIDGET (button)); g_object_ref (GTK_WIDGET (button));
if (gtk_toggle_button_get_active (toggle_button)) if (gtk_toggle_button_get_active (toggle_button))
{ {
tmp_button = NULL; active_item = gtk_radio_group_get_active_item (priv->group);
tmp_list = priv->group;
while (tmp_list) if (active_item == NULL || active_item == G_OBJECT (button))
{
tmp_button = tmp_list->data;
tmp_list = tmp_list->next;
if (tmp_button != toggle_button &&
gtk_toggle_button_get_active (tmp_button))
break;
tmp_button = NULL;
}
if (!tmp_button)
{ {
new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE); new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
} }
@@ -830,18 +748,10 @@ gtk_radio_button_clicked (GtkButton *button)
_gtk_toggle_button_set_active (toggle_button, _gtk_toggle_button_set_active (toggle_button,
!gtk_toggle_button_get_active (toggle_button)); !gtk_toggle_button_get_active (toggle_button));
tmp_list = priv->group; active_item = gtk_radio_group_get_active_item (priv->group);
while (tmp_list) _gtk_radio_group_set_active_item (priv->group, G_OBJECT (toggle_button));
{ if (active_item != G_OBJECT (toggle_button))
tmp_button = tmp_list->data; gtk_button_clicked (GTK_BUTTON (active_item));
tmp_list = tmp_list->next;
if (gtk_toggle_button_get_active (tmp_button) && (tmp_button != toggle_button))
{
gtk_button_clicked (GTK_BUTTON (tmp_button));
break;
}
}
new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE); new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
} }
@@ -861,6 +771,9 @@ gtk_radio_button_clicked (GtkButton *button)
gtk_toggle_button_toggled (toggle_button); gtk_toggle_button_toggled (toggle_button);
g_object_notify (G_OBJECT (toggle_button), "active"); g_object_notify (G_OBJECT (toggle_button), "active");
if (gtk_toggle_button_get_active (toggle_button))
_gtk_radio_group_emit_active_changed (priv->group);
} }
_gtk_button_set_depressed (button, depressed); _gtk_button_set_depressed (button, depressed);

View File

@@ -33,6 +33,7 @@
#include <gtk/gtkcheckbutton.h> #include <gtk/gtkcheckbutton.h>
#include <gtk/gtkradiogroup.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@@ -74,21 +75,22 @@ struct _GtkRadioButtonClass
GType gtk_radio_button_get_type (void) G_GNUC_CONST; GType gtk_radio_button_get_type (void) G_GNUC_CONST;
GtkWidget* gtk_radio_button_new (GSList *group); GtkWidget* gtk_radio_button_new (GtkRadioGroup *group);
GtkWidget* gtk_radio_button_new_from_widget (GtkRadioButton *radio_group_member); GtkWidget* gtk_radio_button_new_with_label (GtkRadioGroup *group,
GtkWidget* gtk_radio_button_new_with_label (GSList *group, const gchar *label);
const gchar *label); GtkWidget* gtk_radio_button_new_with_mnemonic (GtkRadioGroup *group,
GtkWidget* gtk_radio_button_new_with_label_from_widget (GtkRadioButton *radio_group_member, const gchar *label);
const gchar *label); #ifndef GTK_DISABLE_DEPRECATED
GtkWidget* gtk_radio_button_new_with_mnemonic (GSList *group, GtkWidget* gtk_radio_button_new_from_widget (GtkRadioButton *radio_group_member);
const gchar *label); GtkWidget* gtk_radio_button_new_with_label_from_widget (GtkRadioButton *radio_group_member,
GtkWidget* gtk_radio_button_new_with_mnemonic_from_widget (GtkRadioButton *radio_group_member, const gchar *label);
const gchar *label); GtkWidget* gtk_radio_button_new_with_mnemonic_from_widget (GtkRadioButton *radio_group_member,
GSList* gtk_radio_button_get_group (GtkRadioButton *radio_button); const gchar *label);
void gtk_radio_button_set_group (GtkRadioButton *radio_button, #endif
GSList *group); GtkRadioGroup *gtk_radio_button_get_group (GtkRadioButton *radio_button);
void gtk_radio_button_join_group (GtkRadioButton *radio_button, void gtk_radio_button_set_group (GtkRadioButton *radio_button,
GtkRadioButton *group_source); GtkRadioGroup *group);
G_END_DECLS G_END_DECLS
#endif /* __GTK_RADIO_BUTTON_H__ */ #endif /* __GTK_RADIO_BUTTON_H__ */

306
gtk/gtkradiogroup.c Normal file
View File

@@ -0,0 +1,306 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "config.h"
#include "gtkradiogroupprivate.h"
#include "gtkprivate.h"
#include "gtkmarshalers.h"
#include "gtkintl.h"
/**
* SECTION:gtkradiogroup
* @Short_description: A group of object having radiobutton like behaviour
* @Title: GtkRadioGroup
* @See_also: #GtkRadioButton, #GtkRadioAction, #GtkRadioToolButton, #GtkRadioMenuItem
*
* #GtkRadioButton, and several other similar widgets are grouped together in logical
* groups (unrelated to how they are laid out in the user interface) such that only
* one item in the group can be active at any one time. This grouping is represented
* by the #GtkRadioGroup class.
*
* #GtkRadioGroup has operations that let you list the items and get the active item.
* There are also signals that signal when the group content changes and when the
* active item changes.
*
* Since: 3.0
*/
struct _GtkRadioGroupPrivate
{
GSList *items;
GObject *active;
};
enum {
PROP_0,
PROP_ACTIVE_ITEM
};
static void gtk_radio_group_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void gtk_radio_group_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
G_DEFINE_TYPE (GtkRadioGroup, gtk_radio_group, G_TYPE_INITIALLY_UNOWNED)
enum {
ACTIVE_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
static void
gtk_radio_group_class_init (GtkRadioGroupClass *class)
{
GObjectClass *gobject_class;
gobject_class = G_OBJECT_CLASS (class);
gobject_class->set_property = gtk_radio_group_set_property;
gobject_class->get_property = gtk_radio_group_get_property;
/**
* GtkRadioGroup:active-item:
*
* Gets the active item in a radio group.
*/
g_object_class_install_property (gobject_class,
PROP_ACTIVE_ITEM,
g_param_spec_object ("active-item",
P_("Active item"),
P_("The active item in the radio group."),
G_TYPE_OBJECT,
GTK_PARAM_READABLE));
class->active_changed = NULL;
/**
* GtkRadioGroup::active-changed:
* @radio_group: the radio group on which the signal is emitted
* @active: the new active item
*
* The ::active-changed signal gets emitted when there are changes
* in what item is the active one.
*/
signals[ACTIVE_CHANGED] = g_signal_new (I_("active-changed"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GtkRadioGroupClass, active_changed),
NULL, NULL,
_gtk_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, G_TYPE_OBJECT);
g_type_class_add_private (class, sizeof (GtkRadioGroupPrivate));
}
static void
gtk_radio_group_init (GtkRadioGroup *radio_group)
{
GtkRadioGroupPrivate *priv;
radio_group->priv = G_TYPE_INSTANCE_GET_PRIVATE (radio_group,
GTK_TYPE_RADIO_GROUP,
GtkRadioGroupPrivate);
priv = radio_group->priv;
priv->items = NULL;
priv->active = NULL;
}
static void
gtk_radio_group_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkRadioGroup *radio_group;
radio_group = GTK_RADIO_GROUP (object);
switch (prop_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_radio_group_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkRadioGroup *radio_group;
radio_group = GTK_RADIO_GROUP (object);
switch (prop_id)
{
case PROP_ACTIVE_ITEM:
g_value_set_object (value, radio_group->priv->active);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/**
* gtk_radio_group_new:
*
* Creates a new empty #GtkRadioGroup.
*
* Note that #GtkRadioGroup inherits from #GInitiallyUnowned, so
* the newly constructed group is floating. Typically adding an
* item to the group will sink it as the item will own the group, but
* if you need to keep around the group without adding anything to
* it you must call g_object_ref_sink() to get an owning reference
* to it.
*
* Returns: a new radio group
*/
GtkRadioGroup*
gtk_radio_group_new (void)
{
GtkRadioGroup *radio_group;
radio_group = g_object_new (GTK_TYPE_RADIO_GROUP, NULL);
return radio_group;
}
/**
* gtk_radio_group_get_items:
* @radio_group: a #GtkRadioGroup.
*
* Returns a list with the items in the #GtkRadioGroup.
*
* Return value: (transfer container) (element-type GObject): a
* newly-allocated #GSList containing all the items in the group.
* It should be freed by g_slist_free().
*/
GSList*
gtk_radio_group_get_items (GtkRadioGroup *radio_group)
{
g_return_val_if_fail (GTK_IS_RADIO_GROUP (radio_group), NULL);
return g_slist_copy (radio_group->priv->items);
}
/**
* gtk_radio_group_get_items:
* @radio_group: a #GtkRadioGroup.
*
* Retrieves the currently active item in the group.
*
* Return value: (transfer none): pointer to a #GObject that
* is the active item in the group, or %NULL if the group
* is empty.
*/
GObject *
gtk_radio_group_get_active_item (GtkRadioGroup *radio_group)
{
g_return_val_if_fail (GTK_IS_RADIO_GROUP (radio_group), NULL);
return radio_group->priv->active;
}
gboolean
_gtk_radio_group_is_empty (GtkRadioGroup *radio_group)
{
return radio_group->priv->items == NULL;
}
GObject *
_gtk_radio_group_get_singleton (GtkRadioGroup *radio_group)
{
GtkRadioGroupPrivate *priv;
priv = radio_group->priv;
if (priv->items != NULL && priv->items->next == NULL)
return g_object_ref (priv->items->data);
return NULL;
}
/* Caller must handle signal emission if the active item
changes */
void
_gtk_radio_group_add_item (GtkRadioGroup *radio_group,
GObject *item)
{
GtkRadioGroupPrivate *priv;
g_return_if_fail (GTK_IS_RADIO_GROUP (radio_group));
g_return_if_fail (!g_slist_find (radio_group->priv->items, item));
priv = radio_group->priv;
priv->items = g_slist_prepend (priv->items, item);
if (priv->active == NULL)
priv->active = item;
}
/* Caller must handle signal emission if the active item
changes */
void
_gtk_radio_group_remove_item (GtkRadioGroup *radio_group,
GObject *item)
{
GtkRadioGroupPrivate *priv;
g_return_if_fail (GTK_IS_RADIO_GROUP (radio_group));
g_return_if_fail (g_slist_find (radio_group->priv->items, item));
priv = radio_group->priv;
priv->items = g_slist_remove (priv->items, item);
if (priv->active == item)
{
if (priv->items)
priv->active = priv->items->data;
else
priv->active = NULL;
}
}
void
_gtk_radio_group_set_active_item (GtkRadioGroup *radio_group,
GObject *item)
{
radio_group->priv->active = item;
}
void
_gtk_radio_group_emit_active_changed (GtkRadioGroup *radio_group)
{
g_object_notify (G_OBJECT (radio_group), "active-item");
g_signal_emit (radio_group, signals[ACTIVE_CHANGED], 0, radio_group->priv->active);
}

81
gtk/gtkradiogroup.h Normal file
View File

@@ -0,0 +1,81 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#ifndef __GTK_RADIO_GROUP_H__
#define __GTK_RADIO_GROUP_H__
#include <gdk/gdk.h>
G_BEGIN_DECLS
#define GTK_TYPE_RADIO_GROUP (gtk_radio_group_get_type ())
#define GTK_RADIO_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_RADIO_GROUP, GtkRadioGroup))
#define GTK_RADIO_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_RADIO_GROUP, GtkRadioGroupClass))
#define GTK_IS_RADIO_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_RADIO_GROUP))
#define GTK_IS_RADIO_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_RADIO_GROUP))
#define GTK_RADIO_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_RADIO_GROUP, GtkRadioGroupClass))
typedef struct _GtkRadioGroup GtkRadioGroup;
typedef struct _GtkRadioGroupPrivate GtkRadioGroupPrivate;
typedef struct _GtkRadioGroupClass GtkRadioGroupClass;
struct _GtkRadioGroup
{
GInitiallyUnowned parent_instance;
/*< private >*/
GtkRadioGroupPrivate *priv;
};
struct _GtkRadioGroupClass
{
GInitiallyUnownedClass parent_class;
/* Signals */
void (*active_changed) (GtkRadioGroup *radio_group, GObject *active);
/* Padding for future expansion */
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
};
GType gtk_radio_group_get_type (void) G_GNUC_CONST;
GtkRadioGroup* gtk_radio_group_new (void);
GSList * gtk_radio_group_get_items (GtkRadioGroup *radio_group);
GObject * gtk_radio_group_get_active_item (GtkRadioGroup *radio_group);
G_END_DECLS
#endif /* __GTK_RADIO_GROUP_H__ */

View File

@@ -0,0 +1,46 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __GTK_RADIO_GROUP_PRIVATE_H__
#define __GTK_RADIO_GROUP_PRIVATE_H__
#include <gtk/gtkradiogroup.h>
G_BEGIN_DECLS
void _gtk_radio_group_add_item (GtkRadioGroup *radio_group,
GObject *item);
void _gtk_radio_group_remove_item (GtkRadioGroup *radio_group,
GObject *item);
gboolean _gtk_radio_group_is_empty (GtkRadioGroup *radio_group);
GObject *_gtk_radio_group_get_singleton (GtkRadioGroup *radio_group);
void _gtk_radio_group_set_active_item (GtkRadioGroup *radio_group,
GObject *item);
void _gtk_radio_group_emit_active_changed (GtkRadioGroup *radio_group);
G_END_DECLS
#endif /* __GTK_RADIO_GROUP_PRIVATE_H__ */

View File

@@ -28,6 +28,7 @@
#include "gtkaccellabel.h" #include "gtkaccellabel.h"
#include "gtkmarshalers.h" #include "gtkmarshalers.h"
#include "gtkradiomenuitem.h" #include "gtkradiomenuitem.h"
#include "gtkradiogroupprivate.h"
#include "gtkactivatable.h" #include "gtkactivatable.h"
#include "gtkprivate.h" #include "gtkprivate.h"
#include "gtkintl.h" #include "gtkintl.h"
@@ -35,7 +36,7 @@
struct _GtkRadioMenuItemPrivate struct _GtkRadioMenuItemPrivate
{ {
GSList *group; GtkRadioGroup *group;
}; };
enum { enum {
@@ -60,13 +61,11 @@ static guint group_changed_signal = 0;
G_DEFINE_TYPE (GtkRadioMenuItem, gtk_radio_menu_item, GTK_TYPE_CHECK_MENU_ITEM) G_DEFINE_TYPE (GtkRadioMenuItem, gtk_radio_menu_item, GTK_TYPE_CHECK_MENU_ITEM)
GtkWidget* GtkWidget*
gtk_radio_menu_item_new (GSList *group) gtk_radio_menu_item_new (GtkRadioGroup *group)
{ {
GtkRadioMenuItem *radio_menu_item; GtkRadioMenuItem *radio_menu_item;
radio_menu_item = g_object_new (GTK_TYPE_RADIO_MENU_ITEM, NULL); radio_menu_item = g_object_new (GTK_TYPE_RADIO_MENU_ITEM, "group", group, NULL);
gtk_radio_menu_item_set_group (radio_menu_item, group);
return GTK_WIDGET (radio_menu_item); return GTK_WIDGET (radio_menu_item);
} }
@@ -83,14 +82,11 @@ gtk_radio_menu_item_set_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
GSList *slist; GtkRadioGroup *group;
case PROP_GROUP: case PROP_GROUP:
if (G_VALUE_HOLDS_OBJECT (value)) group = g_value_get_object (value);
slist = gtk_radio_menu_item_get_group ((GtkRadioMenuItem*) g_value_get_object (value)); gtk_radio_menu_item_set_group (radio_menu_item, group);
else
slist = NULL;
gtk_radio_menu_item_set_group (radio_menu_item, slist);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -104,8 +100,15 @@ gtk_radio_menu_item_get_property (GObject *object,
GValue *value, GValue *value,
GParamSpec *pspec) GParamSpec *pspec)
{ {
GtkRadioMenuItem *radio_menu_item;
radio_menu_item = GTK_RADIO_MENU_ITEM (object);
switch (prop_id) switch (prop_id)
{ {
case PROP_GROUP:
g_value_set_object (value, gtk_radio_menu_item_get_group (radio_menu_item));
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@@ -114,60 +117,41 @@ gtk_radio_menu_item_get_property (GObject *object,
void void
gtk_radio_menu_item_set_group (GtkRadioMenuItem *radio_menu_item, gtk_radio_menu_item_set_group (GtkRadioMenuItem *radio_menu_item,
GSList *group) GtkRadioGroup *group)
{ {
GtkRadioMenuItemPrivate *priv; GtkRadioMenuItemPrivate *priv;
GtkWidget *old_group_singleton = NULL; GObject *old_group_singleton = NULL;
GtkWidget *new_group_singleton = NULL; GObject *new_group_singleton;
GObject *old_group_active;
gboolean is_active;
g_return_if_fail (GTK_IS_RADIO_MENU_ITEM (radio_menu_item)); g_return_if_fail (GTK_IS_RADIO_MENU_ITEM (radio_menu_item));
g_return_if_fail (!g_slist_find (group, radio_menu_item));
priv = radio_menu_item->priv; priv = radio_menu_item->priv;
if (priv->group == group)
return;
if (group == NULL)
group = gtk_radio_group_new ();
if (priv->group) if (priv->group)
{ {
GSList *slist; _gtk_radio_group_remove_item (priv->group, G_OBJECT (radio_menu_item));
old_group_singleton = _gtk_radio_group_get_singleton (priv->group);
priv->group = g_slist_remove (priv->group, radio_menu_item); /* Ensure some widget is active in the old group */
old_group_active = gtk_radio_group_get_active_item (priv->group);
if (old_group_active)
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (old_group_active), TRUE);
if (priv->group && !priv->group->next) g_object_unref (priv->group);
old_group_singleton = g_object_ref (priv->group->data);
for (slist = priv->group; slist; slist = slist->next)
{
GtkRadioMenuItem *tmp_item;
tmp_item = slist->data;
tmp_item->priv->group = priv->group;
}
} }
if (group && !group->next) priv->group = g_object_ref_sink (group);
new_group_singleton = g_object_ref (group->data); new_group_singleton = _gtk_radio_group_get_singleton (group);
priv->group = g_slist_prepend (group, radio_menu_item); _gtk_radio_group_add_item (group, G_OBJECT (radio_menu_item));
if (group)
{
GSList *slist;
for (slist = group; slist; slist = slist->next)
{
GtkRadioMenuItem *tmp_item;
tmp_item = slist->data;
tmp_item->priv->group = priv->group;
}
}
else
{
_gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (radio_menu_item), TRUE);
/* gtk_widget_set_state (GTK_WIDGET (radio_menu_item), GTK_STATE_ACTIVE);
*/
}
g_object_ref (radio_menu_item); g_object_ref (radio_menu_item);
@@ -184,13 +168,18 @@ gtk_radio_menu_item_set_group (GtkRadioMenuItem *radio_menu_item,
g_object_unref (new_group_singleton); g_object_unref (new_group_singleton);
} }
is_active = gtk_radio_group_get_active_item (group) == G_OBJECT (radio_menu_item);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (radio_menu_item), is_active);
if (is_active)
_gtk_radio_group_emit_active_changed (group);
g_object_unref (radio_menu_item); g_object_unref (radio_menu_item);
} }
/** /**
* gtk_radio_menu_item_new_with_label: * gtk_radio_menu_item_new_with_label:
* @group: (element-type GtkRadioMenuItem) (transfer full): * @group: a #GtkRadioMenuItem or %NULL
* @label: the text for the label * @label: the text for the label
* *
* Creates a new #GtkRadioMenuItem whose child is a simple #GtkLabel. * Creates a new #GtkRadioMenuItem whose child is a simple #GtkLabel.
@@ -198,7 +187,7 @@ gtk_radio_menu_item_set_group (GtkRadioMenuItem *radio_menu_item,
* Returns: (transfer none): A new #GtkRadioMenuItem * Returns: (transfer none): A new #GtkRadioMenuItem
*/ */
GtkWidget* GtkWidget*
gtk_radio_menu_item_new_with_label (GSList *group, gtk_radio_menu_item_new_with_label (GtkRadioGroup *group,
const gchar *label) const gchar *label)
{ {
GtkWidget *radio_menu_item; GtkWidget *radio_menu_item;
@@ -227,7 +216,7 @@ gtk_radio_menu_item_new_with_label (GSList *group,
* in @label indicate the mnemonic for the menu item. * in @label indicate the mnemonic for the menu item.
**/ **/
GtkWidget* GtkWidget*
gtk_radio_menu_item_new_with_mnemonic (GSList *group, gtk_radio_menu_item_new_with_mnemonic (GtkRadioGroup *group,
const gchar *label) const gchar *label)
{ {
GtkWidget *radio_menu_item; GtkWidget *radio_menu_item;
@@ -258,14 +247,14 @@ gtk_radio_menu_item_new_with_mnemonic (GSList *group,
GtkWidget * GtkWidget *
gtk_radio_menu_item_new_from_widget (GtkRadioMenuItem *group) gtk_radio_menu_item_new_from_widget (GtkRadioMenuItem *group)
{ {
GSList *list = NULL; GtkRadioGroup *radio_group = NULL;
g_return_val_if_fail (GTK_IS_RADIO_MENU_ITEM (group), NULL); g_return_val_if_fail (GTK_IS_RADIO_MENU_ITEM (group), NULL);
if (group) if (group)
list = gtk_radio_menu_item_get_group (group); radio_group = gtk_radio_menu_item_get_group (group);
return gtk_radio_menu_item_new (list); return gtk_radio_menu_item_new (radio_group);
} }
/** /**
@@ -288,14 +277,14 @@ GtkWidget *
gtk_radio_menu_item_new_with_mnemonic_from_widget (GtkRadioMenuItem *group, gtk_radio_menu_item_new_with_mnemonic_from_widget (GtkRadioMenuItem *group,
const gchar *label) const gchar *label)
{ {
GSList *list = NULL; GtkRadioGroup *radio_group = NULL;
g_return_val_if_fail (GTK_IS_RADIO_MENU_ITEM (group), NULL); g_return_val_if_fail (GTK_IS_RADIO_MENU_ITEM (group), NULL);
if (group) if (group)
list = gtk_radio_menu_item_get_group (group); radio_group = gtk_radio_menu_item_get_group (group);
return gtk_radio_menu_item_new_with_mnemonic (list, label); return gtk_radio_menu_item_new_with_mnemonic (radio_group, label);
} }
/** /**
@@ -314,30 +303,46 @@ GtkWidget *
gtk_radio_menu_item_new_with_label_from_widget (GtkRadioMenuItem *group, gtk_radio_menu_item_new_with_label_from_widget (GtkRadioMenuItem *group,
const gchar *label) const gchar *label)
{ {
GSList *list = NULL; GtkRadioGroup *radio_group = NULL;
g_return_val_if_fail (GTK_IS_RADIO_MENU_ITEM (group), NULL); g_return_val_if_fail (GTK_IS_RADIO_MENU_ITEM (group), NULL);
if (group) if (group)
list = gtk_radio_menu_item_get_group (group); radio_group = gtk_radio_menu_item_get_group (group);
return gtk_radio_menu_item_new_with_label (list, label); return gtk_radio_menu_item_new_with_label (radio_group, label);
} }
static void
gtk_radio_menu_item_ensure_group (GtkRadioMenuItem *radio_menu_item)
{
GtkRadioMenuItemPrivate *priv = radio_menu_item->priv;
if (priv->group == NULL)
{
priv->group = g_object_ref_sink (gtk_radio_group_new ());
_gtk_radio_group_add_item (priv->group, G_OBJECT (radio_menu_item));
}
}
/** /**
* gtk_radio_menu_item_get_group: * gtk_radio_menu_item_get_group:
* @radio_menu_item: a #GtkRadioMenuItem * @radio_menu_item: a #GtkRadioMenuItem
* *
* Returns the group to which the radio menu item belongs, as a #GList of * Retrieves the group to which the radio menu item belongs.
* #GtkRadioMenuItem. The list belongs to GTK+ and should not be freed.
* *
* Returns: (transfer none): the group of @radio_menu_item * Return value: (transfer none): a #GtkRadioGroup
* containing all the radio menu items in the same group
* as @radio_menu_button.
*/ */
GSList* GtkRadioGroup*
gtk_radio_menu_item_get_group (GtkRadioMenuItem *radio_menu_item) gtk_radio_menu_item_get_group (GtkRadioMenuItem *radio_menu_item)
{ {
g_return_val_if_fail (GTK_IS_RADIO_MENU_ITEM (radio_menu_item), NULL); g_return_val_if_fail (GTK_IS_RADIO_MENU_ITEM (radio_menu_item), NULL);
gtk_radio_menu_item_ensure_group (radio_menu_item);
return radio_menu_item->priv->group; return radio_menu_item->priv->group;
} }
@@ -371,9 +376,9 @@ gtk_radio_menu_item_class_init (GtkRadioMenuItemClass *klass)
PROP_GROUP, PROP_GROUP,
g_param_spec_object ("group", g_param_spec_object ("group",
P_("Group"), P_("Group"),
P_("The radio menu item whose group this widget belongs to."), P_("The radio group this menu item belongs to."),
GTK_TYPE_RADIO_MENU_ITEM, GTK_TYPE_RADIO_GROUP,
GTK_PARAM_WRITABLE)); GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
/** /**
* GtkStyle::group-changed: * GtkStyle::group-changed:
@@ -409,7 +414,7 @@ gtk_radio_menu_item_init (GtkRadioMenuItem *radio_menu_item)
GtkRadioMenuItemPrivate); GtkRadioMenuItemPrivate);
priv = radio_menu_item->priv; priv = radio_menu_item->priv;
priv->group = g_slist_prepend (NULL, radio_menu_item); priv->group = NULL;
gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (radio_menu_item), TRUE); gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (radio_menu_item), TRUE);
} }
@@ -418,30 +423,20 @@ gtk_radio_menu_item_destroy (GtkWidget *widget)
{ {
GtkRadioMenuItem *radio_menu_item = GTK_RADIO_MENU_ITEM (widget); GtkRadioMenuItem *radio_menu_item = GTK_RADIO_MENU_ITEM (widget);
GtkRadioMenuItemPrivate *priv = radio_menu_item->priv; GtkRadioMenuItemPrivate *priv = radio_menu_item->priv;
GtkWidget *old_group_singleton = NULL; GObject *old_group_singleton = NULL;
GtkRadioMenuItem *tmp_menu_item; gboolean was_in_group = FALSE;
GSList *tmp_list;
gboolean was_in_group;
was_in_group = priv->group && priv->group->next; if (priv->group)
priv->group = g_slist_remove (priv->group, radio_menu_item);
if (priv->group && !priv->group->next)
old_group_singleton = priv->group->data;
tmp_list = priv->group;
while (tmp_list)
{ {
tmp_menu_item = tmp_list->data; _gtk_radio_group_remove_item (priv->group, G_OBJECT (radio_menu_item));
tmp_list = tmp_list->next; was_in_group = !_gtk_radio_group_is_empty (priv->group);
old_group_singleton = _gtk_radio_group_get_singleton (priv->group);
tmp_menu_item->priv->group = priv->group; /* this menu item is no longer in the group */
g_object_unref (priv->group);
priv->group = NULL;
} }
/* this radio menu item is no longer in the group */
priv->group = NULL;
if (old_group_singleton) if (old_group_singleton)
g_signal_emit (old_group_singleton, group_changed_signal, 0); g_signal_emit (old_group_singleton, group_changed_signal, 0);
if (was_in_group) if (was_in_group)
@@ -456,12 +451,13 @@ gtk_radio_menu_item_activate (GtkMenuItem *menu_item)
GtkRadioMenuItem *radio_menu_item = GTK_RADIO_MENU_ITEM (menu_item); GtkRadioMenuItem *radio_menu_item = GTK_RADIO_MENU_ITEM (menu_item);
GtkRadioMenuItemPrivate *priv = radio_menu_item->priv; GtkRadioMenuItemPrivate *priv = radio_menu_item->priv;
GtkCheckMenuItem *check_menu_item = GTK_CHECK_MENU_ITEM (menu_item); GtkCheckMenuItem *check_menu_item = GTK_CHECK_MENU_ITEM (menu_item);
GtkCheckMenuItem *tmp_menu_item;
GtkAction *action; GtkAction *action;
GSList *tmp_list; GObject *active_item;
gboolean active; gboolean active;
gint toggled; gint toggled;
gtk_radio_menu_item_ensure_group (radio_menu_item);
action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (menu_item)); action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (menu_item));
if (action && gtk_menu_item_get_submenu (menu_item) == NULL) if (action && gtk_menu_item_get_submenu (menu_item) == NULL)
gtk_action_activate (action); gtk_action_activate (action);
@@ -471,22 +467,9 @@ gtk_radio_menu_item_activate (GtkMenuItem *menu_item)
active = gtk_check_menu_item_get_active (check_menu_item); active = gtk_check_menu_item_get_active (check_menu_item);
if (active) if (active)
{ {
tmp_menu_item = NULL; active_item = gtk_radio_group_get_active_item (priv->group);
tmp_list = priv->group;
while (tmp_list) if (active_item != G_OBJECT (menu_item))
{
tmp_menu_item = tmp_list->data;
tmp_list = tmp_list->next;
if (gtk_check_menu_item_get_active (tmp_menu_item) &&
tmp_menu_item != check_menu_item)
break;
tmp_menu_item = NULL;
}
if (tmp_menu_item)
{ {
toggled = TRUE; toggled = TRUE;
_gtk_check_menu_item_set_active (check_menu_item, !active); _gtk_check_menu_item_set_active (check_menu_item, !active);
@@ -497,24 +480,17 @@ gtk_radio_menu_item_activate (GtkMenuItem *menu_item)
toggled = TRUE; toggled = TRUE;
_gtk_check_menu_item_set_active (check_menu_item, !active); _gtk_check_menu_item_set_active (check_menu_item, !active);
tmp_list = priv->group; active_item = gtk_radio_group_get_active_item (priv->group);
while (tmp_list) _gtk_radio_group_set_active_item (priv->group, G_OBJECT (menu_item));
{ if (active_item != G_OBJECT (menu_item))
tmp_menu_item = tmp_list->data; gtk_menu_item_activate (GTK_MENU_ITEM (active_item));
tmp_list = tmp_list->next;
if (gtk_check_menu_item_get_active (tmp_menu_item) &&
tmp_menu_item != check_menu_item)
{
gtk_menu_item_activate (GTK_MENU_ITEM (tmp_menu_item));
break;
}
}
} }
if (toggled) if (toggled)
{ {
gtk_check_menu_item_toggled (check_menu_item); gtk_check_menu_item_toggled (check_menu_item);
if (gtk_check_menu_item_get_active (check_menu_item))
_gtk_radio_group_emit_active_changed (priv->group);
} }
gtk_widget_queue_draw (GTK_WIDGET (radio_menu_item)); gtk_widget_queue_draw (GTK_WIDGET (radio_menu_item));

View File

@@ -33,6 +33,7 @@
#include <gtk/gtkcheckmenuitem.h> #include <gtk/gtkcheckmenuitem.h>
#include <gtk/gtkradiogroup.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@@ -74,19 +75,21 @@ struct _GtkRadioMenuItemClass
GType gtk_radio_menu_item_get_type (void) G_GNUC_CONST; GType gtk_radio_menu_item_get_type (void) G_GNUC_CONST;
GtkWidget* gtk_radio_menu_item_new (GSList *group); GtkWidget* gtk_radio_menu_item_new (GtkRadioGroup *group);
GtkWidget* gtk_radio_menu_item_new_with_label (GSList *group, GtkWidget* gtk_radio_menu_item_new_with_label (GtkRadioGroup *group,
const gchar *label); const gchar *label);
GtkWidget* gtk_radio_menu_item_new_with_mnemonic (GSList *group, GtkWidget* gtk_radio_menu_item_new_with_mnemonic (GtkRadioGroup *group,
const gchar *label); const gchar *label);
GtkWidget* gtk_radio_menu_item_new_from_widget (GtkRadioMenuItem *group); #ifndef GTK_DISABLE_DEPRECATED
GtkWidget *gtk_radio_menu_item_new_with_mnemonic_from_widget (GtkRadioMenuItem *group, GtkWidget* gtk_radio_menu_item_new_from_widget (GtkRadioMenuItem *group);
const gchar *label); GtkWidget * gtk_radio_menu_item_new_with_mnemonic_from_widget (GtkRadioMenuItem *group,
GtkWidget *gtk_radio_menu_item_new_with_label_from_widget (GtkRadioMenuItem *group, const gchar *label);
const gchar *label); GtkWidget * gtk_radio_menu_item_new_with_label_from_widget (GtkRadioMenuItem *group,
GSList* gtk_radio_menu_item_get_group (GtkRadioMenuItem *radio_menu_item); const gchar *label);
void gtk_radio_menu_item_set_group (GtkRadioMenuItem *radio_menu_item, #endif
GSList *group); GtkRadioGroup* gtk_radio_menu_item_get_group (GtkRadioMenuItem *radio_menu_item);
void gtk_radio_menu_item_set_group (GtkRadioMenuItem *radio_menu_item,
GtkRadioGroup *group);
G_END_DECLS G_END_DECLS

View File

@@ -36,6 +36,10 @@ static void gtk_radio_tool_button_set_property (GObject *object,
guint prop_id, guint prop_id,
const GValue *value, const GValue *value,
GParamSpec *pspec); GParamSpec *pspec);
static void gtk_radio_tool_button_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
G_DEFINE_TYPE (GtkRadioToolButton, gtk_radio_tool_button, GTK_TYPE_TOGGLE_TOOL_BUTTON) G_DEFINE_TYPE (GtkRadioToolButton, gtk_radio_tool_button, GTK_TYPE_TOGGLE_TOOL_BUTTON)
@@ -49,6 +53,7 @@ gtk_radio_tool_button_class_init (GtkRadioToolButtonClass *klass)
toolbutton_class = (GtkToolButtonClass *)klass; toolbutton_class = (GtkToolButtonClass *)klass;
object_class->set_property = gtk_radio_tool_button_set_property; object_class->set_property = gtk_radio_tool_button_set_property;
object_class->get_property = gtk_radio_tool_button_get_property;
toolbutton_class->button_type = GTK_TYPE_RADIO_BUTTON; toolbutton_class->button_type = GTK_TYPE_RADIO_BUTTON;
@@ -63,9 +68,9 @@ gtk_radio_tool_button_class_init (GtkRadioToolButtonClass *klass)
PROP_GROUP, PROP_GROUP,
g_param_spec_object ("group", g_param_spec_object ("group",
P_("Group"), P_("Group"),
P_("The radio tool button whose group this button belongs to."), P_("The radio group this tool button belongs to."),
GTK_TYPE_RADIO_TOOL_BUTTON, GTK_TYPE_RADIO_GROUP,
GTK_PARAM_WRITABLE)); GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
} }
@@ -90,15 +95,10 @@ gtk_radio_tool_button_set_property (GObject *object,
{ {
case PROP_GROUP: case PROP_GROUP:
{ {
GtkRadioToolButton *arg; GtkRadioGroup *group;
GSList *slist = NULL;
if (G_VALUE_HOLDS_OBJECT (value)) group = g_value_get_object (value);
{ gtk_radio_tool_button_set_group (button, group);
arg = GTK_RADIO_TOOL_BUTTON (g_value_get_object (value));
if (arg)
slist = gtk_radio_tool_button_get_group (arg);
gtk_radio_tool_button_set_group (button, slist);
}
} }
break; break;
default: default:
@@ -107,6 +107,27 @@ gtk_radio_tool_button_set_property (GObject *object,
} }
} }
static void
gtk_radio_tool_button_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkRadioToolButton *button;
button = GTK_RADIO_TOOL_BUTTON (object);
switch (prop_id)
{
case PROP_GROUP:
g_value_set_object (value, gtk_radio_tool_button_get_group (button));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/** /**
* gtk_radio_tool_button_new: * gtk_radio_tool_button_new:
* @group: (allow-none): An existing radio button group, or %NULL if you are creating a new group * @group: (allow-none): An existing radio button group, or %NULL if you are creating a new group
@@ -118,15 +139,14 @@ gtk_radio_tool_button_set_property (GObject *object,
* Since: 2.4 * Since: 2.4
**/ **/
GtkToolItem * GtkToolItem *
gtk_radio_tool_button_new (GSList *group) gtk_radio_tool_button_new (GtkRadioGroup *group)
{ {
GtkRadioToolButton *button; GtkRadioToolButton *button;
button = g_object_new (GTK_TYPE_RADIO_TOOL_BUTTON, button = g_object_new (GTK_TYPE_RADIO_TOOL_BUTTON,
"group", group,
NULL); NULL);
gtk_radio_tool_button_set_group (button, group);
return GTK_TOOL_ITEM (button); return GTK_TOOL_ITEM (button);
} }
@@ -144,7 +164,7 @@ gtk_radio_tool_button_new (GSList *group)
* Since: 2.4 * Since: 2.4
**/ **/
GtkToolItem * GtkToolItem *
gtk_radio_tool_button_new_from_stock (GSList *group, gtk_radio_tool_button_new_from_stock (GtkRadioGroup *group,
const gchar *stock_id) const gchar *stock_id)
{ {
GtkRadioToolButton *button; GtkRadioToolButton *button;
@@ -152,12 +172,10 @@ gtk_radio_tool_button_new_from_stock (GSList *group,
g_return_val_if_fail (stock_id != NULL, NULL); g_return_val_if_fail (stock_id != NULL, NULL);
button = g_object_new (GTK_TYPE_RADIO_TOOL_BUTTON, button = g_object_new (GTK_TYPE_RADIO_TOOL_BUTTON,
"group", group,
"stock-id", stock_id, "stock-id", stock_id,
NULL); NULL);
gtk_radio_tool_button_set_group (button, group);
return GTK_TOOL_ITEM (button); return GTK_TOOL_ITEM (button);
} }
@@ -174,14 +192,14 @@ gtk_radio_tool_button_new_from_stock (GSList *group,
GtkToolItem * GtkToolItem *
gtk_radio_tool_button_new_from_widget (GtkRadioToolButton *group) gtk_radio_tool_button_new_from_widget (GtkRadioToolButton *group)
{ {
GSList *list = NULL; GtkRadioGroup *radio_group = NULL;
g_return_val_if_fail (GTK_IS_RADIO_TOOL_BUTTON (group), NULL); g_return_val_if_fail (GTK_IS_RADIO_TOOL_BUTTON (group), NULL);
if (group) if (group)
list = gtk_radio_tool_button_get_group (GTK_RADIO_TOOL_BUTTON (group)); radio_group = gtk_radio_tool_button_get_group (GTK_RADIO_TOOL_BUTTON (group));
return gtk_radio_tool_button_new (list); return gtk_radio_tool_button_new (radio_group);
} }
/** /**
@@ -201,14 +219,14 @@ GtkToolItem *
gtk_radio_tool_button_new_with_stock_from_widget (GtkRadioToolButton *group, gtk_radio_tool_button_new_with_stock_from_widget (GtkRadioToolButton *group,
const gchar *stock_id) const gchar *stock_id)
{ {
GSList *list = NULL; GtkRadioGroup *radio_group = NULL;
g_return_val_if_fail (GTK_IS_RADIO_TOOL_BUTTON (group), NULL); g_return_val_if_fail (GTK_IS_RADIO_TOOL_BUTTON (group), NULL);
if (group) if (group)
list = gtk_radio_tool_button_get_group (group); radio_group = gtk_radio_tool_button_get_group (group);
return gtk_radio_tool_button_new_from_stock (list, stock_id); return gtk_radio_tool_button_new_from_stock (radio_group, stock_id);
} }
static GtkRadioButton * static GtkRadioButton *
@@ -227,7 +245,7 @@ get_radio_button (GtkRadioToolButton *button)
* *
* Since: 2.4 * Since: 2.4
*/ */
GSList * GtkRadioGroup *
gtk_radio_tool_button_get_group (GtkRadioToolButton *button) gtk_radio_tool_button_get_group (GtkRadioToolButton *button)
{ {
g_return_val_if_fail (GTK_IS_RADIO_TOOL_BUTTON (button), NULL); g_return_val_if_fail (GTK_IS_RADIO_TOOL_BUTTON (button), NULL);
@@ -246,7 +264,7 @@ gtk_radio_tool_button_get_group (GtkRadioToolButton *button)
**/ **/
void void
gtk_radio_tool_button_set_group (GtkRadioToolButton *button, gtk_radio_tool_button_set_group (GtkRadioToolButton *button,
GSList *group) GtkRadioGroup *group)
{ {
g_return_if_fail (GTK_IS_RADIO_TOOL_BUTTON (button)); g_return_if_fail (GTK_IS_RADIO_TOOL_BUTTON (button));

View File

@@ -28,6 +28,7 @@
#define __GTK_RADIO_TOOL_BUTTON_H__ #define __GTK_RADIO_TOOL_BUTTON_H__
#include <gtk/gtktoggletoolbutton.h> #include <gtk/gtktoggletoolbutton.h>
#include <gtk/gtkradiogroup.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@@ -59,15 +60,17 @@ struct _GtkRadioToolButtonClass
GType gtk_radio_tool_button_get_type (void) G_GNUC_CONST; GType gtk_radio_tool_button_get_type (void) G_GNUC_CONST;
GtkToolItem *gtk_radio_tool_button_new (GSList *group); GtkToolItem * gtk_radio_tool_button_new (GtkRadioGroup *group);
GtkToolItem *gtk_radio_tool_button_new_from_stock (GSList *group, GtkToolItem * gtk_radio_tool_button_new_from_stock (GtkRadioGroup *group,
const gchar *stock_id); const gchar *stock_id);
GtkToolItem *gtk_radio_tool_button_new_from_widget (GtkRadioToolButton *group); #ifndef GTK_DISABLE_DEPRECATED
GtkToolItem *gtk_radio_tool_button_new_with_stock_from_widget (GtkRadioToolButton *group, GtkToolItem * gtk_radio_tool_button_new_from_widget (GtkRadioToolButton *group);
const gchar *stock_id); GtkToolItem * gtk_radio_tool_button_new_with_stock_from_widget (GtkRadioToolButton *group,
GSList * gtk_radio_tool_button_get_group (GtkRadioToolButton *button); const gchar *stock_id);
void gtk_radio_tool_button_set_group (GtkRadioToolButton *button, #endif
GSList *group); GtkRadioGroup *gtk_radio_tool_button_get_group (GtkRadioToolButton *button);
void gtk_radio_tool_button_set_group (GtkRadioToolButton *button,
GtkRadioGroup *group);
G_END_DECLS G_END_DECLS

View File

@@ -44,6 +44,7 @@ static void
gail_radio_button_init (GailRadioButton *radio_button) gail_radio_button_init (GailRadioButton *radio_button)
{ {
radio_button->old_group = NULL; radio_button->old_group = NULL;
radio_button->old_group_size = 0;
} }
static void static void
@@ -60,7 +61,9 @@ gail_radio_button_ref_relation_set (AtkObject *obj)
{ {
GtkWidget *widget; GtkWidget *widget;
AtkRelationSet *relation_set; AtkRelationSet *relation_set;
GtkRadioGroup *group;
GSList *list; GSList *list;
guint list_length;
GailRadioButton *radio_button; GailRadioButton *radio_button;
g_return_val_if_fail (GAIL_IS_RADIO_BUTTON (obj), NULL); g_return_val_if_fail (GAIL_IS_RADIO_BUTTON (obj), NULL);
@@ -80,9 +83,12 @@ gail_radio_button_ref_relation_set (AtkObject *obj)
/* /*
* If the radio button'group has changed remove the relation * If the radio button'group has changed remove the relation
*/ */
list = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget)); group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
list = gtk_radio_group_get_items (group);
list_length = g_slist_length (list);
if (radio_button->old_group != list) if (radio_button->old_group != group ||
radio_button->old_group_size != list_length)
{ {
AtkRelation *relation; AtkRelation *relation;
@@ -96,15 +102,14 @@ gail_radio_button_ref_relation_set (AtkObject *obj)
* Get the members of the button group * Get the members of the button group
*/ */
radio_button->old_group = list; radio_button->old_group = group;
if (list) radio_button->old_group_size = list_length;
if (group)
{ {
AtkObject **accessible_array; AtkObject **accessible_array;
guint list_length;
AtkRelation* relation; AtkRelation* relation;
gint i = 0; gint i = 0;
list_length = g_slist_length (list);
accessible_array = (AtkObject**) g_malloc (sizeof (AtkObject *) * accessible_array = (AtkObject**) g_malloc (sizeof (AtkObject *) *
list_length); list_length);
while (list != NULL) while (list != NULL)
@@ -126,5 +131,6 @@ gail_radio_button_ref_relation_set (AtkObject *obj)
g_object_unref (relation); g_object_unref (relation);
} }
} }
g_slist_free (list);
return relation_set; return relation_set;
} }

View File

@@ -38,7 +38,8 @@ struct _GailRadioButton
{ {
GailToggleButton parent; GailToggleButton parent;
GSList *old_group; GtkRadioGroup *old_group;
guint old_group_size;
}; };
GType gail_radio_button_get_type (void); GType gail_radio_button_get_type (void);

View File

@@ -62,6 +62,7 @@ static void
gail_radio_menu_item_init (GailRadioMenuItem *radio_menu_item) gail_radio_menu_item_init (GailRadioMenuItem *radio_menu_item)
{ {
radio_menu_item->old_group = NULL; radio_menu_item->old_group = NULL;
radio_menu_item->old_group_size = 0;
} }
AtkRelationSet* AtkRelationSet*
@@ -69,7 +70,9 @@ gail_radio_menu_item_ref_relation_set (AtkObject *obj)
{ {
GtkWidget *widget; GtkWidget *widget;
AtkRelationSet *relation_set; AtkRelationSet *relation_set;
GtkRadioGroup *group;
GSList *list; GSList *list;
guint list_length;
GailRadioMenuItem *radio_menu_item; GailRadioMenuItem *radio_menu_item;
g_return_val_if_fail (GAIL_IS_RADIO_MENU_ITEM (obj), NULL); g_return_val_if_fail (GAIL_IS_RADIO_MENU_ITEM (obj), NULL);
@@ -89,9 +92,12 @@ gail_radio_menu_item_ref_relation_set (AtkObject *obj)
/* /*
* If the radio menu_item'group has changed remove the relation * If the radio menu_item'group has changed remove the relation
*/ */
list = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (widget)); group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (widget));
list = gtk_radio_group_get_items (group);
list_length = g_slist_length (list);
if (radio_menu_item->old_group != list) if (radio_menu_item->old_group != group ||
radio_menu_item->old_group_size != list_length)
{ {
AtkRelation *relation; AtkRelation *relation;
@@ -105,15 +111,14 @@ gail_radio_menu_item_ref_relation_set (AtkObject *obj)
* Get the members of the menu_item group * Get the members of the menu_item group
*/ */
radio_menu_item->old_group = list; radio_menu_item->old_group = group;
radio_menu_item->old_group_size = list_length;
if (list) if (list)
{ {
AtkObject **accessible_array; AtkObject **accessible_array;
guint list_length;
AtkRelation* relation; AtkRelation* relation;
gint i = 0; gint i = 0;
list_length = g_slist_length (list);
accessible_array = (AtkObject**) g_malloc (sizeof (AtkObject *) * accessible_array = (AtkObject**) g_malloc (sizeof (AtkObject *) *
list_length); list_length);
while (list != NULL) while (list != NULL)
@@ -135,5 +140,6 @@ gail_radio_menu_item_ref_relation_set (AtkObject *obj)
g_object_unref (relation); g_object_unref (relation);
} }
} }
g_slist_free (list);
return relation_set; return relation_set;
} }

View File

@@ -38,7 +38,8 @@ struct _GailRadioMenuItem
{ {
GailCheckMenuItem parent; GailCheckMenuItem parent;
GSList *old_group; GtkRadioGroup *old_group;
guint old_group_size;
}; };
GType gail_radio_menu_item_get_type (void); GType gail_radio_menu_item_get_type (void);

View File

@@ -58,6 +58,7 @@ static void
gail_radio_sub_menu_item_init (GailRadioSubMenuItem *radio_menu_item) gail_radio_sub_menu_item_init (GailRadioSubMenuItem *radio_menu_item)
{ {
radio_menu_item->old_group = NULL; radio_menu_item->old_group = NULL;
radio_menu_item->old_group_size = 0;
} }
AtkRelationSet* AtkRelationSet*
@@ -65,7 +66,9 @@ gail_radio_sub_menu_item_ref_relation_set (AtkObject *obj)
{ {
GtkWidget *widget; GtkWidget *widget;
AtkRelationSet *relation_set; AtkRelationSet *relation_set;
GtkRadioGroup *group;
GSList *list; GSList *list;
guint list_length;
GailRadioSubMenuItem *radio_menu_item; GailRadioSubMenuItem *radio_menu_item;
g_return_val_if_fail (GAIL_IS_RADIO_SUB_MENU_ITEM (obj), NULL); g_return_val_if_fail (GAIL_IS_RADIO_SUB_MENU_ITEM (obj), NULL);
@@ -85,9 +88,12 @@ gail_radio_sub_menu_item_ref_relation_set (AtkObject *obj)
/* /*
* If the radio menu_item'group has changed remove the relation * If the radio menu_item'group has changed remove the relation
*/ */
list = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (widget)); group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (widget));
list = gtk_radio_group_get_items (group);
list_length = g_slist_length (list);
if (radio_menu_item->old_group != list) if (radio_menu_item->old_group != group ||
radio_menu_item->old_group_size != list_length)
{ {
AtkRelation *relation; AtkRelation *relation;
@@ -101,15 +107,14 @@ gail_radio_sub_menu_item_ref_relation_set (AtkObject *obj)
* Get the members of the menu_item group * Get the members of the menu_item group
*/ */
radio_menu_item->old_group = list; radio_menu_item->old_group = group;
radio_menu_item->old_group_size = list_length;
if (list) if (list)
{ {
AtkObject **accessible_array; AtkObject **accessible_array;
guint list_length;
AtkRelation* relation; AtkRelation* relation;
gint i = 0; gint i = 0;
list_length = g_slist_length (list);
accessible_array = (AtkObject**) g_malloc (sizeof (AtkObject *) * accessible_array = (AtkObject**) g_malloc (sizeof (AtkObject *) *
list_length); list_length);
while (list != NULL) while (list != NULL)
@@ -131,5 +136,6 @@ gail_radio_sub_menu_item_ref_relation_set (AtkObject *obj)
g_object_unref (relation); g_object_unref (relation);
} }
} }
g_slist_free (list);
return relation_set; return relation_set;
} }

View File

@@ -38,7 +38,8 @@ struct _GailRadioSubMenuItem
{ {
GailCheckSubMenuItem parent; GailCheckSubMenuItem parent;
GSList *old_group; GtkRadioGroup *old_group;
guint old_group_size;
}; };
GType gail_radio_sub_menu_item_get_type (void); GType gail_radio_sub_menu_item_get_type (void);

View File

@@ -174,24 +174,26 @@ build_alpha_widgets (void)
GtkWidget *hbox; GtkWidget *hbox;
GtkWidget *label; GtkWidget *label;
GtkWidget *entry; GtkWidget *entry;
GtkRadioGroup *group;
table = gtk_table_new (1, 1, FALSE); table = gtk_table_new (1, 1, FALSE);
radio_button = gtk_radio_button_new_with_label (NULL, "Red"); group = gtk_radio_group_new ();
radio_button = gtk_radio_button_new_with_label (group, "Red");
gtk_table_attach (GTK_TABLE (table), gtk_table_attach (GTK_TABLE (table),
radio_button, radio_button,
0, 1, 0, 1, 0, 1, 0, 1,
GTK_EXPAND | GTK_FILL, 0, GTK_EXPAND | GTK_FILL, 0,
0, 0); 0, 0);
radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Green"); radio_button = gtk_radio_button_new_with_label (group, "Green");
gtk_table_attach (GTK_TABLE (table), gtk_table_attach (GTK_TABLE (table),
radio_button, radio_button,
0, 1, 1, 2, 0, 1, 1, 2,
GTK_EXPAND | GTK_FILL, 0, GTK_EXPAND | GTK_FILL, 0,
0, 0); 0, 0);
radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Blue"), radio_button = gtk_radio_button_new_with_label (group, "Blue"),
gtk_table_attach (GTK_TABLE (table), gtk_table_attach (GTK_TABLE (table),
radio_button, radio_button,
0, 1, 2, 3, 0, 1, 2, 3,
@@ -214,14 +216,14 @@ build_alpha_widgets (void)
GTK_EXPAND | GTK_FILL, 0, GTK_EXPAND | GTK_FILL, 0,
0, 0); 0, 0);
radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Green"); radio_button = gtk_radio_button_new_with_label (group, "Green");
gtk_table_attach (GTK_TABLE (table), gtk_table_attach (GTK_TABLE (table),
radio_button, radio_button,
0, 1, 1, 2, 0, 1, 1, 2,
GTK_EXPAND | GTK_FILL, 0, GTK_EXPAND | GTK_FILL, 0,
0, 0); 0, 0);
radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Blue"), radio_button = gtk_radio_button_new_with_label (group, "Blue"),
gtk_table_attach (GTK_TABLE (table), gtk_table_attach (GTK_TABLE (table),
radio_button, radio_button,
0, 1, 2, 3, 0, 1, 2, 3,
@@ -856,7 +858,7 @@ static GtkWidget *
create_widget_grid (GType widget_type) create_widget_grid (GType widget_type)
{ {
GtkWidget *table; GtkWidget *table;
GtkWidget *group_widget = NULL; GtkRadioGroup *group = NULL;
gint i, j; gint i, j;
table = gtk_table_new (FALSE, 3, 3); table = gtk_table_new (FALSE, 3, 3);
@@ -890,10 +892,9 @@ create_widget_grid (GType widget_type)
if (g_type_is_a (widget_type, GTK_TYPE_RADIO_BUTTON)) if (g_type_is_a (widget_type, GTK_TYPE_RADIO_BUTTON))
{ {
if (!group_widget) if (!group)
group_widget = widget; group = gtk_radio_group_new ();
else g_object_set (widget, "group", group, NULL);
g_object_set (widget, "group", group_widget, NULL);
} }
} }
@@ -2928,7 +2929,7 @@ create_menu (GdkScreen *screen, gint depth, gint length, gboolean tearoff)
GtkWidget *menu; GtkWidget *menu;
GtkWidget *menuitem; GtkWidget *menuitem;
GtkWidget *image; GtkWidget *image;
GSList *group; GtkRadioGroup *group;
char buf[32]; char buf[32];
int i, j; int i, j;
@@ -2955,12 +2956,12 @@ create_menu (GdkScreen *screen, gint depth, gint length, gboolean tearoff)
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem); gtk_widget_show (menuitem);
group = gtk_radio_group_new ();
for (i = 0, j = 1; i < length; i++, j++) for (i = 0, j = 1; i < length; i++, j++)
{ {
sprintf (buf, "item %2d - %d", depth, j); sprintf (buf, "item %2d - %d", depth, j);
menuitem = gtk_radio_menu_item_new_with_label (group, buf); menuitem = gtk_radio_menu_item_new_with_label (group, buf);
group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem); gtk_widget_show (menuitem);

View File

@@ -515,7 +515,7 @@ main (gint argc, gchar **argv)
GtkWidget *button; GtkWidget *button;
GtkWidget *label; GtkWidget *label;
GIcon *gicon; GIcon *gicon;
GSList *group; GtkRadioGroup *group;
gtk_init (&argc, &argv); gtk_init (&argc, &argv);
@@ -672,8 +672,8 @@ main (gint argc, gchar **argv)
gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (item), FALSE); gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (item), FALSE);
g_assert (gtk_toolbar_get_nth_item (GTK_TOOLBAR (toolbar), 0) != 0); g_assert (gtk_toolbar_get_nth_item (GTK_TOOLBAR (toolbar), 0) != 0);
item = gtk_radio_tool_button_new_from_stock (NULL, GTK_STOCK_JUSTIFY_LEFT); group = gtk_radio_group_new ();
group = gtk_radio_tool_button_get_group (GTK_RADIO_TOOL_BUTTON (item)); item = gtk_radio_tool_button_new_from_stock (group, GTK_STOCK_JUSTIFY_LEFT);
add_item_to_list (store, item, "Left"); add_item_to_list (store, item, "Left");
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
@@ -681,7 +681,6 @@ main (gint argc, gchar **argv)
item = gtk_radio_tool_button_new_from_stock (group, GTK_STOCK_JUSTIFY_CENTER); item = gtk_radio_tool_button_new_from_stock (group, GTK_STOCK_JUSTIFY_CENTER);
make_prop_editor (G_OBJECT (item)); make_prop_editor (G_OBJECT (item));
group = gtk_radio_tool_button_get_group (GTK_RADIO_TOOL_BUTTON (item));
add_item_to_list (store, item, "Center"); add_item_to_list (store, item, "Center");
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);