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