1/* gtkbuildable.c
2 * Copyright (C) 2006-2007 Async Open Source,
3 * Johan Dahlin <jdahlin@async.com.br>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * GtkBuildable:
21 *
22 * `GtkBuildable` allows objects to extend and customize their deserialization
23 * from ui files.
24 *
25 * The interface includes methods for setting names and properties of objects,
26 * parsing custom tags and constructing child objects.
27 *
28 * The `GtkBuildable` interface is implemented by all widgets and
29 * many of the non-widget objects that are provided by GTK. The
30 * main user of this interface is [class@Gtk.Builder]. There should be
31 * very little need for applications to call any of these functions directly.
32 *
33 * An object only needs to implement this interface if it needs to extend the
34 * `GtkBuilder` XML format or run any extra routines at deserialization time.
35 */
36
37#include "config.h"
38#include "gtkbuildableprivate.h"
39#include "gtkintl.h"
40
41
42typedef GtkBuildableIface GtkBuildableInterface;
43G_DEFINE_INTERFACE (GtkBuildable, gtk_buildable, G_TYPE_OBJECT)
44
45static void
46gtk_buildable_default_init (GtkBuildableInterface *iface)
47{
48}
49
50/*< private >
51 * gtk_buildable_set_buildable_id:
52 * @buildable: a `GtkBuildable`
53 * @id: name to set
54 *
55 * Sets the ID of the @buildable object.
56 */
57void
58gtk_buildable_set_buildable_id (GtkBuildable *buildable,
59 const char *id)
60{
61 GtkBuildableIface *iface;
62
63 g_return_if_fail (GTK_IS_BUILDABLE (buildable));
64 g_return_if_fail (id != NULL);
65
66 iface = GTK_BUILDABLE_GET_IFACE (buildable);
67
68 if (iface->set_id)
69 (* iface->set_id) (buildable, id);
70 else
71 g_object_set_data_full (G_OBJECT (buildable),
72 key: "gtk-builder-id",
73 data: g_strdup (str: id),
74 destroy: g_free);
75}
76
77/**
78 * gtk_buildable_get_buildable_id:
79 * @buildable: a `GtkBuildable`
80 *
81 * Gets the ID of the @buildable object.
82 *
83 * `GtkBuilder` sets the name based on the ID attribute
84 * of the <object> tag used to construct the @buildable.
85 *
86 * Returns: (nullable): the ID of the buildable object
87 **/
88const char *
89gtk_buildable_get_buildable_id (GtkBuildable *buildable)
90{
91 GtkBuildableIface *iface;
92
93 g_return_val_if_fail (GTK_IS_BUILDABLE (buildable), NULL);
94
95 iface = GTK_BUILDABLE_GET_IFACE (buildable);
96
97 if (iface->get_id)
98 return (* iface->get_id) (buildable);
99 else
100 return (const char *)g_object_get_data (G_OBJECT (buildable),
101 key: "gtk-builder-id");
102}
103
104/*< private >
105 * gtk_buildable_add_child:
106 * @buildable: a `GtkBuildable`
107 * @builder: a `GtkBuilder`
108 * @child: child to add
109 * @type: (nullable): kind of child
110 *
111 * Adds a child to @buildable. @type is an optional string
112 * describing how the child should be added.
113 */
114void
115gtk_buildable_add_child (GtkBuildable *buildable,
116 GtkBuilder *builder,
117 GObject *child,
118 const char *type)
119{
120 GtkBuildableIface *iface;
121
122 g_return_if_fail (GTK_IS_BUILDABLE (buildable));
123 g_return_if_fail (GTK_IS_BUILDER (builder));
124
125 iface = GTK_BUILDABLE_GET_IFACE (buildable);
126 g_return_if_fail (iface->add_child != NULL);
127
128 (* iface->add_child) (buildable, builder, child, type);
129}
130
131/*< private >
132 * gtk_buildable_parser_finished:
133 * @buildable: a `GtkBuildable`
134 * @builder: a `GtkBuilder`
135 *
136 * Called when the builder finishes the parsing of a
137 * GtkBuilder UI definition.
138 *
139 * Note that this will be called once for each time
140 * gtk_builder_add_from_file() or gtk_builder_add_from_string()
141 * is called on a builder.
142 */
143void
144gtk_buildable_parser_finished (GtkBuildable *buildable,
145 GtkBuilder *builder)
146{
147 GtkBuildableIface *iface;
148
149 g_return_if_fail (GTK_IS_BUILDABLE (buildable));
150 g_return_if_fail (GTK_IS_BUILDER (builder));
151
152 iface = GTK_BUILDABLE_GET_IFACE (buildable);
153 if (iface->parser_finished)
154 (* iface->parser_finished) (buildable, builder);
155}
156
157/*< private >
158 * gtk_buildable_construct_child:
159 * @buildable: A `GtkBuildable`
160 * @builder: `GtkBuilder` used to construct this object
161 * @name: name of child to construct
162 *
163 * Constructs a child of @buildable with the name @name.
164 *
165 * `GtkBuilder` calls this function if a “constructor” has been
166 * specified in the UI definition.
167 *
168 * Returns: (transfer full): the constructed child
169 */
170GObject *
171gtk_buildable_construct_child (GtkBuildable *buildable,
172 GtkBuilder *builder,
173 const char *name)
174{
175 GtkBuildableIface *iface;
176
177 g_return_val_if_fail (GTK_IS_BUILDABLE (buildable), NULL);
178 g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
179 g_return_val_if_fail (name != NULL, NULL);
180
181 iface = GTK_BUILDABLE_GET_IFACE (buildable);
182 g_return_val_if_fail (iface->construct_child != NULL, NULL);
183
184 return (* iface->construct_child) (buildable, builder, name);
185}
186
187/*< private >
188 * gtk_buildable_custom_tag_start:
189 * @buildable: a `GtkBuildable`
190 * @builder: a `GtkBuilder` used to construct this object
191 * @child: (nullable): child object or %NULL for non-child tags
192 * @tagname: name of tag
193 * @parser: (out): a `GMarkupParser` to fill in
194 * @data: (out): return location for user data that will be passed in
195 * to parser functions
196 *
197 * This is called for each unknown element under <child>.
198 *
199 * Returns: %TRUE if an object has a custom implementation, %FALSE
200 * if it doesn't.
201 */
202gboolean
203gtk_buildable_custom_tag_start (GtkBuildable *buildable,
204 GtkBuilder *builder,
205 GObject *child,
206 const char *tagname,
207 GtkBuildableParser *parser,
208 gpointer *data)
209{
210 GtkBuildableIface *iface;
211
212 g_return_val_if_fail (GTK_IS_BUILDABLE (buildable), FALSE);
213 g_return_val_if_fail (GTK_IS_BUILDER (builder), FALSE);
214 g_return_val_if_fail (tagname != NULL, FALSE);
215
216 iface = GTK_BUILDABLE_GET_IFACE (buildable);
217 g_return_val_if_fail (iface->custom_tag_start != NULL, FALSE);
218
219 return (* iface->custom_tag_start) (buildable, builder, child,
220 tagname, parser, data);
221}
222
223/*< private >
224 * gtk_buildable_custom_tag_end:
225 * @buildable: A `GtkBuildable`
226 * @builder: `GtkBuilder` used to construct this object
227 * @child: (nullable): child object or %NULL for non-child tags
228 * @tagname: name of tag
229 * @data: user data that will be passed in to parser functions
230 *
231 * This is called at the end of each custom element handled by
232 * the buildable.
233 */
234void
235gtk_buildable_custom_tag_end (GtkBuildable *buildable,
236 GtkBuilder *builder,
237 GObject *child,
238 const char *tagname,
239 gpointer data)
240{
241 GtkBuildableIface *iface;
242
243 g_return_if_fail (GTK_IS_BUILDABLE (buildable));
244 g_return_if_fail (GTK_IS_BUILDER (builder));
245 g_return_if_fail (tagname != NULL);
246
247 iface = GTK_BUILDABLE_GET_IFACE (buildable);
248 if (iface->custom_tag_end)
249 (* iface->custom_tag_end) (buildable, builder, child, tagname, data);
250}
251
252/*< private >
253 * gtk_buildable_custom_finished:
254 * @buildable: a `GtkBuildable`
255 * @builder: a `GtkBuilder`
256 * @child: (nullable): child object or %NULL for non-child tags
257 * @tagname: the name of the tag
258 * @data: user data created in custom_tag_start
259 *
260 * This is similar to gtk_buildable_parser_finished() but is
261 * called once for each custom tag handled by the @buildable.
262 */
263void
264gtk_buildable_custom_finished (GtkBuildable *buildable,
265 GtkBuilder *builder,
266 GObject *child,
267 const char *tagname,
268 gpointer data)
269{
270 GtkBuildableIface *iface;
271
272 g_return_if_fail (GTK_IS_BUILDABLE (buildable));
273 g_return_if_fail (GTK_IS_BUILDER (builder));
274
275 iface = GTK_BUILDABLE_GET_IFACE (buildable);
276 if (iface->custom_finished)
277 (* iface->custom_finished) (buildable, builder, child, tagname, data);
278}
279
280/*< private >
281 * gtk_buildable_get_internal_child:
282 * @buildable: a `GtkBuildable`
283 * @builder: a `GtkBuilder`
284 * @childname: name of child
285 *
286 * Get the internal child called @childname of the @buildable object.
287 *
288 * Returns: (transfer none): the internal child of the buildable object
289 */
290GObject *
291gtk_buildable_get_internal_child (GtkBuildable *buildable,
292 GtkBuilder *builder,
293 const char *childname)
294{
295 GtkBuildableIface *iface;
296
297 g_return_val_if_fail (GTK_IS_BUILDABLE (buildable), NULL);
298 g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
299 g_return_val_if_fail (childname != NULL, NULL);
300
301 iface = GTK_BUILDABLE_GET_IFACE (buildable);
302 if (!iface->get_internal_child)
303 return NULL;
304
305 return (* iface->get_internal_child) (buildable, builder, childname);
306}
307

source code of gtk/gtk/gtkbuildable.c