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