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 *menuitem;
GSList *group;
GtkRadioGroup *group;
char buf[32];
int i, j;
@@ -52,11 +52,11 @@ create_menu (gint depth,
gtk_widget_show (menuitem);
}
group = gtk_radio_group_new ();
for (i = 0, j = 1; i < 5; i++, j++)
{
sprintf (buf, "item %2d - %d", depth, j);
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_widget_show (menuitem);

View File

@@ -690,7 +690,7 @@ load_stock_items (GtkToolPalette *palette)
static void
load_toggle_items (GtkToolPalette *palette)
{
GSList *toggle_group = NULL;
GtkRadioGroup *toggle_group;
GtkToolItem *item;
GtkWidget *group;
char *label;
@@ -699,6 +699,7 @@ load_toggle_items (GtkToolPalette *palette)
group = gtk_tool_item_group_new ("Radio Item");
gtk_container_add (GTK_CONTAINER (palette), group);
toggle_group = gtk_radio_group_new ();
for (i = 1; i <= 10; ++i)
{
label = g_strdup_printf ("#%d", i);
@@ -707,7 +708,6 @@ load_toggle_items (GtkToolPalette *palette)
g_free (label);
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 *radio;
GtkWidget *align;
GtkRadioGroup *group;
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);
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);
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);
align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
gtk_container_add (GTK_CONTAINER (align), widget);

View File

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

View File

