]> Pileus Git - ~andy/gtk/blob - gtk/gtkfontchooser.c
GtkFontChooser: initialization and destruction of deprecated widgets and data models
[~andy/gtk] / gtk / gtkfontchooser.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * Massively updated for Pango by Owen Taylor, May 2000
5  * GtkFontSelection widget for Gtk+, by Damon Chaplin, May 1998.
6  * Based on the GnomeFontSelector widget, by Elliot Lee, but major changes.
7  * The GnomeFontSelector was derived from app/text_tool.c in the GIMP.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 /*
26  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
27  * file for a list of people on the GTK+ Team.  See the ChangeLog
28  * files for a list of changes.  These files are distributed with
29  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
30  */
31
32 #include "config.h"
33
34 #include <stdlib.h>
35 #include <glib/gprintf.h>
36 #include <string.h>
37
38 #include <atk/atk.h>
39
40 #include "gtkfontsel.h"
41 #include "gtkbutton.h"
42 #include "gtkcellrenderertext.h"
43 #include "gtkentry.h"
44 #include "gtkframe.h"
45 #include "gtkhbbox.h"
46 #include "gtkhbox.h"
47 #include "gtklabel.h"
48 #include "gtkliststore.h"
49 #include "gtkrc.h"
50 #include "gtkstock.h"
51 #include "gtktable.h"
52 #include "gtktreeselection.h"
53 #include "gtktreeview.h"
54 #include "gtkvbox.h"
55 #include "gtkscrolledwindow.h"
56 #include "gtkintl.h"
57 #include "gtkaccessible.h"
58 #include "gtkbuildable.h"
59 #include "gtkprivate.h"
60 #include "gtkalignment.h"
61 #include "gtkscale.h"
62 #include "gtkbox.h"
63 #include "gtkspinbutton.h"
64 #include "gtkwidget.h"
65
66 /**
67  * SECTION:gtkfontsel
68  * @Short_description: A widget for selecting fonts
69  * @Title: GtkFontSelection
70  * @See_also: #GtkFontSelectionDialog
71  *
72  * The #GtkFontSelection widget lists the available fonts, styles and sizes,
73  * allowing the user to select a font.
74  * It is used in the #GtkFontSelectionDialog widget to provide a dialog box for
75  * selecting fonts.
76  *
77  * To set the font which is initially selected, use
78  * gtk_font_selection_set_font_name().
79  *
80  * To get the selected font use gtk_font_selection_get_font_name().
81  *
82  * To change the text which is shown in the preview area, use
83  * gtk_font_selection_set_preview_text().
84  */
85
86
87 struct _GtkFontSelectionPrivate
88 {
89   GtkWidget *search_entry;
90   GtkWidget *family_face_list;
91   GtkWidget *size_slider;
92   GtkWidget *size_spin;
93   GtkWidget *preview;
94
95   GtkListStore *model;  
96   GtkTreeModel *filter;
97
98   gint             size;
99   PangoFontFace   *face;
100   PangoFontFamily *family;
101   
102   gboolean         ignore_slider;
103
104   /*FIXME: Remove these widgets after deprecation removal */
105   GtkWidget *size_list;
106   GtkWidget *font_list;
107   GtkWidget *face_list;
108
109   GtkListStore *_size_model;
110   GtkListStore *_font_model;
111   GtkListStore *_face_model;
112 };
113
114
115 struct _GtkFontSelectionDialogPrivate
116 {
117   GtkWidget *fontsel;
118
119   GtkWidget *ok_button;
120   GtkWidget *apply_button;
121   GtkWidget *cancel_button;
122 };
123
124
125 #define DEFAULT_FONT_NAME "Sans 10"
126 #define MAX_FONT_SIZE 999
127
128 /* This is the initial fixed height and the top padding of the preview entry */
129 #define PREVIEW_HEIGHT 72
130 #define PREVIEW_TOP_PADDING 6
131
132 /* Widget default geometry */
133 #define FONTSEL_WIDTH           540
134 #define FONTSEL_HEIGHT          408
135
136 /* These are the sizes of the font, style & size lists. */
137 #define FONT_LIST_HEIGHT        136
138 #define FONT_LIST_WIDTH         190
139 #define FONT_STYLE_LIST_WIDTH   170
140 #define FONT_SIZE_LIST_WIDTH    60
141
142 #define ROW_FORMAT_STRING "<span weight=\"bold\" size=\"small\" foreground=\"%s\">%s</span>\n<span size=\"x-large\" font_desc=\"%s\">%s</span>"
143
144 /* These are what we use as the standard font sizes, for the size list.
145  */
146 #define FONT_SIZES_LENGTH 14
147 static const gint font_sizes[] = {
148   6, 8, 9, 10, 11, 12, 13, 14, 16, 20, 24, 36, 48, 72
149 };
150
151 enum {
152    PROP_0,
153    PROP_FONT_NAME,
154    PROP_PREVIEW_TEXT
155 };
156
157
158 enum {
159   FAMILY_COLUMN,
160   FACE_COLUMN,
161   PREVIEW_TEXT_COLUMN,
162   PREVIEW_TITLE_COLUMN,
163   /*FIXME: Remove two strings after deprecation removal */
164   FAMILY_NAME_COLUMN,
165   FACE_NAME_COLUMN
166 };
167
168 static void  gtk_font_selection_set_property       (GObject         *object,
169                                                                       guint            prop_id,
170                                                                       const GValue    *value,
171                                                                       GParamSpec      *pspec);
172 static void  gtk_font_selection_get_property       (GObject         *object,
173                                                                                   guint            prop_id,
174                                                                                   GValue          *value,
175                                                                                   GParamSpec      *pspec);
176 static void  gtk_font_selection_finalize                 (GObject         *object);
177
178 #if 0
179 static void  gtk_font_selection_screen_changed     (GtkWidget         *widget,
180                                                     GdkScreen       *previous_screen);
181 static void  gtk_font_selection_style_updated      (GtkWidget      *widget);
182 #endif
183
184 static void  gtk_font_selection_ref_family        (GtkFontSelection *fontsel,
185                                                    PangoFontFamily  *family);
186 static void  gtk_font_selection_ref_face          (GtkFontSelection *fontsel,
187                                                    PangoFontFace    *face);
188
189 static void gtk_font_selection_bootstrap_fontlist (GtkFontSelection *fontsel);
190
191 G_DEFINE_TYPE (GtkFontSelection, gtk_font_selection, GTK_TYPE_VBOX)
192
193 static void
194 gtk_font_selection_class_init (GtkFontSelectionClass *klass)
195 {
196   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
197
198 #if 0
199   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
200   widget_class->screen_changed = gtk_font_selection_screen_changed;
201   widget_class->style_updated = gtk_font_selection_style_updated;
202 #endif
203
204   gobject_class->finalize = gtk_font_selection_finalize;
205   gobject_class->set_property = gtk_font_selection_set_property;
206   gobject_class->get_property = gtk_font_selection_get_property;
207
208   g_object_class_install_property (gobject_class,
209                                    PROP_FONT_NAME,
210                                    g_param_spec_string ("font-name",
211                                                         P_("Font name"),
212                                                         P_("The string that represents this font"),
213                                                         DEFAULT_FONT_NAME,
214                                                         GTK_PARAM_READWRITE));
215   g_object_class_install_property (gobject_class,
216                                    PROP_PREVIEW_TEXT,
217                                    g_param_spec_string ("preview-text",
218                                                         P_("Preview text"),
219                                                         P_("The text to display in order to demonstrate the selected font"),
220                                                         pango_language_get_sample_string (NULL),
221                                                         GTK_PARAM_READWRITE));
222
223   g_type_class_add_private (klass, sizeof (GtkFontSelectionPrivate));
224 }
225
226 static void 
227 gtk_font_selection_set_property (GObject         *object,
228                                                    guint            prop_id,
229                                                    const GValue    *value,
230                                                    GParamSpec      *pspec)
231 {
232   GtkFontSelection *fontsel;
233
234   fontsel = GTK_FONT_SELECTION (object);
235
236   switch (prop_id)
237     {
238     case PROP_FONT_NAME:
239       gtk_font_selection_set_font_name (fontsel, g_value_get_string (value));
240       break;
241     case PROP_PREVIEW_TEXT:
242       gtk_font_selection_set_preview_text (fontsel, g_value_get_string (value));
243       break;
244     default:
245       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
246       break;
247     }
248 }
249
250 static void
251 gtk_font_selection_get_property (GObject         *object,
252                                                    guint            prop_id,
253                                                    GValue          *value,
254                                                    GParamSpec      *pspec)
255 {
256   GtkFontSelection *fontsel;
257
258   fontsel = GTK_FONT_SELECTION (object);
259
260   switch (prop_id)
261     {
262     case PROP_FONT_NAME:
263       g_value_take_string (value, gtk_font_selection_get_font_name (fontsel));
264       break;
265     case PROP_PREVIEW_TEXT:
266       g_value_set_string (value, gtk_font_selection_get_preview_text (fontsel));
267       break;
268     default:
269       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
270       break;
271     }
272 }
273
274 void
275 refilter_and_focus (GtkFontSelectionPrivate *priv)
276 {
277   GtkTreeIter  iter;
278   GtkTreeView *treeview = GTK_TREE_VIEW (priv->family_face_list);
279   GtkTreePath *path = gtk_tree_path_new ();
280
281   gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));
282
283   if (!path)
284     return;
285
286   gtk_tree_view_get_cursor (treeview, &path, NULL);
287
288   if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->filter), &iter, path))
289     {
290       gtk_tree_path_free (path);
291       return;
292     }
293
294   gtk_tree_view_scroll_to_cell (treeview, path, NULL, FALSE, 0.0, 0.0);
295   gtk_tree_path_free (path);
296 }
297
298 void
299 deleted_text_cb (GtkEntryBuffer *buffer,
300                  guint           position,
301                  guint           n_chars,
302                  gpointer        user_data)
303 {
304   GtkFontSelectionPrivate *priv  = (GtkFontSelectionPrivate*)user_data;
305   GtkWidget               *entry = priv->search_entry;
306   
307   if (gtk_entry_buffer_get_length (buffer) == 0)
308     {
309       gtk_entry_set_icon_from_stock (GTK_ENTRY (entry),
310                                      GTK_ENTRY_ICON_SECONDARY,
311                                      GTK_STOCK_FIND);
312     }
313
314   gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));
315 }
316
317 void
318 inserted_text_cb (GtkEntryBuffer *buffer,
319                   guint           position,
320                   gchar          *chars,
321                   guint           n_chars,
322                   gpointer        user_data) 
323 {
324   GtkFontSelectionPrivate *priv  = (GtkFontSelectionPrivate*)user_data;
325   GtkWidget               *entry = priv->search_entry;
326
327   if (g_strcmp0 (gtk_entry_get_icon_stock (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY),
328                  GTK_STOCK_CLEAR))
329     gtk_entry_set_icon_from_stock (GTK_ENTRY (entry),
330                                    GTK_ENTRY_ICON_SECONDARY,
331                                    GTK_STOCK_CLEAR);
332
333
334   gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));
335 }
336
337 void
338 icon_press_cb (GtkEntry             *entry,
339                GtkEntryIconPosition  pos,
340                GdkEvent             *event,
341                gpointer              user_data)
342 {
343   gtk_entry_buffer_delete_text (gtk_entry_get_buffer (entry), 0, -1);
344 }
345
346 void
347 slider_change_cb (GtkAdjustment *adjustment, gpointer data)
348 {
349   GtkFontSelectionPrivate *priv = (GtkFontSelectionPrivate*)data;
350
351   /* If we set the silder value manually, we ignore this callback */
352   if (priv->ignore_slider)
353     {
354       priv->ignore_slider = FALSE;
355       return;
356     }
357
358   gtk_adjustment_set_value (gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON(priv->size_spin)),
359                             gtk_adjustment_get_value (adjustment));
360 }
361
362 void
363 spin_change_cb (GtkAdjustment *adjustment, gpointer data)
364 {
365   PangoFontDescription *desc;
366   GtkFontSelectionPrivate *priv = (GtkFontSelectionPrivate*)data;
367
368   gdouble size = gtk_adjustment_get_value (adjustment);
369   
370   GtkAdjustment *slider_adj = gtk_range_get_adjustment (GTK_RANGE (priv->size_slider));
371
372   /* We ignore the slider value change callback for both of this set_value call */
373   priv->ignore_slider = TRUE;
374   if (size < gtk_adjustment_get_lower (slider_adj))
375     gtk_adjustment_set_value (slider_adj, gtk_adjustment_get_lower (slider_adj));
376   else if (size > gtk_adjustment_get_upper (slider_adj))
377     gtk_adjustment_set_value (slider_adj, gtk_adjustment_get_upper (slider_adj));
378   else
379     gtk_adjustment_set_value (slider_adj, size);
380
381   priv->size = ((gint)gtk_adjustment_get_value (adjustment)) * PANGO_SCALE;
382
383   desc = pango_context_get_font_description (gtk_widget_get_pango_context (priv->preview));
384   pango_font_description_set_size (desc, priv->size);
385   gtk_widget_override_font (priv->preview, desc);
386   
387   gtk_widget_queue_draw (priv->preview);
388 }
389
390 void
391 set_range_marks (GtkFontSelectionPrivate *priv,
392                  GtkWidget* size_slider,
393                  gint* sizes,
394                  gint length)
395 {
396   GtkAdjustment *adj;
397   gint i;
398   gdouble value;
399   
400   if (length<2)
401     {
402       sizes = (gint*)font_sizes;
403       length = FONT_SIZES_LENGTH;
404     }
405   
406   gtk_scale_clear_marks (GTK_SCALE (size_slider));
407   
408   adj = gtk_range_get_adjustment(GTK_RANGE (size_slider));
409   
410   gtk_adjustment_set_lower (adj, (gdouble) sizes[0]);
411   gtk_adjustment_set_upper (adj, (gdouble) sizes[length-1]);
412
413   value = gtk_adjustment_get_value (adj);
414   if (value > (gdouble) sizes[length-1])
415     {
416       gtk_adjustment_set_value (adj, (gdouble) sizes[length-1]);
417       priv->ignore_slider = TRUE;
418     }
419   else if (value < (gdouble) sizes[0])
420     {
421       gtk_adjustment_set_value (adj, (gdouble) sizes[0]);
422       priv->ignore_slider = TRUE; 
423     }
424   
425   for (i=0; i<length; i++)
426     gtk_scale_add_mark (GTK_SCALE (size_slider),
427                         (gdouble) sizes[i],
428                         GTK_POS_BOTTOM, NULL);
429                         
430 }
431
432 void
433 cursor_changed_cb (GtkTreeView *treeview, gpointer data)
434 {
435   PangoFontFamily      *family;
436   PangoFontFace        *face;
437   PangoFontDescription *desc;
438   
439   gint *sizes;
440   gint  i, n_sizes;
441
442   GtkTreeIter iter;
443   GtkTreePath *path = gtk_tree_path_new ();
444   
445   GtkFontSelection        *fontsel = (GtkFontSelection*)data;
446   
447   gtk_tree_view_get_cursor (treeview, &path, NULL);
448   
449   if (!path)
450     return;
451
452   if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (fontsel->priv->filter), &iter, path))
453     {
454       gtk_tree_path_free (path);
455       return;
456     } 
457   
458   
459   gtk_tree_model_get (GTK_TREE_MODEL (fontsel->priv->filter), &iter,
460                       FACE_COLUMN, &face,
461                       FAMILY_COLUMN, &family,
462                       -1);
463
464   gtk_tree_view_scroll_to_cell (treeview, path, NULL, FALSE, 0.0, 0.0);
465
466   gtk_tree_path_free (path);
467   path = NULL;
468   
469   if (!face || !family)
470     {
471       g_object_unref (face);
472       g_object_unref (family);
473       return;
474     }
475
476   desc = pango_font_face_describe (face);
477   pango_font_description_set_size (desc, fontsel->priv->size);
478   gtk_widget_override_font (fontsel->priv->preview, desc);
479
480   pango_font_face_list_sizes (face, &sizes, &n_sizes);
481   /* It seems not many fonts actually have a sane set of sizes */
482   for (i=0; i<n_sizes; i++)
483     sizes[i] = sizes[i] / PANGO_SCALE;
484   
485   set_range_marks (fontsel->priv, fontsel->priv->size_slider, sizes, n_sizes);
486
487   gtk_font_selection_ref_family (fontsel, family);
488   gtk_font_selection_ref_face  (fontsel,   face);
489
490   /* Free resources */
491   g_object_unref ((gpointer)face);
492   pango_font_description_free(desc);
493 }
494
495 gboolean
496 zoom_preview_cb (GtkWidget *scrolled_window, GdkEventScroll *event, gpointer data)
497 {
498   GtkFontSelectionPrivate *priv = (GtkFontSelectionPrivate*)data;
499
500   GtkAdjustment *adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->size_spin));
501
502   if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_RIGHT)
503     gtk_adjustment_set_value (adj,
504                               gtk_adjustment_get_value (adj) +
505                               gtk_adjustment_get_step_increment (adj));
506   else if (event->direction == GDK_SCROLL_DOWN || event->direction == GDK_SCROLL_LEFT)
507     gtk_adjustment_set_value (adj,
508                               gtk_adjustment_get_value (adj) -
509                               gtk_adjustment_get_step_increment (adj));
510   return TRUE;
511 }
512
513 static void
514 gtk_font_selection_init (GtkFontSelection *fontsel)
515 {
516   GtkFontSelectionPrivate *priv;
517   PangoFontDescription    *font_desc;
518   GtkWidget               *scrolled_win;
519   GtkWidget               *alignment;
520   GtkWidget               *preview_and_size;
521   GtkWidget               *size_controls;
522
523   fontsel->priv = G_TYPE_INSTANCE_GET_PRIVATE (fontsel,
524                                                GTK_TYPE_FONT_SELECTION,
525                                                GtkFontSelectionPrivate);
526
527   priv = fontsel->priv;
528   priv->size_list = NULL;
529   priv->font_list = NULL;
530   priv->face_list = NULL;
531
532   priv->_size_model = NULL;
533   priv->_font_model = NULL;
534   priv->_face_model = NULL;
535
536   gtk_widget_push_composite_child ();
537
538   /* Creating fundamental widgets for the private struct */
539   priv->search_entry = gtk_entry_new ();
540   priv->family_face_list = gtk_tree_view_new ();
541   priv->preview = gtk_entry_new ();
542   priv->size_slider = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL,
543                                                 (gdouble) font_sizes[0],
544                                                 (gdouble) font_sizes[FONT_SIZES_LENGTH - 1],
545                                                 1.0);
546
547   priv->size_spin = gtk_spin_button_new_with_range (0.0, (gdouble)(G_MAXINT / PANGO_SCALE), 1.0);
548
549   /** Bootstrapping widget layout **/
550   gtk_box_set_spacing (GTK_BOX (fontsel), 6);
551   gtk_box_pack_start (GTK_BOX (fontsel), priv->search_entry, FALSE, TRUE, 0);
552
553   /* Main font family/face view */
554   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
555   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
556                                   GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
557   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
558                                        GTK_SHADOW_ETCHED_IN);
559   gtk_container_add (GTK_CONTAINER (scrolled_win), priv->family_face_list);
560
561   /* Alignment for the preview and size controls */
562 /*  alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
563   gtk_alignment_set_padding (GTK_ALIGNMENT (alignment),
564                              PREVIEW_TOP_PADDING, 0, 0, 0);*/
565   gtk_box_pack_start (GTK_BOX (fontsel), scrolled_win, TRUE, TRUE, 0);
566
567   preview_and_size = gtk_vbox_new (TRUE, 0);
568   gtk_box_set_homogeneous (GTK_BOX (preview_and_size), FALSE);
569   gtk_box_set_spacing (GTK_BOX (preview_and_size), 6);
570
571   /* The preview entry needs a scrolled window to make sure we have a */
572   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
573   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
574                                   GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
575   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
576                                        GTK_SHADOW_ETCHED_IN);
577   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win),
578                                          priv->preview);
579   gtk_box_pack_start (GTK_BOX (preview_and_size), scrolled_win, FALSE, FALSE, 0);
580   
581   /* Setting the size requests for various widgets */
582   gtk_widget_set_size_request (GTK_WIDGET (fontsel), FONTSEL_WIDTH, FONTSEL_HEIGHT);
583   gtk_widget_set_size_request (scrolled_win,  -1, PREVIEW_HEIGHT);
584   gtk_widget_set_size_request (priv->preview, -1, PREVIEW_HEIGHT - 6);
585
586   /* Unset the frame on the preview entry */
587   gtk_entry_set_has_frame (GTK_ENTRY (priv->preview), FALSE);
588
589   /* Packing the slider and the spin in a hbox */
590   size_controls = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
591   gtk_scale_set_draw_value (GTK_SCALE (priv->size_slider), FALSE);
592   gtk_box_set_spacing (GTK_BOX (size_controls), 6);
593   gtk_box_pack_start  (GTK_BOX (size_controls), priv->size_slider, TRUE, TRUE, 0);
594   gtk_box_pack_start  (GTK_BOX (size_controls), priv->size_spin, FALSE, TRUE, 0);
595   
596   gtk_widget_set_valign (priv->size_spin, GTK_ALIGN_START);
597
598   gtk_box_pack_start (GTK_BOX (preview_and_size), size_controls, FALSE, FALSE, 0);
599 //  gtk_container_add (GTK_CONTAINER (alignment), preview_and_size);
600
601   gtk_box_pack_start (GTK_BOX (fontsel), GTK_WIDGET(preview_and_size), FALSE, TRUE, 0);
602
603   /* Getting the default size */
604   font_desc  = pango_context_get_font_description (gtk_widget_get_pango_context (GTK_WIDGET (fontsel)));
605   priv->size = pango_font_description_get_size (font_desc);
606   priv->face = NULL;
607   priv->family = NULL;
608   
609   gtk_adjustment_set_value (gtk_range_get_adjustment (GTK_RANGE (priv->size_slider)),
610                             (gdouble)(priv->size / PANGO_SCALE));
611   gtk_adjustment_set_value (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->size_spin)),
612                             (gdouble)(priv->size / PANGO_SCALE));
613
614   gtk_widget_show_all (GTK_WIDGET (fontsel));
615   gtk_widget_hide (GTK_WIDGET (fontsel));
616
617   /* Treeview column and model bootstrapping */
618   gtk_font_selection_bootstrap_fontlist (fontsel);
619   
620   /* Set default preview text */
621   gtk_entry_set_text (GTK_ENTRY (priv->preview),
622                       pango_language_get_sample_string (NULL));
623   
624   /* Set search icon and place holder text */
625   gtk_entry_set_icon_from_stock (GTK_ENTRY (priv->search_entry),
626                                  GTK_ENTRY_ICON_SECONDARY,
627                                  GTK_STOCK_FIND);
628   gtk_entry_set_placeholder_text (GTK_ENTRY (priv->search_entry), _("Search font name"));
629   
630   /** Callback connections **/
631   /* Connect to callback for the live search text entry */
632   g_signal_connect (G_OBJECT (gtk_entry_get_buffer (GTK_ENTRY (priv->search_entry))),
633                     "deleted-text", G_CALLBACK (deleted_text_cb), priv);
634   g_signal_connect (G_OBJECT (gtk_entry_get_buffer (GTK_ENTRY (priv->search_entry))),
635                     "inserted-text", G_CALLBACK (inserted_text_cb), priv);
636   g_signal_connect (G_OBJECT (priv->search_entry),
637                     "icon-press", G_CALLBACK (icon_press_cb), priv);
638
639   /* Size controls callbacks */
640   g_signal_connect (G_OBJECT (gtk_range_get_adjustment (GTK_RANGE (priv->size_slider))),
641                     "value-changed", G_CALLBACK (slider_change_cb), priv);
642   g_signal_connect (G_OBJECT (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->size_spin))),
643                     "value-changed", G_CALLBACK (spin_change_cb), priv);
644   priv->ignore_slider = FALSE;
645   
646   /* Font selection callback */
647   g_signal_connect (G_OBJECT (priv->family_face_list), "cursor-changed",
648                     G_CALLBACK (cursor_changed_cb),    fontsel);
649
650   /* Zoom on preview scroll*/
651   g_signal_connect (G_OBJECT (scrolled_win),      "scroll-event",
652                     G_CALLBACK (zoom_preview_cb), priv);
653
654   g_signal_connect (G_OBJECT (priv->size_slider), "scroll-event",
655                     G_CALLBACK (zoom_preview_cb), priv);
656
657   set_range_marks (priv, priv->size_slider, (gint*)font_sizes, FONT_SIZES_LENGTH);
658
659   /* Set default focus */
660   gtk_widget_pop_composite_child();
661 }
662
663 /**
664  * gtk_font_selection_new:
665  *
666  * Creates a new #GtkFontSelection.
667  *
668  * Return value: a new #GtkFontSelection
669  */
670 GtkWidget *
671 gtk_font_selection_new (void)
672 {
673   GtkFontSelection *fontsel;
674   
675   fontsel = g_object_new (GTK_TYPE_FONT_SELECTION, NULL);
676   
677   return GTK_WIDGET (fontsel);
678 }
679
680 static int
681 cmp_families (const void *a, const void *b)
682 {
683   const char *a_name = pango_font_family_get_name (*(PangoFontFamily **)a);
684   const char *b_name = pango_font_family_get_name (*(PangoFontFamily **)b);
685
686   return g_utf8_collate (a_name, b_name);
687 }
688
689 static void 
690 populate_list (GtkTreeView* treeview, GtkListStore* model)
691 {
692   GtkStyleContext *style_context;
693   GdkRGBA          g_color;
694   PangoColor       p_color;
695   gchar            *color_string;
696
697   GtkTreeIter   match_row;
698   GtkTreePath  *path;
699
700   gint n_families, i;  
701   PangoFontFamily **families;
702
703   GString     *tmp = g_string_new (NULL);
704   GString     *family_and_face = g_string_new (NULL);
705
706   pango_context_list_families (gtk_widget_get_pango_context (GTK_WIDGET (treeview)),
707                                &families,
708                                &n_families);
709
710   qsort (families, n_families, sizeof (PangoFontFamily *), cmp_families);
711
712   gtk_list_store_clear (model);
713
714   /* Get row header font color */
715   style_context = gtk_widget_get_style_context (GTK_WIDGET (treeview));
716   gtk_style_context_get_color (style_context,
717                                GTK_STATE_FLAG_NORMAL |GTK_STATE_FLAG_INSENSITIVE,
718                                &g_color);
719
720   p_color.red   = (guint16)((gdouble)G_MAXUINT16 * g_color.red);
721   p_color.green = (guint16)((gdouble)G_MAXUINT16 * g_color.green);
722   p_color.blue  = (guint16)((gdouble)G_MAXUINT16 * g_color.blue);
723   color_string  = pango_color_to_string (&p_color);
724
725   /* Iterate over families and faces */
726   for (i=0; i<n_families; i++)
727     {
728       GtkTreeIter     iter;
729       PangoFontFace **faces;
730       
731       int             j, n_faces;
732       const gchar    *fam_name = pango_font_family_get_name (families[i]);
733
734       pango_font_family_list_faces (families[i], &faces, &n_faces);
735       
736       for (j=0; j<n_faces; j++)
737         {
738           PangoFontDescription *pango_desc = pango_font_face_describe (faces[j]);
739           const gchar *face_name = pango_font_face_get_face_name (faces[j]);
740           gchar       *font_desc = pango_font_description_to_string (pango_desc);
741           
742           /* foreground_color, family_name, face_name, desc, sample string */
743           g_string_printf (family_and_face, "%s %s",
744                                             fam_name,
745                                             face_name);
746           
747           g_string_printf (tmp, ROW_FORMAT_STRING,
748                                 color_string,
749                                 family_and_face->str,
750                                 font_desc,
751                                 pango_language_get_sample_string (NULL));
752
753           gtk_list_store_append (model, &iter);
754           gtk_list_store_set (model, &iter,
755                               FAMILY_COLUMN, families[i],
756                               FACE_COLUMN, faces[j],
757                               PREVIEW_TITLE_COLUMN, family_and_face->str,
758                               PREVIEW_TEXT_COLUMN, tmp->str,
759                               /** FIXME: FAMILY_NAME_COLUMN and FACE_NAME_COLUMN
760                                   are needed only until we remove the deprecated
761                                   API **/
762                               FAMILY_NAME_COLUMN, fam_name,
763                               FACE_NAME_COLUMN, face_name,
764                               -1);
765
766           if ((i == 0 && j == 0) ||
767               (!g_ascii_strcasecmp (face_name, "sans") && j == 0))
768             {
769               match_row = iter;
770             }
771
772           pango_font_description_free(pango_desc);
773           g_free (font_desc);
774         }
775
776       g_free (faces);
777     }
778
779   path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &match_row);
780   
781   if (path)
782   {
783     gtk_tree_view_set_cursor (treeview, path, NULL, FALSE);
784     gtk_tree_path_free(path);
785   }
786
787
788   g_string_free (family_and_face, TRUE);
789   g_string_free (tmp, TRUE);
790   g_free (color_string);
791   g_free (families);
792 }
793
794 gboolean
795 visible_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
796 {
797   gboolean result = FALSE;
798   GtkFontSelectionPrivate *priv = (GtkFontSelectionPrivate*) data;
799
800   const gchar *search_text = (const gchar*)gtk_entry_get_text (GTK_ENTRY (priv->search_entry));
801   gchar       *font_name;
802   gchar       *font_name_casefold;
803   gchar       *search_text_casefold;
804
805   gtk_tree_model_get (model, iter,
806                       PREVIEW_TITLE_COLUMN, &font_name,
807                       -1);
808
809   /* Covering some corner cases to speed up the result */
810   if (font_name == NULL ||
811       strlen (search_text) > strlen (font_name))
812     {
813       g_free (font_name);
814       return FALSE;
815     }  
816   if (strlen (search_text) == 0)
817     {
818       g_free (font_name);
819       return TRUE;
820     }
821   
822   font_name_casefold = g_utf8_casefold (font_name, -1);
823   search_text_casefold = g_utf8_casefold (search_text, -1);
824   
825   if (g_strrstr (font_name_casefold, search_text_casefold))
826     result = TRUE;
827
828   g_free (search_text_casefold);
829   g_free (font_name_casefold);
830   g_free (font_name);
831   return result;
832 }
833
834 static void
835 gtk_font_selection_bootstrap_fontlist (GtkFontSelection* fontsel)
836 {
837   GtkTreeView       *treeview = GTK_TREE_VIEW (fontsel->priv->family_face_list);
838   GtkCellRenderer   *cell;
839   GtkTreeViewColumn *col;
840
841   fontsel->priv->model = gtk_list_store_new (6,
842                                              PANGO_TYPE_FONT_FAMILY,
843                                              PANGO_TYPE_FONT_FACE,
844                                              G_TYPE_STRING,
845                                              G_TYPE_STRING,
846                                              /*FIXME: Remove two strings after deprecation removal */
847                                              G_TYPE_STRING,
848                                              G_TYPE_STRING);
849
850   fontsel->priv->filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fontsel->priv->model),
851                                                      NULL);
852   g_object_unref (fontsel->priv->model);
853
854   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (fontsel->priv->filter),
855                                           visible_func,
856                                           (gpointer)fontsel->priv,
857                                           NULL);
858
859   gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (fontsel->priv->filter));
860   g_object_unref (fontsel->priv->filter);
861
862   gtk_tree_view_set_rules_hint      (treeview, TRUE);
863   gtk_tree_view_set_headers_visible (treeview, FALSE);
864
865   cell = gtk_cell_renderer_text_new ();
866   col = gtk_tree_view_column_new_with_attributes ("Family",
867                                                   cell,
868                                                   "markup", PREVIEW_TEXT_COLUMN,
869                                                   NULL);
870                                                   
871
872   g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
873
874   gtk_tree_view_append_column (treeview, col);
875
876   populate_list (treeview, fontsel->priv->model);
877 }
878
879
880 static void
881 gtk_font_selection_finalize (GObject *object)
882 {
883   GtkFontSelection *fontsel = GTK_FONT_SELECTION (object);
884
885   gtk_font_selection_ref_family (fontsel, NULL);
886   gtk_font_selection_ref_face (fontsel, NULL);
887
888   G_OBJECT_CLASS (gtk_font_selection_parent_class)->finalize (object);
889 }
890
891 #if 0
892 static void
893 gtk_font_selection_screen_changed (GtkWidget *widget,
894                                    GdkScreen *previous_screen)
895 {
896   return;
897 }
898
899 static void
900 gtk_font_selection_style_updated (GtkWidget *widget)
901 {
902   /*GTK_WIDGET_CLASS (gtk_font_selection_parent_class)->style_updated (widget);*/
903   return;
904 }
905 #endif 
906
907 static void
908 gtk_font_selection_ref_family (GtkFontSelection *fontsel,
909                                PangoFontFamily  *family)
910 {
911   GtkFontSelectionPrivate *priv = fontsel->priv;
912
913   if (family)
914     family = g_object_ref (family);
915   if (priv->family)
916     g_object_unref (priv->family);
917   priv->family = family;
918 }
919
920 static void
921 gtk_font_selection_ref_face (GtkFontSelection *fontsel,
922                              PangoFontFace    *face)
923 {
924   GtkFontSelectionPrivate *priv = fontsel->priv;
925
926   if (face)
927     face = g_object_ref (face);
928   if (priv->face)
929     g_object_unref (priv->face);
930   priv->face = face;
931 }
932
933 /* These functions populate the deprecated widgets to maintain API compatibility */
934 static void
935 populate_font_model (GtkFontSelection *fontsel)
936 {
937   GtkFontSelectionPrivate *priv = fontsel->priv;
938 }
939
940 static void
941 update_font_model_selection (GtkFontSelection *fontsel)
942 {
943   GtkFontSelectionPrivate *priv = fontsel->priv;
944 }
945
946 static void
947 update_face_model (GtkFontSelection *fontsel)
948 {
949   GtkFontSelectionPrivate *priv = fontsel->priv;
950 }
951
952 static void
953 update_size_model (GtkFontSelection *fontsel)
954 {
955   GtkFontSelectionPrivate *priv = fontsel->priv;
956 }
957
958 static void
959 initialize_deprecated_widgets (GtkFontSelection *fontsel)
960 {
961   GtkFontSelectionPrivate *priv = fontsel->priv;
962
963   priv->_size_model = gtk_list_store_new (2, G_TYPE_INT, G_TYPE_STRING);
964   priv->_font_model = gtk_list_store_new (2, PANGO_TYPE_FONT_FAMILY, G_TYPE_STRING);
965   priv->_face_model = gtk_list_store_new (2, PANGO_TYPE_FONT_FACE,   G_TYPE_STRING);
966
967   priv->size_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (priv->_size_model));
968   priv->font_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (priv->_font_model));
969   priv->face_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (priv->_size_model));
970
971   g_object_unref (priv->_size_model);
972   g_object_unref (priv->_font_model);
973   g_object_unref (priv->_face_model);
974 }
975
976 static void
977 destroy_deprecated_widgets (GtkFontSelection *fontsel)
978 {
979   GtkFontSelectionPrivate *priv = fontsel->priv;
980
981   g_object_unref (priv->size_list);
982   g_object_unref (priv->font_list);
983   g_object_unref (priv->face_list);
984 }
985
986 /*****************************************************************************
987  * These functions are the main public interface for getting/setting the font.
988  *****************************************************************************/
989
990 /**
991  * gtk_font_selection_get_family_list:
992  * @fontsel: a #GtkFontSelection
993  *
994  * This returns the #GtkTreeView that lists font families, for
995  * example, 'Sans', 'Serif', etc.
996  *
997  * Return value: (transfer none): A #GtkWidget that is part of @fontsel
998  *
999  * Deprecated: 3.2
1000  */
1001 GtkWidget *
1002 gtk_font_selection_get_family_list (GtkFontSelection *fontsel)
1003 {
1004   GtkFontSelectionPrivate *priv = fontsel->priv;
1005   g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), NULL);
1006
1007   return NULL;
1008 }
1009
1010 /**
1011  * gtk_font_selection_get_face_list:
1012  * @fontsel: a #GtkFontSelection
1013  *
1014  * This returns the #GtkTreeView which lists all styles available for
1015  * the selected font. For example, 'Regular', 'Bold', etc.
1016  * 
1017  * Return value: (transfer none): A #GtkWidget that is part of @fontsel
1018  *
1019  * Deprecated: 3.2
1020  */
1021 GtkWidget *
1022 gtk_font_selection_get_face_list (GtkFontSelection *fontsel)
1023 {
1024   GtkFontSelectionPrivate *priv = fontsel->priv;
1025   g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), NULL);
1026
1027   return NULL;
1028 }
1029
1030 /**
1031  * gtk_font_selection_get_size_entry:
1032  * @fontsel: a #GtkFontSelection
1033  *
1034  * This returns the #GtkEntry used to allow the user to edit the font
1035  * number manually instead of selecting it from the list of font sizes.
1036  *
1037  * Return value: (transfer none): A #GtkWidget that is part of @fontsel
1038  *
1039  * Deprecated: 3.2
1040  */
1041 GtkWidget *
1042 gtk_font_selection_get_size_entry (GtkFontSelection *fontsel)
1043 {
1044   GtkFontSelectionPrivate *priv = fontsel->priv;
1045   g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), NULL);
1046
1047   return priv->size_spin;
1048 }
1049
1050 /**
1051  * gtk_font_selection_get_size_list:
1052  * @fontsel: a #GtkFontSelection
1053  *
1054  * This returns the #GtkTreeeView used to list font sizes.
1055  *
1056  * Return value: (transfer none): A #GtkWidget that is part of @fontsel
1057  *
1058  * Deprecated: 3.2
1059  */
1060 GtkWidget *
1061 gtk_font_selection_get_size_list (GtkFontSelection *fontsel)
1062 {
1063   GtkFontSelectionPrivate *priv = fontsel->priv;
1064   g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), NULL);
1065
1066   return NULL;
1067 }
1068
1069 /**
1070  * gtk_font_selection_get_preview_entry:
1071  * @fontsel: a #GtkFontSelection
1072  *
1073  * This returns the #GtkEntry used to display the font as a preview.
1074  *
1075  * Return value: (transfer none): A #GtkWidget that is part of @fontsel
1076  *
1077  * Deprecated: 3.2
1078  */
1079 GtkWidget *
1080 gtk_font_selection_get_preview_entry (GtkFontSelection *fontsel)
1081 {
1082   GtkFontSelectionPrivate *priv = fontsel->priv;
1083   g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), NULL);
1084
1085   return priv->preview;
1086 }
1087
1088 /**
1089  * gtk_font_selection_get_family:
1090  * @fontsel: a #GtkFontSelection
1091  *
1092  * Gets the #PangoFontFamily representing the selected font family.
1093  *
1094  * Return value: (transfer none): A #PangoFontFamily representing the
1095  *     selected font family. Font families are a collection of font
1096  *     faces. The returned object is owned by @fontsel and must not
1097  *     be modified or freed.
1098  *
1099  * Since: 2.14
1100  */
1101 PangoFontFamily *
1102 gtk_font_selection_get_family (GtkFontSelection *fontsel)
1103 {
1104   g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), NULL);
1105
1106   return NULL;
1107 }
1108
1109 /**
1110  * gtk_font_selection_get_face:
1111  * @fontsel: a #GtkFontSelection
1112  *
1113  * Gets the #PangoFontFace representing the selected font group
1114  * details (i.e. family, slant, weight, width, etc).
1115  *
1116  * Return value: (transfer none): A #PangoFontFace representing the
1117  *     selected font group details. The returned object is owned by
1118  *     @fontsel and must not be modified or freed.
1119  *
1120  * Since: 2.14
1121  */
1122 PangoFontFace *
1123 gtk_font_selection_get_face (GtkFontSelection *fontsel)
1124 {
1125   g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), NULL);
1126
1127   return NULL;
1128 }
1129
1130 /**
1131  * gtk_font_selection_get_size:
1132  * @fontsel: a #GtkFontSelection
1133  *
1134  * The selected font size.
1135  *
1136  * Return value: A n integer representing the selected font size,
1137  *     or -1 if no font size is selected.
1138  *
1139  * Since: 2.14
1140  **/
1141 gint
1142 gtk_font_selection_get_size (GtkFontSelection *fontsel)
1143 {
1144   g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), -1);
1145
1146   return fontsel->priv->size;
1147 }
1148
1149 /**
1150  * gtk_font_selection_get_font_name:
1151  * @fontsel: a #GtkFontSelection
1152  * 
1153  * Gets the currently-selected font name. 
1154  *
1155  * Note that this can be a different string than what you set with 
1156  * gtk_font_selection_set_font_name(), as the font selection widget may 
1157  * normalize font names and thus return a string with a different structure. 
1158  * For example, "Helvetica Italic Bold 12" could be normalized to 
1159  * "Helvetica Bold Italic 12". Use pango_font_description_equal()
1160  * if you want to compare two font descriptions.
1161  * 
1162  * Return value: (transfer full) (allow-none): A string with the name of the
1163  *     current font, or %NULL if  no font is selected. You must free this
1164  *     string with g_free().
1165  */
1166 gchar *
1167 gtk_font_selection_get_font_name (GtkFontSelection *fontsel)
1168 {
1169   if (!fontsel->priv->family)
1170     return NULL;
1171
1172   return g_strdup (pango_font_family_get_name (fontsel->priv->family));
1173 }
1174
1175 /* This sets the current font, then selecting the appropriate list rows. */
1176
1177 /**
1178  * gtk_font_selection_set_font_name:
1179  * @fontsel: a #GtkFontSelection
1180  * @fontname: a font name like "Helvetica 12" or "Times Bold 18"
1181  * 
1182  * Sets the currently-selected font. 
1183  *
1184  * Note that the @fontsel needs to know the screen in which it will appear 
1185  * for this to work; this can be guaranteed by simply making sure that the 
1186  * @fontsel is inserted in a toplevel window before you call this function.
1187  * 
1188  * Return value: %TRUE if the font could be set successfully; %FALSE if no 
1189  *     such font exists or if the @fontsel doesn't belong to a particular 
1190  *     screen yet.
1191  */
1192 gboolean
1193 gtk_font_selection_set_font_name (GtkFontSelection *fontsel,
1194                                   const gchar      *fontname)
1195 {
1196 #if 0
1197   PangoFontFamily *family = NULL;
1198   PangoFontFace *face = NULL;
1199   PangoFontDescription *new_desc;
1200 #endif
1201
1202   g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), FALSE);
1203
1204   return TRUE;
1205 }
1206
1207 /**
1208  * gtk_font_selection_get_preview_text:
1209  * @fontsel: a #GtkFontSelection
1210  *
1211  * Gets the text displayed in the preview area.
1212  * 
1213  * Return value: the text displayed in the preview area. 
1214  *     This string is owned by the widget and should not be 
1215  *     modified or freed 
1216  */
1217 G_CONST_RETURN gchar*
1218 gtk_font_selection_get_preview_text (GtkFontSelection *fontsel)
1219 {
1220   return NULL;
1221 }
1222
1223
1224 /**
1225  * gtk_font_selection_set_preview_text:
1226  * @fontsel: a #GtkFontSelection
1227  * @text: the text to display in the preview area 
1228  *
1229  * Sets the text displayed in the preview area.
1230  * The @text is used to show how the selected font looks.
1231  */
1232 void
1233 gtk_font_selection_set_preview_text  (GtkFontSelection *fontsel,
1234                                       const gchar      *text)
1235 {
1236 #if 0
1237   GtkFontSelectionPrivate *priv;
1238
1239   g_return_if_fail (GTK_IS_FONT_SELECTION (fontsel));
1240   g_return_if_fail (text != NULL);
1241
1242   priv = fontsel->priv;
1243 #endif
1244 }
1245
1246
1247 /**
1248  * SECTION:gtkfontseldlg
1249  * @Short_description: A dialog box for selecting fonts
1250  * @Title: GtkFontSelectionDialog
1251  * @See_also: #GtkFontSelection, #GtkDialog
1252  *
1253  * The #GtkFontSelectionDialog widget is a dialog box for selecting a font.
1254  *
1255  * To set the font which is initially selected, use
1256  * gtk_font_selection_dialog_set_font_name().
1257  *
1258  * To get the selected font use gtk_font_selection_dialog_get_font_name().
1259  *
1260  * To change the text which is shown in the preview area, use
1261  * gtk_font_selection_dialog_set_preview_text().
1262  *
1263  * <refsect2 id="GtkFontSelectionDialog-BUILDER-UI">
1264  * <title>GtkFontSelectionDialog as GtkBuildable</title>
1265  * The GtkFontSelectionDialog implementation of the GtkBuildable interface
1266  * exposes the embedded #GtkFontSelection as internal child with the
1267  * name "font_selection". It also exposes the buttons with the names
1268  * "ok_button", "cancel_button" and "apply_button".
1269  * </refsect2>
1270  */
1271
1272 static void gtk_font_selection_dialog_buildable_interface_init     (GtkBuildableIface *iface);
1273 static GObject * gtk_font_selection_dialog_buildable_get_internal_child (GtkBuildable *buildable,
1274                                                                           GtkBuilder   *builder,
1275                                                                           const gchar  *childname);
1276
1277 G_DEFINE_TYPE_WITH_CODE (GtkFontSelectionDialog, gtk_font_selection_dialog,
1278                          GTK_TYPE_DIALOG,
1279                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
1280                                                 gtk_font_selection_dialog_buildable_interface_init))
1281
1282 static GtkBuildableIface *parent_buildable_iface;
1283
1284 static void
1285 gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass)
1286 {
1287   g_type_class_add_private (klass, sizeof (GtkFontSelectionDialogPrivate));
1288 }
1289
1290 static void
1291 gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag)
1292 {
1293   GtkFontSelectionDialogPrivate *priv;
1294   GtkDialog *dialog = GTK_DIALOG (fontseldiag);
1295   GtkWidget *action_area, *content_area;
1296
1297   fontseldiag->priv = G_TYPE_INSTANCE_GET_PRIVATE (fontseldiag,
1298                                                    GTK_TYPE_FONT_SELECTION_DIALOG,
1299                                                    GtkFontSelectionDialogPrivate);
1300   priv = fontseldiag->priv;
1301
1302   content_area = gtk_dialog_get_content_area (dialog);
1303   action_area = gtk_dialog_get_action_area (dialog);
1304
1305   gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
1306   gtk_box_set_spacing (GTK_BOX (content_area), 2); /* 2 * 5 + 2 = 12 */
1307   gtk_container_set_border_width (GTK_CONTAINER (action_area), 5);
1308   gtk_box_set_spacing (GTK_BOX (action_area), 6);
1309
1310   gtk_widget_push_composite_child ();
1311
1312   gtk_window_set_resizable (GTK_WINDOW (fontseldiag), TRUE);
1313
1314   /* Create the content area */
1315   priv->fontsel = gtk_font_selection_new ();
1316   gtk_container_set_border_width (GTK_CONTAINER (priv->fontsel), 5);
1317   gtk_widget_show (priv->fontsel);
1318   gtk_box_pack_start (GTK_BOX (content_area),
1319                       priv->fontsel, TRUE, TRUE, 0);
1320
1321   /* Create the action area */
1322   priv->cancel_button = gtk_dialog_add_button (dialog,
1323                                                GTK_STOCK_CANCEL,
1324                                                GTK_RESPONSE_CANCEL);
1325
1326   priv->apply_button = gtk_dialog_add_button (dialog,
1327                                               GTK_STOCK_APPLY,
1328                                               GTK_RESPONSE_APPLY);
1329   gtk_widget_hide (priv->apply_button);
1330
1331   priv->ok_button = gtk_dialog_add_button (dialog,
1332                                            GTK_STOCK_OK,
1333                                            GTK_RESPONSE_OK);
1334   gtk_widget_grab_default (priv->ok_button);
1335
1336   gtk_dialog_set_alternative_button_order (GTK_DIALOG (fontseldiag),
1337                                            GTK_RESPONSE_OK,
1338                                            GTK_RESPONSE_APPLY,
1339                                            GTK_RESPONSE_CANCEL,
1340                                            -1);
1341
1342   gtk_window_set_title (GTK_WINDOW (fontseldiag),
1343                         _("Font Selection"));
1344
1345   gtk_widget_pop_composite_child ();
1346 }
1347
1348 /**
1349  * gtk_font_selection_dialog_new:
1350  * @title: the title of the dialog window 
1351  *
1352  * Creates a new #GtkFontSelectionDialog.
1353  *
1354  * Return value: a new #GtkFontSelectionDialog
1355  */
1356 GtkWidget*
1357 gtk_font_selection_dialog_new (const gchar *title)
1358 {
1359   GtkFontSelectionDialog *fontseldiag;
1360   
1361   fontseldiag = g_object_new (GTK_TYPE_FONT_SELECTION_DIALOG, NULL);
1362
1363   if (title)
1364     gtk_window_set_title (GTK_WINDOW (fontseldiag), title);
1365   
1366   return GTK_WIDGET (fontseldiag);
1367 }
1368
1369 /**
1370  * gtk_font_selection_dialog_get_font_selection:
1371  * @fsd: a #GtkFontSelectionDialog
1372  *
1373  * Retrieves the #GtkFontSelection widget embedded in the dialog.
1374  *
1375  * Returns: (transfer none): the embedded #GtkFontSelection
1376  *
1377  * Since: 2.22
1378  **/
1379 GtkWidget*
1380 gtk_font_selection_dialog_get_font_selection (GtkFontSelectionDialog *fsd)
1381 {
1382   g_return_val_if_fail (GTK_IS_FONT_SELECTION_DIALOG (fsd), NULL);
1383
1384   return fsd->priv->fontsel;
1385 }
1386
1387
1388 /**
1389  * gtk_font_selection_dialog_get_ok_button:
1390  * @fsd: a #GtkFontSelectionDialog
1391  *
1392  * Gets the 'OK' button.
1393  *
1394  * Return value: (transfer none): the #GtkWidget used in the dialog
1395  *     for the 'OK' button.
1396  *
1397  * Since: 2.14
1398  */
1399 GtkWidget *
1400 gtk_font_selection_dialog_get_ok_button (GtkFontSelectionDialog *fsd)
1401 {
1402   g_return_val_if_fail (GTK_IS_FONT_SELECTION_DIALOG (fsd), NULL);
1403
1404   return fsd->priv->ok_button;
1405 }
1406
1407 /**
1408  * gtk_font_selection_dialog_get_cancel_button:
1409  * @fsd: a #GtkFontSelectionDialog
1410  *
1411  * Gets the 'Cancel' button.
1412  *
1413  * Return value: (transfer none): the #GtkWidget used in the dialog
1414  *     for the 'Cancel' button.
1415  *
1416  * Since: 2.14
1417  */
1418 GtkWidget *
1419 gtk_font_selection_dialog_get_cancel_button (GtkFontSelectionDialog *fsd)
1420 {
1421   g_return_val_if_fail (GTK_IS_FONT_SELECTION_DIALOG (fsd), NULL);
1422
1423   return fsd->priv->cancel_button;
1424 }
1425
1426 static void
1427 gtk_font_selection_dialog_buildable_interface_init (GtkBuildableIface *iface)
1428 {
1429   parent_buildable_iface = g_type_interface_peek_parent (iface);
1430   iface->get_internal_child = gtk_font_selection_dialog_buildable_get_internal_child;
1431 }
1432
1433 static GObject *
1434 gtk_font_selection_dialog_buildable_get_internal_child (GtkBuildable *buildable,
1435                                                         GtkBuilder   *builder,
1436                                                         const gchar  *childname)
1437 {
1438   GtkFontSelectionDialogPrivate *priv;
1439
1440   priv = GTK_FONT_SELECTION_DIALOG (buildable)->priv;
1441
1442   if (g_strcmp0 (childname, "ok_button") == 0)
1443     return G_OBJECT (priv->ok_button);
1444   else if (g_strcmp0 (childname, "cancel_button") == 0)
1445     return G_OBJECT (priv->cancel_button);
1446   else if (g_strcmp0 (childname, "apply_button") == 0)
1447     return G_OBJECT (priv->apply_button);
1448   else if (g_strcmp0 (childname, "font_selection") == 0)
1449     return G_OBJECT (priv->fontsel);
1450
1451   return parent_buildable_iface->get_internal_child (buildable, builder, childname);
1452 }
1453
1454 /**
1455  * gtk_font_selection_dialog_get_font_name:
1456  * @fsd: a #GtkFontSelectionDialog
1457  * 
1458  * Gets the currently-selected font name.
1459  *
1460  * Note that this can be a different string than what you set with 
1461  * gtk_font_selection_dialog_set_font_name(), as the font selection widget
1462  * may normalize font names and thus return a string with a different 
1463  * structure. For example, "Helvetica Italic Bold 12" could be normalized 
1464  * to "Helvetica Bold Italic 12".  Use pango_font_description_equal()
1465  * if you want to compare two font descriptions.
1466  * 
1467  * Return value: A string with the name of the current font, or %NULL if no 
1468  *     font is selected. You must free this string with g_free().
1469  */
1470 gchar*
1471 gtk_font_selection_dialog_get_font_name (GtkFontSelectionDialog *fsd)
1472 {
1473   GtkFontSelectionDialogPrivate *priv;
1474
1475   g_return_val_if_fail (GTK_IS_FONT_SELECTION_DIALOG (fsd), NULL);
1476
1477   priv = fsd->priv;
1478
1479   return gtk_font_selection_get_font_name (GTK_FONT_SELECTION (priv->fontsel));
1480 }
1481
1482 /**
1483  * gtk_font_selection_dialog_set_font_name:
1484  * @fsd: a #GtkFontSelectionDialog
1485  * @fontname: a font name like "Helvetica 12" or "Times Bold 18"
1486  *
1487  * Sets the currently selected font. 
1488  * 
1489  * Return value: %TRUE if the font selected in @fsd is now the
1490  *     @fontname specified, %FALSE otherwise. 
1491  */
1492 gboolean
1493 gtk_font_selection_dialog_set_font_name (GtkFontSelectionDialog *fsd,
1494                                          const gchar            *fontname)
1495 {
1496   GtkFontSelectionDialogPrivate *priv;
1497
1498   g_return_val_if_fail (GTK_IS_FONT_SELECTION_DIALOG (fsd), FALSE);
1499   g_return_val_if_fail (fontname, FALSE);
1500
1501   priv = fsd->priv;
1502
1503   return gtk_font_selection_set_font_name (GTK_FONT_SELECTION (priv->fontsel), fontname);
1504 }
1505
1506 /**
1507  * gtk_font_selection_dialog_get_preview_text:
1508  * @fsd: a #GtkFontSelectionDialog
1509  *
1510  * Gets the text displayed in the preview area.
1511  * 
1512  * Return value: the text displayed in the preview area. 
1513  *     This string is owned by the widget and should not be 
1514  *     modified or freed 
1515  */
1516 G_CONST_RETURN gchar*
1517 gtk_font_selection_dialog_get_preview_text (GtkFontSelectionDialog *fsd)
1518 {
1519   GtkFontSelectionDialogPrivate *priv;
1520
1521   g_return_val_if_fail (GTK_IS_FONT_SELECTION_DIALOG (fsd), NULL);
1522
1523   priv = fsd->priv;
1524
1525   return gtk_font_selection_get_preview_text (GTK_FONT_SELECTION (priv->fontsel));
1526 }
1527
1528 /**
1529  * gtk_font_selection_dialog_set_preview_text:
1530  * @fsd: a #GtkFontSelectionDialog
1531  * @text: the text to display in the preview area
1532  *
1533  * Sets the text displayed in the preview area. 
1534  */
1535 void
1536 gtk_font_selection_dialog_set_preview_text (GtkFontSelectionDialog *fsd,
1537                                             const gchar            *text)
1538 {
1539   GtkFontSelectionDialogPrivate *priv;
1540
1541   g_return_if_fail (GTK_IS_FONT_SELECTION_DIALOG (fsd));
1542   g_return_if_fail (text != NULL);
1543
1544   priv = fsd->priv;
1545
1546   gtk_font_selection_set_preview_text (GTK_FONT_SELECTION (priv->fontsel), text);
1547 }