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