@@ -258,6 +258,7 @@ gtk_public_h_sources = \
gtkprogressbar.h \
gtkradioaction.h \
gtkradiobutton.h \
gtkradiogroup.h \
gtkradiomenuitem.h \
gtkradiotoolbutton.h \
gtkrange.h \
@@ -378,6 +379,7 @@ gtk_private_h_sources = \
gtkprintoperation-private.h\
gtkprintutils.h \
gtkprivate.h \
gtkradiogroupprivate.h \
gtkrbtree.h \
gtkrecentchooserdefault.h \
gtkrecentchooserprivate.h \
@@ -530,6 +532,7 @@ gtk_base_c_sources = \
gtkprogressbar.c \
gtkradioaction.c \
gtkradiobutton.c \
gtkradiogroup.c \
gtkradiomenuitem.c \
gtkradiotoolbutton.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.
*/
guint i;
GSList *group = NULL;
GtkRadioGroup *radio_group = NULL;
GtkRadioAction *first_action = NULL;
g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
radio_group = gtk_radio_group_new ();
for (i = 0; i < n_entries; i++)
{
GtkRadioAction *action;
@@ -1338,8 +1339,7 @@ gtk_action_group_add_radio_actions_full (GtkActionGroup *action_group
if (i == 0)
first_action = action;
gtk_radio_action_set_group (action, group);
group = gtk_radio_action_get_group (action);
gtk_radio_action_set_group (action, radio_group);
if (value == entries[i].value)
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;
const GtkIMContextInfo **contexts;
guint n_contexts, i;
GSList *group = NULL;
GtkRadioGroup *group;
GtkWidget *menuitem, *system_menuitem;
const char *system_context_id;
group = gtk_radio_group_new ();
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"));
if (!priv->context_id_aux)
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_signal_connect (menuitem, "activate", G_CALLBACK (activate_cb), context);
@@ -602,8 +602,7 @@ gtk_im_multicontext_append_menuitems (GtkIMMulticontext *context,
g_signal_connect (menuitem, "activate", G_CALLBACK (activate_cb), context);
gtk_widget_show (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 ();
gtk_widget_show (menuitem);
gtk_menu_shell_append (menushell, menuitem);
@@ -681,10 +680,8 @@ gtk_im_multicontext_append_menuitems (GtkIMMulticontext *context,
text = g_strdup_printf (C_("input method menu", "System (%s)"), translated_name);
gtk_label_set_text (GTK_LABEL (label), 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"),
(char *)contexts[i]->context_id);
g_signal_connect (menuitem, "activate",

View File

@@ -549,7 +549,7 @@ gtk_mount_operation_ask_password (GMountOperation *mount_op,
{
GtkWidget *anon_box;
GtkWidget *choice;
GSList *group;
GtkRadioGroup *group;
anon_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
gtk_box_pack_start (GTK_BOX (vbox), anon_box,
@@ -622,7 +622,7 @@ gtk_mount_operation_ask_password (GMountOperation *mount_op,
{
GtkWidget *choice;
GtkWidget *remember_box;
GSList *group;
GtkRadioGroup *group;
GPasswordSave password_save;
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);
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"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (choice),
password_save == G_PASSWORD_SAVE_PERMANENTLY);

View File

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

View File

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

View File

@@ -32,6 +32,7 @@
#include "gtkradioaction.h"
#include "gtkradiomenuitem.h"
#include "gtkradiogroupprivate.h"
#include "gtktoggletoolbutton.h"
#include "gtkintl.h"
#include "gtkprivate.h"
@@ -49,7 +50,7 @@
struct _GtkRadioActionPrivate
{
GSList *group;
GtkRadioGroup *group;
gint value;
};
@@ -133,9 +134,9 @@ gtk_radio_action_class_init (GtkRadioActionClass *klass)
PROP_GROUP,
g_param_spec_object ("group",
P_("Group"),
P_("The radio action whose group this action belongs to."),
GTK_TYPE_RADIO_ACTION,
GTK_PARAM_WRITABLE));
P_("The radio group this action belongs to."),
GTK_TYPE_RADIO_GROUP,
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
/**
* GtkRadioAction:current-value:
@@ -184,7 +185,7 @@ gtk_radio_action_init (GtkRadioAction *action)
GTK_TYPE_RADIO_ACTION,
GtkRadioActionPrivate);
action->private_data->group = g_slist_prepend (NULL, action);
action->private_data->group = NULL;
action->private_data->value = 0;
gtk_toggle_action_set_draw_as_radio (GTK_TOGGLE_ACTION (action), TRUE);
@@ -230,20 +231,18 @@ static void
gtk_radio_action_finalize (GObject *object)
{
GtkRadioAction *action;
GSList *tmp_list;
GtkRadioActionPrivate *priv;
action = GTK_RADIO_ACTION (object);
priv = action->private_data;
action->private_data->group = g_slist_remove (action->private_data->group, action);
tmp_list = action->private_data->group;
while (tmp_list)
if (priv->group)
{
GtkRadioAction *tmp_action = tmp_list->data;
_gtk_radio_group_remove_item (priv->group, object);
tmp_list = tmp_list->next;
tmp_action->private_data->group = action->private_data->group;
/* this action is no longer in the group */
g_object_unref (priv->group);
priv->group = NULL;
}
G_OBJECT_CLASS (gtk_radio_action_parent_class)->finalize (object);
@@ -264,18 +263,12 @@ gtk_radio_action_set_property (GObject *object,
case PROP_VALUE:
radio_action->private_data->value = g_value_get_int (value);
break;
case PROP_GROUP:
case PROP_GROUP:
{
GtkRadioAction *arg;
GSList *slist = NULL;
if (G_VALUE_HOLDS_OBJECT (value))
{
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);
}
GtkRadioGroup *group;
group = g_value_get_object (value);
gtk_radio_action_set_group (radio_action, group);
}
break;
case PROP_CURRENT_VALUE:
@@ -300,6 +293,9 @@ gtk_radio_action_get_property (GObject *object,
switch (prop_id)
{
case PROP_GROUP:
g_value_set_object (value, gtk_radio_action_get_group (radio_action));
break;
case PROP_VALUE:
g_value_set_int (value, radio_action->private_data->value);
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
gtk_radio_action_activate (GtkAction *action)
{
GtkRadioAction *radio_action;
GtkToggleAction *toggle_action;
GtkRadioActionPrivate *priv;
GtkToggleAction *tmp_action;
GSList *tmp_list;
GObject *active_item;
GSList *list, *l;
gboolean active;
gint toggled;
radio_action = GTK_RADIO_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);
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;
tmp_list = tmp_list->next;
if (gtk_toggle_action_get_active (tmp_action) &&
(tmp_action != toggle_action))
{
_gtk_toggle_action_set_active (toggle_action, !active);
break;
}
toggled = TRUE;
_gtk_toggle_action_set_active (toggle_action, !active);
}
g_object_notify (G_OBJECT (action), "active");
}
else
{
toggled = TRUE;
_gtk_toggle_action_set_active (toggle_action, !active);
g_object_notify (G_OBJECT (action), "active");
tmp_list = radio_action->private_data->group;
while (tmp_list)
{
tmp_action = tmp_list->data;
tmp_list = tmp_list->next;
active_item = gtk_radio_group_get_active_item (priv->group);
_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));
if (gtk_toggle_action_get_active (tmp_action) &&
(tmp_action != toggle_action))
{
_gtk_action_emit_activate (GTK_ACTION (tmp_action));
break;
}
}
tmp_list = radio_action->private_data->group;
while (tmp_list)
list = gtk_radio_group_get_items (priv->group);
for (l = list; l != NULL; l = l->next)
{
tmp_action = tmp_list->data;
tmp_list = tmp_list->next;
g_object_notify (G_OBJECT (tmp_action), "current-value");
tmp_action = l->data;
g_object_notify (G_OBJECT (tmp_action), "current-value");
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 *
@@ -391,138 +395,61 @@ create_menu_item (GtkAction *action)
* gtk_radio_action_get_group:
* @action: the action object
*
* Returns the list representing the radio group for this object.
* Note that the returned list is only valid until the next change
* to the group.
* Retrieves the radio group this object is part of.
*
* A common way to set up a group of radio group is the following:
* |[
* GSList *group = NULL;
* 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
* Return value: (transfer none): a #GtkRadioGroup
* containing all the radio buttons in the same group
* as @radio_action.
*
* Since: 2.4
*/
GSList *
GtkRadioGroup *
gtk_radio_action_get_group (GtkRadioAction *action)
{
g_return_val_if_fail (GTK_IS_RADIO_ACTION (action), NULL);
gtk_radio_action_ensure_group (action);
return action->private_data->group;
}
/**
* gtk_radio_action_set_group:
* @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.
*
* Since: 2.4
*/
void
gtk_radio_action_set_group (GtkRadioAction *action,
GSList *group)
gtk_radio_action_set_group (GtkRadioAction *action,
GtkRadioGroup *group)
{
GtkRadioActionPrivate *priv;
gboolean is_active;
g_return_if_fail (GTK_IS_RADIO_ACTION (action));
g_return_if_fail (!g_slist_find (group, action));
if (action->private_data->group)
{
GSList *slist;
priv = action->private_data;
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)
{
GtkRadioAction *tmp_action = slist->data;
if (group == NULL)
group = gtk_radio_group_new ();
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)
{
GSList *slist;
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);
}
is_active = gtk_radio_group_get_active_item (group) == G_OBJECT (action);
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), is_active);
if (is_active)
_gtk_radio_group_emit_active_changed (group);
}
/**
@@ -539,22 +466,15 @@ gtk_radio_action_join_group (GtkRadioAction *action,
gint
gtk_radio_action_get_current_value (GtkRadioAction *action)
{
GSList *slist;
GObject *active_action;
g_return_val_if_fail (GTK_IS_RADIO_ACTION (action), 0);
if (action->private_data->group)
{
for (slist = action->private_data->group; slist; slist = slist->next)
{
GtkToggleAction *toggle_action = slist->data;
gtk_radio_action_ensure_group (action);
if (gtk_toggle_action_get_active (toggle_action))
return GTK_RADIO_ACTION (toggle_action)->private_data->value;
}
}
active_action = gtk_radio_group_get_active_item (action->private_data->group);
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,
gint current_value)
{
GSList *slist;
GSList *slist, *l;
g_return_if_fail (GTK_IS_RADIO_ACTION (action));
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)
{
@@ -588,6 +509,7 @@ gtk_radio_action_set_current_value (GtkRadioAction *action,
return;
}
}
g_slist_free (slist);
}
if (action->private_data->value == current_value)

View File

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

View File

@@ -28,6 +28,7 @@
#include "gtklabel.h"
#include "gtkmarshalers.h"
#include "gtkradiobutton.h"
#include "gtkradiogroupprivate.h"
#include "gtkprivate.h"
#include "gtkintl.h"
@@ -46,11 +47,10 @@
* 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.
*
* Radio button widgets are created with gtk_radio_button_new(), passing %NULL
* as the argument if this is the first radio button in a group. In subsequent
* calls, the group you wish to add this button to should be passed as an
* argument. Optionally, gtk_radio_button_new_with_label() can be used if you
* want a text label on the radio button.
* Radio button widgets are created with gtk_radio_button_new(), passing in a
* #GtkRadioGroup created with gtk_radio_group_new() (or %NULL to automatically
* create a new group for the button). Optionally, gtk_radio_button_new_with_label()
* can be used if you want a text label on the radio button.
*
* Alternatively, when adding widgets to an existing group of radio buttons,
* use gtk_radio_button_new_from_widget() with a #GtkRadioButton that already
@@ -72,18 +72,21 @@
* void create_radio_buttons (void) {
*
* GtkWidget *window, *radio1, *radio2, *box, *entry;
* GtkRadioGroup *group;
*
* window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
* box = gtk_box_new (GTK_ORIENTATION_VERTICAL, TRUE, 2);
*
* /&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 (<!-- -->);
* gtk_container_add (GTK_CONTAINER (radio1), entry);
*
*
* /&ast; Create a radio button with a label &ast;/
* radio2 = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio1),
* "I'm the second radio button.");
* radio2 = gtk_radio_button_new_with_label (group,
* "I'm the second radio button.");
*
* /&ast; Pack them into a box, then show all the widgets &ast;/
* gtk_box_pack_start (GTK_BOX (box), radio1, TRUE, TRUE, 2);
@@ -100,12 +103,14 @@
* selected button.
* Inside the #GtkToggleButton::toggled handler, gtk_toggle_button_get_active()
* 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
{
GSList *group;
GtkRadioGroup *group;
};
enum {
@@ -158,9 +163,9 @@ gtk_radio_button_class_init (GtkRadioButtonClass *class)
PROP_GROUP,
g_param_spec_object ("group",
P_("Group"),
P_("The radio button whose group this widget belongs to."),
GTK_TYPE_RADIO_BUTTON,
GTK_PARAM_WRITABLE));
P_("The radio group this button belongs to."),
GTK_TYPE_RADIO_GROUP,
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
widget_class->destroy = gtk_radio_button_destroy;
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;
priv->group = g_slist_prepend (NULL, radio_button);
priv->group = NULL;
_gtk_button_set_depressed (GTK_BUTTON (radio_button), TRUE);
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)
{
GSList *slist;
GtkRadioButton *button;
GtkRadioGroup *group;
case PROP_GROUP:
button = g_value_get_object (value);
if (button)
slist = gtk_radio_button_get_group (button);
else
slist = NULL;
gtk_radio_button_set_group (radio_button, slist);
group = g_value_get_object (value);
gtk_radio_button_set_group (radio_button, group);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -253,19 +252,38 @@ gtk_radio_button_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
GtkRadioButton *radio_button;
radio_button = GTK_RADIO_BUTTON (object);
switch (prop_id)
{
case PROP_GROUP:
g_value_set_object (value, gtk_radio_button_get_group (radio_button));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
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:
* @radio_button: a #GtkRadioButton.
* @group: (transfer none) (element-type GtkRadioButton): an existing radio
* button group, such as one returned from gtk_radio_button_get_group().
* @group: (allow-none): an existing #GtkRadioGroup or %NULL
* to remove the radio button from its current group
*
* 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,
@@ -274,57 +292,44 @@ gtk_radio_button_get_property (GObject *object,
*/
void
gtk_radio_button_set_group (GtkRadioButton *radio_button,
GSList *group)
GtkRadioGroup *group)
{
GtkRadioButtonPrivate *priv;
GtkWidget *old_group_singleton = NULL;
GtkWidget *new_group_singleton = NULL;
GObject *old_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 (!g_slist_find (group, radio_button));
priv = radio_button->priv;
if (priv->group == group)
return;
if (group == NULL)
group = gtk_radio_group_new ();
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)
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;
}
g_object_unref (priv->group);
}
if (group && !group->next)
new_group_singleton = g_object_ref (group->data);
priv->group = g_slist_prepend (group, radio_button);
priv->group = g_object_ref_sink (group);
new_group_singleton = _gtk_radio_group_get_singleton (group);
if (group)
{
GSList *slist;
for (slist = group; slist; slist = slist->next)
{
GtkRadioButton *tmp_button;
tmp_button = slist->data;
tmp_button->priv->group = priv->group;
}
}
_gtk_radio_group_add_item (group, G_OBJECT (radio_button));
g_object_ref (radio_button);
g_object_notify (G_OBJECT (radio_button), "group");
g_signal_emit (radio_button, group_changed_signal, 0);
if (old_group_singleton)
@@ -338,66 +343,15 @@ gtk_radio_button_set_group (GtkRadioButton *radio_button,
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);
}
/**
* 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:
* @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
*/
GtkWidget*
gtk_radio_button_new (GSList *group)
gtk_radio_button_new (GtkRadioGroup *group)
{
GtkRadioButton *radio_button;
radio_button = g_object_new (GTK_TYPE_RADIO_BUTTON, NULL);
if (group)
gtk_radio_button_set_group (radio_button, group);
radio_button = g_object_new (GTK_TYPE_RADIO_BUTTON, "group", group, NULL);
return GTK_WIDGET (radio_button);
}
@@ -431,16 +382,12 @@ gtk_radio_button_new (GSList *group)
* Returns: (transfer full): a new radio button.
*/
GtkWidget*
gtk_radio_button_new_with_label (GSList *group,
gtk_radio_button_new_with_label (GtkRadioGroup *group,
const gchar *label)
{
GtkWidget *radio_button;
radio_button = g_object_new (GTK_TYPE_RADIO_BUTTON, "label", label, NULL) ;
if (group)
gtk_radio_button_set_group (GTK_RADIO_BUTTON (radio_button), group);
radio_button = g_object_new (GTK_TYPE_RADIO_BUTTON, "group", group, "label", label, NULL) ;
return radio_button;
}
@@ -459,19 +406,17 @@ gtk_radio_button_new_with_label (GSList *group,
* Returns: (transfer full): a new #GtkRadioButton
*/
GtkWidget*
gtk_radio_button_new_with_mnemonic (GSList *group,
gtk_radio_button_new_with_mnemonic (GtkRadioGroup *group,
const gchar *label)
{
GtkWidget *radio_button;
radio_button = g_object_new (GTK_TYPE_RADIO_BUTTON,
"label", label,
"use-underline", TRUE,
radio_button = g_object_new (GTK_TYPE_RADIO_BUTTON,
"group", group,
"label", label,
"use-underline", TRUE,
NULL);
if (group)
gtk_radio_button_set_group (GTK_RADIO_BUTTON (radio_button), group);
return radio_button;
}
@@ -488,10 +433,10 @@ gtk_radio_button_new_with_mnemonic (GSList *group,
GtkWidget*
gtk_radio_button_new_from_widget (GtkRadioButton *radio_group_member)
{
GSList *l = NULL;
GtkRadioGroup *group = NULL;
if (radio_group_member)
l = gtk_radio_button_get_group (radio_group_member);
return gtk_radio_button_new (l);
group = gtk_radio_button_get_group (radio_group_member);
return gtk_radio_button_new (group);
}
/**
@@ -508,10 +453,10 @@ GtkWidget*
gtk_radio_button_new_with_label_from_widget (GtkRadioButton *radio_group_member,
const gchar *label)
{
GSList *l = NULL;
GtkRadioGroup *group = NULL;
if (radio_group_member)
l = gtk_radio_button_get_group (radio_group_member);
return gtk_radio_button_new_with_label (l, label);
group = gtk_radio_button_get_group (radio_group_member);
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,
const gchar *label)
{
GSList *l = NULL;
GtkRadioGroup *group = NULL;
if (radio_group_member)
l = gtk_radio_button_get_group (radio_group_member);
return gtk_radio_button_new_with_mnemonic (l, label);
group = gtk_radio_button_get_group (radio_group_member);
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.
*
* 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
* as @radio_button. The returned list is owned by the radio button
* and must not be modified or freed.
* as @radio_button.
*/
GSList*
GtkRadioGroup *
gtk_radio_button_get_group (GtkRadioButton *radio_button)
{
g_return_val_if_fail (GTK_IS_RADIO_BUTTON (radio_button), NULL);
gtk_radio_button_ensure_group (radio_button);
return radio_button->priv->group;
}
@@ -560,32 +506,22 @@ gtk_radio_button_get_group (GtkRadioButton *radio_button)
static void
gtk_radio_button_destroy (GtkWidget *widget)
{
GtkWidget *old_group_singleton = NULL;
GObject *old_group_singleton = NULL;
GtkRadioButton *radio_button = GTK_RADIO_BUTTON (widget);
GtkRadioButtonPrivate *priv = radio_button->priv;
GtkRadioButton *tmp_button;
GSList *tmp_list;
gboolean was_in_group;
gboolean was_in_group = FALSE;
was_in_group = priv->group && priv->group->next;
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)
if (priv->group)
{
tmp_button = tmp_list->data;
tmp_list = tmp_list->next;
_gtk_radio_group_remove_item (priv->group, G_OBJECT (radio_button));
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)
g_signal_emit (old_group_singleton, group_changed_signal, 0);
if (was_in_group)
@@ -647,14 +583,15 @@ gtk_radio_button_focus (GtkWidget *widget,
{
GtkRadioButton *radio_button = GTK_RADIO_BUTTON (widget);
GtkRadioButtonPrivate *priv = radio_button->priv;
GSList *tmp_slist;
/* Radio buttons with draw_indicator unset focus "normally", since
* they look like buttons to the user.
*/
if (!gtk_toggle_button_get_mode (GTK_TOGGLE_BUTTON (widget)))
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))
{
GtkSettings *settings = gtk_widget_get_settings (widget);
@@ -668,12 +605,12 @@ gtk_radio_button_focus (GtkWidget *widget,
{
case GTK_DIR_LEFT:
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);
break;
case GTK_DIR_UP:
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);
break;
case GTK_DIR_TAB_FORWARD:
@@ -756,22 +693,15 @@ gtk_radio_button_focus (GtkWidget *widget,
}
else
{
GtkRadioButton *selected_button = NULL;
GObject *selected_button;
/* We accept the focus if, we don't have the focus and
* - we are the currently active button in the group
* - there is no currently active radio button.
*/
tmp_slist = priv->group;
while (tmp_slist)
{
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)
selected_button = gtk_radio_group_get_active_item (priv->group);
if (selected_button && selected_button != G_OBJECT (radio_button))
return FALSE;
gtk_widget_grab_focus (widget);
@@ -785,34 +715,22 @@ gtk_radio_button_clicked (GtkButton *button)
GtkRadioButton *radio_button = GTK_RADIO_BUTTON (button);
GtkRadioButtonPrivate *priv = radio_button->priv;
GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (button);
GtkToggleButton *tmp_button;
GObject *active_item;
GtkStateType new_state;
GSList *tmp_list;
gint toggled;
gboolean depressed;
gtk_radio_button_ensure_group (radio_button);
toggled = FALSE;
g_object_ref (GTK_WIDGET (button));
if (gtk_toggle_button_get_active (toggle_button))
{
tmp_button = NULL;
tmp_list = priv->group;
active_item = gtk_radio_group_get_active_item (priv->group);
while (tmp_list)
{
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)
if (active_item == NULL || active_item == G_OBJECT (button))
{
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_get_active (toggle_button));
tmp_list = priv->group;
while (tmp_list)
{
tmp_button = tmp_list->data;
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;
}
}
active_item = gtk_radio_group_get_active_item (priv->group);
_gtk_radio_group_set_active_item (priv->group, G_OBJECT (toggle_button));
if (active_item != G_OBJECT (toggle_button))
gtk_button_clicked (GTK_BUTTON (active_item));
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);
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);

View File

@@ -33,6 +33,7 @@
#include <gtk/gtkcheckbutton.h>
#include <gtk/gtkradiogroup.h>
G_BEGIN_DECLS
@@ -74,21 +75,22 @@ struct _GtkRadioButtonClass
GType gtk_radio_button_get_type (void) G_GNUC_CONST;
GtkWidget* gtk_radio_button_new (GSList *group);
GtkWidget* gtk_radio_button_new_from_widget (GtkRadioButton *radio_group_member);
GtkWidget* gtk_radio_button_new_with_label (GSList *group,
const gchar *label);
GtkWidget* gtk_radio_button_new_with_label_from_widget (GtkRadioButton *radio_group_member,
const gchar *label);
GtkWidget* gtk_radio_button_new_with_mnemonic (GSList *group,
const gchar *label);
GtkWidget* gtk_radio_button_new_with_mnemonic_from_widget (GtkRadioButton *radio_group_member,
const gchar *label);
GSList* gtk_radio_button_get_group (GtkRadioButton *radio_button);
void gtk_radio_button_set_group (GtkRadioButton *radio_button,
GSList *group);
void gtk_radio_button_join_group (GtkRadioButton *radio_button,
GtkRadioButton *group_source);
GtkWidget* gtk_radio_button_new (GtkRadioGroup *group);
GtkWidget* gtk_radio_button_new_with_label (GtkRadioGroup *group,
const gchar *label);
GtkWidget* gtk_radio_button_new_with_mnemonic (GtkRadioGroup *group,
const gchar *label);
#ifndef GTK_DISABLE_DEPRECATED
GtkWidget* gtk_radio_button_new_from_widget (GtkRadioButton *radio_group_member);
GtkWidget* gtk_radio_button_new_with_label_from_widget (GtkRadioButton *radio_group_member,
const gchar *label);
GtkWidget* gtk_radio_button_new_with_mnemonic_from_widget (GtkRadioButton *radio_group_member,
const gchar *label);
#endif
GtkRadioGroup *gtk_radio_button_get_group (GtkRadioButton *radio_button);
void gtk_radio_button_set_group (GtkRadioButton *radio_button,
GtkRadioGroup *group);
G_END_DECLS
#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 "gtkmarshalers.h"
#include "gtkradiomenuitem.h"
#include "gtkradiogroupprivate.h"
#include "gtkactivatable.h"
#include "gtkprivate.h"
#include "gtkintl.h"
@@ -35,7 +36,7 @@
struct _GtkRadioMenuItemPrivate
{
GSList *group;
GtkRadioGroup *group;
};
enum {
@@ -60,13 +61,11 @@ static guint group_changed_signal = 0;
G_DEFINE_TYPE (GtkRadioMenuItem, gtk_radio_menu_item, GTK_TYPE_CHECK_MENU_ITEM)
GtkWidget*
gtk_radio_menu_item_new (GSList *group)
gtk_radio_menu_item_new (GtkRadioGroup *group)
{
GtkRadioMenuItem *radio_menu_item;
radio_menu_item = g_object_new (GTK_TYPE_RADIO_MENU_ITEM, NULL);
gtk_radio_menu_item_set_group (radio_menu_item, group);
radio_menu_item = g_object_new (GTK_TYPE_RADIO_MENU_ITEM, "group", group, NULL);
return GTK_WIDGET (radio_menu_item);
}
@@ -83,14 +82,11 @@ gtk_radio_menu_item_set_property (GObject *object,
switch (prop_id)
{
GSList *slist;
GtkRadioGroup *group;
case PROP_GROUP:
if (G_VALUE_HOLDS_OBJECT (value))
slist = gtk_radio_menu_item_get_group ((GtkRadioMenuItem*) g_value_get_object (value));
else
slist = NULL;
gtk_radio_menu_item_set_group (radio_menu_item, slist);
group = g_value_get_object (value);
gtk_radio_menu_item_set_group (radio_menu_item, group);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -104,8 +100,15 @@ gtk_radio_menu_item_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
GtkRadioMenuItem *radio_menu_item;
radio_menu_item = GTK_RADIO_MENU_ITEM (object);
switch (prop_id)
{
case PROP_GROUP:
g_value_set_object (value, gtk_radio_menu_item_get_group (radio_menu_item));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -114,60 +117,41 @@ gtk_radio_menu_item_get_property (GObject *object,
void
gtk_radio_menu_item_set_group (GtkRadioMenuItem *radio_menu_item,
GSList *group)
GtkRadioGroup *group)
{
GtkRadioMenuItemPrivate *priv;
GtkWidget *old_group_singleton = NULL;
GtkWidget *new_group_singleton = NULL;
GObject *old_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 (!g_slist_find (group, radio_menu_item));
priv = radio_menu_item->priv;
if (priv->group == group)
return;
if (group == NULL)
group = gtk_radio_group_new ();
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)
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;
}
g_object_unref (priv->group);
}
if (group && !group->next)
new_group_singleton = g_object_ref (group->data);
priv->group = g_slist_prepend (group, radio_menu_item);
priv->group = g_object_ref_sink (group);
new_group_singleton = _gtk_radio_group_get_singleton (group);
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);
*/
}
_gtk_radio_group_add_item (group, G_OBJECT (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);
}
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);
}
/**
* gtk_radio_menu_item_new_with_label:
* @group: (element-type GtkRadioMenuItem) (transfer full):
* @group: a #GtkRadioMenuItem or %NULL
* @label: the text for the label
*
* 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
*/
GtkWidget*
gtk_radio_menu_item_new_with_label (GSList *group,
gtk_radio_menu_item_new_with_label (GtkRadioGroup *group,
const gchar *label)
{
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.
**/
GtkWidget*
gtk_radio_menu_item_new_with_mnemonic (GSList *group,
gtk_radio_menu_item_new_with_mnemonic (GtkRadioGroup *group,
const gchar *label)
{
GtkWidget *radio_menu_item;
@@ -258,14 +247,14 @@ gtk_radio_menu_item_new_with_mnemonic (GSList *group,
GtkWidget *
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);
if (group)
list = gtk_radio_menu_item_get_group (group);
return gtk_radio_menu_item_new (list);
radio_group = gtk_radio_menu_item_get_group (group);
return gtk_radio_menu_item_new (radio_group);
}
/**
@@ -288,14 +277,14 @@ GtkWidget *
gtk_radio_menu_item_new_with_mnemonic_from_widget (GtkRadioMenuItem *group,
const gchar *label)
{
GSList *list = NULL;
GtkRadioGroup *radio_group = NULL;
g_return_val_if_fail (GTK_IS_RADIO_MENU_ITEM (group), NULL);
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,
const gchar *label)
{
GSList *list = NULL;
GtkRadioGroup *radio_group = NULL;
g_return_val_if_fail (GTK_IS_RADIO_MENU_ITEM (group), NULL);
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:
* @radio_menu_item: a #GtkRadioMenuItem
*
* Returns the group to which the radio menu item belongs, as a #GList of
* #GtkRadioMenuItem. The list belongs to GTK+ and should not be freed.
* Retrieves the group to which the radio menu item belongs.
*
* 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)
{
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;
}
@@ -371,9 +376,9 @@ gtk_radio_menu_item_class_init (GtkRadioMenuItemClass *klass)
PROP_GROUP,
g_param_spec_object ("group",
P_("Group"),
P_("The radio menu item whose group this widget belongs to."),
GTK_TYPE_RADIO_MENU_ITEM,
GTK_PARAM_WRITABLE));
P_("The radio group this menu item belongs to."),
GTK_TYPE_RADIO_GROUP,
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
/**
* GtkStyle::group-changed:
@@ -409,7 +414,7 @@ gtk_radio_menu_item_init (GtkRadioMenuItem *radio_menu_item)
GtkRadioMenuItemPrivate);
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);
}
@@ -418,30 +423,20 @@ gtk_radio_menu_item_destroy (GtkWidget *widget)
{
GtkRadioMenuItem *radio_menu_item = GTK_RADIO_MENU_ITEM (widget);
GtkRadioMenuItemPrivate *priv = radio_menu_item->priv;
GtkWidget *old_group_singleton = NULL;
GtkRadioMenuItem *tmp_menu_item;
GSList *tmp_list;
gboolean was_in_group;
GObject *old_group_singleton = NULL;
gboolean was_in_group = FALSE;
was_in_group = priv->group && priv->group->next;
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)
if (priv->group)
{
tmp_menu_item = tmp_list->data;
tmp_list = tmp_list->next;
_gtk_radio_group_remove_item (priv->group, G_OBJECT (radio_menu_item));
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)
g_signal_emit (old_group_singleton, group_changed_signal, 0);
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);
GtkRadioMenuItemPrivate *priv = radio_menu_item->priv;
GtkCheckMenuItem *check_menu_item = GTK_CHECK_MENU_ITEM (menu_item);
GtkCheckMenuItem *tmp_menu_item;
GtkAction *action;
GSList *tmp_list;
GObject *active_item;
gboolean active;
gint toggled;
gtk_radio_menu_item_ensure_group (radio_menu_item);
action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (menu_item));
if (action && gtk_menu_item_get_submenu (menu_item) == NULL)
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);
if (active)
{
tmp_menu_item = NULL;
tmp_list = priv->group;
active_item = gtk_radio_group_get_active_item (priv->group);
while (tmp_list)
{
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)
if (active_item != G_OBJECT (menu_item))
{
toggled = TRUE;
_gtk_check_menu_item_set_active (check_menu_item, !active);
@@ -497,24 +480,17 @@ gtk_radio_menu_item_activate (GtkMenuItem *menu_item)
toggled = TRUE;
_gtk_check_menu_item_set_active (check_menu_item, !active);
tmp_list = priv->group;
while (tmp_list)
{
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)
{
gtk_menu_item_activate (GTK_MENU_ITEM (tmp_menu_item));
break;
}
}
active_item = gtk_radio_group_get_active_item (priv->group);
_gtk_radio_group_set_active_item (priv->group, G_OBJECT (menu_item));
if (active_item != G_OBJECT (menu_item))
gtk_menu_item_activate (GTK_MENU_ITEM (active_item));
}
if (toggled)
{
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));

View File

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

View File

@@ -36,6 +36,10 @@ static void gtk_radio_tool_button_set_property (GObject *object,
guint prop_id,
const GValue *value,
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)
@@ -49,7 +53,8 @@ gtk_radio_tool_button_class_init (GtkRadioToolButtonClass *klass)
toolbutton_class = (GtkToolButtonClass *)klass;
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;
/**
@@ -63,9 +68,9 @@ gtk_radio_tool_button_class_init (GtkRadioToolButtonClass *klass)
PROP_GROUP,
g_param_spec_object ("group",
P_("Group"),
P_("The radio tool button whose group this button belongs to."),
GTK_TYPE_RADIO_TOOL_BUTTON,
GTK_PARAM_WRITABLE));
P_("The radio group this tool button belongs to."),
GTK_TYPE_RADIO_GROUP,
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
}
@@ -90,15 +95,10 @@ gtk_radio_tool_button_set_property (GObject *object,
{
case PROP_GROUP:
{
GtkRadioToolButton *arg;
GSList *slist = NULL;
if (G_VALUE_HOLDS_OBJECT (value))
{
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);
}
GtkRadioGroup *group;
group = g_value_get_object (value);
gtk_radio_tool_button_set_group (button, group);
}
break;
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:
* @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
**/
GtkToolItem *
gtk_radio_tool_button_new (GSList *group)
gtk_radio_tool_button_new (GtkRadioGroup *group)
{
GtkRadioToolButton *button;
button = g_object_new (GTK_TYPE_RADIO_TOOL_BUTTON,
"group", group,
NULL);
gtk_radio_tool_button_set_group (button, group);
return GTK_TOOL_ITEM (button);
}
@@ -144,20 +164,18 @@ gtk_radio_tool_button_new (GSList *group)
* Since: 2.4
**/
GtkToolItem *
gtk_radio_tool_button_new_from_stock (GSList *group,
gtk_radio_tool_button_new_from_stock (GtkRadioGroup *group,
const gchar *stock_id)
{
GtkRadioToolButton *button;
g_return_val_if_fail (stock_id != NULL, NULL);
button = g_object_new (GTK_TYPE_RADIO_TOOL_BUTTON,
"group", group,
"stock-id", stock_id,
NULL);
gtk_radio_tool_button_set_group (button, group);
return GTK_TOOL_ITEM (button);
}
@@ -174,14 +192,14 @@ gtk_radio_tool_button_new_from_stock (GSList *group,
GtkToolItem *
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);
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,
const gchar *stock_id)
{
GSList *list = NULL;
GtkRadioGroup *radio_group = NULL;
g_return_val_if_fail (GTK_IS_RADIO_TOOL_BUTTON (group), NULL);
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 *
@@ -227,7 +245,7 @@ get_radio_button (GtkRadioToolButton *button)
*
* Since: 2.4
*/
GSList *
GtkRadioGroup *
gtk_radio_tool_button_get_group (GtkRadioToolButton *button)
{
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
gtk_radio_tool_button_set_group (GtkRadioToolButton *button,
GSList *group)
GtkRadioGroup *group)
{
g_return_if_fail (GTK_IS_RADIO_TOOL_BUTTON (button));

View File

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

View File

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

View File

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

View File

@@ -62,6 +62,7 @@ static void
gail_radio_menu_item_init (GailRadioMenuItem *radio_menu_item)
{
radio_menu_item->old_group = NULL;
radio_menu_item->old_group_size = 0;
}
AtkRelationSet*
@@ -69,7 +70,9 @@ gail_radio_menu_item_ref_relation_set (AtkObject *obj)
{
GtkWidget *widget;
AtkRelationSet *relation_set;
GtkRadioGroup *group;
GSList *list;
guint list_length;
GailRadioMenuItem *radio_menu_item;
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
*/
list = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (widget));
if (radio_menu_item->old_group != list)
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 != group ||
radio_menu_item->old_group_size != list_length)
{
AtkRelation *relation;
@@ -105,15 +111,14 @@ gail_radio_menu_item_ref_relation_set (AtkObject *obj)
* 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)
{
AtkObject **accessible_array;
guint list_length;
AtkRelation* relation;
gint i = 0;
list_length = g_slist_length (list);
accessible_array = (AtkObject**) g_malloc (sizeof (AtkObject *) *
list_length);
while (list != NULL)
@@ -135,5 +140,6 @@ gail_radio_menu_item_ref_relation_set (AtkObject *obj)
g_object_unref (relation);
}
}
g_slist_free (list);
return relation_set;
}

View File

@@ -38,7 +38,8 @@ struct _GailRadioMenuItem
{
GailCheckMenuItem parent;
GSList *old_group;
GtkRadioGroup *old_group;
guint old_group_size;
};
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)
{
radio_menu_item->old_group = NULL;
radio_menu_item->old_group_size = 0;
}
AtkRelationSet*
@@ -65,7 +66,9 @@ gail_radio_sub_menu_item_ref_relation_set (AtkObject *obj)
{
GtkWidget *widget;
AtkRelationSet *relation_set;
GtkRadioGroup *group;
GSList *list;
guint list_length;
GailRadioSubMenuItem *radio_menu_item;
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
*/
list = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (widget));
if (radio_menu_item->old_group != list)
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 != group ||
radio_menu_item->old_group_size != list_length)
{
AtkRelation *relation;
@@ -101,15 +107,14 @@ gail_radio_sub_menu_item_ref_relation_set (AtkObject *obj)
* 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)
{
AtkObject **accessible_array;
guint list_length;
AtkRelation* relation;
gint i = 0;
list_length = g_slist_length (list);
accessible_array = (AtkObject**) g_malloc (sizeof (AtkObject *) *
list_length);
while (list != NULL)
@@ -131,5 +136,6 @@ gail_radio_sub_menu_item_ref_relation_set (AtkObject *obj)
g_object_unref (relation);
}
}
g_slist_free (list);
return relation_set;
}

View File

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

View File

@@ -174,24 +174,26 @@ build_alpha_widgets (void)
GtkWidget *hbox;
GtkWidget *label;
GtkWidget *entry;
GtkRadioGroup *group;
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),
radio_button,
0, 1, 0, 1,
GTK_EXPAND | GTK_FILL, 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),
radio_button,
0, 1, 1, 2,
GTK_EXPAND | GTK_FILL, 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),
radio_button,
0, 1, 2, 3,
@@ -214,14 +216,14 @@ build_alpha_widgets (void)
GTK_EXPAND | GTK_FILL, 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),
radio_button,
0, 1, 1, 2,
GTK_EXPAND | GTK_FILL, 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),
radio_button,
0, 1, 2, 3,
@@ -856,9 +858,9 @@ static GtkWidget *
create_widget_grid (GType widget_type)
{
GtkWidget *table;
GtkWidget *group_widget = NULL;
GtkRadioGroup *group = NULL;
gint i, j;
table = gtk_table_new (FALSE, 3, 3);
for (i = 0; i < 5; i++)
@@ -890,10 +892,9 @@ create_widget_grid (GType widget_type)
if (g_type_is_a (widget_type, GTK_TYPE_RADIO_BUTTON))
{
if (!group_widget)
group_widget = widget;
else
g_object_set (widget, "group", group_widget, NULL);
if (!group)
group = gtk_radio_group_new ();
g_object_set (widget, "group", group, NULL);
}
}
@@ -2928,7 +2929,7 @@ create_menu (GdkScreen *screen, gint depth, gint length, gboolean tearoff)
GtkWidget *menu;
GtkWidget *menuitem;
GtkWidget *image;
GSList *group;
GtkRadioGroup *group;
char buf[32];
int i, j;
@@ -2954,13 +2955,13 @@ create_menu (GdkScreen *screen, gint depth, gint length, gboolean tearoff)
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
group = gtk_radio_group_new ();
for (i = 0, j = 1; i < length; i++, j++)
{
sprintf (buf, "item %2d - %d", depth, j);
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_widget_show (menuitem);

View File

@@ -515,8 +515,8 @@ main (gint argc, gchar **argv)
GtkWidget *button;
GtkWidget *label;
GIcon *gicon;
GSList *group;
GtkRadioGroup *group;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
@@ -671,9 +671,9 @@ main (gint argc, gchar **argv)
gtk_tool_item_set_expand (item, TRUE);
gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (item), FALSE);
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_tool_button_get_group (GTK_RADIO_TOOL_BUTTON (item));
group = gtk_radio_group_new ();
item = gtk_radio_tool_button_new_from_stock (group, GTK_STOCK_JUSTIFY_LEFT);
add_item_to_list (store, item, "Left");
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);
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");
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);