comparison src/gtkcellview.c @ 10708:d0d1d631ed49

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