]> Pileus Git - ~andy/gtk/blob - gtk/gtkradioaction.c
Fix many instances of "the the" in docs and comments. (#165815, Masao
[~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 "gtkalias.h"
34 #include "gtkradioaction.h"
35 #include "gtkradiomenuitem.h"
36 #include "gtktoggleactionprivate.h"
37 #include "gtktoggletoolbutton.h"
38 #include "gtkintl.h"
39
40 #define GTK_RADIO_ACTION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_RADIO_ACTION, GtkRadioActionPrivate))
41
42 struct _GtkRadioActionPrivate 
43 {
44   GSList *group;
45   gint    value;
46 };
47
48 enum 
49 {
50   CHANGED,
51   LAST_SIGNAL
52 };
53
54 enum 
55 {
56   PROP_0,
57   PROP_VALUE,
58   PROP_GROUP
59 };
60
61 static void gtk_radio_action_init         (GtkRadioAction *action);
62 static void gtk_radio_action_class_init   (GtkRadioActionClass *class);
63 static void gtk_radio_action_finalize     (GObject *object);
64 static void gtk_radio_action_set_property (GObject         *object,
65                                            guint            prop_id,
66                                            const GValue    *value,
67                                            GParamSpec      *pspec);
68 static void gtk_radio_action_get_property (GObject         *object,
69                                            guint            prop_id,
70                                            GValue          *value,
71                                            GParamSpec      *pspec);
72 static void gtk_radio_action_activate     (GtkAction *action);
73 static GtkWidget *create_menu_item        (GtkAction *action);
74
75
76 GType
77 gtk_radio_action_get_type (void)
78 {
79   static GtkType type = 0;
80
81   if (!type)
82     {
83       static const GTypeInfo type_info =
84       {
85         sizeof (GtkRadioActionClass),
86         (GBaseInitFunc) NULL,
87         (GBaseFinalizeFunc) NULL,
88         (GClassInitFunc) gtk_radio_action_class_init,
89         (GClassFinalizeFunc) NULL,
90         NULL,
91         
92         sizeof (GtkRadioAction),
93         0, /* n_preallocs */
94         (GInstanceInitFunc) gtk_radio_action_init,
95       };
96
97       type = g_type_register_static (GTK_TYPE_TOGGLE_ACTION,
98                                      "GtkRadioAction",
99                                      &type_info, 0);
100     }
101   return type;
102 }
103
104 static GObjectClass *parent_class = NULL;
105 static guint         radio_action_signals[LAST_SIGNAL] = { 0 };
106
107 static void
108 gtk_radio_action_class_init (GtkRadioActionClass *klass)
109 {
110   GObjectClass *gobject_class;
111   GtkActionClass *action_class;
112
113   parent_class = g_type_class_peek_parent (klass);
114   gobject_class = G_OBJECT_CLASS (klass);
115   action_class = GTK_ACTION_CLASS (klass);
116
117   gobject_class->finalize = gtk_radio_action_finalize;
118   gobject_class->set_property = gtk_radio_action_set_property;
119   gobject_class->get_property = gtk_radio_action_get_property;
120
121   action_class->activate = gtk_radio_action_activate;
122
123   action_class->create_menu_item = create_menu_item;
124
125   /**
126    * GtkRadioAction:value:
127    *
128    * The value is an arbitrary integer which can be used as a
129    * convenient way to determine which action in the group is 
130    * currently active in an ::activate or ::changed signal handler.
131    * See gtk_radio_action_get_current_value() and #GtkRadioActionEntry
132    * for convenient ways to get and set this property.
133    *
134    * Since: 2.4
135    */
136   g_object_class_install_property (gobject_class,
137                                    PROP_VALUE,
138                                    g_param_spec_int ("value",
139                                                      P_("The value"),
140                                                      P_("The value returned by gtk_radio_action_get_current_value() when this action is the current action of its group."),
141                                                      G_MININT,
142                                                      G_MAXINT,
143                                                      0,
144                                                      G_PARAM_READWRITE));
145
146   /**
147    * GtkRadioAction:group:
148    *
149    * Sets a new group for a radio action.
150    *
151    * Since: 2.4
152    */
153   g_object_class_install_property (gobject_class,
154                                    PROP_GROUP,
155                                    g_param_spec_object ("group",
156                                                         P_("Group"),
157                                                         P_("The radio action whose group this action belongs to."),
158                                                         GTK_TYPE_RADIO_ACTION,
159                                                         G_PARAM_WRITABLE));
160
161   /**
162    * GtkRadioAction::changed:
163    * @action: the action on which the signal is emitted
164    * @current: the member of @action<!-- -->s group which has just been activated
165    *
166    * The ::changed signal is emitted on every member of a radio group when the
167    * active member is changed. The signal gets emitted after the ::activate signals
168    * for the previous and current active members.
169    *
170    * Since: 2.4
171    */
172   radio_action_signals[CHANGED] =
173     g_signal_new ("changed",
174                   G_OBJECT_CLASS_TYPE (klass),
175                   G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
176                   G_STRUCT_OFFSET (GtkRadioActionClass, changed),  NULL, NULL,
177                   g_cclosure_marshal_VOID__OBJECT,
178                   G_TYPE_NONE, 1, GTK_TYPE_RADIO_ACTION);
179
180   g_type_class_add_private (gobject_class, sizeof (GtkRadioActionPrivate));
181 }
182
183 static void
184 gtk_radio_action_init (GtkRadioAction *action)
185 {
186   action->private_data = GTK_RADIO_ACTION_GET_PRIVATE (action);
187   action->private_data->group = g_slist_prepend (NULL, action);
188   action->private_data->value = 0;
189 }
190
191 /**
192  * gtk_radio_action_new:
193  * @name: A unique name for the action
194  * @label: The label displayed in menu items and on buttons
195  * @tooltip: A tooltip for this action
196  * @stock_id: The stock icon to display in widgets representing this action
197  * @value: The value which gtk_radio_action_get_current_value() should return
198  *    if this action is selected.
199  *
200  * Creates a new #GtkRadioAction object. To add the action to
201  * a #GtkActionGroup and set the accelerator for the action,
202  * call gtk_action_group_add_action_with_accel().
203  *
204  * Return value: a new #GtkRadioAction
205  *
206  * Since: 2.4
207  */
208 GtkRadioAction *
209 gtk_radio_action_new (const gchar *name,
210                       const gchar *label,
211                       const gchar *tooltip,
212                       const gchar *stock_id,
213                       gint value)
214 {
215   GtkRadioAction *action;
216
217   action = g_object_new (GTK_TYPE_RADIO_ACTION,
218                          "name", name,
219                          "label", label,
220                          "tooltip", tooltip,
221                          "stock_id", stock_id,
222                          "value", value,
223                          NULL);
224
225   return action;
226 }
227
228 static void
229 gtk_radio_action_finalize (GObject *object)
230 {
231   GtkRadioAction *action;
232   GSList *tmp_list;
233
234   action = GTK_RADIO_ACTION (object);
235
236   action->private_data->group = g_slist_remove (action->private_data->group, action);
237
238   tmp_list = action->private_data->group;
239
240   while (tmp_list)
241     {
242       GtkRadioAction *tmp_action = tmp_list->data;
243
244       tmp_list = tmp_list->next;
245       tmp_action->private_data->group = action->private_data->group;
246     }
247
248   (* parent_class->finalize) (object);
249 }
250
251 static void
252 gtk_radio_action_set_property (GObject         *object,
253                                guint            prop_id,
254                                const GValue    *value,
255                                GParamSpec      *pspec)
256 {
257   GtkRadioAction *radio_action;
258   
259   radio_action = GTK_RADIO_ACTION (object);
260
261   switch (prop_id)
262     {
263     case PROP_VALUE:
264       radio_action->private_data->value = g_value_get_int (value);
265       break;
266     case PROP_GROUP: 
267       {
268         GtkRadioAction *arg;
269         GSList *slist = NULL;
270         
271         if (G_VALUE_HOLDS_OBJECT (value)) 
272           {
273             arg = GTK_RADIO_ACTION (g_value_get_object (value));
274             if (arg)
275               slist = gtk_radio_action_get_group (arg);
276             gtk_radio_action_set_group (radio_action, slist);
277           }
278       }
279       break;
280     default:
281       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
282       break;
283     }
284 }
285
286 static void
287 gtk_radio_action_get_property (GObject    *object,
288                                guint       prop_id,
289                                GValue     *value,
290                                GParamSpec *pspec)
291 {
292   GtkRadioAction *radio_action;
293
294   radio_action = GTK_RADIO_ACTION (object);
295
296   switch (prop_id)
297     {
298     case PROP_VALUE:
299       g_value_set_int (value, radio_action->private_data->value);
300       break;
301     default:
302       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
303       break;
304     }
305 }
306
307 static void
308 gtk_radio_action_activate (GtkAction *action)
309 {
310   GtkRadioAction *radio_action;
311   GtkToggleAction *toggle_action;
312   GtkToggleAction *tmp_action;
313   GSList *tmp_list;
314
315   radio_action = GTK_RADIO_ACTION (action);
316   toggle_action = GTK_TOGGLE_ACTION (action);
317
318   if (toggle_action->private_data->active)
319     {
320       tmp_list = radio_action->private_data->group;
321
322       while (tmp_list)
323         {
324           tmp_action = tmp_list->data;
325           tmp_list = tmp_list->next;
326
327           if (tmp_action->private_data->active && (tmp_action != toggle_action)) 
328             {
329               toggle_action->private_data->active = !toggle_action->private_data->active;
330               break;
331             }
332         }
333     }
334   else
335     {
336       toggle_action->private_data->active = !toggle_action->private_data->active;
337
338       tmp_list = radio_action->private_data->group;
339       while (tmp_list)
340         {
341           tmp_action = tmp_list->data;
342           tmp_list = tmp_list->next;
343
344           if (tmp_action->private_data->active && (tmp_action != toggle_action))
345             {
346               _gtk_action_emit_activate (GTK_ACTION (tmp_action));
347               break;
348             }
349         }
350
351       tmp_list = radio_action->private_data->group;
352       while (tmp_list)
353         {
354           tmp_action = tmp_list->data;
355           tmp_list = tmp_list->next;
356           
357           g_signal_emit (tmp_action, radio_action_signals[CHANGED], 0, radio_action);
358         }
359     }
360
361   gtk_toggle_action_toggled (toggle_action);
362 }
363
364 static GtkWidget *
365 create_menu_item (GtkAction *action)
366 {
367   return g_object_new (GTK_TYPE_CHECK_MENU_ITEM, 
368                        "draw_as_radio", TRUE,
369                        NULL);
370 }
371
372 /**
373  * gtk_radio_action_get_group:
374  * @action: the action object
375  *
376  * Returns the list representing the radio group for this object
377  *
378  * Returns: the list representing the radio group for this object
379  *
380  * Since: 2.4
381  */
382 GSList *
383 gtk_radio_action_get_group (GtkRadioAction *action)
384 {
385   g_return_val_if_fail (GTK_IS_RADIO_ACTION (action), NULL);
386
387   return action->private_data->group;
388 }
389
390 /**
391  * gtk_radio_action_set_group:
392  * @action: the action object
393  * @group: a list representing a radio group
394  *
395  * Sets the radio group for the radio action object.
396  *
397  * Since: 2.4
398  */
399 void
400 gtk_radio_action_set_group (GtkRadioAction *action, 
401                             GSList         *group)
402 {
403   g_return_if_fail (GTK_IS_RADIO_ACTION (action));
404   g_return_if_fail (!g_slist_find (group, action));
405
406   if (action->private_data->group)
407     {
408       GSList *slist;
409
410       action->private_data->group = g_slist_remove (action->private_data->group, action);
411
412       for (slist = action->private_data->group; slist; slist = slist->next)
413         {
414           GtkRadioAction *tmp_action = slist->data;
415
416           tmp_action->private_data->group = action->private_data->group;
417         }
418     }
419
420   action->private_data->group = g_slist_prepend (group, action);
421
422   if (group)
423     {
424       GSList *slist;
425
426       for (slist = action->private_data->group; slist; slist = slist->next)
427         {
428           GtkRadioAction *tmp_action = slist->data;
429
430           tmp_action->private_data->group = action->private_data->group;
431         }
432     }
433   else
434     {
435       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
436     }
437 }
438
439 /**
440  * gtk_radio_action_get_current_value:
441  * @action: a #GtkRadioAction
442  * 
443  * Obtains the value property of the currently active member of 
444  * the group to which @action belongs.
445  * 
446  * Return value: The value of the currently active group member
447  *
448  * Since: 2.4
449  **/
450 gint
451 gtk_radio_action_get_current_value (GtkRadioAction *action)
452 {
453   GSList *slist;
454
455   g_return_val_if_fail (GTK_IS_RADIO_ACTION (action), 0);
456
457   if (action->private_data->group)
458     {
459       for (slist = action->private_data->group; slist; slist = slist->next)
460         {
461           GtkToggleAction *toggle_action = slist->data;
462
463           if (toggle_action->private_data->active)
464             return GTK_RADIO_ACTION (toggle_action)->private_data->value;
465         }
466     }
467
468   return action->private_data->value;
469 }