2 * Copyright (C) 2003 Kristian Rietveld <kris@gtk.org>
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.
24 #include "gtkcelllayout.h"
25 #include "gtkbuilderprivate.h"
29 typedef GtkCellLayoutIface GtkCellLayoutInterface;
30 G_DEFINE_INTERFACE (GtkCellLayout, gtk_cell_layout, G_TYPE_OBJECT);
34 gtk_cell_layout_default_init (GtkCellLayoutInterface *iface)
39 * gtk_cell_layout_pack_start:
40 * @cell_layout: A #GtkCellLayout.
41 * @cell: A #GtkCellRenderer.
42 * @expand: %TRUE if @cell is to be given extra space allocated to @cell_layout.
44 * Packs the @cell into the beginning of @cell_layout. If @expand is %FALSE,
45 * then the @cell is allocated no more space than it needs. Any unused space
46 * is divided evenly between cells for which @expand is %TRUE.
48 * Note that reusing the same cell renderer is not supported.
53 gtk_cell_layout_pack_start (GtkCellLayout *cell_layout,
54 GtkCellRenderer *cell,
57 g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
58 g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
60 (* GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->pack_start) (cell_layout,
66 * gtk_cell_layout_pack_end:
67 * @cell_layout: A #GtkCellLayout.
68 * @cell: A #GtkCellRenderer.
69 * @expand: %TRUE if @cell is to be given extra space allocated to @cell_layout.
71 * Adds the @cell to the end of @cell_layout. If @expand is %FALSE, then the
72 * @cell is allocated no more space than it needs. Any unused space is
73 * divided evenly between cells for which @expand is %TRUE.
75 * Note that reusing the same cell renderer is not supported.
80 gtk_cell_layout_pack_end (GtkCellLayout *cell_layout,
81 GtkCellRenderer *cell,
84 g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
85 g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
87 (* GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->pack_end) (cell_layout,
93 * gtk_cell_layout_clear:
94 * @cell_layout: A #GtkCellLayout.
96 * Unsets all the mappings on all renderers on @cell_layout and
97 * removes all renderers from @cell_layout.
102 gtk_cell_layout_clear (GtkCellLayout *cell_layout)
104 g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
106 (* GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->clear) (cell_layout);
110 gtk_cell_layout_set_attributesv (GtkCellLayout *cell_layout,
111 GtkCellRenderer *cell,
116 GtkCellLayoutIface *iface;
118 attribute = va_arg (args, gchar *);
120 iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
122 (* iface->clear_attributes) (cell_layout, cell);
124 while (attribute != NULL)
126 column = va_arg (args, gint);
127 (* iface->add_attribute) (cell_layout, cell, attribute, column);
128 attribute = va_arg (args, gchar *);
133 * gtk_cell_layout_set_attributes:
134 * @cell_layout: A #GtkCellLayout.
135 * @cell: A #GtkCellRenderer.
136 * @Varargs: A %NULL-terminated list of attributes.
138 * Sets the attributes in list as the attributes of @cell_layout. The
139 * attributes should be in attribute/column order, as in
140 * gtk_cell_layout_add_attribute(). All existing attributes are removed, and
141 * replaced with the new attributes.
146 gtk_cell_layout_set_attributes (GtkCellLayout *cell_layout,
147 GtkCellRenderer *cell,
152 g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
153 g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
155 va_start (args, cell);
156 gtk_cell_layout_set_attributesv (cell_layout, cell, args);
161 * gtk_cell_layout_add_attribute:
162 * @cell_layout: A #GtkCellLayout.
163 * @cell: A #GtkCellRenderer.
164 * @attribute: An attribute on the renderer.
165 * @column: The column position on the model to get the attribute from.
167 * Adds an attribute mapping to the list in @cell_layout. The @column is the
168 * column of the model to get a value from, and the @attribute is the
169 * parameter on @cell to be set from the value. So for example if column 2
170 * of the model contains strings, you could have the "text" attribute of a
171 * #GtkCellRendererText get its values from column 2.
176 gtk_cell_layout_add_attribute (GtkCellLayout *cell_layout,
177 GtkCellRenderer *cell,
178 const gchar *attribute,
181 g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
182 g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
183 g_return_if_fail (attribute != NULL);
184 g_return_if_fail (column >= 0);
186 (* GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->add_attribute) (cell_layout,
193 * gtk_cell_layout_set_cell_data_func:
194 * @cell_layout: A #GtkCellLayout.
195 * @cell: A #GtkCellRenderer.
196 * @func: The #GtkCellLayoutDataFunc to use.
197 * @func_data: The user data for @func.
198 * @destroy: The destroy notification for @func_data.
200 * Sets the #GtkCellLayoutDataFunc to use for @cell_layout. This function
201 * is used instead of the standard attributes mapping for setting the
202 * column value, and should set the value of @cell_layout's cell renderer(s)
203 * as appropriate. @func may be %NULL to remove and older one.
208 gtk_cell_layout_set_cell_data_func (GtkCellLayout *cell_layout,
209 GtkCellRenderer *cell,
210 GtkCellLayoutDataFunc func,
212 GDestroyNotify destroy)
214 g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
215 g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
217 (* GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->set_cell_data_func) (cell_layout,
225 * gtk_cell_layout_clear_attributes:
226 * @cell_layout: A #GtkCellLayout.
227 * @cell: A #GtkCellRenderer to clear the attribute mapping on.
229 * Clears all existing attributes previously set with
230 * gtk_cell_layout_set_attributes().
235 gtk_cell_layout_clear_attributes (GtkCellLayout *cell_layout,
236 GtkCellRenderer *cell)
238 g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
239 g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
241 (* GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->clear_attributes) (cell_layout,
246 * gtk_cell_layout_reorder:
247 * @cell_layout: A #GtkCellLayout.
248 * @cell: A #GtkCellRenderer to reorder.
249 * @position: New position to insert @cell at.
251 * Re-inserts @cell at @position. Note that @cell has already to be packed
252 * into @cell_layout for this to function properly.
257 gtk_cell_layout_reorder (GtkCellLayout *cell_layout,
258 GtkCellRenderer *cell,
261 g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
262 g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
264 (* GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->reorder) (cell_layout,
270 * gtk_cell_layout_get_cells:
271 * @cell_layout: a #GtkCellLayout
273 * Returns the cell renderers which have been added to @cell_layout.
275 * Return value: (element-type GtkCellRenderer) (transfer container): a list of cell renderers. The list, but not the
276 * renderers has been newly allocated and should be freed with
277 * g_list_free() when no longer needed.
282 gtk_cell_layout_get_cells (GtkCellLayout *cell_layout)
284 GtkCellLayoutIface *iface;
286 g_return_val_if_fail (GTK_IS_CELL_LAYOUT (cell_layout), NULL);
288 iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
289 if (iface->get_cells)
290 return iface->get_cells (cell_layout);
296 * gtk_cell_layout_get_area:
297 * @cell_layout: a #GtkCellLayout
299 * Returns the underlying #GtkCellArea which might be @cell_layout if called on a #GtkCellArea or
300 * might be %NULL if no #GtkCellArea is used by @cell_layout.
302 * Return value: (transfer none): a list of cell renderers. The list, but not the
303 * renderers has been newly allocated and should be freed with
304 * g_list_free() when no longer needed.
309 gtk_cell_layout_get_area (GtkCellLayout *cell_layout)
311 GtkCellLayoutIface *iface;
313 g_return_val_if_fail (GTK_IS_CELL_LAYOUT (cell_layout), NULL);
315 iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
317 return iface->get_area (cell_layout);
322 /* Attribute parsing */
324 GtkCellLayout *cell_layout;
325 GtkCellRenderer *renderer;
327 } AttributesSubParserData;
330 attributes_start_element (GMarkupParseContext *context,
331 const gchar *element_name,
333 const gchar **values,
337 AttributesSubParserData *parser_data = (AttributesSubParserData*)user_data;
340 if (strcmp (element_name, "attribute") == 0)
342 for (i = 0; names[i]; i++)
343 if (strcmp (names[i], "name") == 0)
344 parser_data->attr_name = g_strdup (values[i]);
346 else if (strcmp (element_name, "attributes") == 0)
349 g_warning ("Unsupported tag for GtkCellLayout: %s\n", element_name);
353 attributes_text_element (GMarkupParseContext *context,
359 AttributesSubParserData *parser_data = (AttributesSubParserData*)user_data;
364 if (!parser_data->attr_name)
367 string = g_strndup (text, text_len);
369 l = g_ascii_strtoll (string, &endptr, 0);
370 if (errno || endptr == string)
374 GTK_BUILDER_ERROR_INVALID_VALUE,
375 "Could not parse integer `%s'",
382 gtk_cell_layout_add_attribute (parser_data->cell_layout,
383 parser_data->renderer,
384 parser_data->attr_name, l);
385 g_free (parser_data->attr_name);
386 parser_data->attr_name = NULL;
389 static const GMarkupParser attributes_parser =
391 attributes_start_element,
393 attributes_text_element,
397 /* Cell packing parsing */
399 gtk_cell_layout_buildable_set_cell_property (GtkCellArea *area,
401 GtkCellRenderer *cell,
406 GValue gvalue = { 0, };
407 GError *error = NULL;
409 pspec = gtk_cell_area_class_find_cell_property (GTK_CELL_AREA_GET_CLASS (area), name);
412 g_warning ("%s does not have a property called %s",
413 g_type_name (G_OBJECT_TYPE (area)), name);
417 if (!gtk_builder_value_from_string (builder, pspec, value, &gvalue, &error))
419 g_warning ("Could not read property %s:%s with value %s of type %s: %s",
420 g_type_name (G_OBJECT_TYPE (area)),
423 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
425 g_error_free (error);
429 gtk_cell_area_cell_set_property (area, cell, name, &gvalue);
430 g_value_unset (&gvalue);
435 GtkCellLayout *cell_layout;
436 GtkCellRenderer *renderer;
437 gchar *cell_prop_name;
439 gboolean translatable;
440 } CellPackingSubParserData;
443 cell_packing_start_element (GMarkupParseContext *context,
444 const gchar *element_name,
446 const gchar **values,
450 CellPackingSubParserData *parser_data = (CellPackingSubParserData*)user_data;
453 if (strcmp (element_name, "property") == 0)
455 for (i = 0; names[i]; i++)
456 if (strcmp (names[i], "name") == 0)
457 parser_data->cell_prop_name = g_strdup (values[i]);
458 else if (strcmp (names[i], "translatable") == 0)
460 if (!_gtk_builder_boolean_from_string (values[i],
461 &parser_data->translatable,
465 else if (strcmp (names[i], "comments") == 0)
466 ; /* for translators */
467 else if (strcmp (names[i], "context") == 0)
468 parser_data->context = g_strdup (values[i]);
470 g_warning ("Unsupported attribute for GtkCellLayout Cell "
471 "property: %s\n", names[i]);
473 else if (strcmp (element_name, "cell-packing") == 0)
476 g_warning ("Unsupported tag for GtkCellLayout: %s\n", element_name);
480 cell_packing_text_element (GMarkupParseContext *context,
486 CellPackingSubParserData *parser_data = (CellPackingSubParserData*)user_data;
490 if (!parser_data->cell_prop_name)
493 if (parser_data->translatable && text_len)
496 domain = gtk_builder_get_translation_domain (parser_data->builder);
498 value = _gtk_builder_parser_translate (domain,
499 parser_data->context,
504 value = g_strdup (text);
507 area = gtk_cell_layout_get_area (parser_data->cell_layout);
511 g_warning ("%s does not have an internal GtkCellArea class and cannot apply child cell properties",
512 g_type_name (G_OBJECT_TYPE (parser_data->cell_layout)));
516 gtk_cell_layout_buildable_set_cell_property (area,
517 parser_data->builder,
518 parser_data->renderer,
519 parser_data->cell_prop_name,
522 g_free (parser_data->cell_prop_name);
523 g_free (parser_data->context);
525 parser_data->cell_prop_name = NULL;
526 parser_data->context = NULL;
527 parser_data->translatable = FALSE;
530 static const GMarkupParser cell_packing_parser =
532 cell_packing_start_element,
534 cell_packing_text_element,
538 _gtk_cell_layout_buildable_custom_tag_start (GtkBuildable *buildable,
541 const gchar *tagname,
542 GMarkupParser *parser,
545 AttributesSubParserData *attr_data;
546 CellPackingSubParserData *packing_data;
551 if (strcmp (tagname, "attributes") == 0)
553 attr_data = g_slice_new0 (AttributesSubParserData);
554 attr_data->cell_layout = GTK_CELL_LAYOUT (buildable);
555 attr_data->renderer = GTK_CELL_RENDERER (child);
556 attr_data->attr_name = NULL;
558 *parser = attributes_parser;
562 else if (strcmp (tagname, "cell-packing") == 0)
564 packing_data = g_slice_new0 (CellPackingSubParserData);
565 packing_data->builder = builder;
566 packing_data->cell_layout = GTK_CELL_LAYOUT (buildable);
567 packing_data->renderer = GTK_CELL_RENDERER (child);
569 *parser = cell_packing_parser;
570 *data = packing_data;
578 _gtk_cell_layout_buildable_custom_tag_end (GtkBuildable *buildable,
581 const gchar *tagname,
584 AttributesSubParserData *attr_data;
586 if (strcmp (tagname, "attributes") == 0)
588 attr_data = (AttributesSubParserData*)data;
589 g_assert (!attr_data->attr_name);
590 g_slice_free (AttributesSubParserData, attr_data);
593 else if (strcmp (tagname, "cell-packing") == 0)
595 g_slice_free (CellPackingSubParserData, (gpointer)data);
601 _gtk_cell_layout_buildable_add_child (GtkBuildable *buildable,
606 GtkCellLayoutIface *iface;
608 g_return_if_fail (GTK_IS_CELL_LAYOUT (buildable));
609 g_return_if_fail (GTK_IS_CELL_RENDERER (child));
611 iface = GTK_CELL_LAYOUT_GET_IFACE (buildable);
612 g_return_if_fail (iface->pack_start != NULL);
613 iface->pack_start (GTK_CELL_LAYOUT (buildable), GTK_CELL_RENDERER (child), FALSE);