]> Pileus Git - ~andy/gtk/blob - gtk/gtkcelllayout.c
Add GtkBuilder, fixes #172535
[~andy/gtk] / gtk / gtkcelllayout.c
1 /* gtkcelllayout.c
2  * Copyright (C) 2003  Kristian Rietveld  <kris@gtk.org>
3  *
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.
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  * Library General Public License for more details.
13  *
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.
18  */
19
20 #include <string.h>
21 #include <stdlib.h>
22 #include <config.h>
23 #include "gtkcelllayout.h"
24 #include "gtkintl.h"
25 #include "gtkalias.h"
26
27 GType
28 gtk_cell_layout_get_type (void)
29 {
30   static GType cell_layout_type = 0;
31
32   if (! cell_layout_type)
33     {
34       const GTypeInfo cell_layout_info =
35       {
36         sizeof (GtkCellLayoutIface),
37         NULL,
38         NULL,
39         NULL,
40         NULL,
41         NULL,
42         0,
43         0,
44         NULL
45       };
46
47       cell_layout_type =
48         g_type_register_static (G_TYPE_INTERFACE, I_("GtkCellLayout"),
49                                 &cell_layout_info, 0);
50
51       g_type_interface_add_prerequisite (cell_layout_type, G_TYPE_OBJECT);
52     }
53
54   return cell_layout_type;
55 }
56
57 /**
58  * gtk_cell_layout_pack_start:
59  * @cell_layout: A #GtkCellLayout.
60  * @cell: A #GtkCellRenderer.
61  * @expand: %TRUE if @cell is to be given extra space allocated to @cell_layout.
62  *
63  * Packs the @cell into the beginning of @cell_layout. If @expand is %FALSE,
64  * then the @cell is allocated no more space than it needs. Any unused space
65  * is divided evenly between cells for which @expand is %TRUE.
66  *
67  * Note that reusing the same cell renderer is not supported. 
68  *
69  * Since: 2.4
70  */
71 void
72 gtk_cell_layout_pack_start (GtkCellLayout   *cell_layout,
73                             GtkCellRenderer *cell,
74                             gboolean         expand)
75 {
76   g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
77   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
78
79   (* GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->pack_start) (cell_layout,
80                                                            cell,
81                                                            expand);
82 }
83
84 /**
85  * gtk_cell_layout_pack_end:
86  * @cell_layout: A #GtkCellLayout.
87  * @cell: A #GtkCellRenderer.
88  * @expand: %TRUE if @cell is to be given extra space allocated to @cell_layout.
89  *
90  * Adds the @cell to the end of @cell_layout. If @expand is %FALSE, then the
91  * @cell is allocated no more space than it needs. Any unused space is
92  * divided evenly between cells for which @expand is %TRUE.
93  *
94  * Note that reusing the same cell renderer is not supported. 
95  *
96  * Since: 2.4
97  */
98 void
99 gtk_cell_layout_pack_end (GtkCellLayout   *cell_layout,
100                           GtkCellRenderer *cell,
101                           gboolean         expand)
102 {
103   g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
104   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
105
106   (* GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->pack_end) (cell_layout,
107                                                          cell,
108                                                          expand);
109 }
110
111 /**
112  * gtk_cell_layout_clear:
113  * @cell_layout: A #GtkCellLayout.
114  *
115  * Unsets all the mappings on all renderers on @cell_layout and
116  * removes all renderers from @cell_layout.
117  *
118  * Since: 2.4
119  */
120 void
121 gtk_cell_layout_clear (GtkCellLayout *cell_layout)
122 {
123   g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
124
125   (* GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->clear) (cell_layout);
126 }
127
128 static void
129 gtk_cell_layout_set_attributesv (GtkCellLayout   *cell_layout,
130                                  GtkCellRenderer *cell,
131                                  va_list          args)
132 {
133   gchar *attribute;
134   gint column;
135   GtkCellLayoutIface *iface;
136
137   attribute = va_arg (args, gchar *);
138
139   iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
140
141   (* iface->clear_attributes) (cell_layout, cell);
142
143   while (attribute != NULL)
144     {
145       column = va_arg (args, gint);
146       (* iface->add_attribute) (cell_layout, cell, attribute, column);
147       attribute = va_arg (args, gchar *);
148     }
149 }
150
151 /**
152  * gtk_cell_layout_set_attributes:
153  * @cell_layout: A #GtkCellLayout.
154  * @cell: A #GtkCellRenderer.
155  * @Varargs: A %NULL-terminated list of attributes.
156  *
157  * Sets the attributes in list as the attributes of @cell_layout. The
158  * attributes should be in attribute/column order, as in
159  * gtk_cell_layout_add_attribute(). All existing attributes are removed, and
160  * replaced with the new attributes.
161  *
162  * Since: 2.4
163  */
164 void
165 gtk_cell_layout_set_attributes (GtkCellLayout   *cell_layout,
166                                 GtkCellRenderer *cell,
167                                 ...)
168 {
169   va_list args;
170
171   g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
172   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
173
174   va_start (args, cell);
175   gtk_cell_layout_set_attributesv (cell_layout, cell, args);
176   va_end (args);
177 }
178
179 /**
180  * gtk_cell_layout_add_attribute:
181  * @cell_layout: A #GtkCellLayout.
182  * @cell: A #GtkCellRenderer.
183  * @attribute: An attribute on the renderer.
184  * @column: The column position on the model to get the attribute from.
185  *
186  * Adds an attribute mapping to the list in @cell_layout. The @column is the
187  * column of the model to get a value from, and the @attribute is the
188  * parameter on @cell to be set from the value. So for example if column 2
189  * of the model contains strings, you could have the "text" attribute of a
190  * #GtkCellRendererText get its values from column 2.
191  *
192  * Since: 2.4
193  */
194 void
195 gtk_cell_layout_add_attribute (GtkCellLayout   *cell_layout,
196                                GtkCellRenderer *cell,
197                                const gchar     *attribute,
198                                gint             column)
199 {
200   g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
201   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
202   g_return_if_fail (attribute != NULL);
203   g_return_if_fail (column >= 0);
204
205   (* GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->add_attribute) (cell_layout,
206                                                               cell,
207                                                               attribute,
208                                                               column);
209 }
210
211 /**
212  * gtk_cell_layout_set_cell_data_func:
213  * @cell_layout: A #GtkCellLayout.
214  * @cell: A #GtkCellRenderer.
215  * @func: The #GtkCellLayoutDataFunc to use.
216  * @func_data: The user data for @func.
217  * @destroy: The destroy notification for @func_data.
218  *
219  * Sets the #GtkCellLayoutDataFunc to use for @cell_layout. This function
220  * is used instead of the standard attributes mapping for setting the
221  * column value, and should set the value of @cell_layout's cell renderer(s)
222  * as appropriate. @func may be %NULL to remove and older one.
223  *
224  * Since: 2.4
225  */
226 void
227 gtk_cell_layout_set_cell_data_func (GtkCellLayout         *cell_layout,
228                                     GtkCellRenderer       *cell,
229                                     GtkCellLayoutDataFunc  func,
230                                     gpointer               func_data,
231                                     GDestroyNotify         destroy)
232 {
233   g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
234   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
235
236   (* GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->set_cell_data_func) (cell_layout,
237                                                                    cell,
238                                                                    func,
239                                                                    func_data,
240                                                                    destroy);
241 }
242
243 /**
244  * gtk_cell_layout_clear_attributes:
245  * @cell_layout: A #GtkCellLayout.
246  * @cell: A #GtkCellRenderer to clear the attribute mapping on.
247  *
248  * Clears all existing attributes previously set with
249  * gtk_cell_layout_set_attributes().
250  *
251  * Since: 2.4
252  */
253 void
254 gtk_cell_layout_clear_attributes (GtkCellLayout   *cell_layout,
255                                   GtkCellRenderer *cell)
256 {
257   g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
258   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
259
260   (* GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->clear_attributes) (cell_layout,
261                                                                  cell);
262 }
263
264 /**
265  * gtk_cell_layout_reorder:
266  * @cell_layout: A #GtkCellLayout.
267  * @cell: A #GtkCellRenderer to reorder.
268  * @position: New position to insert @cell at.
269  *
270  * Re-inserts @cell at @position. Note that @cell has already to be packed
271  * into @cell_layout for this to function properly.
272  *
273  * Since: 2.4
274  */
275 void
276 gtk_cell_layout_reorder (GtkCellLayout   *cell_layout,
277                          GtkCellRenderer *cell,
278                          gint             position)
279 {
280   g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
281   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
282
283   (* GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->reorder) (cell_layout,
284                                                         cell,
285                                                         position);
286 }
287
288 /**
289  * gtk_cell_layout_get_cells:
290  * @cell_layout: a #GtkCellLayout
291  * 
292  * Returns the cell renderers which have been added to @cell_layout.
293  *
294  * Return value: a list of cell renderers. The list, but not the
295  *   renderers has been newly allocated and should be freed with
296  *   g_list_free() when no longer needed.
297  * 
298  * Since: 2.12
299  */
300 GList *
301 gtk_cell_layout_get_cells (GtkCellLayout *cell_layout)
302 {
303   GtkCellLayoutIface *iface;
304
305   g_return_val_if_fail (GTK_IS_CELL_LAYOUT (cell_layout), NULL);
306
307   iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);  
308   if (iface->get_cells)
309     return iface->get_cells (cell_layout);
310
311   return NULL;
312 }
313
314 typedef struct {
315   GtkCellLayout   *cell_layout;
316   GtkCellRenderer *renderer;
317   gchar           *attr_name;
318 } AttributesSubParserData;
319
320 static void
321 attributes_start_element (GMarkupParseContext *context,
322                           const gchar         *element_name,
323                           const gchar        **names,
324                           const gchar        **values,
325                           gpointer             user_data,
326                           GError             **error)
327 {
328   AttributesSubParserData *parser_data = (AttributesSubParserData*)user_data;
329   guint i;
330
331   if (strcmp (element_name, "attribute") == 0)
332     for (i = 0; names[i]; i++)
333       if (strcmp (names[i], "name") == 0)
334         parser_data->attr_name = g_strdup (values[i]);
335   else if (strcmp (element_name, "attributes") == 0)
336     return;
337   else
338     g_warning ("Unsupported tag for GtkCellLayout: %s\n", element_name);
339 }
340
341 static void
342 attributes_text_element (GMarkupParseContext *context,
343                          const gchar         *text,
344                          gsize                text_len,
345                          gpointer             user_data,
346                          GError             **error)
347 {
348   AttributesSubParserData *parser_data = (AttributesSubParserData*)user_data;
349
350   if (!parser_data->attr_name)
351     return;
352   gtk_cell_layout_add_attribute (parser_data->cell_layout,
353                                  parser_data->renderer,
354                                  parser_data->attr_name, atoi (text));
355   g_free (parser_data->attr_name);
356   parser_data->attr_name = NULL;
357 }
358
359 static const GMarkupParser attributes_parser =
360   {
361     attributes_start_element,
362     NULL,
363     attributes_text_element,
364   };
365
366 gboolean
367 _gtk_cell_layout_buildable_custom_tag_start (GtkBuildable  *buildable,
368                                              GtkBuilder    *builder,
369                                              GObject       *child,
370                                              const gchar   *tagname,
371                                              GMarkupParser *parser,
372                                              gpointer      *data)
373 {
374   AttributesSubParserData *parser_data;
375
376   if (!child)
377     return FALSE;
378
379   if (strcmp (tagname, "attributes") == 0)
380     {
381       parser_data = g_slice_new0 (AttributesSubParserData);
382       parser_data->cell_layout = GTK_CELL_LAYOUT (buildable);
383       parser_data->renderer = GTK_CELL_RENDERER (child);
384       parser_data->attr_name = NULL;
385
386       *parser = attributes_parser;
387       *data = parser_data;
388       return TRUE;
389     }
390
391   return FALSE;
392 }
393
394 void
395 _gtk_cell_layout_buildable_custom_tag_end (GtkBuildable *buildable,
396                                            GtkBuilder   *builder,
397                                            GObject      *child,
398                                            const gchar  *tagname,
399                                            gpointer     *data)
400 {
401   AttributesSubParserData *parser_data;
402
403   parser_data = (AttributesSubParserData*)data;
404   g_assert (!parser_data->attr_name);
405   g_slice_free (AttributesSubParserData, parser_data);
406 }
407
408 void
409 _gtk_cell_layout_buildable_add (GtkBuildable      *buildable,
410                                 GtkBuilder        *builder,
411                                 GObject           *child,
412                                 const gchar       *type)
413 {
414   GtkCellLayoutIface *iface;
415   
416   g_return_if_fail (GTK_IS_CELL_LAYOUT (buildable));
417   g_return_if_fail (GTK_IS_CELL_RENDERER (child));
418
419   iface = GTK_CELL_LAYOUT_GET_IFACE (buildable);
420   g_return_if_fail (iface->pack_end != NULL);
421   iface->pack_end (GTK_CELL_LAYOUT (buildable), GTK_CELL_RENDERER (child), FALSE);
422 }
423
424 #define __GTK_CELL_LAYOUT_C__
425 #include "gtkaliasdef.c"