]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellrenderertext.c
5a99a5a76ae9b5f50dd909156480e0d5900a5ec6
[~andy/gtk] / gtk / gtkcellrenderertext.c
1 /* gtkcellrenderertext.c
2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
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 <stdlib.h>
21 #include "gtkcellrenderertext.h"
22 #include "gtkintl.h"
23
24 static void gtk_cell_renderer_text_init       (GtkCellRendererText      *celltext);
25 static void gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class);
26 static void gtk_cell_renderer_text_finalize   (GObject                  *object);
27
28 static void gtk_cell_renderer_text_get_property  (GObject                  *object,
29                                                   guint                     param_id,
30                                                   GValue                   *value,
31                                                   GParamSpec               *pspec);
32 static void gtk_cell_renderer_text_set_property  (GObject                  *object,
33                                                   guint                     param_id,
34                                                   const GValue             *value,
35                                                   GParamSpec               *pspec);
36 static void gtk_cell_renderer_text_get_size   (GtkCellRenderer          *cell,
37                                                GtkWidget                *widget,
38                                                GdkRectangle             *cell_area,
39                                                gint                     *x_offset,
40                                                gint                     *y_offset,
41                                                gint                     *width,
42                                                gint                     *height);
43 static void gtk_cell_renderer_text_render     (GtkCellRenderer          *cell,
44                                                GdkWindow                *window,
45                                                GtkWidget                *widget,
46                                                GdkRectangle             *background_area,
47                                                GdkRectangle             *cell_area,
48                                                GdkRectangle             *expose_area,
49                                                guint                     flags);
50
51
52
53 enum {
54   PROP_0,
55
56   PROP_TEXT,
57   PROP_MARKUP,
58   PROP_ATTRIBUTES,
59   
60   /* Style args */
61   PROP_BACKGROUND,
62   PROP_FOREGROUND,
63   PROP_BACKGROUND_GDK,
64   PROP_FOREGROUND_GDK,
65   PROP_FONT,
66   PROP_FONT_DESC,
67   PROP_FAMILY,
68   PROP_STYLE,
69   PROP_VARIANT,
70   PROP_WEIGHT,
71   PROP_STRETCH,
72   PROP_SIZE,
73   PROP_SIZE_POINTS,
74   PROP_SCALE,
75   PROP_EDITABLE,
76   PROP_STRIKETHROUGH,
77   PROP_UNDERLINE,
78   PROP_RISE,
79   
80   /* Whether-a-style-arg-is-set args */
81   PROP_BACKGROUND_SET,
82   PROP_FOREGROUND_SET,
83   PROP_FAMILY_SET,
84   PROP_STYLE_SET,
85   PROP_VARIANT_SET,
86   PROP_WEIGHT_SET,
87   PROP_STRETCH_SET,
88   PROP_SIZE_SET,
89   PROP_SCALE_SET,
90   PROP_EDITABLE_SET,
91   PROP_STRIKETHROUGH_SET,
92   PROP_UNDERLINE_SET,
93   PROP_RISE_SET
94 };
95
96 static gpointer parent_class;
97
98 GtkType
99 gtk_cell_renderer_text_get_type (void)
100 {
101   static GtkType cell_text_type = 0;
102
103   if (!cell_text_type)
104     {
105       static const GTypeInfo cell_text_info =
106       {
107         sizeof (GtkCellRendererTextClass),
108         NULL,           /* base_init */
109         NULL,           /* base_finalize */
110         (GClassInitFunc) gtk_cell_renderer_text_class_init,
111         NULL,           /* class_finalize */
112         NULL,           /* class_data */
113         sizeof (GtkCellRendererText),
114         0,              /* n_preallocs */
115         (GInstanceInitFunc) gtk_cell_renderer_text_init,
116       };
117
118       cell_text_type = g_type_register_static (GTK_TYPE_CELL_RENDERER, "GtkCellRendererText", &cell_text_info, 0);
119     }
120
121   return cell_text_type;
122 }
123
124 static void
125 gtk_cell_renderer_text_init (GtkCellRendererText *celltext)
126 {
127   GTK_CELL_RENDERER (celltext)->xalign = 0.0;
128   GTK_CELL_RENDERER (celltext)->yalign = 0.5;
129   GTK_CELL_RENDERER (celltext)->xpad = 2;
130   GTK_CELL_RENDERER (celltext)->ypad = 2;
131
132   celltext->fixed_height_rows = -1;
133   celltext->font = pango_font_description_new ();
134 }
135
136 static void
137 gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class)
138 {
139   GObjectClass *object_class = G_OBJECT_CLASS (class);
140   GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
141
142   parent_class = g_type_class_peek_parent (class);
143   
144   object_class->finalize = gtk_cell_renderer_text_finalize;
145   
146   object_class->get_property = gtk_cell_renderer_text_get_property;
147   object_class->set_property = gtk_cell_renderer_text_set_property;
148
149   cell_class->get_size = gtk_cell_renderer_text_get_size;
150   cell_class->render = gtk_cell_renderer_text_render;
151
152   g_object_class_install_property (object_class,
153                                    PROP_TEXT,
154                                    g_param_spec_string ("text",
155                                                         _("Text"),
156                                                         _("Text to render"),
157                                                         NULL,
158                                                         G_PARAM_READWRITE));
159   
160   g_object_class_install_property (object_class,
161                                    PROP_MARKUP,
162                                    g_param_spec_string ("markup",
163                                                         _("Markup"),
164                                                         _("Marked up text to render"),
165                                                         NULL,
166                                                         G_PARAM_WRITABLE));
167
168   g_object_class_install_property (object_class,
169                                    PROP_ATTRIBUTES,
170                                    g_param_spec_boxed ("attributes",
171                                                        _("Attributes"),
172                                                        _("A list of style attributes to apply to the text of the renderer."),
173                                                        PANGO_TYPE_ATTR_LIST,
174                                                        G_PARAM_READWRITE));
175   
176   g_object_class_install_property (object_class,
177                                    PROP_BACKGROUND,
178                                    g_param_spec_string ("background",
179                                                         _("Background color name"),
180                                                         _("Background color as a string"),
181                                                         NULL,
182                                                         G_PARAM_WRITABLE));
183
184   g_object_class_install_property (object_class,
185                                    PROP_BACKGROUND_GDK,
186                                    g_param_spec_boxed ("background_gdk",
187                                                        _("Background color"),
188                                                        _("Background color as a GdkColor"),
189                                                        GDK_TYPE_COLOR,
190                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));  
191
192   g_object_class_install_property (object_class,
193                                    PROP_FOREGROUND,
194                                    g_param_spec_string ("foreground",
195                                                         _("Foreground color name"),
196                                                         _("Foreground color as a string"),
197                                                         NULL,
198                                                         G_PARAM_WRITABLE));
199
200   g_object_class_install_property (object_class,
201                                    PROP_FOREGROUND_GDK,
202                                    g_param_spec_boxed ("foreground_gdk",
203                                                        _("Foreground color"),
204                                                        _("Foreground color as a GdkColor"),
205                                                        GDK_TYPE_COLOR,
206                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
207
208
209   g_object_class_install_property (object_class,
210                                    PROP_EDITABLE,
211                                    g_param_spec_boolean ("editable",
212                                                          _("Editable"),
213                                                          _("Whether the text can be modified by the user"),
214                                                          TRUE,
215                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
216
217   g_object_class_install_property (object_class,
218                                    PROP_FONT,
219                                    g_param_spec_string ("font",
220                                                         _("Font"),
221                                                         _("Font description as a string"),
222                                                         NULL,
223                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));
224
225   g_object_class_install_property (object_class,
226                                    PROP_FONT_DESC,
227                                    g_param_spec_boxed ("font_desc",
228                                                        _("Font"),
229                                                        _("Font description as a PangoFontDescription struct"),
230                                                        PANGO_TYPE_FONT_DESCRIPTION,
231                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
232
233   
234   g_object_class_install_property (object_class,
235                                    PROP_FAMILY,
236                                    g_param_spec_string ("family",
237                                                         _("Font family"),
238                                                         _("Name of the font family, e.g. Sans, Helvetica, Times, Monospace"),
239                                                         NULL,
240                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));
241
242   g_object_class_install_property (object_class,
243                                    PROP_STYLE,
244                                    g_param_spec_enum ("style",
245                                                       _("Font style"),
246                                                       _("Font style"),
247                                                       PANGO_TYPE_STYLE,
248                                                       PANGO_STYLE_NORMAL,
249                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
250
251   g_object_class_install_property (object_class,
252                                    PROP_VARIANT,
253                                    g_param_spec_enum ("variant",
254                                                      _("Font variant"),
255                                                      _("Font variant"),
256                                                       PANGO_TYPE_VARIANT,
257                                                       PANGO_VARIANT_NORMAL,
258                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
259   
260   g_object_class_install_property (object_class,
261                                    PROP_WEIGHT,
262                                    g_param_spec_int ("weight",
263                                                      _("Font weight"),
264                                                      _("Font weight"),
265                                                      0,
266                                                      G_MAXINT,
267                                                      PANGO_WEIGHT_NORMAL,
268                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
269   
270
271   g_object_class_install_property (object_class,
272                                    PROP_STRETCH,
273                                    g_param_spec_enum ("stretch",
274                                                       _("Font stretch"),
275                                                       _("Font stretch"),
276                                                       PANGO_TYPE_STRETCH,
277                                                       PANGO_STRETCH_NORMAL,
278                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
279   
280   g_object_class_install_property (object_class,
281                                    PROP_SIZE,
282                                    g_param_spec_int ("size",
283                                                      _("Font size"),
284                                                      _("Font size"),
285                                                      0,
286                                                      G_MAXINT,
287                                                      0,
288                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
289
290   g_object_class_install_property (object_class,
291                                    PROP_SIZE_POINTS,
292                                    g_param_spec_double ("size_points",
293                                                         _("Font points"),
294                                                         _("Font size in points"),
295                                                         0.0,
296                                                         G_MAXDOUBLE,
297                                                         0.0,
298                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));  
299
300   g_object_class_install_property (object_class,
301                                    PROP_SCALE,
302                                    g_param_spec_double ("scale",
303                                                         _("Font scale"),
304                                                         _("Font scaling factor"),
305                                                         0.0,
306                                                         G_MAXDOUBLE,
307                                                         1.0,
308                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));
309   
310   g_object_class_install_property (object_class,
311                                    PROP_RISE,
312                                    g_param_spec_int ("rise",
313                                                      _("Rise"),
314                                                      _("Offset of text above the baseline (below the baseline if rise is negative)"),
315                                                      -G_MAXINT,
316                                                      G_MAXINT,
317                                                      0,
318                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
319
320
321   g_object_class_install_property (object_class,
322                                    PROP_STRIKETHROUGH,
323                                    g_param_spec_boolean ("strikethrough",
324                                                          _("Strikethrough"),
325                                                          _("Whether to strike through the text"),
326                                                          FALSE,
327                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
328   
329   g_object_class_install_property (object_class,
330                                    PROP_UNDERLINE,
331                                    g_param_spec_enum ("underline",
332                                                       _("Underline"),
333                                                       _("Style of underline for this text"),
334                                                       PANGO_TYPE_UNDERLINE,
335                                                       PANGO_UNDERLINE_NONE,
336                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
337
338   /* Style props are set or not */
339
340 #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))
341
342   ADD_SET_PROP ("background_set", PROP_BACKGROUND_SET,
343                 _("Background set"),
344                 _("Whether this tag affects the background color"));
345
346   ADD_SET_PROP ("foreground_set", PROP_FOREGROUND_SET,
347                 _("Foreground set"),
348                 _("Whether this tag affects the foreground color"));
349   
350   ADD_SET_PROP ("editable_set", PROP_EDITABLE_SET,
351                 _("Editability set"),
352                 _("Whether this tag affects text editability"));
353
354   ADD_SET_PROP ("family_set", PROP_FAMILY_SET,
355                 _("Font family set"),
356                 _("Whether this tag affects the font family"));  
357
358   ADD_SET_PROP ("style_set", PROP_STYLE_SET,
359                 _("Font style set"),
360                 _("Whether this tag affects the font style"));
361
362   ADD_SET_PROP ("variant_set", PROP_VARIANT_SET,
363                 _("Font variant set"),
364                 _("Whether this tag affects the font variant"));
365
366   ADD_SET_PROP ("weight_set", PROP_WEIGHT_SET,
367                 _("Font weight set"),
368                 _("Whether this tag affects the font weight"));
369
370   ADD_SET_PROP ("stretch_set", PROP_STRETCH_SET,
371                 _("Font stretch set"),
372                 _("Whether this tag affects the font stretch"));
373
374   ADD_SET_PROP ("size_set", PROP_SIZE_SET,
375                 _("Font size set"),
376                 _("Whether this tag affects the font size"));
377
378   ADD_SET_PROP ("scale_set", PROP_SCALE_SET,
379                 _("Font scale set"),
380                 _("Whether this tag scales the font size by a factor"));
381   
382   ADD_SET_PROP ("rise_set", PROP_RISE_SET,
383                 _("Rise set"),
384                 _("Whether this tag affects the rise"));
385
386   ADD_SET_PROP ("strikethrough_set", PROP_STRIKETHROUGH_SET,
387                 _("Strikethrough set"),
388                 _("Whether this tag affects strikethrough"));
389
390   ADD_SET_PROP ("underline_set", PROP_UNDERLINE_SET,
391                 _("Underline set"),
392                 _("Whether this tag affects underlining"));
393 }
394
395 static void
396 gtk_cell_renderer_text_finalize (GObject *object)
397 {
398   GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (object);
399
400   pango_font_description_free (celltext->font);
401
402   if (celltext->text)
403     g_free (celltext->text);
404
405   if (celltext->extra_attrs)
406     pango_attr_list_unref (celltext->extra_attrs);
407
408   (* G_OBJECT_CLASS (parent_class)->finalize) (object);
409 }
410
411 static PangoFontMask
412 get_property_font_set_mask (guint prop_id)
413 {
414   switch (prop_id)
415     {
416     case PROP_FAMILY_SET:
417       return PANGO_FONT_MASK_FAMILY;
418     case PROP_STYLE_SET:
419       return PANGO_FONT_MASK_STYLE;
420     case PROP_VARIANT_SET:
421       return PANGO_FONT_MASK_VARIANT;
422     case PROP_WEIGHT_SET:
423       return PANGO_FONT_MASK_WEIGHT;
424     case PROP_STRETCH_SET:
425       return PANGO_FONT_MASK_STRETCH;
426     case PROP_SIZE_SET:
427       return PANGO_FONT_MASK_SIZE;
428     }
429
430   return 0;
431 }
432
433 static void
434 gtk_cell_renderer_text_get_property (GObject        *object,
435                                      guint           param_id,
436                                      GValue         *value,
437                                      GParamSpec     *pspec)
438 {
439   GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (object);
440
441   switch (param_id)
442     {
443     case PROP_TEXT:
444       g_value_set_string (value, celltext->text);
445       break;
446
447     case PROP_ATTRIBUTES:
448       g_value_set_boxed (value, celltext->extra_attrs);
449       break;
450
451     case PROP_BACKGROUND_GDK:
452       {
453         GdkColor color;
454         
455         color.red = celltext->background.red;
456         color.green = celltext->background.green;
457         color.blue = celltext->background.blue;
458         
459         g_value_set_boxed (value, &color);
460       }
461       break;
462
463     case PROP_FOREGROUND_GDK:
464       {
465         GdkColor color;
466         
467         color.red = celltext->foreground.red;
468         color.green = celltext->foreground.green;
469         color.blue = celltext->foreground.blue;
470         
471         g_value_set_boxed (value, &color);
472       }
473       break;
474
475     case PROP_FONT:
476       {
477         /* FIXME GValue imposes a totally gratuitous string copy
478          * here, we could just hand off string ownership
479          */
480         gchar *str = pango_font_description_to_string (celltext->font);
481         g_value_set_string (value, str);
482         g_free (str);
483       }
484       break;
485       
486     case PROP_FONT_DESC:
487       g_value_set_boxed (value, celltext->font);
488       break;
489
490     case PROP_FAMILY:
491       g_value_set_string (value, pango_font_description_get_family (celltext->font));
492       break;
493
494     case PROP_STYLE:
495       g_value_set_enum (value, pango_font_description_get_style (celltext->font));
496       break;
497
498     case PROP_VARIANT:
499       g_value_set_enum (value, pango_font_description_get_variant (celltext->font));
500       break;
501
502     case PROP_WEIGHT:
503       g_value_set_int (value, pango_font_description_get_weight (celltext->font));
504       break;
505
506     case PROP_STRETCH:
507       g_value_set_enum (value, pango_font_description_get_stretch (celltext->font));
508       break;
509
510     case PROP_SIZE:
511       g_value_set_int (value, pango_font_description_get_size (celltext->font));
512       break;
513
514     case PROP_SIZE_POINTS:
515       g_value_set_double (value, ((double)pango_font_description_get_size (celltext->font)) / (double)PANGO_SCALE);
516       break;
517
518     case PROP_SCALE:
519       g_value_set_double (value, celltext->font_scale);
520       break;
521       
522     case PROP_EDITABLE:
523       g_value_set_boolean (value, celltext->editable);
524       break;
525
526     case PROP_STRIKETHROUGH:
527       g_value_set_boolean (value, celltext->strikethrough);
528       break;
529
530     case PROP_UNDERLINE:
531       g_value_set_enum (value, celltext->underline_style);
532       break;
533
534     case PROP_RISE:
535       g_value_set_int (value, celltext->rise);
536       break;  
537
538     case PROP_BACKGROUND_SET:
539       g_value_set_boolean (value, celltext->background_set);
540       break;
541
542     case PROP_FOREGROUND_SET:
543       g_value_set_boolean (value, celltext->foreground_set);
544       break;
545
546     case PROP_FAMILY_SET:
547     case PROP_STYLE_SET:
548     case PROP_VARIANT_SET:
549     case PROP_WEIGHT_SET:
550     case PROP_STRETCH_SET:
551     case PROP_SIZE_SET:
552       {
553         PangoFontMask mask = get_property_font_set_mask (param_id);
554         g_value_set_boolean (value, (pango_font_description_get_set_fields (celltext->font) & mask) != 0);
555       }
556
557     case PROP_SCALE_SET:
558       g_value_set_boolean (value, celltext->scale_set);
559       break;
560       
561     case PROP_EDITABLE_SET:
562       g_value_set_boolean (value, celltext->editable_set);
563       break;
564
565     case PROP_STRIKETHROUGH_SET:
566       g_value_set_boolean (value, celltext->strikethrough_set);
567       break;
568
569     case PROP_UNDERLINE_SET:
570       g_value_set_boolean (value, celltext->underline_set);
571       break;
572
573     case  PROP_RISE_SET:
574       g_value_set_boolean (value, celltext->rise_set);
575       break;
576       
577     case PROP_BACKGROUND:
578     case PROP_FOREGROUND:
579     case PROP_MARKUP:
580     default:
581       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
582       break;
583     }
584 }
585
586
587 static void
588 set_bg_color (GtkCellRendererText *celltext,
589               GdkColor            *color)
590 {
591   if (color)
592     {
593       if (!celltext->background_set)
594         {
595           celltext->background_set = TRUE;
596           g_object_notify (G_OBJECT (celltext), "background_set");
597         }
598       
599       celltext->background.red = color->red;
600       celltext->background.green = color->green;
601       celltext->background.blue = color->blue;
602     }
603   else
604     {
605       if (celltext->background_set)
606         {
607           celltext->background_set = FALSE;
608           g_object_notify (G_OBJECT (celltext), "background_set");
609         }
610     }
611 }
612
613
614 static void
615 set_fg_color (GtkCellRendererText *celltext,
616               GdkColor            *color)
617 {
618   if (color)
619     {
620       if (!celltext->foreground_set)
621         {
622           celltext->foreground_set = TRUE;
623           g_object_notify (G_OBJECT (celltext), "foreground_set");
624         }
625       
626       celltext->foreground.red = color->red;
627       celltext->foreground.green = color->green;
628       celltext->foreground.blue = color->blue;
629     }
630   else
631     {
632       if (celltext->foreground_set)
633         {
634           celltext->foreground_set = FALSE;
635           g_object_notify (G_OBJECT (celltext), "foreground_set");
636         }
637     }
638 }
639
640 static void
641 notify_set_changed (GObject       *object,
642                     PangoFontMask  changed_mask)
643 {
644   if (changed_mask & PANGO_FONT_MASK_FAMILY)
645     g_object_notify (object, "family_set");
646   if (changed_mask & PANGO_FONT_MASK_STYLE)
647     g_object_notify (object, "style_set");
648   if (changed_mask & PANGO_FONT_MASK_VARIANT)
649     g_object_notify (object, "variant_set");
650   if (changed_mask & PANGO_FONT_MASK_WEIGHT)
651     g_object_notify (object, "weight_set");
652   if (changed_mask & PANGO_FONT_MASK_STRETCH)
653     g_object_notify (object, "stretch_set");
654   if (changed_mask & PANGO_FONT_MASK_SIZE)
655     g_object_notify (object, "size_set");
656 }
657
658 static void
659 set_font_description (GtkCellRendererText  *celltext,
660                       PangoFontDescription *font_desc)
661 {
662   GObject *object = G_OBJECT (celltext);
663   PangoFontDescription *new_font_desc;
664   PangoFontMask old_mask, new_mask, changed_mask, set_changed_mask;
665   
666   if (font_desc)
667     new_font_desc = pango_font_description_copy (font_desc);
668   else
669     new_font_desc = pango_font_description_new ();
670
671   old_mask = pango_font_description_get_set_fields (celltext->font);
672   new_mask = pango_font_description_get_set_fields (new_font_desc);
673
674   changed_mask = old_mask | new_mask;
675   set_changed_mask = old_mask ^ new_mask;
676
677   pango_font_description_free (celltext->font);
678   celltext->font = new_font_desc;
679   
680   g_object_freeze_notify (object);
681
682   g_object_notify (object, "font_desc");
683   g_object_notify (object, "font");
684   
685   if (changed_mask & PANGO_FONT_MASK_FAMILY)
686     g_object_notify (object, "family");
687   if (changed_mask & PANGO_FONT_MASK_STYLE)
688     g_object_notify (object, "style");
689   if (changed_mask & PANGO_FONT_MASK_VARIANT)
690     g_object_notify (object, "variant");
691   if (changed_mask & PANGO_FONT_MASK_WEIGHT)
692     g_object_notify (object, "weight");
693   if (changed_mask & PANGO_FONT_MASK_STRETCH)
694     g_object_notify (object, "stretch");
695   if (changed_mask & PANGO_FONT_MASK_SIZE)
696     {
697       g_object_notify (object, "size");
698       g_object_notify (object, "size_points");
699     }
700
701   notify_set_changed (object, set_changed_mask);
702   
703   g_object_thaw_notify (object);
704 }
705
706 static void
707 gtk_cell_renderer_text_set_property (GObject      *object,
708                                      guint         param_id,
709                                      const GValue *value,
710                                      GParamSpec   *pspec)
711 {
712   GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (object);
713
714   switch (param_id)
715     {
716     case PROP_TEXT:
717       if (celltext->text)
718         g_free (celltext->text);
719       celltext->text = g_strdup (g_value_get_string (value));
720       g_object_notify (object, "text");
721       break;
722
723     case PROP_ATTRIBUTES:
724       if (celltext->extra_attrs)
725         pango_attr_list_unref (celltext->extra_attrs);
726
727       celltext->extra_attrs = g_value_get_boxed (value);
728       if (celltext->extra_attrs)
729         pango_attr_list_ref (celltext->extra_attrs);
730       break;
731     case PROP_MARKUP:
732       {
733         const gchar *str;
734         gchar *text = NULL;
735         GError *error = NULL;
736         PangoAttrList *attrs = NULL;
737         
738         if (celltext->text)
739           g_free (celltext->text);
740
741         if (celltext->extra_attrs)
742           pango_attr_list_unref (celltext->extra_attrs);
743
744         str = g_value_get_string (value);
745         if (str && !pango_parse_markup (str,
746                                         -1,
747                                         0,
748                                         &attrs,
749                                         &text,
750                                         NULL,
751                                         &error))
752           {
753             g_warning ("Failed to set cell text from markup due to error parsing markup: %s",
754                        error->message);
755             g_error_free (error);
756             return;
757           }
758         
759         celltext->text = text;
760         celltext->extra_attrs = attrs;
761       }
762       break;
763       
764     case PROP_BACKGROUND:
765       {
766         GdkColor color;
767
768         if (!g_value_get_string (value))
769           set_bg_color (celltext, NULL);       /* reset to backgrounmd_set to FALSE */
770         else if (gdk_color_parse (g_value_get_string (value), &color))
771           set_bg_color (celltext, &color);
772         else
773           g_warning ("Don't know color `%s'", g_value_get_string (value));
774
775         g_object_notify (object, "background_gdk");
776       }
777       break;
778       
779     case PROP_FOREGROUND:
780       {
781         GdkColor color;
782
783         if (!g_value_get_string (value))
784           set_fg_color (celltext, NULL);       /* reset to foreground_set to FALSE */
785         else if (gdk_color_parse (g_value_get_string (value), &color))
786           set_fg_color (celltext, &color);
787         else
788           g_warning ("Don't know color `%s'", g_value_get_string (value));
789
790         g_object_notify (object, "foreground_gdk");
791       }
792       break;
793
794     case PROP_BACKGROUND_GDK:
795       /* This notifies the GObject itself. */
796       set_bg_color (celltext, g_value_get_boxed (value));
797       break;
798
799     case PROP_FOREGROUND_GDK:
800       /* This notifies the GObject itself. */
801       set_fg_color (celltext, g_value_get_boxed (value));
802       break;
803
804     case PROP_FONT:
805       {
806         PangoFontDescription *font_desc = NULL;
807         const gchar *name;
808
809         name = g_value_get_string (value);
810
811         if (name)
812           font_desc = pango_font_description_from_string (name);
813
814         set_font_description (celltext, font_desc);
815         
816         if (celltext->fixed_height_rows != -1)
817           celltext->calc_fixed_height = TRUE;
818       }
819       break;
820
821     case PROP_FONT_DESC:
822       set_font_description (celltext, g_value_get_boxed (value));
823       
824       if (celltext->fixed_height_rows != -1)
825         celltext->calc_fixed_height = TRUE;
826       break;
827
828     case PROP_FAMILY:
829     case PROP_STYLE:
830     case PROP_VARIANT:
831     case PROP_WEIGHT:
832     case PROP_STRETCH:
833     case PROP_SIZE:
834     case PROP_SIZE_POINTS:
835       {
836         PangoFontMask old_set_mask = pango_font_description_get_set_fields (celltext->font);
837         
838         switch (param_id)
839           {
840           case PROP_FAMILY:
841             pango_font_description_set_family (celltext->font,
842                                                g_value_get_string (value));
843             break;
844           case PROP_STYLE:
845             pango_font_description_set_style (celltext->font,
846                                               g_value_get_enum (value));
847             break;
848           case PROP_VARIANT:
849             pango_font_description_set_variant (celltext->font,
850                                                 g_value_get_enum (value));
851             break;
852           case PROP_WEIGHT:
853             pango_font_description_set_weight (celltext->font,
854                                                g_value_get_enum (value));
855             break;
856           case PROP_STRETCH:
857             pango_font_description_set_stretch (celltext->font,
858                                                 g_value_get_enum (value));
859             break;
860           case PROP_SIZE:
861             pango_font_description_set_size (celltext->font,
862                                              g_value_get_int (value));
863             g_object_notify (object, "size_points");
864             break;
865           case PROP_SIZE_POINTS:
866             pango_font_description_set_size (celltext->font,
867                                              g_value_get_double (value) * PANGO_SCALE);
868             g_object_notify (object, "size");
869             break;
870           }
871         
872         if (celltext->fixed_height_rows != -1)
873           celltext->calc_fixed_height = TRUE;
874         
875         notify_set_changed (object, old_set_mask & pango_font_description_get_set_fields (celltext->font));
876         g_object_notify (object, "font_desc");
877         g_object_notify (object, "font");
878       }
879       
880     case PROP_SCALE:
881       celltext->font_scale = g_value_get_double (value);
882       celltext->scale_set = TRUE;
883       if (celltext->fixed_height_rows != -1)
884         celltext->calc_fixed_height = TRUE;
885       g_object_notify (object, "scale_set");
886       break;
887       
888     case PROP_EDITABLE:
889       celltext->editable = g_value_get_boolean (value);
890       celltext->editable_set = TRUE;
891       g_object_notify (object, "editable_set");
892       break;
893
894     case PROP_STRIKETHROUGH:
895       celltext->strikethrough = g_value_get_boolean (value);
896       celltext->strikethrough_set = TRUE;
897       g_object_notify (object, "strikethrough_set");
898       break;
899
900     case PROP_UNDERLINE:
901       celltext->underline_style = g_value_get_enum (value);
902       celltext->underline_set = TRUE;
903       g_object_notify (object, "underline_set");
904             
905       break;
906
907     case PROP_RISE:
908       celltext->rise = g_value_get_int (value);
909       celltext->rise_set = TRUE;
910       g_object_notify (object, "rise_set");
911       if (celltext->fixed_height_rows != -1)
912         celltext->calc_fixed_height = TRUE;
913       break;  
914
915     case PROP_BACKGROUND_SET:
916       celltext->background_set = g_value_get_boolean (value);
917       break;
918
919     case PROP_FOREGROUND_SET:
920       celltext->foreground_set = g_value_get_boolean (value);
921       break;
922
923     case PROP_FAMILY_SET:
924     case PROP_STYLE_SET:
925     case PROP_VARIANT_SET:
926     case PROP_WEIGHT_SET:
927     case PROP_STRETCH_SET:
928     case PROP_SIZE_SET:
929       if (!g_value_get_boolean (value))
930         pango_font_description_unset_fields (celltext->font,
931                                              get_property_font_set_mask (param_id));
932       break;
933
934     case PROP_SCALE_SET:
935       celltext->scale_set = g_value_get_boolean (value);
936       break;
937       
938     case PROP_EDITABLE_SET:
939       celltext->editable_set = g_value_get_boolean (value);
940       break;
941
942     case PROP_STRIKETHROUGH_SET:
943       celltext->strikethrough_set = g_value_get_boolean (value);
944       break;
945
946     case PROP_UNDERLINE_SET:
947       celltext->underline_set = g_value_get_boolean (value);
948       break;
949
950     case PROP_RISE_SET:
951       celltext->rise_set = g_value_get_boolean (value);
952       break;
953
954     default:
955       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
956       break;
957     }
958 }
959
960 /**
961  * gtk_cell_renderer_text_new:
962  * 
963  * Creates a new #GtkCellRendererText. Adjust how text is drawn using
964  * object properties. Object properties can be
965  * set globally (with g_object_set()). Also, with #GtkTreeViewColumn,
966  * you can bind a property to a value in a #GtkTreeModel. For example,
967  * you can bind the "text" property on the cell renderer to a string
968  * value in the model, thus rendering a different string in each row
969  * of the #GtkTreeView
970  * 
971  * Return value: the new cell renderer
972  **/
973 GtkCellRenderer *
974 gtk_cell_renderer_text_new (void)
975 {
976   return GTK_CELL_RENDERER (g_object_new (gtk_cell_renderer_text_get_type (), NULL));
977 }
978
979 static void
980 add_attr (PangoAttrList  *attr_list,
981           PangoAttribute *attr)
982 {
983   attr->start_index = 0;
984   attr->end_index = G_MAXINT;
985   
986   pango_attr_list_insert (attr_list, attr);
987 }
988
989 static PangoLayout*
990 get_layout (GtkCellRendererText *celltext,
991             GtkWidget           *widget,
992             gboolean             will_render,
993             GtkCellRendererState flags)
994 {
995   PangoAttrList *attr_list;
996   PangoLayout *layout;
997   PangoUnderline uline;
998   
999   layout = gtk_widget_create_pango_layout (widget, celltext->text);
1000
1001   if (celltext->extra_attrs)
1002     attr_list = pango_attr_list_copy (celltext->extra_attrs);
1003   else
1004     attr_list = pango_attr_list_new ();
1005
1006   if (will_render)
1007     {
1008       /* Add options that affect appearance but not size */
1009       
1010       /* note that background doesn't go here, since it affects
1011        * background_area not the PangoLayout area
1012        */
1013       
1014       if (celltext->foreground_set)
1015         {
1016           PangoColor color;
1017
1018           color = celltext->foreground;
1019           
1020           add_attr (attr_list,
1021                     pango_attr_foreground_new (color.red, color.green, color.blue));
1022         }
1023
1024       if (celltext->strikethrough_set)
1025         add_attr (attr_list,
1026                   pango_attr_strikethrough_new (celltext->strikethrough));
1027     }
1028
1029   add_attr (attr_list, pango_attr_font_desc_new (celltext->font));
1030
1031   if (celltext->scale_set &&
1032       celltext->font_scale != 1.0)
1033     add_attr (attr_list, pango_attr_scale_new (celltext->font_scale));
1034   
1035   if (celltext->underline_set)
1036     uline = celltext->underline_style;
1037   else
1038     uline = PANGO_UNDERLINE_NONE;
1039   
1040   if ((flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT)
1041     {
1042       switch (uline)
1043         {
1044         case PANGO_UNDERLINE_NONE:
1045           uline = PANGO_UNDERLINE_SINGLE;
1046           break;
1047
1048         case PANGO_UNDERLINE_SINGLE:
1049           uline = PANGO_UNDERLINE_DOUBLE;
1050           break;
1051
1052         default:
1053           break;
1054         }
1055     }
1056
1057   if (uline != PANGO_UNDERLINE_NONE)
1058     add_attr (attr_list, pango_attr_underline_new (celltext->underline_style));
1059
1060   if (celltext->rise_set)
1061     add_attr (attr_list, pango_attr_rise_new (celltext->rise));
1062   
1063   pango_layout_set_attributes (layout, attr_list);
1064   pango_layout_set_width (layout, -1);
1065
1066   pango_attr_list_unref (attr_list);
1067   
1068   return layout;
1069 }
1070
1071 static void
1072 gtk_cell_renderer_text_get_size (GtkCellRenderer *cell,
1073                                  GtkWidget       *widget,
1074                                  GdkRectangle    *cell_area,
1075                                  gint            *x_offset,
1076                                  gint            *y_offset,
1077                                  gint            *width,
1078                                  gint            *height)
1079 {
1080   GtkCellRendererText *celltext = (GtkCellRendererText *) cell;
1081   PangoRectangle rect;
1082   PangoLayout *layout;
1083
1084   if (celltext->calc_fixed_height)
1085     {
1086       PangoContext *context;
1087       PangoFontMetrics *metrics;
1088       PangoFontDescription *font_desc;
1089       gint row_height;
1090
1091       font_desc = pango_font_description_copy (widget->style->font_desc);
1092       pango_font_description_merge (font_desc, celltext->font, TRUE);
1093
1094       if (celltext->scale_set)
1095         pango_font_description_set_size (font_desc,
1096                                          celltext->font_scale * pango_font_description_get_size (font_desc));
1097
1098       context = gtk_widget_get_pango_context (widget);
1099
1100       metrics = pango_context_get_metrics (context,
1101                                            font_desc,
1102                                            pango_context_get_language (context));
1103       row_height = (pango_font_metrics_get_ascent (metrics) +
1104                     pango_font_metrics_get_descent (metrics));
1105       pango_font_metrics_unref (metrics);
1106       
1107       gtk_cell_renderer_set_fixed_size (cell,
1108                                         cell->width, 2*cell->ypad +
1109                                         celltext->fixed_height_rows * PANGO_PIXELS (row_height));
1110       
1111       if (height)
1112         {
1113           *height = cell->height;
1114           height = NULL;
1115         }
1116       celltext->calc_fixed_height = FALSE;
1117       if (width == NULL)
1118         return;
1119     }
1120   layout = get_layout (celltext, widget, FALSE, 0);
1121   pango_layout_get_pixel_extents (layout, NULL, &rect);
1122
1123   if (width)
1124     *width = GTK_CELL_RENDERER (celltext)->xpad * 2 + rect.width;
1125
1126   if (height)
1127     *height = GTK_CELL_RENDERER (celltext)->ypad * 2 + rect.height;
1128
1129   if (cell_area)
1130     {
1131       if (x_offset)
1132         {
1133           *x_offset = cell->xalign * (cell_area->width - rect.width - (2 * cell->xpad));
1134           *x_offset = MAX (*x_offset, 0) + cell->xpad;
1135         }
1136       if (y_offset)
1137         {
1138           *y_offset = cell->yalign * (cell_area->height - rect.height - (2 * cell->ypad));
1139           *y_offset = MAX (*y_offset, 0) + cell->ypad;
1140         }
1141     }
1142
1143   g_object_unref (G_OBJECT (layout));
1144 }
1145
1146 static void
1147 gtk_cell_renderer_text_render (GtkCellRenderer    *cell,
1148                                GdkWindow          *window,
1149                                GtkWidget          *widget,
1150                                GdkRectangle       *background_area,
1151                                GdkRectangle       *cell_area,
1152                                GdkRectangle       *expose_area,
1153                                guint               flags)
1154
1155 {
1156   GtkCellRendererText *celltext = (GtkCellRendererText *) cell;
1157   PangoLayout *layout;
1158   GtkStateType state;
1159   gint x_offset;
1160   gint y_offset;
1161
1162   layout = get_layout (celltext, widget, TRUE, flags);
1163
1164   gtk_cell_renderer_text_get_size (cell, widget, cell_area, &x_offset, &y_offset, NULL, NULL);
1165
1166   if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED)
1167     {
1168       if (GTK_WIDGET_HAS_FOCUS (widget))
1169         state = GTK_STATE_SELECTED;
1170       else
1171         state = GTK_STATE_ACTIVE;
1172     }
1173   else
1174     {
1175       state = GTK_STATE_NORMAL;
1176     }
1177
1178   if (celltext->background_set && state != GTK_STATE_SELECTED)
1179     {
1180       GdkColor color;
1181       GdkGC *gc;
1182       
1183       color.red = celltext->background.red;
1184       color.green = celltext->background.green;
1185       color.blue = celltext->background.blue;
1186
1187       gc = gdk_gc_new (window);
1188
1189       gdk_gc_set_rgb_fg_color (gc, &color);
1190       
1191       gdk_draw_rectangle (window,
1192                           gc,
1193                           TRUE,
1194                           background_area->x,
1195                           background_area->y,
1196                           background_area->width,
1197                           background_area->height);
1198
1199       g_object_unref (G_OBJECT (gc));
1200     }
1201   
1202   gtk_paint_layout (widget->style,
1203                     window,
1204                     state,
1205                     TRUE,
1206                     cell_area,
1207                     widget,
1208                     "cellrenderertext",
1209                     cell_area->x + x_offset,
1210                     cell_area->y + y_offset,
1211                     layout);
1212
1213   g_object_unref (G_OBJECT (layout));
1214 }
1215
1216 /**
1217  * gtk_cell_renderer_text_set_fixed_height_from_font:
1218  * @renderer: A #GtkCellRendererText
1219  * @number_of_rows: Number of rows of text each cell renderer is allocated, or -1
1220  * 
1221  * Sets the height of a renderer to explicitly be determined by the "font" and
1222  * "y_pad" property set on it.  Further changes in these properties do not
1223  * affect the height, so they must be accompanied by a subsequent call to this
1224  * function.  Using this function is unflexible, and should really only be used
1225  * if calculating the size of a cell is too slow.  If @no_rows is -1, then the
1226  * fixed height is unset, and the height is determined by the properties again.
1227  **/
1228 void
1229 gtk_cell_renderer_text_set_fixed_height_from_font (GtkCellRendererText *renderer,
1230                                                    gint                 number_of_rows)
1231 {
1232   g_return_if_fail (GTK_IS_CELL_RENDERER_TEXT (renderer));
1233   g_return_if_fail (number_of_rows == -1 || number_of_rows > 0);
1234
1235   if (number_of_rows == -1)
1236     {
1237       gtk_cell_renderer_set_fixed_size (GTK_CELL_RENDERER (renderer),
1238                                         GTK_CELL_RENDERER (renderer)->width,
1239                                         -1);
1240     }
1241   else
1242     {
1243       renderer->fixed_height_rows = number_of_rows;
1244       renderer->calc_fixed_height = TRUE;
1245     }
1246 }