10708
|
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 */
|