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