a3951aae0cc9e952cec7718023accf0eef245a27
[hildon] / src / hildon-font-selection-dialog.c
1 /*
2  * This file is part of hildon-libs
3  *
4  * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
5  *
6  * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; version 2.1 of
11  * the License.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24
25 /**
26  * SECTION:hildon-font-selection-dialog
27  * @short_description: A widget used to allow users to select a font 
28  * with certain properties
29  *
30  * Font selection can be made using this widget. Users can select font name, 
31  * size, style, etc. Users can also preview text in the selected font.
32  */
33  
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include <gtk/gtkstock.h>
38 #include <gtk/gtkcombobox.h>
39 #include <gtk/gtktogglebutton.h>
40 #include <gtk/gtkcheckbutton.h>
41 #include <gtk/gtklabel.h>
42 #include <gtk/gtkvbox.h>
43 #include <gtk/gtkliststore.h>
44 #include <gtk/gtknotebook.h>
45 #include <gtk/gtk.h>
46 #include <glib.h>
47 #include <gdk/gdkkeysyms.h>
48
49 #include "hildon-font-selection-dialog.h"
50 #include <hildon-widgets/hildon-caption.h>
51 #include <hildon-widgets/hildon-color-selector.h>
52 #include <hildon-widgets/hildon-color-button.h>
53
54 #ifdef HAVE_CONFIG_H
55 #include <config.h>
56 #endif
57
58 #include <libintl.h>
59 #define _(String) dgettext(PACKAGE, String)
60
61 #define SUPERSCRIPT_RISE 3333
62 #define SUBSCRIPT_LOW   -3333
63 #define ON_BIT  0x01
64 #define OFF_BIT 0x02
65
66 /*
67  * These are what we use as the standard font sizes, for the size list.
68  */
69 static const guint16 font_sizes[] = 
70 {
71   6, 8, 10, 12, 16, 24, 32
72 };
73
74 #define HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(obj) \
75 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
76                               HILDON_TYPE_FONT_SELECTION_DIALOG, \
77                               HildonFontSelectionDialogPrivate))
78
79 /*None of designed api function works, so now it all comes down to 
80  *use properties to achieve what we are supposed to achieve*/
81 enum
82 {
83   PROP_FAMILY = 1,
84   PROP_FAMILY_SET,
85   PROP_SIZE,
86   PROP_SIZE_SET,
87   PROP_COLOR,
88   PROP_COLOR_SET,
89   PROP_BOLD,
90   PROP_BOLD_SET,
91   PROP_ITALIC,
92   PROP_ITALIC_SET,
93   PROP_UNDERLINE,
94   PROP_UNDERLINE_SET,
95   PROP_STRIKETHROUGH,
96   PROP_STRIKETHROUGH_SET,
97   PROP_POSITION,
98   PROP_POSITION_SET,
99   PROP_PREVIEW_TEXT,
100   PROP_FONT_SCALING
101 };
102
103 typedef struct
104 _HildonFontSelectionDialogPrivate HildonFontSelectionDialogPrivate;
105
106 struct _HildonFontSelectionDialogPrivate 
107 {  
108   GtkNotebook *notebook;
109
110   gchar *preview_text;
111
112   /*Tab one*/
113   GtkWidget *cbx_font_type;
114   GtkWidget *cbx_font_size;
115   GtkWidget *font_color_button;
116
117   /*Tab two*/
118   GtkWidget *chk_bold;
119   GtkWidget *chk_italic;
120   GtkWidget *chk_underline;
121
122   /*Tab three*/
123   GtkWidget *chk_strikethrough;
124   GtkWidget *cbx_positioning;
125
126   /*Every family*/
127   PangoFontFamily **families;
128   gint n_families;
129
130   /*color_set is used to show whether the color is inconsistent
131    * The handler id is used to block the signal emission
132    * when we change the color setting*/
133   
134   gboolean color_set;
135
136   /* font_scaling is the scaling factor applied to font
137    * scale in the preview dialog */
138
139   gdouble font_scaling;
140   gulong color_modified_signal_handler;
141 };
142
143 /*combo box active row indicator -2--inconsistent, -1--undefined 
144  * please make sure that you use settings_init settings_apply
145  * and settings_destroy, dont even try to touch this structure 
146  * without using the three above interface functions, of course
147  * if you know what you are doing, do as you please ;-)*/
148 typedef struct
149 {
150   HildonFontSelectionDialog
151                *fsd; /*pointer to our font selection dialog*/
152   
153   gint         family; /*combo box indicator*/
154   gint         size; /*combo box indicator*/
155   GdkColor     *color; /*free after read the setting*/
156   gboolean     color_inconsist;
157   gint         weight; /*bit mask*/
158   gint         style;  /*bit mask*/
159   gint         underline; /*bit mask*/
160   gint         strikethrough; /*bit mask*/
161   gint         position; /*combo box indicator*/
162
163 }HildonFontSelectionDialogSettings;
164
165 static gboolean
166               hildon_font_selection_dialog_preview_key_press
167                                             (GtkWidget * widget,
168                                              GdkEventKey * event,
169                                              gpointer unused);
170
171 /*Some tools from gtk_font_selection*/
172 static int    cmp_families                   (const void *a, const void *b);
173
174 static void   hildon_font_selection_dialog_show_preview
175                                              (HildonFontSelectionDialog 
176                                               *fontsel);
177                                              
178 static PangoAttrList*
179               hildon_font_selection_dialog_create_attrlist
180                                              (HildonFontSelectionDialog 
181                                               *fontsel, guint start_index,
182                                               guint len);
183
184 static void   hildon_font_selection_dialog_show_available_positionings
185                                              (HildonFontSelectionDialogPrivate
186                                               *priv);
187                                                  
188 static void   hildon_font_selection_dialog_show_available_fonts
189                                              (HildonFontSelectionDialog
190                                               *fontsel);
191                                                  
192 static void   hildon_font_selection_dialog_show_available_sizes
193                                              (HildonFontSelectionDialogPrivate
194                                               *priv);
195
196 static void   hildon_font_selection_dialog_class_init
197                                              (HildonFontSelectionDialogClass 
198                                               *klass);
199                                                  
200 static void   hildon_font_selection_dialog_init
201                                              (HildonFontSelectionDialog 
202                                               *fontseldiag);
203
204 static void   hildon_font_selection_dialog_finalize
205                                              (GObject * object);
206
207 static void   hildon_font_selection_dialog_construct_notebook  
208                                              (HildonFontSelectionDialog
209                                               *fontsel);
210                                              
211 static void   color_modified_cb              (HildonColorButton *button,
212                                               GParamSpec *pspec,
213                                               gpointer fsd_priv);
214
215 static void   check_tags                     (gpointer data,
216                                               gpointer user_data);
217
218 static void   settings_init                  (HildonFontSelectionDialogSettings
219                                               *setttings,
220                                               HildonFontSelectionDialog
221                                               *fsd);
222
223 static void   settings_apply                 (HildonFontSelectionDialogSettings
224                                               *setttings);
225
226 static void   settings_destroy               (HildonFontSelectionDialogSettings
227                                               *setttings);
228
229 static void   bit_mask_toggle                (gint mask, GtkToggleButton*
230                                               button, GObject *object, 
231                                               const gchar *prop, 
232                                               const gchar *prop_set);
233
234 static void   combo_active                   (gint active, GtkComboBox *box,
235                                               GObject *object, 
236                                               const gchar *prop,
237                                               const gchar *prop_set);
238
239 static void   add_preview_text_attr          (PangoAttrList *list, 
240                                               PangoAttribute *attr, 
241                                               guint start, 
242                                               guint len);
243
244 static void   toggle_clicked                 (GtkButton *button, 
245                                               gpointer unused);
246         
247                                              
248                                              
249 static GtkDialogClass *font_selection_dialog_parent_class = NULL;
250
251 GType hildon_font_selection_dialog_get_type(void)
252 {
253   static GType font_selection_dialog_type = 0;
254
255   if (!font_selection_dialog_type) {
256     static const GTypeInfo fontsel_diag_info = {
257       sizeof(HildonFontSelectionDialogClass),
258       NULL,       /* base_init */
259       NULL,       /* base_finalize */
260       (GClassInitFunc) hildon_font_selection_dialog_class_init,
261       NULL,       /* class_finalize */
262       NULL,       /* class_data */
263       sizeof(HildonFontSelectionDialog),
264       0,  /* n_preallocs */
265       (GInstanceInitFunc) hildon_font_selection_dialog_init,
266     };
267
268     font_selection_dialog_type =
269       g_type_register_static(GTK_TYPE_DIALOG,
270                              "HildonFontSelectionDialog",
271                              &fontsel_diag_info, 0);
272   }
273
274   return font_selection_dialog_type;
275 }
276
277 static void
278 hildon_font_selection_dialog_get_property (GObject      *object,
279                                            guint         prop_id,
280                                            GValue       *value,
281                                            GParamSpec   *pspec)
282 {
283   gint i;
284   GdkColor *color = NULL;
285   
286   HildonFontSelectionDialogPrivate *priv =
287     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(
288         HILDON_FONT_SELECTION_DIALOG(object));
289   
290   
291   switch (prop_id)
292     {
293     case PROP_FAMILY:
294       i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_font_type));
295       if(i >= 0 && i < priv->n_families)
296         g_value_set_string(value, 
297                            pango_font_family_get_name(priv->families[i]));
298       else
299         g_value_set_string(value, "Sans");
300       break;
301       
302     case PROP_FAMILY_SET:
303       i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_font_type));
304       if(i >= 0 && i < priv->n_families)
305         g_value_set_boolean(value, TRUE);
306       else
307         g_value_set_boolean(value, FALSE);
308       break;
309       
310     case PROP_SIZE:
311       i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_font_size));
312       if(i >= 0 && i < G_N_ELEMENTS(font_sizes))
313         g_value_set_int(value, font_sizes[i]);
314       else
315         g_value_set_int(value, 16);
316       break;
317       
318     case PROP_SIZE_SET:
319       i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_font_size));
320       if(i >= 0 && i < G_N_ELEMENTS(font_sizes))
321         g_value_set_boolean(value, TRUE);
322       else
323         g_value_set_boolean(value, FALSE);
324       break;
325
326     case PROP_COLOR:
327       color = hildon_color_button_get_color
328         (HILDON_COLOR_BUTTON(priv->font_color_button));
329       g_value_set_boxed(value, (gconstpointer) color);
330       if(color != NULL)
331         gdk_color_free(color);
332       break;
333       
334     case PROP_COLOR_SET:
335       g_value_set_boolean(value, priv->color_set);
336       break;
337
338     case PROP_BOLD:
339       g_value_set_boolean(value, 
340         gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->chk_bold)));
341       break;
342
343     case PROP_BOLD_SET:
344       g_value_set_boolean(value,
345         !gtk_toggle_button_get_inconsistent
346         (GTK_TOGGLE_BUTTON(priv->chk_bold)));
347       break;
348       
349     case PROP_ITALIC:
350       g_value_set_boolean(value, 
351         gtk_toggle_button_get_active
352         (GTK_TOGGLE_BUTTON(priv->chk_italic)));
353       break;
354
355     case PROP_ITALIC_SET:
356       g_value_set_boolean(value,
357         !gtk_toggle_button_get_inconsistent
358         (GTK_TOGGLE_BUTTON(priv->chk_italic)));
359       break;
360       
361     case PROP_UNDERLINE:
362       g_value_set_boolean(value, 
363         gtk_toggle_button_get_active
364         (GTK_TOGGLE_BUTTON(priv->chk_underline)));
365       break;
366
367     case PROP_UNDERLINE_SET:
368       g_value_set_boolean(value,
369         !gtk_toggle_button_get_inconsistent
370         (GTK_TOGGLE_BUTTON(priv->chk_underline)));
371       break;
372       
373     case PROP_STRIKETHROUGH:
374       g_value_set_boolean(value, 
375         gtk_toggle_button_get_active
376         (GTK_TOGGLE_BUTTON(priv->chk_strikethrough)));
377       break;
378
379     case PROP_STRIKETHROUGH_SET:
380       g_value_set_boolean(value,
381         !gtk_toggle_button_get_inconsistent
382         (GTK_TOGGLE_BUTTON(priv->chk_strikethrough)));
383       break;
384
385     case PROP_POSITION:
386       i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_positioning));
387       if(i == 1)/*super*/
388         g_value_set_int(value, 1);
389       else if(i == 2)/*sub*/
390         g_value_set_int(value, -1);
391       else
392         g_value_set_int(value, 0);
393       break;
394     
395     case PROP_FONT_SCALING:
396         g_value_set_double(value, priv->font_scaling);
397       break;
398   
399     case PROP_POSITION_SET:
400       i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_positioning));
401       if(i >= 0 && i < 3)
402         g_value_set_boolean(value, TRUE);
403       else
404         g_value_set_boolean(value, FALSE);
405       break;
406     
407     case PROP_PREVIEW_TEXT:
408         g_value_set_string(value,
409                 hildon_font_selection_dialog_get_preview_text(
410                     HILDON_FONT_SELECTION_DIALOG(object)));
411       break;
412     
413     default:
414       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
415       break;
416     }
417 }
418
419 static void 
420 hildon_font_selection_dialog_set_property (GObject         *object,
421                                            guint            prop_id,
422                                            const GValue    *value,
423                                            GParamSpec      *pspec)
424 {
425   gint i, size;
426   const gchar *str;
427   gboolean b;
428   GdkColor *color = NULL;
429   GdkColor black;
430   
431   HildonFontSelectionDialogPrivate *priv =
432     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(
433         HILDON_FONT_SELECTION_DIALOG(object));
434   black.red = black.green = black.blue = 0;
435   
436   switch (prop_id)
437     {
438     case PROP_FAMILY:
439       str = g_value_get_string(value);
440       for(i = 0; i < priv->n_families; i++)
441         {
442           if(strcmp(str, pango_font_family_get_name(priv->families[i]))
443              == 0)
444             {
445               gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_font_type), i);
446               break;
447             }
448         }
449       break;
450       
451     case PROP_FAMILY_SET:
452       b = g_value_get_boolean(value);
453       if(!b)
454         gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_font_type), -1);
455       break;
456     
457     case PROP_SIZE:
458       size = g_value_get_int(value);
459       for(i = 0; i < G_N_ELEMENTS(font_sizes); i++)
460         {
461           if(size == font_sizes[i])
462             {
463               gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_font_size), i);
464               break;
465             }
466         }
467       break;
468       
469     case PROP_SIZE_SET:
470       b = g_value_get_boolean(value);
471       if(!b)
472         gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_font_size), -1);
473       break;
474
475     case PROP_COLOR:
476       color = (GdkColor *) g_value_get_boxed(value);
477       if(color != NULL)
478         hildon_color_button_set_color(HILDON_COLOR_BUTTON
479                                       (priv->font_color_button),
480                                       color);
481       else
482         hildon_color_button_set_color(HILDON_COLOR_BUTTON
483                                       (priv->font_color_button),
484                                       &black);
485       break;
486
487     case PROP_COLOR_SET:
488       priv->color_set = g_value_get_boolean(value);
489       if(!priv->color_set)
490         {
491           /*set color to black, but block our signal handler*/
492           g_signal_handler_block((gpointer) priv->font_color_button,
493                                  priv->color_modified_signal_handler);
494           
495           hildon_color_button_set_color(HILDON_COLOR_BUTTON
496                                         (priv->font_color_button), 
497                                         &black);
498           
499           g_signal_handler_unblock((gpointer) priv->font_color_button,
500                                  priv->color_modified_signal_handler);
501         }
502       break;
503
504     case PROP_BOLD:
505       /*this call will make sure that we dont get extra clicked signal*/
506       gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_bold),
507                                          FALSE);
508       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->chk_bold),
509                                    g_value_get_boolean(value));
510       break;
511
512     case PROP_BOLD_SET:
513       gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_bold),
514                                          !g_value_get_boolean(value));
515       break;
516       
517     case PROP_ITALIC:
518       gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_italic),
519                                          FALSE);
520       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->chk_italic),
521                                    g_value_get_boolean(value));
522       break;
523
524     case PROP_ITALIC_SET:
525       gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_italic),
526                                          !g_value_get_boolean(value));
527       break;
528       
529     case PROP_UNDERLINE:
530       gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON
531                                          (priv->chk_underline),
532                                          FALSE);
533       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->chk_underline),
534                                    g_value_get_boolean(value));
535       break;
536
537     case PROP_UNDERLINE_SET:
538       gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_underline),
539                                          !g_value_get_boolean(value));
540       break;
541   
542     case PROP_STRIKETHROUGH:
543       gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON
544                                          (priv->chk_strikethrough),
545                                          FALSE);
546       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->chk_strikethrough),
547                                    g_value_get_boolean(value));
548       break;
549
550     case PROP_STRIKETHROUGH_SET:
551       gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON
552                                          (priv->chk_strikethrough),
553                                          !g_value_get_boolean(value));
554       break;
555
556     case PROP_POSITION:
557       i = g_value_get_int(value);
558       if( i == 1 )
559         gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_positioning), 1);
560       else if(i == -1)
561         gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_positioning), 2);
562       else
563         gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_positioning), 0);
564       break;
565
566     case PROP_FONT_SCALING:
567       priv->font_scaling = g_value_get_double(value);
568       break;
569       
570     case PROP_POSITION_SET:
571       b = g_value_get_boolean(value);
572       if(!b)
573         gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_positioning), -1);
574       break;
575
576     case PROP_PREVIEW_TEXT:
577       hildon_font_selection_dialog_set_preview_text(
578               HILDON_FONT_SELECTION_DIALOG(object),
579               g_value_get_string(value));
580       break;
581     
582     default:
583       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
584       break;
585     }
586 }
587
588 static void
589 hildon_font_selection_dialog_class_init(HildonFontSelectionDialogClass *
590                                         klass)
591 {
592   GObjectClass *gobject_class;
593
594   font_selection_dialog_parent_class = g_type_class_peek_parent(klass);
595   gobject_class = G_OBJECT_CLASS(klass);
596   gobject_class->finalize = hildon_font_selection_dialog_finalize;
597   gobject_class->get_property = hildon_font_selection_dialog_get_property;
598   gobject_class->set_property = hildon_font_selection_dialog_set_property;
599
600   /* Install property to the class */
601   g_object_class_install_property(gobject_class, PROP_FAMILY,
602                                   g_param_spec_string("family",
603                                   "Font family", "String defines"
604                                   " the font family", "Sans",
605                                   G_PARAM_READWRITE));
606   
607   g_object_class_install_property(gobject_class, PROP_FAMILY_SET,
608                                   g_param_spec_boolean ("family-set",
609                                   "family inconsistent state",
610                                   "Whether the family property"
611                                   " is inconsistent", FALSE,
612                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
613   
614   g_object_class_install_property(gobject_class, PROP_SIZE,
615                                    g_param_spec_int ("size",
616                                    "Font size",
617                                    "Font size in Pt",
618                                    6, 32, 16,
619                                    G_PARAM_READWRITE));
620   
621   g_object_class_install_property(gobject_class, PROP_SIZE_SET,
622                                   g_param_spec_boolean ("size-set",
623                                   "size inconsistent state",
624                                   "Whether the size property"
625                                   " is inconsistent", FALSE,
626                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
627   
628   g_object_class_install_property(gobject_class, PROP_COLOR,
629                                   g_param_spec_boxed ("color",
630                                   "text color",
631                                   "gdk color for the text",
632                                   GDK_TYPE_COLOR,
633                                   G_PARAM_READWRITE));
634
635   g_object_class_install_property(gobject_class, PROP_COLOR_SET,
636                                   g_param_spec_boolean ("color-set",
637                                   "color inconsistent state",
638                                   "Whether the color property"
639                                   " is inconsistent", FALSE,
640                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
641
642   g_object_class_install_property(gobject_class, PROP_BOLD,
643                                   g_param_spec_boolean ("bold",
644                                   "text weight",
645                                   "Whether the text is bold",
646                                   FALSE,
647                                   G_PARAM_READWRITE));
648   
649   g_object_class_install_property(gobject_class, PROP_BOLD_SET,
650                                   g_param_spec_boolean ("bold-set",
651                                   "bold inconsistent state",
652                                   "Whether the bold"
653                                   " is inconsistent", FALSE,
654                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
655   
656   g_object_class_install_property(gobject_class, PROP_ITALIC,
657                                   g_param_spec_boolean ("italic",
658                                   "text style",
659                                   "Whether the text is italic",
660                                   FALSE,
661                                   G_PARAM_READWRITE));
662   
663   g_object_class_install_property(gobject_class, PROP_ITALIC_SET,
664                                   g_param_spec_boolean ("italic-set",
665                                   "italic inconsistent state",
666                                   "Whether the italic"
667                                   " is inconsistent", FALSE,
668                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
669   
670   g_object_class_install_property(gobject_class, PROP_UNDERLINE,
671                                   g_param_spec_boolean ("underline",
672                                   "text underline",
673                                   "Whether the text is underlined",
674                                   FALSE,
675                                   G_PARAM_READWRITE));
676   
677   g_object_class_install_property(gobject_class, PROP_UNDERLINE_SET,
678                                   g_param_spec_boolean ("underline-set",
679                                   "underline inconsistent state",
680                                   "Whether the underline"
681                                   " is inconsistent", FALSE,
682                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
683   
684   g_object_class_install_property(gobject_class, PROP_STRIKETHROUGH,
685                                   g_param_spec_boolean ("strikethrough",
686                                   "strikethroughed text",
687                                   "Whether the text is strikethroughed",
688                                   FALSE,
689                                   G_PARAM_READWRITE));
690   
691   g_object_class_install_property(gobject_class, PROP_STRIKETHROUGH_SET,
692                                   g_param_spec_boolean ("strikethrough-set",
693                                   "strikethrough inconsistent state",
694                                   "Whether the strikethrough"
695                                   " is inconsistent", FALSE,
696                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
697   
698   g_object_class_install_property(gobject_class, PROP_POSITION,
699                                    g_param_spec_int ("position",
700                                    "Font position",
701                                    "Font position super or subscript",
702                                    -1, 1, 0,
703                                    G_PARAM_READWRITE));
704
705   /* FIXME This was introduced in 0.14.1. We don't have documentation for 
706    * properties anyways, but once it's there it needs to be marked as 
707    * Since: 0.14.1 */
708   g_object_class_install_property(gobject_class, PROP_FONT_SCALING,
709                                    g_param_spec_double ("font-scaling",
710                                    "Font scaling",
711                                    "Font scaling for the preview dialog",
712                                    0, 10, 1,
713                                    G_PARAM_READWRITE));
714   
715   g_object_class_install_property(gobject_class, PROP_POSITION_SET,
716                                   g_param_spec_boolean ("position-set",
717                                   "position inconsistent state",
718                                   "Whether the position"
719                                   " is inconsistent", FALSE,
720                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
721   
722   g_object_class_install_property(gobject_class, PROP_PREVIEW_TEXT,
723                                   g_param_spec_string("preview-text",
724                                   "Preview Text", 
725                                   "the text in preview dialog, which does" 
726                                   "not include the reference text",
727                                   "",
728                                   G_PARAM_READWRITE));
729   
730
731   g_type_class_add_private(klass,
732                            sizeof(struct _HildonFontSelectionDialogPrivate));
733 }
734
735
736 static void 
737 hildon_font_selection_dialog_init(HildonFontSelectionDialog *fontseldiag)
738 {
739   HildonFontSelectionDialogPrivate *priv =
740     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontseldiag);
741   GtkWidget *preview_button;
742   
743   priv->notebook = GTK_NOTEBOOK(gtk_notebook_new());
744
745   hildon_font_selection_dialog_construct_notebook(fontseldiag);
746   
747   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fontseldiag)->vbox),
748                      GTK_WIDGET(priv->notebook), TRUE, TRUE, 0);
749   
750   /* Add dialog buttons */
751   gtk_dialog_add_button(GTK_DIALOG(fontseldiag),
752                         _("ecdg_bd_font_dialog_ok"),
753                         GTK_RESPONSE_OK);
754   
755   preview_button = gtk_button_new_with_label(_("ecdg_bd_font_dialog_preview"));
756   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fontseldiag)->action_area), 
757                      preview_button, FALSE, TRUE, 0);
758   g_signal_connect_swapped(preview_button, "clicked",
759                            G_CALLBACK
760                            (hildon_font_selection_dialog_show_preview),
761                            fontseldiag);
762   gtk_widget_show(preview_button);
763
764   gtk_dialog_add_button(GTK_DIALOG(fontseldiag),
765                         _("ecdg_bd_font_dialog_cancel"),
766                         GTK_RESPONSE_CANCEL);
767
768   /*Set default preview text*/
769   priv->preview_text = g_strdup(_("ecdg_fi_preview_font_preview_text"));
770
771   gtk_window_set_title(GTK_WINDOW(fontseldiag), _("ecdg_ti_font"));
772   /*here is the line to make sure that notebook has the default focus*/
773   gtk_container_set_focus_child(GTK_CONTAINER(GTK_DIALOG(fontseldiag)->vbox),
774                                 GTK_WIDGET(priv->notebook));
775 }
776
777 static void 
778 hildon_font_selection_dialog_construct_notebook (HildonFontSelectionDialog
779                                                  *fontsel)
780 {
781   gint i;
782   GtkWidget *vbox_tab[3];
783   GtkWidget *font_color_box;
784   GtkWidget *caption_control;
785   GtkSizeGroup *group;
786   
787   HildonFontSelectionDialogPrivate *priv =
788     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontsel);
789
790   for (i = 0; i < 3; i++)
791     vbox_tab[i] = gtk_vbox_new(TRUE, 0);
792
793   group =
794     GTK_SIZE_GROUP(gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL));
795   
796   /* Build the first page of the GtkNotebook: font style */
797   priv->cbx_font_type = gtk_combo_box_new_text();
798   hildon_font_selection_dialog_show_available_fonts(fontsel);
799   caption_control = hildon_caption_new(group,
800                                        _("ecdg_fi_font_font"),
801                                        priv->cbx_font_type,
802                                        NULL,
803                                        HILDON_CAPTION_OPTIONAL);
804   gtk_box_pack_start(GTK_BOX(vbox_tab[0]), caption_control,
805                      FALSE, FALSE, 0);
806
807   priv->cbx_font_size = gtk_combo_box_new_text();
808   hildon_font_selection_dialog_show_available_sizes(priv);
809   caption_control = hildon_caption_new(group,
810                                        _("ecdg_fi_font_size"),
811                                        priv->cbx_font_size,
812                                        NULL,
813                                        HILDON_CAPTION_OPTIONAL);
814   gtk_box_pack_start(GTK_BOX(vbox_tab[0]), caption_control,
815                      FALSE, FALSE, 0);
816
817   font_color_box = gtk_hbox_new(FALSE, 0);
818   priv->font_color_button = hildon_color_button_new();
819   priv->color_set = FALSE;
820   priv->font_scaling = 1.0;
821   priv->color_modified_signal_handler = 
822     g_signal_connect(G_OBJECT(priv->font_color_button), "notify::color",
823                      G_CALLBACK(color_modified_cb), (gpointer) priv);
824   gtk_box_pack_start(GTK_BOX(font_color_box),
825                      priv->font_color_button, FALSE, FALSE, 0);
826   
827   caption_control =
828     hildon_caption_new(group, _("ecdg_fi_font_colour_selector"),
829                        font_color_box,
830                        NULL, HILDON_CAPTION_OPTIONAL);
831   
832   gtk_box_pack_start(GTK_BOX(vbox_tab[0]), caption_control,
833                      FALSE, FALSE, 0);
834
835   /* Build the second page of the GtkNotebook: font formatting */ 
836   priv->chk_bold = gtk_check_button_new();
837   caption_control = hildon_caption_new(group,
838                                        _("ecdg_fi_font_bold"),
839                                        priv->chk_bold,
840                                        NULL,
841                                        HILDON_CAPTION_OPTIONAL);
842   gtk_box_pack_start(GTK_BOX(vbox_tab[1]), caption_control,
843                      FALSE, FALSE, 0);
844   g_signal_connect(G_OBJECT(priv->chk_bold), "clicked", 
845                    G_CALLBACK(toggle_clicked), NULL);
846
847   priv->chk_italic = gtk_check_button_new();
848   caption_control =
849     hildon_caption_new(group, _("ecdg_fi_font_italic"),
850                        priv->chk_italic,
851                        NULL, HILDON_CAPTION_OPTIONAL);
852   gtk_box_pack_start(GTK_BOX(vbox_tab[1]), caption_control,
853                      FALSE, FALSE, 0);
854   g_signal_connect(G_OBJECT(priv->chk_italic), "clicked", 
855                    G_CALLBACK(toggle_clicked), NULL);
856
857   priv->chk_underline = gtk_check_button_new();
858   caption_control =
859     hildon_caption_new(group, _("ecdg_fi_font_underline"),
860                        priv->chk_underline, NULL,
861                        HILDON_CAPTION_OPTIONAL);
862   gtk_box_pack_start(GTK_BOX(vbox_tab[1]), caption_control,
863                      FALSE, FALSE, 0);
864   g_signal_connect(G_OBJECT(priv->chk_underline), "clicked", 
865                    G_CALLBACK(toggle_clicked), NULL);
866
867   /* Build the third page of the GtkNotebook: other font properties */
868   priv->chk_strikethrough = gtk_check_button_new();
869   caption_control =
870     hildon_caption_new(group, _("ecdg_fi_font_strikethrough"),
871                        priv->chk_strikethrough, NULL,
872                        HILDON_CAPTION_OPTIONAL);
873   gtk_box_pack_start(GTK_BOX(vbox_tab[2]), caption_control,
874                      FALSE, FALSE, 0);
875   g_signal_connect(G_OBJECT(priv->chk_strikethrough), "clicked", 
876                    G_CALLBACK(toggle_clicked), NULL);
877
878   priv->cbx_positioning = gtk_combo_box_new_text();
879   hildon_font_selection_dialog_show_available_positionings(priv);
880   caption_control =
881     hildon_caption_new(group, _("ecdg_fi_font_special"),
882                        priv->cbx_positioning, NULL,
883                        HILDON_CAPTION_OPTIONAL);
884   gtk_box_pack_start(GTK_BOX(vbox_tab[2]), caption_control,
885                      FALSE, FALSE, 0);
886   
887   /* Populate notebook */
888   gtk_notebook_insert_page(priv->notebook, vbox_tab[0], NULL, 0);
889   gtk_notebook_insert_page(priv->notebook, vbox_tab[1], NULL, 1);
890   gtk_notebook_insert_page(priv->notebook, vbox_tab[2], NULL, 2);
891   gtk_notebook_set_tab_label_text(priv->notebook, vbox_tab[0],
892                                   _("ecdg_ti_font_dialog_style"));
893   gtk_notebook_set_tab_label_text(priv->notebook, vbox_tab[1],
894                                   _("ecdg_ti_font_dialog_format"));
895   gtk_notebook_set_tab_label_text(priv->notebook, vbox_tab[2],
896                                   _("ecdg_ti_font_dialog_other"));
897   
898   gtk_widget_show_all(GTK_WIDGET(priv->notebook));
899 }
900
901 static void 
902 color_modified_cb(HildonColorButton *button, 
903                   GParamSpec *pspec, 
904                   gpointer fsd_priv)
905 {
906   HildonFontSelectionDialogPrivate *priv = 
907           (HildonFontSelectionDialogPrivate *) fsd_priv;
908
909   priv->color_set = TRUE;
910 }
911
912 static void 
913 hildon_font_selection_dialog_finalize(GObject * object)
914 {
915   HildonFontSelectionDialogPrivate *priv;
916   HildonFontSelectionDialog *fontsel;
917
918   g_assert(HILDON_IS_FONT_SELECTION_DIALOG(object));
919   fontsel = HILDON_FONT_SELECTION_DIALOG(object);
920
921   priv = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontsel);
922   
923   g_free(priv->preview_text);
924   g_free(priv->families);
925
926   if (G_OBJECT_CLASS(font_selection_dialog_parent_class)->finalize)
927     G_OBJECT_CLASS(font_selection_dialog_parent_class)->finalize(object);
928 }
929
930 static int 
931 cmp_families(const void *a, const void *b)
932 {
933   const char *a_name =
934     pango_font_family_get_name(*(PangoFontFamily **) a);
935   const char *b_name =
936     pango_font_family_get_name(*(PangoFontFamily **) b);
937
938   return g_utf8_collate(a_name, b_name);
939 }
940
941 /* Exits the preview dialog with GTK_RESPONSE_CANCEL if Esc key
942  * was pressed */
943 static gboolean
944 hildon_font_selection_dialog_preview_key_press(GtkWidget   * widget,
945                                                GdkEventKey * event,
946                                                gpointer      unused)
947 {
948   g_assert(widget);
949   g_assert(event);
950   
951   if (event->keyval == GDK_Escape)
952     {
953       gtk_dialog_response(GTK_DIALOG(widget), GTK_RESPONSE_CANCEL);
954       return TRUE;
955     }
956
957   return FALSE;
958 }
959
960 static void
961 add_preview_text_attr(PangoAttrList *list, PangoAttribute *attr, 
962                       guint start, guint len)
963 {
964   attr->start_index = start;
965   attr->end_index = start + len;
966   pango_attr_list_insert(list, attr);
967 }
968
969 static PangoAttrList*
970 hildon_font_selection_dialog_create_attrlist(HildonFontSelectionDialog *
971                                          fontsel, guint start_index, guint len)
972 {
973   PangoAttrList *list;
974   PangoAttribute *attr;
975   gint size, position;
976   gboolean family_set, size_set, color_set, bold, bold_set,
977            italic, italic_set, underline, underline_set,
978            strikethrough, strikethrough_set, position_set;
979   GdkColor *color = NULL;
980   gchar *family = NULL;
981   gdouble font_scaling = 1.0;
982
983   list = pango_attr_list_new();
984  
985   g_object_get(G_OBJECT(fontsel),
986                "family", &family, "family-set", &family_set,
987                "size", &size, "size-set", &size_set,
988                "color", &color, "color-set", &color_set,
989                "bold", &bold, "bold-set", &bold_set,
990                "italic", &italic, "italic-set", &italic_set,
991                "underline", &underline, "underline-set", &underline_set,
992                "strikethrough", &strikethrough, "strikethrough-set", 
993                &strikethrough_set, "position", &position, 
994                "position-set", &position_set, 
995                "font-scaling", &font_scaling,
996                NULL);
997
998   /*family*/
999   if(family_set)
1000     {
1001       attr = pango_attr_family_new(family);
1002       add_preview_text_attr(list, attr, start_index, len);
1003     }
1004   g_free(family);
1005   
1006   /*size*/
1007   if(size_set)
1008     {
1009       attr = pango_attr_size_new(size * PANGO_SCALE);
1010       add_preview_text_attr(list, attr, start_index, len);
1011     }
1012   
1013   /*color*/
1014   if(color_set)
1015     {
1016       attr = pango_attr_foreground_new(color->red, color->green, color->blue);
1017       add_preview_text_attr(list, attr, start_index, len);
1018     }
1019   
1020   if(color != NULL)
1021     gdk_color_free(color);
1022   
1023   /*weight*/
1024   if(bold_set)
1025     {
1026       if(bold)
1027         attr = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
1028       else
1029         attr = pango_attr_weight_new(PANGO_WEIGHT_NORMAL);
1030
1031       add_preview_text_attr(list, attr, start_index, len);
1032     }
1033   
1034   /*style*/
1035   if(italic_set)
1036     {
1037       if(italic)
1038         attr = pango_attr_style_new(PANGO_STYLE_ITALIC);
1039       else
1040         attr = pango_attr_style_new(PANGO_STYLE_NORMAL);
1041
1042       add_preview_text_attr(list, attr, start_index, len);
1043     }
1044   
1045   /*underline*/
1046   if(underline_set)
1047     {
1048       if(underline)
1049         attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
1050       else
1051         attr = pango_attr_underline_new(PANGO_UNDERLINE_NONE);
1052
1053       add_preview_text_attr(list, attr, start_index, len);
1054     }
1055   
1056   /*strikethrough*/
1057   if(strikethrough_set)
1058     {
1059       if(strikethrough)
1060         attr = pango_attr_strikethrough_new(TRUE);
1061       else
1062         attr = pango_attr_strikethrough_new(FALSE);
1063
1064       add_preview_text_attr(list, attr, start_index, len);
1065     }
1066   
1067   /*position*/
1068   if(position_set)
1069     {
1070       switch(position)
1071         {
1072         case 1: /*super*/
1073           attr = pango_attr_rise_new(SUPERSCRIPT_RISE);
1074           break;
1075         case -1: /*sub*/
1076           attr = pango_attr_rise_new(SUBSCRIPT_LOW);
1077           break;
1078         default: /*normal*/
1079           attr = pango_attr_rise_new(0);
1080           break;
1081         }
1082
1083       add_preview_text_attr(list, attr, start_index, len);
1084     }
1085
1086   /*font scaling for preview*/
1087   if(font_scaling)
1088     {
1089       attr = pango_attr_scale_new(font_scaling);
1090       add_preview_text_attr(list, attr, 0, len + start_index);
1091     }
1092    
1093   return list;
1094 }
1095
1096 static void
1097 hildon_font_selection_dialog_show_preview(HildonFontSelectionDialog *
1098                                           fontsel)
1099 {
1100   HildonFontSelectionDialogPrivate *priv =
1101     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontsel);
1102   gint size;
1103   gboolean family_set, size_set;
1104   PangoAttribute *attr;
1105   PangoAttrList *list;
1106   GtkWidget *preview_dialog;
1107   GtkWidget *preview_label;
1108   gchar *str = NULL;
1109   gboolean position_set = FALSE;
1110   gint position = 0;
1111   gboolean show_ref = FALSE;
1112
1113   g_object_get(G_OBJECT(fontsel), "position-set", &position_set, NULL);
1114   if (position_set) {
1115     g_object_get(G_OBJECT(fontsel), "position", &position, NULL);
1116     if (position == 1 || position == -1)
1117       show_ref = TRUE;
1118   }
1119   
1120   /*Preview dialog init*/
1121   preview_dialog=
1122     gtk_dialog_new_with_buttons(_("ecdg_ti_preview_font"), NULL,
1123                                 GTK_DIALOG_MODAL |
1124                                 GTK_DIALOG_DESTROY_WITH_PARENT |
1125                                 GTK_DIALOG_NO_SEPARATOR,
1126                                 _("ecdg_bd_font_dialog_ok"),
1127                                 GTK_RESPONSE_ACCEPT,
1128                                 NULL);
1129
1130   str = (show_ref) ? g_strconcat(_("ecdg_fi_preview_font_preview_reference"), priv->preview_text, 0) :
1131                      g_strdup (priv->preview_text);
1132
1133   preview_label = gtk_label_new(str);
1134   gtk_label_set_line_wrap(GTK_LABEL(preview_label), TRUE);
1135   
1136   g_free(str);
1137   str = NULL;
1138
1139   gtk_container_add(GTK_CONTAINER(GTK_DIALOG(preview_dialog)->vbox),
1140                     preview_label);
1141
1142   
1143   /* set keypress handler (ESC hardkey) */
1144   g_signal_connect(G_OBJECT(preview_dialog), "key-press-event",
1145                   G_CALLBACK(hildon_font_selection_dialog_preview_key_press),
1146                   NULL);
1147   
1148   
1149   /*Set the font*/
1150   list = (show_ref) ? hildon_font_selection_dialog_create_attrlist(fontsel, 
1151       strlen(_("ecdg_fi_preview_font_preview_reference")),
1152       strlen(priv->preview_text)) :
1153       hildon_font_selection_dialog_create_attrlist(fontsel, 
1154       0,
1155       strlen(priv->preview_text));
1156
1157   g_object_get(G_OBJECT(fontsel), "family", &str, "family-set",
1158                &family_set, "size", &size, "size-set", &size_set,
1159                NULL);
1160
1161   /* FIXME: This is a slightly ugly hack to force the width of the window so that
1162    * the whole text fits with various font sizes. It's being done in such a way, 
1163    * because of some GtkLabel wrapping issues and other mysterious bugs related to 
1164    * truncating ellipsizing. Needs a rethink in future. (MDK) */
1165
1166   gint dialog_width = (size_set && size > 24) ? 600 : 500; 
1167   gtk_window_set_default_size (GTK_WINDOW(preview_dialog), dialog_width, -1);
1168
1169   /*make reference text to have the same fontface and size*/
1170   if(family_set)
1171     {
1172       attr = pango_attr_family_new(str);
1173       add_preview_text_attr(list, attr, 0, strlen(_("ecdg_fi_preview_font_preview_reference")));
1174     }
1175   g_free(str);
1176   
1177   /*size*/
1178   if(size_set)
1179     {
1180       attr = pango_attr_size_new(size * PANGO_SCALE);
1181       add_preview_text_attr(list, attr, 0, strlen(_("ecdg_fi_preview_font_preview_reference")));
1182     }
1183   
1184   gtk_label_set_attributes(GTK_LABEL(preview_label), list);
1185   pango_attr_list_unref(list);
1186   
1187   /*And show the dialog*/
1188   gtk_window_set_transient_for(GTK_WINDOW(preview_dialog), 
1189                                GTK_WINDOW(fontsel));
1190
1191   gtk_widget_show_all(preview_dialog);
1192   gtk_dialog_run(GTK_DIALOG(preview_dialog));
1193   gtk_widget_destroy(preview_dialog);
1194 }
1195
1196
1197 static gboolean is_internal_font(const gchar * name){
1198   return strcmp(name, "DeviceSymbols") == 0
1199       || strcmp(name, "Nokia Smiley" ) == 0
1200       || strcmp(name, "NewCourier" ) == 0
1201       || strcmp(name, "NewTimes" ) == 0
1202       || strcmp(name, "SwissA" ) == 0
1203       || strcmp(name, "Nokia Sans"   ) == 0
1204       || strcmp(name, "Nokia Sans Cn") == 0;
1205 }
1206
1207 static void filter_out_internal_fonts(PangoFontFamily **families, int *n_families){
1208   int i;
1209   int n; /* counts valid fonts */
1210   const gchar * name = NULL;
1211
1212   for(i = 0, n = 0; i < *n_families; i++){
1213
1214     name = pango_font_family_get_name(families[i]);
1215         
1216     if(!is_internal_font(name)){
1217
1218       if(i!=n){ /* there are filtered out families */
1219         families[n] = families[i]; /* shift the current family */
1220       }
1221
1222       n++; /* count one more valid */
1223     }
1224   }/* foreach font family */
1225
1226   *n_families = n;  
1227 }
1228
1229
1230 static void
1231 hildon_font_selection_dialog_show_available_fonts(HildonFontSelectionDialog 
1232                                                   *fontsel)
1233
1234 {
1235   gint i;
1236   
1237   HildonFontSelectionDialogPrivate *priv =
1238     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontsel);
1239
1240   pango_context_list_families(gtk_widget_get_pango_context
1241                               (GTK_WIDGET(fontsel)), &priv->families,
1242                               &priv->n_families);
1243
1244   filter_out_internal_fonts(priv->families, &priv->n_families);
1245
1246   qsort(priv->families, priv->n_families, sizeof(PangoFontFamily *),
1247         cmp_families);
1248
1249
1250   for (i = 0; i < priv->n_families; i++) 
1251     {
1252       const gchar *name = pango_font_family_get_name(priv->families[i]);
1253
1254       gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_font_type),
1255                                 name);
1256     }
1257 }
1258
1259
1260 static void
1261 hildon_font_selection_dialog_show_available_positionings
1262                                              (HildonFontSelectionDialogPrivate
1263                                               *priv)
1264 {
1265   gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_positioning),
1266                             _("ecdg_va_font_printpos_1"));
1267   gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_positioning),
1268                             _("ecdg_va_font_printpos_2"));
1269   gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_positioning),
1270                             _("ecdg_va_font_printpos_3"));
1271 }
1272
1273 /*Loads the sizes from a pre-allocated table*/
1274 static void
1275 hildon_font_selection_dialog_show_available_sizes
1276                                              (HildonFontSelectionDialogPrivate
1277                                               *priv)
1278 {
1279   gchar *size_str;
1280   gint i;
1281
1282   for (i = 0; i < G_N_ELEMENTS(font_sizes); i++) 
1283     {
1284       size_str = g_strdup_printf ("%i%s",
1285                                   font_sizes[i],
1286                                   _("ecdg_va_font_size_trailer"));
1287
1288       gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_font_size),
1289                                 size_str);
1290       g_free (size_str);
1291     }
1292 }
1293
1294 /* WARNING: This function is called only from deprecated API */
1295 static
1296 void check_tags(gpointer data, gpointer user_data)
1297 {
1298   gchar *font_family;
1299   GdkColor *fore_color =  NULL;
1300   gint p_size, p_weight, p_style, p_underline, p_rise;
1301   gboolean b_st, ff_s, size_s, fgc_s, w_s, ss_s, u_s, sth_s, r_s;
1302   
1303   GtkTextTag *tag = (GtkTextTag*) data;
1304   HildonFontSelectionDialogSettings *settings = 
1305     (HildonFontSelectionDialogSettings *) user_data;
1306   HildonFontSelectionDialogPrivate *priv = 
1307     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(settings->fsd);
1308   
1309   /*get all the properties*/
1310   g_object_get(G_OBJECT(tag),
1311                "family", &font_family, "family-set", &ff_s,
1312                "size", &p_size, "size-set", &size_s,
1313                "foreground-gdk", &fore_color, "foreground-set", &fgc_s,
1314                "weight", &p_weight, "weight-set", &w_s,
1315                "style", &p_style, "style-set", &ss_s,
1316                "underline", &p_underline, "underline-set", &u_s,
1317                "strikethrough", &b_st, "strikethrough-set", &sth_s, 
1318                "rise", &p_rise, "rise-set", & r_s,
1319                NULL);
1320   
1321   /* Check that the given values are valid. 
1322    * If not, set the combobox row indicator to 'inconsistent' */
1323   if(ff_s)
1324     {
1325       gint new_f = -1;
1326       gint i;
1327       
1328       for(i = 0; i < priv->n_families; i++)
1329         {
1330           if(strcmp(font_family, 
1331                     pango_font_family_get_name(priv->families[i])) == 0)
1332             {
1333               new_f = i;
1334               break;
1335             }
1336         }
1337       
1338       if(settings->family == -1)
1339         settings->family = new_f;
1340       else if(settings->family != -2 && 
1341               settings->family != new_f)
1342         settings->family = -2;/*inconsist*/
1343
1344       g_free(font_family);
1345     }
1346   
1347   if(size_s)
1348     {
1349       gint new_size = -1;
1350       gint i;
1351       
1352       for(i = 0; i < G_N_ELEMENTS(font_sizes); i++)
1353         {
1354           if(p_size == font_sizes[i] * PANGO_SCALE)
1355             {
1356               new_size = i;
1357               break;
1358             }
1359         }
1360       
1361       if(settings->size == -1)
1362         settings->size = new_size;
1363       else if(settings->size != -2 && 
1364               settings->size != new_size)
1365         settings->size = -2;/*inconsist*/
1366     }
1367   
1368   if(fgc_s && settings->color == NULL 
1369      && !settings->color_inconsist)
1370         settings->color = fore_color;
1371   else if(fore_color != NULL)
1372     {
1373       if(!gdk_color_equal(fore_color, settings->color) 
1374          && fgc_s)
1375         settings->color_inconsist = TRUE;
1376       
1377       gdk_color_free(fore_color);
1378     }
1379
1380   if(w_s)
1381     settings->weight |= p_weight == PANGO_WEIGHT_NORMAL ? OFF_BIT : ON_BIT;
1382   
1383   if(ss_s)
1384     settings->style |= p_style == PANGO_STYLE_NORMAL ? OFF_BIT : ON_BIT;
1385   
1386   if(u_s)
1387     settings->underline |= 
1388       p_underline == PANGO_UNDERLINE_NONE ? OFF_BIT : ON_BIT;
1389   
1390   if(sth_s)
1391     settings->strikethrough |= b_st ? ON_BIT : OFF_BIT;
1392
1393   if(r_s)
1394     {
1395       gint new_rs = -1;
1396       
1397       if(p_rise == 0)
1398         new_rs = 0;/*normal*/
1399       else if (p_rise > 0)
1400         new_rs = 1;/*super*/
1401       else
1402         new_rs = 2;/*sub*/
1403
1404       if(settings->position == -1)
1405         settings->position = new_rs;
1406       else if(settings->position != -2 && 
1407               settings->position != new_rs)
1408         settings->position = -2;/*inconsist*/
1409     }
1410 }
1411
1412 /* WARNING: This function is called only from deprecated API */
1413 static
1414 void check_attrs(gpointer data, gpointer user_data)
1415 {
1416   PangoAttribute *attr = (PangoAttribute *) data;
1417   HildonFontSelectionDialogSettings *settings = 
1418     (HildonFontSelectionDialogSettings *) user_data;
1419   HildonFontSelectionDialogPrivate *priv = 
1420     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(settings->fsd);
1421   
1422   gchar *family;
1423   GdkColor color;
1424   gint i;
1425   gint size, weight, style, underline, strikethrough, rise;
1426   gint new_f = -1, new_size = -1, new_rise = -1;
1427
1428   /* Check that the given values are valid.
1429    * If not, set the combobox row indicator to 'inconsistent' */
1430   switch(attr->klass->type)
1431     {
1432     case PANGO_ATTR_FAMILY:
1433       family = ((PangoAttrString *) attr)->value;
1434
1435       for(i = 0; i < priv->n_families; i++)
1436         {
1437           if(strcmp(family, 
1438                     pango_font_family_get_name(priv->families[i])) == 0)
1439             {
1440               new_f = i;
1441               break;
1442             }
1443         }
1444
1445       if(settings->family == -1)
1446         settings->family = new_f;
1447       else if(settings->family != -2 && 
1448               settings->family != new_f)
1449         settings->family = -2;/*inconsist*/
1450       
1451       break;
1452     case PANGO_ATTR_SIZE:
1453       size = ((PangoAttrInt *) attr)->value;
1454       
1455       for(i = 0; i < G_N_ELEMENTS(font_sizes); i++)
1456         {
1457           if(size == font_sizes[i] * PANGO_SCALE)
1458             {
1459               new_size = i;
1460               break;
1461             }
1462         }
1463       
1464       if(settings->size == -1)
1465         settings->size = new_size;
1466       else if(settings->size != -2 && 
1467               settings->size != new_size)
1468         settings->size = -2;/*inconsist*/
1469
1470       break;
1471     case PANGO_ATTR_FOREGROUND:
1472       color.red = ((PangoAttrColor *) attr)->color.red;
1473       color.green = ((PangoAttrColor *) attr)->color.green;
1474       color.blue = ((PangoAttrColor *) attr)->color.blue;
1475
1476       if(!settings->color_inconsist &&  settings->color == NULL)
1477         settings->color = gdk_color_copy(&color);
1478       else if(settings->color != NULL && 
1479               !gdk_color_equal(&color, settings->color))
1480         settings->color_inconsist = TRUE;
1481
1482       break;
1483     case PANGO_ATTR_WEIGHT:
1484       weight = ((PangoAttrInt *) attr)->value;
1485
1486       settings->weight |= weight == PANGO_WEIGHT_NORMAL ? OFF_BIT : ON_BIT;
1487       
1488       break;
1489     case PANGO_ATTR_STYLE:
1490       style = ((PangoAttrInt *) attr)->value;
1491
1492       settings->style |= style == PANGO_STYLE_NORMAL ? OFF_BIT : ON_BIT; 
1493       
1494       break;
1495     case PANGO_ATTR_UNDERLINE:
1496       underline = ((PangoAttrInt *) attr)->value;
1497
1498       settings->underline |= 
1499         underline == PANGO_UNDERLINE_NONE ? OFF_BIT : ON_BIT;
1500   
1501       break;
1502     case PANGO_ATTR_STRIKETHROUGH:
1503       strikethrough = ((PangoAttrInt *) attr)->value;
1504       
1505       settings->strikethrough |= strikethrough ? ON_BIT : OFF_BIT;
1506
1507       break;
1508     case PANGO_ATTR_RISE:
1509       rise = ((PangoAttrInt *) attr)->value;
1510       
1511       if(rise == 0)
1512         new_rise = 0;/*normal*/
1513       else if (rise > 0)
1514         new_rise = 1;/*super*/
1515       else
1516         new_rise = 2;/*sub*/
1517
1518       if(settings->position == -1)
1519         settings->position = new_rise;
1520       else if(settings->position != -2 && 
1521               settings->position != new_rise)
1522         settings->position = -2;/*inconsist*/
1523
1524       break;
1525     default:
1526       break;
1527     }
1528
1529   pango_attribute_destroy(attr);
1530 }
1531
1532 /* WARNING: This function is called only from deprecated API */
1533 static void
1534 settings_init(HildonFontSelectionDialogSettings *settings,
1535               HildonFontSelectionDialog  *fsd)
1536 {
1537   settings->fsd = fsd;
1538   settings->family = -1;
1539   settings->size = -1;
1540   settings->color = NULL;
1541   settings->color_inconsist = FALSE;
1542   settings->weight = 0;
1543   settings->style = 0;
1544   settings->underline = 0;
1545   settings->strikethrough = 0;
1546   settings->position = -1;
1547 }
1548
1549 /* WARNING: This function is called only from deprecated API */
1550 static void
1551 bit_mask_toggle(gint mask, GtkToggleButton *button,
1552                 GObject *object, const gchar *prop,
1553                 const gchar *prop_set)
1554 {
1555   
1556   if(mask == 3)
1557     gtk_toggle_button_set_inconsistent(button, TRUE);
1558   else
1559     {
1560       gtk_toggle_button_set_inconsistent(button, FALSE);
1561
1562       if(mask == 1)
1563         gtk_toggle_button_set_active(button, TRUE);
1564       else
1565         gtk_toggle_button_set_active(button, FALSE);
1566
1567       g_object_notify(object, prop);
1568     }
1569
1570   g_object_notify(object, prop_set);
1571 }
1572
1573 /* WARNING: This function is called only from deprecated API */
1574 static void
1575 combo_active(gint active, GtkComboBox *box, 
1576              GObject *object, const gchar *prop, const gchar *prop_set)
1577 {
1578   /*probaly not the best function, but we need all these
1579    * parameters to keep things together*/
1580  
1581   
1582   if(active >= 0)
1583     {
1584       gtk_combo_box_set_active(box, active);
1585       g_object_notify(object, prop);
1586     }
1587   else
1588     gtk_combo_box_set_active(box, -1);
1589
1590   g_object_notify(object, prop_set);
1591 }
1592
1593 /* WARNING: This function is called only from deprecated API */
1594 static void
1595 settings_apply(HildonFontSelectionDialogSettings *settings)
1596 {
1597
1598   HildonFontSelectionDialogPrivate *priv = 
1599     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(settings->fsd);
1600   
1601   /*family*/
1602   combo_active(settings->family, GTK_COMBO_BOX(priv->cbx_font_type),
1603                G_OBJECT(settings->fsd), "family", "family-set");
1604   
1605   /*size*/
1606   combo_active(settings->size, GTK_COMBO_BOX(priv->cbx_font_size),
1607                G_OBJECT(settings->fsd), "size", "size-set");
1608   
1609   /*block our signal handler indicating color has been changed by
1610    * the user before set the color, and unblock it after setting
1611    * is done*/
1612   
1613   if(settings->color == NULL || settings->color_inconsist)
1614     {
1615       GdkColor black;
1616
1617       black.red = black.green = black.blue = 0;
1618       g_signal_handler_block((gpointer) priv->font_color_button,
1619                              priv->color_modified_signal_handler);
1620       
1621       g_object_set(G_OBJECT(settings->fsd), "color", &black, "color-set", 
1622                    FALSE, NULL);
1623
1624       g_signal_handler_unblock((gpointer) priv->font_color_button,
1625                                priv->color_modified_signal_handler);
1626     }
1627   else 
1628       g_object_set(G_OBJECT(settings->fsd), "color", settings->color, NULL);
1629   
1630   /*weight*/
1631   bit_mask_toggle(settings->weight, GTK_TOGGLE_BUTTON(priv->chk_bold),
1632                   G_OBJECT(settings->fsd), "bold", "bold-set");
1633   
1634   /*style*/
1635   bit_mask_toggle(settings->style, GTK_TOGGLE_BUTTON(priv->chk_italic),
1636                   G_OBJECT(settings->fsd), "italic", "italic-set");
1637   
1638   /*underline*/
1639   bit_mask_toggle(settings->underline, 
1640                   GTK_TOGGLE_BUTTON(priv->chk_underline), 
1641                   G_OBJECT(settings->fsd), "underline", "underline-set");
1642   
1643   /*strikethrough*/
1644   bit_mask_toggle(settings->strikethrough, 
1645                   GTK_TOGGLE_BUTTON(priv->chk_strikethrough),
1646                   G_OBJECT(settings->fsd), "strikethrough", 
1647                   "strikethrough-set");
1648
1649   /*position*/
1650   combo_active(settings->position, GTK_COMBO_BOX(priv->cbx_positioning),
1651                G_OBJECT(settings->fsd), "position", "position-set");
1652 }
1653
1654 static void
1655 settings_destroy(HildonFontSelectionDialogSettings *settings)
1656 {
1657   if(settings->color != NULL)
1658     gdk_color_free(settings->color);
1659 }
1660
1661 static void
1662 toggle_clicked(GtkButton *button, gpointer unused)
1663 {
1664   GtkToggleButton *t_b = GTK_TOGGLE_BUTTON(button);
1665
1666   /*we have to remove the inconsistent state ourselves*/
1667   if(gtk_toggle_button_get_inconsistent(t_b))
1668     {
1669       gtk_toggle_button_set_inconsistent(t_b, FALSE);
1670       gtk_toggle_button_set_active(t_b, FALSE);
1671     }
1672 }
1673
1674 /*******************/
1675 /*Public functions*/
1676 /*******************/
1677
1678 /**
1679  * hildon_font_selection_dialog_new:
1680  * @parent: the parent window
1681  * @title: the title of font selection dialog
1682  *
1683  * If NULL is passed for title, then default title
1684  * "Font" will be used.
1685  *
1686  * Returns: a new #HildonFontSelectionDialog
1687  */
1688 GtkWidget *
1689 hildon_font_selection_dialog_new(GtkWindow * parent,
1690                                  const gchar * title)
1691 {
1692   HildonFontSelectionDialog *fontseldiag;
1693
1694   fontseldiag = g_object_new(HILDON_TYPE_FONT_SELECTION_DIALOG,
1695                              "has-separator", FALSE, NULL);
1696
1697   if (title)
1698     gtk_window_set_title(GTK_WINDOW(fontseldiag), title);
1699
1700   if (parent)
1701     gtk_window_set_transient_for(GTK_WINDOW(fontseldiag), parent);
1702
1703   return GTK_WIDGET(fontseldiag);
1704 }
1705
1706 /**
1707  * hildon_font_selection_dialog_get_preview_text:
1708  * @fsd: the font selection dialog
1709  *
1710  * Gets the text in preview dialog, which does not include the 
1711  * reference text. The returned string must be freed by the user.
1712  *
1713  * Returns: a string pointer
1714  */
1715 gchar *
1716 hildon_font_selection_dialog_get_preview_text(HildonFontSelectionDialog * fsd)
1717 {
1718   HildonFontSelectionDialogPrivate *priv;
1719
1720   g_return_val_if_fail(HILDON_IS_FONT_SELECTION_DIALOG(fsd), FALSE);
1721   priv = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fsd);
1722   return g_strdup(priv->preview_text);
1723 }
1724
1725 /**
1726  * hildon_font_selection_dialog_set_preview_text:
1727  * @fsd: the font selection dialog
1728  * @text: the text to be displayed in the preview dialog
1729  *
1730  * The default preview text is
1731  * "The quick brown fox jumped over the lazy dogs"
1732  */
1733 void
1734 hildon_font_selection_dialog_set_preview_text(HildonFontSelectionDialog *
1735                                               fsd, const gchar * text)
1736 {
1737    HildonFontSelectionDialogPrivate *priv = NULL;
1738    
1739    g_return_if_fail(HILDON_IS_FONT_SELECTION_DIALOG(fsd));
1740    g_return_if_fail(text);
1741   
1742    priv = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fsd);
1743    
1744    g_free(priv->preview_text);
1745    priv->preview_text = g_strdup(text);
1746    g_object_notify (G_OBJECT (fsd), "preview-text");
1747 }