]> Pileus Git - ~andy/gtk/blob - gtk/gtkfontchooser.c
efcea55248fbfa213aa0d99e33f51eae7c78029c
[~andy/gtk] / gtk / gtkfontchooser.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2011 Alberto Ruiz <aruiz@gnome.org>
3  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4  *
5  * Massively updated to rework the user interface by Alberto Ruiz, 2011
6  * Massively updated for Pango by Owen Taylor, May 2000
7  * GtkFontChooser widget for Gtk+, by Damon Chaplin, May 1998.
8  * Based on the GnomeFontSelector widget, by Elliot Lee, but major changes.
9  * The GnomeFontSelector was derived from app/text_tool.c in the GIMP.
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the
23  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24  * Boston, MA 02111-1307, USA.
25  */
26
27 #include "config.h"
28
29 #include <stdlib.h>
30 #include <glib/gprintf.h>
31 #include <string.h>
32
33 #include <atk/atk.h>
34
35 #include "gtkfontchooser.h"
36 #include "gtkbutton.h"
37 #include "gtkcellrenderertext.h"
38 #include "gtkentry.h"
39 #include "gtkframe.h"
40 #include "gtkhbbox.h"
41 #include "gtkhbox.h"
42 #include "gtklabel.h"
43 #include "gtkliststore.h"
44 #include "gtkrc.h"
45 #include "gtkstock.h"
46 #include "gtktable.h"
47 #include "gtktreeselection.h"
48 #include "gtktreeview.h"
49 #include "gtkvbox.h"
50 #include "gtkscrolledwindow.h"
51 #include "gtkintl.h"
52 #include "gtkaccessible.h"
53 #include "gtkbuildable.h"
54 #include "gtkprivate.h"
55 #include "gtkalignment.h"
56 #include "gtkscale.h"
57 #include "gtkbox.h"
58 #include "gtkspinbutton.h"
59 #include "gtkwidget.h"
60
61 /**
62  * SECTION:gtkfontchooser
63  * @Short_description: A widget for selecting fonts
64  * @Title: GtkFontChooser
65  * @See_also: #GtkFontChooserDialog
66  *
67  * The #GtkFontChooser widget lists the available fonts, styles and sizes,
68  * allowing the user to select a font.
69  * It is used in the #GtkFontChooserDialog widget to provide a dialog box for
70  * selecting fonts.
71  *
72  * To set the font which is initially selected, use
73  * gtk_font_chooser_set_font_name().
74  *
75  * To get the selected font use gtk_font_chooser_get_font_name().
76  *
77  * To change the text which is shown in the preview area, use
78  * gtk_font_chooser_set_preview_text().
79  */
80
81
82 struct _GtkFontChooserPrivate
83 {
84   GtkWidget    *search_entry;
85   GtkWidget    *family_face_list;
86   GtkListStore *model;  
87   GtkTreeModel *filter;
88
89   GtkWidget       *preview;
90   GtkWidget       *preview_scrolled_window;
91   gchar           *preview_text;
92   gboolean         show_preview_entry;
93
94   GtkWidget *size_spin;
95   GtkWidget *size_slider;
96   gboolean   ignore_slider;
97
98   gint             size;
99   PangoFontFace   *face;
100   PangoFontFamily *family;
101
102   /* Deprecated */
103   GtkWidget    *size_list;
104   GtkWidget    *font_list;
105   GtkWidget    *face_list;
106
107   GtkListStore *_size_model;
108   GtkListStore *_font_model;
109   GtkListStore *_face_model;
110
111   gboolean      ignore_size;
112   gboolean      ignore_face;
113   gboolean      ignore_font;
114 };
115
116
117 struct _GtkFontChooserDialogPrivate
118 {
119   GtkWidget *fontchooser;
120
121   GtkWidget *select_button;
122   GtkWidget *cancel_button;
123
124   /* Deprecated */
125   GtkWidget *apply_button;
126 };
127
128
129 #define DEFAULT_FONT_NAME "Sans 10"
130 #define MAX_FONT_SIZE 999
131
132 /* This is the initial fixed height and the top padding of the preview entry */
133 #define PREVIEW_HEIGHT 72
134 #define PREVIEW_TOP_PADDING 6
135
136 /* Widget default geometry */
137 #define FONT_CHOOSER_WIDTH           540
138 #define FONT_CHOOSER_HEIGHT          408
139
140 /* These are the sizes of the font, style & size lists. */
141 #define FONT_LIST_HEIGHT  136
142 #define FONT_LIST_WIDTH   190
143 #define FONT_STYLE_LIST_WIDTH 170
144 #define FONT_SIZE_LIST_WIDTH  60
145
146 #define ROW_FORMAT_STRING "<span weight=\"bold\" size=\"small\" foreground=\"%s\">%s</span>\n<span size=\"x-large\" font_desc=\"%s\">%s</span>"
147
148 /* These are what we use as the standard font sizes, for the size list.
149  */
150 #define FONT_SIZES_LENGTH 14
151 static const gint font_sizes[] = {
152   6, 8, 9, 10, 11, 12, 13, 14, 16, 20, 24, 36, 48, 72
153 };
154
155 enum {
156    PROP_0,
157    PROP_FONT_NAME,
158    PROP_PREVIEW_TEXT,
159    PROP_SHOW_PREVIEW_ENTRY
160 };
161
162
163 enum {
164   FAMILY_COLUMN,
165   FACE_COLUMN,
166   PREVIEW_TEXT_COLUMN,
167   PREVIEW_TITLE_COLUMN
168 };
169
170 static void  gtk_font_chooser_set_property       (GObject         *object,
171                                                   guint            prop_id,
172                                                   const GValue    *value,
173                                                   GParamSpec      *pspec);
174 static void  gtk_font_chooser_get_property       (GObject         *object,
175                                                   guint            prop_id,
176                                                   GValue          *value,
177                                                   GParamSpec      *pspec);
178 static void  gtk_font_chooser_finalize           (GObject         *object);
179
180 static void  gtk_font_chooser_screen_changed     (GtkWidget       *widget,
181                                                   GdkScreen       *previous_screen);
182 static void  gtk_font_chooser_style_updated      (GtkWidget      *widget);
183
184 static void  gtk_font_chooser_ref_family         (GtkFontChooser *fontchooser,
185                                                   PangoFontFamily  *family);
186 static void  gtk_font_chooser_ref_face           (GtkFontChooser *fontchooser,
187                                                   PangoFontFace    *face);
188
189 static void gtk_font_chooser_bootstrap_fontlist (GtkFontChooser *fontchooser);
190
191 /* Deprecated */
192 static void update_font_list_selection            (GtkFontChooser *fontchooser);
193 static void update_size_list_selection            (GtkFontChooser *fontchooser);
194 static void update_face_model                     (GtkFontChooser *fontchooser,
195                                                    gboolean          first);
196
197 G_DEFINE_TYPE (GtkFontChooser, gtk_font_chooser, GTK_TYPE_VBOX)
198
199 static void
200 gtk_font_chooser_class_init (GtkFontChooserClass *klass)
201 {
202   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
203   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
204
205   widget_class->screen_changed = gtk_font_chooser_screen_changed;
206   widget_class->style_updated = gtk_font_chooser_style_updated;
207
208   gobject_class->finalize = gtk_font_chooser_finalize;
209   gobject_class->set_property = gtk_font_chooser_set_property;
210   gobject_class->get_property = gtk_font_chooser_get_property;
211
212   g_object_class_install_property (gobject_class,
213                                    PROP_FONT_NAME,
214                                    g_param_spec_string ("font-name",
215                                                         P_("Font name"),
216                                                         P_("The string that represents this font"),
217                                                         DEFAULT_FONT_NAME,
218                                                         GTK_PARAM_READWRITE));
219   g_object_class_install_property (gobject_class,
220                                    PROP_PREVIEW_TEXT,
221                                    g_param_spec_string ("preview-text",
222                                                         P_("Preview text"),
223                                                         P_("The text to display in order to demonstrate the selected font"),
224                                                         pango_language_get_sample_string (NULL),
225                                                         GTK_PARAM_READWRITE));
226
227   g_object_class_install_property (gobject_class,
228                                    PROP_SHOW_PREVIEW_ENTRY,
229                                    g_param_spec_boolean ("show-preview-entry",
230                                                         P_("Show preview text entry"),
231                                                         P_("Whether the preview text entry is shown or not"),
232                                                         TRUE,
233                                                         GTK_PARAM_READWRITE));
234
235   g_type_class_add_private (klass, sizeof (GtkFontChooserPrivate));
236 }
237
238 static void 
239 gtk_font_chooser_set_property (GObject         *object,
240                                  guint            prop_id,
241                                  const GValue    *value,
242                                  GParamSpec      *pspec)
243 {
244   GtkFontChooser *fontchooser;
245
246   fontchooser = GTK_FONT_CHOOSER (object);
247
248   switch (prop_id)
249     {
250     case PROP_FONT_NAME:
251       gtk_font_chooser_set_font_name (fontchooser, g_value_get_string (value));
252       break;
253     case PROP_PREVIEW_TEXT:
254       gtk_font_chooser_set_preview_text (fontchooser, g_value_get_string (value));
255       break;
256     case PROP_SHOW_PREVIEW_ENTRY:
257       gtk_font_chooser_set_show_preview_entry (fontchooser, g_value_get_boolean (value));
258     default:
259       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
260       break;
261     }
262 }
263
264 static void
265 gtk_font_chooser_get_property (GObject         *object,
266                                  guint            prop_id,
267                                  GValue          *value,
268                                  GParamSpec      *pspec)
269 {
270   GtkFontChooser *fontchooser;
271
272   fontchooser = GTK_FONT_CHOOSER (object);
273
274   switch (prop_id)
275     {
276     case PROP_FONT_NAME:
277       g_value_take_string (value, gtk_font_chooser_get_font_name (fontchooser));
278       break;
279     case PROP_PREVIEW_TEXT:
280       g_value_set_string (value, gtk_font_chooser_get_preview_text (fontchooser));
281       break;
282     case PROP_SHOW_PREVIEW_ENTRY:
283       g_value_set_boolean (value, gtk_font_chooser_get_show_preview_entry (fontchooser));
284     default:
285       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
286       break;
287     }
288 }
289
290 void
291 refilter_and_focus (GtkFontChooserPrivate *priv)
292 {
293   GtkTreeIter  iter;
294   GtkTreeView *treeview = GTK_TREE_VIEW (priv->family_face_list);
295   GtkTreePath *path = gtk_tree_path_new ();
296
297   gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));
298
299   if (!path)
300     return;
301
302   gtk_tree_view_get_cursor (treeview, &path, NULL);
303
304   if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->filter), &iter, path))
305     {
306       gtk_tree_path_free (path);
307       return;
308     }
309
310   gtk_tree_view_scroll_to_cell (treeview, path, NULL, TRUE, 0.5, 0.5);
311   gtk_tree_path_free (path);
312 }
313
314 void
315 deleted_text_cb (GtkEntryBuffer *buffer,
316                  guint           position,
317                  guint           n_chars,
318                  gpointer        user_data)
319 {
320   GtkFontChooserPrivate *priv  = (GtkFontChooserPrivate*)user_data;
321   GtkWidget             *entry = priv->search_entry;
322   
323   if (gtk_entry_buffer_get_length (buffer) == 0)
324     {
325       gtk_entry_set_icon_from_stock (GTK_ENTRY (entry),
326                                      GTK_ENTRY_ICON_SECONDARY,
327                                      GTK_STOCK_FIND);
328     }
329
330   gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));
331 }
332
333 void
334 inserted_text_cb (GtkEntryBuffer *buffer,
335                   guint           position,
336                   gchar          *chars,
337                   guint           n_chars,
338                   gpointer        user_data) 
339 {
340   GtkFontChooserPrivate *priv  = (GtkFontChooserPrivate*)user_data;
341   GtkWidget             *entry = priv->search_entry;
342
343   if (g_strcmp0 (gtk_entry_get_icon_stock (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY),
344                  GTK_STOCK_CLEAR))
345     gtk_entry_set_icon_from_stock (GTK_ENTRY (entry),
346                                    GTK_ENTRY_ICON_SECONDARY,
347                                    GTK_STOCK_CLEAR);
348
349
350   gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));
351 }
352
353 void
354 icon_press_cb (GtkEntry             *entry,
355                GtkEntryIconPosition  pos,
356                GdkEvent             *event,
357                gpointer              user_data)
358 {
359   gtk_entry_buffer_delete_text (gtk_entry_get_buffer (entry), 0, -1);
360 }
361
362 void
363 slider_change_cb (GtkAdjustment *adjustment, gpointer data)
364 {
365   GtkFontChooserPrivate *priv = (GtkFontChooserPrivate*)data;
366
367   /* If we set the silder value manually, we ignore this callback */
368   if (priv->ignore_slider)
369     {
370       priv->ignore_slider = FALSE;
371       return;
372     }
373
374   gtk_adjustment_set_value (gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON(priv->size_spin)),
375                             gtk_adjustment_get_value (adjustment));
376 }
377
378 void
379 spin_change_cb (GtkAdjustment *adjustment, gpointer data)
380 {
381   PangoFontDescription    *desc;
382   GtkFontChooser        *fontchooser = (GtkFontChooser*)data;
383   GtkFontChooserPrivate *priv    = fontchooser->priv;
384
385   gdouble size = gtk_adjustment_get_value (adjustment);
386   
387   GtkAdjustment *slider_adj = gtk_range_get_adjustment (GTK_RANGE (priv->size_slider));
388
389   /* We ignore the slider value change callback for both of this set_value call */
390   priv->ignore_slider = TRUE;
391   if (size < gtk_adjustment_get_lower (slider_adj))
392     gtk_adjustment_set_value (slider_adj, gtk_adjustment_get_lower (slider_adj));
393   else if (size > gtk_adjustment_get_upper (slider_adj))
394     gtk_adjustment_set_value (slider_adj, gtk_adjustment_get_upper (slider_adj));
395   else
396     gtk_adjustment_set_value (slider_adj, size);
397
398   priv->size = ((gint)gtk_adjustment_get_value (adjustment)) * PANGO_SCALE;
399
400   desc = pango_context_get_font_description (gtk_widget_get_pango_context (priv->preview));
401   pango_font_description_set_size (desc, priv->size);
402   gtk_widget_override_font (priv->preview, desc);
403
404
405   /* Deprecated */
406   if (priv->size_list)
407     {
408       priv->ignore_size = TRUE;
409       update_size_list_selection (fontchooser);
410     }
411   
412   g_object_notify (G_OBJECT (fontchooser), "font-name");
413
414   gtk_widget_queue_draw (priv->preview);
415 }
416
417 void
418 set_range_marks (GtkFontChooserPrivate *priv,
419                  GtkWidget* size_slider,
420                  gint* sizes,
421                  gint length)
422 {
423   GtkAdjustment *adj;
424   gint i;
425   gdouble value;
426
427   if (length<2)
428     {
429       sizes = (gint*)font_sizes;
430       length = FONT_SIZES_LENGTH;
431     }
432   
433   gtk_scale_clear_marks (GTK_SCALE (size_slider));
434   
435   adj = gtk_range_get_adjustment(GTK_RANGE (size_slider));
436   
437   gtk_adjustment_set_lower (adj, (gdouble) sizes[0]);
438   gtk_adjustment_set_upper (adj, (gdouble) sizes[length-1]);
439
440   value = gtk_adjustment_get_value (adj);
441   if (value > (gdouble) sizes[length-1])
442     {
443       gtk_adjustment_set_value (adj, (gdouble) sizes[length-1]);
444       priv->ignore_slider = TRUE;
445     }
446   else if (value < (gdouble) sizes[0])
447     {
448       gtk_adjustment_set_value (adj, (gdouble) sizes[0]);
449       priv->ignore_slider = TRUE; 
450     }
451   
452   /* Deprecated: just populate the marks in the scale after removal */
453   if (!priv->_size_model)
454     {
455       for (i=0; i<length; i++)
456         gtk_scale_add_mark (GTK_SCALE (size_slider),
457                             (gdouble) sizes[i],
458                             GTK_POS_BOTTOM, NULL);
459     }
460   else
461     {
462       GString *size_str = g_string_new (NULL);
463       gtk_list_store_clear (priv->_size_model);
464       
465       for (i=0; i<length; i++)
466         {
467           GtkTreeIter iter;
468
469           g_string_printf (size_str, "%d", sizes[i]);
470
471           gtk_scale_add_mark (GTK_SCALE (size_slider),
472                               (gdouble) sizes[i],
473                               GTK_POS_BOTTOM, NULL);
474
475           gtk_list_store_append (priv->_size_model, &iter);
476           gtk_list_store_set (priv->_size_model, &iter,
477                               0, sizes[i],
478                               1, size_str->str,
479                               -1);
480         }
481       g_string_free (size_str, TRUE);
482     }
483 }
484
485 void
486 cursor_changed_cb (GtkTreeView *treeview, gpointer data)
487 {
488   PangoFontFamily      *family;
489   PangoFontFace        *face;
490   PangoFontDescription *desc;
491   
492   gint *sizes;
493   gint  i, n_sizes;
494
495   GtkTreeIter iter;
496   GtkTreePath *path = gtk_tree_path_new ();
497   
498   GtkFontChooser *fontchooser = (GtkFontChooser*)data;
499   
500   gtk_tree_view_get_cursor (treeview, &path, NULL);
501   
502   if (!path)
503     return;
504
505   if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (fontchooser->priv->filter), &iter, path))
506     {
507       gtk_tree_path_free (path);
508       return;
509     } 
510   
511   
512   gtk_tree_model_get (GTK_TREE_MODEL (fontchooser->priv->filter), &iter,
513                       FACE_COLUMN, &face,
514                       FAMILY_COLUMN, &family,
515                       -1);
516
517   gtk_tree_view_scroll_to_cell (treeview, path, NULL, TRUE, 0.5, 0.5);
518
519   gtk_tree_path_free (path);
520   path = NULL;
521   
522   if (!face || !family)
523     {
524       g_object_unref (face);
525       g_object_unref (family);
526       return;
527     }
528
529   desc = pango_font_face_describe (face);
530   pango_font_description_set_size (desc, fontchooser->priv->size);
531   gtk_widget_override_font (fontchooser->priv->preview, desc);
532
533   pango_font_face_list_sizes (face, &sizes, &n_sizes);
534   /* It seems not many fonts actually have a sane set of sizes */
535   for (i=0; i<n_sizes; i++)
536     sizes[i] = sizes[i] / PANGO_SCALE;
537   
538   set_range_marks (fontchooser->priv, fontchooser->priv->size_slider, sizes, n_sizes);
539
540   gtk_font_chooser_ref_family (fontchooser, family);
541   gtk_font_chooser_ref_face   (fontchooser, face);
542
543   /* Deprecated: Remove if clause after removal */
544   if (fontchooser->priv->_font_model)
545     update_font_list_selection (fontchooser);
546
547   /* Free resources */
548   g_object_unref ((gpointer)family);
549   g_object_unref ((gpointer)face);
550   pango_font_description_free(desc);
551
552   g_object_notify (G_OBJECT (fontchooser), "font-name");
553 }
554
555 gboolean
556 zoom_preview_cb (GtkWidget *scrolled_window, GdkEventScroll *event, gpointer data)
557 {
558   GtkFontChooserPrivate *priv = (GtkFontChooserPrivate*)data;
559
560   GtkAdjustment *adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->size_spin));
561
562   if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_RIGHT)
563     gtk_adjustment_set_value (adj,
564                               gtk_adjustment_get_value (adj) +
565                               gtk_adjustment_get_step_increment (adj));
566   else if (event->direction == GDK_SCROLL_DOWN || event->direction == GDK_SCROLL_LEFT)
567     gtk_adjustment_set_value (adj,
568                               gtk_adjustment_get_value (adj) -
569                               gtk_adjustment_get_step_increment (adj));
570   return TRUE;
571 }
572
573 static void
574 gtk_font_chooser_init (GtkFontChooser *fontchooser)
575 {
576   GtkFontChooserPrivate *priv;
577   PangoFontDescription    *font_desc;
578   GtkWidget               *scrolled_win;
579   GtkWidget               *preview_and_size;
580   GtkWidget               *size_controls;
581
582   fontchooser->priv = G_TYPE_INSTANCE_GET_PRIVATE (fontchooser,
583                                                    GTK_TYPE_FONT_CHOOSER,
584                                                    GtkFontChooserPrivate);
585
586   priv = fontchooser->priv;
587
588   /* Deprecated: These members will not exist after removal */
589   priv->size_list = NULL;
590   priv->font_list = NULL;
591   priv->face_list = NULL;
592
593   priv->_size_model = NULL;
594   priv->_font_model = NULL;
595   priv->_face_model = NULL;
596
597   priv->ignore_size = FALSE;
598   priv->ignore_face = FALSE;
599   priv->ignore_font = FALSE;
600
601   /* Default preview string  */
602   priv->preview_text = g_strdup (pango_language_get_sample_string (NULL));
603   priv->show_preview_entry = TRUE;
604
605   /* Getting the default size */
606   font_desc  = pango_context_get_font_description (gtk_widget_get_pango_context (GTK_WIDGET (fontchooser)));
607   priv->size = pango_font_description_get_size (font_desc);
608   priv->face = NULL;
609   priv->family = NULL;
610
611   gtk_widget_push_composite_child ();
612
613   /* Creating fundamental widgets for the private struct */
614   priv->search_entry = gtk_entry_new ();
615   priv->family_face_list = gtk_tree_view_new ();
616   priv->preview = gtk_entry_new ();
617   priv->size_slider = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL,
618                                                 (gdouble) font_sizes[0],
619                                                 (gdouble) font_sizes[FONT_SIZES_LENGTH - 1],
620                                                 1.0);
621
622   priv->size_spin = gtk_spin_button_new_with_range (0.0, (gdouble)(G_MAXINT / PANGO_SCALE), 1.0);
623
624   /** Bootstrapping widget layout **/
625   gtk_box_set_spacing (GTK_BOX (fontchooser), 6);
626   gtk_box_pack_start (GTK_BOX (fontchooser), priv->search_entry, FALSE, TRUE, 0);
627
628   /* Main font family/face view */
629   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
630   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
631                                   GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
632   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
633                                        GTK_SHADOW_ETCHED_IN);
634   gtk_container_add (GTK_CONTAINER (scrolled_win), priv->family_face_list);
635
636   /* Alignment for the preview and size controls */
637   gtk_box_pack_start (GTK_BOX (fontchooser), scrolled_win, TRUE, TRUE, 0);
638
639   preview_and_size = gtk_vbox_new (TRUE, 0);
640   gtk_box_set_homogeneous (GTK_BOX (preview_and_size), FALSE);
641   gtk_box_set_spacing (GTK_BOX (preview_and_size), 6);
642
643   /* The preview entry needs a scrolled window to make sure we have a */
644   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
645   priv->preview_scrolled_window = scrolled_win;
646   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
647                                   GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
648   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
649                                        GTK_SHADOW_ETCHED_IN);
650   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win),
651                                          priv->preview);
652   gtk_box_pack_start (GTK_BOX (preview_and_size), scrolled_win, FALSE, FALSE, 0);
653   
654   /* Setting the size requests for various widgets */
655   gtk_widget_set_size_request (GTK_WIDGET (fontchooser), FONT_CHOOSER_WIDTH, FONT_CHOOSER_HEIGHT);
656   gtk_widget_set_size_request (scrolled_win,  -1, PREVIEW_HEIGHT);
657   gtk_widget_set_size_request (priv->preview, -1, PREVIEW_HEIGHT - 6);
658
659   /* Unset the frame on the preview entry */
660   gtk_entry_set_has_frame (GTK_ENTRY (priv->preview), FALSE);
661
662   /* Packing the slider and the spin in a hbox */
663   size_controls = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
664   gtk_scale_set_draw_value (GTK_SCALE (priv->size_slider), FALSE);
665   gtk_box_set_spacing (GTK_BOX (size_controls), 6);
666   gtk_box_pack_start  (GTK_BOX (size_controls), priv->size_slider, TRUE, TRUE, 0);
667   gtk_box_pack_start  (GTK_BOX (size_controls), priv->size_spin, FALSE, TRUE, 0);
668   
669   gtk_widget_set_valign (priv->size_spin, GTK_ALIGN_START);
670
671   gtk_box_pack_start (GTK_BOX (preview_and_size), size_controls, FALSE, FALSE, 0);
672
673   gtk_box_pack_start (GTK_BOX (fontchooser), GTK_WIDGET(preview_and_size), FALSE, TRUE, 0);
674   
675   gtk_adjustment_set_value (gtk_range_get_adjustment (GTK_RANGE (priv->size_slider)),
676                             (gdouble)(priv->size / PANGO_SCALE));
677   gtk_adjustment_set_value (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->size_spin)),
678                             (gdouble)(priv->size / PANGO_SCALE));
679
680   gtk_widget_show_all (GTK_WIDGET (fontchooser));
681   gtk_widget_hide     (GTK_WIDGET (fontchooser));
682
683   /* Treeview column and model bootstrapping */
684   gtk_font_chooser_bootstrap_fontlist (fontchooser);
685   
686   /* Set default preview text */
687   gtk_entry_set_text (GTK_ENTRY (priv->preview),
688                       pango_language_get_sample_string (NULL));
689   
690   /* Set search icon and place holder text */
691   gtk_entry_set_icon_from_stock (GTK_ENTRY (priv->search_entry),
692                                  GTK_ENTRY_ICON_SECONDARY,
693                                  GTK_STOCK_FIND);
694   gtk_entry_set_placeholder_text (GTK_ENTRY (priv->search_entry), _("Search font name"));
695   
696   /** Callback connections **/
697   /* Connect to callback for the live search text entry */
698   g_signal_connect (G_OBJECT (gtk_entry_get_buffer (GTK_ENTRY (priv->search_entry))),
699                     "deleted-text", G_CALLBACK (deleted_text_cb), priv);
700   g_signal_connect (G_OBJECT (gtk_entry_get_buffer (GTK_ENTRY (priv->search_entry))),
701                     "inserted-text", G_CALLBACK (inserted_text_cb), priv);
702   g_signal_connect (G_OBJECT (priv->search_entry),
703                     "icon-press", G_CALLBACK (icon_press_cb), priv);
704
705   /* Size controls callbacks */
706   g_signal_connect (G_OBJECT (gtk_range_get_adjustment (GTK_RANGE (priv->size_slider))),
707                     "value-changed", G_CALLBACK (slider_change_cb), priv);
708   g_signal_connect (G_OBJECT (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->size_spin))),
709                     "value-changed", G_CALLBACK (spin_change_cb), fontchooser);
710   priv->ignore_slider = FALSE;
711   
712   /* Font selection callback */
713   g_signal_connect (G_OBJECT (priv->family_face_list), "cursor-changed",
714                     G_CALLBACK (cursor_changed_cb),    fontchooser);
715
716   /* Zoom on preview scroll*/
717   g_signal_connect (G_OBJECT (scrolled_win),      "scroll-event",
718                     G_CALLBACK (zoom_preview_cb), priv);
719
720   g_signal_connect (G_OBJECT (priv->size_slider), "scroll-event",
721                     G_CALLBACK (zoom_preview_cb), priv);
722
723   set_range_marks (priv, priv->size_slider, (gint*)font_sizes, FONT_SIZES_LENGTH);
724
725   /* Set default focus */
726   gtk_widget_pop_composite_child();
727 }
728
729 /**
730  * gtk_font_chooser_new:
731  *
732  * Creates a new #GtkFontChooser.
733  *
734  * Return value: a new #GtkFontChooser
735  */
736 GtkWidget *
737 gtk_font_chooser_new (void)
738 {
739   GtkFontChooser *fontchooser;
740   
741   fontchooser = g_object_new (GTK_TYPE_FONT_CHOOSER, NULL);
742   
743   return GTK_WIDGET (fontchooser);
744 }
745
746 static int
747 cmp_families (const void *a, const void *b)
748 {
749   const char *a_name = pango_font_family_get_name (*(PangoFontFamily **)a);
750   const char *b_name = pango_font_family_get_name (*(PangoFontFamily **)b);
751
752   return g_utf8_collate (a_name, b_name);
753 }
754
755 static void 
756 populate_list (GtkFontChooser *fontchooser, GtkTreeView* treeview, GtkListStore* model)
757 {
758   GtkStyleContext      *style_context;
759   GdkRGBA               g_color;
760   PangoColor            p_color;
761   gchar                *color_string;
762   PangoFontDescription *default_font;
763
764   GtkTreeIter   match_row;
765   GtkTreePath  *path;
766
767   gint n_families, i;  
768   PangoFontFamily **families;
769
770   GString     *tmp = g_string_new (NULL);
771   GString     *family_and_face = g_string_new (NULL);
772
773   pango_context_list_families (gtk_widget_get_pango_context (GTK_WIDGET (treeview)),
774                                &families,
775                                &n_families);
776
777   qsort (families, n_families, sizeof (PangoFontFamily *), cmp_families);
778
779   gtk_list_store_clear (model);
780
781   /* Get row header font color */
782   style_context = gtk_widget_get_style_context (GTK_WIDGET (treeview));
783   gtk_style_context_get_color (style_context,
784                                GTK_STATE_FLAG_NORMAL | GTK_STATE_FLAG_INSENSITIVE,
785                                &g_color);
786
787   p_color.red   = (guint16)((gdouble)G_MAXUINT16 * g_color.red);
788   p_color.green = (guint16)((gdouble)G_MAXUINT16 * g_color.green);
789   p_color.blue  = (guint16)((gdouble)G_MAXUINT16 * g_color.blue);
790   color_string  = pango_color_to_string (&p_color);
791
792   /* Get theme font */
793   default_font  = (PangoFontDescription*) gtk_style_context_get_font (style_context,
794                                                                       GTK_STATE_NORMAL);
795
796   /* Iterate over families and faces */
797   for (i=0; i<n_families; i++)
798     {
799       GtkTreeIter     iter;
800       PangoFontFace **faces;
801       
802       int             j, n_faces;
803       const gchar    *fam_name = pango_font_family_get_name (families[i]);
804
805       pango_font_family_list_faces (families[i], &faces, &n_faces);
806       
807       for (j=0; j<n_faces; j++)
808         {
809           PangoFontDescription *pango_desc = pango_font_face_describe (faces[j]);
810           const gchar *face_name = pango_font_face_get_face_name (faces[j]);
811           gchar       *font_desc = pango_font_description_to_string (pango_desc);
812           
813           /* foreground_color, family_name, face_name, desc, sample string */
814           g_string_printf (family_and_face, "%s %s",
815                                             fam_name,
816                                             face_name);
817           
818           g_string_printf (tmp, ROW_FORMAT_STRING,
819                            color_string,
820                            family_and_face->str,
821                            font_desc,
822                            fontchooser->priv->preview_text);
823
824           gtk_list_store_append (model, &iter);
825           gtk_list_store_set (model, &iter,
826                               FAMILY_COLUMN, families[i],
827                               FACE_COLUMN, faces[j],
828                               PREVIEW_TITLE_COLUMN, family_and_face->str,
829                               PREVIEW_TEXT_COLUMN, tmp->str,
830                               -1);
831
832           /* Select the first font or the default font/face from the style context */
833           if ((i == 0 && j == 0) ||
834               (!strcmp (fam_name, pango_font_description_get_family (default_font)) && j == 0))
835             match_row = iter;
836
837           pango_font_description_free(pango_desc);
838           g_free (font_desc);
839         }
840
841       g_free (faces);
842     }
843
844   path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &match_row);
845
846   if (path)
847     {
848       gtk_tree_view_set_cursor (treeview, path, NULL, FALSE);
849       gtk_tree_view_scroll_to_cell (treeview, path, NULL, TRUE, 0.5, 0.5);
850       gtk_tree_path_free(path);
851     }
852
853   g_string_free (family_and_face, TRUE);
854   g_string_free (tmp, TRUE);
855   g_free (color_string);
856   g_free (families);
857 }
858
859 gboolean
860 visible_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
861 {
862   gboolean result = FALSE;
863   GtkFontChooserPrivate *priv = (GtkFontChooserPrivate*) data;
864
865   const gchar *search_text = (const gchar*)gtk_entry_get_text (GTK_ENTRY (priv->search_entry));
866   gchar       *font_name;
867   gchar       *font_name_casefold;
868   gchar       *search_text_casefold;
869
870   gtk_tree_model_get (model, iter,
871                       PREVIEW_TITLE_COLUMN, &font_name,
872                       -1);
873
874   /* Covering some corner cases to speed up the result */
875   if (font_name == NULL ||
876       strlen (search_text) > strlen (font_name))
877     {
878       g_free (font_name);
879       return FALSE;
880     }  
881   if (strlen (search_text) == 0)
882     {
883       g_free (font_name);
884       return TRUE;
885     }
886   
887   font_name_casefold = g_utf8_casefold (font_name, -1);
888   search_text_casefold = g_utf8_casefold (search_text, -1);
889   
890   if (g_strrstr (font_name_casefold, search_text_casefold))
891     result = TRUE;
892
893   g_free (search_text_casefold);
894   g_free (font_name_casefold);
895   g_free (font_name);
896   return result;
897 }
898
899 static void
900 gtk_font_chooser_bootstrap_fontlist (GtkFontChooser* fontchooser)
901 {
902   GtkTreeView       *treeview = GTK_TREE_VIEW (fontchooser->priv->family_face_list);
903   GtkCellRenderer   *cell;
904   GtkTreeViewColumn *col;
905
906   fontchooser->priv->model = gtk_list_store_new (4,
907                                              PANGO_TYPE_FONT_FAMILY,
908                                              PANGO_TYPE_FONT_FACE,
909                                              G_TYPE_STRING,
910                                              G_TYPE_STRING);
911
912   fontchooser->priv->filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fontchooser->priv->model),
913                                                      NULL);
914   g_object_unref (fontchooser->priv->model);
915
916   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (fontchooser->priv->filter),
917                                           visible_func,
918                                           (gpointer)fontchooser->priv,
919                                           NULL);
920
921   gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (fontchooser->priv->filter));
922   g_object_unref (fontchooser->priv->filter);
923
924   gtk_tree_view_set_rules_hint      (treeview, TRUE);
925   gtk_tree_view_set_headers_visible (treeview, FALSE);
926
927   cell = gtk_cell_renderer_text_new ();
928   col = gtk_tree_view_column_new_with_attributes ("Family",
929                                                   cell,
930                                                   "markup", PREVIEW_TEXT_COLUMN,
931                                                   NULL);
932                                                   
933   g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
934
935   gtk_tree_view_append_column (treeview, col);
936
937   populate_list (fontchooser, treeview, fontchooser->priv->model);
938 }
939
940
941 static void
942 gtk_font_chooser_finalize (GObject *object)
943 {
944   GtkFontChooser *fontchooser = GTK_FONT_CHOOSER (object);
945
946   gtk_font_chooser_ref_family (fontchooser, NULL);
947   gtk_font_chooser_ref_face (fontchooser, NULL);
948
949   /* Deprecated: Remove if clause after removal */
950   if (fontchooser->priv->size_list)
951     {
952       g_object_unref (fontchooser->priv->size_list);
953       g_object_unref (fontchooser->priv->font_list);
954       g_object_unref (fontchooser->priv->face_list);
955     }
956
957   G_OBJECT_CLASS (gtk_font_chooser_parent_class)->finalize (object);
958 }
959
960
961 static void
962 gtk_font_chooser_screen_changed (GtkWidget *widget,
963                                    GdkScreen *previous_screen)
964 {
965   GtkFontChooser *fontchooser = GTK_FONT_CHOOSER (widget);
966
967   populate_list (fontchooser,
968                  GTK_TREE_VIEW (fontchooser->priv->family_face_list),
969                  fontchooser->priv->model);
970   return;
971 }
972
973 static void
974 gtk_font_chooser_style_updated (GtkWidget *widget)
975 {
976   GtkFontChooser *fontchooser = GTK_FONT_CHOOSER (widget);
977
978   GTK_WIDGET_CLASS (gtk_font_chooser_parent_class)->style_updated (widget);
979
980   populate_list (fontchooser,
981                  GTK_TREE_VIEW (fontchooser->priv->family_face_list),
982                  fontchooser->priv->model);
983   return;
984 }
985
986 static void
987 gtk_font_chooser_ref_family (GtkFontChooser *fontchooser,
988                                PangoFontFamily  *family)
989 {
990   GtkFontChooserPrivate *priv = fontchooser->priv;
991
992   if (family)
993     family = g_object_ref (family);
994   if (priv->family)
995     g_object_unref (priv->family);
996   priv->family = family;
997 }
998
999 static void
1000 gtk_font_chooser_ref_face (GtkFontChooser *fontchooser,
1001                              PangoFontFace    *face)
1002 {
1003   GtkFontChooserPrivate *priv = fontchooser->priv;
1004
1005   if (face)
1006     face = g_object_ref (face);
1007   if (priv->face)
1008     g_object_unref (priv->face);
1009   priv->face = face;
1010 }
1011
1012 /* Deprecated: All these functions aid deprecated functionality */
1013 static void
1014 populate_font_model (GtkFontChooser *fontchooser)
1015 {
1016   gint                      n_families, i;
1017   PangoFontFamily         **families;
1018   GtkFontChooserPrivate    *priv = fontchooser->priv;
1019   GtkTreePath              *path;
1020
1021   pango_context_list_families (gtk_widget_get_pango_context (GTK_WIDGET (fontchooser)),
1022                                &families,
1023                                &n_families);
1024
1025   qsort (families, n_families, sizeof (PangoFontFamily *), cmp_families);
1026
1027   gtk_list_store_clear (priv->_font_model);
1028   
1029   for (i=0; i<n_families; i++)
1030     {
1031       GtkTreeIter  iter;
1032
1033       gtk_list_store_append (priv->_font_model, &iter);
1034       gtk_list_store_set (priv->_font_model, &iter,
1035                           0, families[i],
1036                           1, pango_font_family_get_name (families[i]),
1037                           -1);
1038       if (priv->family &&
1039           !strcmp (pango_font_family_get_name (families[i]),
1040                    pango_font_family_get_name (priv->family)))
1041         {
1042           path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->_face_model),
1043                                           &iter);
1044           if (path)
1045             {
1046               GtkWidget *tv = gtk_bin_get_child (GTK_BIN (priv->font_list));
1047               gtk_tree_view_set_cursor (GTK_TREE_VIEW (tv),
1048                                         path,
1049                                         NULL,
1050                                         FALSE);
1051               gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (tv),
1052                                             path, NULL, TRUE, 0.5, 0.5);
1053               gtk_tree_path_free (path);
1054             }
1055         }
1056     }
1057
1058   g_free (families);
1059 }
1060
1061 static void
1062 update_font_list_selection (GtkFontChooser *fontchooser)
1063 {
1064   GtkTreeIter              iter;
1065   gboolean                 valid;
1066   GtkFontChooserPrivate *priv = fontchooser->priv;
1067   gchar                   *family_name;
1068
1069   valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->_font_model), &iter);
1070   while (valid)
1071     {
1072       GtkWidget   *tv;
1073       GtkTreePath *path;
1074       gtk_tree_model_get (GTK_TREE_MODEL (priv->_font_model), &iter,
1075                           1, &family_name,
1076                           -1);
1077       if (strcmp (family_name, pango_font_family_get_name (priv->family)))
1078         {
1079           gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->_font_model), &iter);
1080           g_free (family_name);
1081           continue;
1082         }
1083       path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->_font_model), &iter);
1084
1085       if (!path)
1086         {
1087           g_free (family_name);
1088           break;
1089         }
1090
1091       tv = gtk_bin_get_child (GTK_BIN (priv->font_list));
1092
1093       priv->ignore_font = TRUE;
1094       gtk_tree_view_set_cursor (GTK_TREE_VIEW (tv), path, NULL, FALSE);
1095       gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (tv), path, NULL, TRUE, 0.5, 0.5);
1096
1097       /* Free resources */
1098       gtk_tree_path_free (path);
1099       g_free (family_name);
1100       break;
1101     }
1102
1103   update_face_model (fontchooser, FALSE);
1104 }
1105
1106 static void
1107 update_face_model (GtkFontChooser *fontchooser, gboolean first)
1108 {
1109   GtkFontChooserPrivate  *priv = fontchooser->priv;
1110   PangoFontFace           **faces;
1111   int                       i, n_faces;
1112
1113   pango_font_family_list_faces (priv->family, &faces, &n_faces);
1114
1115   gtk_list_store_clear (priv->_face_model);
1116
1117   for (i=0; i<n_faces; i++)
1118     {
1119       GtkTreeIter  iter;
1120
1121       gtk_list_store_append (priv->_face_model, &iter);
1122       gtk_list_store_set (priv->_face_model, &iter,
1123                           0, faces[i],
1124                           1, pango_font_face_get_face_name (faces[i]),
1125                           -1);
1126
1127       if ((!first && faces[i] == priv->face) ||
1128           (first && i == 0))
1129         {
1130           GtkTreePath *path;
1131           GtkWidget *tv;
1132
1133           path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->_face_model), &iter);
1134           if (!path)
1135             continue;
1136
1137           tv = gtk_bin_get_child (GTK_BIN (priv->face_list));
1138
1139           if (!first)
1140             priv->ignore_face = TRUE;
1141
1142           gtk_tree_view_set_cursor (GTK_TREE_VIEW (tv), path, NULL, FALSE);
1143
1144           gtk_tree_path_free (path);
1145
1146           if (first)
1147               gtk_font_chooser_ref_face (fontchooser, faces[i]);
1148         }
1149     }
1150
1151   update_size_list_selection (fontchooser);
1152
1153   g_object_notify (G_OBJECT (fontchooser), "font-name");
1154 }
1155
1156 static void
1157 update_size_list_selection (GtkFontChooser *fontchooser)
1158 {
1159   GtkTreeIter              iter;
1160   gboolean                 valid;
1161   GtkFontChooserPrivate *priv = fontchooser->priv;
1162   GtkWidget               *tv = gtk_bin_get_child (GTK_BIN (priv->size_list));
1163
1164   gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (tv)));
1165
1166   valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->_size_model), &iter);
1167   while (valid)
1168     {
1169       gint         size;
1170       gtk_tree_model_get (GTK_TREE_MODEL (priv->_size_model), &iter,
1171                           0, &size,
1172                           -1);
1173
1174       if (size * PANGO_SCALE == priv->size)
1175         {
1176           GtkTreePath *path;
1177
1178
1179           path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->_size_model), &iter);
1180           if (!path)
1181             break;
1182
1183  
1184           priv->ignore_size = TRUE;
1185           gtk_tree_view_set_cursor (GTK_TREE_VIEW (tv), path, NULL, FALSE);
1186
1187           gtk_tree_path_free (path);
1188           break;
1189         }
1190       valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->_size_model), &iter);
1191     }
1192 }
1193
1194
1195 static void
1196 select_family_and_face (GtkFontChooser *fontchooser)
1197 {
1198   GtkTreeIter              iter;
1199   gboolean                 valid;
1200   GtkFontChooserPrivate *priv = fontchooser->priv;
1201   PangoFontFace           *face;
1202   PangoFontFamily         *family;
1203
1204   gtk_entry_set_text (GTK_ENTRY (priv->search_entry), "");
1205
1206   valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->filter), &iter);
1207   while (valid)
1208     {
1209       gtk_tree_model_get (GTK_TREE_MODEL (priv->filter), &iter,
1210                           FACE_COLUMN,   &face,
1211                           FAMILY_COLUMN, &family, 
1212                           -1);
1213
1214       if (face == priv->face && family == priv->family)
1215         {
1216           GtkTreePath *path;
1217
1218           path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->filter), &iter);
1219           if (!path)
1220           {
1221             g_object_unref (face);
1222             g_object_unref (family);
1223             break;
1224           }
1225
1226           priv->ignore_size = TRUE;
1227           gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->family_face_list), path, NULL, FALSE);
1228
1229           gtk_tree_path_free (path);
1230           g_object_unref (face);
1231           g_object_unref (family);
1232           break;
1233         }
1234
1235       g_object_unref (face);
1236       g_object_unref (family);
1237       valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->filter), &iter);
1238     }
1239 }
1240
1241
1242 static void
1243 family_list_cursor_changed_cb (GtkTreeView *treeview, gpointer data)
1244 {
1245   GtkWidget        *tv;
1246   GtkTreeIter       iter;
1247   GtkTreePath      *path;
1248   GtkFontChooser *fontchooser = (GtkFontChooser*)data;
1249   PangoFontFamily  *font;
1250
1251   if (fontchooser->priv->ignore_font)
1252     {
1253       fontchooser->priv->ignore_font = FALSE;
1254       return;
1255     }
1256
1257   tv = gtk_bin_get_child (GTK_BIN (fontchooser->priv->font_list));
1258   gtk_tree_view_get_cursor (GTK_TREE_VIEW (tv), &path, NULL);
1259
1260   if (!path)
1261     return;
1262
1263   gtk_tree_model_get_iter (GTK_TREE_MODEL (fontchooser->priv->_font_model),
1264                            &iter,
1265                            path);
1266   
1267   gtk_tree_model_get (GTK_TREE_MODEL (fontchooser->priv->_font_model), &iter,
1268                       0, &font,
1269                       -1);
1270
1271   gtk_font_chooser_ref_family (fontchooser, font);
1272   update_face_model (fontchooser, TRUE);
1273
1274   fontchooser->priv->ignore_font = TRUE;
1275   select_family_and_face (fontchooser);
1276
1277   gtk_tree_path_free (path);
1278   g_object_unref (font);
1279 }
1280
1281 static void
1282 face_list_cursor_changed_cb (GtkTreeView *treeview, gpointer data)
1283 {
1284   GtkWidget        *tv;
1285   GtkTreeIter       iter;
1286   GtkTreePath      *path;
1287   GtkFontChooser *fontchooser = (GtkFontChooser*)data;
1288   PangoFontFace    *face;
1289
1290   if (fontchooser->priv->ignore_face)
1291     {
1292       fontchooser->priv->ignore_face = FALSE;
1293       return;
1294     }
1295
1296   tv = gtk_bin_get_child (GTK_BIN (fontchooser->priv->face_list));
1297   gtk_tree_view_get_cursor (GTK_TREE_VIEW (tv), &path, NULL);
1298
1299   if (!path)
1300     return;
1301
1302   gtk_tree_model_get_iter (GTK_TREE_MODEL (fontchooser->priv->_face_model),
1303                            &iter,
1304                            path);
1305   
1306   gtk_tree_model_get (GTK_TREE_MODEL (fontchooser->priv->_face_model), &iter,
1307                       0, &face,
1308                       -1);
1309
1310   gtk_font_chooser_ref_face (fontchooser, face);
1311
1312   fontchooser->priv->ignore_face = TRUE;
1313   select_family_and_face (fontchooser);
1314
1315   gtk_tree_path_free (path);
1316   g_object_unref (face);
1317 }
1318
1319 static void
1320 size_list_cursor_changed_cb (GtkTreeView *treeview, gpointer data)
1321 {
1322   GtkWidget        *tv;
1323   GtkTreeIter       iter;
1324   GtkTreePath      *path;
1325   GtkFontChooser *fontchooser = (GtkFontChooser*)data;
1326   gint              value;
1327
1328   if (fontchooser->priv->ignore_size)
1329     {
1330       fontchooser->priv->ignore_size = FALSE;
1331       return;
1332     }
1333
1334   tv = gtk_bin_get_child (GTK_BIN (fontchooser->priv->size_list));
1335   gtk_tree_view_get_cursor (GTK_TREE_VIEW (tv), &path, NULL);
1336
1337   if (!path)
1338     return;
1339
1340   gtk_tree_model_get_iter (GTK_TREE_MODEL (fontchooser->priv->_size_model),
1341                            &iter,
1342                            path);
1343   
1344   gtk_tree_model_get (GTK_TREE_MODEL (fontchooser->priv->_size_model), &iter,
1345                       0, &value,
1346                       -1);
1347
1348   gtk_spin_button_set_value (GTK_SPIN_BUTTON (fontchooser->priv->size_spin), value);
1349   gtk_tree_path_free (path);
1350 }
1351
1352 static void
1353 initialize_deprecated_widgets (GtkFontChooser *fontchooser)
1354 {
1355   GtkTreeViewColumn       *col;
1356   GtkFontChooserPrivate *priv = fontchooser->priv;
1357
1358   GtkWidget *size_list;
1359   GtkWidget *font_list;
1360   GtkWidget *face_list;
1361
1362   priv->_size_model = gtk_list_store_new (2, G_TYPE_INT, G_TYPE_STRING);
1363   priv->_font_model = gtk_list_store_new (2, PANGO_TYPE_FONT_FAMILY, G_TYPE_STRING);
1364   priv->_face_model = gtk_list_store_new (2, PANGO_TYPE_FONT_FACE,   G_TYPE_STRING);
1365
1366   size_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (priv->_size_model));
1367   font_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (priv->_font_model));
1368   face_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (priv->_face_model));
1369
1370   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (size_list), FALSE);
1371   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (font_list), FALSE);
1372   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (face_list), FALSE);
1373
1374   g_object_unref (priv->_size_model);
1375   g_object_unref (priv->_font_model);
1376   g_object_unref (priv->_face_model);
1377
1378   col = gtk_tree_view_column_new_with_attributes ("Size",
1379                                                   gtk_cell_renderer_text_new (),
1380                                                   "text", 1,
1381                                                   NULL);
1382   gtk_tree_view_append_column (GTK_TREE_VIEW (size_list), col);
1383
1384   col = gtk_tree_view_column_new_with_attributes ("Family",
1385                                                   gtk_cell_renderer_text_new (),
1386                                                   "text", 1,
1387                                                   NULL);
1388   gtk_tree_view_append_column (GTK_TREE_VIEW (font_list), col);
1389
1390   col = gtk_tree_view_column_new_with_attributes ("Face",
1391                                                   gtk_cell_renderer_text_new (),
1392                                                   "text", 1,
1393                                                   NULL);
1394   gtk_tree_view_append_column (GTK_TREE_VIEW (face_list), col);
1395
1396
1397   priv->font_list = gtk_scrolled_window_new (NULL, NULL);
1398   priv->face_list = gtk_scrolled_window_new (NULL, NULL);
1399   priv->size_list = gtk_scrolled_window_new (NULL, NULL);
1400
1401   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->font_list),
1402                                   GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1403   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->face_list),
1404                                   GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1405   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->size_list),
1406                                   GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1407
1408   gtk_container_add (GTK_CONTAINER (priv->font_list), font_list);
1409   gtk_container_add (GTK_CONTAINER (priv->face_list), face_list);
1410   gtk_container_add (GTK_CONTAINER (priv->size_list), size_list);
1411
1412   g_signal_connect (G_OBJECT (font_list), "cursor-changed",
1413                     G_CALLBACK (family_list_cursor_changed_cb), fontchooser);
1414
1415   g_signal_connect (G_OBJECT (face_list), "cursor-changed",
1416                     G_CALLBACK (face_list_cursor_changed_cb), fontchooser);
1417
1418   g_signal_connect (G_OBJECT (size_list), "cursor-changed",
1419                     G_CALLBACK (size_list_cursor_changed_cb), fontchooser);
1420
1421   populate_font_model (fontchooser);
1422   cursor_changed_cb (GTK_TREE_VIEW (priv->family_face_list), fontchooser);
1423 }
1424
1425 /*****************************************************************************
1426  * These functions are the main public interface for getting/setting the font.
1427  *****************************************************************************/
1428
1429 /**
1430  * gtk_font_chooser_get_family:
1431  * @fontchooser: a #GtkFontChooser
1432  *
1433  * Gets the #PangoFontFamily representing the selected font family.
1434  *
1435  * Return value: (transfer none): A #PangoFontFamily representing the
1436  *     selected font family. Font families are a collection of font
1437  *     faces. The returned object is owned by @fontchooser and must not
1438  *     be modified or freed.
1439  *
1440  * Since: 2.14
1441  */
1442 PangoFontFamily *
1443 gtk_font_chooser_get_family (GtkFontChooser *fontchooser)
1444 {
1445   g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), NULL);
1446
1447   return fontchooser->priv->family;
1448 }
1449
1450 /**
1451  * gtk_font_chooser_get_face:
1452  * @fontchooser: a #GtkFontChooser
1453  *
1454  * Gets the #PangoFontFace representing the selected font group
1455  * details (i.e. family, slant, weight, width, etc).
1456  *
1457  * Return value: (transfer none): A #PangoFontFace representing the
1458  *     selected font group details. The returned object is owned by
1459  *     @fontchooser and must not be modified or freed.
1460  *
1461  * Since: 2.14
1462  */
1463 PangoFontFace *
1464 gtk_font_chooser_get_face (GtkFontChooser *fontchooser)
1465 {
1466   g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), NULL);
1467
1468   return fontchooser->priv->face;
1469 }
1470
1471 /**
1472  * gtk_font_chooser_get_size:
1473  * @fontchooser: a #GtkFontChooser
1474  *
1475  * The selected font size.
1476  *
1477  * Return value: A n integer representing the selected font size,
1478  *     or -1 if no font size is selected.
1479  *
1480  * Since: 2.14
1481  **/
1482 gint
1483 gtk_font_chooser_get_size (GtkFontChooser *fontchooser)
1484 {
1485   g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), -1);
1486
1487   return fontchooser->priv->size;
1488 }
1489
1490 /**
1491  * gtk_font_chooser_get_font_name:
1492  * @fontchooser: a #GtkFontChooser
1493  * 
1494  * Gets the currently-selected font name. 
1495  *
1496  * Note that this can be a different string than what you set with 
1497  * gtk_font_chooser_set_font_name(), as the font selection widget may 
1498  * normalize font names and thus return a string with a different structure. 
1499  * For example, "Helvetica Italic Bold 12" could be normalized to 
1500  * "Helvetica Bold Italic 12". Use pango_font_description_equal()
1501  * if you want to compare two font descriptions.
1502  * 
1503  * Return value: (transfer full) (allow-none): A string with the name of the
1504  *     current font, or %NULL if  no font is selected. You must free this
1505  *     string with g_free().
1506  */
1507 gchar *
1508 gtk_font_chooser_get_font_name (GtkFontChooser *fontchooser)
1509 {
1510   gchar                *font_name;
1511   PangoFontDescription *desc;
1512
1513   if (!fontchooser->priv->face)
1514     return NULL;
1515
1516   desc = pango_font_face_describe (fontchooser->priv->face);
1517   font_name = pango_font_description_to_string (desc);
1518   pango_font_description_free (desc);
1519   return font_name;
1520 }
1521
1522 /* This sets the current font, then selecting the appropriate list rows. */
1523
1524 /**
1525  * gtk_font_chooser_set_font_name:
1526  * @fontchooser: a #GtkFontChooser
1527  * @fontname: a font name like "Helvetica 12" or "Times Bold 18"
1528  * 
1529  * Sets the currently-selected font. 
1530  *
1531  * Note that the @fontchooser needs to know the screen in which it will appear 
1532  * for this to work; this can be guaranteed by simply making sure that the 
1533  * @fontchooser is inserted in a toplevel window before you call this function.
1534  * 
1535  * Return value: %TRUE if the font could be set successfully; %FALSE if no 
1536  *     such font exists or if the @fontchooser doesn't belong to a particular 
1537  *     screen yet.
1538  */
1539 gboolean
1540 gtk_font_chooser_set_font_name (GtkFontChooser *fontchooser,
1541                                   const gchar      *fontname)
1542 {
1543   GtkFontChooserPrivate *priv = fontchooser->priv;
1544   GtkTreeIter           iter;
1545   gboolean              valid;
1546   gchar                *family_name;
1547   PangoFontDescription *desc;
1548   gboolean              found = FALSE;
1549   
1550   g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), FALSE);
1551   g_return_val_if_fail (fontname != NULL, FALSE);
1552
1553   if (!gtk_widget_has_screen (GTK_WIDGET (fontchooser)))
1554     return FALSE;
1555
1556   desc = pango_font_description_from_string (fontname);
1557   family_name = (gchar*)pango_font_description_get_family (desc);
1558
1559   if (!family_name)
1560   {
1561     pango_font_description_free (desc);
1562     return FALSE;
1563   }
1564
1565   /* We make sure the filter is clear */
1566   gtk_entry_set_text (GTK_ENTRY (priv->search_entry), "");
1567
1568   /* We find the matching family/face */
1569   for (valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->filter), &iter);
1570        valid;
1571        valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->filter), &iter))
1572     {
1573       PangoFontFace        *face;
1574       PangoFontDescription *tmp_desc;
1575
1576       gtk_tree_model_get (GTK_TREE_MODEL (priv->filter), &iter,
1577                           FACE_COLUMN,   &face,
1578                           -1);
1579
1580       tmp_desc = pango_font_face_describe (face);
1581       if (pango_font_description_get_size_is_absolute (desc))
1582         pango_font_description_set_absolute_size (tmp_desc,
1583                                                   pango_font_description_get_size (desc));
1584       else
1585         pango_font_description_set_size (tmp_desc,
1586                                          pango_font_description_get_size (desc));        
1587
1588
1589       if (pango_font_description_equal (desc, tmp_desc))
1590         {
1591           GtkTreePath *path;
1592           gint size = pango_font_description_get_size (desc);
1593
1594           if (size)
1595             {
1596               if (pango_font_description_get_size_is_absolute (desc))
1597                 size = size * PANGO_SCALE;
1598               gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->size_spin),
1599                                          size / PANGO_SCALE);
1600             }
1601
1602           path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->filter),
1603                                           &iter);
1604
1605           if (path)
1606             {
1607               gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->family_face_list),
1608                                         path,
1609                                         NULL,
1610                                         FALSE);
1611               gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->family_face_list),
1612                                             path,
1613                                             NULL,
1614                                             TRUE,
1615                                             0.5,
1616                                             0.5);
1617               gtk_tree_path_free (path);
1618             }
1619
1620           found = TRUE;
1621         }
1622
1623       g_object_unref (face);
1624       pango_font_description_free (tmp_desc);
1625
1626       if (found)
1627         break;
1628     }
1629
1630   pango_font_description_free (desc);
1631   g_object_notify (G_OBJECT (fontchooser), "font-name");
1632
1633   return found;
1634 }
1635
1636 /**
1637  * gtk_font_chooser_get_preview_text:
1638  * @fontchooser: a #GtkFontChooser
1639  *
1640  * Gets the text displayed in the preview area.
1641  * 
1642  * Return value: (transfer none): the text displayed in the
1643  *     preview area. This string is owned by the widget and
1644  *     should not be modified or freed 
1645  */
1646 G_CONST_RETURN gchar*
1647 gtk_font_chooser_get_preview_text (GtkFontChooser *fontchooser)
1648 {
1649   g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), NULL);
1650   return (const gchar*)fontchooser->priv->preview_text;
1651 }
1652
1653
1654 /**
1655  * gtk_font_chooser_set_preview_text:
1656  * @fontchooser: a #GtkFontChooser
1657  * @text: (transfer none): the text to display in the preview area 
1658  *
1659  * Sets the text displayed in the preview area.
1660  * The @text is used to show how the selected font looks.
1661  */
1662 void
1663 gtk_font_chooser_set_preview_text  (GtkFontChooser *fontchooser,
1664                                       const gchar      *text)
1665 {
1666   g_return_if_fail (GTK_IS_FONT_CHOOSER (fontchooser));
1667   g_return_if_fail (text != NULL);
1668
1669   g_free (fontchooser->priv->preview_text);
1670   fontchooser->priv->preview_text = g_strdup (text);
1671
1672   populate_list (fontchooser,
1673                  GTK_TREE_VIEW (fontchooser->priv->family_face_list),
1674                  fontchooser->priv->model);
1675
1676   gtk_entry_set_text (GTK_ENTRY (fontchooser->priv->preview), text);
1677
1678   g_object_notify (G_OBJECT (fontchooser), "preview-text");
1679 }
1680
1681 /**
1682  * gtk_font_chooser_get_show_preview_entry:
1683  * @fontchooser: a #GtkFontChooser
1684  *
1685  * Return value: %TRUE if the preview entry is shown or %FALSE if
1686  *               it is hidden.
1687  * Since: 3.2
1688  */
1689 gboolean
1690 gtk_font_chooser_get_show_preview_entry (GtkFontChooser *fontchooser)
1691 {
1692   g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), FALSE);
1693
1694   return fontchooser->priv->show_preview_entry;
1695 }
1696
1697 /**
1698  * gtk_font_chooser_set_show_preview_entry:
1699  * @fontchooser: a #GtkFontChooser
1700  * @show_preview_entry: whether to show the editable preview entry or not
1701  *
1702  * Shows or hides the editable preview entry.
1703  * Since: 3.2
1704  */
1705 void
1706 gtk_font_chooser_set_show_preview_entry (GtkFontChooser *fontchooser,
1707                                            gboolean          show_preview_entry)
1708 {
1709   g_return_if_fail (GTK_IS_FONT_CHOOSER (fontchooser));
1710
1711   if (show_preview_entry)
1712     gtk_widget_show (fontchooser->priv->preview_scrolled_window);
1713   else
1714     gtk_widget_hide (fontchooser->priv->preview_scrolled_window);
1715
1716   fontchooser->priv->show_preview_entry = show_preview_entry;
1717   g_object_notify (G_OBJECT (fontchooser), "show-preview-entry");
1718 }
1719
1720 /**
1721  * gtk_font_chooser_get_family_list:
1722  * @fontchooser: a #GtkFontChooser
1723  *
1724  * This returns the #GtkTreeView that lists font families, for
1725  * example, 'Sans', 'Serif', etc.
1726  *
1727  * Return value: (transfer none): A #GtkWidget that is part of @fontchooser
1728  *
1729  * Deprecated: 3.2
1730  */
1731 GtkWidget *
1732 gtk_font_chooser_get_family_list (GtkFontChooser *fontchooser)
1733 {
1734   GtkFontChooserPrivate *priv = fontchooser->priv;
1735   g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), NULL);
1736   if (!priv->font_list)
1737     initialize_deprecated_widgets (fontchooser);
1738
1739   return priv->font_list;
1740 }
1741
1742 /**
1743  * gtk_font_chooser_get_face_list:
1744  * @fontchooser: a #GtkFontChooser
1745  *
1746  * This returns the #GtkTreeView which lists all styles available for
1747  * the selected font. For example, 'Regular', 'Bold', etc.
1748  * 
1749  * Return value: (transfer none): A #GtkWidget that is part of @fontchooser
1750  *
1751  * Deprecated: 3.2
1752  */
1753 GtkWidget *
1754 gtk_font_chooser_get_face_list (GtkFontChooser *fontchooser)
1755 {
1756   GtkFontChooserPrivate *priv = fontchooser->priv;
1757   g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), NULL);
1758   if (!priv->face_list)
1759     initialize_deprecated_widgets (fontchooser);
1760
1761   return priv->face_list;
1762 }
1763
1764 /**
1765  * gtk_font_chooser_get_size_entry:
1766  * @fontchooser: a #GtkFontChooser
1767  *
1768  * This returns the #GtkEntry used to allow the user to edit the font
1769  * number manually instead of selecting it from the list of font sizes.
1770  *
1771  * Return value: (transfer none): A #GtkWidget that is part of @fontchooser
1772  *
1773  * Deprecated: 3.2
1774  */
1775 GtkWidget *
1776 gtk_font_chooser_get_size_entry (GtkFontChooser *fontchooser)
1777 {
1778   GtkFontChooserPrivate *priv = fontchooser->priv;
1779   g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), NULL);
1780
1781   return priv->size_spin;
1782 }
1783
1784 /**
1785  * gtk_font_chooser_get_size_list:
1786  * @fontchooser: a #GtkFontChooser
1787  *
1788  * This returns the #GtkTreeeView used to list font sizes.
1789  *
1790  * Return value: (transfer none): A #GtkWidget that is part of @fontchooser
1791  *
1792  * Deprecated: 3.2
1793  */
1794 GtkWidget *
1795 gtk_font_chooser_get_size_list (GtkFontChooser *fontchooser)
1796 {
1797   GtkFontChooserPrivate *priv = fontchooser->priv;
1798   g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), NULL);
1799   if (!priv->size_list)
1800     initialize_deprecated_widgets (fontchooser);
1801
1802   return priv->size_list;
1803 }
1804
1805 /**
1806  * gtk_font_chooser_get_preview_entry:
1807  * @fontchooser: a #GtkFontChooser
1808  *
1809  * This returns the #GtkEntry used to display the font as a preview.
1810  *
1811  * Return value: (transfer none): A #GtkWidget that is part of @fontchooser
1812  *
1813  * Deprecated: 3.2
1814  */
1815 GtkWidget *
1816 gtk_font_chooser_get_preview_entry (GtkFontChooser *fontchooser)
1817 {
1818   GtkFontChooserPrivate *priv = fontchooser->priv;
1819   g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), NULL);
1820
1821   return priv->preview;
1822 }
1823
1824 /**
1825  * SECTION:gtkfontchooserdlg
1826  * @Short_description: A dialog box for selecting fonts
1827  * @Title: GtkFontChooserDialog
1828  * @See_also: #GtkFontChooser, #GtkDialog
1829  *
1830  * The #GtkFontChooserDialog widget is a dialog box for selecting a font.
1831  *
1832  * To set the font which is initially selected, use
1833  * gtk_font_chooser_dialog_set_font_name().
1834  *
1835  * To get the selected font use gtk_font_chooser_dialog_get_font_name().
1836  *
1837  * To change the text which is shown in the preview area, use
1838  * gtk_font_chooser_dialog_set_preview_text().
1839  *
1840  * <refsect2 id="GtkFontChooserDialog-BUILDER-UI">
1841  * <title>GtkFontChooserDialog as GtkBuildable</title>
1842  * The GtkFontChooserDialog implementation of the GtkBuildable interface
1843  * exposes the embedded #GtkFontChooser as internal child with the
1844  * name "font_selection". It also exposes the buttons with the names
1845  * "select_button" and "cancel_button. The buttons with the names 
1846  * "ok_button" and "apply_button" are exposed but deprecated.
1847  * </refsect2>
1848  */
1849
1850 static void gtk_font_chooser_dialog_buildable_interface_init     (GtkBuildableIface *iface);
1851 static GObject * gtk_font_chooser_dialog_buildable_get_internal_child (GtkBuildable *buildable,
1852                     GtkBuilder   *builder,
1853                     const gchar  *childname);
1854
1855 G_DEFINE_TYPE_WITH_CODE (GtkFontChooserDialog, gtk_font_chooser_dialog,
1856        GTK_TYPE_DIALOG,
1857        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
1858             gtk_font_chooser_dialog_buildable_interface_init))
1859
1860 static GtkBuildableIface *parent_buildable_iface;
1861
1862 static void
1863 gtk_font_chooser_dialog_class_init (GtkFontChooserDialogClass *klass)
1864 {
1865   g_type_class_add_private (klass, sizeof (GtkFontChooserDialogPrivate));
1866 }
1867
1868 static void
1869 gtk_font_chooser_dialog_init (GtkFontChooserDialog *fontchooserdiag)
1870 {
1871   GtkFontChooserDialogPrivate *priv;
1872   GtkDialog *dialog = GTK_DIALOG (fontchooserdiag);
1873   GtkWidget *action_area, *content_area;
1874
1875   fontchooserdiag->priv = G_TYPE_INSTANCE_GET_PRIVATE (fontchooserdiag,
1876                                                    GTK_TYPE_FONT_CHOOSER_DIALOG,
1877                                                    GtkFontChooserDialogPrivate);
1878   priv = fontchooserdiag->priv;
1879
1880   content_area = gtk_dialog_get_content_area (dialog);
1881   action_area = gtk_dialog_get_action_area (dialog);
1882
1883   gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
1884   gtk_box_set_spacing (GTK_BOX (content_area), 2); /* 2 * 5 + 2 = 12 */
1885   gtk_container_set_border_width (GTK_CONTAINER (action_area), 5);
1886   gtk_box_set_spacing (GTK_BOX (action_area), 6);
1887
1888   gtk_widget_push_composite_child ();
1889
1890   gtk_window_set_resizable (GTK_WINDOW (fontchooserdiag), TRUE);
1891
1892   /* Create the content area */
1893   priv->fontchooser = gtk_font_chooser_new ();
1894   gtk_container_set_border_width (GTK_CONTAINER (priv->fontchooser), 5);
1895   gtk_widget_show (priv->fontchooser);
1896   gtk_box_pack_start (GTK_BOX (content_area),
1897                       priv->fontchooser, TRUE, TRUE, 0);
1898
1899   /* Create the action area */
1900   priv->cancel_button = gtk_dialog_add_button (dialog,
1901                                                GTK_STOCK_CANCEL,
1902                                                GTK_RESPONSE_CANCEL);
1903   /* Deprecated: Apply button is not used anymore */
1904   priv->apply_button = gtk_dialog_add_button (dialog,
1905                                               GTK_STOCK_APPLY,
1906                                               GTK_RESPONSE_APPLY);
1907   gtk_widget_hide (priv->apply_button);
1908
1909   priv->select_button = gtk_dialog_add_button (dialog,
1910                                                _("Select"),
1911                                                GTK_RESPONSE_OK);
1912   gtk_widget_grab_default (priv->select_button);
1913
1914   gtk_dialog_set_alternative_button_order (GTK_DIALOG (fontchooserdiag),
1915              GTK_RESPONSE_OK,
1916              GTK_RESPONSE_APPLY, /* Deprecated */
1917              GTK_RESPONSE_CANCEL,
1918              -1);
1919
1920   gtk_window_set_title (GTK_WINDOW (fontchooserdiag),
1921                         _("Font Selection"));
1922
1923   gtk_widget_pop_composite_child ();
1924 }
1925
1926 /**
1927  * gtk_font_chooser_dialog_new:
1928  * @title: (allow-none): the title of the dialog window 
1929  *
1930  * Creates a new #GtkFontChooserDialog.
1931  *
1932  * Return value: a new #GtkFontChooserDialog
1933  */
1934 GtkWidget*
1935 gtk_font_chooser_dialog_new (const gchar *title)
1936 {
1937   GtkFontChooserDialog *fontchooserdiag;
1938   
1939   fontchooserdiag = g_object_new (GTK_TYPE_FONT_CHOOSER_DIALOG, NULL);
1940
1941   if (title)
1942     gtk_window_set_title (GTK_WINDOW (fontchooserdiag), title);
1943   
1944   return GTK_WIDGET (fontchooserdiag);
1945 }
1946
1947 /**
1948  * gtk_font_chooser_dialog_get_font_selection:
1949  * @fsd: a #GtkFontChooserDialog
1950  *
1951  * Retrieves the #GtkFontChooser widget embedded in the dialog.
1952  *
1953  * Returns: (transfer none): the embedded #GtkFontChooser
1954  *
1955  * Since: 2.22
1956  **/
1957 GtkWidget*
1958 gtk_font_chooser_dialog_get_font_selection (GtkFontChooserDialog *fsd)
1959 {
1960   g_return_val_if_fail (GTK_IS_FONT_CHOOSER_DIALOG (fsd), NULL);
1961
1962   return fsd->priv->fontchooser;
1963 }
1964
1965 static void
1966 gtk_font_chooser_dialog_buildable_interface_init (GtkBuildableIface *iface)
1967 {
1968   parent_buildable_iface = g_type_interface_peek_parent (iface);
1969   iface->get_internal_child = gtk_font_chooser_dialog_buildable_get_internal_child;
1970 }
1971
1972 static GObject *
1973 gtk_font_chooser_dialog_buildable_get_internal_child (GtkBuildable *buildable,
1974               GtkBuilder   *builder,
1975               const gchar  *childname)
1976 {
1977   GtkFontChooserDialogPrivate *priv;
1978
1979   priv = GTK_FONT_CHOOSER_DIALOG (buildable)->priv;
1980
1981   if (g_strcmp0 (childname, "select_button") == 0)
1982     return G_OBJECT (priv->select_button);
1983   else if (g_strcmp0 (childname, "cancel_button") == 0)
1984     return G_OBJECT (priv->cancel_button);
1985   else if (g_strcmp0 (childname, "font_selection") == 0)
1986     return G_OBJECT (priv->fontchooser);
1987
1988   /* Deprecated */
1989   else if (g_strcmp0 (childname, "ok_button") == 0)
1990     return G_OBJECT (priv->select_button);
1991   else if (g_strcmp0 (childname, "apply_button") == 0)
1992     return G_OBJECT (priv->apply_button);
1993
1994   return parent_buildable_iface->get_internal_child (buildable, builder, childname);
1995 }
1996
1997 /**
1998  * gtk_font_chooser_dialog_get_font_name:
1999  * @fsd: a #GtkFontChooserDialog
2000  * 
2001  * Gets the currently-selected font name.
2002  *
2003  * Note that this can be a different string than what you set with 
2004  * gtk_font_chooser_dialog_set_font_name(), as the font selection widget
2005  * may normalize font names and thus return a string with a different 
2006  * structure. For example, "Helvetica Italic Bold 12" could be normalized 
2007  * to "Helvetica Bold Italic 12".  Use pango_font_description_equal()
2008  * if you want to compare two font descriptions.
2009  * 
2010  * Return value: A string with the name of the current font, or %NULL if no 
2011  *     font is selected. You must free this string with g_free().
2012  */
2013 gchar*
2014 gtk_font_chooser_dialog_get_font_name (GtkFontChooserDialog *fsd)
2015 {
2016   GtkFontChooserDialogPrivate *priv;
2017
2018   g_return_val_if_fail (GTK_IS_FONT_CHOOSER_DIALOG (fsd), NULL);
2019
2020   priv = fsd->priv;
2021
2022   return gtk_font_chooser_get_font_name (GTK_FONT_CHOOSER (priv->fontchooser));
2023 }
2024
2025 /**
2026  * gtk_font_chooser_dialog_set_font_name:
2027  * @fsd: a #GtkFontChooserDialog
2028  * @fontname: a font name like "Helvetica 12" or "Times Bold 18"
2029  *
2030  * Sets the currently selected font. 
2031  * 
2032  * Return value: %TRUE if the font selected in @fsd is now the
2033  *     @fontname specified, %FALSE otherwise. 
2034  */
2035 gboolean
2036 gtk_font_chooser_dialog_set_font_name (GtkFontChooserDialog *fsd,
2037            const gchar          *fontname)
2038 {
2039   GtkFontChooserDialogPrivate *priv;
2040
2041   g_return_val_if_fail (GTK_IS_FONT_CHOOSER_DIALOG (fsd), FALSE);
2042   g_return_val_if_fail (fontname, FALSE);
2043
2044   priv = fsd->priv;
2045
2046   return gtk_font_chooser_set_font_name (GTK_FONT_CHOOSER (priv->fontchooser), fontname);
2047 }
2048
2049 /**
2050  * gtk_font_chooser_dialog_get_preview_text:
2051  * @fsd: a #GtkFontChooserDialog
2052  *
2053  * Gets the text displayed in the preview area.
2054  * 
2055  * Return value: the text displayed in the preview area. 
2056  *     This string is owned by the widget and should not be 
2057  *     modified or freed 
2058  */
2059 G_CONST_RETURN gchar*
2060 gtk_font_chooser_dialog_get_preview_text (GtkFontChooserDialog *fsd)
2061 {
2062   GtkFontChooserDialogPrivate *priv;
2063
2064   g_return_val_if_fail (GTK_IS_FONT_CHOOSER_DIALOG (fsd), NULL);
2065
2066   priv = fsd->priv;
2067
2068   return gtk_font_chooser_get_preview_text (GTK_FONT_CHOOSER (priv->fontchooser));
2069 }
2070
2071 /**
2072  * gtk_font_chooser_dialog_set_preview_text:
2073  * @fsd: a #GtkFontChooserDialog
2074  * @text: the text to display in the preview area
2075  *
2076  * Sets the text displayed in the preview area. 
2077  */
2078 void
2079 gtk_font_chooser_dialog_set_preview_text (GtkFontChooserDialog *fsd,
2080               const gchar            *text)
2081 {
2082   GtkFontChooserDialogPrivate *priv;
2083
2084   g_return_if_fail (GTK_IS_FONT_CHOOSER_DIALOG (fsd));
2085   g_return_if_fail (text != NULL);
2086
2087   priv = fsd->priv;
2088
2089   gtk_font_chooser_set_preview_text (GTK_FONT_CHOOSER (priv->fontchooser), text);
2090 }
2091
2092 /**
2093  * gtk_font_chooser_dialog_get_ok_button:
2094  * @fsd: a #GtkFontChooserDialog
2095  *
2096  * Gets the 'OK' button.
2097  *
2098  * Return value: (transfer none): the #GtkWidget used in the dialog
2099  *     for the 'OK' button.
2100  *
2101  * Deprecated: 3.2
2102  */
2103 GtkWidget *
2104 gtk_font_chooser_dialog_get_ok_button (GtkFontChooserDialog *fsd)
2105 {
2106   g_return_val_if_fail (GTK_IS_FONT_CHOOSER_DIALOG (fsd), NULL);
2107
2108   return fsd->priv->select_button;
2109 }
2110
2111 /**
2112  * gtk_font_chooser_dialog_get_cancel_button:
2113  * @fsd: a #GtkFontChooserDialog
2114  *
2115  * Gets the 'Cancel' button.
2116  *
2117  * Return value: (transfer none): the #GtkWidget used in the dialog
2118  *     for the 'Cancel' button.
2119  *
2120  * Deprecated: 3.2
2121  */
2122 GtkWidget *
2123 gtk_font_chooser_dialog_get_cancel_button (GtkFontChooserDialog *fsd)
2124 {
2125   g_return_val_if_fail (GTK_IS_FONT_CHOOSER_DIALOG (fsd), NULL);
2126
2127   return fsd->priv->cancel_button;
2128 }