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