]> Pileus Git - ~andy/gtk/blob - gtk/gtktoggleaction.c
Add an active property. (#322673, Jorn Baayen)
[~andy/gtk] / gtk / gtktoggleaction.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 "gtkintl.h"
34 #include "gtktoggleaction.h"
35 #include "gtktoggleactionprivate.h"
36 #include "gtktoggletoolbutton.h"
37 #include "gtktogglebutton.h"
38 #include "gtkcheckmenuitem.h"
39 #include "gtkprivate.h"
40 #include "gtkalias.h"
41
42 enum 
43 {
44   TOGGLED,
45   LAST_SIGNAL
46 };
47
48 enum {
49   PROP_0,
50   PROP_DRAW_AS_RADIO,
51   PROP_ACTIVE
52 };
53
54 static void gtk_toggle_action_init       (GtkToggleAction *action);
55 static void gtk_toggle_action_class_init (GtkToggleActionClass *class);
56
57 GType
58 gtk_toggle_action_get_type (void)
59 {
60   static GtkType type = 0;
61
62   if (!type)
63     {
64       static const GTypeInfo type_info =
65       {
66         sizeof (GtkToggleActionClass),
67         (GBaseInitFunc) NULL,
68         (GBaseFinalizeFunc) NULL,
69         (GClassInitFunc) gtk_toggle_action_class_init,
70         (GClassFinalizeFunc) NULL,
71         NULL,
72         
73         sizeof (GtkToggleAction),
74         0, /* n_preallocs */
75         (GInstanceInitFunc) gtk_toggle_action_init,
76       };
77
78       type = g_type_register_static (GTK_TYPE_ACTION,
79                                      I_("GtkToggleAction"),
80                                      &type_info, 0);
81     }
82   return type;
83 }
84
85 static void gtk_toggle_action_activate     (GtkAction       *action);
86 static void gtk_toggle_action_real_toggled (GtkToggleAction *action);
87 static void connect_proxy                  (GtkAction       *action,
88                                             GtkWidget       *proxy);
89 static void disconnect_proxy               (GtkAction       *action,
90                                             GtkWidget       *proxy);
91 static void set_property                   (GObject         *object,
92                                             guint            prop_id,
93                                             const GValue    *value,
94                                             GParamSpec      *pspec);
95 static void get_property                   (GObject         *object,
96                                             guint            prop_id,
97                                             GValue          *value,
98                                             GParamSpec      *pspec);
99 static GtkWidget *create_menu_item         (GtkAction       *action);
100
101
102 static GObjectClass *parent_class = NULL;
103 static guint         action_signals[LAST_SIGNAL] = { 0 };
104
105 static void
106 gtk_toggle_action_class_init (GtkToggleActionClass *klass)
107 {
108   GObjectClass *gobject_class;
109   GtkActionClass *action_class;
110
111   parent_class = g_type_class_peek_parent (klass);
112   gobject_class = G_OBJECT_CLASS (klass);
113   action_class = GTK_ACTION_CLASS (klass);
114
115   gobject_class->set_property = set_property;
116   gobject_class->get_property = get_property;
117
118   action_class->activate = gtk_toggle_action_activate;
119   action_class->connect_proxy = connect_proxy;
120   action_class->disconnect_proxy = disconnect_proxy;
121
122   action_class->menu_item_type = GTK_TYPE_CHECK_MENU_ITEM;
123   action_class->toolbar_item_type = GTK_TYPE_TOGGLE_TOOL_BUTTON;
124
125   action_class->create_menu_item = create_menu_item;
126
127   klass->toggled = gtk_toggle_action_real_toggled;
128
129   g_object_class_install_property (gobject_class,
130                                    PROP_DRAW_AS_RADIO,
131                                    g_param_spec_boolean ("draw-as-radio",
132                                                          P_("Create the same proxies as a radio action"),
133                                                          P_("Whether the proxies for this action look like radio action proxies"),
134                                                          FALSE,
135                                                          GTK_PARAM_READWRITE));
136
137   /**
138    * GtkToggleAction:active:
139    *
140    * If the toggle action should be active in or not.
141    *
142    * Since: 2.10
143    */
144   g_object_class_install_property (gobject_class,
145                                    PROP_ACTIVE,
146                                    g_param_spec_boolean ("active",
147                                                          P_("Active"),
148                                                          P_("If the toggle action should be active in or not"),
149                                                          FALSE,
150                                                          GTK_PARAM_READWRITE));
151
152   action_signals[TOGGLED] =
153     g_signal_new (I_("toggled"),
154                   G_OBJECT_CLASS_TYPE (klass),
155                   G_SIGNAL_RUN_FIRST,
156                   G_STRUCT_OFFSET (GtkToggleActionClass, toggled),
157                   NULL, NULL,
158                   g_cclosure_marshal_VOID__VOID,
159                   G_TYPE_NONE, 0);
160
161   g_type_class_add_private (gobject_class, sizeof (GtkToggleActionPrivate));
162 }
163
164 static void
165 gtk_toggle_action_init (GtkToggleAction *action)
166 {
167   action->private_data = GTK_TOGGLE_ACTION_GET_PRIVATE (action);
168   action->private_data->active = FALSE;
169   action->private_data->draw_as_radio = FALSE;
170 }
171
172 /**
173  * gtk_toggle_action_new:
174  * @name: A unique name for the action
175  * @label: The label displayed in menu items and on buttons
176  * @tooltip: A tooltip for the action
177  * @stock_id: The stock icon to display in widgets representing the action
178  *
179  * Creates a new #GtkToggleAction object. To add the action to
180  * a #GtkActionGroup and set the accelerator for the action,
181  * call gtk_action_group_add_action_with_accel().
182  *
183  * Return value: a new #GtkToggleAction
184  *
185  * Since: 2.4
186  */
187 GtkToggleAction *
188 gtk_toggle_action_new (const gchar *name,
189                        const gchar *label,
190                        const gchar *tooltip,
191                        const gchar *stock_id)
192 {
193   GtkToggleAction *action;
194
195   action = g_object_new (GTK_TYPE_TOGGLE_ACTION,
196                          "name", name,
197                          "label", label,
198                          "tooltip", tooltip,
199                          "stock-id", stock_id,
200                          NULL);
201
202   return action;
203 }
204
205 static void
206 get_property (GObject     *object,
207               guint        prop_id,
208               GValue      *value,
209               GParamSpec  *pspec)
210 {
211   GtkToggleAction *action = GTK_TOGGLE_ACTION (object);
212   
213   switch (prop_id)
214     {
215     case PROP_DRAW_AS_RADIO:
216       g_value_set_boolean (value, gtk_toggle_action_get_draw_as_radio (action));
217       break;
218     case PROP_ACTIVE:
219       g_value_set_boolean (value, gtk_toggle_action_get_active (action));
220       break;
221     default:
222       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
223       break;
224     }
225 }
226
227 static void
228 set_property (GObject      *object,
229               guint         prop_id,
230               const GValue *value,
231               GParamSpec   *pspec)
232 {
233   GtkToggleAction *action = GTK_TOGGLE_ACTION (object);
234   
235   switch (prop_id)
236     {
237     case PROP_DRAW_AS_RADIO:
238       gtk_toggle_action_set_draw_as_radio (action, g_value_get_boolean (value));
239       break;
240     case PROP_ACTIVE:
241       gtk_toggle_action_set_active (action, g_value_get_boolean (value));
242       break;
243     default:
244       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
245       break;
246     }
247 }
248
249 static void
250 gtk_toggle_action_activate (GtkAction *action)
251 {
252   GtkToggleAction *toggle_action;
253
254   g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
255
256   toggle_action = GTK_TOGGLE_ACTION (action);
257
258   toggle_action->private_data->active = !toggle_action->private_data->active;
259
260   g_object_notify (action, "active");
261
262   gtk_toggle_action_toggled (toggle_action);
263 }
264
265 static void
266 gtk_toggle_action_real_toggled (GtkToggleAction *action)
267 {
268   GSList *slist;
269
270   g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
271
272   for (slist = gtk_action_get_proxies (GTK_ACTION (action)); slist; slist = slist->next)
273     {
274       GtkWidget *proxy = slist->data;
275
276       gtk_action_block_activate_from (GTK_ACTION (action), proxy);
277       if (GTK_IS_CHECK_MENU_ITEM (proxy))
278         gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (proxy),
279                                         action->private_data->active);
280       else if (GTK_IS_TOGGLE_TOOL_BUTTON (proxy))
281         gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (proxy),
282                                            action->private_data->active);
283       else if (GTK_IS_TOGGLE_BUTTON (proxy))
284         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (proxy),
285                                       action->private_data->active);
286       else {
287         g_warning ("Don't know how to toggle `%s' widgets",
288                    G_OBJECT_TYPE_NAME (proxy));
289       }
290       gtk_action_unblock_activate_from (GTK_ACTION (action), proxy);
291     }
292 }
293
294 static void
295 connect_proxy (GtkAction *action, 
296                GtkWidget *proxy)
297 {
298   GtkToggleAction *toggle_action;
299
300   toggle_action = GTK_TOGGLE_ACTION (action);
301
302   /* do this before hand, so that we don't call the "activate" handler */
303   if (GTK_IS_CHECK_MENU_ITEM (proxy))
304     gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (proxy),
305                                     toggle_action->private_data->active);
306   else if (GTK_IS_TOGGLE_TOOL_BUTTON (proxy))
307     gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (proxy),
308                                        toggle_action->private_data->active);
309   else if (GTK_IS_TOGGLE_BUTTON (proxy))
310     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (proxy),
311                                   toggle_action->private_data->active);
312
313   (* GTK_ACTION_CLASS (parent_class)->connect_proxy) (action, proxy);
314 }
315
316 static void
317 disconnect_proxy (GtkAction *action, 
318                   GtkWidget *proxy)
319 {
320   (* GTK_ACTION_CLASS (parent_class)->disconnect_proxy) (action, proxy);
321 }
322
323 /**
324  * gtk_toggle_action_toggled:
325  * @action: the action object
326  *
327  * Emits the "toggled" signal on the toggle action.
328  *
329  * Since: 2.4
330  */
331 void
332 gtk_toggle_action_toggled (GtkToggleAction *action)
333 {
334   g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
335
336   g_signal_emit (action, action_signals[TOGGLED], 0);
337 }
338
339 /**
340  * gtk_toggle_action_set_active:
341  * @action: the action object
342  * @is_active: whether the action should be checked or not
343  *
344  * Sets the checked state on the toggle action.
345  *
346  * Since: 2.4
347  */
348 void
349 gtk_toggle_action_set_active (GtkToggleAction *action, 
350                               gboolean         is_active)
351 {
352   g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
353
354   is_active = is_active != FALSE;
355
356   if (action->private_data->active != is_active)
357     {
358       _gtk_action_emit_activate (GTK_ACTION (action));
359     }
360 }
361
362 /**
363  * gtk_toggle_action_get_active:
364  * @action: the action object
365  *
366  * Returns the checked state of the toggle action.
367
368  * Returns: the checked state of the toggle action
369  *
370  * Since: 2.4
371  */
372 gboolean
373 gtk_toggle_action_get_active (GtkToggleAction *action)
374 {
375   g_return_val_if_fail (GTK_IS_TOGGLE_ACTION (action), FALSE);
376
377   return action->private_data->active;
378 }
379
380
381 /**
382  * gtk_toggle_action_set_draw_as_radio:
383  * @action: the action object
384  * @draw_as_radio: whether the action should have proxies like a radio 
385  *    action
386  *
387  * Sets whether the action should have proxies like a radio action.
388  *
389  * Since: 2.4
390  */
391 void
392 gtk_toggle_action_set_draw_as_radio (GtkToggleAction *action, 
393                                      gboolean         draw_as_radio)
394 {
395   g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
396
397   draw_as_radio = draw_as_radio != FALSE;
398
399   if (action->private_data->draw_as_radio != draw_as_radio)
400     {
401       action->private_data->draw_as_radio = draw_as_radio;
402       
403       g_object_notify (G_OBJECT (action), "draw-as-radio");      
404     }
405 }
406
407 /**
408  * gtk_toggle_action_get_draw_as_radio:
409  * @action: the action object
410  *
411  * Returns whether the action should have proxies like a radio action.
412  *
413  * Returns: whether the action should have proxies like a radio action.
414  *
415  * Since: 2.4
416  */
417 gboolean
418 gtk_toggle_action_get_draw_as_radio (GtkToggleAction *action)
419 {
420   g_return_val_if_fail (GTK_IS_TOGGLE_ACTION (action), FALSE);
421
422   return action->private_data->draw_as_radio;
423 }
424
425 static GtkWidget *
426 create_menu_item (GtkAction *action)
427 {
428   GtkToggleAction *toggle_action = GTK_TOGGLE_ACTION (action);
429
430   return g_object_new (GTK_TYPE_CHECK_MENU_ITEM, 
431                        "draw-as-radio", toggle_action->private_data->draw_as_radio,
432                        NULL);
433 }
434
435 #define __GTK_TOGGLE_ACTION_C__
436 #include "gtkaliasdef.c"