]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellview.c
just call gtk_cell_view_cell_layout_clear instead of trying to free the
[~andy/gtk] / gtk / gtkcellview.c
1 /* gtkellview.c
2  * Copyright (C) 2002, 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 "gtkcellview.h"
21 #include "gtkcelllayout.h"
22 #include "gtkintl.h"
23 #include "gtksignal.h"
24 #include "gtkcellrenderertext.h"
25 #include "gtkcellrendererpixbuf.h"
26 #include <gobject/gmarshal.h>
27
28 typedef struct _GtkCellViewCellInfo GtkCellViewCellInfo;
29 struct _GtkCellViewCellInfo
30 {
31   GtkCellRenderer *cell;
32
33   gint requested_width;
34   gint real_width;
35   guint expand : 1;
36   guint pack : 1;
37
38   GSList *attributes;
39
40   GtkCellLayoutDataFunc func;
41   gpointer func_data;
42   GDestroyNotify destroy;
43 };
44
45 struct _GtkCellViewPrivate
46 {
47   GtkTreeModel *model;
48   GtkTreeRowReference *displayed_row;
49   GList *cell_list;
50   gint spacing;
51
52   GdkColor background;
53   gboolean background_set;
54 };
55
56
57 static void        gtk_cell_view_class_init               (GtkCellViewClass *klass);
58 static void        gtk_cell_view_cell_layout_init         (GtkCellLayoutIface *iface);
59 static void        gtk_cell_view_get_property             (GObject           *object,
60                                                            guint             param_id,
61                                                            GValue           *value,
62                                                            GParamSpec       *pspec);
63 static void        gtk_cell_view_set_property             (GObject          *object,
64                                                            guint             param_id,
65                                                            const GValue     *value,
66                                                            GParamSpec       *pspec);
67 static void        gtk_cell_view_init                     (GtkCellView      *cellview);
68 static void        gtk_cell_view_finalize                 (GObject          *object);
69 static void        gtk_cell_view_style_set                (GtkWidget        *widget,
70                                                            GtkStyle         *previous_style);
71 static void        gtk_cell_view_size_request             (GtkWidget        *widget,
72                                                            GtkRequisition   *requisition);
73 static void        gtk_cell_view_size_allocate            (GtkWidget        *widget,
74                                                            GtkAllocation    *allocation);
75 static gboolean    gtk_cell_view_expose                   (GtkWidget        *widget,
76                                                            GdkEventExpose   *event);
77 static void        gtk_cell_view_set_valuesv              (GtkCellView      *cellview,
78                                                            GtkCellRenderer  *renderer,
79                                                            va_list           args);
80 static GtkCellViewCellInfo *gtk_cell_view_get_cell_info   (GtkCellView      *cellview,
81                                                            GtkCellRenderer  *renderer);
82 static void        gtk_cell_view_set_cell_data            (GtkCellView      *cellview);
83
84
85 static void        gtk_cell_view_cell_layout_pack_start        (GtkCellLayout         *layout,
86                                                                 GtkCellRenderer       *renderer,
87                                                                 gboolean               expand);
88 static void        gtk_cell_view_cell_layout_pack_end          (GtkCellLayout         *layout,
89                                                                 GtkCellRenderer       *renderer,
90                                                                 gboolean               expand);
91 static void        gtk_cell_view_cell_layout_add_attribute     (GtkCellLayout         *layout,
92                                                                 GtkCellRenderer       *renderer,
93                                                                 const gchar           *attribute,
94                                                                 gint                   column);
95 static void       gtk_cell_view_cell_layout_clear              (GtkCellLayout         *layout);
96 static void       gtk_cell_view_cell_layout_clear_attributes   (GtkCellLayout         *layout,
97                                                                 GtkCellRenderer       *renderer);
98 static void       gtk_cell_view_cell_layout_set_cell_data_func (GtkCellLayout         *layout,
99                                                                 GtkCellRenderer       *cell,
100                                                                 GtkCellLayoutDataFunc  func,
101                                                                 gpointer               func_data,
102                                                                 GDestroyNotify         destroy);
103
104
105 enum
106 {
107   PROP_0,
108   PROP_BACKGROUND,
109   PROP_BACKGROUND_GDK,
110   PROP_BACKGROUND_SET
111 };
112
113 static GtkObjectClass *parent_class = NULL;
114
115
116 GType
117 gtk_cell_view_get_type (void)
118 {
119   static GType cell_view_type = 0;
120
121   if (!cell_view_type)
122     {
123       static const GTypeInfo cell_view_info =
124         {
125           sizeof (GtkCellViewClass),
126           NULL, /* base_init */
127           NULL, /* base_finalize */
128           (GClassInitFunc) gtk_cell_view_class_init,
129           NULL, /* class_finalize */
130           NULL, /* class_data */
131           sizeof (GtkCellView),
132           0,
133           (GInstanceInitFunc) gtk_cell_view_init
134         };
135
136       static const GInterfaceInfo cell_layout_info =
137        {
138          (GInterfaceInitFunc) gtk_cell_view_cell_layout_init,
139          NULL,
140          NULL
141        };
142
143       cell_view_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkCellView",
144                                                &cell_view_info, 0);
145
146       g_type_add_interface_static (cell_view_type, GTK_TYPE_CELL_LAYOUT,
147                                    &cell_layout_info);
148     }
149
150   return cell_view_type;
151 }
152
153 static void
154 gtk_cell_view_class_init (GtkCellViewClass *klass)
155 {
156   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
157   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
158
159   parent_class = g_type_class_peek_parent (klass);
160
161   gobject_class->get_property = gtk_cell_view_get_property;
162   gobject_class->set_property = gtk_cell_view_set_property;
163   gobject_class->finalize = gtk_cell_view_finalize;
164
165   widget_class->expose_event = gtk_cell_view_expose;
166   widget_class->size_allocate = gtk_cell_view_size_allocate;
167   widget_class->size_request = gtk_cell_view_size_request;
168   widget_class->style_set = gtk_cell_view_style_set;
169
170   /* properties */
171   g_object_class_install_property (gobject_class,
172                                    PROP_BACKGROUND,
173                                    g_param_spec_string ("background",
174                                                         _("Background color name"),
175                                                         _("Background color as a string"),
176                                                         NULL,
177                                                         G_PARAM_WRITABLE));
178   g_object_class_install_property (gobject_class,
179                                    PROP_BACKGROUND_GDK,
180                                    g_param_spec_boxed ("background_gdk",
181                                                       _("Background color"),
182                                                       _("Background color as a GdkColor"),
183                                                       GDK_TYPE_COLOR,
184                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
185
186 #define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (gobject_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE))
187
188   ADD_SET_PROP ("background_set", PROP_BACKGROUND_SET,
189                 _("Background set"),
190                 _("Whether this tag affects the background color"));
191
192   g_type_class_add_private (gobject_class, sizeof (GtkCellViewPrivate));
193 }
194
195 static void
196 gtk_cell_view_cell_layout_init (GtkCellLayoutIface *iface)
197 {
198   iface->pack_start = gtk_cell_view_cell_layout_pack_start;
199   iface->pack_end = gtk_cell_view_cell_layout_pack_end;
200   iface->clear = gtk_cell_view_cell_layout_clear;
201   iface->add_attribute = gtk_cell_view_cell_layout_add_attribute;
202   iface->set_cell_data_func = gtk_cell_view_cell_layout_set_cell_data_func;
203   iface->clear_attributes = gtk_cell_view_cell_layout_clear_attributes;
204 }
205
206 static void
207 gtk_cell_view_get_property (GObject    *object,
208                             guint       param_id,
209                             GValue     *value,
210                             GParamSpec *pspec)
211 {
212   GtkCellView *view = GTK_CELL_VIEW (object);
213
214   switch (param_id)
215     {
216       case PROP_BACKGROUND_GDK:
217         {
218           GdkColor color;
219
220           color = view->priv->background;
221
222           g_value_set_boxed (value, &color);
223         }
224         break;
225       case PROP_BACKGROUND_SET:
226         g_value_set_boolean (value, view->priv->background_set);
227         break;
228       default:
229         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
230         break;
231     }
232 }
233
234 static void
235 gtk_cell_view_set_property (GObject      *object,
236                             guint         param_id,
237                             const GValue *value,
238                             GParamSpec   *pspec)
239 {
240   GtkCellView *view = GTK_CELL_VIEW (object);
241
242   switch (param_id)
243     {
244       case PROP_BACKGROUND:
245         {
246           GdkColor color;
247
248           if (!g_value_get_string (value))
249             gtk_cell_view_set_background_color (view, NULL);
250           else if (gdk_color_parse (g_value_get_string (value), &color))
251             gtk_cell_view_set_background_color (view, &color);
252           else
253             g_warning ("Don't know color `%s'", g_value_get_string (value));
254
255           g_object_notify (object, "background_gdk");
256         }
257         break;
258       case PROP_BACKGROUND_GDK:
259         gtk_cell_view_set_background_color (view, g_value_get_boxed (value));
260         break;
261       case PROP_BACKGROUND_SET:
262         view->priv->background_set = g_value_get_boolean (value);
263         break;
264       default:
265         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
266         break;
267     }
268 }
269
270 static void
271 gtk_cell_view_init (GtkCellView *cellview)
272 {
273   GTK_WIDGET_SET_FLAGS (cellview, GTK_NO_WINDOW);
274
275   cellview->priv = GTK_CELL_VIEW_GET_PRIVATE (cellview);
276 }
277
278 static void
279 gtk_cell_view_style_set (GtkWidget *widget,
280                          GtkStyle  *previous_style)
281 {
282   if (previous_style && GTK_WIDGET_REALIZED (widget))
283     gdk_window_set_background (widget->window,
284                                &widget->style->base[GTK_WIDGET_STATE (widget)]);
285 }
286
287 static void
288 gtk_cell_view_finalize (GObject *object)
289 {
290   GtkCellView *cellview = GTK_CELL_VIEW (object);
291
292   gtk_cell_view_cell_layout_clear (GTK_CELL_LAYOUT (object));
293
294   if (G_OBJECT_CLASS (parent_class)->finalize)
295     (* G_OBJECT_CLASS (parent_class)->finalize) (object);
296 }
297
298 static void
299 gtk_cell_view_size_request (GtkWidget      *widget,
300                             GtkRequisition *requisition)
301 {
302   GList *i;
303   gboolean first_cell = TRUE;
304   GtkCellView *cellview;
305
306   cellview = GTK_CELL_VIEW (widget);
307
308   requisition->width = 0;
309   requisition->height = 0;
310
311   if (cellview->priv->displayed_row)
312     gtk_cell_view_set_cell_data (cellview);
313
314   for (i = cellview->priv->cell_list; i; i = i->next)
315     {
316       gint width, height;
317       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
318
319       if (!info->cell->visible)
320         continue;
321
322       if (!first_cell)
323         requisition->width += cellview->priv->spacing;
324
325       gtk_cell_renderer_get_size (info->cell, widget, NULL, NULL, NULL,
326                                   &width, &height);
327
328       info->requested_width = width;
329       requisition->width += width;
330       requisition->height = MAX (requisition->height, height);
331
332       first_cell = FALSE;
333     }
334 }
335
336 static void
337 gtk_cell_view_size_allocate (GtkWidget     *widget,
338                              GtkAllocation *allocation)
339 {
340   GList *i;
341   gint expand_cell_count = 0;
342   gint full_requested_width = 0;
343   gint extra_space;
344   GtkCellView *cellview;
345
346   widget->allocation = *allocation;
347
348   cellview = GTK_CELL_VIEW (widget);
349
350   /* checking how much extra space we have */
351   for (i = cellview->priv->cell_list; i; i = i->next)
352     {
353       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
354
355       if (!info->cell->visible)
356         continue;
357
358       if (info->expand)
359         expand_cell_count++;
360
361       full_requested_width += info->requested_width;
362     }
363
364   extra_space = widget->allocation.width - full_requested_width;
365   if (extra_space < 0)
366     extra_space = 0;
367   else if (extra_space > 0 && expand_cell_count > 0)
368     extra_space /= expand_cell_count;
369
370   /* iterate list for PACK_START cells */
371   for (i = cellview->priv->cell_list; i; i = i->next)
372     {
373       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
374
375       if (info->pack == GTK_PACK_END)
376         continue;
377
378       if (!info->cell->visible)
379         continue;
380
381       info->real_width = info->requested_width + (info->expand?extra_space:0);
382     }
383
384   /* iterate list for PACK_END cells */
385   for (i = cellview->priv->cell_list; i; i = i->next)
386     {
387       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
388
389       if (info->pack == GTK_PACK_START)
390         continue;
391
392       if (!info->cell->visible)
393         continue;
394
395       info->real_width = info->requested_width + (info->expand?extra_space:0);
396     }
397 }
398
399 static gboolean
400 gtk_cell_view_expose (GtkWidget      *widget,
401                       GdkEventExpose *event)
402 {
403   GList *i;
404   GtkCellView *cellview;
405   GdkRectangle area;
406
407   cellview = GTK_CELL_VIEW (widget);
408
409   if (! GTK_WIDGET_DRAWABLE (widget))
410     return FALSE;
411
412   /* "blank" background */
413   if (cellview->priv->background_set)
414     {
415       GdkGC *gc;
416
417       gc = gdk_gc_new (GTK_WIDGET (cellview)->window);
418       gdk_gc_set_rgb_fg_color (gc, &cellview->priv->background);
419
420       gdk_draw_rectangle (GTK_WIDGET (cellview)->window,
421                           gc,
422                           TRUE,
423
424                           /*0, 0,*/
425                           widget->allocation.x,
426                           widget->allocation.y,
427
428                           widget->allocation.width,
429                           widget->allocation.height);
430
431       g_object_unref (G_OBJECT (gc));
432     }
433
434   /* set cell data (if applicable) */
435   if (cellview->priv->displayed_row)
436     gtk_cell_view_set_cell_data (cellview);
437
438   /* render cells */
439   area = widget->allocation;
440
441   /* we draw on our very own window, initialize x and y to zero */
442   area.x = widget->allocation.x;
443   area.y = widget->allocation.y;
444
445   /* PACK_START */
446   for (i = cellview->priv->cell_list; i; i = i->next)
447     {
448       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
449
450       if (info->pack == GTK_PACK_END)
451         continue;
452
453       if (!info->cell->visible)
454         continue;
455
456       area.width = info->real_width;
457
458       gtk_cell_renderer_render (info->cell,
459                                 event->window,
460                                 widget,
461                                 /* FIXME! */
462                                 &area, &area, &event->area, 0);
463
464       area.x += info->real_width;
465     }
466
467   /* PACK_END */
468   for (i = cellview->priv->cell_list; i; i = i->next)
469     {
470       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
471
472       if (info->pack == GTK_PACK_START)
473         continue;
474
475       if (!info->cell->visible)
476         continue;
477
478       area.width = info->real_width;
479
480       gtk_cell_renderer_render (info->cell,
481                                 widget->window,
482                                 widget,
483                                 /* FIXME ! */
484                                 &area, &area, &event->area, 0);
485       area.x += info->real_width;
486     }
487
488   return FALSE;
489 }
490
491 static GtkCellViewCellInfo *
492 gtk_cell_view_get_cell_info (GtkCellView     *cellview,
493                              GtkCellRenderer *renderer)
494 {
495   GList *i;
496
497   for (i = cellview->priv->cell_list; i; i = i->next)
498     {
499       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
500
501       if (info->cell == renderer)
502         return info;
503     }
504
505   return NULL;
506 }
507
508 static void
509 gtk_cell_view_set_cell_data (GtkCellView *cellview)
510 {
511   GList *i;
512   GtkTreeIter iter;
513   GtkTreePath *path;
514
515   g_return_if_fail (cellview->priv->displayed_row != NULL);
516
517   path = gtk_tree_row_reference_get_path (cellview->priv->displayed_row);
518   gtk_tree_model_get_iter (cellview->priv->model, &iter, path);
519   gtk_tree_path_free (path);
520
521   for (i = cellview->priv->cell_list; i; i = i->next)
522     {
523       GSList *j;
524       GtkCellViewCellInfo *info = i->data;
525
526       if (info->func)
527         {
528           (* info->func) (GTK_CELL_LAYOUT (cellview),
529                           info->cell,
530                           cellview->priv->model,
531                           &iter,
532                           info->func_data);
533           continue;
534         }
535
536       for (j = info->attributes; j && j->next; j = j->next->next)
537         {
538           gchar *property = j->data;
539           gint column = GPOINTER_TO_INT (j->next->data);
540           GValue value = {0, };
541
542           gtk_tree_model_get_value (cellview->priv->model, &iter,
543                                     column, &value);
544           g_object_set_property (G_OBJECT (info->cell),
545                                  property, &value);
546           g_value_unset (&value);
547         }
548     }
549 }
550
551 /* GtkCellLayout implementation */
552 static void
553 gtk_cell_view_cell_layout_pack_start (GtkCellLayout   *layout,
554                                       GtkCellRenderer *renderer,
555                                       gboolean         expand)
556 {
557   GtkCellViewCellInfo *info;
558   GtkCellView *cellview = GTK_CELL_VIEW (layout);
559
560   g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
561   g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
562   g_return_if_fail (!gtk_cell_view_get_cell_info (cellview, renderer));
563
564   g_object_ref (G_OBJECT (renderer));
565   gtk_object_sink (GTK_OBJECT (renderer));
566
567   info = g_new0 (GtkCellViewCellInfo, 1);
568   info->cell = renderer;
569   info->expand = expand ? TRUE : FALSE;
570   info->pack = GTK_PACK_START;
571
572   cellview->priv->cell_list = g_list_append (cellview->priv->cell_list, info);
573 }
574
575 static void
576 gtk_cell_view_cell_layout_pack_end (GtkCellLayout   *layout,
577                                     GtkCellRenderer *renderer,
578                                     gboolean         expand)
579 {
580   GtkCellViewCellInfo *info;
581   GtkCellView *cellview = GTK_CELL_VIEW (layout);
582
583   g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
584   g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
585   g_return_if_fail (!gtk_cell_view_get_cell_info (cellview, renderer));
586
587   g_object_ref (G_OBJECT (renderer));
588   gtk_object_sink (GTK_OBJECT (renderer));
589
590   info = g_new0 (GtkCellViewCellInfo, 1);
591   info->cell = renderer;
592   info->expand = expand ? TRUE : FALSE;
593   info->pack = GTK_PACK_END;
594
595   cellview->priv->cell_list = g_list_append (cellview->priv->cell_list, info);
596 }
597
598 static void
599 gtk_cell_view_cell_layout_add_attribute (GtkCellLayout   *layout,
600                                          GtkCellRenderer *renderer,
601                                          const gchar     *attribute,
602                                          gint             column)
603 {
604   GtkCellViewCellInfo *info;
605   GtkCellView *cellview = GTK_CELL_VIEW (layout);
606
607   g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
608   info = gtk_cell_view_get_cell_info (cellview, renderer);
609   g_return_if_fail (info != NULL);
610
611   info->attributes = g_slist_prepend (info->attributes,
612                                       GINT_TO_POINTER (column));
613   info->attributes = g_slist_prepend (info->attributes,
614                                       g_strdup (attribute));
615 }
616
617 static void
618 gtk_cell_view_cell_layout_clear (GtkCellLayout *layout)
619 {
620   GList *i;
621   GtkCellView *cellview = GTK_CELL_VIEW (layout);
622
623   g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
624
625   for (i = cellview->priv->cell_list; i; i = i->next)
626     {
627       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
628
629       gtk_cell_view_cell_layout_clear_attributes (layout, info->cell);
630       g_object_unref (G_OBJECT (info->cell));
631       g_free (info);
632     }
633
634   g_list_free (cellview->priv->cell_list);
635   cellview->priv->cell_list = NULL;
636 }
637
638 static void
639 gtk_cell_view_cell_layout_set_cell_data_func (GtkCellLayout         *layout,
640                                               GtkCellRenderer       *cell,
641                                               GtkCellLayoutDataFunc  func,
642                                               gpointer               func_data,
643                                               GDestroyNotify         destroy)
644 {
645   GtkCellView *cellview = GTK_CELL_VIEW (layout);
646   GtkCellViewCellInfo *info;
647
648   g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
649
650   info = gtk_cell_view_get_cell_info (cellview, cell);
651   g_return_if_fail (info != NULL);
652
653   if (info->destroy)
654     {
655       GDestroyNotify d = info->destroy;
656
657       info->destroy = NULL;
658       d (info->func_data);
659     }
660
661   info->func = func;
662   info->func_data = func_data;
663   info->destroy = destroy;
664 }
665
666 static void
667 gtk_cell_view_cell_layout_clear_attributes (GtkCellLayout   *layout,
668                                             GtkCellRenderer *renderer)
669 {
670   GtkCellViewCellInfo *info;
671   GtkCellView *cellview = GTK_CELL_VIEW (layout);
672   GSList *list;
673
674   g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
675   g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
676
677   info = gtk_cell_view_get_cell_info (cellview, renderer);
678   g_return_if_fail (info != NULL);
679
680   list = info->attributes;
681
682   while (list && list->next)
683     {
684       g_free (list->data);
685       list = list->next->next;
686     }
687   g_slist_free (list);
688
689   info->attributes = NULL;
690 }
691
692
693 /* public API */
694 GtkWidget *
695 gtk_cell_view_new (void)
696 {
697   GtkCellView *cellview;
698
699   cellview = GTK_CELL_VIEW (g_object_new (gtk_cell_view_get_type (), NULL));
700
701   return GTK_WIDGET (cellview);
702 }
703
704 GtkWidget *
705 gtk_cell_view_new_with_text (const gchar *text)
706 {
707   GtkCellView *cellview;
708   GtkCellRenderer *renderer;
709   GValue value = {0, };
710
711   cellview = GTK_CELL_VIEW (gtk_cell_view_new ());
712
713   renderer = gtk_cell_renderer_text_new ();
714   gtk_cell_view_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview),
715                                         renderer, TRUE);
716
717   g_value_init (&value, G_TYPE_STRING);
718   g_value_set_string (&value, text);
719   gtk_cell_view_set_values (cellview, renderer, "text", &value, NULL);
720   g_value_unset (&value);
721
722   return GTK_WIDGET (cellview);
723 }
724
725 GtkWidget *
726 gtk_cell_view_new_with_markup (const gchar *markup)
727 {
728   GtkCellView *cellview;
729   GtkCellRenderer *renderer;
730   GValue value = {0, };
731
732   cellview = GTK_CELL_VIEW (gtk_cell_view_new ());
733
734   renderer = gtk_cell_renderer_text_new ();
735   gtk_cell_view_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview),
736                                         renderer, TRUE);
737
738   g_value_init (&value, G_TYPE_STRING);
739   g_value_set_string (&value, markup);
740   gtk_cell_view_set_values (cellview, renderer, "markup", &value, NULL);
741   g_value_unset (&value);
742
743   return GTK_WIDGET (cellview);
744 }
745
746 GtkWidget *
747 gtk_cell_view_new_with_pixbuf (GdkPixbuf *pixbuf)
748 {
749   GtkCellView *cellview;
750   GtkCellRenderer *renderer;
751   GValue value = {0, };
752
753   cellview = GTK_CELL_VIEW (gtk_cell_view_new ());
754
755   renderer = gtk_cell_renderer_pixbuf_new ();
756   gtk_cell_view_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview),
757                                         renderer, TRUE);
758
759   g_value_init (&value, GDK_TYPE_PIXBUF);
760   g_value_set_object (&value, pixbuf);
761   gtk_cell_view_set_values (cellview, renderer, "pixbuf", &value, NULL);
762   g_value_unset (&value);
763
764   return GTK_WIDGET (cellview);
765 }
766
767 void
768 gtk_cell_view_set_value (GtkCellView     *cellview,
769                          GtkCellRenderer *renderer,
770                          gchar           *property,
771                          GValue          *value)
772 {
773   g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
774   g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
775
776   g_object_set_property (G_OBJECT (renderer), property, value);
777
778   /* force redraw */
779   gtk_widget_queue_draw (GTK_WIDGET (cellview));
780 }
781
782 static void
783 gtk_cell_view_set_valuesv (GtkCellView     *cellview,
784                            GtkCellRenderer *renderer,
785                            va_list          args)
786 {
787   gchar *attribute;
788   GValue *value;
789
790   attribute = va_arg (args, gchar *);
791
792   while (attribute)
793     {
794       value = va_arg (args, GValue *);
795       gtk_cell_view_set_value (cellview, renderer, attribute, value);
796       attribute = va_arg (args, gchar *);
797     }
798 }
799
800 void
801 gtk_cell_view_set_values (GtkCellView     *cellview,
802                           GtkCellRenderer *renderer,
803                           ...)
804 {
805   va_list args;
806
807   g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
808   g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
809   g_return_if_fail (gtk_cell_view_get_cell_info (cellview, renderer));
810
811   va_start (args, renderer);
812   gtk_cell_view_set_valuesv (cellview, renderer, args);
813   va_end (args);
814 }
815
816 void
817 gtk_cell_view_set_model (GtkCellView  *cellview,
818                          GtkTreeModel *model)
819 {
820   g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
821   g_return_if_fail (GTK_IS_TREE_MODEL (model));
822
823   if (cellview->priv->model)
824     {
825       if (cellview->priv->displayed_row)
826         gtk_tree_row_reference_free (cellview->priv->displayed_row);
827       cellview->priv->displayed_row = NULL;
828
829       g_object_unref (G_OBJECT (cellview->priv->model));
830       cellview->priv->model = NULL;
831     }
832
833   cellview->priv->model = model;
834
835   if (cellview->priv->model)
836     g_object_ref (G_OBJECT (cellview->priv->model));
837 }
838
839 void
840 gtk_cell_view_set_displayed_row (GtkCellView *cellview,
841                                  GtkTreePath *path)
842 {
843   g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
844   g_return_if_fail (GTK_IS_TREE_MODEL (cellview->priv->model));
845   g_return_if_fail (path != NULL);
846
847   if (cellview->priv->displayed_row)
848     gtk_tree_row_reference_free (cellview->priv->displayed_row);
849
850   cellview->priv->displayed_row =
851     gtk_tree_row_reference_new (cellview->priv->model, path);
852
853   /* force redraw */
854   gtk_widget_queue_draw (GTK_WIDGET (cellview));
855 }
856
857 GtkTreePath *
858 gtk_cell_view_get_displayed_row (GtkCellView *cellview)
859 {
860   g_return_val_if_fail (GTK_IS_CELL_VIEW (cellview), NULL);
861
862   if (!cellview->priv->displayed_row)
863     return NULL;
864
865   return gtk_tree_row_reference_get_path (cellview->priv->displayed_row);
866 }
867
868 void
869 gtk_cell_view_set_background_color (GtkCellView *view,
870                                     GdkColor    *color)
871 {
872   g_return_if_fail (GTK_IS_CELL_VIEW (view));
873
874   if (color)
875     {
876       if (!view->priv->background_set)
877         {
878           view->priv->background_set = TRUE;
879           g_object_notify (G_OBJECT (view), "background_set");
880         }
881
882       view->priv->background = *color;
883     }
884   else
885     {
886       if (view->priv->background_set)
887         {
888           view->priv->background_set = FALSE;
889           g_object_notify (G_OBJECT (view), "background_set");
890         }
891     }
892 }