3 * Copyright (C) 2010 Openismus GmbH
6 * Tristan Van Berkom <tristanvb@openismus.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
30 #include "gtkcelllayout.h"
31 #include "gtkcellarea.h"
32 #include "gtkcellareaiter.h"
34 #include <gobject/gvaluecollector.h>
38 static void gtk_cell_area_dispose (GObject *object);
39 static void gtk_cell_area_finalize (GObject *object);
41 /* GtkCellAreaClass */
42 static void gtk_cell_area_real_get_preferred_height_for_width (GtkCellArea *area,
43 GtkCellAreaIter *iter,
47 gint *natural_height);
48 static void gtk_cell_area_real_get_preferred_width_for_height (GtkCellArea *area,
49 GtkCellAreaIter *iter,
55 /* GtkCellLayoutIface */
56 static void gtk_cell_area_cell_layout_init (GtkCellLayoutIface *iface);
57 static void gtk_cell_area_pack_default (GtkCellLayout *cell_layout,
58 GtkCellRenderer *renderer,
60 static void gtk_cell_area_clear (GtkCellLayout *cell_layout);
61 static void gtk_cell_area_add_attribute (GtkCellLayout *cell_layout,
62 GtkCellRenderer *renderer,
63 const gchar *attribute,
65 static void gtk_cell_area_set_cell_data_func (GtkCellLayout *cell_layout,
66 GtkCellRenderer *cell,
67 GtkCellLayoutDataFunc func,
69 GDestroyNotify destroy);
70 static void gtk_cell_area_clear_attributes (GtkCellLayout *cell_layout,
71 GtkCellRenderer *renderer);
72 static void gtk_cell_area_reorder (GtkCellLayout *cell_layout,
73 GtkCellRenderer *cell,
75 static GList *gtk_cell_area_get_cells (GtkCellLayout *cell_layout);
77 /* Attribute/Cell metadata */
79 const gchar *attribute;
86 GtkCellLayoutDataFunc func;
88 GDestroyNotify destroy;
91 static CellInfo *cell_info_new (GtkCellLayoutDataFunc func,
93 GDestroyNotify destroy);
94 static void cell_info_free (CellInfo *info);
95 static CellAttribute *cell_attribute_new (GtkCellRenderer *renderer,
96 const gchar *attribute,
98 static void cell_attribute_free (CellAttribute *attribute);
99 static gint cell_attribute_find (CellAttribute *cell_attribute,
100 const gchar *attribute);
102 /* Struct to pass data along while looping over
103 * cell renderers to apply attributes
111 struct _GtkCellAreaPrivate
113 GHashTable *cell_info;
116 /* Keep the paramspec pool internal, no need to deliver notifications
117 * on cells. at least no percieved need for now */
118 static GParamSpecPool *cell_property_pool = NULL;
120 #define PARAM_SPEC_PARAM_ID(pspec) ((pspec)->param_id)
121 #define PARAM_SPEC_SET_PARAM_ID(pspec, id) ((pspec)->param_id = (id))
124 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GtkCellArea, gtk_cell_area, G_TYPE_INITIALLY_UNOWNED,
125 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
126 gtk_cell_area_cell_layout_init));
129 gtk_cell_area_init (GtkCellArea *area)
131 GtkCellAreaPrivate *priv;
133 area->priv = G_TYPE_INSTANCE_GET_PRIVATE (area,
138 priv->cell_info = g_hash_table_new_full (g_direct_hash,
141 (GDestroyNotify)cell_info_free);
145 gtk_cell_area_class_init (GtkCellAreaClass *class)
147 GObjectClass *object_class = G_OBJECT_CLASS (class);
150 object_class->dispose = gtk_cell_area_dispose;
151 object_class->finalize = gtk_cell_area_finalize;
155 class->remove = NULL;
156 class->forall = NULL;
158 class->render = NULL;
161 class->create_iter = NULL;
162 class->get_request_mode = NULL;
163 class->get_preferred_width = NULL;
164 class->get_preferred_height = NULL;
165 class->get_preferred_height_for_width = gtk_cell_area_real_get_preferred_height_for_width;
166 class->get_preferred_width_for_height = gtk_cell_area_real_get_preferred_width_for_height;
168 /* Cell properties */
169 if (!cell_property_pool)
170 cell_property_pool = g_param_spec_pool_new (FALSE);
172 g_type_class_add_private (object_class, sizeof (GtkCellAreaPrivate));
175 /*************************************************************
177 *************************************************************/
179 cell_info_new (GtkCellLayoutDataFunc func,
181 GDestroyNotify destroy)
183 CellInfo *info = g_slice_new (CellInfo);
185 info->attributes = NULL;
188 info->destroy = destroy;
194 cell_info_free (CellInfo *info)
197 info->destroy (info->data);
199 g_slist_foreach (info->attributes, (GFunc)cell_attribute_free, NULL);
200 g_slist_free (info->attributes);
202 g_slice_free (CellInfo, info);
205 static CellAttribute *
206 cell_attribute_new (GtkCellRenderer *renderer,
207 const gchar *attribute,
212 /* Check if the attribute really exists and point to
213 * the property string installed on the cell renderer
214 * class (dont dup the string)
216 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (renderer), attribute);
220 CellAttribute *cell_attribute = g_slice_new (CellAttribute);
222 cell_attribute->attribute = pspec->name;
223 cell_attribute->column = column;
225 return cell_attribute;
232 cell_attribute_free (CellAttribute *attribute)
234 g_slice_free (CellAttribute, attribute);
237 /* GCompareFunc for g_slist_find_custom() */
239 cell_attribute_find (CellAttribute *cell_attribute,
240 const gchar *attribute)
242 return g_strcmp0 (cell_attribute->attribute, attribute);
245 /*************************************************************
247 *************************************************************/
249 gtk_cell_area_finalize (GObject *object)
251 GtkCellArea *area = GTK_CELL_AREA (object);
252 GtkCellAreaPrivate *priv = area->priv;
254 /* All cell renderers should already be removed at this point,
255 * just kill our hash table here.
257 g_hash_table_destroy (priv->cell_info);
259 G_OBJECT_CLASS (gtk_cell_area_parent_class)->finalize (object);
264 gtk_cell_area_dispose (GObject *object)
266 /* This removes every cell renderer that may be added to the GtkCellArea,
267 * subclasses should be breaking references to the GtkCellRenderers
270 gtk_cell_layout_clear (GTK_CELL_LAYOUT (object));
272 G_OBJECT_CLASS (gtk_cell_area_parent_class)->dispose (object);
276 /*************************************************************
278 *************************************************************/
280 gtk_cell_area_real_get_preferred_height_for_width (GtkCellArea *area,
281 GtkCellAreaIter *iter,
284 gint *minimum_height,
285 gint *natural_height)
287 /* If the area doesnt do height-for-width, fallback on base preferred height */
288 GTK_CELL_AREA_GET_CLASS (area)->get_preferred_width (area, iter, widget, minimum_height, natural_height);
292 gtk_cell_area_real_get_preferred_width_for_height (GtkCellArea *area,
293 GtkCellAreaIter *iter,
299 /* If the area doesnt do width-for-height, fallback on base preferred width */
300 GTK_CELL_AREA_GET_CLASS (area)->get_preferred_width (area, iter, widget, minimum_width, natural_width);
303 /*************************************************************
304 * GtkCellLayoutIface *
305 *************************************************************/
307 gtk_cell_area_cell_layout_init (GtkCellLayoutIface *iface)
309 iface->pack_start = gtk_cell_area_pack_default;
310 iface->pack_end = gtk_cell_area_pack_default;
311 iface->clear = gtk_cell_area_clear;
312 iface->add_attribute = gtk_cell_area_add_attribute;
313 iface->set_cell_data_func = gtk_cell_area_set_cell_data_func;
314 iface->clear_attributes = gtk_cell_area_clear_attributes;
315 iface->reorder = gtk_cell_area_reorder;
316 iface->get_cells = gtk_cell_area_get_cells;
320 gtk_cell_area_pack_default (GtkCellLayout *cell_layout,
321 GtkCellRenderer *renderer,
324 gtk_cell_area_add (GTK_CELL_AREA (cell_layout), renderer);
328 gtk_cell_area_clear (GtkCellLayout *cell_layout)
330 GtkCellArea *area = GTK_CELL_AREA (cell_layout);
332 gtk_cell_layout_get_cells (cell_layout);
334 for (l = cells; l; l = l->next)
336 GtkCellRenderer *renderer = l->data;
337 gtk_cell_area_remove (area, renderer);
344 gtk_cell_area_add_attribute (GtkCellLayout *cell_layout,
345 GtkCellRenderer *renderer,
346 const gchar *attribute,
349 gtk_cell_area_attribute_connect (GTK_CELL_AREA (cell_layout),
350 renderer, attribute, column);
354 gtk_cell_area_set_cell_data_func (GtkCellLayout *cell_layout,
355 GtkCellRenderer *renderer,
356 GtkCellLayoutDataFunc func,
358 GDestroyNotify destroy)
360 GtkCellArea *area = GTK_CELL_AREA (cell_layout);
361 GtkCellAreaPrivate *priv = area->priv;
364 info = g_hash_table_lookup (priv->cell_info, renderer);
368 if (info->destroy && info->data)
369 info->destroy (info->data);
374 info->data = func_data;
375 info->destroy = destroy;
381 info->destroy = NULL;
386 info = cell_info_new (func, func_data, destroy);
388 g_hash_table_insert (priv->cell_info, renderer, info);
393 gtk_cell_area_clear_attributes (GtkCellLayout *cell_layout,
394 GtkCellRenderer *renderer)
396 GtkCellArea *area = GTK_CELL_AREA (cell_layout);
397 GtkCellAreaPrivate *priv = area->priv;
400 info = g_hash_table_lookup (priv->cell_info, renderer);
404 g_slist_foreach (info->attributes, (GFunc)cell_attribute_free, NULL);
405 g_slist_free (info->attributes);
407 info->attributes = NULL;
412 gtk_cell_area_reorder (GtkCellLayout *cell_layout,
413 GtkCellRenderer *cell,
416 g_warning ("GtkCellLayout::reorder not implemented for `%s'",
417 g_type_name (G_TYPE_FROM_INSTANCE (cell_layout)));
421 accum_cells (GtkCellRenderer *renderer,
424 *accum = g_list_prepend (*accum, renderer);
428 gtk_cell_area_get_cells (GtkCellLayout *cell_layout)
432 gtk_cell_area_forall (GTK_CELL_AREA (cell_layout),
433 (GtkCellCallback)accum_cells,
436 return g_list_reverse (cells);
440 /*************************************************************
442 *************************************************************/
444 gtk_cell_area_add (GtkCellArea *area,
445 GtkCellRenderer *renderer)
447 GtkCellAreaClass *class;
449 g_return_if_fail (GTK_IS_CELL_AREA (area));
450 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
452 class = GTK_CELL_AREA_GET_CLASS (area);
455 class->add (area, renderer);
457 g_warning ("GtkCellAreaClass::add not implemented for `%s'",
458 g_type_name (G_TYPE_FROM_INSTANCE (area)));
462 gtk_cell_area_remove (GtkCellArea *area,
463 GtkCellRenderer *renderer)
465 GtkCellAreaClass *class;
466 GtkCellAreaPrivate *priv;
468 g_return_if_fail (GTK_IS_CELL_AREA (area));
469 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
471 class = GTK_CELL_AREA_GET_CLASS (area);
474 /* Remove any custom attributes and custom cell data func here first */
475 g_hash_table_remove (priv->cell_info, renderer);
478 class->remove (area, renderer);
480 g_warning ("GtkCellAreaClass::remove not implemented for `%s'",
481 g_type_name (G_TYPE_FROM_INSTANCE (area)));
485 gtk_cell_area_forall (GtkCellArea *area,
486 GtkCellCallback callback,
487 gpointer callback_data)
489 GtkCellAreaClass *class;
491 g_return_if_fail (GTK_IS_CELL_AREA (area));
492 g_return_if_fail (callback != NULL);
494 class = GTK_CELL_AREA_GET_CLASS (area);
497 class->forall (area, callback, callback_data);
499 g_warning ("GtkCellAreaClass::forall not implemented for `%s'",
500 g_type_name (G_TYPE_FROM_INSTANCE (area)));
504 gtk_cell_area_event (GtkCellArea *area,
505 GtkCellAreaIter *iter,
508 const GdkRectangle *cell_area)
510 GtkCellAreaClass *class;
512 g_return_val_if_fail (GTK_IS_CELL_AREA (area), 0);
513 g_return_val_if_fail (GTK_IS_CELL_AREA_ITER (iter), 0);
514 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
515 g_return_val_if_fail (event != NULL, 0);
516 g_return_val_if_fail (cell_area != NULL, 0);
518 class = GTK_CELL_AREA_GET_CLASS (area);
521 return class->event (area, iter, widget, event, cell_area);
523 g_warning ("GtkCellAreaClass::event not implemented for `%s'",
524 g_type_name (G_TYPE_FROM_INSTANCE (area)));
529 gtk_cell_area_render (GtkCellArea *area,
530 GtkCellAreaIter *iter,
533 const GdkRectangle *cell_area)
535 GtkCellAreaClass *class;
537 g_return_if_fail (GTK_IS_CELL_AREA (area));
538 g_return_if_fail (GTK_IS_CELL_AREA_ITER (iter));
539 g_return_if_fail (GTK_IS_WIDGET (widget));
540 g_return_if_fail (cr != NULL);
541 g_return_if_fail (cell_area != NULL);
543 class = GTK_CELL_AREA_GET_CLASS (area);
546 class->render (area, iter, widget, cr, cell_area);
548 g_warning ("GtkCellAreaClass::render not implemented for `%s'",
549 g_type_name (G_TYPE_FROM_INSTANCE (area)));
554 gtk_cell_area_create_iter (GtkCellArea *area)
556 GtkCellAreaClass *class;
558 g_return_val_if_fail (GTK_IS_CELL_AREA (area), NULL);
560 class = GTK_CELL_AREA_GET_CLASS (area);
562 if (class->create_iter)
563 return class->create_iter (area);
565 g_warning ("GtkCellAreaClass::create_iter not implemented for `%s'",
566 g_type_name (G_TYPE_FROM_INSTANCE (area)));
573 gtk_cell_area_get_request_mode (GtkCellArea *area)
575 GtkCellAreaClass *class;
577 g_return_val_if_fail (GTK_IS_CELL_AREA (area),
578 GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH);
580 class = GTK_CELL_AREA_GET_CLASS (area);
582 if (class->get_request_mode)
583 return class->get_request_mode (area);
585 g_warning ("GtkCellAreaClass::get_request_mode not implemented for `%s'",
586 g_type_name (G_TYPE_FROM_INSTANCE (area)));
588 return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
592 gtk_cell_area_get_preferred_width (GtkCellArea *area,
593 GtkCellAreaIter *iter,
598 GtkCellAreaClass *class;
600 g_return_if_fail (GTK_IS_CELL_AREA (area));
601 g_return_if_fail (GTK_IS_WIDGET (widget));
603 class = GTK_CELL_AREA_GET_CLASS (area);
605 if (class->get_preferred_width)
606 class->get_preferred_width (area, iter, widget, minimum_size, natural_size);
608 g_warning ("GtkCellAreaClass::get_preferred_width not implemented for `%s'",
609 g_type_name (G_TYPE_FROM_INSTANCE (area)));
613 gtk_cell_area_get_preferred_height_for_width (GtkCellArea *area,
614 GtkCellAreaIter *iter,
617 gint *minimum_height,
618 gint *natural_height)
620 GtkCellAreaClass *class;
622 g_return_if_fail (GTK_IS_CELL_AREA (area));
623 g_return_if_fail (GTK_IS_WIDGET (widget));
625 class = GTK_CELL_AREA_GET_CLASS (area);
626 class->get_preferred_height_for_width (area, iter, widget, width, minimum_height, natural_height);
630 gtk_cell_area_get_preferred_height (GtkCellArea *area,
631 GtkCellAreaIter *iter,
636 GtkCellAreaClass *class;
638 g_return_if_fail (GTK_IS_CELL_AREA (area));
639 g_return_if_fail (GTK_IS_WIDGET (widget));
641 class = GTK_CELL_AREA_GET_CLASS (area);
643 if (class->get_preferred_height)
644 class->get_preferred_height (area, iter, widget, minimum_size, natural_size);
646 g_warning ("GtkCellAreaClass::get_preferred_height not implemented for `%s'",
647 g_type_name (G_TYPE_FROM_INSTANCE (area)));
651 gtk_cell_area_get_preferred_width_for_height (GtkCellArea *area,
652 GtkCellAreaIter *iter,
658 GtkCellAreaClass *class;
660 g_return_if_fail (GTK_IS_CELL_AREA (area));
661 g_return_if_fail (GTK_IS_WIDGET (widget));
663 class = GTK_CELL_AREA_GET_CLASS (area);
664 class->get_preferred_width_for_height (area, iter, widget, height, minimum_width, natural_width);
669 gtk_cell_area_attribute_connect (GtkCellArea *area,
670 GtkCellRenderer *renderer,
671 const gchar *attribute,
674 GtkCellAreaPrivate *priv;
676 CellAttribute *cell_attribute;
678 g_return_if_fail (GTK_IS_CELL_AREA (area));
679 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
680 g_return_if_fail (attribute != NULL);
683 info = g_hash_table_lookup (priv->cell_info, renderer);
687 info = cell_info_new (NULL, NULL, NULL);
689 g_hash_table_insert (priv->cell_info, renderer, info);
695 /* Check we are not adding the same attribute twice */
696 if ((node = g_slist_find_custom (info->attributes, attribute,
697 (GCompareFunc)cell_attribute_find)) != NULL)
699 cell_attribute = node->data;
701 g_warning ("Cannot connect attribute `%s' for cell renderer class `%s' "
702 "since `%s' is already attributed to column %d",
704 g_type_name (G_TYPE_FROM_INSTANCE (area)),
705 attribute, cell_attribute->column);
710 cell_attribute = cell_attribute_new (renderer, attribute, column);
714 g_warning ("Cannot connect attribute `%s' for cell renderer class `%s' "
715 "since attribute does not exist",
717 g_type_name (G_TYPE_FROM_INSTANCE (area)));
721 info->attributes = g_slist_prepend (info->attributes, cell_attribute);
725 gtk_cell_area_attribute_disconnect (GtkCellArea *area,
726 GtkCellRenderer *renderer,
727 const gchar *attribute)
729 GtkCellAreaPrivate *priv;
731 CellAttribute *cell_attribute;
734 g_return_if_fail (GTK_IS_CELL_AREA (area));
735 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
736 g_return_if_fail (attribute != NULL);
739 info = g_hash_table_lookup (priv->cell_info, renderer);
743 node = g_slist_find_custom (info->attributes, attribute,
744 (GCompareFunc)cell_attribute_find);
747 cell_attribute = node->data;
749 cell_attribute_free (cell_attribute);
751 info->attributes = g_slist_delete_link (info->attributes, node);
757 apply_cell_attributes (GtkCellRenderer *renderer,
761 CellAttribute *attribute;
763 GValue value = { 0, };
765 /* Apply the attributes directly to the renderer */
766 for (list = info->attributes; list; list = list->next)
768 attribute = list->data;
770 gtk_tree_model_get_value (data->model, data->iter, attribute->column, &value);
771 g_object_set_property (G_OBJECT (renderer), attribute->attribute, &value);
772 g_value_unset (&value);
775 /* Call any GtkCellLayoutDataFunc that may have been set by the user
778 info->func (GTK_CELL_LAYOUT (data->area), renderer,
779 data->model, data->iter, info->data);
783 gtk_cell_area_apply_attributes (GtkCellArea *area,
784 GtkTreeModel *tree_model,
787 GtkCellAreaPrivate *priv;
790 g_return_if_fail (GTK_IS_CELL_AREA (area));
791 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
792 g_return_if_fail (iter != NULL);
796 /* Go over any cells that have attributes or custom GtkCellLayoutDataFuncs and
797 * apply the data from the treemodel */
798 g_hash_table_foreach (priv->cell_info, (GHFunc)apply_cell_attributes, &data);
801 /* Cell Properties */
803 gtk_cell_area_class_install_cell_property (GtkCellAreaClass *aclass,
807 g_return_if_fail (GTK_IS_CELL_AREA_CLASS (aclass));
808 g_return_if_fail (G_IS_PARAM_SPEC (pspec));
809 if (pspec->flags & G_PARAM_WRITABLE)
810 g_return_if_fail (aclass->set_cell_property != NULL);
811 if (pspec->flags & G_PARAM_READABLE)
812 g_return_if_fail (aclass->get_cell_property != NULL);
813 g_return_if_fail (property_id > 0);
814 g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0); /* paranoid */
815 g_return_if_fail ((pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)) == 0);
817 if (g_param_spec_pool_lookup (cell_property_pool, pspec->name, G_OBJECT_CLASS_TYPE (aclass), TRUE))
819 g_warning (G_STRLOC ": class `%s' already contains a cell property named `%s'",
820 G_OBJECT_CLASS_NAME (aclass), pspec->name);
823 g_param_spec_ref (pspec);
824 g_param_spec_sink (pspec);
825 PARAM_SPEC_SET_PARAM_ID (pspec, property_id);
826 g_param_spec_pool_insert (cell_property_pool, pspec, G_OBJECT_CLASS_TYPE (aclass));
830 gtk_cell_area_class_find_cell_property (GtkCellAreaClass *aclass,
831 const gchar *property_name)
833 g_return_val_if_fail (GTK_IS_CELL_AREA_CLASS (aclass), NULL);
834 g_return_val_if_fail (property_name != NULL, NULL);
836 return g_param_spec_pool_lookup (cell_property_pool,
838 G_OBJECT_CLASS_TYPE (aclass),
843 gtk_cell_area_class_list_cell_properties (GtkCellAreaClass *aclass,
849 g_return_val_if_fail (GTK_IS_CELL_AREA_CLASS (aclass), NULL);
851 pspecs = g_param_spec_pool_list (cell_property_pool,
852 G_OBJECT_CLASS_TYPE (aclass),
861 gtk_cell_area_add_with_properties (GtkCellArea *area,
862 GtkCellRenderer *renderer,
863 const gchar *first_prop_name,
866 GtkCellAreaClass *class;
868 g_return_if_fail (GTK_IS_CELL_AREA (area));
869 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
871 class = GTK_CELL_AREA_GET_CLASS (area);
877 class->add (area, renderer);
879 va_start (var_args, first_prop_name);
880 gtk_cell_area_cell_set_valist (area, renderer, first_prop_name, var_args);
884 g_warning ("GtkCellAreaClass::add not implemented for `%s'",
885 g_type_name (G_TYPE_FROM_INSTANCE (area)));
889 gtk_cell_area_cell_set (GtkCellArea *area,
890 GtkCellRenderer *renderer,
891 const gchar *first_prop_name,
896 g_return_if_fail (GTK_IS_CELL_AREA (area));
897 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
899 va_start (var_args, first_prop_name);
900 gtk_cell_area_cell_set_valist (area, renderer, first_prop_name, var_args);
905 gtk_cell_area_cell_get (GtkCellArea *area,
906 GtkCellRenderer *renderer,
907 const gchar *first_prop_name,
912 g_return_if_fail (GTK_IS_CELL_AREA (area));
913 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
915 va_start (var_args, first_prop_name);
916 gtk_cell_area_cell_get_valist (area, renderer, first_prop_name, var_args);
921 area_get_cell_property (GtkCellArea *area,
922 GtkCellRenderer *renderer,
926 GtkCellAreaClass *class = g_type_class_peek (pspec->owner_type);
928 class->get_cell_property (area, renderer, PARAM_SPEC_PARAM_ID (pspec), value, pspec);
932 area_set_cell_property (GtkCellArea *area,
933 GtkCellRenderer *renderer,
937 GValue tmp_value = { 0, };
938 GtkCellAreaClass *class = g_type_class_peek (pspec->owner_type);
940 /* provide a copy to work from, convert (if necessary) and validate */
941 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
942 if (!g_value_transform (value, &tmp_value))
943 g_warning ("unable to set cell property `%s' of type `%s' from value of type `%s'",
945 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
946 G_VALUE_TYPE_NAME (value));
947 else if (g_param_value_validate (pspec, &tmp_value) && !(pspec->flags & G_PARAM_LAX_VALIDATION))
949 gchar *contents = g_strdup_value_contents (value);
951 g_warning ("value \"%s\" of type `%s' is invalid for property `%s' of type `%s'",
953 G_VALUE_TYPE_NAME (value),
955 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
960 class->set_cell_property (area, renderer, PARAM_SPEC_PARAM_ID (pspec), &tmp_value, pspec);
962 g_value_unset (&tmp_value);
966 gtk_cell_area_cell_set_valist (GtkCellArea *area,
967 GtkCellRenderer *renderer,
968 const gchar *first_property_name,
973 g_return_if_fail (GTK_IS_CELL_AREA (area));
974 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
976 name = first_property_name;
979 GValue value = { 0, };
982 g_param_spec_pool_lookup (cell_property_pool, name,
983 G_OBJECT_TYPE (area), TRUE);
986 g_warning ("%s: cell area class `%s' has no cell property named `%s'",
987 G_STRLOC, G_OBJECT_TYPE_NAME (area), name);
990 if (!(pspec->flags & G_PARAM_WRITABLE))
992 g_warning ("%s: cell property `%s' of cell area class `%s' is not writable",
993 G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (area));
997 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
998 G_VALUE_COLLECT (&value, var_args, 0, &error);
1001 g_warning ("%s: %s", G_STRLOC, error);
1004 /* we purposely leak the value here, it might not be
1005 * in a sane state if an error condition occoured
1009 area_set_cell_property (area, renderer, pspec, &value);
1010 g_value_unset (&value);
1011 name = va_arg (var_args, gchar*);
1016 gtk_cell_area_cell_get_valist (GtkCellArea *area,
1017 GtkCellRenderer *renderer,
1018 const gchar *first_property_name,
1023 g_return_if_fail (GTK_IS_CELL_AREA (area));
1024 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
1026 name = first_property_name;
1029 GValue value = { 0, };
1033 pspec = g_param_spec_pool_lookup (cell_property_pool, name,
1034 G_OBJECT_TYPE (area), TRUE);
1037 g_warning ("%s: cell area class `%s' has no cell property named `%s'",
1038 G_STRLOC, G_OBJECT_TYPE_NAME (area), name);
1041 if (!(pspec->flags & G_PARAM_READABLE))
1043 g_warning ("%s: cell property `%s' of cell area class `%s' is not readable",
1044 G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (area));
1048 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1049 area_get_cell_property (area, renderer, pspec, &value);
1050 G_VALUE_LCOPY (&value, var_args, 0, &error);
1053 g_warning ("%s: %s", G_STRLOC, error);
1055 g_value_unset (&value);
1058 g_value_unset (&value);
1059 name = va_arg (var_args, gchar*);
1064 gtk_cell_area_cell_set_property (GtkCellArea *area,
1065 GtkCellRenderer *renderer,
1066 const gchar *property_name,
1067 const GValue *value)
1071 g_return_if_fail (GTK_IS_CELL_AREA (area));
1072 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
1073 g_return_if_fail (property_name != NULL);
1074 g_return_if_fail (G_IS_VALUE (value));
1076 pspec = g_param_spec_pool_lookup (cell_property_pool, property_name,
1077 G_OBJECT_TYPE (area), TRUE);
1079 g_warning ("%s: cell area class `%s' has no cell property named `%s'",
1080 G_STRLOC, G_OBJECT_TYPE_NAME (area), property_name);
1081 else if (!(pspec->flags & G_PARAM_WRITABLE))
1082 g_warning ("%s: cell property `%s' of cell area class `%s' is not writable",
1083 G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (area));
1086 area_set_cell_property (area, renderer, pspec, value);
1091 gtk_cell_area_cell_get_property (GtkCellArea *area,
1092 GtkCellRenderer *renderer,
1093 const gchar *property_name,
1098 g_return_if_fail (GTK_IS_CELL_AREA (area));
1099 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
1100 g_return_if_fail (property_name != NULL);
1101 g_return_if_fail (G_IS_VALUE (value));
1103 pspec = g_param_spec_pool_lookup (cell_property_pool, property_name,
1104 G_OBJECT_TYPE (area), TRUE);
1106 g_warning ("%s: cell area class `%s' has no cell property named `%s'",
1107 G_STRLOC, G_OBJECT_TYPE_NAME (area), property_name);
1108 else if (!(pspec->flags & G_PARAM_READABLE))
1109 g_warning ("%s: cell property `%s' of cell area class `%s' is not readable",
1110 G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (area));
1113 GValue *prop_value, tmp_value = { 0, };
1115 /* auto-conversion of the callers value type
1117 if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec))
1119 g_value_reset (value);
1122 else if (!g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec), G_VALUE_TYPE (value)))
1124 g_warning ("can't retrieve cell property `%s' of type `%s' as value of type `%s'",
1126 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
1127 G_VALUE_TYPE_NAME (value));
1132 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1133 prop_value = &tmp_value;
1136 area_get_cell_property (area, renderer, pspec, prop_value);
1138 if (prop_value != value)
1140 g_value_transform (prop_value, value);
1141 g_value_unset (&tmp_value);