]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellrenderer.c
6327da9eb380bd158e0a07b45edfc2b39fd790c2
[~andy/gtk] / gtk / gtkcellrenderer.c
1 /* gtkcellrenderer.c
2  * Copyright (C) 2000  Red Hat, Inc. Jonathan Blandford
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "gtkcellrenderer.h"
21 #include "gtkintl.h"
22
23 static void gtk_cell_renderer_init       (GtkCellRenderer      *cell);
24 static void gtk_cell_renderer_class_init (GtkCellRendererClass *class);
25 static void gtk_cell_renderer_get_property  (GObject              *object,
26                                              guint                 param_id,
27                                              GValue               *value,
28                                              GParamSpec           *pspec);
29 static void gtk_cell_renderer_set_property  (GObject              *object,
30                                              guint                 param_id,
31                                              const GValue         *value,
32                                              GParamSpec           *pspec);
33 static void set_cell_bg_color               (GtkCellRenderer      *cell,
34                                              GdkColor             *color);
35
36
37 enum {
38   PROP_ZERO,
39   PROP_MODE,
40   PROP_VISIBLE,
41   PROP_XALIGN,
42   PROP_YALIGN,
43   PROP_XPAD,
44   PROP_YPAD,
45   PROP_WIDTH,
46   PROP_HEIGHT,
47   PROP_IS_EXPANDER,
48   PROP_IS_EXPANDED,
49   PROP_CELL_BACKGROUND,
50   PROP_CELL_BACKGROUND_GDK,
51   PROP_CELL_BACKGROUND_SET
52 };
53
54
55 GtkType
56 gtk_cell_renderer_get_type (void)
57 {
58   static GtkType cell_type = 0;
59
60   if (!cell_type)
61     {
62       static const GTypeInfo cell_info =
63       {
64         sizeof (GtkCellRendererClass),
65         NULL,           /* base_init */
66         NULL,           /* base_finalize */
67         (GClassInitFunc) gtk_cell_renderer_class_init,
68         NULL,           /* class_finalize */
69         NULL,           /* class_data */
70         sizeof (GtkCellRenderer),
71         0,
72         (GInstanceInitFunc) gtk_cell_renderer_init,
73       };
74
75       cell_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkCellRenderer", &cell_info, 0);
76     }
77
78   return cell_type;
79 }
80
81 static void
82 gtk_cell_renderer_init (GtkCellRenderer *cell)
83 {
84   cell->mode = GTK_CELL_RENDERER_MODE_INERT;
85   cell->visible = TRUE;
86   cell->width = -1;
87   cell->height = -1;
88   cell->xalign = 0.5;
89   cell->yalign = 0.5;
90   cell->xpad = 0;
91   cell->ypad = 0;
92 }
93
94 static void
95 gtk_cell_renderer_class_init (GtkCellRendererClass *class)
96 {
97   GObjectClass *object_class = G_OBJECT_CLASS (class);
98
99   object_class->get_property = gtk_cell_renderer_get_property;
100   object_class->set_property = gtk_cell_renderer_set_property;
101
102   class->render = NULL;
103   class->get_size = NULL;
104
105   g_object_class_install_property (object_class,
106                                    PROP_MODE,
107                                    g_param_spec_enum ("mode",
108                                                       _("mode"),
109                                                       _("Editable mode of the CellRenderer"),
110                                                       GTK_TYPE_CELL_RENDERER_MODE,
111                                                       GTK_CELL_RENDERER_MODE_INERT,
112                                                       G_PARAM_READABLE |
113                                                       G_PARAM_WRITABLE));
114
115   g_object_class_install_property (object_class,
116                                    PROP_VISIBLE,
117                                    g_param_spec_boolean ("visible",
118                                                          _("visible"),
119                                                          _("Display the cell"),
120                                                          TRUE,
121                                                          G_PARAM_READABLE |
122                                                          G_PARAM_WRITABLE));
123
124   g_object_class_install_property (object_class,
125                                    PROP_XALIGN,
126                                    g_param_spec_float ("xalign",
127                                                        _("xalign"),
128                                                        _("The x-align."),
129                                                        0.0,
130                                                        1.0,
131                                                        0.0,
132                                                        G_PARAM_READABLE |
133                                                        G_PARAM_WRITABLE));
134
135   g_object_class_install_property (object_class,
136                                    PROP_YALIGN,
137                                    g_param_spec_float ("yalign",
138                                                        _("yalign"),
139                                                        _("The y-align."),
140                                                        0.0,
141                                                        1.0,
142                                                        0.5,
143                                                        G_PARAM_READABLE |
144                                                        G_PARAM_WRITABLE));
145
146   g_object_class_install_property (object_class,
147                                    PROP_XPAD,
148                                    g_param_spec_uint ("xpad",
149                                                       _("xpad"),
150                                                       _("The xpad."),
151                                                       0,
152                                                       100,
153                                                       2,
154                                                       G_PARAM_READABLE |
155                                                       G_PARAM_WRITABLE));
156
157   g_object_class_install_property (object_class,
158                                    PROP_YPAD,
159                                    g_param_spec_uint ("ypad",
160                                                       _("ypad"),
161                                                       _("The ypad."),
162                                                       0,
163                                                       100,
164                                                       2,
165                                                       G_PARAM_READABLE |
166                                                       G_PARAM_WRITABLE));
167
168   g_object_class_install_property (object_class,
169                                    PROP_WIDTH,
170                                    g_param_spec_int ("width",
171                                                      _("width"),
172                                                      _("The fixed width."),
173                                                      -1,
174                                                      100,
175                                                      -1,
176                                                      G_PARAM_READABLE |
177                                                      G_PARAM_WRITABLE));
178
179   g_object_class_install_property (object_class,
180                                    PROP_HEIGHT,
181                                    g_param_spec_int ("height",
182                                                      _("height"),
183                                                      _("The fixed height."),
184                                                      -1,
185                                                      100,
186                                                      -1,
187                                                      G_PARAM_READABLE |
188                                                      G_PARAM_WRITABLE));
189
190   g_object_class_install_property (object_class,
191                                    PROP_IS_EXPANDER,
192                                    g_param_spec_boolean ("is_expander",
193                                                          _("Is Expander"),
194                                                          _("Row has children."),
195                                                          FALSE,
196                                                          G_PARAM_READABLE |
197                                                          G_PARAM_WRITABLE));
198
199
200   g_object_class_install_property (object_class,
201                                    PROP_IS_EXPANDED,
202                                    g_param_spec_boolean ("is_expanded",
203                                                          _("Is Expanded"),
204                                                          _("Row is an expander row, and is expanded"),
205                                                          FALSE,
206                                                          G_PARAM_READABLE |
207                                                          G_PARAM_WRITABLE));
208
209   g_object_class_install_property (object_class,
210                                    PROP_CELL_BACKGROUND,
211                                    g_param_spec_string ("cell_background",
212                                                         _("Cell background color name"),
213                                                         _("Cell background color as a string"),
214                                                         NULL,
215                                                         G_PARAM_WRITABLE));
216
217   g_object_class_install_property (object_class,
218                                    PROP_CELL_BACKGROUND_GDK,
219                                    g_param_spec_boxed ("cell_background_gdk",
220                                                        _("Cell background color"),
221                                                        _("Cell background color as a GdkColor"),
222                                                        GDK_TYPE_COLOR,
223                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
224
225
226 #define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (object_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE))
227
228   ADD_SET_PROP ("cell_background_set", PROP_CELL_BACKGROUND_SET,
229                 _("Cell background set"),
230                 _("Whether this tag affects the cell background color"));
231 }
232
233 static void
234 gtk_cell_renderer_get_property (GObject     *object,
235                                 guint        param_id,
236                                 GValue      *value,
237                                 GParamSpec  *pspec)
238 {
239   GtkCellRenderer *cell = GTK_CELL_RENDERER (object);
240
241   switch (param_id)
242     {
243     case PROP_MODE:
244       g_value_set_enum (value, cell->mode);
245       break;
246     case PROP_VISIBLE:
247       g_value_set_boolean (value, cell->visible);
248       break;
249     case PROP_XALIGN:
250       g_value_set_float (value, cell->xalign);
251       break;
252     case PROP_YALIGN:
253       g_value_set_float (value, cell->yalign);
254       break;
255     case PROP_XPAD:
256       g_value_set_uint (value, cell->xpad);
257       break;
258     case PROP_YPAD:
259       g_value_set_uint (value, cell->ypad);
260       break;
261     case PROP_WIDTH:
262       g_value_set_int (value, cell->width);
263       break;
264     case PROP_HEIGHT:
265       g_value_set_int (value, cell->height);
266       break;
267     case PROP_IS_EXPANDER:
268       g_value_set_int (value, cell->is_expander);
269       break;
270     case PROP_IS_EXPANDED:
271       g_value_set_int (value, cell->is_expanded);
272       break;
273     case PROP_CELL_BACKGROUND_GDK:
274       {
275         GdkColor color;
276
277         color.red = cell->cell_background.red;
278         color.green = cell->cell_background.green;
279         color.blue = cell->cell_background.blue;
280
281         g_value_set_boxed (value, &color);
282       }
283       break;
284     case PROP_CELL_BACKGROUND_SET:
285       g_value_set_boolean (value, cell->cell_background_set);
286       break;
287     case PROP_CELL_BACKGROUND:
288     default:
289       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
290       break;
291     }
292
293 }
294
295 static void
296 gtk_cell_renderer_set_property (GObject      *object,
297                                 guint         param_id,
298                                 const GValue *value,
299                                 GParamSpec   *pspec)
300 {
301   GtkCellRenderer *cell = GTK_CELL_RENDERER (object);
302
303   switch (param_id)
304     {
305     case PROP_MODE:
306       cell->mode = g_value_get_enum (value);
307       break;
308     case PROP_VISIBLE:
309       cell->visible = g_value_get_boolean (value);
310       break;
311     case PROP_XALIGN:
312       cell->xalign = g_value_get_float (value);
313       break;
314     case PROP_YALIGN:
315       cell->yalign = g_value_get_float (value);
316       break;
317     case PROP_XPAD:
318       cell->xpad = g_value_get_uint (value);
319       break;
320     case PROP_YPAD:
321       cell->ypad = g_value_get_uint (value);
322       break;
323     case PROP_WIDTH:
324       cell->width = g_value_get_int (value);
325       break;
326     case PROP_HEIGHT:
327       cell->height = g_value_get_int (value);
328       break;
329     case PROP_IS_EXPANDER:
330       cell->is_expander = g_value_get_boolean (value);
331       break;
332     case PROP_IS_EXPANDED:
333       cell->is_expanded = g_value_get_boolean (value);
334       break;
335     case PROP_CELL_BACKGROUND:
336       {
337         GdkColor color;
338
339         if (!g_value_get_string (value))
340           set_cell_bg_color (cell, NULL);
341         else if (gdk_color_parse (g_value_get_string (value), &color))
342           set_cell_bg_color (cell, &color);
343         else
344           g_warning ("Don't know color `%s'", g_value_get_string (value));
345
346         g_object_notify (object, "cell_background_gdk");
347       }
348       break;
349     case PROP_CELL_BACKGROUND_GDK:
350       set_cell_bg_color (cell, g_value_get_boxed (value));
351       break;
352     case PROP_CELL_BACKGROUND_SET:
353       cell->cell_background_set = g_value_get_boolean (value);
354       break;
355     default:
356       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
357       break;
358     }
359 }
360
361 static void
362 set_cell_bg_color (GtkCellRenderer *cell,
363                    GdkColor        *color)
364 {
365   if (color)
366     {
367       if (!cell->cell_background_set)
368         {
369           cell->cell_background_set = TRUE;
370           g_object_notify (G_OBJECT (cell), "cell_background_set");
371         }
372
373       cell->cell_background.red = color->red;
374       cell->cell_background.green = color->green;
375       cell->cell_background.blue = color->blue;
376     }
377   else
378     {
379       if (cell->cell_background_set)
380         {
381           cell->cell_background_set = FALSE;
382           g_object_notify (G_OBJECT (cell), "cell_background_set");
383         }
384     }
385 }
386
387 /**
388  * gtk_cell_renderer_get_size:
389  * @cell: a #GtkCellRenderer
390  * @widget: the widget the renderer is rendering to
391  * @cell_area: The area a cell will be allocated, or %NULL
392  * @x_offset: location to return x offset of cell relative to @cell_area, or %NULL
393  * @y_offset: location to return y offset of cell relative to @cell_area, or %NULL
394  * @width: location to return width needed to render a cell, or %NULL
395  * @height: location to return height needed to render a cell, or %NULL
396  *
397  * Obtains the width and height needed to render the cell. Used by view widgets
398  * to determine the appropriate size for the cell_area passed to
399  * gtk_cell_renderer_render().  If @cell_area is not %NULL, fills in the x and y
400  * offsets (if set) of the cell relative to this location.  Please note that the
401  * values set in @width and @height, as well as those in @x_offset and @y_offset
402  * are inclusive of the xpad and ypad properties.
403  **/
404 void
405 gtk_cell_renderer_get_size (GtkCellRenderer *cell,
406                             GtkWidget       *widget,
407                             GdkRectangle    *cell_area,
408                             gint            *x_offset,
409                             gint            *y_offset,
410                             gint            *width,
411                             gint            *height)
412 {
413   gint *real_width = width;
414   gint *real_height = height;
415
416   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
417   g_return_if_fail (GTK_CELL_RENDERER_GET_CLASS (cell)->get_size != NULL);
418
419   if (width && cell->width != -1)
420     {
421       real_width = NULL;
422       *width = cell->width;
423     }
424   if (height && cell->height != -1)
425     {
426       real_height = NULL;
427       *height = cell->height;
428     }
429
430   GTK_CELL_RENDERER_GET_CLASS (cell)->get_size (cell, widget, cell_area, x_offset, y_offset, real_width, real_height);
431 }
432
433 /**
434  * gtk_cell_renderer_render:
435  * @cell: a #GtkCellRenderer
436  * @window: a #GdkDrawable to draw to
437  * @widget: the widget owning @window
438  * @background_area: entire cell area (including tree expanders and maybe padding on the sides)
439  * @cell_area: area normally rendered by a cell renderer
440  * @expose_area: area that actually needs updating
441  * @flags: flags that affect rendering
442  *
443  * Invokes the virtual render function of the #GtkCellRenderer. The three
444  * passed-in rectangles are areas of @window. Most renderers will draw within
445  * @cell_area; the xalign, yalign, xpad, and ypad fields of the #GtkCellRenderer
446  * should be honored with respect to @cell_area. @background_area includes the
447  * blank space around the cell, and also the area containing the tree expander;
448  * so the @background_area rectangles for all cells tile to cover the entire
449  * @window.  @expose_area is a clip rectangle.
450  *
451  **/
452 void
453 gtk_cell_renderer_render (GtkCellRenderer     *cell,
454                           GdkWindow           *window,
455                           GtkWidget           *widget,
456                           GdkRectangle        *background_area,
457                           GdkRectangle        *cell_area,
458                           GdkRectangle        *expose_area,
459                           GtkCellRendererState flags)
460 {
461   gboolean selected = FALSE;
462
463   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
464   g_return_if_fail (GTK_CELL_RENDERER_GET_CLASS (cell)->render != NULL);
465
466   selected = (flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED;
467
468   if (cell->cell_background_set && !selected)
469     {
470       GdkColor color;
471       GdkGC *gc;
472
473       color.red = cell->cell_background.red;
474       color.green = cell->cell_background.green;
475       color.blue = cell->cell_background.blue;
476
477       gc = gdk_gc_new (window);
478       gdk_gc_set_rgb_fg_color (gc, &color);
479       gdk_draw_rectangle (window, gc, TRUE,
480                           background_area->x, background_area->y,
481                           background_area->width, background_area->height);
482       g_object_unref (G_OBJECT (gc));
483     }
484
485   GTK_CELL_RENDERER_GET_CLASS (cell)->render (cell,
486                                               window,
487                                               widget,
488                                               background_area,
489                                               cell_area,
490                                               expose_area,
491                                               flags);
492 }
493
494 /**
495  * gtk_cell_renderer_activate:
496  * @cell: a #GtkCellRenderer
497  * @event: a #GdkEvent
498  * @widget: widget that received the event
499  * @path: widget-dependent string representation of the event location; e.g. for #GtkTreeView, a string representation of #GtkTreePath
500  * @background_area: background area as passed to @gtk_cell_renderer_render
501  * @cell_area: cell area as passed to @gtk_cell_renderer_render
502  * @flags: render flags
503  *
504  * Passes an activate event to the cell renderer for possible processing.  Some
505  * cell renderers may use events; for example, #GtkCellRendererToggle toggles
506  * when it gets a mouse click.
507  *
508  * Return value: %TRUE if the event was consumed/handled
509  **/
510 gboolean
511 gtk_cell_renderer_activate (GtkCellRenderer      *cell,
512                             GdkEvent             *event,
513                             GtkWidget            *widget,
514                             const gchar          *path,
515                             GdkRectangle         *background_area,
516                             GdkRectangle         *cell_area,
517                             GtkCellRendererState  flags)
518 {
519   g_return_val_if_fail (GTK_IS_CELL_RENDERER (cell), FALSE);
520
521   if (cell->mode != GTK_CELL_RENDERER_MODE_ACTIVATABLE)
522     return FALSE;
523
524   if (GTK_CELL_RENDERER_GET_CLASS (cell)->activate == NULL)
525     return FALSE;
526
527   return GTK_CELL_RENDERER_GET_CLASS (cell)->activate (cell,
528                                                        event,
529                                                        widget,
530                                                        path,
531                                                        background_area,
532                                                        cell_area,
533                                                        flags);
534 }
535
536 /**
537  * gtk_cell_renderer_start_editing:
538  * @cell: a #GtkCellRenderer
539  * @event: a #GdkEvent
540  * @widget: widget that received the event
541  * @path: widget-dependent string representation of the event location; e.g. for #GtkTreeView, a string representation of #GtkTreePath
542  * @background_area: background area as passed to @gtk_cell_renderer_render
543  * @cell_area: cell area as passed to @gtk_cell_renderer_render
544  * @flags: render flags
545  * 
546  * Passes an activate event to the cell renderer for possible processing.
547  * 
548  * Return value: A new #GtkCellEditable, or %NULL
549  **/
550 GtkCellEditable *
551 gtk_cell_renderer_start_editing (GtkCellRenderer      *cell,
552                                  GdkEvent             *event,
553                                  GtkWidget            *widget,
554                                  const gchar          *path,
555                                  GdkRectangle         *background_area,
556                                  GdkRectangle         *cell_area,
557                                  GtkCellRendererState  flags)
558
559 {
560   g_return_val_if_fail (GTK_IS_CELL_RENDERER (cell), NULL);
561
562   if (cell->mode != GTK_CELL_RENDERER_MODE_EDITABLE)
563     return NULL;
564
565   if (GTK_CELL_RENDERER_GET_CLASS (cell)->start_editing == NULL)
566     return NULL;
567
568   
569   return GTK_CELL_RENDERER_GET_CLASS (cell)->start_editing (cell,
570                                                             event,
571                                                             widget,
572                                                             path,
573                                                             background_area,
574                                                             cell_area,
575                                                             flags);
576 }
577
578 /**
579  * gtk_cell_renderer_set_fixed_size:
580  * @cell: A #GtkCellRenderer
581  * @width: the width of the cell renderer, or -1
582  * @height: the height of the cell renderer, or -1
583  * 
584  * Sets the renderer size to be explicit, independent of the properties set.
585  **/
586 void
587 gtk_cell_renderer_set_fixed_size (GtkCellRenderer *cell,
588                                   gint             width,
589                                   gint             height)
590 {
591   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
592   g_return_if_fail (width >= -1 && height >= -1);
593
594   if ((width != cell->width) || (height != cell->height))
595     {
596       g_object_freeze_notify (G_OBJECT (cell));
597
598       if (width != cell->width)
599         {
600           cell->width = width;
601           g_object_notify (G_OBJECT (cell), "width");
602         }
603
604       if (height != cell->height)
605         {
606           cell->height = height;
607           g_object_notify (G_OBJECT (cell), "height");
608         }
609
610       g_object_thaw_notify (G_OBJECT (cell));
611     }
612 }
613
614 /**
615  * gtk_cell_renderer_get_fixed_size:
616  * @cell: A #GtkCellRenderer
617  * @width: location to fill in with the fixed width of the widget, or %NULL
618  * @height: location to fill in with the fixed height of the widget, or %NULL
619  * 
620  * Fills in @width and @height with the appropriate size of @cell.
621  **/
622 void
623 gtk_cell_renderer_get_fixed_size (GtkCellRenderer *cell,
624                                   gint            *width,
625                                   gint            *height)
626 {
627   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
628
629   if (width)
630     (* width) = cell->width;
631   if (height)
632     (* height) = cell->height;
633 }