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