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