2 * Copyright (C) 2008 Tristan Van Berkom <tristan.van.berkom@gmail.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
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 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * 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.
21 * SECTION:gtkactivatable
22 * @Short_Description: An interface for activatable widgets
24 * Activatable widgets can be connected to a #GtkAction and reflects
25 * the state of its action. A #GtkActivatable can also provide feedback
26 * through its action, as they are responsible for activating their
30 * <title>Implementing GtkActivatable</title>
32 * When extending a class that is already #GtkActivatable; it is only
33 * necessary to implement the #GtkActivatable->reset() and #GtkActivatable->update()
34 * methods and chain up to the parent implementation, however when introducing
35 * a new #GtkActivatable class; the #GtkActivatable:related-action and
36 * #GtkActivatable:use-action-appearance properties need to be handled by
37 * the implementor. Handling these properties is mostly a matter of installing
38 * the action pointer and boolean flag on your instance, and calling
39 * gtk_activatable_do_set_related_action() and gtk_activatable_reset() at the
43 * <title>A class fragment implementing #GtkActivatable</title>
44 * <programlisting><![CDATA[
49 * PROP_ACTIVATABLE_RELATED_ACTION,
50 * PROP_ACTIVATABLE_USE_ACTION_APPEARANCE
53 * struct _FooBarPrivate
59 * gboolean use_action_appearance;
64 * static void foo_bar_activatable_interface_init (GtkActivatableIface *iface);
65 * static void foo_bar_activatable_update (GtkActivatable *activatable,
67 * const gchar *property_name);
68 * static void foo_bar_activatable_reset (GtkActivatable *activatable,
74 * foo_bar_class_init (FooBarClass *klass)
79 * g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action");
80 * g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance");
87 * foo_bar_activatable_interface_init (GtkActivatableIface *iface)
89 * iface->update = foo_bar_activatable_update;
90 * iface->reset = foo_bar_activatable_reset;
93 * ... Break the reference using gtk_activatable_do_set_related_action()...
96 * foo_bar_dispose (GObject *object)
98 * FooBar *bar = FOO_BAR (object);
99 * FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (bar);
105 * gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (bar), NULL);
106 * priv->action = NULL;
108 * G_OBJECT_CLASS (foo_bar_parent_class)->dispose (object);
111 * ... Handle the "related-action" and "use-action-appearance" properties ...
114 * foo_bar_set_property (GObject *object,
116 * const GValue *value,
119 * FooBar *bar = FOO_BAR (object);
120 * FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (bar);
127 * case PROP_ACTIVATABLE_RELATED_ACTION:
128 * foo_bar_set_related_action (bar, g_value_get_object (value));
130 * case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
131 * foo_bar_set_use_action_appearance (bar, g_value_get_boolean (value));
134 * G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
140 * foo_bar_get_property (GObject *object,
145 * FooBar *bar = FOO_BAR (object);
146 * FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (bar);
153 * case PROP_ACTIVATABLE_RELATED_ACTION:
154 * g_value_set_object (value, priv->action);
156 * case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
157 * g_value_set_boolean (value, priv->use_action_appearance);
160 * G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
167 * foo_bar_set_use_action_appearance (FooBar *bar,
168 * gboolean use_appearance)
170 * FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (bar);
172 * if (priv->use_action_appearance != use_appearance)
174 * priv->use_action_appearance = use_appearance;
176 * gtk_activatable_reset (GTK_ACTIVATABLE (bar), priv->action);
180 * ... call gtk_activatable_do_set_related_action() and then assign the action pointer,
181 * no need to reference the action here since gtk_activatable_do_set_related_action() already
182 * holds a reference here for you...
184 * foo_bar_set_related_action (FooBar *bar,
187 * FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (bar);
189 * if (priv->action == action)
192 * gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (bar), action);
194 * priv->action = action;
197 * ... Selectively reset and update activatable depending on the use-action-appearance property ...
199 * gtk_button_activatable_reset (GtkActivatable *activatable,
202 * GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (activatable);
207 * if (gtk_action_is_visible (action))
208 * gtk_widget_show (GTK_WIDGET (activatable));
210 * gtk_widget_hide (GTK_WIDGET (activatable));
212 * gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
216 * if (priv->use_action_appearance)
218 * if (gtk_action_get_stock_id (action))
219 * foo_bar_set_stock (button, gtk_action_get_stock_id (action));
220 * else if (gtk_action_get_label (action))
221 * foo_bar_set_label (button, gtk_action_get_label (action));
229 * foo_bar_activatable_update (GtkActivatable *activatable,
231 * const gchar *property_name)
233 * FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (activatable);
235 * if (strcmp (property_name, "visible") == 0)
237 * if (gtk_action_is_visible (action))
238 * gtk_widget_show (GTK_WIDGET (activatable));
240 * gtk_widget_hide (GTK_WIDGET (activatable));
242 * else if (strcmp (property_name, "sensitive") == 0)
243 * gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
247 * if (!priv->use_action_appearance)
250 * if (strcmp (property_name, "stock-id") == 0)
251 * foo_bar_set_stock (button, gtk_action_get_stock_id (action));
252 * else if (strcmp (property_name, "label") == 0)
253 * foo_bar_set_label (button, gtk_action_get_label (action));
256 * }]]></programlisting>
262 #include "gtkactivatable.h"
263 #include "gtkactiongroup.h"
264 #include "gtktypeutils.h"
265 #include "gtkprivate.h"
267 #include "gtkalias.h"
270 static void gtk_activatable_class_init (gpointer g_iface);
273 gtk_activatable_get_type (void)
275 static GType activatable_type = 0;
277 if (!activatable_type)
279 g_type_register_static_simple (G_TYPE_INTERFACE, I_("GtkActivatable"),
280 sizeof (GtkActivatableIface),
281 (GClassInitFunc) gtk_activatable_class_init,
284 return activatable_type;
288 gtk_activatable_class_init (gpointer g_iface)
291 * GtkActivatable:related-action:
293 * The action that this activatable will activate and receive
294 * updates from for various states and possibly appearance.
296 * <note><para>#GtkActivatable implementors need to handle the this property and
297 * call gtk_activatable_do_set_related_action() when it changes.</para></note>
301 g_object_interface_install_property (g_iface,
302 g_param_spec_object ("related-action",
303 P_("Related Action"),
304 P_("The action this activatable will activate and receive updates from"),
306 GTK_PARAM_READWRITE));
309 * GtkActivatable:use-action-appearance:
311 * Whether this activatable should reset its layout
312 * and appearance when setting the related action or when
313 * the action changes appearance.
315 * See the #GtkAction documentation directly to find which properties
316 * should be ignored by the #GtkActivatable when this property is %FALSE.
318 * <note><para>#GtkActivatable implementors need to handle this property
319 * and call gtk_activatable_reset() on the activatable widget when it changes.</para></note>
323 g_object_interface_install_property (g_iface,
324 g_param_spec_boolean ("use-action-appearance",
325 P_("Use Action Appearance"),
326 P_("Whether to use the related actions appearance properties"),
328 GTK_PARAM_READWRITE));
334 gtk_activatable_update (GtkActivatable *activatable,
336 const gchar *property_name)
338 GtkActivatableIface *iface;
340 g_return_if_fail (GTK_IS_ACTIVATABLE (activatable));
342 iface = GTK_ACTIVATABLE_GET_IFACE (activatable);
344 iface->update (activatable, action, property_name);
346 g_critical ("GtkActivatable->update() unimplemented for type %s",
347 g_type_name (G_OBJECT_TYPE (activatable)));
351 * gtk_activatable_reset:
352 * @activatable: a #GtkActivatable
353 * @action: the related #GtkAction or %NULL
355 * This is called to update the activatable completely, this is called internally when
356 * the #GtkActivatable::related-action property is set or unset and by the implementing
357 * class when #GtkActivatable::use-action-appearance changes.
362 gtk_activatable_reset (GtkActivatable *activatable,
365 GtkActivatableIface *iface;
367 g_return_if_fail (GTK_IS_ACTIVATABLE (activatable));
369 iface = GTK_ACTIVATABLE_GET_IFACE (activatable);
371 iface->reset (activatable, action);
373 g_critical ("GtkActivatable->reset() unimplemented for type %s",
374 g_type_name (G_OBJECT_TYPE (activatable)));
379 * gtk_activatable_set_related_action:
380 * @activatable: a #GtkActivatable
381 * @action: the #GtkAction to set
383 * Sets the related action on the @activatable object.
385 * <note><para>#GtkActivatable implementors need to handle the #GtkActivatable:related-action
386 * property and call gtk_activatable_do_set_related_action() when it changes.</para></note>
391 gtk_activatable_set_related_action (GtkActivatable *activatable,
394 g_return_if_fail (GTK_IS_ACTIVATABLE (activatable));
395 g_return_if_fail (action == NULL || GTK_IS_ACTION (action));
397 g_object_set (activatable, "related-action", action, NULL);
401 gtk_activatable_action_notify (GtkAction *action,
403 GtkActivatable *activatable)
405 gtk_activatable_update (activatable, action, pspec->name);
409 * gtk_activatable_do_set_related_action:
410 * @activatable: a #GtkActivatable
411 * @action: the #GtkAction to set
413 * This is a utility function for #GtkActivatable implementors.
415 * When implementing #GtkActivatable you must call this when
416 * handling changes of the #GtkActivatable:related-action, and
417 * you must also use this to break references in #GObject->dispose().
419 * This function adds a reference to the currently set related
420 * action for you, it also makes sure the #GtkActivatable->update()
421 * method is called when the related #GtkAction properties change
422 * and registers to the action's proxy list.
424 * <note><para>Be careful to call this before setting the local
425 * copy of the #GtkAction property, since this function uses
426 * gtk_activatable_get_action() to retrieve the previous action</para></note>
431 gtk_activatable_do_set_related_action (GtkActivatable *activatable,
434 GtkAction *prev_action;
436 prev_action = gtk_activatable_get_related_action (activatable);
438 if (prev_action != action)
442 g_signal_handlers_disconnect_by_func (prev_action, gtk_activatable_action_notify, activatable);
444 _gtk_action_remove_from_proxy_list (prev_action, GTK_WIDGET (activatable));
446 g_object_unref (prev_action);
448 /* Some apps are using the object data directly...
449 * so continue to set it for a bit longer
451 g_object_set_data (activatable, "gtk-action", NULL);
454 /* Some applications rely on their proxy UI to be set up
455 * before they receive the ::connect-proxy signal, so we
456 * need to call reset() before add_to_proxy_list().
458 gtk_activatable_reset (activatable, action);
462 g_object_ref (action);
464 g_signal_connect (G_OBJECT (action), "notify", G_CALLBACK (gtk_activatable_action_notify), activatable);
466 _gtk_action_add_to_proxy_list (action, GTK_WIDGET (activatable));
468 g_object_set_data (activatable, "gtk-action", action);
474 * gtk_activatable_get_related_action:
475 * @activatable: a #GtkActivatable
477 * Gets the related #GtkAction for @activatable.
479 * Returns: the related #GtkAction if one is set.
484 gtk_activatable_get_related_action (GtkActivatable *activatable)
488 g_return_val_if_fail (GTK_IS_ACTIVATABLE (activatable), NULL);
490 g_object_get (activatable, "related-action", &action, NULL);
492 /* g_object_get() gives us a ref... */
494 g_object_unref (action);
500 * gtk_activatable_set_use_action_appearance:
501 * @activatable: a #GtkActivatable
502 * @use_appearance: whether to use the actions appearance
504 * Sets whether this activatable should reset its layout and appearance
505 * when setting the related action or when the action changes appearance
507 * <note><para>#GtkActivatable implementors need to handle the #GtkActivatable:use-action-appearance
508 * property and call gtk_activatable_reset() to update @activatable if needed.</para></note>
513 gtk_activatable_set_use_action_appearance (GtkActivatable *activatable,
514 gboolean use_appearance)
516 g_object_set (activatable, "use-action-appearance", use_appearance, NULL);
520 * gtk_activatable_get_use_action_appearance:
521 * @activatable: a #GtkActivatable
523 * Gets whether this activatable should reset its layout
524 * and appearance when setting the related action or when
525 * the action changes appearance.
527 * Returns: whether @activatable uses its actions appearance.
532 gtk_activatable_get_use_action_appearance (GtkActivatable *activatable)
534 gboolean use_appearance;
536 g_object_get (activatable, "use-action-appearance", &use_appearance, NULL);
538 return use_appearance;
541 #define __GTK_ACTIVATABLE_C__
542 #include "gtkaliasdef.c"