app: Document when floating variants are consumed
[platform/upstream/glib.git] / gio / gsimpleaction.c
1 /*
2  * Copyright © 2010 Codethink Limited
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; either version 2 of the licence or (at
7  * your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General
15  * Public License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17  * Boston, MA 02111-1307, USA.
18  *
19  * Authors: Ryan Lortie <desrt@desrt.ca>
20  */
21
22 #include "config.h"
23
24 #include "gsimpleaction.h"
25
26 #include "gaction.h"
27 #include "glibintl.h"
28
29 /**
30  * SECTION:gsimpleaction
31  * @title: GSimpleAction
32  * @short_description: A simple GAction implementation
33  *
34  * A #GSimpleAction is the obvious simple implementation of the #GAction
35  * interface. This is the easiest way to create an action for purposes of
36  * adding it to a #GSimpleActionGroup.
37  *
38  * See also #GtkAction.
39  */
40 struct _GSimpleAction
41 {
42   GObject       parent_instance;
43
44   gchar        *name;
45   GVariantType *parameter_type;
46   gboolean      enabled;
47   GVariant     *state;
48 };
49
50 typedef GObjectClass GSimpleActionClass;
51
52 static void g_simple_action_iface_init (GActionInterface *iface);
53 G_DEFINE_TYPE_WITH_CODE (GSimpleAction, g_simple_action, G_TYPE_OBJECT,
54   G_IMPLEMENT_INTERFACE (G_TYPE_ACTION, g_simple_action_iface_init))
55
56 enum
57 {
58   PROP_NONE,
59   PROP_NAME,
60   PROP_PARAMETER_TYPE,
61   PROP_ENABLED,
62   PROP_STATE_TYPE,
63   PROP_STATE
64 };
65
66 enum
67 {
68   SIGNAL_CHANGE_STATE,
69   SIGNAL_ACTIVATE,
70   NR_SIGNALS
71 };
72
73 static guint g_simple_action_signals[NR_SIGNALS];
74
75 static const gchar *
76 g_simple_action_get_name (GAction *action)
77 {
78   GSimpleAction *simple = G_SIMPLE_ACTION (action);
79
80   return simple->name;
81 }
82
83 static const GVariantType *
84 g_simple_action_get_parameter_type (GAction *action)
85 {
86   GSimpleAction *simple = G_SIMPLE_ACTION (action);
87
88   return simple->parameter_type;
89 }
90
91 static const GVariantType *
92 g_simple_action_get_state_type (GAction *action)
93 {
94   GSimpleAction *simple = G_SIMPLE_ACTION (action);
95
96   if (simple->state != NULL)
97     return g_variant_get_type (simple->state);
98   else
99     return NULL;
100 }
101
102 static GVariant *
103 g_simple_action_get_state_hint (GAction *action)
104 {
105   return NULL;
106 }
107
108 static gboolean
109 g_simple_action_get_enabled (GAction *action)
110 {
111   GSimpleAction *simple = G_SIMPLE_ACTION (action);
112
113   return simple->enabled;
114 }
115
116 static void
117 g_simple_action_change_state (GAction  *action,
118                               GVariant *value)
119 {
120   GSimpleAction *simple = G_SIMPLE_ACTION (action);
121
122   /* If the user connected a signal handler then they are responsible
123    * for handling state changes.
124    */
125   if (g_signal_has_handler_pending (action, g_simple_action_signals[SIGNAL_CHANGE_STATE], 0, TRUE))
126     g_signal_emit (action, g_simple_action_signals[SIGNAL_CHANGE_STATE], 0, value);
127
128   /* If not, then the default behaviour is to just set the state. */
129   else
130     g_simple_action_set_state (simple, value);
131 }
132
133 /**
134  * g_simple_action_set_state:
135  * @simple: a #GSimpleAction
136  * @value: the new #GVariant for the state
137  *
138  * Sets the state of the action.
139  *
140  * This directly updates the 'state' property to the given value.
141  *
142  * This should only be called by the implementor of the action.  Users
143  * of the action should not attempt to directly modify the 'state'
144  * property.  Instead, they should call g_action_change_state() to
145  * request the change.
146  *
147  * If the @value GVariant is floating, it is consumed.
148  *
149  * Since: 2.30
150  **/
151 void
152 g_simple_action_set_state (GSimpleAction *simple,
153                            GVariant      *value)
154 {
155   g_return_if_fail (G_IS_SIMPLE_ACTION (simple));
156   g_return_if_fail (value != NULL);
157
158   {
159     const GVariantType *state_type;
160
161     state_type = simple->state ?
162                    g_variant_get_type (simple->state) : NULL;
163     g_return_if_fail (state_type != NULL);
164     g_return_if_fail (g_variant_is_of_type (value, state_type));
165   }
166
167   g_variant_ref_sink (value);
168
169   if (!simple->state || !g_variant_equal (simple->state, value))
170     {
171       if (simple->state)
172         g_variant_unref (simple->state);
173
174       simple->state = g_variant_ref (value);
175
176       g_object_notify (G_OBJECT (simple), "state");
177     }
178
179   g_variant_unref (value);
180 }
181
182 static GVariant *
183 g_simple_action_get_state (GAction *action)
184 {
185   GSimpleAction *simple = G_SIMPLE_ACTION (action);
186
187   return simple->state ? g_variant_ref (simple->state) : NULL;
188 }
189
190 static void
191 g_simple_action_activate (GAction  *action,
192                           GVariant *parameter)
193 {
194   GSimpleAction *simple = G_SIMPLE_ACTION (action);
195
196   g_return_if_fail (simple->parameter_type == NULL ?
197                       parameter == NULL :
198                     (parameter != NULL &&
199                      g_variant_is_of_type (parameter,
200                                            simple->parameter_type)));
201
202   if (parameter != NULL)
203     g_variant_ref_sink (parameter);
204
205   if (simple->enabled)
206     g_signal_emit (simple, g_simple_action_signals[SIGNAL_ACTIVATE], 0, parameter);
207
208   if (parameter != NULL)
209     g_variant_unref (parameter);
210 }
211
212 static void
213 g_simple_action_set_property (GObject    *object,
214                               guint       prop_id,
215                               const GValue     *value,
216                               GParamSpec *pspec)
217 {
218   GSimpleAction *action = G_SIMPLE_ACTION (object);
219
220   switch (prop_id)
221     {
222     case PROP_NAME:
223       action->name = g_strdup (g_value_get_string (value));
224       break;
225
226     case PROP_PARAMETER_TYPE:
227       action->parameter_type = g_value_dup_boxed (value);
228       break;
229
230     case PROP_ENABLED:
231       action->enabled = g_value_get_boolean (value);
232       break;
233
234     case PROP_STATE:
235       action->state = g_value_dup_variant (value);
236       break;
237
238     default:
239       g_assert_not_reached ();
240     }
241 }
242
243 static void
244 g_simple_action_get_property (GObject    *object,
245                               guint       prop_id,
246                               GValue     *value,
247                               GParamSpec *pspec)
248 {
249   GAction *action = G_ACTION (object);
250
251   switch (prop_id)
252     {
253     case PROP_NAME:
254       g_value_set_string (value, g_simple_action_get_name (action));
255       break;
256
257     case PROP_PARAMETER_TYPE:
258       g_value_set_boxed (value, g_simple_action_get_parameter_type (action));
259       break;
260
261     case PROP_ENABLED:
262       g_value_set_boolean (value, g_simple_action_get_enabled (action));
263       break;
264
265     case PROP_STATE_TYPE:
266       g_value_set_boxed (value, g_simple_action_get_state_type (action));
267       break;
268
269     case PROP_STATE:
270       g_value_take_variant (value, g_simple_action_get_state (action));
271       break;
272
273     default:
274       g_assert_not_reached ();
275     }
276 }
277
278 static void
279 g_simple_action_finalize (GObject *object)
280 {
281   GSimpleAction *simple = G_SIMPLE_ACTION (object);
282
283   g_free (simple->name);
284   if (simple->parameter_type)
285     g_variant_type_free (simple->parameter_type);
286   if (simple->state)
287     g_variant_unref (simple->state);
288
289   G_OBJECT_CLASS (g_simple_action_parent_class)
290     ->finalize (object);
291 }
292
293 void
294 g_simple_action_init (GSimpleAction *simple)
295 {
296   simple->enabled = TRUE;
297 }
298
299 void
300 g_simple_action_iface_init (GActionInterface *iface)
301 {
302   iface->get_name = g_simple_action_get_name;
303   iface->get_parameter_type = g_simple_action_get_parameter_type;
304   iface->get_state_type = g_simple_action_get_state_type;
305   iface->get_state_hint = g_simple_action_get_state_hint;
306   iface->get_enabled = g_simple_action_get_enabled;
307   iface->get_state = g_simple_action_get_state;
308   iface->change_state = g_simple_action_change_state;
309   iface->activate = g_simple_action_activate;
310 }
311
312 void
313 g_simple_action_class_init (GSimpleActionClass *class)
314 {
315   GObjectClass *object_class = G_OBJECT_CLASS (class);
316
317   object_class->set_property = g_simple_action_set_property;
318   object_class->get_property = g_simple_action_get_property;
319   object_class->finalize = g_simple_action_finalize;
320
321   /**
322    * GSimpleAction::activate:
323    * @simple: the #GSimpleAction
324    * @parameter: (allow-none): the parameter to the activation
325    *
326    * Indicates that the action was just activated.
327    *
328    * @parameter will always be of the expected type.  In the event that
329    * an incorrect type was given, no signal will be emitted.
330    *
331    * Since: 2.28
332    */
333   g_simple_action_signals[SIGNAL_ACTIVATE] =
334     g_signal_new (I_("activate"),
335                   G_TYPE_SIMPLE_ACTION,
336                   G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
337                   0, NULL, NULL,
338                   g_cclosure_marshal_VOID__VARIANT,
339                   G_TYPE_NONE, 1,
340                   G_TYPE_VARIANT);
341
342   /**
343    * GSimpleAction::change-state:
344    * @simple: the #GSimpleAction
345    * @value: (allow-none): the requested value for the state
346    *
347    * Indicates that the action just received a request to change its
348    * state.
349    *
350    * @value will always be of the correct state type.  In the event that
351    * an incorrect type was given, no signal will be emitted.
352    *
353    * If no handler is connected to this signal then the default
354    * behaviour is to call g_simple_action_set_state() to set the state
355    * to the requested value.  If you connect a signal handler then no
356    * default action is taken.  If the state should change then you must
357    * call g_simple_action_set_state() from the handler.
358    *
359    * <example>
360    * <title>Example 'change-state' handler</title>
361    * <programlisting>
362    * static void
363    * change_volume_state (GSimpleAction *action,
364    *                      GVariant      *value,
365    *                      gpointer       user_data)
366    * {
367    *   gint requested;
368    *
369    *   requested = g_variant_get_int32 (value);
370    *
371    *   // Volume only goes from 0 to 10
372    *   if (0 <= requested && requested <= 10)
373    *     g_simple_action_set_state (action, value);
374    * }
375    * </programlisting>
376    * </example>
377    *
378    * The handler need not set the state to the requested value.  It
379    * could set it to any value at all, or take some other action.
380    *
381    * Since: 2.30
382    */
383   g_simple_action_signals[SIGNAL_CHANGE_STATE] =
384     g_signal_new (I_("change-state"),
385                   G_TYPE_SIMPLE_ACTION,
386                   G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
387                   0, NULL, NULL,
388                   g_cclosure_marshal_VOID__VARIANT,
389                   G_TYPE_NONE, 1,
390                   G_TYPE_VARIANT);
391
392   /**
393    * GSimpleAction:name:
394    *
395    * The name of the action.  This is mostly meaningful for identifying
396    * the action once it has been added to a #GSimpleActionGroup.
397    *
398    * Since: 2.28
399    **/
400   g_object_class_install_property (object_class, PROP_NAME,
401                                    g_param_spec_string ("name",
402                                                         P_("Action Name"),
403                                                         P_("The name used to invoke the action"),
404                                                         NULL,
405                                                         G_PARAM_READWRITE |
406                                                         G_PARAM_CONSTRUCT_ONLY |
407                                                         G_PARAM_STATIC_STRINGS));
408
409   /**
410    * GSimpleAction:parameter-type:
411    *
412    * The type of the parameter that must be given when activating the
413    * action.
414    *
415    * Since: 2.28
416    **/
417   g_object_class_install_property (object_class, PROP_PARAMETER_TYPE,
418                                    g_param_spec_boxed ("parameter-type",
419                                                        P_("Parameter Type"),
420                                                        P_("The type of GVariant passed to activate()"),
421                                                        G_TYPE_VARIANT_TYPE,
422                                                        G_PARAM_READWRITE |
423                                                        G_PARAM_CONSTRUCT_ONLY |
424                                                        G_PARAM_STATIC_STRINGS));
425
426   /**
427    * GSimpleAction:enabled:
428    *
429    * If @action is currently enabled.
430    *
431    * If the action is disabled then calls to g_action_activate() and
432    * g_action_change_state() have no effect.
433    *
434    * Since: 2.28
435    **/
436   g_object_class_install_property (object_class, PROP_ENABLED,
437                                    g_param_spec_boolean ("enabled",
438                                                          P_("Enabled"),
439                                                          P_("If the action can be activated"),
440                                                          TRUE,
441                                                          G_PARAM_READWRITE |
442                                                          G_PARAM_STATIC_STRINGS));
443
444   /**
445    * GSimpleAction:state-type:
446    *
447    * The #GVariantType of the state that the action has, or %NULL if the
448    * action is stateless.
449    *
450    * Since: 2.28
451    **/
452   g_object_class_install_property (object_class, PROP_STATE_TYPE,
453                                    g_param_spec_boxed ("state-type",
454                                                        P_("State Type"),
455                                                        P_("The type of the state kept by the action"),
456                                                        G_TYPE_VARIANT_TYPE,
457                                                        G_PARAM_READABLE |
458                                                        G_PARAM_STATIC_STRINGS));
459
460   /**
461    * GSimpleAction:state:
462    *
463    * The state of the action, or %NULL if the action is stateless.
464    *
465    * Since: 2.28
466    **/
467   g_object_class_install_property (object_class, PROP_STATE,
468                                    g_param_spec_variant ("state",
469                                                          P_("State"),
470                                                          P_("The state the action is in"),
471                                                          G_VARIANT_TYPE_ANY,
472                                                          NULL,
473                                                          G_PARAM_READWRITE |
474                                                          G_PARAM_STATIC_STRINGS));
475 }
476
477 /**
478  * g_simple_action_set_enabled:
479  * @simple: a #GSimpleAction
480  * @enabled: whether the action is enabled
481  *
482  * Sets the action as enabled or not.
483  *
484  * An action must be enabled in order to be activated or in order to
485  * have its state changed from outside callers.
486  *
487  * This should only be called by the implementor of the action.  Users
488  * of the action should not attempt to modify its enabled flag.
489  *
490  * Since: 2.28
491  **/
492 void
493 g_simple_action_set_enabled (GSimpleAction *simple,
494                              gboolean       enabled)
495 {
496   g_return_if_fail (G_IS_SIMPLE_ACTION (simple));
497
498   enabled = !!enabled;
499
500   if (simple->enabled != enabled)
501     {
502       simple->enabled = enabled;
503       g_object_notify (G_OBJECT (simple), "enabled");
504     }
505 }
506 /**
507  * g_simple_action_new:
508  * @name: the name of the action
509  * @parameter_type: (allow-none): the type of parameter to the activate function
510  *
511  * Creates a new action.
512  *
513  * The created action is stateless.  See g_simple_action_new_stateful().
514  *
515  * Returns: a new #GSimpleAction
516  *
517  * Since: 2.28
518  **/
519 GSimpleAction *
520 g_simple_action_new (const gchar        *name,
521                      const GVariantType *parameter_type)
522 {
523   return g_object_new (G_TYPE_SIMPLE_ACTION,
524                        "name", name,
525                        "parameter-type", parameter_type,
526                        NULL);
527 }
528
529 /**
530  * g_simple_action_new_stateful:
531  * @name: the name of the action
532  * @parameter_type: (allow-none): the type of the parameter to the activate function
533  * @state: the initial state of the action
534  *
535  * Creates a new stateful action.
536  *
537  * @state is the initial state of the action.  All future state values
538  * must have the same #GVariantType as the initial state.
539  *
540  * If the @state GVariant is floating, it is consumed.
541  *
542  * Returns: a new #GSimpleAction
543  *
544  * Since: 2.28
545  **/
546 GSimpleAction *
547 g_simple_action_new_stateful (const gchar        *name,
548                               const GVariantType *parameter_type,
549                               GVariant           *state)
550 {
551   return g_object_new (G_TYPE_SIMPLE_ACTION,
552                        "name", name,
553                        "parameter-type", parameter_type,
554                        "state", state,
555                        NULL);
556 }