]> Pileus Git - ~andy/gtk/blob - gtk/gtkradioaction.c
Change the XML format: <Root> element is replaced by <ui>, <menu> element
[~andy/gtk] / gtk / gtkradioaction.c
1 /*
2  * GTK - The GIMP Toolkit
3  * Copyright (C) 1998, 1999 Red Hat, Inc.
4  * All rights reserved.
5  *
6  * This Library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This Library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with the Gnome Library; see the file COPYING.LIB.  If not,
18  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 /*
23  * Author: James Henstridge <james@daa.com.au>
24  *
25  * Modified by the GTK+ Team and others 2003.  See the AUTHORS
26  * file for a list of people on the GTK+ Team.  See the ChangeLog
27  * files for a list of changes.  These files are distributed with
28  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
29  */
30
31 #include <config.h>
32
33 #include "gtkradioaction.h"
34 #include "gtkradiomenuitem.h"
35 #include "gtktoggleactionprivate.h"
36 #include "gtkintl.h"
37
38 #define GTK_RADIO_ACTION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_RADIO_ACTION, GtkRadioActionPrivate))
39
40 struct _GtkRadioActionPrivate 
41 {
42   GSList *group;
43   gint    value;
44 };
45
46 enum 
47 {
48   CHANGED,
49   LAST_SIGNAL
50 };
51
52 enum 
53 {
54   PROP_0,
55   PROP_VALUE
56 };
57
58 static void gtk_radio_action_init         (GtkRadioAction *action);
59 static void gtk_radio_action_class_init   (GtkRadioActionClass *class);
60 static void gtk_radio_action_finalize     (GObject *object);
61 static void gtk_radio_action_set_property (GObject         *object,
62                                            guint            prop_id,
63                                            const GValue    *value,
64                                            GParamSpec      *pspec);
65 static void gtk_radio_action_get_property (GObject         *object,
66                                            guint            prop_id,
67                                            GValue          *value,
68                                            GParamSpec      *pspec);
69 static void gtk_radio_action_activate     (GtkAction *action);
70
71
72 GType
73 gtk_radio_action_get_type (void)
74 {
75   static GtkType type = 0;
76
77   if (!type)
78     {
79       static const GTypeInfo type_info =
80       {
81         sizeof (GtkRadioActionClass),
82         (GBaseInitFunc) NULL,
83         (GBaseFinalizeFunc) NULL,
84         (GClassInitFunc) gtk_radio_action_class_init,
85         (GClassFinalizeFunc) NULL,
86         NULL,
87         
88         sizeof (GtkRadioAction),
89         0, /* n_preallocs */
90         (GInstanceInitFunc) gtk_radio_action_init,
91       };
92
93       type = g_type_register_static (GTK_TYPE_TOGGLE_ACTION,
94                                      "GtkRadioAction",
95                                      &type_info, 0);
96     }
97   return type;
98 }
99
100 static GObjectClass *parent_class = NULL;
101 static guint         radio_action_signals[LAST_SIGNAL] = { 0 };
102
103 static void
104 gtk_radio_action_class_init (GtkRadioActionClass *klass)
105 {
106   GObjectClass *gobject_class;
107   GtkActionClass *action_class;
108
109   parent_class = g_type_class_peek_parent (klass);
110   gobject_class = G_OBJECT_CLASS (klass);
111   action_class = GTK_ACTION_CLASS (klass);
112
113   gobject_class->finalize = gtk_radio_action_finalize;
114   gobject_class->set_property = gtk_radio_action_set_property;
115   gobject_class->get_property = gtk_radio_action_get_property;
116
117   action_class->activate = gtk_radio_action_activate;
118
119   /**
120    * GtkRadioAction:value:
121    *
122    * The value is an arbitrary integer which can be used as a
123    * convenient way to determine which action in the group is 
124    * currently active in an ::activate or ::changed signal handler.
125    * See gtk_radio_action_get_current_value() and #GtkRadioActionEntry
126    * for convenient ways to get and set this property.
127    *
128    * Since: 2.4
129    */
130   g_object_class_install_property (gobject_class,
131                                    PROP_VALUE,
132                                    g_param_spec_int ("value",
133                                                      _("The value"),
134                                                      _("The value returned by gtk_radio_action_get_current_value() when this action is the current action of its group."),
135                                                      G_MININT,
136                                                      G_MAXINT,
137                                                      0,
138                                                      G_PARAM_READWRITE));
139
140   /**
141    * GtkRadioAction::changed:
142    * @action: the action on which the signal is emitted
143    * @current: the member of @action<!-- -->s group which has just been activated
144    *
145    * The ::changed signal is emitted on every member of a radio group when the
146    * active member is changed. The signal gets emitted after the ::activate signals
147    * for the previous and current active members.
148    *
149    * Since: 2.4
150    */
151   radio_action_signals[CHANGED] =
152     g_signal_new ("changed",
153                   G_OBJECT_CLASS_TYPE (klass),
154                   G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
155                   G_STRUCT_OFFSET (GtkRadioActionClass, changed),  NULL, NULL,
156                   g_cclosure_marshal_VOID__OBJECT,
157                   G_TYPE_NONE, 1, GTK_TYPE_RADIO_ACTION);
158
159   g_type_class_add_private (gobject_class, sizeof (GtkRadioActionPrivate));
160 }
161
162 static void
163 gtk_radio_action_init (GtkRadioAction *action)
164 {
165   action->private_data = GTK_RADIO_ACTION_GET_PRIVATE (action);
166   action->private_data->group = g_slist_prepend (NULL, action);
167   action->private_data->value = 0;
168 }
169
170 static void
171 gtk_radio_action_finalize (GObject *object)
172 {
173   GtkRadioAction *action;
174   GSList *tmp_list;
175
176   action = GTK_RADIO_ACTION (object);
177
178   action->private_data->group = g_slist_remove (action->private_data->group, action);
179
180   tmp_list = action->private_data->group;
181
182   while (tmp_list)
183     {
184       GtkRadioAction *tmp_action = tmp_list->data;
185
186       tmp_list = tmp_list->next;
187       tmp_action->private_data->group = action->private_data->group;
188     }
189
190   if (parent_class->finalize)
191     (* parent_class->finalize) (object);
192 }
193
194 static void
195 gtk_radio_action_set_property (GObject         *object,
196                                guint            prop_id,
197                                const GValue    *value,
198                                GParamSpec      *pspec)
199 {
200   GtkRadioAction *radio_action;
201   
202   radio_action = GTK_RADIO_ACTION (object);
203
204   switch (prop_id)
205     {
206     case PROP_VALUE:
207       radio_action->private_data->value = g_value_get_int (value);
208       break;
209     default:
210       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
211       break;
212     }
213 }
214
215 static void
216 gtk_radio_action_get_property (GObject    *object,
217                                guint       prop_id,
218                                GValue     *value,
219                                GParamSpec *pspec)
220 {
221   GtkRadioAction *radio_action;
222
223   radio_action = GTK_RADIO_ACTION (object);
224
225   switch (prop_id)
226     {
227     case PROP_VALUE:
228       g_value_set_int (value, radio_action->private_data->value);
229       break;
230     default:
231       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
232       break;
233     }
234 }
235
236 static void
237 gtk_radio_action_activate (GtkAction *action)
238 {
239   GtkRadioAction *radio_action;
240   GtkToggleAction *toggle_action;
241   GtkToggleAction *tmp_action;
242   GSList *tmp_list;
243
244   radio_action = GTK_RADIO_ACTION (action);
245   toggle_action = GTK_TOGGLE_ACTION (action);
246
247   if (toggle_action->private_data->active)
248     {
249       tmp_list = radio_action->private_data->group;
250
251       while (tmp_list)
252         {
253           tmp_action = tmp_list->data;
254           tmp_list = tmp_list->next;
255
256           if (tmp_action->private_data->active && (tmp_action != toggle_action)) 
257             {
258               toggle_action->private_data->active = !toggle_action->private_data->active;
259               break;
260             }
261         }
262     }
263   else
264     {
265       toggle_action->private_data->active = !toggle_action->private_data->active;
266
267       tmp_list = radio_action->private_data->group;
268       while (tmp_list)
269         {
270           tmp_action = tmp_list->data;
271           tmp_list = tmp_list->next;
272
273           if (tmp_action->private_data->active && (tmp_action != toggle_action))
274             {
275               gtk_action_activate (GTK_ACTION (tmp_action));
276               break;
277             }
278         }
279
280       tmp_list = radio_action->private_data->group;
281       while (tmp_list)
282         {
283           tmp_action = tmp_list->data;
284           tmp_list = tmp_list->next;
285           
286           g_signal_emit (tmp_action, radio_action_signals[CHANGED], 0, radio_action);
287         }
288     }
289
290   gtk_toggle_action_toggled (toggle_action);
291 }
292
293 /**
294  * gtk_radio_action_get_group:
295  * @action: the action object
296  *
297  * Returns the list representing the radio group for this object
298  *
299  * Returns: the list representing the radio group for this object
300  *
301  * Since: 2.4
302  */
303 GSList *
304 gtk_radio_action_get_group (GtkRadioAction *action)
305 {
306   g_return_val_if_fail (GTK_IS_RADIO_ACTION (action), NULL);
307
308   return action->private_data->group;
309 }
310
311 /**
312  * gtk_radio_action_set_group:
313  * @action: the action object
314  * @group: a list representing a radio group
315  *
316  * Sets the radio group for the radio action object.
317  *
318  * Since: 2.4
319  */
320 void
321 gtk_radio_action_set_group (GtkRadioAction *action, 
322                             GSList         *group)
323 {
324   g_return_if_fail (GTK_IS_RADIO_ACTION (action));
325   g_return_if_fail (!g_slist_find (group, action));
326
327   if (action->private_data->group)
328     {
329       GSList *slist;
330
331       action->private_data->group = g_slist_remove (action->private_data->group, action);
332
333       for (slist = action->private_data->group; slist; slist = slist->next)
334         {
335           GtkRadioAction *tmp_action = slist->data;
336
337           tmp_action->private_data->group = action->private_data->group;
338         }
339     }
340
341   action->private_data->group = g_slist_prepend (group, action);
342
343   if (group)
344     {
345       GSList *slist;
346
347       for (slist = action->private_data->group; slist; slist = slist->next)
348         {
349           GtkRadioAction *tmp_action = slist->data;
350
351           tmp_action->private_data->group = action->private_data->group;
352         }
353     }
354   else
355     {
356       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
357     }
358 }
359
360 /**
361  * gtk_radio_action_get_current_value:
362  * @action: a #GtkRadioAction
363  * 
364  * Obtains the value property of the the currently active member of 
365  * the group to which @action belongs.
366  * 
367  * Return value: The value of the currently active group member
368  *
369  * Since: 2.4
370  **/
371 gint
372 gtk_radio_action_get_current_value (GtkRadioAction *action)
373 {
374   GSList *slist;
375
376   g_return_val_if_fail (GTK_IS_RADIO_ACTION (action), 0);
377
378   if (action->private_data->group)
379     {
380       for (slist = action->private_data->group; slist; slist = slist->next)
381         {
382           GtkToggleAction *toggle_action = slist->data;
383
384           if (toggle_action->private_data->active)
385             return GTK_RADIO_ACTION (toggle_action)->private_data->value;
386         }
387     }
388
389   return action->private_data->value;
390 }