GtkActivatable

Activatable widgets can be connected to a #GtkAction and reflects the state of its action. A #GtkActivatable can also provide feedback through its action, as they are responsible for activating their related actions.

Implementing GtkActivatable

When extending a class that is already #GtkActivatable; it is only necessary to implement the #GtkActivatable->sync_action_properties() and #GtkActivatable->update() methods and chain up to the parent implementation, however when introducing a new #GtkActivatable class; the #GtkActivatable:related-action and #GtkActivatable:use-action-appearance properties need to be handled by the implementor. Handling these properties is mostly a matter of installing the action pointer and boolean flag on your instance, and calling gtk.activatable.Activatable.doSetRelatedAction and gtk.activatable.Activatable.syncActionProperties at the appropriate times.

A class fragment implementing #GtkActivatable

1 
2 enum {
3 ...
4 
5 PROP_ACTIVATABLE_RELATED_ACTION,
6 PROP_ACTIVATABLE_USE_ACTION_APPEARANCE
7 }
8 
9 struct _FooBarPrivate
10 {
11 
12   ...
13 
14   GtkAction      *action;
15   gboolean        use_action_appearance;
16 };
17 
18 ...
19 
20 static void foo_bar_activatable_interface_init         (GtkActivatableIface  *iface);
21 static void foo_bar_activatable_update                 (GtkActivatable       *activatable,
22 						           GtkAction            *action,
23 						           const gchar          *property_name);
24 static void foo_bar_activatable_sync_action_properties (GtkActivatable       *activatable,
25 						           GtkAction            *action);
26 ...
27 
28 
29 static void
30 foo_bar_class_init (FooBarClass *klass)
31 {
32 
33   ...
34 
35   g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action");
36   g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance");
37 
38   ...
39 }
40 
41 
42 static void
43 foo_bar_activatable_interface_init (GtkActivatableIface  *iface)
44 {
45   iface->update = foo_bar_activatable_update;
46   iface->sync_action_properties = foo_bar_activatable_sync_action_properties;
47 }
48 
49 ... Break the reference using gtk_activatable_do_set_related_action()...
50 
51 static void
52 foo_bar_dispose (GObject *object)
53 {
54   FooBar *bar = FOO_BAR (object);
55   FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (bar);
56 
57   ...
58 
59   if (priv->action)
60     {
61       gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (bar), NULL);
62       priv->action = NULL;
63     }
64   G_OBJECT_CLASS (foo_bar_parent_class)->dispose (object);
65 }
66 
67 ... Handle the “related-action” and “use-action-appearance” properties ...
68 
69 static void
70 foo_bar_set_property (GObject         *object,
71                       guint            prop_id,
72                       const GValue    *value,
73                       GParamSpec      *pspec)
74 {
75   FooBar *bar = FOO_BAR (object);
76   FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (bar);
77 
78   switch (prop_id)
79     {
80 
81       ...
82 
83     case PROP_ACTIVATABLE_RELATED_ACTION:
84       foo_bar_set_related_action (bar, g_value_get_object (value));
85       break;
86     case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
87       foo_bar_set_use_action_appearance (bar, g_value_get_boolean (value));
88       break;
89     default:
90       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
91       break;
92     }
93 }
94 
95 static void
96 foo_bar_get_property (GObject         *object,
97                          guint            prop_id,
98                          GValue          *value,
99                          GParamSpec      *pspec)
100 {
101   FooBar *bar = FOO_BAR (object);
102   FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (bar);
103 
104   switch (prop_id)
105     {
106 
107       ...
108 
109     case PROP_ACTIVATABLE_RELATED_ACTION:
110       g_value_set_object (value, priv->action);
111       break;
112     case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
113       g_value_set_boolean (value, priv->use_action_appearance);
114       break;
115     default:
116       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
117       break;
118     }
119 }
120 
121 
122 static void
123 foo_bar_set_use_action_appearance (FooBar   *bar,
124 				   gboolean  use_appearance)
125 {
126   FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (bar);
127 
128   if (priv->use_action_appearance != use_appearance)
129     {
130       priv->use_action_appearance = use_appearance;
131 
132       gtk_activatable_sync_action_properties (GTK_ACTIVATABLE (bar), priv->action);
133     }
134 }
135 
136 ... call gtk_activatable_do_set_related_action() and then assign the action pointer,
137 no need to reference the action here since gtk_activatable_do_set_related_action() already
138 holds a reference here for you...
139 static void
140 foo_bar_set_related_action (FooBar    *bar,
141 			    GtkAction *action)
142 {
143   FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (bar);
144 
145   if (priv->action == action)
146     return;
147 
148   gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (bar), action);
149 
150   priv->action = action;
151 }
152 
153 ... Selectively reset and update activatable depending on the use-action-appearance property ...
154 static void
155 gtk_button_activatable_sync_action_properties (GtkActivatable       *activatable,
156 		                                  GtkAction            *action)
157 {
158   GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (activatable);
159 
160   if (!action)
161     return;
162 
163   if (gtk_action_is_visible (action))
164     gtk_widget_show (GTK_WIDGET (activatable));
165   else
166     gtk_widget_hide (GTK_WIDGET (activatable));
167 
168   gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
169 
170   ...
171 
172   if (priv->use_action_appearance)
173     {
174       if (gtk_action_get_stock_id (action))
175 	foo_bar_set_stock (button, gtk_action_get_stock_id (action));
176       else if (gtk_action_get_label (action))
177 	foo_bar_set_label (button, gtk_action_get_label (action));
178 
179       ...
180 
181     }
182 }
183 
184 static void
185 foo_bar_activatable_update (GtkActivatable       *activatable,
186 			       GtkAction            *action,
187 			       const gchar          *property_name)
188 {
189   FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (activatable);
190 
191   if (strcmp (property_name, "visible") == 0)
192     {
193       if (gtk_action_is_visible (action))
194 	gtk_widget_show (GTK_WIDGET (activatable));
195       else
196 	gtk_widget_hide (GTK_WIDGET (activatable));
197     }
198   else if (strcmp (property_name, "sensitive") == 0)
199     gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
200 
201   ...
202 
203   if (!priv->use_action_appearance)
204     return;
205 
206   if (strcmp (property_name, "stock-id") == 0)
207     foo_bar_set_stock (button, gtk_action_get_stock_id (action));
208   else if (strcmp (property_name, "label") == 0)
209     foo_bar_set_label (button, gtk_action_get_label (action));
210 
211   ...
212 }
struct GtkActivatable