]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellview.c
Fix typos
[~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 <config.h>
21 #include "gtkcellview.h"
22 #include "gtkcelllayout.h"
23 #include "gtkintl.h"
24 #include "gtksignal.h"
25 #include "gtkcellrenderertext.h"
26 #include "gtkcellrendererpixbuf.h"
27 #include "gtkprivate.h"
28 #include <gobject/gmarshal.h>
29 #include "gtkalias.h"
30
31 typedef struct _GtkCellViewCellInfo GtkCellViewCellInfo;
32 struct _GtkCellViewCellInfo
33 {
34   GtkCellRenderer *cell;
35
36   gint requested_width;
37   gint real_width;
38   guint expand : 1;
39   guint pack : 1;
40
41   GSList *attributes;
42
43   GtkCellLayoutDataFunc func;
44   gpointer func_data;
45   GDestroyNotify destroy;
46 };
47
48 struct _GtkCellViewPrivate
49 {
50   GtkTreeModel *model;
51   GtkTreeRowReference *displayed_row;
52   GList *cell_list;
53   gint spacing;
54
55   GdkColor background;
56   gboolean background_set;
57 };
58
59
60 static void        gtk_cell_view_cell_layout_init         (GtkCellLayoutIface *iface);
61 static void        gtk_cell_view_get_property             (GObject           *object,
62                                                            guint             param_id,
63                                                            GValue           *value,
64                                                            GParamSpec       *pspec);
65 static void        gtk_cell_view_set_property             (GObject          *object,
66                                                            guint             param_id,
67                                                            const GValue     *value,
68                                                            GParamSpec       *pspec);
69 static void        gtk_cell_view_finalize                 (GObject          *object);
70 static void        gtk_cell_view_style_set                (GtkWidget        *widget,
71                                                            GtkStyle         *previous_style);
72 static void        gtk_cell_view_size_request             (GtkWidget        *widget,
73                                                            GtkRequisition   *requisition);
74 static void        gtk_cell_view_size_allocate            (GtkWidget        *widget,
75                                                            GtkAllocation    *allocation);
76 static gboolean    gtk_cell_view_expose                   (GtkWidget        *widget,
77                                                            GdkEventExpose   *event);
78 static void        gtk_cell_view_set_value                (GtkCellView     *cell_view,
79                                                            GtkCellRenderer *renderer,
80                                                            gchar           *property,
81                                                            GValue          *value);
82 static GtkCellViewCellInfo *gtk_cell_view_get_cell_info   (GtkCellView      *cellview,
83                                                            GtkCellRenderer  *renderer);
84 static void        gtk_cell_view_set_cell_data            (GtkCellView      *cell_view);
85
86
87 static void        gtk_cell_view_cell_layout_pack_start        (GtkCellLayout         *layout,
88                                                                 GtkCellRenderer       *renderer,
89                                                                 gboolean               expand);
90 static void        gtk_cell_view_cell_layout_pack_end          (GtkCellLayout         *layout,
91                                                                 GtkCellRenderer       *renderer,
92                                                                 gboolean               expand);
93 static void        gtk_cell_view_cell_layout_add_attribute     (GtkCellLayout         *layout,
94                                                                 GtkCellRenderer       *renderer,
95                                                                 const gchar           *attribute,
96                                                                 gint                   column);
97 static void       gtk_cell_view_cell_layout_clear              (GtkCellLayout         *layout);
98 static void       gtk_cell_view_cell_layout_clear_attributes   (GtkCellLayout         *layout,
99                                                                 GtkCellRenderer       *renderer);
100 static void       gtk_cell_view_cell_layout_set_cell_data_func (GtkCellLayout         *layout,
101                                                                 GtkCellRenderer       *cell,
102                                                                 GtkCellLayoutDataFunc  func,
103                                                                 gpointer               func_data,
104                                                                 GDestroyNotify         destroy);
105 static void       gtk_cell_view_cell_layout_reorder            (GtkCellLayout         *layout,
106                                                                 GtkCellRenderer       *cell,
107                                                                 gint                   position);
108
109
110 #define GTK_CELL_VIEW_GET_PRIVATE(obj)    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_CELL_VIEW, GtkCellViewPrivate))
111
112 enum
113 {
114   PROP_0,
115   PROP_BACKGROUND,
116   PROP_BACKGROUND_GDK,
117   PROP_BACKGROUND_SET,
118   PROP_MODEL
119 };
120
121 G_DEFINE_TYPE_WITH_CODE (GtkCellView, gtk_cell_view, GTK_TYPE_WIDGET, 
122                          G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
123                                                 gtk_cell_view_cell_layout_init))
124
125 static void
126 gtk_cell_view_class_init (GtkCellViewClass *klass)
127 {
128   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
129   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
130
131   gobject_class->get_property = gtk_cell_view_get_property;
132   gobject_class->set_property = gtk_cell_view_set_property;
133   gobject_class->finalize = gtk_cell_view_finalize;
134
135   widget_class->expose_event = gtk_cell_view_expose;
136   widget_class->size_allocate = gtk_cell_view_size_allocate;
137   widget_class->size_request = gtk_cell_view_size_request;
138   widget_class->style_set = gtk_cell_view_style_set;
139
140   /* properties */
141   g_object_class_install_property (gobject_class,
142                                    PROP_BACKGROUND,
143                                    g_param_spec_string ("background",
144                                                         P_("Background color name"),
145                                                         P_("Background color as a string"),
146                                                         NULL,
147                                                         GTK_PARAM_WRITABLE));
148   g_object_class_install_property (gobject_class,
149                                    PROP_BACKGROUND_GDK,
150                                    g_param_spec_boxed ("background-gdk",
151                                                       P_("Background color"),
152                                                       P_("Background color as a GdkColor"),
153                                                       GDK_TYPE_COLOR,
154                                                       GTK_PARAM_READWRITE));
155
156   /**
157    * GtkCellView:model
158    *
159    * The model for cell view
160    *
161    * since 2.10
162    */
163   g_object_class_install_property (gobject_class,
164                                    PROP_MODEL,
165                                    g_param_spec_object  ("model",
166                                                          P_("CellView model"),
167                                                          P_("The model for cell view"),
168                                                          GTK_TYPE_TREE_MODEL,
169                                                          GTK_PARAM_READWRITE));
170   
171 #define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (gobject_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, GTK_PARAM_READWRITE))
172
173   ADD_SET_PROP ("background-set", PROP_BACKGROUND_SET,
174                 P_("Background set"),
175                 P_("Whether this tag affects the background color"));
176
177   g_type_class_add_private (gobject_class, sizeof (GtkCellViewPrivate));
178 }
179
180 static void
181 gtk_cell_view_cell_layout_init (GtkCellLayoutIface *iface)
182 {
183   iface->pack_start = gtk_cell_view_cell_layout_pack_start;
184   iface->pack_end = gtk_cell_view_cell_layout_pack_end;
185   iface->clear = gtk_cell_view_cell_layout_clear;
186   iface->add_attribute = gtk_cell_view_cell_layout_add_attribute;
187   iface->set_cell_data_func = gtk_cell_view_cell_layout_set_cell_data_func;
188   iface->clear_attributes = gtk_cell_view_cell_layout_clear_attributes;
189   iface->reorder = gtk_cell_view_cell_layout_reorder;
190 }
191
192 static void
193 gtk_cell_view_get_property (GObject    *object,
194                             guint       param_id,
195                             GValue     *value,
196                             GParamSpec *pspec)
197 {
198   GtkCellView *view = GTK_CELL_VIEW (object);
199
200   switch (param_id)
201     {
202       case PROP_BACKGROUND_GDK:
203         {
204           GdkColor color;
205
206           color = view->priv->background;
207
208           g_value_set_boxed (value, &color);
209         }
210         break;
211       case PROP_BACKGROUND_SET:
212         g_value_set_boolean (value, view->priv->background_set);
213         break;
214       case PROP_MODEL:
215         g_value_set_object (value, view->priv->model);
216         break;
217       default:
218         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
219         break;
220     }
221 }
222
223 static void
224 gtk_cell_view_set_property (GObject      *object,
225                             guint         param_id,
226                             const GValue *value,
227                             GParamSpec   *pspec)
228 {
229   GtkCellView *view = GTK_CELL_VIEW (object);
230
231   switch (param_id)
232     {
233       case PROP_BACKGROUND:
234         {
235           GdkColor color;
236
237           if (!g_value_get_string (value))
238             gtk_cell_view_set_background_color (view, NULL);
239           else if (gdk_color_parse (g_value_get_string (value), &color))
240             gtk_cell_view_set_background_color (view, &color);
241           else
242             g_warning ("Don't know color `%s'", g_value_get_string (value));
243
244           g_object_notify (object, "background-gdk");
245         }
246         break;
247       case PROP_BACKGROUND_GDK:
248         gtk_cell_view_set_background_color (view, g_value_get_boxed (value));
249         break;
250       case PROP_BACKGROUND_SET:
251         view->priv->background_set = g_value_get_boolean (value);
252         break;
253       case PROP_MODEL:
254         gtk_cell_view_set_model (view, g_value_get_object (value));
255         break;
256     default:
257         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
258         break;
259     }
260 }
261
262 static void
263 gtk_cell_view_init (GtkCellView *cellview)
264 {
265   GTK_WIDGET_SET_FLAGS (cellview, GTK_NO_WINDOW);
266
267   cellview->priv = GTK_CELL_VIEW_GET_PRIVATE (cellview);
268 }
269
270 static void
271 gtk_cell_view_style_set (GtkWidget *widget,
272                          GtkStyle  *previous_style)
273 {
274   if (previous_style && GTK_WIDGET_REALIZED (widget))
275     gdk_window_set_background (widget->window,
276                                &widget->style->base[GTK_WIDGET_STATE (widget)]);
277 }
278
279 static void
280 gtk_cell_view_finalize (GObject *object)
281 {
282   GtkCellView *cellview = GTK_CELL_VIEW (object);
283
284   gtk_cell_view_cell_layout_clear (GTK_CELL_LAYOUT (cellview));
285
286   if (cellview->priv->model)
287      g_object_unref (cellview->priv->model);
288
289   if (cellview->priv->displayed_row)
290      gtk_tree_row_reference_free (cellview->priv->displayed_row);
291
292   (* G_OBJECT_CLASS (gtk_cell_view_parent_class)->finalize) (object);
293 }
294
295 static void
296 gtk_cell_view_size_request (GtkWidget      *widget,
297                             GtkRequisition *requisition)
298 {
299   GList *i;
300   gboolean first_cell = TRUE;
301   GtkCellView *cellview;
302
303   cellview = GTK_CELL_VIEW (widget);
304
305   requisition->width = 0;
306   requisition->height = 0;
307
308   if (cellview->priv->displayed_row)
309     gtk_cell_view_set_cell_data (cellview);
310
311   for (i = cellview->priv->cell_list; i; i = i->next)
312     {
313       gint width, height;
314       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
315
316       if (!info->cell->visible)
317         continue;
318
319       if (!first_cell)
320         requisition->width += cellview->priv->spacing;
321
322       gtk_cell_renderer_get_size (info->cell, widget, NULL, NULL, NULL,
323                                   &width, &height);
324
325       info->requested_width = width;
326       requisition->width += width;
327       requisition->height = MAX (requisition->height, height);
328
329       first_cell = FALSE;
330     }
331 }
332
333 static void
334 gtk_cell_view_size_allocate (GtkWidget     *widget,
335                              GtkAllocation *allocation)
336 {
337   GList *i;
338   gint expand_cell_count = 0;
339   gint full_requested_width = 0;
340   gint extra_space;
341   GtkCellView *cellview;
342
343   widget->allocation = *allocation;
344
345   cellview = GTK_CELL_VIEW (widget);
346
347   /* checking how much extra space we have */
348   for (i = cellview->priv->cell_list; i; i = i->next)
349     {
350       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
351
352       if (!info->cell->visible)
353         continue;
354
355       if (info->expand)
356         expand_cell_count++;
357
358       full_requested_width += info->requested_width;
359     }
360
361   extra_space = widget->allocation.width - full_requested_width;
362   if (extra_space < 0)
363     extra_space = 0;
364   else if (extra_space > 0 && expand_cell_count > 0)
365     extra_space /= expand_cell_count;
366
367   /* iterate list for PACK_START cells */
368   for (i = cellview->priv->cell_list; i; i = i->next)
369     {
370       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
371
372       if (info->pack == GTK_PACK_END)
373         continue;
374
375       if (!info->cell->visible)
376         continue;
377
378       info->real_width = info->requested_width + (info->expand?extra_space:0);
379     }
380
381   /* iterate list for PACK_END cells */
382   for (i = cellview->priv->cell_list; i; i = i->next)
383     {
384       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
385
386       if (info->pack == GTK_PACK_START)
387         continue;
388
389       if (!info->cell->visible)
390         continue;
391
392       info->real_width = info->requested_width + (info->expand?extra_space:0);
393     }
394 }
395
396 static gboolean
397 gtk_cell_view_expose (GtkWidget      *widget,
398                       GdkEventExpose *event)
399 {
400   GList *i;
401   GtkCellView *cellview;
402   GdkRectangle area;
403   GtkCellRendererState state;
404   gboolean rtl = (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL);
405
406   cellview = GTK_CELL_VIEW (widget);
407
408   if (! GTK_WIDGET_DRAWABLE (widget))
409     return FALSE;
410
411   /* "blank" background */
412   if (cellview->priv->background_set)
413     {
414       cairo_t *cr = gdk_cairo_create (GTK_WIDGET (cellview)->window);
415
416       gdk_cairo_rectangle (cr, &widget->allocation);
417       cairo_set_source_rgb (cr,
418                             cellview->priv->background.red / 65535.,
419                             cellview->priv->background.green / 65535.,
420                             cellview->priv->background.blue / 65535.);
421       cairo_fill (cr);
422
423       cairo_destroy (cr);
424     }
425
426   /* set cell data (if available) */
427   if (cellview->priv->displayed_row)
428     gtk_cell_view_set_cell_data (cellview);
429   else if (cellview->priv->model)
430     return FALSE;
431
432   /* render cells */
433   area = widget->allocation;
434
435   /* we draw on our very own window, initialize x and y to zero */
436   area.x = widget->allocation.x + (rtl ? widget->allocation.width : 0); 
437   area.y = widget->allocation.y;
438
439   if (GTK_WIDGET_STATE (widget) == GTK_STATE_PRELIGHT)
440     state = GTK_CELL_RENDERER_PRELIT;
441   else
442     state = 0;
443       
444   /* PACK_START */
445   for (i = cellview->priv->cell_list; i; i = i->next)
446     {
447       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
448
449       if (info->pack == GTK_PACK_END)
450         continue;
451
452       if (!info->cell->visible)
453         continue;
454
455       area.width = info->real_width;
456       if (rtl)                                             
457          area.x -= area.width;
458
459       gtk_cell_renderer_render (info->cell,
460                                 event->window,
461                                 widget,
462                                 /* FIXME! */
463                                 &area, &area, &event->area, state);
464
465       if (!rtl)                                           
466          area.x += info->real_width;
467     }
468
469    area.x = rtl ? widget->allocation.x : (widget->allocation.x + widget->allocation.width);  
470
471   /* PACK_END */
472   for (i = cellview->priv->cell_list; i; i = i->next)
473     {
474       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
475
476       if (info->pack == GTK_PACK_START)
477         continue;
478
479       if (!info->cell->visible)
480         continue;
481
482       area.width = info->real_width;
483       if (!rtl)
484          area.x -= area.width;   
485
486       gtk_cell_renderer_render (info->cell,
487                                 widget->window,
488                                 widget,
489                                 /* FIXME ! */
490                                 &area, &area, &event->area, state);
491       if (rtl)
492          area.x += info->real_width;
493     }
494
495   return FALSE;
496 }
497
498 static GtkCellViewCellInfo *
499 gtk_cell_view_get_cell_info (GtkCellView     *cellview,
500                              GtkCellRenderer *renderer)
501 {
502   GList *i;
503
504   for (i = cellview->priv->cell_list; i; i = i->next)
505     {
506       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
507
508       if (info->cell == renderer)
509         return info;
510     }
511
512   return NULL;
513 }
514
515 static void
516 gtk_cell_view_set_cell_data (GtkCellView *cell_view)
517 {
518   GList *i;
519   GtkTreeIter iter;
520   GtkTreePath *path;
521
522   g_return_if_fail (cell_view->priv->displayed_row != NULL);
523
524   path = gtk_tree_row_reference_get_path (cell_view->priv->displayed_row);
525   if (!path)
526     return;
527
528   gtk_tree_model_get_iter (cell_view->priv->model, &iter, path);
529   gtk_tree_path_free (path);
530
531   for (i = cell_view->priv->cell_list; i; i = i->next)
532     {
533       GSList *j;
534       GtkCellViewCellInfo *info = i->data;
535
536       g_object_freeze_notify (G_OBJECT (info->cell));
537
538       for (j = info->attributes; j && j->next; j = j->next->next)
539         {
540           gchar *property = j->data;
541           gint column = GPOINTER_TO_INT (j->next->data);
542           GValue value = {0, };
543
544           gtk_tree_model_get_value (cell_view->priv->model, &iter,
545                                     column, &value);
546           g_object_set_property (G_OBJECT (info->cell),
547                                  property, &value);
548           g_value_unset (&value);
549         }
550
551       if (info->func)
552         (* info->func) (GTK_CELL_LAYOUT (cell_view),
553                         info->cell,
554                         cell_view->priv->model,
555                         &iter,
556                         info->func_data);
557
558       g_object_thaw_notify (G_OBJECT (info->cell));
559     }
560 }
561
562 /* GtkCellLayout implementation */
563 static void
564 gtk_cell_view_cell_layout_pack_start (GtkCellLayout   *layout,
565                                       GtkCellRenderer *renderer,
566                                       gboolean         expand)
567 {
568   GtkCellViewCellInfo *info;
569   GtkCellView *cellview = GTK_CELL_VIEW (layout);
570
571   g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
572   g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
573   g_return_if_fail (!gtk_cell_view_get_cell_info (cellview, renderer));
574
575   g_object_ref_sink (renderer);
576
577   info = g_new0 (GtkCellViewCellInfo, 1);
578   info->cell = renderer;
579   info->expand = expand ? TRUE : FALSE;
580   info->pack = GTK_PACK_START;
581
582   cellview->priv->cell_list = g_list_append (cellview->priv->cell_list, info);
583 }
584
585 static void
586 gtk_cell_view_cell_layout_pack_end (GtkCellLayout   *layout,
587                                     GtkCellRenderer *renderer,
588                                     gboolean         expand)
589 {
590   GtkCellViewCellInfo *info;
591   GtkCellView *cellview = GTK_CELL_VIEW (layout);
592
593   g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
594   g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
595   g_return_if_fail (!gtk_cell_view_get_cell_info (cellview, renderer));
596
597   g_object_ref_sink (renderer);
598
599   info = g_new0 (GtkCellViewCellInfo, 1);
600   info->cell = renderer;
601   info->expand = expand ? TRUE : FALSE;
602   info->pack = GTK_PACK_END;
603
604   cellview->priv->cell_list = g_list_append (cellview->priv->cell_list, info);
605 }
606
607 static void
608 gtk_cell_view_cell_layout_add_attribute (GtkCellLayout   *layout,
609                                          GtkCellRenderer *renderer,
610                                          const gchar     *attribute,
611                                          gint             column)
612 {
613   GtkCellViewCellInfo *info;
614   GtkCellView *cellview = GTK_CELL_VIEW (layout);
615
616   g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
617   info = gtk_cell_view_get_cell_info (cellview, renderer);
618   g_return_if_fail (info != NULL);
619
620   info->attributes = g_slist_prepend (info->attributes,
621                                       GINT_TO_POINTER (column));
622   info->attributes = g_slist_prepend (info->attributes,
623                                       g_strdup (attribute));
624 }
625
626 static void
627 gtk_cell_view_cell_layout_clear (GtkCellLayout *layout)
628 {
629   GtkCellView *cellview = GTK_CELL_VIEW (layout);
630
631   g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
632
633   while (cellview->priv->cell_list)
634     {
635       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)cellview->priv->cell_list->data;
636
637       gtk_cell_view_cell_layout_clear_attributes (layout, info->cell);
638       g_object_unref (info->cell);
639       g_free (info);
640       cellview->priv->cell_list = g_list_delete_link (cellview->priv->cell_list, 
641                                                       cellview->priv->cell_list);
642     }
643 }
644
645 static void
646 gtk_cell_view_cell_layout_set_cell_data_func (GtkCellLayout         *layout,
647                                               GtkCellRenderer       *cell,
648                                               GtkCellLayoutDataFunc  func,
649                                               gpointer               func_data,
650                                               GDestroyNotify         destroy)
651 {
652   GtkCellView *cellview = GTK_CELL_VIEW (layout);
653   GtkCellViewCellInfo *info;
654
655   g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
656
657   info = gtk_cell_view_get_cell_info (cellview, cell);
658   g_return_if_fail (info != NULL);
659
660   if (info->destroy)
661     {
662       GDestroyNotify d = info->destroy;
663
664       info->destroy = NULL;
665       d (info->func_data);
666     }
667
668   info->func = func;
669   info->func_data = func_data;
670   info->destroy = destroy;
671 }
672
673 static void
674 gtk_cell_view_cell_layout_clear_attributes (GtkCellLayout   *layout,
675                                             GtkCellRenderer *renderer)
676 {
677   GtkCellViewCellInfo *info;
678   GtkCellView *cellview = GTK_CELL_VIEW (layout);
679   GSList *list;
680
681   g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
682   g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
683
684   info = gtk_cell_view_get_cell_info (cellview, renderer);
685   if (info != NULL)
686     {
687       list = info->attributes;
688       while (list && list->next)
689         {
690           g_free (list->data);
691           list = list->next->next;
692         }
693       
694       g_slist_free (info->attributes);
695       info->attributes = NULL;
696     }
697 }
698
699 static void
700 gtk_cell_view_cell_layout_reorder (GtkCellLayout   *layout,
701                                    GtkCellRenderer *cell,
702                                    gint             position)
703 {
704   GList *link;
705   GtkCellViewCellInfo *info;
706   GtkCellView *cellview = GTK_CELL_VIEW (layout);
707
708   g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
709   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
710
711   info = gtk_cell_view_get_cell_info (cellview, cell);
712
713   g_return_if_fail (info != NULL);
714   g_return_if_fail (position >= 0);
715
716   link = g_list_find (cellview->priv->cell_list, info);
717
718   g_return_if_fail (link != NULL);
719
720   cellview->priv->cell_list = g_list_remove_link (cellview->priv->cell_list,
721                                                   link);
722   cellview->priv->cell_list = g_list_insert (cellview->priv->cell_list,
723                                              info, position);
724
725   gtk_widget_queue_draw (GTK_WIDGET (cellview));
726 }
727
728 /**
729  * gtk_cell_view_new:
730  *
731  * Creates a new #GtkCellView widget.
732  *
733  * Return value: A newly created #GtkCellView widget.
734  *
735  * Since: 2.6
736  */
737 GtkWidget *
738 gtk_cell_view_new (void)
739 {
740   GtkCellView *cellview;
741
742   cellview = g_object_new (gtk_cell_view_get_type (), NULL);
743
744   return GTK_WIDGET (cellview);
745 }
746
747 /**
748  * gtk_cell_view_new_with_text:
749  * @text: the text to display in the cell view
750  *
751  * Creates a new #GtkCellView widget, adds a #GtkCellRendererText 
752  * to it, and makes its show @text.
753  *
754  * Return value: A newly created #GtkCellView widget.
755  *
756  * Since: 2.6
757  */
758 GtkWidget *
759 gtk_cell_view_new_with_text (const gchar *text)
760 {
761   GtkCellView *cellview;
762   GtkCellRenderer *renderer;
763   GValue value = {0, };
764
765   cellview = GTK_CELL_VIEW (gtk_cell_view_new ());
766
767   renderer = gtk_cell_renderer_text_new ();
768   gtk_cell_view_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview),
769                                         renderer, TRUE);
770
771   g_value_init (&value, G_TYPE_STRING);
772   g_value_set_string (&value, text);
773   gtk_cell_view_set_value (cellview, renderer, "text", &value);
774   g_value_unset (&value);
775
776   return GTK_WIDGET (cellview);
777 }
778
779 /**
780  * gtk_cell_view_new_with_markup:
781  * @markup: the text to display in the cell view
782  *
783  * Creates a new #GtkCellView widget, adds a #GtkCellRendererText 
784  * to it, and makes its show @markup. The text can text can be
785  * marked up with the <link linkend="PangoMarkupFormat">Pango text 
786  * markup language</link>.
787  *
788  * Return value: A newly created #GtkCellView widget.
789  *
790  * Since: 2.6
791  */
792 GtkWidget *
793 gtk_cell_view_new_with_markup (const gchar *markup)
794 {
795   GtkCellView *cellview;
796   GtkCellRenderer *renderer;
797   GValue value = {0, };
798
799   cellview = GTK_CELL_VIEW (gtk_cell_view_new ());
800
801   renderer = gtk_cell_renderer_text_new ();
802   gtk_cell_view_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview),
803                                         renderer, TRUE);
804
805   g_value_init (&value, G_TYPE_STRING);
806   g_value_set_string (&value, markup);
807   gtk_cell_view_set_value (cellview, renderer, "markup", &value);
808   g_value_unset (&value);
809
810   return GTK_WIDGET (cellview);
811 }
812
813 /**
814  * gtk_cell_view_new_with_pixbuf:
815  * @pixbuf: the image to display in the cell view
816  *
817  * Creates a new #GtkCellView widget, adds a #GtkCellRendererPixbuf 
818  * to it, and makes its show @pixbuf. 
819  *
820  * Return value: A newly created #GtkCellView widget.
821  *
822  * Since: 2.6
823  */
824 GtkWidget *
825 gtk_cell_view_new_with_pixbuf (GdkPixbuf *pixbuf)
826 {
827   GtkCellView *cellview;
828   GtkCellRenderer *renderer;
829   GValue value = {0, };
830
831   cellview = GTK_CELL_VIEW (gtk_cell_view_new ());
832
833   renderer = gtk_cell_renderer_pixbuf_new ();
834   gtk_cell_view_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview),
835                                         renderer, TRUE);
836
837   g_value_init (&value, GDK_TYPE_PIXBUF);
838   g_value_set_object (&value, pixbuf);
839   gtk_cell_view_set_value (cellview, renderer, "pixbuf", &value);
840   g_value_unset (&value);
841
842   return GTK_WIDGET (cellview);
843 }
844
845 /**
846  * gtk_cell_view_set_value:
847  * @cell_view: a #GtkCellView widget
848  * @renderer: one of the renderers of @cell_view
849  * @property: the name of the property of @renderer to set
850  * @value: the new value to set the property to
851  * 
852  * Sets a property of a cell renderer of @cell_view, and
853  * makes sure the display of @cell_view is updated.
854  *
855  * Since: 2.6
856  */
857 static void
858 gtk_cell_view_set_value (GtkCellView     *cell_view,
859                          GtkCellRenderer *renderer,
860                          gchar           *property,
861                          GValue          *value)
862 {
863   g_return_if_fail (GTK_IS_CELL_VIEW (cell_view));
864   g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
865
866   g_object_set_property (G_OBJECT (renderer), property, value);
867
868   /* force resize and redraw */
869   gtk_widget_queue_resize (GTK_WIDGET (cell_view));
870   gtk_widget_queue_draw (GTK_WIDGET (cell_view));
871 }
872
873 /**
874  * gtk_cell_view_set_model:
875  * @cell_view: a #GtkCellView
876  * @model: a #GtkTreeModel
877  *
878  * Sets the model for @cell_view.  If @cell_view already has a model
879  * set, it will remove it before setting the new model.  If @model is 
880  * %NULL, then it will unset the old model.
881  *
882  * Since: 2.6
883  */
884 void
885 gtk_cell_view_set_model (GtkCellView  *cell_view,
886                          GtkTreeModel *model)
887 {
888   g_return_if_fail (GTK_IS_CELL_VIEW (cell_view));
889   g_return_if_fail (GTK_IS_TREE_MODEL (model));
890
891   if (cell_view->priv->model)
892     {
893       if (cell_view->priv->displayed_row)
894         gtk_tree_row_reference_free (cell_view->priv->displayed_row);
895       cell_view->priv->displayed_row = NULL;
896
897       g_object_unref (cell_view->priv->model);
898       cell_view->priv->model = NULL;
899     }
900
901   cell_view->priv->model = model;
902
903   if (cell_view->priv->model)
904     g_object_ref (cell_view->priv->model);
905 }
906
907 /**
908  * gtk_cell_view_set_displayed_row:
909  * @cell_view: a #GtkCellView
910  * @path: a #GtkTreePath or %NULL to unset.
911  * 
912  * Sets the row of the model that is currently displayed
913  * by the #GtkCellView. If the path is unset, then the
914  * contents of the cellview "stick" at their last value;
915  * this is not normally a desired result, but may be
916  * a needed intermediate state if say, the model for
917  * the #GtkCellView becomes temporarily empty.
918  *
919  * Since: 2.6
920  **/
921 void
922 gtk_cell_view_set_displayed_row (GtkCellView *cell_view,
923                                  GtkTreePath *path)
924 {
925   g_return_if_fail (GTK_IS_CELL_VIEW (cell_view));
926   g_return_if_fail (GTK_IS_TREE_MODEL (cell_view->priv->model));
927
928   if (cell_view->priv->displayed_row)
929     gtk_tree_row_reference_free (cell_view->priv->displayed_row);
930
931   if (path)
932     {
933       cell_view->priv->displayed_row =
934         gtk_tree_row_reference_new (cell_view->priv->model, path);
935     }
936   else
937     cell_view->priv->displayed_row = NULL;
938
939   /* force resize and redraw */
940   gtk_widget_queue_resize (GTK_WIDGET (cell_view));
941   gtk_widget_queue_draw (GTK_WIDGET (cell_view));
942 }
943
944 /**
945  * gtk_cell_view_get_displayed_row:
946  * @cell_view: a #GtkCellView
947  *
948  * Returns a #GtkTreePath referring to the currently 
949  * displayed row. If no row is currently displayed, 
950  * %NULL is returned.
951  *
952  * Returns: the currently displayed row or %NULL
953  *
954  * Since: 2.6
955  */
956 GtkTreePath *
957 gtk_cell_view_get_displayed_row (GtkCellView *cell_view)
958 {
959   g_return_val_if_fail (GTK_IS_CELL_VIEW (cell_view), NULL);
960
961   if (!cell_view->priv->displayed_row)
962     return NULL;
963
964   return gtk_tree_row_reference_get_path (cell_view->priv->displayed_row);
965 }
966
967 /**
968  * gtk_cell_view_get_size_of_row:
969  * @cell_view: a #GtkCellView
970  * @path: a #GtkTreePath 
971  * @requisition: return location for the size 
972  *
973  * Sets @requisition to the size needed by @cell_view to display 
974  * the model row pointed to by @path.
975  * 
976  * Return value: %TRUE
977  *
978  * Since: 2.6
979  */
980 gboolean
981 gtk_cell_view_get_size_of_row (GtkCellView    *cell_view,
982                                GtkTreePath    *path,
983                                GtkRequisition *requisition)
984 {
985   GtkTreeRowReference *tmp;
986   GtkRequisition req;
987
988   g_return_val_if_fail (GTK_IS_CELL_VIEW (cell_view), FALSE);
989   g_return_val_if_fail (path != NULL, FALSE);
990   g_return_val_if_fail (requisition != NULL, FALSE);
991
992   tmp = cell_view->priv->displayed_row;
993   cell_view->priv->displayed_row =
994     gtk_tree_row_reference_new (cell_view->priv->model, path);
995
996   gtk_cell_view_size_request (GTK_WIDGET (cell_view), requisition);
997
998   gtk_tree_row_reference_free (cell_view->priv->displayed_row);
999   cell_view->priv->displayed_row = tmp;
1000
1001   /* restore actual size info */
1002   gtk_cell_view_size_request (GTK_WIDGET (cell_view), &req);
1003
1004   return TRUE;
1005 }
1006
1007 /**
1008  * gtk_cell_view_set_background_color:
1009  * @cell_view: a #GtkCellView
1010  * @color: the new background color
1011  *
1012  * Sets the background color of @view.
1013  *
1014  * Since: 2.6
1015  */
1016 void
1017 gtk_cell_view_set_background_color (GtkCellView    *cell_view,
1018                                     const GdkColor *color)
1019 {
1020   g_return_if_fail (GTK_IS_CELL_VIEW (cell_view));
1021
1022   if (color)
1023     {
1024       if (!cell_view->priv->background_set)
1025         {
1026           cell_view->priv->background_set = TRUE;
1027           g_object_notify (G_OBJECT (cell_view), "background-set");
1028         }
1029
1030       cell_view->priv->background = *color;
1031     }
1032   else
1033     {
1034       if (cell_view->priv->background_set)
1035         {
1036           cell_view->priv->background_set = FALSE;
1037           g_object_notify (G_OBJECT (cell_view), "background-set");
1038         }
1039     }
1040
1041   gtk_widget_queue_draw (GTK_WIDGET (cell_view));
1042 }
1043
1044 /**
1045  * gtk_cell_view_get_cell_renderers:
1046  * @cell_view: a #GtkCellView
1047  * 
1048  * Returns the cell renderers which have been added to @cell_view.
1049  *
1050  * Return value: a list of cell renderers. The list, but not the
1051  *   renderers has been newly allocated and should be freed with
1052  *   g_list_free() when no longer needed.
1053  * 
1054  * Since: 2.6
1055  */
1056 GList *
1057 gtk_cell_view_get_cell_renderers (GtkCellView *cell_view)
1058 {
1059   GList *retval = NULL, *list;
1060
1061   g_return_val_if_fail (cell_view != NULL, NULL);
1062
1063   gtk_cell_view_set_cell_data (cell_view);
1064
1065   for (list = cell_view->priv->cell_list; list; list = list->next)
1066     {
1067       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)list->data;
1068
1069       retval = g_list_prepend (retval, info->cell);
1070     }
1071
1072   return g_list_reverse (retval);
1073 }
1074
1075 #define __GTK_CELL_VIEW_C__
1076 #include "gtkaliasdef.c"