1 /*
2 * Copyright © 2012 Canonical Limited
3 *
4 * This library is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * licence or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful, but
10 * 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 Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authors: Ryan Lortie <desrt@desrt.ca>
18 */
19
20 #include "config.h"
21
22 #include "gtkactionable.h"
23
24 #include "gtkwidget.h"
25 #include "gtkintl.h"
26
27 /**
28 * SECTION:gtkactionable
29 * @title: GtkActionable
30 * @short_description: An interface for widgets that can be associated
31 * with actions
32 *
33 * This interface provides a convenient way of associating widgets with
34 * actions on a #GtkApplicationWindow or #GtkApplication.
35 *
36 * It primarily consists of two properties: #GtkActionable:action-name
37 * and #GtkActionable:action-target. There are also some convenience APIs
38 * for setting these properties.
39 *
40 * The action will be looked up in action groups that are found among
41 * the widgets ancestors. Most commonly, these will be the actions with
42 * the “win.” or “app.” prefix that are associated with the #GtkApplicationWindow
43 * or #GtkApplication, but other action groups that are added with
44 * gtk_widget_insert_action_group() will be consulted as well.
45 *
46 * Since: 3.4
47 **/
48
49 /**
50 * GtkActionable:
51 *
52 * An opaque pointer type.
53 **/
54
55 /**
56 * GtkActionableInterface:
57 * @get_action_name: virtual function for gtk_actionable_get_action_name()
58 * @set_action_name: virtual function for gtk_actionable_set_action_name()
59 * @get_action_target_value: virtual function for gtk_actionable_get_action_target_value()
60 * @set_action_target_value: virtual function for gtk_actionable_set_action_target_value()
61 *
62 * The interface vtable for #GtkActionable.
63 **/
64
G_DEFINE_INTERFACE(GtkActionable,gtk_actionable,GTK_TYPE_WIDGET)65 G_DEFINE_INTERFACE (GtkActionable, gtk_actionable, GTK_TYPE_WIDGET)
66
67 static void
68 gtk_actionable_default_init (GtkActionableInterface *iface)
69 {
70 g_object_interface_install_property (iface,
71 g_param_spec_string ("action-name", P_("Action name"),
72 P_("The name of the associated action, like 'app.quit'"),
73 NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
74
75 g_object_interface_install_property (iface,
76 g_param_spec_variant ("action-target", P_("Action target value"),
77 P_("The parameter for action invocations"),
78 G_VARIANT_TYPE_ANY, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
79 }
80
81 /**
82 * gtk_actionable_get_action_name:
83 * @actionable: a #GtkActionable widget
84 *
85 * Gets the action name for @actionable.
86 *
87 * See gtk_actionable_set_action_name() for more information.
88 *
89 * Returns: (nullable): the action name, or %NULL if none is set
90 *
91 * Since: 3.4
92 **/
93 const gchar *
gtk_actionable_get_action_name(GtkActionable * actionable)94 gtk_actionable_get_action_name (GtkActionable *actionable)
95 {
96 g_return_val_if_fail (GTK_IS_ACTIONABLE (actionable), NULL);
97
98 return GTK_ACTIONABLE_GET_IFACE (actionable)
99 ->get_action_name (actionable);
100 }
101
102 /**
103 * gtk_actionable_set_action_name:
104 * @actionable: a #GtkActionable widget
105 * @action_name: (nullable): an action name, or %NULL
106 *
107 * Specifies the name of the action with which this widget should be
108 * associated. If @action_name is %NULL then the widget will be
109 * unassociated from any previous action.
110 *
111 * Usually this function is used when the widget is located (or will be
112 * located) within the hierarchy of a #GtkApplicationWindow.
113 *
114 * Names are of the form “win.save” or “app.quit” for actions on the
115 * containing #GtkApplicationWindow or its associated #GtkApplication,
116 * respectively. This is the same form used for actions in the #GMenu
117 * associated with the window.
118 *
119 * Since: 3.4
120 **/
121 void
gtk_actionable_set_action_name(GtkActionable * actionable,const gchar * action_name)122 gtk_actionable_set_action_name (GtkActionable *actionable,
123 const gchar *action_name)
124 {
125 g_return_if_fail (GTK_IS_ACTIONABLE (actionable));
126
127 GTK_ACTIONABLE_GET_IFACE (actionable)
128 ->set_action_name (actionable, action_name);
129 }
130
131 /**
132 * gtk_actionable_get_action_target_value:
133 * @actionable: a #GtkActionable widget
134 *
135 * Gets the current target value of @actionable.
136 *
137 * See gtk_actionable_set_action_target_value() for more information.
138 *
139 * Returns: (transfer none): the current target value
140 *
141 * Since: 3.4
142 **/
143 GVariant *
gtk_actionable_get_action_target_value(GtkActionable * actionable)144 gtk_actionable_get_action_target_value (GtkActionable *actionable)
145 {
146 g_return_val_if_fail (GTK_IS_ACTIONABLE (actionable), NULL);
147
148 return GTK_ACTIONABLE_GET_IFACE (actionable)
149 ->get_action_target_value (actionable);
150 }
151
152 /**
153 * gtk_actionable_set_action_target_value:
154 * @actionable: a #GtkActionable widget
155 * @target_value: (nullable): a #GVariant to set as the target value, or %NULL
156 *
157 * Sets the target value of an actionable widget.
158 *
159 * If @target_value is %NULL then the target value is unset.
160 *
161 * The target value has two purposes. First, it is used as the
162 * parameter to activation of the action associated with the
163 * #GtkActionable widget. Second, it is used to determine if the widget
164 * should be rendered as “active” — the widget is active if the state
165 * is equal to the given target.
166 *
167 * Consider the example of associating a set of buttons with a #GAction
168 * with string state in a typical “radio button” situation. Each button
169 * will be associated with the same action, but with a different target
170 * value for that action. Clicking on a particular button will activate
171 * the action with the target of that button, which will typically cause
172 * the action’s state to change to that value. Since the action’s state
173 * is now equal to the target value of the button, the button will now
174 * be rendered as active (and the other buttons, with different targets,
175 * rendered inactive).
176 *
177 * Since: 3.4
178 **/
179 void
gtk_actionable_set_action_target_value(GtkActionable * actionable,GVariant * target_value)180 gtk_actionable_set_action_target_value (GtkActionable *actionable,
181 GVariant *target_value)
182 {
183 g_return_if_fail (GTK_IS_ACTIONABLE (actionable));
184
185 GTK_ACTIONABLE_GET_IFACE (actionable)
186 ->set_action_target_value (actionable, target_value);
187 }
188
189 /**
190 * gtk_actionable_set_action_target:
191 * @actionable: a #GtkActionable widget
192 * @format_string: a GVariant format string
193 * @...: arguments appropriate for @format_string
194 *
195 * Sets the target of an actionable widget.
196 *
197 * This is a convenience function that calls g_variant_new() for
198 * @format_string and uses the result to call
199 * gtk_actionable_set_action_target_value().
200 *
201 * If you are setting a string-valued target and want to set the action
202 * name at the same time, you can use
203 * gtk_actionable_set_detailed_action_name ().
204 *
205 * Since: 3.4
206 **/
207 void
gtk_actionable_set_action_target(GtkActionable * actionable,const gchar * format_string,...)208 gtk_actionable_set_action_target (GtkActionable *actionable,
209 const gchar *format_string,
210 ...)
211 {
212 va_list ap;
213
214 va_start (ap, format_string);
215 gtk_actionable_set_action_target_value (actionable, g_variant_new_va (format_string, NULL, &ap));
216 va_end (ap);
217 }
218
219 /**
220 * gtk_actionable_set_detailed_action_name:
221 * @actionable: a #GtkActionable widget
222 * @detailed_action_name: the detailed action name
223 *
224 * Sets the action-name and associated string target value of an
225 * actionable widget.
226 *
227 * @detailed_action_name is a string in the format accepted by
228 * g_action_parse_detailed_name().
229 *
230 * (Note that prior to version 3.22.25,
231 * this function is only usable for actions with a simple "s" target, and
232 * @detailed_action_name must be of the form `"action::target"` where
233 * `action` is the action name and `target` is the string to use
234 * as the target.)
235 *
236 * Since: 3.4
237 **/
238 void
gtk_actionable_set_detailed_action_name(GtkActionable * actionable,const gchar * detailed_action_name)239 gtk_actionable_set_detailed_action_name (GtkActionable *actionable,
240 const gchar *detailed_action_name)
241 {
242 GError *error = NULL;
243 GVariant *target;
244 gchar *name;
245
246 if (detailed_action_name == NULL)
247 {
248 gtk_actionable_set_action_name (actionable, NULL);
249 gtk_actionable_set_action_target_value (actionable, NULL);
250 return;
251 }
252
253 if (!g_action_parse_detailed_name (detailed_action_name, &name, &target, &error))
254 g_error ("gtk_actionable_set_detailed_action_name: %s", error->message);
255
256 gtk_actionable_set_action_name (actionable, name);
257 gtk_actionable_set_action_target_value (actionable, target);
258
259 if (target)
260 g_variant_unref (target);
261 g_free (name);
262 }
263
264