]> Pileus Git - ~andy/gtk/blob - gtk/gtktoggleaction.c
stylecontext: Do invalidation on first resize container
[~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 this library. If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /*
21  * Author: James Henstridge <james@daa.com.au>
22  *
23  * Modified by the GTK+ Team and others 2003.  See the AUTHORS
24  * file for a list of people on the GTK+ Team.  See the ChangeLog
25  * files for a list of changes.  These files are distributed with
26  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
27  */
28
29 #include "config.h"
30
31 #include "gtkintl.h"
32 #include "gtktoggleaction.h"
33 #include "gtktoggletoolbutton.h"
34 #include "gtktogglebutton.h"
35 #include "gtkcheckmenuitem.h"
36 #include "gtkprivate.h"
37
38
39 /**
40  * SECTION:gtktoggleaction
41  * @Short_description: An action which can be toggled between two states
42  * @Title: GtkToggleAction
43  *
44  * A #GtkToggleAction corresponds roughly to a #GtkCheckMenuItem. It has an
45  * "active" state specifying whether the action has been checked or not.
46  */
47
48 struct _GtkToggleActionPrivate
49 {
50   guint active        : 1;
51   guint draw_as_radio : 1;
52 };
53
54 enum 
55 {
56   TOGGLED,
57   LAST_SIGNAL
58 };
59
60 enum {
61   PROP_0,
62   PROP_DRAW_AS_RADIO,
63   PROP_ACTIVE
64 };
65
66 G_DEFINE_TYPE (GtkToggleAction, gtk_toggle_action, GTK_TYPE_ACTION)
67
68 static void gtk_toggle_action_activate     (GtkAction       *action);
69 static void set_property                   (GObject         *object,
70                                             guint            prop_id,
71                                             const GValue    *value,
72                                             GParamSpec      *pspec);
73 static void get_property                   (GObject         *object,
74                                             guint            prop_id,
75                                             GValue          *value,
76                                             GParamSpec      *pspec);
77 static GtkWidget *create_menu_item         (GtkAction       *action);
78
79
80 static GObjectClass *parent_class = NULL;
81 static guint         action_signals[LAST_SIGNAL] = { 0 };
82
83 static void
84 gtk_toggle_action_class_init (GtkToggleActionClass *klass)
85 {
86   GObjectClass *gobject_class;
87   GtkActionClass *action_class;
88
89   parent_class = g_type_class_peek_parent (klass);
90   gobject_class = G_OBJECT_CLASS (klass);
91   action_class = GTK_ACTION_CLASS (klass);
92
93   gobject_class->set_property = set_property;
94   gobject_class->get_property = get_property;
95
96   action_class->activate = gtk_toggle_action_activate;
97
98   action_class->menu_item_type = GTK_TYPE_CHECK_MENU_ITEM;
99   action_class->toolbar_item_type = GTK_TYPE_TOGGLE_TOOL_BUTTON;
100
101   action_class->create_menu_item = create_menu_item;
102
103   klass->toggled = NULL;
104
105   /**
106    * GtkToggleAction:draw-as-radio:
107    *
108    * Whether the proxies for this action look like radio action proxies.
109    *
110    * This is an appearance property and thus only applies if 
111    * #GtkActivatable:use-action-appearance is %TRUE.
112    */
113   g_object_class_install_property (gobject_class,
114                                    PROP_DRAW_AS_RADIO,
115                                    g_param_spec_boolean ("draw-as-radio",
116                                                          P_("Create the same proxies as a radio action"),
117                                                          P_("Whether the proxies for this action look like radio action proxies"),
118                                                          FALSE,
119                                                          GTK_PARAM_READWRITE));
120
121   /**
122    * GtkToggleAction:active:
123    *
124    * Whether the toggle action should be active.
125    *
126    * Since: 2.10
127    */
128   g_object_class_install_property (gobject_class,
129                                    PROP_ACTIVE,
130                                    g_param_spec_boolean ("active",
131                                                          P_("Active"),
132                                                          P_("Whether the toggle action should be active"),
133                                                          FALSE,
134                                                          GTK_PARAM_READWRITE));
135   /**
136    * GtkToggleAction::toggled:
137    * @toggleaction: the object which received the signal.
138    *
139    * Should be connected if you wish to perform an action
140    * whenever the #GtkToggleAction state is changed.
141    */
142   action_signals[TOGGLED] =
143     g_signal_new (I_("toggled"),
144                   G_OBJECT_CLASS_TYPE (klass),
145                   G_SIGNAL_RUN_FIRST,
146                   G_STRUCT_OFFSET (GtkToggleActionClass, toggled),
147                   NULL, NULL,
148                   g_cclosure_marshal_VOID__VOID,
149                   G_TYPE_NONE, 0);
150
151   g_type_class_add_private (gobject_class, sizeof (GtkToggleActionPrivate));
152 }
153
154 static void
155 gtk_toggle_action_init (GtkToggleAction *action)
156 {
157   action->private_data = G_TYPE_INSTANCE_GET_PRIVATE (action,
158                                                       GTK_TYPE_TOGGLE_ACTION,
159                                                       GtkToggleActionPrivate);
160   action->private_data->active = FALSE;
161   action->private_data->draw_as_radio = FALSE;
162 }
163
164 /**
165  * gtk_toggle_action_new:
166  * @name: A unique name for the action
167  * @label: (allow-none): The label displayed in menu items and on buttons,
168  *         or %NULL
169  * @tooltip: (allow-none): A tooltip for the action, or %NULL
170  * @stock_id: (allow-none): The stock icon to display in widgets representing
171  *            the action, or %NULL
172  *
173  * Creates a new #GtkToggleAction object. To add the action to
174  * a #GtkActionGroup and set the accelerator for the action,
175  * call gtk_action_group_add_action_with_accel().
176  *
177  * Return value: a new #GtkToggleAction
178  *
179  * Since: 2.4
180  */
181 GtkToggleAction *
182 gtk_toggle_action_new (const gchar *name,
183                        const gchar *label,
184                        const gchar *tooltip,
185                        const gchar *stock_id)
186 {
187   g_return_val_if_fail (name != NULL, NULL);
188
189   return g_object_new (GTK_TYPE_TOGGLE_ACTION,
190                        "name", name,
191                        "label", label,
192                        "tooltip", tooltip,
193                        "stock-id", stock_id,
194                        NULL);
195 }
196
197 static void
198 get_property (GObject     *object,
199               guint        prop_id,
200               GValue      *value,
201               GParamSpec  *pspec)
202 {
203   GtkToggleAction *action = GTK_TOGGLE_ACTION (object);
204   
205   switch (prop_id)
206     {
207     case PROP_DRAW_AS_RADIO:
208       g_value_set_boolean (value, gtk_toggle_action_get_draw_as_radio (action));
209       break;
210     case PROP_ACTIVE:
211       g_value_set_boolean (value, gtk_toggle_action_get_active (action));
212       break;
213     default:
214       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
215       break;
216     }
217 }
218
219 static void
220 set_property (GObject      *object,
221               guint         prop_id,
222               const GValue *value,
223               GParamSpec   *pspec)
224 {
225   GtkToggleAction *action = GTK_TOGGLE_ACTION (object);
226   
227   switch (prop_id)
228     {
229     case PROP_DRAW_AS_RADIO:
230       gtk_toggle_action_set_draw_as_radio (action, g_value_get_boolean (value));
231       break;
232     case PROP_ACTIVE:
233       gtk_toggle_action_set_active (action, g_value_get_boolean (value));
234       break;
235     default:
236       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
237       break;
238     }
239 }
240
241 static void
242 gtk_toggle_action_activate (GtkAction *action)
243 {
244   GtkToggleAction *toggle_action;
245
246   g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
247
248   toggle_action = GTK_TOGGLE_ACTION (action);
249
250   toggle_action->private_data->active = !toggle_action->private_data->active;
251
252   g_object_notify (G_OBJECT (action), "active");
253
254   gtk_toggle_action_toggled (toggle_action);
255 }
256
257 /**
258  * gtk_toggle_action_toggled:
259  * @action: the action object
260  *
261  * Emits the "toggled" signal on the toggle action.
262  *
263  * Since: 2.4
264  */
265 void
266 gtk_toggle_action_toggled (GtkToggleAction *action)
267 {
268   g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
269
270   g_signal_emit (action, action_signals[TOGGLED], 0);
271 }
272
273 /**
274  * gtk_toggle_action_set_active:
275  * @action: the action object
276  * @is_active: whether the action should be checked or not
277  *
278  * Sets the checked state on the toggle action.
279  *
280  * Since: 2.4
281  */
282 void
283 gtk_toggle_action_set_active (GtkToggleAction *action, 
284                               gboolean         is_active)
285 {
286   g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
287
288   is_active = is_active != FALSE;
289
290   if (action->private_data->active != is_active)
291     _gtk_action_emit_activate (GTK_ACTION (action));
292 }
293
294 /**
295  * gtk_toggle_action_get_active:
296  * @action: the action object
297  *
298  * Returns the checked state of the toggle action.
299  *
300  * Returns: the checked state of the toggle action
301  *
302  * Since: 2.4
303  */
304 gboolean
305 gtk_toggle_action_get_active (GtkToggleAction *action)
306 {
307   g_return_val_if_fail (GTK_IS_TOGGLE_ACTION (action), FALSE);
308
309   return action->private_data->active;
310 }
311
312
313 /**
314  * gtk_toggle_action_set_draw_as_radio:
315  * @action: the action object
316  * @draw_as_radio: whether the action should have proxies like a radio 
317  *    action
318  *
319  * Sets whether the action should have proxies like a radio action.
320  *
321  * Since: 2.4
322  */
323 void
324 gtk_toggle_action_set_draw_as_radio (GtkToggleAction *action, 
325                                      gboolean         draw_as_radio)
326 {
327   g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
328
329   draw_as_radio = draw_as_radio != FALSE;
330
331   if (action->private_data->draw_as_radio != draw_as_radio)
332     {
333       action->private_data->draw_as_radio = draw_as_radio;
334       
335       g_object_notify (G_OBJECT (action), "draw-as-radio");      
336     }
337 }
338
339 /**
340  * gtk_toggle_action_get_draw_as_radio:
341  * @action: the action object
342  *
343  * Returns whether the action should have proxies like a radio action.
344  *
345  * Returns: whether the action should have proxies like a radio action.
346  *
347  * Since: 2.4
348  */
349 gboolean
350 gtk_toggle_action_get_draw_as_radio (GtkToggleAction *action)
351 {
352   g_return_val_if_fail (GTK_IS_TOGGLE_ACTION (action), FALSE);
353
354   return action->private_data->draw_as_radio;
355 }
356
357 static GtkWidget *
358 create_menu_item (GtkAction *action)
359 {
360   GtkToggleAction *toggle_action = GTK_TOGGLE_ACTION (action);
361
362   return g_object_new (GTK_TYPE_CHECK_MENU_ITEM, 
363                        "draw-as-radio", toggle_action->private_data->draw_as_radio,
364                        NULL);
365 }
366
367
368 /* Private */
369
370 /*
371  * _gtk_toggle_action_set_active:
372  * @toggle_action: a #GtkToggleAction
373  * @is_active: whether the action is active or not
374  *
375  * Sets the #GtkToggleAction:active property directly. This function does
376  * not emit signals or notifications: it is left to the caller to do so.
377  */
378 void
379 _gtk_toggle_action_set_active (GtkToggleAction *toggle_action,
380                                gboolean         is_active)
381 {
382   GtkToggleActionPrivate *priv = toggle_action->private_data;
383
384   priv->active = is_active;
385 }