]> Pileus Git - ~andy/gtk/blob - gtk/gtkfontchooserwidget.c
Change FSF Address
[~andy/gtk] / gtk / gtkfontchooserwidget.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2011 Alberto Ruiz <aruiz@gnome.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "config.h"
19
20 #include <stdlib.h>
21 #include <glib/gprintf.h>
22 #include <string.h>
23
24 #include <atk/atk.h>
25
26 #include "gtkfontchooserwidget.h"
27 #include "gtkfontchooser.h"
28 #include "gtkfontchooserutils.h"
29 #include "gtkcellrenderertext.h"
30 #include "gtkentry.h"
31 #include "gtkframe.h"
32 #include "gtkbbox.h"
33 #include "gtkbox.h"
34 #include "gtklabel.h"
35 #include "gtkliststore.h"
36 #include "gtkstock.h"
37 #include "gtktextview.h"
38 #include "gtktreeselection.h"
39 #include "gtktreeview.h"
40 #include "gtkscrolledwindow.h"
41 #include "gtkintl.h"
42 #include "gtkaccessible.h"
43 #include "gtkbuildable.h"
44 #include "gtkprivate.h"
45 #include "gtkscale.h"
46 #include "gtkspinbutton.h"
47 #include "gtknotebook.h"
48 #include "gtkwidget.h"
49 #include "gtkgrid.h"
50
51 /**
52  * SECTION:gtkfontchooserwidget
53  * @Short_description: A widget for selecting fonts
54  * @Title: GtkFontChooserWidget
55  * @See_also: #GtkFontChooserDialog
56  *
57  * The #GtkFontChooserWidget widget lists the available fonts,
58  * styles and sizes, allowing the user to select a font. It is
59  * used in the #GtkFontChooserDialog widget to provide a
60  * dialog box for selecting fonts.
61  *
62  * To set the font which is initially selected, use
63  * gtk_font_chooser_set_font() or gtk_font_chooser_set_font_desc().
64  *
65  * To get the selected font use gtk_font_chooser_get_font() or
66  * gtk_font_chooser_get_font_desc().
67  *
68  * To change the text which is shown in the preview area, use
69  * gtk_font_chooser_set_preview_text().
70  *
71  * Since: 3.2
72  */
73
74
75 struct _GtkFontChooserWidgetPrivate
76 {
77   GtkWidget    *search_entry;
78   GtkWidget    *family_face_list;
79   GtkCellRenderer *family_face_cell;
80   GtkWidget    *list_scrolled_window;
81   GtkWidget    *empty_list;
82   GtkWidget    *list_notebook;
83   GtkTreeModel *model;
84   GtkTreeModel *filter_model;
85
86   GtkWidget       *preview;
87   gchar           *preview_text;
88   gboolean         show_preview_entry;
89
90   GtkWidget *size_spin;
91   GtkWidget *size_slider;
92
93   PangoFontDescription *font_desc;
94   GtkTreeIter           font_iter;      /* invalid if font not available or pointer into model
95                                            (not filter_model) to the row containing font */
96   GtkFontFilterFunc filter_func;
97   gpointer          filter_data;
98   GDestroyNotify    filter_data_destroy;
99 };
100
101 /* This is the initial fixed height and the top padding of the preview entry */
102 #define PREVIEW_HEIGHT 72
103 #define PREVIEW_TOP_PADDING 6
104
105 /* These are the sizes of the font, style & size lists. */
106 #define FONT_LIST_HEIGHT  136
107 #define FONT_LIST_WIDTH   190
108 #define FONT_STYLE_LIST_WIDTH 170
109 #define FONT_SIZE_LIST_WIDTH  60
110
111 #define NO_FONT_MATCHED_SEARCH N_("No fonts matched your search. You can revise your search and try again.")
112
113 enum {
114   FAMILY_COLUMN,
115   FACE_COLUMN,
116   FONT_DESC_COLUMN,
117   PREVIEW_TITLE_COLUMN
118 };
119
120 static void gtk_font_chooser_widget_set_property         (GObject         *object,
121                                                           guint            prop_id,
122                                                           const GValue    *value,
123                                                           GParamSpec      *pspec);
124 static void gtk_font_chooser_widget_get_property         (GObject         *object,
125                                                           guint            prop_id,
126                                                           GValue          *value,
127                                                           GParamSpec      *pspec);
128 static void gtk_font_chooser_widget_finalize             (GObject         *object);
129
130 static void gtk_font_chooser_widget_screen_changed       (GtkWidget       *widget,
131                                                           GdkScreen       *previous_screen);
132
133 static void gtk_font_chooser_widget_bootstrap_fontlist   (GtkFontChooserWidget *fontchooser);
134
135 static gboolean gtk_font_chooser_widget_find_font        (GtkFontChooserWidget *fontchooser,
136                                                           const PangoFontDescription *font_desc,
137                                                           GtkTreeIter          *iter);
138 static void     gtk_font_chooser_widget_ensure_selection (GtkFontChooserWidget *fontchooser);
139
140 static gchar   *gtk_font_chooser_widget_get_font         (GtkFontChooserWidget *fontchooser);
141 static void     gtk_font_chooser_widget_set_font         (GtkFontChooserWidget *fontchooser,
142                                                           const gchar          *fontname);
143
144 static PangoFontDescription *gtk_font_chooser_widget_get_font_desc  (GtkFontChooserWidget *fontchooser);
145 static void                  gtk_font_chooser_widget_merge_font_desc(GtkFontChooserWidget *fontchooser,
146                                                                      PangoFontDescription *font_desc,
147                                                                      GtkTreeIter          *iter);
148 static void                  gtk_font_chooser_widget_take_font_desc (GtkFontChooserWidget *fontchooser,
149                                                                      PangoFontDescription *font_desc);
150
151
152 static const gchar *gtk_font_chooser_widget_get_preview_text (GtkFontChooserWidget *fontchooser);
153 static void         gtk_font_chooser_widget_set_preview_text (GtkFontChooserWidget *fontchooser,
154                                                               const gchar          *text);
155
156 static gboolean gtk_font_chooser_widget_get_show_preview_entry (GtkFontChooserWidget *fontchooser);
157 static void     gtk_font_chooser_widget_set_show_preview_entry (GtkFontChooserWidget *fontchooser,
158                                                                 gboolean              show_preview_entry);
159
160 static void gtk_font_chooser_widget_iface_init (GtkFontChooserIface *iface);
161
162 G_DEFINE_TYPE_WITH_CODE (GtkFontChooserWidget, gtk_font_chooser_widget, GTK_TYPE_BOX,
163                          G_IMPLEMENT_INTERFACE (GTK_TYPE_FONT_CHOOSER,
164                                                 gtk_font_chooser_widget_iface_init))
165
166 static void
167 gtk_font_chooser_widget_class_init (GtkFontChooserWidgetClass *klass)
168 {
169   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
170   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
171
172   widget_class->screen_changed = gtk_font_chooser_widget_screen_changed;
173
174   gobject_class->finalize = gtk_font_chooser_widget_finalize;
175   gobject_class->set_property = gtk_font_chooser_widget_set_property;
176   gobject_class->get_property = gtk_font_chooser_widget_get_property;
177
178   _gtk_font_chooser_install_properties (gobject_class);
179
180   g_type_class_add_private (klass, sizeof (GtkFontChooserWidgetPrivate));
181 }
182
183 static void
184 gtk_font_chooser_widget_set_property (GObject         *object,
185                                       guint            prop_id,
186                                       const GValue    *value,
187                                       GParamSpec      *pspec)
188 {
189   GtkFontChooserWidget *fontchooser = GTK_FONT_CHOOSER_WIDGET (object);
190
191   switch (prop_id)
192     {
193     case GTK_FONT_CHOOSER_PROP_FONT:
194       gtk_font_chooser_widget_set_font (fontchooser, g_value_get_string (value));
195       break;
196     case GTK_FONT_CHOOSER_PROP_FONT_DESC:
197       gtk_font_chooser_widget_take_font_desc (fontchooser, g_value_dup_boxed (value));
198       break;
199     case GTK_FONT_CHOOSER_PROP_PREVIEW_TEXT:
200       gtk_font_chooser_widget_set_preview_text (fontchooser, g_value_get_string (value));
201       break;
202     case GTK_FONT_CHOOSER_PROP_SHOW_PREVIEW_ENTRY:
203       gtk_font_chooser_widget_set_show_preview_entry (fontchooser, g_value_get_boolean (value));
204       break;
205     default:
206       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
207       break;
208     }
209 }
210
211 static void
212 gtk_font_chooser_widget_get_property (GObject         *object,
213                                       guint            prop_id,
214                                       GValue          *value,
215                                       GParamSpec      *pspec)
216 {
217   GtkFontChooserWidget *fontchooser = GTK_FONT_CHOOSER_WIDGET (object);
218
219   switch (prop_id)
220     {
221     case GTK_FONT_CHOOSER_PROP_FONT:
222       g_value_take_string (value, gtk_font_chooser_widget_get_font (fontchooser));
223       break;
224     case GTK_FONT_CHOOSER_PROP_FONT_DESC:
225       g_value_set_boxed (value, gtk_font_chooser_widget_get_font_desc (fontchooser));
226       break;
227     case GTK_FONT_CHOOSER_PROP_PREVIEW_TEXT:
228       g_value_set_string (value, gtk_font_chooser_widget_get_preview_text (fontchooser));
229       break;
230     case GTK_FONT_CHOOSER_PROP_SHOW_PREVIEW_ENTRY:
231       g_value_set_boolean (value, gtk_font_chooser_widget_get_show_preview_entry (fontchooser));
232       break;
233     default:
234       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
235       break;
236     }
237 }
238
239 static void
240 gtk_font_chooser_widget_refilter_font_list (GtkFontChooserWidget *fontchooser)
241 {
242   gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (fontchooser->priv->filter_model));
243   gtk_font_chooser_widget_ensure_selection (fontchooser);
244 }
245
246 static void
247 text_changed_cb (GtkEntry       *entry,
248                  GParamSpec     *pspec,
249                  GtkFontChooserWidget *fc)
250 {
251   GtkFontChooserWidgetPrivate *priv = fc->priv;
252   const gchar *text;
253
254   text = gtk_entry_get_text (entry);
255
256   if (text == NULL || text[0] == '\0')
257     {
258       GIcon *icon;
259
260       icon = g_themed_icon_new_with_default_fallbacks ("edit-find-symbolic");
261       g_object_set (G_OBJECT (priv->search_entry),
262                     "secondary-icon-gicon", icon,
263                     "secondary-icon-activatable", FALSE,
264                     "secondary-icon-sensitive", FALSE,
265                     NULL);
266       g_object_unref (icon);
267     }
268   else
269     {
270       if (!gtk_entry_get_icon_activatable (GTK_ENTRY (priv->search_entry), GTK_ENTRY_ICON_SECONDARY))
271         {
272           GIcon *icon;
273
274           icon = g_themed_icon_new_with_default_fallbacks ("edit-clear-symbolic");
275           g_object_set (G_OBJECT (priv->search_entry),
276                         "secondary-icon-gicon", icon,
277                         "secondary-icon-activatable", TRUE,
278                         "secondary-icon-sensitive", TRUE,
279                         NULL);
280           g_object_unref (icon);
281         }
282     }
283
284   gtk_font_chooser_widget_refilter_font_list (fc);
285 }
286
287 static void
288 icon_press_cb (GtkEntry             *entry,
289                GtkEntryIconPosition  pos,
290                GdkEvent             *event,
291                gpointer              user_data)
292 {
293   gtk_entry_set_text (entry, "");
294 }
295
296 static void
297 size_change_cb (GtkAdjustment *adjustment,
298                 gpointer       user_data)
299 {
300   GtkFontChooserWidget *fontchooser = user_data;
301   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
302   PangoFontDescription *font_desc;
303   gdouble size = gtk_adjustment_get_value (adjustment);
304
305   font_desc = pango_font_description_new ();
306   if (pango_font_description_get_size_is_absolute (priv->font_desc))
307     pango_font_description_set_absolute_size (font_desc, size * PANGO_SCALE);
308   else
309     pango_font_description_set_size (font_desc, size * PANGO_SCALE);
310
311   gtk_font_chooser_widget_take_font_desc (fontchooser, font_desc);
312 }
313
314 static void
315 gtk_font_chooser_widget_update_marks (GtkFontChooserWidget *fontchooser)
316 {
317   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
318   GtkAdjustment *adj;
319   const int *sizes;
320   gint *font_sizes;
321   gint i, n_sizes;
322
323   if (gtk_list_store_iter_is_valid (GTK_LIST_STORE (priv->model), &priv->font_iter))
324     {
325       PangoFontFace *face;
326
327       gtk_tree_model_get (priv->model, &priv->font_iter,
328                           FACE_COLUMN, &face,
329                           -1);
330
331       pango_font_face_list_sizes (face, &font_sizes, &n_sizes);
332
333       /* It seems not many fonts actually have a sane set of sizes */
334       for (i = 0; i < n_sizes; i++)
335         font_sizes[i] = font_sizes[i] / PANGO_SCALE;
336
337       g_object_unref (face);
338     }
339   else
340     {
341       font_sizes = NULL;
342       n_sizes = 0;
343     }
344
345   if (n_sizes < 2)
346     {
347       static const gint fallback_sizes[] = {
348         6, 8, 9, 10, 11, 12, 13, 14, 16, 20, 24, 36, 48, 72
349       };
350
351       sizes = fallback_sizes;
352       n_sizes = G_N_ELEMENTS (fallback_sizes);
353     }
354   else
355     {
356       sizes = font_sizes;
357     }
358
359   gtk_scale_clear_marks (GTK_SCALE (priv->size_slider));
360
361   adj = gtk_range_get_adjustment(GTK_RANGE (priv->size_slider));
362
363   /* ensure clamping doesn't callback into font resizing code */
364   g_signal_handlers_block_by_func (adj, size_change_cb, fontchooser);
365   gtk_adjustment_configure (adj,
366                             gtk_adjustment_get_value (adj),
367                             sizes[0],
368                             sizes[n_sizes - 1],
369                             gtk_adjustment_get_step_increment (adj),
370                             gtk_adjustment_get_page_increment (adj),
371                             gtk_adjustment_get_page_size (adj));
372   g_signal_handlers_unblock_by_func (adj, size_change_cb, fontchooser);
373
374   for (i = 0; i < n_sizes; i++)
375     {
376       gtk_scale_add_mark (GTK_SCALE (priv->size_slider),
377                           sizes[i],
378                           GTK_POS_BOTTOM, NULL);
379     }
380
381   g_free (font_sizes);
382 }
383
384 static void
385 row_activated_cb (GtkTreeView       *view,
386                   GtkTreePath       *path,
387                   GtkTreeViewColumn *column,
388                   gpointer           user_data)
389 {
390   GtkFontChooserWidget *fontchooser = user_data;
391   gchar *fontname;
392
393   fontname = gtk_font_chooser_widget_get_font (fontchooser);
394   _gtk_font_chooser_font_activated (GTK_FONT_CHOOSER (fontchooser), fontname);
395   g_free (fontname);
396 }
397
398 static PangoFontDescription *
399 tree_model_get_font_description (GtkTreeModel *model,
400                                  GtkTreeIter  *iter)
401 {
402   PangoFontDescription *desc;
403   PangoFontFace *face;
404   GtkTreeIter child_iter;
405
406   gtk_tree_model_get (model, iter,
407                       FONT_DESC_COLUMN, &desc,
408                       -1);
409   if (desc != NULL)
410     return desc;
411
412   gtk_tree_model_get (model, iter,
413                       FACE_COLUMN, &face,
414                       -1);
415   desc = pango_font_face_describe (face);
416   g_object_unref (face);
417   
418   if (GTK_IS_TREE_MODEL_FILTER (model))
419     {
420       gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model),
421                                                         &child_iter,
422                                                         iter);
423       iter = &child_iter;
424       model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
425     }
426
427   gtk_list_store_set (GTK_LIST_STORE (model), iter,
428                       FONT_DESC_COLUMN, desc,
429                       -1);
430
431   return desc;
432 }
433
434 static void
435 cursor_changed_cb (GtkTreeView *treeview,
436                    gpointer     user_data)
437 {
438   GtkFontChooserWidget *fontchooser = user_data;
439   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
440   PangoFontDescription *desc;
441   GtkTreeIter filter_iter, iter;
442   GtkTreePath *path = NULL;
443
444   gtk_tree_view_get_cursor (treeview, &path, NULL);
445
446   if (!path)
447     return;
448
449   if (!gtk_tree_model_get_iter (priv->filter_model, &filter_iter, path))
450     {
451       gtk_tree_path_free (path);
452       return;
453     }
454
455   gtk_tree_path_free (path);
456
457   gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (priv->filter_model),
458                                                     &iter,
459                                                     &filter_iter);
460   desc = tree_model_get_font_description (priv->model, &iter);
461
462   gtk_font_chooser_widget_merge_font_desc (fontchooser, desc, &iter);
463 }
464
465 static gboolean
466 zoom_preview_cb (GtkWidget      *scrolled_window,
467                  GdkEventScroll *event,
468                  gpointer        user_data)
469 {
470   GtkFontChooserWidget *fc = user_data;
471   GtkFontChooserWidgetPrivate *priv = fc->priv;
472   GtkAdjustment *adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->size_spin));
473
474   if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_RIGHT)
475     gtk_adjustment_set_value (adj,
476                               gtk_adjustment_get_value (adj) +
477                               gtk_adjustment_get_step_increment (adj));
478   else if (event->direction == GDK_SCROLL_DOWN || event->direction == GDK_SCROLL_LEFT)
479     gtk_adjustment_set_value (adj,
480                               gtk_adjustment_get_value (adj) -
481                               gtk_adjustment_get_step_increment (adj));
482   return TRUE;
483 }
484
485 static void
486 row_inserted_cb (GtkTreeModel *model,
487                  GtkTreePath  *path,
488                  GtkTreeIter  *iter,
489                  gpointer      user_data)
490 {
491   GtkFontChooserWidget *fontchooser = user_data;
492   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
493
494   gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->list_notebook), 0);
495 }
496
497 static void
498 row_deleted_cb  (GtkTreeModel *model,
499                  GtkTreePath  *path,
500                  gpointer      user_data)
501 {
502   GtkFontChooserWidget *fontchooser = user_data;
503   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
504
505   if (gtk_tree_model_iter_n_children (model, NULL) == 0)
506     gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->list_notebook), 1);
507 }
508
509 static void
510 gtk_font_chooser_widget_init (GtkFontChooserWidget *fontchooser)
511 {
512   GIcon *icon;
513   GtkFontChooserWidgetPrivate *priv;
514   GtkWidget *scrolled_win;
515   GtkWidget *grid;
516
517   fontchooser->priv = G_TYPE_INSTANCE_GET_PRIVATE (fontchooser,
518                                                    GTK_TYPE_FONT_CHOOSER_WIDGET,
519                                                    GtkFontChooserWidgetPrivate);
520
521   priv = fontchooser->priv;
522
523   /* Default preview string  */
524   priv->preview_text = g_strdup (pango_language_get_sample_string (NULL));
525   priv->show_preview_entry = TRUE;
526   priv->font_desc = pango_font_description_new ();
527
528   gtk_widget_push_composite_child ();
529
530   /* Creating fundamental widgets for the private struct */
531   priv->search_entry = gtk_entry_new ();
532   priv->family_face_list = gtk_tree_view_new ();
533   gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv->family_face_list), FALSE);
534   priv->preview = gtk_entry_new ();
535   priv->size_slider = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL,
536                                                 0.0,
537                                                 (gdouble)(G_MAXINT / PANGO_SCALE),
538                                                 1.0);
539
540   priv->size_spin = gtk_spin_button_new_with_range (0.0, (gdouble)(G_MAXINT / PANGO_SCALE), 1.0);
541
542   /** Bootstrapping widget layout **/
543   gtk_box_set_spacing (GTK_BOX (fontchooser), 6);
544
545   /* Main font family/face view */
546   priv->list_scrolled_window = gtk_scrolled_window_new (NULL, NULL);
547   scrolled_win = priv->list_scrolled_window;
548   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
549                                   GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
550   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
551                                        GTK_SHADOW_ETCHED_IN);
552   gtk_widget_set_size_request (scrolled_win, 400, 300);
553   gtk_container_add (GTK_CONTAINER (scrolled_win), priv->family_face_list);
554
555   /* Text to display when list is empty */
556   priv->empty_list = gtk_label_new (_(NO_FONT_MATCHED_SEARCH));
557   gtk_widget_set_margin_top    (priv->empty_list, 12);
558   gtk_widget_set_margin_left   (priv->empty_list, 12);
559   gtk_widget_set_margin_right  (priv->empty_list, 12);
560   gtk_widget_set_margin_bottom (priv->empty_list, 12);
561   gtk_widget_set_halign (priv->empty_list, GTK_ALIGN_CENTER);
562   gtk_widget_set_valign (priv->empty_list, GTK_ALIGN_START);
563
564   priv->list_notebook = gtk_notebook_new ();
565   gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->list_notebook), FALSE);
566   gtk_notebook_append_page (GTK_NOTEBOOK (priv->list_notebook), scrolled_win, NULL);
567   gtk_notebook_append_page (GTK_NOTEBOOK (priv->list_notebook), priv->empty_list, NULL);
568
569   /* Basic layout */
570   grid = gtk_grid_new ();
571
572   gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
573   gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
574
575   gtk_grid_attach (GTK_GRID (grid), priv->search_entry, 0, 0, 2, 1);
576   gtk_grid_attach (GTK_GRID (grid), priv->list_notebook, 0, 1, 2, 1);
577   gtk_grid_attach (GTK_GRID (grid), priv->preview,      0, 2, 2, 1);
578
579   gtk_grid_attach (GTK_GRID (grid), priv->size_slider,  0, 3, 1, 1);
580   gtk_grid_attach (GTK_GRID (grid), priv->size_spin,    1, 3, 1, 1);
581
582   gtk_widget_set_hexpand  (GTK_WIDGET (scrolled_win),      TRUE);
583   gtk_widget_set_vexpand  (GTK_WIDGET (scrolled_win),      TRUE);
584   gtk_widget_set_hexpand  (GTK_WIDGET (priv->search_entry), TRUE);
585
586   gtk_widget_set_hexpand  (GTK_WIDGET (priv->size_slider), TRUE);
587   gtk_widget_set_hexpand  (GTK_WIDGET (priv->size_spin),   FALSE);
588
589   gtk_box_pack_start (GTK_BOX (fontchooser), grid, TRUE, TRUE, 0);
590
591   gtk_widget_show_all (GTK_WIDGET (fontchooser));
592   gtk_widget_hide     (GTK_WIDGET (fontchooser));
593
594   /* Treeview column and model bootstrapping */
595   gtk_font_chooser_widget_bootstrap_fontlist (fontchooser);
596
597   /* Set default preview text */
598   gtk_entry_set_text (GTK_ENTRY (priv->preview),
599                       pango_language_get_sample_string (NULL));
600
601   /* Set search icon and place holder text */
602   icon = g_themed_icon_new_with_default_fallbacks ("edit-find-symbolic");
603   g_object_set (G_OBJECT (priv->search_entry),
604                 "secondary-icon-gicon", icon,
605                 "secondary-icon-activatable", FALSE,
606                 "secondary-icon-sensitive", FALSE,
607                 NULL);
608   g_object_unref (icon);
609
610   gtk_entry_set_placeholder_text (GTK_ENTRY (priv->search_entry), _("Search font name"));
611
612   /** Callback connections **/
613   g_signal_connect (priv->search_entry, "notify::text",
614                     G_CALLBACK (text_changed_cb), fontchooser);
615   g_signal_connect (priv->search_entry,
616                     "icon-press", G_CALLBACK (icon_press_cb), NULL);
617
618   g_signal_connect (gtk_range_get_adjustment (GTK_RANGE (priv->size_slider)),
619                     "value-changed", G_CALLBACK (size_change_cb), fontchooser);
620   g_signal_connect (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->size_spin)),
621                     "value-changed", G_CALLBACK (size_change_cb), fontchooser);
622
623   g_signal_connect (priv->family_face_list, "cursor-changed",
624                     G_CALLBACK (cursor_changed_cb), fontchooser);
625   g_signal_connect (priv->family_face_list, "row-activated",
626                     G_CALLBACK (row_activated_cb), fontchooser);
627
628   /* Zoom on preview scroll */
629   g_signal_connect (priv->preview, "scroll-event",
630                     G_CALLBACK (zoom_preview_cb), fontchooser);
631
632   g_signal_connect (priv->size_slider, "scroll-event",
633                     G_CALLBACK (zoom_preview_cb), fontchooser);
634
635   /* Font list empty hides the scrolledwindow */
636   g_signal_connect (G_OBJECT (priv->filter_model), "row-deleted",
637                     G_CALLBACK (row_deleted_cb), fontchooser);
638   g_signal_connect (G_OBJECT (priv->filter_model), "row-inserted",
639                     G_CALLBACK (row_inserted_cb), fontchooser);
640
641   /* Set default focus */
642   gtk_widget_pop_composite_child ();
643
644   gtk_font_chooser_widget_take_font_desc (fontchooser, NULL);
645 }
646
647 /**
648  * gtk_font_chooser_widget_new:
649  *
650  * Creates a new #GtkFontChooserWidget.
651  *
652  * Return value: a new #GtkFontChooserWidget
653  *
654  * Since: 3.2
655  */
656 GtkWidget *
657 gtk_font_chooser_widget_new (void)
658 {
659   return g_object_new (GTK_TYPE_FONT_CHOOSER_WIDGET, NULL);
660 }
661
662 static int
663 cmp_families (const void *a,
664               const void *b)
665 {
666   const char *a_name = pango_font_family_get_name (*(PangoFontFamily **)a);
667   const char *b_name = pango_font_family_get_name (*(PangoFontFamily **)b);
668
669   return g_utf8_collate (a_name, b_name);
670 }
671
672 static void
673 gtk_font_chooser_widget_load_fonts (GtkFontChooserWidget *fontchooser)
674 {
675   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
676   GtkListStore *list_store;
677   gint n_families, i;
678   PangoFontFamily **families;
679   gchar *family_and_face;
680
681   list_store = GTK_LIST_STORE (priv->model);
682
683   pango_context_list_families (gtk_widget_get_pango_context (GTK_WIDGET (fontchooser)),
684                                &families,
685                                &n_families);
686
687   qsort (families, n_families, sizeof (PangoFontFamily *), cmp_families);
688
689   gtk_list_store_clear (list_store);
690
691   /* Iterate over families and faces */
692   for (i = 0; i < n_families; i++)
693     {
694       GtkTreeIter     iter;
695       PangoFontFace **faces;
696       int             j, n_faces;
697       const gchar    *fam_name = pango_font_family_get_name (families[i]);
698
699       pango_font_family_list_faces (families[i], &faces, &n_faces);
700
701       for (j = 0; j < n_faces; j++)
702         {
703           const gchar *face_name;
704
705           face_name = pango_font_face_get_face_name (faces[j]);
706
707           family_and_face = g_strconcat (fam_name, " ", face_name, NULL);
708
709           gtk_list_store_insert_with_values (list_store, &iter, -1,
710                                              FAMILY_COLUMN, families[i],
711                                              FACE_COLUMN, faces[j],
712                                              PREVIEW_TITLE_COLUMN, family_and_face,
713                                              -1);
714
715           g_free (family_and_face);
716         }
717
718       g_free (faces);
719     }
720
721   g_free (families);
722
723   /* now make sure the font list looks right */
724   if (!gtk_font_chooser_widget_find_font (fontchooser,
725                                           priv->font_desc,
726                                           &priv->font_iter))
727     memset (&priv->font_iter, 0, sizeof (GtkTreeIter));
728
729   gtk_font_chooser_widget_ensure_selection (fontchooser);
730 }
731
732 static gboolean
733 visible_func (GtkTreeModel *model,
734               GtkTreeIter  *iter,
735               gpointer      user_data)
736 {
737   GtkFontChooserWidgetPrivate *priv = user_data;
738   gboolean result = TRUE;
739   const gchar *search_text;
740   gchar **split_terms;
741   gchar *font_name, *font_name_casefold;
742   guint i;
743
744   if (priv->filter_func != NULL)
745     {
746       PangoFontFamily *family;
747       PangoFontFace *face;
748
749       gtk_tree_model_get (model, iter,
750                           FAMILY_COLUMN, &family,
751                           FACE_COLUMN, &face,
752                           -1);
753
754       result = priv->filter_func (family, face, priv->filter_data);
755
756       g_object_unref (family);
757       g_object_unref (face);
758       
759       if (!result)
760         return FALSE;
761     }
762
763   /* If there's no filter string we show the item */
764   search_text = gtk_entry_get_text (GTK_ENTRY (priv->search_entry));
765   if (strlen (search_text) == 0)
766     return TRUE;
767
768   gtk_tree_model_get (model, iter,
769                       PREVIEW_TITLE_COLUMN, &font_name,
770                       -1);
771
772   if (font_name == NULL)
773     return FALSE;
774
775   split_terms = g_strsplit (search_text, " ", 0);
776   font_name_casefold = g_utf8_casefold (font_name, -1);
777
778   for (i = 0; split_terms[i] && result; i++)
779     {
780       gchar* term_casefold = g_utf8_casefold (split_terms[i], -1);
781
782       if (!strstr (font_name_casefold, term_casefold))
783         result = FALSE;
784
785       g_free (term_casefold);
786     }
787
788   g_free (font_name_casefold);
789   g_free (font_name);
790   g_strfreev (split_terms);
791
792   return result;
793 }
794
795 /* in pango units */
796 static int
797 gtk_font_chooser_widget_get_preview_text_height (GtkFontChooserWidget *fontchooser)
798 {
799   GtkWidget *treeview = fontchooser->priv->family_face_list;
800   double dpi, font_size;
801
802   dpi = gdk_screen_get_resolution (gtk_widget_get_screen (treeview));
803   gtk_style_context_get (gtk_widget_get_style_context (treeview),
804                          gtk_widget_get_state_flags (treeview),
805                          "font-size", &font_size,
806                          NULL);
807
808   return (dpi < 0.0 ? 96.0 : dpi) / 72.0 * PANGO_SCALE_X_LARGE * font_size * PANGO_SCALE;
809 }
810
811 static PangoAttrList *
812 gtk_font_chooser_widget_get_preview_attributes (GtkFontChooserWidget       *fontchooser,
813                                                 const PangoFontDescription *font_desc,
814                                                 gsize                       first_line_len)
815 {
816   PangoAttribute *attribute;
817   PangoAttrList *attrs;
818
819   attrs = pango_attr_list_new ();
820
821   attribute = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
822   attribute->end_index = first_line_len;
823   pango_attr_list_insert (attrs, attribute);
824
825   attribute = pango_attr_scale_new (PANGO_SCALE_SMALL);
826   attribute->end_index = first_line_len;
827   pango_attr_list_insert (attrs, attribute);
828
829   if (font_desc)
830     {
831       attribute = pango_attr_font_desc_new (font_desc);
832       attribute->start_index = first_line_len;
833       pango_attr_list_insert (attrs, attribute);
834     }
835
836   attribute = pango_attr_fallback_new (FALSE);
837   attribute->start_index = first_line_len;
838   pango_attr_list_insert (attrs, attribute);
839
840   attribute = pango_attr_size_new_absolute (gtk_font_chooser_widget_get_preview_text_height (fontchooser));
841   attribute->start_index = first_line_len;
842   pango_attr_list_insert (attrs, attribute);
843
844   return attrs;
845 }
846
847 static void
848 gtk_font_chooser_widget_cell_data_func (GtkTreeViewColumn *column,
849                                         GtkCellRenderer   *cell,
850                                         GtkTreeModel      *tree_model,
851                                         GtkTreeIter       *iter,
852                                         gpointer           user_data)
853 {
854   GtkFontChooserWidget *fontchooser = user_data;
855   PangoFontDescription *font_desc;
856   PangoAttrList *attrs;
857   char *to_string, *text;
858   gsize first_line_len;
859
860   font_desc = tree_model_get_font_description (tree_model, iter);
861
862   to_string = pango_font_description_to_string (font_desc);
863
864   text = g_strconcat (to_string, "\n", fontchooser->priv->preview_text, NULL);
865   first_line_len = strlen (to_string) + 1;
866   
867   attrs = gtk_font_chooser_widget_get_preview_attributes (fontchooser, 
868                                                           font_desc,
869                                                           first_line_len);
870
871   g_object_set (cell,
872                 "attributes", attrs,
873                 "text", text,
874                 NULL);
875
876   pango_font_description_free (font_desc);
877   pango_attr_list_unref (attrs);
878   g_free (to_string);
879   g_free (text);
880 }
881
882 static void
883 gtk_font_chooser_widget_set_cell_size (GtkFontChooserWidget *fontchooser)
884 {
885   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
886   PangoAttrList *attrs;
887   GtkRequisition size;
888
889   gtk_cell_renderer_set_fixed_size (priv->family_face_cell, -1, -1);
890
891   attrs = gtk_font_chooser_widget_get_preview_attributes (fontchooser, 
892                                                           NULL,
893                                                           1);
894   
895   g_object_set (priv->family_face_cell,
896                 "attributes", attrs,
897                 "text", "x\nx",
898                 NULL);
899
900   pango_attr_list_unref (attrs);
901
902   gtk_cell_renderer_get_preferred_size (priv->family_face_cell,
903                                         priv->family_face_list,
904                                         &size,
905                                         NULL);
906   gtk_cell_renderer_set_fixed_size (priv->family_face_cell, size.width, size.height);
907 }
908
909 static void
910 gtk_font_chooser_widget_bootstrap_fontlist (GtkFontChooserWidget *fontchooser)
911 {
912   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
913   GtkTreeView *treeview = GTK_TREE_VIEW (priv->family_face_list);
914   GtkTreeViewColumn *col;
915
916   g_signal_connect_data (priv->family_face_list,
917                          "style-updated",
918                          G_CALLBACK (gtk_font_chooser_widget_set_cell_size),
919                          fontchooser,
920                          NULL,
921                          G_CONNECT_AFTER | G_CONNECT_SWAPPED);
922
923   priv->model = GTK_TREE_MODEL (gtk_list_store_new (4,
924                                                     PANGO_TYPE_FONT_FAMILY,
925                                                     PANGO_TYPE_FONT_FACE,
926                                                     PANGO_TYPE_FONT_DESCRIPTION,
927                                                     G_TYPE_STRING));
928
929   priv->filter_model = gtk_tree_model_filter_new (priv->model, NULL);
930   g_object_unref (priv->model);
931
932   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (priv->filter_model),
933                                           visible_func, (gpointer)priv, NULL);
934
935   gtk_tree_view_set_model (treeview, priv->filter_model);
936   g_object_unref (priv->filter_model);
937
938   gtk_tree_view_set_rules_hint      (treeview, TRUE);
939   gtk_tree_view_set_headers_visible (treeview, FALSE);
940   gtk_tree_view_set_fixed_height_mode (treeview, TRUE);
941
942   priv->family_face_cell = gtk_cell_renderer_text_new ();
943   g_object_set (priv->family_face_cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
944
945   col = gtk_tree_view_column_new ();
946   gtk_tree_view_column_set_title (col, _("Font Family"));
947   gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED);
948   gtk_tree_view_column_pack_start (col, priv->family_face_cell, TRUE);
949   gtk_tree_view_column_set_cell_data_func (col,
950                                            priv->family_face_cell,
951                                            gtk_font_chooser_widget_cell_data_func,
952                                            fontchooser,
953                                            NULL);
954
955   gtk_tree_view_append_column (treeview, col);
956
957   gtk_font_chooser_widget_load_fonts (fontchooser);
958
959   gtk_font_chooser_widget_set_cell_size (fontchooser);
960 }
961
962 static void
963 gtk_font_chooser_widget_finalize (GObject *object)
964 {
965   GtkFontChooserWidget *fontchooser = GTK_FONT_CHOOSER_WIDGET (object);
966   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
967
968   if (priv->font_desc)
969     pango_font_description_free (priv->font_desc);
970
971   if (priv->filter_data_destroy)
972     priv->filter_data_destroy (priv->filter_data);
973
974   G_OBJECT_CLASS (gtk_font_chooser_widget_parent_class)->finalize (object);
975 }
976
977 static gboolean
978 my_pango_font_family_equal (const char *familya,
979                             const char *familyb)
980 {
981   return g_ascii_strcasecmp (familya, familyb) == 0;
982 }
983
984 static gboolean
985 gtk_font_chooser_widget_find_font (GtkFontChooserWidget        *fontchooser,
986                                    const PangoFontDescription  *font_desc,
987                                    /* out arguments */
988                                    GtkTreeIter                 *iter)
989 {
990   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
991   PangoFontDescription *desc;
992   PangoFontFamily *family;
993   gboolean valid;
994
995   if (pango_font_description_get_family (font_desc) == NULL)
996     return FALSE;
997
998   for (valid = gtk_tree_model_get_iter_first (priv->model, iter);
999        valid;
1000        valid = gtk_tree_model_iter_next (priv->model, iter))
1001     {
1002       gtk_tree_model_get (priv->model, iter,
1003                           FAMILY_COLUMN, &family,
1004                           -1);
1005
1006       if (!my_pango_font_family_equal (pango_font_description_get_family (font_desc),
1007                                        pango_font_family_get_name (family)))
1008         continue;
1009
1010       desc = tree_model_get_font_description (priv->model, iter);
1011
1012       pango_font_description_merge_static (desc, font_desc, FALSE);
1013       if (pango_font_description_equal (desc, font_desc))
1014         break;
1015
1016       pango_font_description_free (desc);
1017     }
1018   
1019   return valid;
1020 }
1021
1022 static void
1023 gtk_font_chooser_widget_screen_changed (GtkWidget *widget,
1024                                         GdkScreen *previous_screen)
1025 {
1026   GtkFontChooserWidget *fontchooser = GTK_FONT_CHOOSER_WIDGET (widget);
1027
1028   if (GTK_WIDGET_CLASS (gtk_font_chooser_widget_parent_class)->screen_changed)
1029     GTK_WIDGET_CLASS (gtk_font_chooser_widget_parent_class)->screen_changed (widget, previous_screen);
1030
1031   if (previous_screen == NULL)
1032     previous_screen = gdk_screen_get_default ();
1033
1034   if (previous_screen == gtk_widget_get_screen (widget))
1035     return;
1036
1037   gtk_font_chooser_widget_load_fonts (fontchooser);
1038 }
1039
1040 static PangoFontFamily *
1041 gtk_font_chooser_widget_get_family (GtkFontChooser *chooser)
1042 {
1043   GtkFontChooserWidget *fontchooser = GTK_FONT_CHOOSER_WIDGET (chooser);
1044   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
1045   PangoFontFamily *family;
1046
1047   if (!gtk_list_store_iter_is_valid (GTK_LIST_STORE (priv->model), &priv->font_iter))
1048     return NULL;
1049
1050   gtk_tree_model_get (priv->model, &priv->font_iter,
1051                       FAMILY_COLUMN, &family,
1052                       -1);
1053   g_object_unref (family);
1054
1055   return family;
1056 }
1057
1058 static PangoFontFace *
1059 gtk_font_chooser_widget_get_face (GtkFontChooser *chooser)
1060 {
1061   GtkFontChooserWidget *fontchooser = GTK_FONT_CHOOSER_WIDGET (chooser);
1062   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
1063   PangoFontFace *face;
1064
1065   if (!gtk_list_store_iter_is_valid (GTK_LIST_STORE (priv->model), &priv->font_iter))
1066     return NULL;
1067
1068   gtk_tree_model_get (priv->model, &priv->font_iter,
1069                       FACE_COLUMN, &face,
1070                       -1);
1071   g_object_unref (face);
1072
1073   return face;
1074 }
1075
1076 static gint
1077 gtk_font_chooser_widget_get_size (GtkFontChooser *chooser)
1078 {
1079   GtkFontChooserWidget *fontchooser = GTK_FONT_CHOOSER_WIDGET (chooser);
1080
1081   return pango_font_description_get_size (fontchooser->priv->font_desc);
1082 }
1083
1084 static gchar *
1085 gtk_font_chooser_widget_get_font (GtkFontChooserWidget *fontchooser)
1086 {
1087   return pango_font_description_to_string (fontchooser->priv->font_desc);
1088 }
1089
1090 static PangoFontDescription *
1091 gtk_font_chooser_widget_get_font_desc (GtkFontChooserWidget *fontchooser)
1092 {
1093   return fontchooser->priv->font_desc;
1094 }
1095
1096 static void
1097 gtk_font_chooser_widget_set_font (GtkFontChooserWidget *fontchooser,
1098                                   const gchar          *fontname)
1099 {
1100   PangoFontDescription *font_desc;
1101
1102   font_desc = pango_font_description_from_string (fontname);
1103   gtk_font_chooser_widget_take_font_desc (fontchooser, font_desc);
1104 }
1105
1106 static void
1107 gtk_font_chooser_widget_ensure_selection (GtkFontChooserWidget *fontchooser)
1108 {
1109   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
1110   GtkTreeSelection *selection;
1111   GtkTreeIter filter_iter;
1112   
1113   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->family_face_list));
1114
1115   if (gtk_list_store_iter_is_valid (GTK_LIST_STORE (priv->model), &priv->font_iter) &&
1116       gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (priv->filter_model),
1117                                                         &filter_iter,
1118                                                         &priv->font_iter))
1119     {
1120       gtk_tree_selection_select_iter (selection, &filter_iter);
1121     }
1122   else
1123     {
1124       gtk_tree_selection_unselect_all (selection);
1125     }
1126 }
1127
1128 static void
1129 gtk_font_chooser_widget_merge_font_desc (GtkFontChooserWidget *fontchooser,
1130                                          PangoFontDescription *font_desc,
1131                                          GtkTreeIter          *iter)
1132 {
1133   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
1134   PangoFontMask mask;
1135
1136   g_assert (font_desc != NULL);
1137   /* iter may be NULL if the font doesn't exist on the list */
1138
1139   mask = pango_font_description_get_set_fields (font_desc);
1140
1141   /* sucky test, because we can't restrict the comparison to 
1142    * only the parts that actually do get merged */
1143   if (pango_font_description_equal (font_desc, priv->font_desc))
1144     {
1145       pango_font_description_free (font_desc);
1146       return;
1147     }
1148
1149   pango_font_description_merge (priv->font_desc, font_desc, TRUE);
1150   
1151   if (mask & PANGO_FONT_MASK_SIZE)
1152     {
1153       double font_size = (double) pango_font_description_get_size (priv->font_desc) / PANGO_SCALE;
1154       /* XXX: This clamps, which can cause it to reloop into here, do we need
1155        * to block its signal handler? */
1156       gtk_range_set_value (GTK_RANGE (priv->size_slider), font_size);
1157       gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->size_spin), font_size);
1158     }
1159   if (mask & (PANGO_FONT_MASK_FAMILY | PANGO_FONT_MASK_STYLE | PANGO_FONT_MASK_VARIANT |
1160               PANGO_FONT_MASK_WEIGHT | PANGO_FONT_MASK_STRETCH))
1161     {
1162       if (&priv->font_iter != iter)
1163         {
1164           if (iter == NULL)
1165             memset (&priv->font_iter, 0, sizeof (GtkTreeIter));
1166           else
1167             memcpy (&priv->font_iter, iter, sizeof (GtkTreeIter));
1168           
1169           gtk_font_chooser_widget_ensure_selection (fontchooser);
1170         }
1171
1172       gtk_font_chooser_widget_update_marks (fontchooser);
1173     }
1174
1175   gtk_widget_override_font (priv->preview, priv->font_desc);
1176
1177   pango_font_description_free (font_desc); /* adopted */
1178
1179   g_object_notify (G_OBJECT (fontchooser), "font");
1180   g_object_notify (G_OBJECT (fontchooser), "font-desc");
1181 }
1182
1183 static void
1184 gtk_font_chooser_widget_take_font_desc (GtkFontChooserWidget *fontchooser,
1185                                         PangoFontDescription *font_desc)
1186 {
1187   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
1188   PangoFontMask mask;
1189
1190   if (font_desc == NULL)
1191     font_desc = pango_font_description_from_string (GTK_FONT_CHOOSER_DEFAULT_FONT_NAME);
1192
1193   mask = pango_font_description_get_set_fields (font_desc);
1194   if (mask & (PANGO_FONT_MASK_FAMILY | PANGO_FONT_MASK_STYLE | PANGO_FONT_MASK_VARIANT |
1195               PANGO_FONT_MASK_WEIGHT | PANGO_FONT_MASK_STRETCH))
1196     {
1197       GtkTreeIter iter;
1198
1199       if (gtk_font_chooser_widget_find_font (fontchooser,
1200                                              font_desc,
1201                                              &iter))
1202         {
1203           gtk_font_chooser_widget_merge_font_desc (fontchooser,
1204                                                    font_desc,
1205                                                    &iter);
1206         }
1207       else
1208         {
1209           gtk_font_chooser_widget_merge_font_desc (fontchooser,
1210                                                    font_desc,
1211                                                    NULL);
1212         }
1213     }
1214   else
1215     {
1216       gtk_font_chooser_widget_merge_font_desc (fontchooser,
1217                                                font_desc,
1218                                                &priv->font_iter);
1219                                                           
1220     }
1221 }
1222
1223 static const gchar*
1224 gtk_font_chooser_widget_get_preview_text (GtkFontChooserWidget *fontchooser)
1225 {
1226   return fontchooser->priv->preview_text;
1227 }
1228
1229 static void
1230 gtk_font_chooser_widget_set_preview_text (GtkFontChooserWidget *fontchooser,
1231                                           const gchar          *text)
1232 {
1233   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
1234
1235   g_free (priv->preview_text);
1236   priv->preview_text = g_strdup (text);
1237
1238   gtk_entry_set_text (GTK_ENTRY (priv->preview), text);
1239
1240   g_object_notify (G_OBJECT (fontchooser), "preview-text");
1241
1242   /* XXX: There's no API to tell the treeview that a column has changed,
1243    * so we just */
1244   gtk_widget_queue_draw (priv->family_face_list);
1245 }
1246
1247 static gboolean
1248 gtk_font_chooser_widget_get_show_preview_entry (GtkFontChooserWidget *fontchooser)
1249 {
1250   return fontchooser->priv->show_preview_entry;
1251 }
1252
1253 static void
1254 gtk_font_chooser_widget_set_show_preview_entry (GtkFontChooserWidget *fontchooser,
1255                                                 gboolean              show_preview_entry)
1256 {
1257   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
1258
1259   if (priv->show_preview_entry != show_preview_entry)
1260     {
1261       fontchooser->priv->show_preview_entry = show_preview_entry;
1262
1263       if (show_preview_entry)
1264         gtk_widget_show (fontchooser->priv->preview);
1265       else
1266         gtk_widget_hide (fontchooser->priv->preview);
1267
1268       g_object_notify (G_OBJECT (fontchooser), "show-preview-entry");
1269     }
1270 }
1271
1272 static void
1273 gtk_font_chooser_widget_set_filter_func (GtkFontChooser  *chooser,
1274                                          GtkFontFilterFunc filter,
1275                                          gpointer          data,
1276                                          GDestroyNotify    destroy)
1277 {
1278   GtkFontChooserWidget *fontchooser = GTK_FONT_CHOOSER_WIDGET (chooser);
1279   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
1280
1281   if (priv->filter_data_destroy)
1282     priv->filter_data_destroy (priv->filter_data);
1283
1284   priv->filter_func = filter;
1285   priv->filter_data = data;
1286   priv->filter_data_destroy = destroy;
1287
1288   gtk_font_chooser_widget_refilter_font_list (fontchooser);
1289 }
1290
1291 static void
1292 gtk_font_chooser_widget_iface_init (GtkFontChooserIface *iface)
1293 {
1294   iface->get_font_family = gtk_font_chooser_widget_get_family;
1295   iface->get_font_face = gtk_font_chooser_widget_get_face;
1296   iface->get_font_size = gtk_font_chooser_widget_get_size;
1297   iface->set_filter_func = gtk_font_chooser_widget_set_filter_func;
1298 }