]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellrenderer.c
stylecontext: Do invalidation on first resize container
[~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, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "config.h"
19 #include "gtkcellrenderer.h"
20 #include "gtkintl.h"
21 #include "gtkmarshalers.h"
22 #include "gtktypebuiltins.h"
23 #include "gtkprivate.h"
24 #include "gtktreeprivate.h"
25 #include "a11y/gtkrenderercellaccessible.h"
26
27
28 /**
29  * SECTION:gtkcellrenderer
30  * @Short_description: An object for rendering a single cell
31  * @Title: GtkCellRenderer
32  * @See_also: #GtkCellRendererText, #GtkCellRendererPixbuf, #GtkCellRendererToggle
33  *
34  * The #GtkCellRenderer is a base class of a set of objects used for
35  * rendering a cell to a #cairo_t.  These objects are used primarily by
36  * the #GtkTreeView widget, though they aren't tied to them in any
37  * specific way.  It is worth noting that #GtkCellRenderer is not a
38  * #GtkWidget and cannot be treated as such.
39  *
40  * The primary use of a #GtkCellRenderer is for drawing a certain graphical
41  * elements on a #cairo_t. Typically, one cell renderer is used to
42  * draw many cells on the screen.  To this extent, it isn't expected that a
43  * CellRenderer keep any permanent state around.  Instead, any state is set
44  * just prior to use using #GObjects property system.  Then, the
45  * cell is measured using gtk_cell_renderer_get_size(). Finally, the cell
46  * is rendered in the correct location using gtk_cell_renderer_render().
47  *
48  * There are a number of rules that must be followed when writing a new
49  * #GtkCellRenderer.  First and foremost, it's important that a certain set
50  * of properties will always yield a cell renderer of the same size,
51  * barring a #GtkStyle change.  The #GtkCellRenderer also has a number of
52  * generic properties that are expected to be honored by all children.
53  *
54  * Beyond merely rendering a cell, cell renderers can optionally
55  * provide active user interface elements. A cell renderer can be
56  * <firstterm>activatable</firstterm> like #GtkCellRendererToggle,
57  * which toggles when it gets activated by a mouse click, or it can be
58  * <firstterm>editable</firstterm> like #GtkCellRendererText, which
59  * allows the user to edit the text using a #GtkEntry.
60  * To make a cell renderer activatable or editable, you have to
61  * implement the #GtkCellRendererClass.activate or
62  * #GtkCellRendererClass.start_editing virtual functions, respectively.
63  *
64  * Many properties of #GtkCellRenderer and its subclasses have a
65  * corresponding "set" property, e.g. "cell-background-set" corresponds
66  * to "cell-background". These "set" properties reflect whether a property
67  * has been set or not. You should not set them independently.
68  */
69
70
71 #define DEBUG_CELL_SIZE_REQUEST 0
72
73 static void gtk_cell_renderer_init          (GtkCellRenderer      *cell);
74 static void gtk_cell_renderer_class_init    (GtkCellRendererClass *class);
75 static void gtk_cell_renderer_get_property  (GObject              *object,
76                                              guint                 param_id,
77                                              GValue               *value,
78                                              GParamSpec           *pspec);
79 static void gtk_cell_renderer_set_property  (GObject              *object,
80                                              guint                 param_id,
81                                              const GValue         *value,
82                                              GParamSpec           *pspec);
83 static void set_cell_bg_color               (GtkCellRenderer      *cell,
84                                              GdkRGBA              *rgba);
85
86 /* Fallback GtkCellRenderer    implementation to use remaining ->get_size() implementations */
87 static GtkSizeRequestMode gtk_cell_renderer_real_get_request_mode(GtkCellRenderer         *cell);
88 static void gtk_cell_renderer_real_get_preferred_width           (GtkCellRenderer         *cell,
89                                                                   GtkWidget               *widget,
90                                                                   gint                    *minimum_size,
91                                                                   gint                    *natural_size);
92 static void gtk_cell_renderer_real_get_preferred_height          (GtkCellRenderer         *cell,
93                                                                   GtkWidget               *widget,
94                                                                   gint                    *minimum_size,
95                                                                   gint                    *natural_size);
96 static void gtk_cell_renderer_real_get_preferred_height_for_width(GtkCellRenderer         *cell,
97                                                                   GtkWidget               *widget,
98                                                                   gint                     width,
99                                                                   gint                    *minimum_height,
100                                                                   gint                    *natural_height);
101 static void gtk_cell_renderer_real_get_preferred_width_for_height(GtkCellRenderer         *cell,
102                                                                   GtkWidget               *widget,
103                                                                   gint                     height,
104                                                                   gint                    *minimum_width,
105                                                                   gint                    *natural_width);
106 static void gtk_cell_renderer_real_get_aligned_area              (GtkCellRenderer         *cell,
107                                                                   GtkWidget               *widget,
108                                                                   GtkCellRendererState     flags,
109                                                                   const GdkRectangle      *cell_area,
110                                                                   GdkRectangle            *aligned_area);
111
112
113 struct _GtkCellRendererPrivate
114 {
115   gfloat xalign;
116   gfloat yalign;
117
118   gint width;
119   gint height;
120
121   guint16 xpad;
122   guint16 ypad;
123
124   guint mode                : 2;
125   guint visible             : 1;
126   guint is_expander         : 1;
127   guint is_expanded         : 1;
128   guint cell_background_set : 1;
129   guint sensitive           : 1;
130   guint editing             : 1;
131
132   GdkRGBA cell_background;
133 };
134
135 struct _GtkCellRendererClassPrivate
136 {
137   GType accessible_type;
138 };
139
140 enum {
141   PROP_0,
142   PROP_MODE,
143   PROP_VISIBLE,
144   PROP_SENSITIVE,
145   PROP_XALIGN,
146   PROP_YALIGN,
147   PROP_XPAD,
148   PROP_YPAD,
149   PROP_WIDTH,
150   PROP_HEIGHT,
151   PROP_IS_EXPANDER,
152   PROP_IS_EXPANDED,
153   PROP_CELL_BACKGROUND,
154   PROP_CELL_BACKGROUND_GDK,
155   PROP_CELL_BACKGROUND_RGBA,
156   PROP_CELL_BACKGROUND_SET,
157   PROP_EDITING
158 };
159
160 /* Signal IDs */
161 enum {
162   EDITING_CANCELED,
163   EDITING_STARTED,
164   LAST_SIGNAL
165 };
166
167 static guint  cell_renderer_signals[LAST_SIGNAL] = { 0 };
168
169 static void
170 gtk_cell_renderer_init (GtkCellRenderer *cell)
171 {
172   GtkCellRendererPrivate *priv;
173
174   cell->priv = G_TYPE_INSTANCE_GET_PRIVATE (cell,
175                                             GTK_TYPE_CELL_RENDERER,
176                                             GtkCellRendererPrivate);
177   priv = cell->priv;
178
179   priv->mode = GTK_CELL_RENDERER_MODE_INERT;
180   priv->visible = TRUE;
181   priv->width = -1;
182   priv->height = -1;
183   priv->xalign = 0.5;
184   priv->yalign = 0.5;
185   priv->xpad = 0;
186   priv->ypad = 0;
187   priv->sensitive = TRUE;
188   priv->is_expander = FALSE;
189   priv->is_expanded = FALSE;
190   priv->editing = FALSE;
191 }
192
193 static void
194 gtk_cell_renderer_class_init (GtkCellRendererClass *class)
195 {
196   GObjectClass *object_class = G_OBJECT_CLASS (class);
197
198   object_class->get_property = gtk_cell_renderer_get_property;
199   object_class->set_property = gtk_cell_renderer_set_property;
200
201   class->render = NULL;
202   class->get_size = NULL;
203   class->get_request_mode               = gtk_cell_renderer_real_get_request_mode;
204   class->get_preferred_width            = gtk_cell_renderer_real_get_preferred_width;
205   class->get_preferred_height           = gtk_cell_renderer_real_get_preferred_height;
206   class->get_preferred_width_for_height = gtk_cell_renderer_real_get_preferred_width_for_height;
207   class->get_preferred_height_for_width = gtk_cell_renderer_real_get_preferred_height_for_width;
208   class->get_aligned_area               = gtk_cell_renderer_real_get_aligned_area;
209
210   /**
211    * GtkCellRenderer::editing-canceled:
212    * @renderer: the object which received the signal
213    *
214    * This signal gets emitted when the user cancels the process of editing a
215    * cell.  For example, an editable cell renderer could be written to cancel
216    * editing when the user presses Escape. 
217    *
218    * See also: gtk_cell_renderer_stop_editing().
219    *
220    * Since: 2.4
221    */
222   cell_renderer_signals[EDITING_CANCELED] =
223     g_signal_new (I_("editing-canceled"),
224                   G_OBJECT_CLASS_TYPE (object_class),
225                   G_SIGNAL_RUN_FIRST,
226                   G_STRUCT_OFFSET (GtkCellRendererClass, editing_canceled),
227                   NULL, NULL,
228                   _gtk_marshal_VOID__VOID,
229                   G_TYPE_NONE, 0);
230
231   /**
232    * GtkCellRenderer::editing-started:
233    * @renderer: the object which received the signal
234    * @editable: the #GtkCellEditable
235    * @path: the path identifying the edited cell
236    *
237    * This signal gets emitted when a cell starts to be edited.
238    * The intended use of this signal is to do special setup
239    * on @editable, e.g. adding a #GtkEntryCompletion or setting
240    * up additional columns in a #GtkComboBox.
241    *
242    * Note that GTK+ doesn't guarantee that cell renderers will
243    * continue to use the same kind of widget for editing in future
244    * releases, therefore you should check the type of @editable
245    * before doing any specific setup, as in the following example:
246    * |[
247    * static void
248    * text_editing_started (GtkCellRenderer *cell,
249    *                       GtkCellEditable *editable,
250    *                       const gchar     *path,
251    *                       gpointer         data)
252    * {
253    *   if (GTK_IS_ENTRY (editable)) 
254    *     {
255    *       GtkEntry *entry = GTK_ENTRY (editable);
256    *       
257    *       /&ast; ... create a GtkEntryCompletion &ast;/
258    *       
259    *       gtk_entry_set_completion (entry, completion);
260    *     }
261    * }
262    * ]|
263    *
264    * Since: 2.6
265    */
266   cell_renderer_signals[EDITING_STARTED] =
267     g_signal_new (I_("editing-started"),
268                   G_OBJECT_CLASS_TYPE (object_class),
269                   G_SIGNAL_RUN_FIRST,
270                   G_STRUCT_OFFSET (GtkCellRendererClass, editing_started),
271                   NULL, NULL,
272                   _gtk_marshal_VOID__OBJECT_STRING,
273                   G_TYPE_NONE, 2,
274                   GTK_TYPE_CELL_EDITABLE,
275                   G_TYPE_STRING);
276
277   g_object_class_install_property (object_class,
278                                    PROP_MODE,
279                                    g_param_spec_enum ("mode",
280                                                       P_("mode"),
281                                                       P_("Editable mode of the CellRenderer"),
282                                                       GTK_TYPE_CELL_RENDERER_MODE,
283                                                       GTK_CELL_RENDERER_MODE_INERT,
284                                                       GTK_PARAM_READWRITE));
285
286   g_object_class_install_property (object_class,
287                                    PROP_VISIBLE,
288                                    g_param_spec_boolean ("visible",
289                                                          P_("visible"),
290                                                          P_("Display the cell"),
291                                                          TRUE,
292                                                          GTK_PARAM_READWRITE));
293   g_object_class_install_property (object_class,
294                                    PROP_SENSITIVE,
295                                    g_param_spec_boolean ("sensitive",
296                                                          P_("Sensitive"),
297                                                          P_("Display the cell sensitive"),
298                                                          TRUE,
299                                                          GTK_PARAM_READWRITE));
300
301   g_object_class_install_property (object_class,
302                                    PROP_XALIGN,
303                                    g_param_spec_float ("xalign",
304                                                        P_("xalign"),
305                                                        P_("The x-align"),
306                                                        0.0,
307                                                        1.0,
308                                                        0.5,
309                                                        GTK_PARAM_READWRITE));
310
311   g_object_class_install_property (object_class,
312                                    PROP_YALIGN,
313                                    g_param_spec_float ("yalign",
314                                                        P_("yalign"),
315                                                        P_("The y-align"),
316                                                        0.0,
317                                                        1.0,
318                                                        0.5,
319                                                        GTK_PARAM_READWRITE));
320
321   g_object_class_install_property (object_class,
322                                    PROP_XPAD,
323                                    g_param_spec_uint ("xpad",
324                                                       P_("xpad"),
325                                                       P_("The xpad"),
326                                                       0,
327                                                       G_MAXUINT,
328                                                       0,
329                                                       GTK_PARAM_READWRITE));
330
331   g_object_class_install_property (object_class,
332                                    PROP_YPAD,
333                                    g_param_spec_uint ("ypad",
334                                                       P_("ypad"),
335                                                       P_("The ypad"),
336                                                       0,
337                                                       G_MAXUINT,
338                                                       0,
339                                                       GTK_PARAM_READWRITE));
340
341   g_object_class_install_property (object_class,
342                                    PROP_WIDTH,
343                                    g_param_spec_int ("width",
344                                                      P_("width"),
345                                                      P_("The fixed width"),
346                                                      -1,
347                                                      G_MAXINT,
348                                                      -1,
349                                                      GTK_PARAM_READWRITE));
350
351   g_object_class_install_property (object_class,
352                                    PROP_HEIGHT,
353                                    g_param_spec_int ("height",
354                                                      P_("height"),
355                                                      P_("The fixed height"),
356                                                      -1,
357                                                      G_MAXINT,
358                                                      -1,
359                                                      GTK_PARAM_READWRITE));
360
361   g_object_class_install_property (object_class,
362                                    PROP_IS_EXPANDER,
363                                    g_param_spec_boolean ("is-expander",
364                                                          P_("Is Expander"),
365                                                          P_("Row has children"),
366                                                          FALSE,
367                                                          GTK_PARAM_READWRITE));
368
369
370   g_object_class_install_property (object_class,
371                                    PROP_IS_EXPANDED,
372                                    g_param_spec_boolean ("is-expanded",
373                                                          P_("Is Expanded"),
374                                                          P_("Row is an expander row, and is expanded"),
375                                                          FALSE,
376                                                          GTK_PARAM_READWRITE));
377
378   g_object_class_install_property (object_class,
379                                    PROP_CELL_BACKGROUND,
380                                    g_param_spec_string ("cell-background",
381                                                         P_("Cell background color name"),
382                                                         P_("Cell background color as a string"),
383                                                         NULL,
384                                                         GTK_PARAM_WRITABLE));
385
386   /**
387    * GtkCellRenderer:cell-background-gdk:
388    *
389    * Cell background as a #GdkColor
390    *
391    * Deprecated: 3.4: Use #GtkCellRenderer:cell-background-rgba instead.
392    */
393   g_object_class_install_property (object_class,
394                                    PROP_CELL_BACKGROUND_GDK,
395                                    g_param_spec_boxed ("cell-background-gdk",
396                                                        P_("Cell background color"),
397                                                        P_("Cell background color as a GdkColor"),
398                                                        GDK_TYPE_COLOR,
399                                                        GTK_PARAM_READWRITE | G_PARAM_DEPRECATED));
400   /**
401    * GtkCellRenderer:cell-background-rgba:
402    *
403    * Cell background as a #GdkRGBA
404    *
405    * Since: 3.0
406    */
407   g_object_class_install_property (object_class,
408                                    PROP_CELL_BACKGROUND_RGBA,
409                                    g_param_spec_boxed ("cell-background-rgba",
410                                                        P_("Cell background RGBA color"),
411                                                        P_("Cell background color as a GdkRGBA"),
412                                                        GDK_TYPE_RGBA,
413                                                        GTK_PARAM_READWRITE));
414
415   g_object_class_install_property (object_class,
416                                    PROP_EDITING,
417                                    g_param_spec_boolean ("editing",
418                                                          P_("Editing"),
419                                                          P_("Whether the cell renderer is currently in editing mode"),
420                                                          FALSE,
421                                                          GTK_PARAM_READABLE));
422
423
424 #define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (object_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, GTK_PARAM_READWRITE))
425
426   ADD_SET_PROP ("cell-background-set", PROP_CELL_BACKGROUND_SET,
427                 P_("Cell background set"),
428                 P_("Whether the cell background color is set"));
429
430   g_type_class_add_private (class, sizeof (GtkCellRendererPrivate));
431
432   gtk_cell_renderer_class_set_accessible_type (class, GTK_TYPE_RENDERER_CELL_ACCESSIBLE);
433 }
434
435 static void
436 gtk_cell_renderer_base_class_init (gpointer g_class)
437 {
438   GtkCellRendererClass *klass = g_class;
439
440   klass->priv = G_TYPE_CLASS_GET_PRIVATE (g_class, GTK_TYPE_CELL_RENDERER, GtkCellRendererClassPrivate);
441 }
442
443 GType
444 gtk_cell_renderer_get_type (void)
445 {
446   static GType cell_renderer_type = 0;
447
448   if (G_UNLIKELY (cell_renderer_type == 0))
449     {
450       const GTypeInfo cell_renderer_info =
451       {
452         sizeof (GtkCellRendererClass),
453         gtk_cell_renderer_base_class_init,
454         NULL,
455         (GClassInitFunc) gtk_cell_renderer_class_init,
456         NULL,           /* class_finalize */
457         NULL,           /* class_init */
458         sizeof (GtkWidget),
459         0,              /* n_preallocs */
460         (GInstanceInitFunc) gtk_cell_renderer_init,
461         NULL,           /* value_table */
462       };
463       cell_renderer_type = g_type_register_static (G_TYPE_INITIALLY_UNOWNED, "GtkCellRenderer",
464                                                    &cell_renderer_info, G_TYPE_FLAG_ABSTRACT);
465
466       g_type_add_class_private (cell_renderer_type, sizeof (GtkCellRendererClassPrivate));
467     }
468
469   return cell_renderer_type;
470 }
471
472 static void
473 gtk_cell_renderer_get_property (GObject     *object,
474                                 guint        param_id,
475                                 GValue      *value,
476                                 GParamSpec  *pspec)
477 {
478   GtkCellRenderer *cell = GTK_CELL_RENDERER (object);
479   GtkCellRendererPrivate *priv = cell->priv;
480
481   switch (param_id)
482     {
483     case PROP_MODE:
484       g_value_set_enum (value, priv->mode);
485       break;
486     case PROP_VISIBLE:
487       g_value_set_boolean (value, priv->visible);
488       break;
489     case PROP_SENSITIVE:
490       g_value_set_boolean (value, priv->sensitive);
491       break;
492     case PROP_EDITING:
493       g_value_set_boolean (value, priv->editing);
494       break;
495     case PROP_XALIGN:
496       g_value_set_float (value, priv->xalign);
497       break;
498     case PROP_YALIGN:
499       g_value_set_float (value, priv->yalign);
500       break;
501     case PROP_XPAD:
502       g_value_set_uint (value, priv->xpad);
503       break;
504     case PROP_YPAD:
505       g_value_set_uint (value, priv->ypad);
506       break;
507     case PROP_WIDTH:
508       g_value_set_int (value, priv->width);
509       break;
510     case PROP_HEIGHT:
511       g_value_set_int (value, priv->height);
512       break;
513     case PROP_IS_EXPANDER:
514       g_value_set_boolean (value, priv->is_expander);
515       break;
516     case PROP_IS_EXPANDED:
517       g_value_set_boolean (value, priv->is_expanded);
518       break;
519     case PROP_CELL_BACKGROUND_GDK:
520       {
521         GdkColor color;
522
523         color.red = (guint16) (priv->cell_background.red * 65535);
524         color.green = (guint16) (priv->cell_background.green * 65535);
525         color.blue = (guint16) (priv->cell_background.blue * 65535);
526
527         g_value_set_boxed (value, &color);
528       }
529       break;
530     case PROP_CELL_BACKGROUND_RGBA:
531       g_value_set_boxed (value, &priv->cell_background);
532       break;
533     case PROP_CELL_BACKGROUND_SET:
534       g_value_set_boolean (value, priv->cell_background_set);
535       break;
536     case PROP_CELL_BACKGROUND:
537     default:
538       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
539       break;
540     }
541
542 }
543
544 static void
545 gtk_cell_renderer_set_property (GObject      *object,
546                                 guint         param_id,
547                                 const GValue *value,
548                                 GParamSpec   *pspec)
549 {
550   GtkCellRenderer *cell = GTK_CELL_RENDERER (object);
551   GtkCellRendererPrivate *priv = cell->priv;
552
553   switch (param_id)
554     {
555     case PROP_MODE:
556       priv->mode = g_value_get_enum (value);
557       break;
558     case PROP_VISIBLE:
559       priv->visible = g_value_get_boolean (value);
560       break;
561     case PROP_SENSITIVE:
562       priv->sensitive = g_value_get_boolean (value);
563       break;
564     case PROP_EDITING:
565       priv->editing = g_value_get_boolean (value);
566       break;
567     case PROP_XALIGN:
568       priv->xalign = g_value_get_float (value);
569       break;
570     case PROP_YALIGN:
571       priv->yalign = g_value_get_float (value);
572       break;
573     case PROP_XPAD:
574       priv->xpad = g_value_get_uint (value);
575       break;
576     case PROP_YPAD:
577       priv->ypad = g_value_get_uint (value);
578       break;
579     case PROP_WIDTH:
580       priv->width = g_value_get_int (value);
581       break;
582     case PROP_HEIGHT:
583       priv->height = g_value_get_int (value);
584       break;
585     case PROP_IS_EXPANDER:
586       priv->is_expander = g_value_get_boolean (value);
587       break;
588     case PROP_IS_EXPANDED:
589       priv->is_expanded = g_value_get_boolean (value);
590       break;
591     case PROP_CELL_BACKGROUND:
592       {
593         GdkRGBA rgba;
594
595         if (!g_value_get_string (value))
596           set_cell_bg_color (cell, NULL);
597         else if (gdk_rgba_parse (&rgba, g_value_get_string (value)))
598           set_cell_bg_color (cell, &rgba);
599         else
600           g_warning ("Don't know color `%s'", g_value_get_string (value));
601
602         g_object_notify (object, "cell-background-gdk");
603       }
604       break;
605     case PROP_CELL_BACKGROUND_GDK:
606       {
607         GdkColor *color;
608
609         color = g_value_get_boxed (value);
610         if (color)
611           {
612             GdkRGBA rgba;
613
614             rgba.red = color->red / 65535.;
615             rgba.green = color->green / 65535.;
616             rgba.blue = color->blue / 65535.;
617             rgba.alpha = 1;
618
619             set_cell_bg_color (cell, &rgba);
620           }
621         else
622           {
623             set_cell_bg_color (cell, NULL);
624           }
625       }
626       break;
627     case PROP_CELL_BACKGROUND_RGBA:
628       set_cell_bg_color (cell, g_value_get_boxed (value));
629       break;
630     case PROP_CELL_BACKGROUND_SET:
631       priv->cell_background_set = g_value_get_boolean (value);
632       break;
633     default:
634       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
635       break;
636     }
637 }
638
639 static void
640 set_cell_bg_color (GtkCellRenderer *cell,
641                    GdkRGBA         *rgba)
642 {
643   GtkCellRendererPrivate *priv = cell->priv;
644
645   if (rgba)
646     {
647       if (!priv->cell_background_set)
648         {
649           priv->cell_background_set = TRUE;
650           g_object_notify (G_OBJECT (cell), "cell-background-set");
651         }
652
653       priv->cell_background = *rgba;
654     }
655   else
656     {
657       if (priv->cell_background_set)
658         {
659           priv->cell_background_set = FALSE;
660           g_object_notify (G_OBJECT (cell), "cell-background-set");
661         }
662     }
663 }
664
665 /**
666  * gtk_cell_renderer_get_size:
667  * @cell: a #GtkCellRenderer
668  * @widget: the widget the renderer is rendering to
669  * @cell_area: (allow-none): The area a cell will be allocated, or %NULL
670  * @x_offset: (out) (allow-none): location to return x offset of cell relative to @cell_area, or %NULL
671  * @y_offset: (out) (allow-none): location to return y offset of cell relative to @cell_area, or %NULL
672  * @width: (out) (allow-none): location to return width needed to render a cell, or %NULL
673  * @height: (out) (allow-none): location to return height needed to render a cell, or %NULL
674  *
675  * Obtains the width and height needed to render the cell. Used by view 
676  * widgets to determine the appropriate size for the cell_area passed to
677  * gtk_cell_renderer_render().  If @cell_area is not %NULL, fills in the
678  * x and y offsets (if set) of the cell relative to this location. 
679  *
680  * Please note that the values set in @width and @height, as well as those 
681  * in @x_offset and @y_offset are inclusive of the xpad and ypad properties.
682  *
683  *
684  * Deprecated: 3.0: Use gtk_cell_renderer_get_preferred_size() instead.
685  **/
686 void
687 gtk_cell_renderer_get_size (GtkCellRenderer    *cell,
688                             GtkWidget          *widget,
689                             const GdkRectangle *cell_area,
690                             gint               *x_offset,
691                             gint               *y_offset,
692                             gint               *width,
693                             gint               *height)
694 {
695   GtkRequisition request;
696
697   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
698
699   gtk_cell_renderer_get_preferred_size (cell, widget, &request, NULL);
700
701   if (width)
702     *width = request.width;
703   
704   if (height)
705     *height = request.height;
706
707   if (cell_area)
708     _gtk_cell_renderer_calc_offset (cell, cell_area, gtk_widget_get_direction (widget),
709                                     request.width, request.height, x_offset, y_offset);
710 }
711
712 /**
713  * gtk_cell_renderer_render:
714  * @cell: a #GtkCellRenderer
715  * @cr: a cairo context to draw to
716  * @widget: the widget owning @window
717  * @background_area: entire cell area (including tree expanders and maybe 
718  *    padding on the sides)
719  * @cell_area: area normally rendered by a cell renderer
720  * @flags: flags that affect rendering
721  *
722  * Invokes the virtual render function of the #GtkCellRenderer. The three
723  * passed-in rectangles are areas in @cr. Most renderers will draw within
724  * @cell_area; the xalign, yalign, xpad, and ypad fields of the #GtkCellRenderer
725  * should be honored with respect to @cell_area. @background_area includes the
726  * blank space around the cell, and also the area containing the tree expander;
727  * so the @background_area rectangles for all cells tile to cover the entire
728  * @window.
729  **/
730 void
731 gtk_cell_renderer_render (GtkCellRenderer      *cell,
732                           cairo_t              *cr,
733                           GtkWidget            *widget,
734                           const GdkRectangle   *background_area,
735                           const GdkRectangle   *cell_area,
736                           GtkCellRendererState  flags)
737 {
738   gboolean selected = FALSE;
739   GtkCellRendererPrivate *priv = cell->priv;
740   GtkStyleContext *context;
741   GtkStateFlags state;
742
743   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
744   g_return_if_fail (GTK_CELL_RENDERER_GET_CLASS (cell)->render != NULL);
745   g_return_if_fail (cr != NULL);
746
747   selected = (flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED;
748
749   cairo_save (cr);
750
751   if (priv->cell_background_set && !selected)
752     {
753       gdk_cairo_rectangle (cr, background_area);
754       gdk_cairo_set_source_rgba (cr, &priv->cell_background);
755       cairo_fill (cr);
756     }
757
758   gdk_cairo_rectangle (cr, background_area);
759   cairo_clip (cr);
760
761   context = gtk_widget_get_style_context (widget);
762
763   gtk_style_context_save (context);
764   gtk_style_context_add_class (context, GTK_STYLE_CLASS_CELL);
765
766   state = gtk_cell_renderer_get_state (cell, widget, flags);
767   gtk_style_context_set_state (context, state);
768
769   GTK_CELL_RENDERER_GET_CLASS (cell)->render (cell,
770                                               cr,
771                                               widget,
772                                               background_area,
773                                               cell_area,
774                                               flags);
775   gtk_style_context_restore (context);
776   cairo_restore (cr);
777 }
778
779 /**
780  * gtk_cell_renderer_activate:
781  * @cell: a #GtkCellRenderer
782  * @event: a #GdkEvent
783  * @widget: widget that received the event
784  * @path: widget-dependent string representation of the event location; 
785  *    e.g. for #GtkTreeView, a string representation of #GtkTreePath
786  * @background_area: background area as passed to gtk_cell_renderer_render()
787  * @cell_area: cell area as passed to gtk_cell_renderer_render()
788  * @flags: render flags
789  *
790  * Passes an activate event to the cell renderer for possible processing.  
791  * Some cell renderers may use events; for example, #GtkCellRendererToggle 
792  * toggles when it gets a mouse click.
793  *
794  * Return value: %TRUE if the event was consumed/handled
795  **/
796 gboolean
797 gtk_cell_renderer_activate (GtkCellRenderer      *cell,
798                             GdkEvent             *event,
799                             GtkWidget            *widget,
800                             const gchar          *path,
801                             const GdkRectangle   *background_area,
802                             const GdkRectangle   *cell_area,
803                             GtkCellRendererState  flags)
804 {
805   GtkCellRendererPrivate *priv;
806
807   g_return_val_if_fail (GTK_IS_CELL_RENDERER (cell), FALSE);
808
809   priv = cell->priv;
810
811   if (priv->mode != GTK_CELL_RENDERER_MODE_ACTIVATABLE)
812     return FALSE;
813
814   if (GTK_CELL_RENDERER_GET_CLASS (cell)->activate == NULL)
815     return FALSE;
816
817   return GTK_CELL_RENDERER_GET_CLASS (cell)->activate (cell,
818                                                        event,
819                                                        widget,
820                                                        path,
821                                                        (GdkRectangle *) background_area,
822                                                        (GdkRectangle *) cell_area,
823                                                        flags);
824 }
825
826 /**
827  * gtk_cell_renderer_start_editing:
828  * @cell: a #GtkCellRenderer
829  * @event: a #GdkEvent
830  * @widget: widget that received the event
831  * @path: widget-dependent string representation of the event location;
832  *    e.g. for #GtkTreeView, a string representation of #GtkTreePath
833  * @background_area: background area as passed to gtk_cell_renderer_render()
834  * @cell_area: cell area as passed to gtk_cell_renderer_render()
835  * @flags: render flags
836  *
837  * Passes an activate event to the cell renderer for possible processing.
838  *
839  * Return value: (transfer none): A new #GtkCellEditable, or %NULL
840  **/
841 GtkCellEditable *
842 gtk_cell_renderer_start_editing (GtkCellRenderer      *cell,
843                                  GdkEvent             *event,
844                                  GtkWidget            *widget,
845                                  const gchar          *path,
846                                  const GdkRectangle   *background_area,
847                                  const GdkRectangle   *cell_area,
848                                  GtkCellRendererState  flags)
849
850 {
851   GtkCellRendererPrivate *priv;
852   GtkCellEditable *editable;
853
854   g_return_val_if_fail (GTK_IS_CELL_RENDERER (cell), NULL);
855
856   priv = cell->priv;
857
858   if (priv->mode != GTK_CELL_RENDERER_MODE_EDITABLE)
859     return NULL;
860
861   if (GTK_CELL_RENDERER_GET_CLASS (cell)->start_editing == NULL)
862     return NULL;
863
864   editable = GTK_CELL_RENDERER_GET_CLASS (cell)->start_editing (cell,
865                                                                 event,
866                                                                 widget,
867                                                                 path,
868                                                                 (GdkRectangle *) background_area,
869                                                                 (GdkRectangle *) cell_area,
870                                                                 flags);
871   gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (editable)),
872                                GTK_STYLE_CLASS_CELL);
873
874   g_signal_emit (cell, 
875                  cell_renderer_signals[EDITING_STARTED], 0,
876                  editable, path);
877
878   priv->editing = TRUE;
879
880   return editable;
881 }
882
883 /**
884  * gtk_cell_renderer_set_fixed_size:
885  * @cell: A #GtkCellRenderer
886  * @width: the width of the cell renderer, or -1
887  * @height: the height of the cell renderer, or -1
888  *
889  * Sets the renderer size to be explicit, independent of the properties set.
890  **/
891 void
892 gtk_cell_renderer_set_fixed_size (GtkCellRenderer *cell,
893                                   gint             width,
894                                   gint             height)
895 {
896   GtkCellRendererPrivate *priv;
897
898   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
899   g_return_if_fail (width >= -1 && height >= -1);
900
901   priv = cell->priv;
902
903   if ((width != priv->width) || (height != priv->height))
904     {
905       g_object_freeze_notify (G_OBJECT (cell));
906
907       if (width != priv->width)
908         {
909           priv->width = width;
910           g_object_notify (G_OBJECT (cell), "width");
911         }
912
913       if (height != priv->height)
914         {
915           priv->height = height;
916           g_object_notify (G_OBJECT (cell), "height");
917         }
918
919       g_object_thaw_notify (G_OBJECT (cell));
920     }
921 }
922
923 /**
924  * gtk_cell_renderer_get_fixed_size:
925  * @cell: A #GtkCellRenderer
926  * @width: (out) (allow-none): location to fill in with the fixed width of the cell, or %NULL
927  * @height: (out) (allow-none): location to fill in with the fixed height of the cell, or %NULL
928  *
929  * Fills in @width and @height with the appropriate size of @cell.
930  **/
931 void
932 gtk_cell_renderer_get_fixed_size (GtkCellRenderer *cell,
933                                   gint            *width,
934                                   gint            *height)
935 {
936   GtkCellRendererPrivate *priv;
937
938   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
939
940   priv = cell->priv;
941
942   if (width)
943     *width = priv->width;
944   if (height)
945     *height = priv->height;
946 }
947
948 /**
949  * gtk_cell_renderer_set_alignment:
950  * @cell: A #GtkCellRenderer
951  * @xalign: the x alignment of the cell renderer
952  * @yalign: the y alignment of the cell renderer
953  *
954  * Sets the renderer's alignment within its available space.
955  *
956  * Since: 2.18
957  **/
958 void
959 gtk_cell_renderer_set_alignment (GtkCellRenderer *cell,
960                                  gfloat           xalign,
961                                  gfloat           yalign)
962 {
963   GtkCellRendererPrivate *priv;
964
965   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
966   g_return_if_fail (xalign >= 0.0 && xalign <= 1.0);
967   g_return_if_fail (yalign >= 0.0 && yalign <= 1.0);
968
969   priv = cell->priv;
970
971   if ((xalign != priv->xalign) || (yalign != priv->yalign))
972     {
973       g_object_freeze_notify (G_OBJECT (cell));
974
975       if (xalign != priv->xalign)
976         {
977           priv->xalign = xalign;
978           g_object_notify (G_OBJECT (cell), "xalign");
979         }
980
981       if (yalign != priv->yalign)
982         {
983           priv->yalign = yalign;
984           g_object_notify (G_OBJECT (cell), "yalign");
985         }
986
987       g_object_thaw_notify (G_OBJECT (cell));
988     }
989 }
990
991 /**
992  * gtk_cell_renderer_get_alignment:
993  * @cell: A #GtkCellRenderer
994  * @xalign: (out) (allow-none): location to fill in with the x alignment of the cell, or %NULL
995  * @yalign: (out) (allow-none): location to fill in with the y alignment of the cell, or %NULL
996  *
997  * Fills in @xalign and @yalign with the appropriate values of @cell.
998  *
999  * Since: 2.18
1000  **/
1001 void
1002 gtk_cell_renderer_get_alignment (GtkCellRenderer *cell,
1003                                  gfloat          *xalign,
1004                                  gfloat          *yalign)
1005 {
1006   GtkCellRendererPrivate *priv;
1007
1008   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1009
1010   priv = cell->priv;
1011
1012   if (xalign)
1013     *xalign = priv->xalign;
1014   if (yalign)
1015     *yalign = priv->yalign;
1016 }
1017
1018 /**
1019  * gtk_cell_renderer_set_padding:
1020  * @cell: A #GtkCellRenderer
1021  * @xpad: the x padding of the cell renderer
1022  * @ypad: the y padding of the cell renderer
1023  *
1024  * Sets the renderer's padding.
1025  *
1026  * Since: 2.18
1027  **/
1028 void
1029 gtk_cell_renderer_set_padding (GtkCellRenderer *cell,
1030                                gint             xpad,
1031                                gint             ypad)
1032 {
1033   GtkCellRendererPrivate *priv;
1034
1035   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1036   g_return_if_fail (xpad >= 0 && xpad >= 0);
1037
1038   priv = cell->priv;
1039
1040   if ((xpad != priv->xpad) || (ypad != priv->ypad))
1041     {
1042       g_object_freeze_notify (G_OBJECT (cell));
1043
1044       if (xpad != priv->xpad)
1045         {
1046           priv->xpad = xpad;
1047           g_object_notify (G_OBJECT (cell), "xpad");
1048         }
1049
1050       if (ypad != priv->ypad)
1051         {
1052           priv->ypad = ypad;
1053           g_object_notify (G_OBJECT (cell), "ypad");
1054         }
1055
1056       g_object_thaw_notify (G_OBJECT (cell));
1057     }
1058 }
1059
1060 /**
1061  * gtk_cell_renderer_get_padding:
1062  * @cell: A #GtkCellRenderer
1063  * @xpad: (out) (allow-none): location to fill in with the x padding of the cell, or %NULL
1064  * @ypad: (out) (allow-none): location to fill in with the y padding of the cell, or %NULL
1065  *
1066  * Fills in @xpad and @ypad with the appropriate values of @cell.
1067  *
1068  * Since: 2.18
1069  **/
1070 void
1071 gtk_cell_renderer_get_padding (GtkCellRenderer *cell,
1072                                gint            *xpad,
1073                                gint            *ypad)
1074 {
1075   GtkCellRendererPrivate *priv;
1076
1077   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1078
1079   priv = cell->priv;
1080
1081   if (xpad)
1082     *xpad = priv->xpad;
1083   if (ypad)
1084     *ypad = priv->ypad;
1085 }
1086
1087 /**
1088  * gtk_cell_renderer_set_visible:
1089  * @cell: A #GtkCellRenderer
1090  * @visible: the visibility of the cell
1091  *
1092  * Sets the cell renderer's visibility.
1093  *
1094  * Since: 2.18
1095  **/
1096 void
1097 gtk_cell_renderer_set_visible (GtkCellRenderer *cell,
1098                                gboolean         visible)
1099 {
1100   GtkCellRendererPrivate *priv;
1101
1102   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1103
1104   priv = cell->priv;
1105
1106   if (priv->visible != visible)
1107     {
1108       priv->visible = visible ? TRUE : FALSE;
1109       g_object_notify (G_OBJECT (cell), "visible");
1110     }
1111 }
1112
1113 /**
1114  * gtk_cell_renderer_get_visible:
1115  * @cell: A #GtkCellRenderer
1116  *
1117  * Returns the cell renderer's visibility.
1118  *
1119  * Returns: %TRUE if the cell renderer is visible
1120  *
1121  * Since: 2.18
1122  */
1123 gboolean
1124 gtk_cell_renderer_get_visible (GtkCellRenderer *cell)
1125 {
1126   g_return_val_if_fail (GTK_IS_CELL_RENDERER (cell), FALSE);
1127
1128   return cell->priv->visible;
1129 }
1130
1131 /**
1132  * gtk_cell_renderer_set_sensitive:
1133  * @cell: A #GtkCellRenderer
1134  * @sensitive: the sensitivity of the cell
1135  *
1136  * Sets the cell renderer's sensitivity.
1137  *
1138  * Since: 2.18
1139  **/
1140 void
1141 gtk_cell_renderer_set_sensitive (GtkCellRenderer *cell,
1142                                  gboolean         sensitive)
1143 {
1144   GtkCellRendererPrivate *priv;
1145
1146   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1147
1148   priv = cell->priv;
1149
1150   if (priv->sensitive != sensitive)
1151     {
1152       priv->sensitive = sensitive ? TRUE : FALSE;
1153       g_object_notify (G_OBJECT (cell), "sensitive");
1154     }
1155 }
1156
1157 /**
1158  * gtk_cell_renderer_get_sensitive:
1159  * @cell: A #GtkCellRenderer
1160  *
1161  * Returns the cell renderer's sensitivity.
1162  *
1163  * Returns: %TRUE if the cell renderer is sensitive
1164  *
1165  * Since: 2.18
1166  */
1167 gboolean
1168 gtk_cell_renderer_get_sensitive (GtkCellRenderer *cell)
1169 {
1170   g_return_val_if_fail (GTK_IS_CELL_RENDERER (cell), FALSE);
1171
1172   return cell->priv->sensitive;
1173 }
1174
1175
1176 /**
1177  * gtk_cell_renderer_is_activatable:
1178  * @cell: A #GtkCellRenderer
1179  *
1180  * Checks whether the cell renderer can do something when activated.
1181  *
1182  * Returns: %TRUE if the cell renderer can do anything when activated
1183  *
1184  * Since: 3.0
1185  */
1186 gboolean
1187 gtk_cell_renderer_is_activatable (GtkCellRenderer *cell)
1188 {
1189   GtkCellRendererPrivate *priv;
1190
1191   g_return_val_if_fail (GTK_IS_CELL_RENDERER (cell), FALSE);
1192
1193   priv = cell->priv;
1194
1195   return (priv->visible &&
1196           (priv->mode == GTK_CELL_RENDERER_MODE_EDITABLE ||
1197            priv->mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE));
1198 }
1199
1200
1201 /**
1202  * gtk_cell_renderer_stop_editing:
1203  * @cell: A #GtkCellRenderer
1204  * @canceled: %TRUE if the editing has been canceled
1205  * 
1206  * Informs the cell renderer that the editing is stopped.
1207  * If @canceled is %TRUE, the cell renderer will emit the 
1208  * #GtkCellRenderer::editing-canceled signal. 
1209  *
1210  * This function should be called by cell renderer implementations 
1211  * in response to the #GtkCellEditable::editing-done signal of 
1212  * #GtkCellEditable.
1213  *
1214  * Since: 2.6
1215  **/
1216 void
1217 gtk_cell_renderer_stop_editing (GtkCellRenderer *cell,
1218                                 gboolean         canceled)
1219 {
1220   GtkCellRendererPrivate *priv;
1221
1222   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1223
1224   priv = cell->priv;
1225
1226   if (priv->editing)
1227     {
1228       priv->editing = FALSE;
1229       if (canceled)
1230         g_signal_emit (cell, cell_renderer_signals[EDITING_CANCELED], 0);
1231     }
1232 }
1233
1234 static void
1235 gtk_cell_renderer_real_get_preferred_size (GtkCellRenderer   *cell,
1236                                            GtkWidget         *widget,
1237                                            GtkOrientation     orientation,
1238                                            gint              *minimum_size,
1239                                            gint              *natural_size)
1240 {
1241   GtkRequisition min_req;
1242
1243   /* Fallback on the old API to get the size. */
1244   if (GTK_CELL_RENDERER_GET_CLASS (cell)->get_size)
1245     GTK_CELL_RENDERER_GET_CLASS (cell)->get_size (GTK_CELL_RENDERER (cell), widget, NULL, NULL, NULL,
1246                                                   &min_req.width, &min_req.height);
1247   else
1248     {
1249       min_req.width = 0;
1250       min_req.height = 0;
1251     }
1252
1253   if (orientation == GTK_ORIENTATION_HORIZONTAL)
1254     {
1255       if (minimum_size)
1256         *minimum_size = min_req.width;
1257
1258       if (natural_size)
1259         *natural_size = min_req.width;
1260     }
1261   else
1262     {
1263       if (minimum_size)
1264         *minimum_size = min_req.height;
1265
1266       if (natural_size)
1267         *natural_size = min_req.height;
1268     }
1269 }
1270
1271 static GtkSizeRequestMode 
1272 gtk_cell_renderer_real_get_request_mode (GtkCellRenderer *cell)
1273 {
1274   /* By default cell renderers are height-for-width. */
1275   return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
1276 }
1277
1278 static void
1279 gtk_cell_renderer_real_get_preferred_width (GtkCellRenderer *cell,
1280                                             GtkWidget       *widget,
1281                                             gint            *minimum_size,
1282                                             gint            *natural_size)
1283 {
1284   gtk_cell_renderer_real_get_preferred_size (cell, widget, GTK_ORIENTATION_HORIZONTAL, 
1285                                              minimum_size, natural_size);
1286 }
1287
1288 static void
1289 gtk_cell_renderer_real_get_preferred_height (GtkCellRenderer *cell,
1290                                              GtkWidget       *widget,
1291                                              gint            *minimum_size,
1292                                              gint            *natural_size)
1293 {
1294   gtk_cell_renderer_real_get_preferred_size (cell, widget, GTK_ORIENTATION_VERTICAL, 
1295                                              minimum_size, natural_size);
1296 }
1297
1298
1299 static void
1300 gtk_cell_renderer_real_get_preferred_height_for_width (GtkCellRenderer *cell,
1301                                                        GtkWidget       *widget,
1302                                                        gint             width,
1303                                                        gint            *minimum_height,
1304                                                        gint            *natural_height)
1305 {
1306   /* Fall back on the height reported from ->get_size() */
1307   gtk_cell_renderer_get_preferred_height (cell, widget, minimum_height, natural_height);
1308 }
1309
1310 static void
1311 gtk_cell_renderer_real_get_preferred_width_for_height (GtkCellRenderer *cell,
1312                                                        GtkWidget       *widget,
1313                                                        gint             height,
1314                                                        gint            *minimum_width,
1315                                                        gint            *natural_width)
1316 {
1317   /* Fall back on the width reported from ->get_size() */
1318   gtk_cell_renderer_get_preferred_width (cell, widget, minimum_width, natural_width);
1319 }
1320
1321
1322 /* Default implementation assumes that a cell renderer will never use more
1323  * space than its natural size (this is fine for toggles and pixbufs etc
1324  * but needs to be overridden from wrapping/ellipsizing text renderers) */
1325 static void
1326 gtk_cell_renderer_real_get_aligned_area (GtkCellRenderer         *cell,
1327                                          GtkWidget               *widget,
1328                                          GtkCellRendererState     flags,
1329                                          const GdkRectangle      *cell_area,
1330                                          GdkRectangle            *aligned_area)
1331 {
1332   gint opposite_size, x_offset, y_offset;
1333   gint natural_size;
1334
1335   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1336   g_return_if_fail (GTK_IS_WIDGET (widget));
1337   g_return_if_fail (cell_area != NULL);
1338   g_return_if_fail (aligned_area != NULL);
1339
1340   *aligned_area = *cell_area;
1341
1342   /* Trim up the aligned size */
1343   if (gtk_cell_renderer_get_request_mode (cell) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
1344     {
1345       gtk_cell_renderer_get_preferred_width (cell, widget, 
1346                                              NULL, &natural_size);
1347
1348       aligned_area->width = MIN (aligned_area->width, natural_size);
1349
1350       gtk_cell_renderer_get_preferred_height_for_width (cell, widget, 
1351                                                         aligned_area->width, 
1352                                                         NULL, &opposite_size);
1353
1354       aligned_area->height = MIN (opposite_size, aligned_area->height);
1355     }
1356   else
1357     {
1358       gtk_cell_renderer_get_preferred_height (cell, widget, 
1359                                               NULL, &natural_size);
1360
1361       aligned_area->height = MIN (aligned_area->width, natural_size);
1362
1363       gtk_cell_renderer_get_preferred_width_for_height (cell, widget, 
1364                                                         aligned_area->height, 
1365                                                         NULL, &opposite_size);
1366
1367       aligned_area->width = MIN (opposite_size, aligned_area->width);
1368     }
1369
1370   /* offset the cell position */
1371   _gtk_cell_renderer_calc_offset (cell, cell_area, 
1372                                   gtk_widget_get_direction (widget),
1373                                   aligned_area->width, 
1374                                   aligned_area->height,
1375                                   &x_offset, &y_offset);
1376
1377   aligned_area->x += x_offset;
1378   aligned_area->y += y_offset;
1379 }
1380
1381
1382 /* An internal convenience function for some containers to peek at the
1383  * cell alignment in a target allocation (used to draw focus and align
1384  * cells in the icon view).
1385  *
1386  * Note this is only a trivial 'align * (allocation - request)' operation.
1387  */
1388 void
1389 _gtk_cell_renderer_calc_offset    (GtkCellRenderer      *cell,
1390                                    const GdkRectangle   *cell_area,
1391                                    GtkTextDirection      direction,
1392                                    gint                  width,
1393                                    gint                  height,
1394                                    gint                 *x_offset,
1395                                    gint                 *y_offset)
1396
1397   GtkCellRendererPrivate *priv;
1398
1399   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1400   g_return_if_fail (cell_area != NULL);
1401   g_return_if_fail (x_offset || y_offset);
1402
1403   priv = cell->priv;
1404
1405   if (x_offset)
1406     {
1407       *x_offset = (((direction == GTK_TEXT_DIR_RTL) ?
1408                     (1.0 - priv->xalign) : priv->xalign) * 
1409                    (cell_area->width - width));
1410       *x_offset = MAX (*x_offset, 0);
1411     }
1412   if (y_offset)
1413     {
1414       *y_offset = (priv->yalign *
1415                    (cell_area->height - height));
1416       *y_offset = MAX (*y_offset, 0);
1417     }
1418 }
1419
1420 /**
1421  * gtk_cell_renderer_get_request_mode:
1422  * @cell: a #GtkCellRenderer    instance
1423  *
1424  * Gets whether the cell renderer prefers a height-for-width layout
1425  * or a width-for-height layout.
1426  *
1427  * Returns: The #GtkSizeRequestMode preferred by this renderer.
1428  *
1429  * Since: 3.0
1430  */
1431 GtkSizeRequestMode
1432 gtk_cell_renderer_get_request_mode (GtkCellRenderer *cell)
1433 {
1434   g_return_val_if_fail (GTK_IS_CELL_RENDERER (cell), FALSE);
1435
1436   return GTK_CELL_RENDERER_GET_CLASS (cell)->get_request_mode (cell);
1437 }
1438
1439 /**
1440  * gtk_cell_renderer_get_preferred_width:
1441  * @cell: a #GtkCellRenderer instance
1442  * @widget: the #GtkWidget this cell will be rendering to
1443  * @minimum_size: (out) (allow-none): location to store the minimum size, or %NULL
1444  * @natural_size: (out) (allow-none): location to store the natural size, or %NULL
1445  *
1446  * Retreives a renderer's natural size when rendered to @widget.
1447  *
1448  * Since: 3.0
1449  */
1450 void
1451 gtk_cell_renderer_get_preferred_width (GtkCellRenderer *cell,
1452                                        GtkWidget       *widget,
1453                                        gint            *minimum_size,
1454                                        gint            *natural_size)
1455 {
1456   GtkCellRendererClass *klass;
1457   gint width;
1458
1459   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1460   g_return_if_fail (GTK_IS_WIDGET (widget));
1461   g_return_if_fail (NULL != minimum_size || NULL != natural_size);
1462
1463   gtk_cell_renderer_get_fixed_size (GTK_CELL_RENDERER (cell), &width, NULL);
1464
1465   if (width < 0)
1466     {
1467       klass = GTK_CELL_RENDERER_GET_CLASS (cell);
1468       klass->get_preferred_width (cell, widget, minimum_size, natural_size);
1469     }
1470   else
1471     {
1472       if (minimum_size)
1473         *minimum_size = width;
1474       if (natural_size)
1475         *natural_size = width;
1476     }
1477
1478 #if DEBUG_CELL_SIZE_REQUEST
1479   g_message ("%s returning minimum width: %d and natural width: %d",
1480              G_OBJECT_TYPE_NAME (cell), 
1481              minimum_size ? *minimum_size : 20000, 
1482              natural_size ? *natural_size : 20000);
1483 #endif
1484 }
1485
1486
1487 /**
1488  * gtk_cell_renderer_get_preferred_height:
1489  * @cell: a #GtkCellRenderer instance
1490  * @widget: the #GtkWidget this cell will be rendering to
1491  * @minimum_size: (out) (allow-none): location to store the minimum size, or %NULL
1492  * @natural_size: (out) (allow-none): location to store the natural size, or %NULL
1493  *
1494  * Retreives a renderer's natural size when rendered to @widget.
1495  *
1496  * Since: 3.0
1497  */
1498 void
1499 gtk_cell_renderer_get_preferred_height (GtkCellRenderer *cell,
1500                                         GtkWidget       *widget,
1501                                         gint            *minimum_size,
1502                                         gint            *natural_size)
1503 {
1504   GtkCellRendererClass *klass;
1505   gint height;
1506
1507   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1508   g_return_if_fail (GTK_IS_WIDGET (widget));
1509   g_return_if_fail (NULL != minimum_size || NULL != natural_size);
1510
1511   gtk_cell_renderer_get_fixed_size (GTK_CELL_RENDERER (cell), NULL, &height);
1512
1513   if (height < 0)
1514     {
1515       klass = GTK_CELL_RENDERER_GET_CLASS (cell);
1516       klass->get_preferred_height (cell, widget, minimum_size, natural_size);
1517     }
1518   else
1519     {
1520       if (minimum_size)
1521         *minimum_size = height;
1522       if (natural_size)
1523         *natural_size = height;
1524     }
1525
1526 #if DEBUG_CELL_SIZE_REQUEST
1527   g_message ("%s returning minimum height: %d and natural height: %d",
1528              G_OBJECT_TYPE_NAME (cell), 
1529              minimum_size ? *minimum_size : 20000, 
1530              natural_size ? *natural_size : 20000);
1531 #endif
1532 }
1533
1534
1535 /**
1536  * gtk_cell_renderer_get_preferred_width_for_height:
1537  * @cell: a #GtkCellRenderer instance
1538  * @widget: the #GtkWidget this cell will be rendering to
1539  * @height: the size which is available for allocation
1540  * @minimum_width: (out) (allow-none): location for storing the minimum size, or %NULL
1541  * @natural_width: (out) (allow-none): location for storing the preferred size, or %NULL
1542  *
1543  * Retreives a cell renderers's minimum and natural width if it were rendered to 
1544  * @widget with the specified @height.
1545  *
1546  * Since: 3.0
1547  */
1548 void
1549 gtk_cell_renderer_get_preferred_width_for_height (GtkCellRenderer *cell,
1550                                                   GtkWidget       *widget,
1551                                                   gint             height,
1552                                                   gint            *minimum_width,
1553                                                   gint            *natural_width)
1554 {
1555   GtkCellRendererClass *klass;
1556   gint width;
1557
1558   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1559   g_return_if_fail (GTK_IS_WIDGET (widget));
1560   g_return_if_fail (NULL != minimum_width || NULL != natural_width);
1561
1562   gtk_cell_renderer_get_fixed_size (GTK_CELL_RENDERER (cell), &width, NULL);
1563
1564   if (width < 0)
1565     {
1566       klass = GTK_CELL_RENDERER_GET_CLASS (cell);
1567       klass->get_preferred_width_for_height (cell, widget, height, minimum_width, natural_width);
1568     }
1569   else
1570     {
1571       if (minimum_width)
1572         *minimum_width = width;
1573       if (natural_width)
1574         *natural_width = width;
1575     }
1576
1577 #if DEBUG_CELL_SIZE_REQUEST
1578   g_message ("%s width for height: %d is minimum %d and natural: %d",
1579              G_OBJECT_TYPE_NAME (cell), height,
1580              minimum_width ? *minimum_width : 20000, 
1581              natural_width ? *natural_width : 20000);
1582 #endif
1583 }
1584
1585 /**
1586  * gtk_cell_renderer_get_preferred_height_for_width:
1587  * @cell: a #GtkCellRenderer instance
1588  * @widget: the #GtkWidget this cell will be rendering to
1589  * @width: the size which is available for allocation
1590  * @minimum_height: (out) (allow-none): location for storing the minimum size, or %NULL
1591  * @natural_height: (out) (allow-none): location for storing the preferred size, or %NULL
1592  *
1593  * Retreives a cell renderers's minimum and natural height if it were rendered to 
1594  * @widget with the specified @width.
1595  *
1596  * Since: 3.0
1597  */
1598 void
1599 gtk_cell_renderer_get_preferred_height_for_width (GtkCellRenderer *cell,
1600                                                   GtkWidget       *widget,
1601                                                   gint             width,
1602                                                   gint            *minimum_height,
1603                                                   gint            *natural_height)
1604 {
1605   GtkCellRendererClass *klass;
1606   gint height;
1607
1608   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1609   g_return_if_fail (GTK_IS_WIDGET (widget));
1610   g_return_if_fail (NULL != minimum_height || NULL != natural_height);
1611
1612   gtk_cell_renderer_get_fixed_size (GTK_CELL_RENDERER (cell), NULL, &height);
1613
1614   if (height < 0)
1615     {
1616       klass = GTK_CELL_RENDERER_GET_CLASS (cell);
1617       klass->get_preferred_height_for_width (cell, widget, width, minimum_height, natural_height);
1618     }
1619   else
1620     {
1621       if (minimum_height)
1622         *minimum_height = height;
1623       if (natural_height)
1624         *natural_height = height;
1625     }
1626
1627 #if DEBUG_CELL_SIZE_REQUEST
1628   g_message ("%s height for width: %d is minimum %d and natural: %d",
1629              G_OBJECT_TYPE_NAME (cell), width,
1630              minimum_height ? *minimum_height : 20000, 
1631              natural_height ? *natural_height : 20000);
1632 #endif
1633 }
1634
1635 /**
1636  * gtk_cell_renderer_get_preferred_size:
1637  * @cell: a #GtkCellRenderer instance
1638  * @widget: the #GtkWidget this cell will be rendering to
1639  * @minimum_size: (out) (allow-none): location for storing the minimum size, or %NULL
1640  * @natural_size: (out) (allow-none): location for storing the natural size, or %NULL
1641  *
1642  * Retrieves the minimum and natural size of a cell taking
1643  * into account the widget's preference for height-for-width management.
1644  *
1645  * Since: 3.0
1646  */
1647 void
1648 gtk_cell_renderer_get_preferred_size (GtkCellRenderer *cell,
1649                                       GtkWidget       *widget,
1650                                       GtkRequisition  *minimum_size,
1651                                       GtkRequisition  *natural_size)
1652 {
1653   gint min_width, nat_width;
1654   gint min_height, nat_height;
1655
1656   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1657
1658   if (gtk_cell_renderer_get_request_mode (cell) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
1659     {
1660       gtk_cell_renderer_get_preferred_width (cell, widget, &min_width, &nat_width);
1661
1662       if (minimum_size)
1663         {
1664           minimum_size->width = min_width;
1665           gtk_cell_renderer_get_preferred_height_for_width (cell, widget, min_width,
1666                                                             &minimum_size->height, NULL);
1667         }
1668
1669       if (natural_size)
1670         {
1671           natural_size->width = nat_width;
1672           gtk_cell_renderer_get_preferred_height_for_width (cell, widget, nat_width,
1673                                                             NULL, &natural_size->height);
1674         }
1675     }
1676   else /* GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT */
1677     {
1678       gtk_cell_renderer_get_preferred_height (cell, widget, &min_height, &nat_height);
1679
1680       if (minimum_size)
1681         {
1682           minimum_size->height = min_height;
1683           gtk_cell_renderer_get_preferred_width_for_height (cell, widget, min_height,
1684                                                             &minimum_size->width, NULL);
1685         }
1686
1687       if (natural_size)
1688         {
1689           natural_size->height = nat_height;
1690           gtk_cell_renderer_get_preferred_width_for_height (cell, widget, nat_height,
1691                                                             NULL, &natural_size->width);
1692         }
1693     }
1694 }
1695
1696 /**
1697  * gtk_cell_renderer_get_aligned_area:
1698  * @cell: a #GtkCellRenderer instance
1699  * @widget: the #GtkWidget this cell will be rendering to
1700  * @flags: render flags
1701  * @cell_area: cell area which would be passed to gtk_cell_renderer_render()
1702  * @aligned_area: (out): the return location for the space inside @cell_area
1703  *                that would acually be used to render.
1704  *
1705  * Gets the aligned area used by @cell inside @cell_area. Used for finding
1706  * the appropriate edit and focus rectangle.
1707  *
1708  * Since: 3.0
1709  */
1710 void
1711 gtk_cell_renderer_get_aligned_area (GtkCellRenderer      *cell,
1712                                     GtkWidget            *widget,
1713                                     GtkCellRendererState  flags,
1714                                     const GdkRectangle   *cell_area,
1715                                     GdkRectangle         *aligned_area)
1716 {
1717   GtkCellRendererClass *klass;
1718
1719   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1720   g_return_if_fail (GTK_IS_WIDGET (widget));
1721   g_return_if_fail (cell_area != NULL);
1722   g_return_if_fail (aligned_area != NULL);
1723
1724   klass = GTK_CELL_RENDERER_GET_CLASS (cell);
1725   klass->get_aligned_area (cell, widget, flags, cell_area, aligned_area);
1726
1727   g_assert (aligned_area->x >= cell_area->x && aligned_area->x <= cell_area->x + cell_area->width);
1728   g_assert (aligned_area->y >= cell_area->y && aligned_area->y <= cell_area->y + cell_area->height);
1729   g_assert ((aligned_area->x - cell_area->x) + aligned_area->width <= cell_area->width);
1730   g_assert ((aligned_area->y - cell_area->y) + aligned_area->height <= cell_area->height);
1731 }
1732
1733 /**
1734  * gtk_cell_renderer_get_state:
1735  * @cell: a #GtkCellRenderer, or %NULL
1736  * @widget: a #GtkWidget, or %NULL
1737  * @cell_state: cell renderer state
1738  *
1739  * Translates the cell renderer state to #GtkStateFlags,
1740  * based on the cell renderer and widget sensitivity, and
1741  * the given #GtkCellRendererState.
1742  *
1743  * Returns: the widget state flags applying to @cell
1744  *
1745  * Since: 3.0
1746  **/
1747 GtkStateFlags
1748 gtk_cell_renderer_get_state (GtkCellRenderer      *cell,
1749                              GtkWidget            *widget,
1750                              GtkCellRendererState  cell_state)
1751 {
1752   GtkStateFlags state = 0;
1753
1754   g_return_val_if_fail (!cell || GTK_IS_CELL_RENDERER (cell), 0);
1755   g_return_val_if_fail (!widget || GTK_IS_WIDGET (widget), 0);
1756
1757   if (widget)
1758     state |= gtk_widget_get_state_flags (widget);
1759
1760   state &= ~(GTK_STATE_FLAG_FOCUSED | GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_SELECTED);
1761
1762   if ((state & GTK_STATE_FLAG_INSENSITIVE) != 0 ||
1763       (cell && !gtk_cell_renderer_get_sensitive (cell)) ||
1764       (cell_state & GTK_CELL_RENDERER_INSENSITIVE) != 0)
1765     {
1766       state |= GTK_STATE_FLAG_INSENSITIVE;
1767     }
1768   else
1769     {
1770       if ((widget && gtk_widget_has_focus (widget)) &&
1771           (cell_state & GTK_CELL_RENDERER_FOCUSED) != 0)
1772         state |= GTK_STATE_FLAG_FOCUSED;
1773
1774       if ((cell_state & GTK_CELL_RENDERER_PRELIT) != 0)
1775         state |= GTK_STATE_FLAG_PRELIGHT;
1776     }
1777
1778   if ((cell_state & GTK_CELL_RENDERER_SELECTED) != 0)
1779     state |= GTK_STATE_FLAG_SELECTED;
1780
1781   return state;
1782 }
1783
1784 /**
1785  * gtk_cell_renderer_class_set_accessible_type:
1786  * @renderer_class: class to set the accessible type for
1787  * @type: The object type that implements the accessible for @widget_class.
1788  *     The type must be a subtype of #GtkRendererCellAccessible
1789  *
1790  * Sets the type to be used for creating accessibles for cells rendered by
1791  * cell renderers of @renderer_class. Note that multiple accessibles will
1792  * be created.
1793  *
1794  * This function should only be called from class init functions of cell
1795  * renderers.
1796  **/
1797 void
1798 gtk_cell_renderer_class_set_accessible_type (GtkCellRendererClass *renderer_class,
1799                                              GType                 type)
1800 {
1801   GtkCellRendererClassPrivate *priv;
1802
1803   g_return_if_fail (GTK_IS_CELL_RENDERER_CLASS (renderer_class));
1804   g_return_if_fail (g_type_is_a (type, GTK_TYPE_RENDERER_CELL_ACCESSIBLE));
1805
1806   priv = renderer_class->priv;
1807
1808   priv->accessible_type = type;
1809 }
1810
1811 GType
1812 _gtk_cell_renderer_get_accessible_type (GtkCellRenderer *renderer)
1813 {
1814   g_return_val_if_fail (GTK_IS_CELL_RENDERER (renderer), GTK_TYPE_RENDERER_CELL_ACCESSIBLE);
1815
1816   return GTK_CELL_RENDERER_GET_CLASS (renderer)->priv->accessible_type;
1817 }
1818