]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellrenderer.c
Allow custom initialization of cell editables. (#147221)
[~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 <config.h>
21 #include "gtkcellrenderer.h"
22 #include "gtkintl.h"
23 #include "gtkmarshalers.h"
24 #include "gtktreeprivate.h"
25
26 static void gtk_cell_renderer_init       (GtkCellRenderer      *cell);
27 static void gtk_cell_renderer_class_init (GtkCellRendererClass *class);
28 static void gtk_cell_renderer_get_property  (GObject              *object,
29                                              guint                 param_id,
30                                              GValue               *value,
31                                              GParamSpec           *pspec);
32 static void gtk_cell_renderer_set_property  (GObject              *object,
33                                              guint                 param_id,
34                                              const GValue         *value,
35                                              GParamSpec           *pspec);
36 static void set_cell_bg_color               (GtkCellRenderer      *cell,
37                                              GdkColor             *color);
38
39
40 #define GTK_CELL_RENDERER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_CELL_RENDERER, GtkCellRendererPrivate))
41
42 typedef struct _GtkCellRendererPrivate GtkCellRendererPrivate;
43 struct _GtkCellRendererPrivate
44 {
45   GdkColor cell_background;
46 };
47
48
49 enum {
50   PROP_ZERO,
51   PROP_MODE,
52   PROP_VISIBLE,
53   PROP_SENSITIVE,
54   PROP_XALIGN,
55   PROP_YALIGN,
56   PROP_XPAD,
57   PROP_YPAD,
58   PROP_WIDTH,
59   PROP_HEIGHT,
60   PROP_IS_EXPANDER,
61   PROP_IS_EXPANDED,
62   PROP_CELL_BACKGROUND,
63   PROP_CELL_BACKGROUND_GDK,
64   PROP_CELL_BACKGROUND_SET
65 };
66
67 /* Signal IDs */
68 enum {
69   EDITING_CANCELED,
70   EDITING_STARTED,
71   LAST_SIGNAL
72 };
73
74 static guint cell_renderer_signals[LAST_SIGNAL] = { 0 };
75
76
77 GType
78 gtk_cell_renderer_get_type (void)
79 {
80   static GType cell_type = 0;
81
82   if (!cell_type)
83     {
84       static const GTypeInfo cell_info =
85       {
86         sizeof (GtkCellRendererClass),
87         NULL,           /* base_init */
88         NULL,           /* base_finalize */
89         (GClassInitFunc) gtk_cell_renderer_class_init,
90         NULL,           /* class_finalize */
91         NULL,           /* class_data */
92         sizeof (GtkCellRenderer),
93         0,              /* n_preallocs */
94         (GInstanceInitFunc) gtk_cell_renderer_init,
95         NULL,           /* value_table */
96       };
97
98       cell_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkCellRenderer", 
99                                           &cell_info, G_TYPE_FLAG_ABSTRACT);
100     }
101
102   return cell_type;
103 }
104
105 static void
106 gtk_cell_renderer_init (GtkCellRenderer *cell)
107 {
108   cell->mode = GTK_CELL_RENDERER_MODE_INERT;
109   cell->visible = TRUE;
110   cell->width = -1;
111   cell->height = -1;
112   cell->xalign = 0.5;
113   cell->yalign = 0.5;
114   cell->xpad = 0;
115   cell->ypad = 0;
116   cell->sensitive = TRUE;
117   cell->is_expander = FALSE;
118   cell->is_expanded = FALSE;
119 }
120
121 static void
122 gtk_cell_renderer_class_init (GtkCellRendererClass *class)
123 {
124   GObjectClass *object_class = G_OBJECT_CLASS (class);
125
126   object_class->get_property = gtk_cell_renderer_get_property;
127   object_class->set_property = gtk_cell_renderer_set_property;
128
129   class->render = NULL;
130   class->get_size = NULL;
131
132   /**
133    * GtkCellRenderer::editing-canceled:
134    * @renderer: the object which received the signal
135    *
136    * This signal gets emitted when the user cancels the process of editing a
137    * cell.  For example, an editable cell renderer could be written to cancel
138    * editing when the user presses Escape. 
139    *
140    * See also: gtk_cell_renderer_editing_canceled()
141    *
142    * Since: 2.4
143    */
144   cell_renderer_signals[EDITING_CANCELED] =
145     g_signal_new ("editing-canceled",
146                   G_OBJECT_CLASS_TYPE (object_class),
147                   G_SIGNAL_RUN_FIRST,
148                   G_STRUCT_OFFSET (GtkCellRendererClass, editing_canceled),
149                   NULL, NULL,
150                   _gtk_marshal_VOID__VOID,
151                   G_TYPE_NONE, 0);
152
153   /**
154    * GtkCellRenderer::editing-started:
155    * @renderer: the object which received the signal
156    * @editable: the #GtkCellEditable
157    * @path: the path identifying the edited cell
158    *
159    * This signal gets emitted when a cell starts to be edited.
160    * The indended use of this signal is to do special setup
161    * on @editable, e.g. adding a #GtkEntryCompletion or setting
162    * up additional columns in a #GtkComboBox.
163    *
164    * Note that GTK+ doesn't guarantee that cell renderers will
165    * continue to use the same kind of widget for editing in future
166    * releases, therefore you should check the type of @editable
167    * before doing any specific setup, as in the following example:
168    *
169    * <informalexample><programlisting>
170    * static void
171    * text_editing_started (GtkCellRenderer *cell,
172    *                       GtkCellEditable *editable,
173    *                       const gchar     *path,
174    *                       gpointer         data)
175    * {
176    *   if (GTK_IS_ENTRY (editable)) 
177    *     {
178    *       GtkEntry *entry = GTK_ENTRY (editable);
179    *       
180    *       /* ... create a GtkEntryCompletion *<!-- -->/
181    *
182    *       gtk_entry_set_completion (entry, completion);
183    *     }
184    * }
185    * </programlisting></informalexample>
186    *
187    * Since: 2.6
188    */
189   cell_renderer_signals[EDITING_STARTED] =
190     g_signal_new ("editing-started",
191                   G_OBJECT_CLASS_TYPE (object_class),
192                   G_SIGNAL_RUN_FIRST,
193                   G_STRUCT_OFFSET (GtkCellRendererClass, editing_started),
194                   NULL, NULL,
195                   _gtk_marshal_VOID__OBJECT_STRING,
196                   G_TYPE_NONE, 2,
197                   GTK_TYPE_CELL_EDITABLE,
198                   G_TYPE_STRING);
199
200   g_object_class_install_property (object_class,
201                                    PROP_MODE,
202                                    g_param_spec_enum ("mode",
203                                                       P_("mode"),
204                                                       P_("Editable mode of the CellRenderer"),
205                                                       GTK_TYPE_CELL_RENDERER_MODE,
206                                                       GTK_CELL_RENDERER_MODE_INERT,
207                                                       G_PARAM_READABLE |
208                                                       G_PARAM_WRITABLE));
209
210   g_object_class_install_property (object_class,
211                                    PROP_VISIBLE,
212                                    g_param_spec_boolean ("visible",
213                                                          P_("visible"),
214                                                          P_("Display the cell"),
215                                                          TRUE,
216                                                          G_PARAM_READWRITE));
217   g_object_class_install_property (object_class,
218                                    PROP_SENSITIVE,
219                                    g_param_spec_boolean ("sensitive",
220                                                          P_("Sensitive"),
221                                                          P_("Display the cell sensitive"),
222                                                          TRUE,
223                                                          G_PARAM_READWRITE));
224
225   g_object_class_install_property (object_class,
226                                    PROP_XALIGN,
227                                    g_param_spec_float ("xalign",
228                                                        P_("xalign"),
229                                                        P_("The x-align"),
230                                                        0.0,
231                                                        1.0,
232                                                        0.5,
233                                                        G_PARAM_READABLE |
234                                                        G_PARAM_WRITABLE));
235
236   g_object_class_install_property (object_class,
237                                    PROP_YALIGN,
238                                    g_param_spec_float ("yalign",
239                                                        P_("yalign"),
240                                                        P_("The y-align"),
241                                                        0.0,
242                                                        1.0,
243                                                        0.5,
244                                                        G_PARAM_READABLE |
245                                                        G_PARAM_WRITABLE));
246
247   g_object_class_install_property (object_class,
248                                    PROP_XPAD,
249                                    g_param_spec_uint ("xpad",
250                                                       P_("xpad"),
251                                                       P_("The xpad"),
252                                                       0,
253                                                       G_MAXUINT,
254                                                       0,
255                                                       G_PARAM_READABLE |
256                                                       G_PARAM_WRITABLE));
257
258   g_object_class_install_property (object_class,
259                                    PROP_YPAD,
260                                    g_param_spec_uint ("ypad",
261                                                       P_("ypad"),
262                                                       P_("The ypad"),
263                                                       0,
264                                                       G_MAXUINT,
265                                                       0,
266                                                       G_PARAM_READABLE |
267                                                       G_PARAM_WRITABLE));
268
269   g_object_class_install_property (object_class,
270                                    PROP_WIDTH,
271                                    g_param_spec_int ("width",
272                                                      P_("width"),
273                                                      P_("The fixed width"),
274                                                      -1,
275                                                      G_MAXINT,
276                                                      -1,
277                                                      G_PARAM_READABLE |
278                                                      G_PARAM_WRITABLE));
279
280   g_object_class_install_property (object_class,
281                                    PROP_HEIGHT,
282                                    g_param_spec_int ("height",
283                                                      P_("height"),
284                                                      P_("The fixed height"),
285                                                      -1,
286                                                      G_MAXINT,
287                                                      -1,
288                                                      G_PARAM_READABLE |
289                                                      G_PARAM_WRITABLE));
290
291   g_object_class_install_property (object_class,
292                                    PROP_IS_EXPANDER,
293                                    g_param_spec_boolean ("is_expander",
294                                                          P_("Is Expander"),
295                                                          P_("Row has children"),
296                                                          FALSE,
297                                                          G_PARAM_READABLE |
298                                                          G_PARAM_WRITABLE));
299
300
301   g_object_class_install_property (object_class,
302                                    PROP_IS_EXPANDED,
303                                    g_param_spec_boolean ("is_expanded",
304                                                          P_("Is Expanded"),
305                                                          P_("Row is an expander row, and is expanded"),
306                                                          FALSE,
307                                                          G_PARAM_READABLE |
308                                                          G_PARAM_WRITABLE));
309
310   g_object_class_install_property (object_class,
311                                    PROP_CELL_BACKGROUND,
312                                    g_param_spec_string ("cell_background",
313                                                         P_("Cell background color name"),
314                                                         P_("Cell background color as a string"),
315                                                         NULL,
316                                                         G_PARAM_WRITABLE));
317
318   g_object_class_install_property (object_class,
319                                    PROP_CELL_BACKGROUND_GDK,
320                                    g_param_spec_boxed ("cell_background_gdk",
321                                                        P_("Cell background color"),
322                                                        P_("Cell background color as a GdkColor"),
323                                                        GDK_TYPE_COLOR,
324                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
325
326
327 #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))
328
329   ADD_SET_PROP ("cell_background_set", PROP_CELL_BACKGROUND_SET,
330                 P_("Cell background set"),
331                 P_("Whether this tag affects the cell background color"));
332
333   g_type_class_add_private (object_class, sizeof (GtkCellRendererPrivate));
334 }
335
336 static void
337 gtk_cell_renderer_get_property (GObject     *object,
338                                 guint        param_id,
339                                 GValue      *value,
340                                 GParamSpec  *pspec)
341 {
342   GtkCellRenderer *cell = GTK_CELL_RENDERER (object);
343   GtkCellRendererPrivate *priv = GTK_CELL_RENDERER_GET_PRIVATE (object);
344
345   switch (param_id)
346     {
347     case PROP_MODE:
348       g_value_set_enum (value, cell->mode);
349       break;
350     case PROP_VISIBLE:
351       g_value_set_boolean (value, cell->visible);
352       break;
353     case PROP_SENSITIVE:
354       g_value_set_boolean (value, cell->sensitive);
355       break;
356     case PROP_XALIGN:
357       g_value_set_float (value, cell->xalign);
358       break;
359     case PROP_YALIGN:
360       g_value_set_float (value, cell->yalign);
361       break;
362     case PROP_XPAD:
363       g_value_set_uint (value, cell->xpad);
364       break;
365     case PROP_YPAD:
366       g_value_set_uint (value, cell->ypad);
367       break;
368     case PROP_WIDTH:
369       g_value_set_int (value, cell->width);
370       break;
371     case PROP_HEIGHT:
372       g_value_set_int (value, cell->height);
373       break;
374     case PROP_IS_EXPANDER:
375       g_value_set_boolean (value, cell->is_expander);
376       break;
377     case PROP_IS_EXPANDED:
378       g_value_set_boolean (value, cell->is_expanded);
379       break;
380     case PROP_CELL_BACKGROUND_GDK:
381       {
382         GdkColor color;
383
384         color.red = priv->cell_background.red;
385         color.green = priv->cell_background.green;
386         color.blue = priv->cell_background.blue;
387
388         g_value_set_boxed (value, &color);
389       }
390       break;
391     case PROP_CELL_BACKGROUND_SET:
392       g_value_set_boolean (value, cell->cell_background_set);
393       break;
394     case PROP_CELL_BACKGROUND:
395     default:
396       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
397       break;
398     }
399
400 }
401
402 static void
403 gtk_cell_renderer_set_property (GObject      *object,
404                                 guint         param_id,
405                                 const GValue *value,
406                                 GParamSpec   *pspec)
407 {
408   GtkCellRenderer *cell = GTK_CELL_RENDERER (object);
409
410   switch (param_id)
411     {
412     case PROP_MODE:
413       cell->mode = g_value_get_enum (value);
414       break;
415     case PROP_VISIBLE:
416       cell->visible = g_value_get_boolean (value);
417       break;
418     case PROP_SENSITIVE:
419       cell->sensitive = g_value_get_boolean (value);
420       break;
421     case PROP_XALIGN:
422       cell->xalign = g_value_get_float (value);
423       break;
424     case PROP_YALIGN:
425       cell->yalign = g_value_get_float (value);
426       break;
427     case PROP_XPAD:
428       cell->xpad = g_value_get_uint (value);
429       break;
430     case PROP_YPAD:
431       cell->ypad = g_value_get_uint (value);
432       break;
433     case PROP_WIDTH:
434       cell->width = g_value_get_int (value);
435       break;
436     case PROP_HEIGHT:
437       cell->height = g_value_get_int (value);
438       break;
439     case PROP_IS_EXPANDER:
440       cell->is_expander = g_value_get_boolean (value);
441       break;
442     case PROP_IS_EXPANDED:
443       cell->is_expanded = g_value_get_boolean (value);
444       break;
445     case PROP_CELL_BACKGROUND:
446       {
447         GdkColor color;
448
449         if (!g_value_get_string (value))
450           set_cell_bg_color (cell, NULL);
451         else if (gdk_color_parse (g_value_get_string (value), &color))
452           set_cell_bg_color (cell, &color);
453         else
454           g_warning ("Don't know color `%s'", g_value_get_string (value));
455
456         g_object_notify (object, "cell_background_gdk");
457       }
458       break;
459     case PROP_CELL_BACKGROUND_GDK:
460       set_cell_bg_color (cell, g_value_get_boxed (value));
461       break;
462     case PROP_CELL_BACKGROUND_SET:
463       cell->cell_background_set = g_value_get_boolean (value);
464       break;
465     default:
466       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
467       break;
468     }
469 }
470
471 static void
472 set_cell_bg_color (GtkCellRenderer *cell,
473                    GdkColor        *color)
474 {
475   GtkCellRendererPrivate *priv = GTK_CELL_RENDERER_GET_PRIVATE (cell);
476
477   if (color)
478     {
479       if (!cell->cell_background_set)
480         {
481           cell->cell_background_set = TRUE;
482           g_object_notify (G_OBJECT (cell), "cell_background_set");
483         }
484
485       priv->cell_background.red = color->red;
486       priv->cell_background.green = color->green;
487       priv->cell_background.blue = color->blue;
488     }
489   else
490     {
491       if (cell->cell_background_set)
492         {
493           cell->cell_background_set = FALSE;
494           g_object_notify (G_OBJECT (cell), "cell_background_set");
495         }
496     }
497 }
498
499 /**
500  * gtk_cell_renderer_get_size:
501  * @cell: a #GtkCellRenderer
502  * @widget: the widget the renderer is rendering to
503  * @cell_area: The area a cell will be allocated, or %NULL
504  * @x_offset: location to return x offset of cell relative to @cell_area, or %NULL
505  * @y_offset: location to return y offset of cell relative to @cell_area, or %NULL
506  * @width: location to return width needed to render a cell, or %NULL
507  * @height: location to return height needed to render a cell, or %NULL
508  *
509  * Obtains the width and height needed to render the cell. Used by view widgets
510  * to determine the appropriate size for the cell_area passed to
511  * gtk_cell_renderer_render().  If @cell_area is not %NULL, fills in the x and y
512  * offsets (if set) of the cell relative to this location.  Please note that the
513  * values set in @width and @height, as well as those in @x_offset and @y_offset
514  * are inclusive of the xpad and ypad properties.
515  **/
516 void
517 gtk_cell_renderer_get_size (GtkCellRenderer *cell,
518                             GtkWidget       *widget,
519                             GdkRectangle    *cell_area,
520                             gint            *x_offset,
521                             gint            *y_offset,
522                             gint            *width,
523                             gint            *height)
524 {
525   gint *real_width = width;
526   gint *real_height = height;
527
528   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
529   g_return_if_fail (GTK_CELL_RENDERER_GET_CLASS (cell)->get_size != NULL);
530
531   if (width && cell->width != -1)
532     {
533       real_width = NULL;
534       *width = cell->width;
535     }
536   if (height && cell->height != -1)
537     {
538       real_height = NULL;
539       *height = cell->height;
540     }
541
542   GTK_CELL_RENDERER_GET_CLASS (cell)->get_size (cell,
543                                                 widget,
544                                                 cell_area,
545                                                 x_offset,
546                                                 y_offset,
547                                                 real_width,
548                                                 real_height);
549 }
550
551 /**
552  * gtk_cell_renderer_render:
553  * @cell: a #GtkCellRenderer
554  * @window: a #GdkDrawable to draw to
555  * @widget: the widget owning @window
556  * @background_area: entire cell area (including tree expanders and maybe padding on the sides)
557  * @cell_area: area normally rendered by a cell renderer
558  * @expose_area: area that actually needs updating
559  * @flags: flags that affect rendering
560  *
561  * Invokes the virtual render function of the #GtkCellRenderer. The three
562  * passed-in rectangles are areas of @window. Most renderers will draw within
563  * @cell_area; the xalign, yalign, xpad, and ypad fields of the #GtkCellRenderer
564  * should be honored with respect to @cell_area. @background_area includes the
565  * blank space around the cell, and also the area containing the tree expander;
566  * so the @background_area rectangles for all cells tile to cover the entire
567  * @window.  @expose_area is a clip rectangle.
568  *
569  **/
570 void
571 gtk_cell_renderer_render (GtkCellRenderer     *cell,
572                           GdkWindow           *window,
573                           GtkWidget           *widget,
574                           GdkRectangle        *background_area,
575                           GdkRectangle        *cell_area,
576                           GdkRectangle        *expose_area,
577                           GtkCellRendererState flags)
578 {
579   gboolean selected = FALSE;
580   GtkCellRendererPrivate *priv = GTK_CELL_RENDERER_GET_PRIVATE (cell);
581
582   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
583   g_return_if_fail (GTK_CELL_RENDERER_GET_CLASS (cell)->render != NULL);
584
585   selected = (flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED;
586
587   if (cell->cell_background_set && !selected)
588     {
589       GdkColor color;
590       GdkGC *gc;
591
592       color.red = priv->cell_background.red;
593       color.green = priv->cell_background.green;
594       color.blue = priv->cell_background.blue;
595
596       gc = gdk_gc_new (window);
597       gdk_gc_set_rgb_fg_color (gc, &color);
598       gdk_draw_rectangle (window, gc, TRUE,
599                           background_area->x, background_area->y,
600                           background_area->width, background_area->height);
601       g_object_unref (gc);
602     }
603
604   GTK_CELL_RENDERER_GET_CLASS (cell)->render (cell,
605                                               window,
606                                               widget,
607                                               background_area,
608                                               cell_area,
609                                               expose_area,
610                                               flags);
611 }
612
613 /**
614  * gtk_cell_renderer_activate:
615  * @cell: a #GtkCellRenderer
616  * @event: a #GdkEvent
617  * @widget: widget that received the event
618  * @path: widget-dependent string representation of the event location; e.g. for #GtkTreeView, a string representation of #GtkTreePath
619  * @background_area: background area as passed to @gtk_cell_renderer_render
620  * @cell_area: cell area as passed to @gtk_cell_renderer_render
621  * @flags: render flags
622  *
623  * Passes an activate event to the cell renderer for possible processing.  Some
624  * cell renderers may use events; for example, #GtkCellRendererToggle toggles
625  * when it gets a mouse click.
626  *
627  * Return value: %TRUE if the event was consumed/handled
628  **/
629 gboolean
630 gtk_cell_renderer_activate (GtkCellRenderer      *cell,
631                             GdkEvent             *event,
632                             GtkWidget            *widget,
633                             const gchar          *path,
634                             GdkRectangle         *background_area,
635                             GdkRectangle         *cell_area,
636                             GtkCellRendererState  flags)
637 {
638   g_return_val_if_fail (GTK_IS_CELL_RENDERER (cell), FALSE);
639
640   if (cell->mode != GTK_CELL_RENDERER_MODE_ACTIVATABLE)
641     return FALSE;
642
643   if (GTK_CELL_RENDERER_GET_CLASS (cell)->activate == NULL)
644     return FALSE;
645
646   return GTK_CELL_RENDERER_GET_CLASS (cell)->activate (cell,
647                                                        event,
648                                                        widget,
649                                                        path,
650                                                        background_area,
651                                                        cell_area,
652                                                        flags);
653 }
654
655 /**
656  * gtk_cell_renderer_start_editing:
657  * @cell: a #GtkCellRenderer
658  * @event: a #GdkEvent
659  * @widget: widget that received the event
660  * @path: widget-dependent string representation of the event location; e.g. for #GtkTreeView, a string representation of #GtkTreePath
661  * @background_area: background area as passed to @gtk_cell_renderer_render
662  * @cell_area: cell area as passed to @gtk_cell_renderer_render
663  * @flags: render flags
664  * 
665  * Passes an activate event to the cell renderer for possible processing.
666  * 
667  * Return value: A new #GtkCellEditable, or %NULL
668  **/
669 GtkCellEditable *
670 gtk_cell_renderer_start_editing (GtkCellRenderer      *cell,
671                                  GdkEvent             *event,
672                                  GtkWidget            *widget,
673                                  const gchar          *path,
674                                  GdkRectangle         *background_area,
675                                  GdkRectangle         *cell_area,
676                                  GtkCellRendererState  flags)
677
678 {
679   GtkCellEditable *editable;
680
681   g_return_val_if_fail (GTK_IS_CELL_RENDERER (cell), NULL);
682
683   if (cell->mode != GTK_CELL_RENDERER_MODE_EDITABLE)
684     return NULL;
685
686   if (GTK_CELL_RENDERER_GET_CLASS (cell)->start_editing == NULL)
687     return NULL;
688
689   
690   editable = GTK_CELL_RENDERER_GET_CLASS (cell)->start_editing (cell,
691                                                                 event,
692                                                                 widget,
693                                                                 path,
694                                                                 background_area,
695                                                                 cell_area,
696                                                                 flags);
697
698   g_signal_emit (cell, 
699                  cell_renderer_signals[EDITING_STARTED], 0,
700                  editable, path);
701
702   return editable;
703 }
704
705 /**
706  * gtk_cell_renderer_set_fixed_size:
707  * @cell: A #GtkCellRenderer
708  * @width: the width of the cell renderer, or -1
709  * @height: the height of the cell renderer, or -1
710  * 
711  * Sets the renderer size to be explicit, independent of the properties set.
712  **/
713 void
714 gtk_cell_renderer_set_fixed_size (GtkCellRenderer *cell,
715                                   gint             width,
716                                   gint             height)
717 {
718   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
719   g_return_if_fail (width >= -1 && height >= -1);
720
721   if ((width != cell->width) || (height != cell->height))
722     {
723       g_object_freeze_notify (G_OBJECT (cell));
724
725       if (width != cell->width)
726         {
727           cell->width = width;
728           g_object_notify (G_OBJECT (cell), "width");
729         }
730
731       if (height != cell->height)
732         {
733           cell->height = height;
734           g_object_notify (G_OBJECT (cell), "height");
735         }
736
737       g_object_thaw_notify (G_OBJECT (cell));
738     }
739 }
740
741 /**
742  * gtk_cell_renderer_get_fixed_size:
743  * @cell: A #GtkCellRenderer
744  * @width: location to fill in with the fixed width of the widget, or %NULL
745  * @height: location to fill in with the fixed height of the widget, or %NULL
746  * 
747  * Fills in @width and @height with the appropriate size of @cell.
748  **/
749 void
750 gtk_cell_renderer_get_fixed_size (GtkCellRenderer *cell,
751                                   gint            *width,
752                                   gint            *height)
753 {
754   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
755
756   if (width)
757     (* width) = cell->width;
758   if (height)
759     (* height) = cell->height;
760 }
761
762 /**
763  * gtk_cell_renderer_editing_canceled:
764  * @cell: A #GtkCellRenderer
765  * 
766  * Causes the cell renderer to emit the "editing-canceled" signal.  This
767  * function is for use only by implementations of cell renderers that need to
768  * notify the client program that an editing process was canceled and the
769  * changes were not committed.
770  *
771  * Since: 2.4
772  **/
773 void
774 gtk_cell_renderer_editing_canceled (GtkCellRenderer *cell)
775 {
776   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
777
778   g_signal_emit (cell, cell_renderer_signals[EDITING_CANCELED], 0);
779 }