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