1 /*
2  * GTK - The GIMP Toolkit
3  * Copyright (C) 1998 David Abilleira Freijeiro <odaf@nexo.es>
4  * All rights reserved.
5  *
6  * Based on gnome-color-picker by Federico Mena <federico@nuclecu.unam.mx>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20  */
21 /*
22  * Modified by the GTK+ Team and others 2003.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
26  */
27 
28 #include "config.h"
29 
30 #include "gtkfontbutton.h"
31 
32 #include "gtkmain.h"
33 #include "gtkbox.h"
34 #include "gtklabel.h"
35 #include "gtkfontchooser.h"
36 #include "gtkfontchooserdialog.h"
37 #include "gtkimage.h"
38 #include "gtkmarshalers.h"
39 #include "gtkseparator.h"
40 #include "gtkprivate.h"
41 #include "gtkintl.h"
42 #include "gtkcssprovider.h"
43 
44 #include <string.h>
45 #include <stdio.h>
46 #include "gtkfontchooserutils.h"
47 
48 
49 /**
50  * SECTION:gtkfontbutton
51  * @Short_description: A button to launch a font chooser dialog
52  * @Title: GtkFontButton
53  * @See_also: #GtkFontChooserDialog, #GtkColorButton.
54  *
55  * The #GtkFontButton is a button which displays the currently selected
56  * font an allows to open a font chooser dialog to change the font.
57  * It is suitable widget for selecting a font in a preference dialog.
58  *
59  * # CSS nodes
60  *
61  * GtkFontButton has a single CSS node with name button and style class .font.
62  */
63 
64 
65 struct _GtkFontButtonPrivate
66 {
67   gchar         *title;
68 
69   gchar         *fontname;
70 
71   guint         use_font : 1;
72   guint         use_size : 1;
73   guint         show_style : 1;
74   guint         show_size : 1;
75   guint         show_preview_entry : 1;
76 
77   GtkWidget     *font_dialog;
78   GtkWidget     *font_label;
79   GtkWidget     *size_label;
80   GtkWidget     *font_size_box;
81 
82   PangoFontDescription *font_desc;
83   PangoFontFamily      *font_family;
84   PangoFontFace        *font_face;
85   PangoFontMap         *font_map;
86   gint                  font_size;
87   char                 *font_features;
88   PangoLanguage        *language;
89   gchar                *preview_text;
90   GtkFontFilterFunc     font_filter;
91   gpointer              font_filter_data;
92   GDestroyNotify        font_filter_data_destroy;
93   GtkCssProvider       *provider;
94 
95   GtkFontChooserLevel   level;
96 };
97 
98 /* Signals */
99 enum
100 {
101   FONT_SET,
102   LAST_SIGNAL
103 };
104 
105 enum
106 {
107   PROP_0,
108   PROP_TITLE,
109   PROP_FONT_NAME,
110   PROP_USE_FONT,
111   PROP_USE_SIZE,
112   PROP_SHOW_STYLE,
113   PROP_SHOW_SIZE
114 };
115 
116 /* Prototypes */
117 static void gtk_font_button_finalize               (GObject            *object);
118 static void gtk_font_button_get_property           (GObject            *object,
119                                                     guint               param_id,
120                                                     GValue             *value,
121                                                     GParamSpec         *pspec);
122 static void gtk_font_button_set_property           (GObject            *object,
123                                                     guint               param_id,
124                                                     const GValue       *value,
125                                                     GParamSpec         *pspec);
126 
127 static void gtk_font_button_clicked                 (GtkButton         *button);
128 
129 /* Dialog response functions */
130 static void response_cb                             (GtkDialog         *dialog,
131                                                      gint               response_id,
132                                                      gpointer           data);
133 static void dialog_destroy                          (GtkWidget         *widget,
134                                                      gpointer           data);
135 
136 /* Auxiliary functions */
137 static void gtk_font_button_label_use_font          (GtkFontButton     *gfs);
138 static void gtk_font_button_update_font_info        (GtkFontButton     *gfs);
139 
140 static void        font_button_set_font_name (GtkFontButton *button,
141                                               const char    *fontname);
142 static void        gtk_font_button_set_level     (GtkFontButton       *font_button,
143                                                   GtkFontChooserLevel  level);
144 static void        gtk_font_button_set_language  (GtkFontButton *button,
145                                                   const char    *language);
146 
147 static guint font_button_signals[LAST_SIGNAL] = { 0 };
148 
149 static void
clear_font_data(GtkFontButton * font_button)150 clear_font_data (GtkFontButton *font_button)
151 {
152   GtkFontButtonPrivate *priv = font_button->priv;
153 
154   if (priv->font_family)
155     g_object_unref (priv->font_family);
156   priv->font_family = NULL;
157 
158   if (priv->font_face)
159     g_object_unref (priv->font_face);
160   priv->font_face = NULL;
161 
162   if (priv->font_desc)
163     pango_font_description_free (priv->font_desc);
164   priv->font_desc = NULL;
165 
166   g_free (priv->fontname);
167   priv->fontname = NULL;
168 
169   g_free (priv->font_features);
170   priv->font_features = NULL;
171 }
172 
173 static void
clear_font_filter_data(GtkFontButton * font_button)174 clear_font_filter_data (GtkFontButton *font_button)
175 {
176   GtkFontButtonPrivate *priv = font_button->priv;
177 
178   if (priv->font_filter_data_destroy)
179     priv->font_filter_data_destroy (priv->font_filter_data);
180   priv->font_filter = NULL;
181   priv->font_filter_data = NULL;
182   priv->font_filter_data_destroy = NULL;
183 }
184 
185 static gboolean
font_description_style_equal(const PangoFontDescription * a,const PangoFontDescription * b)186 font_description_style_equal (const PangoFontDescription *a,
187                               const PangoFontDescription *b)
188 {
189   return (pango_font_description_get_weight (a) == pango_font_description_get_weight (b) &&
190           pango_font_description_get_style (a) == pango_font_description_get_style (b) &&
191           pango_font_description_get_stretch (a) == pango_font_description_get_stretch (b) &&
192           pango_font_description_get_variant (a) == pango_font_description_get_variant (b));
193 }
194 
195 static void
gtk_font_button_update_font_data(GtkFontButton * font_button)196 gtk_font_button_update_font_data (GtkFontButton *font_button)
197 {
198   GtkFontButtonPrivate *priv = font_button->priv;
199   PangoFontFamily **families;
200   PangoFontFace **faces;
201   gint n_families, n_faces, i;
202   const gchar *family;
203 
204   g_assert (priv->font_desc != NULL);
205 
206   priv->fontname = pango_font_description_to_string (priv->font_desc);
207 
208   family = pango_font_description_get_family (priv->font_desc);
209   if (family == NULL)
210     return;
211 
212   n_families = 0;
213   families = NULL;
214   pango_context_list_families (gtk_widget_get_pango_context (GTK_WIDGET (font_button)),
215                                &families, &n_families);
216   n_faces = 0;
217   faces = NULL;
218   for (i = 0; i < n_families; i++)
219     {
220       const gchar *name = pango_font_family_get_name (families[i]);
221 
222       if (!g_ascii_strcasecmp (name, family))
223         {
224           priv->font_family = g_object_ref (families[i]);
225 
226           pango_font_family_list_faces (families[i], &faces, &n_faces);
227           break;
228         }
229     }
230   g_free (families);
231 
232   for (i = 0; i < n_faces; i++)
233     {
234       PangoFontDescription *tmp_desc = pango_font_face_describe (faces[i]);
235 
236       if (font_description_style_equal (tmp_desc, priv->font_desc))
237         {
238           priv->font_face = g_object_ref (faces[i]);
239 
240           pango_font_description_free (tmp_desc);
241           break;
242         }
243       else
244         pango_font_description_free (tmp_desc);
245     }
246 
247   g_free (faces);
248 }
249 
250 static gchar *
gtk_font_button_get_preview_text(GtkFontButton * font_button)251 gtk_font_button_get_preview_text (GtkFontButton *font_button)
252 {
253   GtkFontButtonPrivate *priv = font_button->priv;
254 
255   if (priv->font_dialog)
256     return gtk_font_chooser_get_preview_text (GTK_FONT_CHOOSER (priv->font_dialog));
257 
258   return g_strdup (priv->preview_text);
259 }
260 
261 static void
gtk_font_button_set_preview_text(GtkFontButton * font_button,const gchar * preview_text)262 gtk_font_button_set_preview_text (GtkFontButton *font_button,
263                                   const gchar   *preview_text)
264 {
265   GtkFontButtonPrivate *priv = font_button->priv;
266 
267   if (priv->font_dialog)
268     {
269       gtk_font_chooser_set_preview_text (GTK_FONT_CHOOSER (priv->font_dialog),
270                                          preview_text);
271       return;
272     }
273 
274   g_free (priv->preview_text);
275   priv->preview_text = g_strdup (preview_text);
276 }
277 
278 
279 static gboolean
gtk_font_button_get_show_preview_entry(GtkFontButton * font_button)280 gtk_font_button_get_show_preview_entry (GtkFontButton *font_button)
281 {
282   GtkFontButtonPrivate *priv = font_button->priv;
283 
284   if (priv->font_dialog)
285     return gtk_font_chooser_get_show_preview_entry (GTK_FONT_CHOOSER (priv->font_dialog));
286 
287   return priv->show_preview_entry;
288 }
289 
290 static void
gtk_font_button_set_show_preview_entry(GtkFontButton * font_button,gboolean show)291 gtk_font_button_set_show_preview_entry (GtkFontButton *font_button,
292                                         gboolean       show)
293 {
294   GtkFontButtonPrivate *priv = font_button->priv;
295 
296   show = show != FALSE;
297 
298   if (priv->show_preview_entry != show)
299     {
300       priv->show_preview_entry = show;
301       if (priv->font_dialog)
302         gtk_font_chooser_set_show_preview_entry (GTK_FONT_CHOOSER (priv->font_dialog), show);
303       g_object_notify (G_OBJECT (font_button), "show-preview-entry");
304     }
305 }
306 
307 static PangoFontFamily *
gtk_font_button_font_chooser_get_font_family(GtkFontChooser * chooser)308 gtk_font_button_font_chooser_get_font_family (GtkFontChooser *chooser)
309 {
310   GtkFontButton *font_button = GTK_FONT_BUTTON (chooser);
311   GtkFontButtonPrivate *priv = font_button->priv;
312 
313   return priv->font_family;
314 }
315 
316 static PangoFontFace *
gtk_font_button_font_chooser_get_font_face(GtkFontChooser * chooser)317 gtk_font_button_font_chooser_get_font_face (GtkFontChooser *chooser)
318 {
319   GtkFontButton *font_button = GTK_FONT_BUTTON (chooser);
320   GtkFontButtonPrivate *priv = font_button->priv;
321 
322   return priv->font_face;
323 }
324 
325 static int
gtk_font_button_font_chooser_get_font_size(GtkFontChooser * chooser)326 gtk_font_button_font_chooser_get_font_size (GtkFontChooser *chooser)
327 {
328   GtkFontButton *font_button = GTK_FONT_BUTTON (chooser);
329   GtkFontButtonPrivate *priv = font_button->priv;
330 
331   return priv->font_size;
332 }
333 
334 static void
gtk_font_button_font_chooser_set_filter_func(GtkFontChooser * chooser,GtkFontFilterFunc filter_func,gpointer filter_data,GDestroyNotify data_destroy)335 gtk_font_button_font_chooser_set_filter_func (GtkFontChooser    *chooser,
336                                               GtkFontFilterFunc  filter_func,
337                                               gpointer           filter_data,
338                                               GDestroyNotify     data_destroy)
339 {
340   GtkFontButton *font_button = GTK_FONT_BUTTON (chooser);
341   GtkFontButtonPrivate *priv = font_button->priv;
342 
343   if (priv->font_dialog)
344     {
345       gtk_font_chooser_set_filter_func (GTK_FONT_CHOOSER (priv->font_dialog),
346                                         filter_func,
347                                         filter_data,
348                                         data_destroy);
349       return;
350     }
351 
352   clear_font_filter_data (font_button);
353   priv->font_filter = filter_func;
354   priv->font_filter_data = filter_data;
355   priv->font_filter_data_destroy = data_destroy;
356 }
357 
358 static void
gtk_font_button_take_font_desc(GtkFontButton * font_button,PangoFontDescription * font_desc)359 gtk_font_button_take_font_desc (GtkFontButton        *font_button,
360                                 PangoFontDescription *font_desc)
361 {
362   GtkFontButtonPrivate *priv = font_button->priv;
363   GObject *object = G_OBJECT (font_button);
364 
365   if (priv->font_desc && font_desc &&
366       pango_font_description_equal (priv->font_desc, font_desc))
367     {
368       pango_font_description_free (font_desc);
369       return;
370     }
371 
372   g_object_freeze_notify (object);
373 
374   clear_font_data (font_button);
375 
376   if (font_desc)
377     priv->font_desc = font_desc; /* adopted */
378   else
379     priv->font_desc = pango_font_description_from_string (_("Sans 12"));
380 
381   if (pango_font_description_get_size_is_absolute (priv->font_desc))
382     priv->font_size = pango_font_description_get_size (priv->font_desc);
383   else
384     priv->font_size = pango_font_description_get_size (priv->font_desc) / PANGO_SCALE;
385 
386   gtk_font_button_update_font_data (font_button);
387   gtk_font_button_update_font_info (font_button);
388 
389   if (priv->font_dialog)
390     gtk_font_chooser_set_font_desc (GTK_FONT_CHOOSER (priv->font_dialog),
391                                     priv->font_desc);
392 
393   g_object_notify (G_OBJECT (font_button), "font");
394   g_object_notify (G_OBJECT (font_button), "font-desc");
395   g_object_notify (G_OBJECT (font_button), "font-name");
396 
397   g_object_thaw_notify (object);
398 }
399 
400 static const PangoFontDescription *
gtk_font_button_get_font_desc(GtkFontButton * font_button)401 gtk_font_button_get_font_desc (GtkFontButton *font_button)
402 {
403   return font_button->priv->font_desc;
404 }
405 
406 static void
gtk_font_button_font_chooser_set_font_map(GtkFontChooser * chooser,PangoFontMap * font_map)407 gtk_font_button_font_chooser_set_font_map (GtkFontChooser *chooser,
408                                            PangoFontMap   *font_map)
409 {
410   GtkFontButton *font_button = GTK_FONT_BUTTON (chooser);
411 
412   if (g_set_object (&font_button->priv->font_map, font_map))
413     {
414       PangoContext *context;
415 
416       if (!font_map)
417         font_map = pango_cairo_font_map_get_default ();
418 
419       context = gtk_widget_get_pango_context (font_button->priv->font_label);
420       pango_context_set_font_map (context, font_map);
421     }
422 }
423 
424 static PangoFontMap *
gtk_font_button_font_chooser_get_font_map(GtkFontChooser * chooser)425 gtk_font_button_font_chooser_get_font_map (GtkFontChooser *chooser)
426 {
427   GtkFontButton *font_button = GTK_FONT_BUTTON (chooser);
428 
429   return font_button->priv->font_map;
430 }
431 
432 static void
gtk_font_button_font_chooser_notify(GObject * object,GParamSpec * pspec,gpointer user_data)433 gtk_font_button_font_chooser_notify (GObject    *object,
434                                      GParamSpec *pspec,
435                                      gpointer    user_data)
436 {
437   /* We do not forward the notification of the "font" property to the dialog! */
438   if (pspec->name == I_("preview-text") ||
439       pspec->name == I_("show-preview-entry"))
440     g_object_notify_by_pspec (user_data, pspec);
441 }
442 
443 static void
gtk_font_button_font_chooser_iface_init(GtkFontChooserIface * iface)444 gtk_font_button_font_chooser_iface_init (GtkFontChooserIface *iface)
445 {
446   iface->get_font_family = gtk_font_button_font_chooser_get_font_family;
447   iface->get_font_face = gtk_font_button_font_chooser_get_font_face;
448   iface->get_font_size = gtk_font_button_font_chooser_get_font_size;
449   iface->set_filter_func = gtk_font_button_font_chooser_set_filter_func;
450   iface->set_font_map = gtk_font_button_font_chooser_set_font_map;
451   iface->get_font_map = gtk_font_button_font_chooser_get_font_map;
452 }
453 
G_DEFINE_TYPE_WITH_CODE(GtkFontButton,gtk_font_button,GTK_TYPE_BUTTON,G_ADD_PRIVATE (GtkFontButton)G_IMPLEMENT_INTERFACE (GTK_TYPE_FONT_CHOOSER,gtk_font_button_font_chooser_iface_init))454 G_DEFINE_TYPE_WITH_CODE (GtkFontButton, gtk_font_button, GTK_TYPE_BUTTON,
455                          G_ADD_PRIVATE (GtkFontButton)
456                          G_IMPLEMENT_INTERFACE (GTK_TYPE_FONT_CHOOSER,
457                                                 gtk_font_button_font_chooser_iface_init))
458 
459 static void
460 gtk_font_button_class_init (GtkFontButtonClass *klass)
461 {
462   GObjectClass *gobject_class;
463   GtkWidgetClass *widget_class;
464   GtkButtonClass *button_class;
465 
466   gobject_class = (GObjectClass *) klass;
467   widget_class = (GtkWidgetClass *) klass;
468   button_class = (GtkButtonClass *) klass;
469 
470   gobject_class->finalize = gtk_font_button_finalize;
471   gobject_class->set_property = gtk_font_button_set_property;
472   gobject_class->get_property = gtk_font_button_get_property;
473 
474   button_class->clicked = gtk_font_button_clicked;
475 
476   klass->font_set = NULL;
477 
478   _gtk_font_chooser_install_properties (gobject_class);
479 
480   /**
481    * GtkFontButton:title:
482    *
483    * The title of the font chooser dialog.
484    *
485    * Since: 2.4
486    */
487   g_object_class_install_property (gobject_class,
488                                    PROP_TITLE,
489                                    g_param_spec_string ("title",
490                                                         P_("Title"),
491                                                         P_("The title of the font chooser dialog"),
492                                                         _("Pick a Font"),
493                                                         GTK_PARAM_READWRITE));
494 
495   /**
496    * GtkFontButton:font-name:
497    *
498    * The name of the currently selected font.
499    *
500    * Since: 2.4
501    *
502    * Deprecated: 3.22: Use the #GtkFontChooser::font property instead
503    */
504   g_object_class_install_property (gobject_class,
505                                    PROP_FONT_NAME,
506                                    g_param_spec_string ("font-name",
507                                                         P_("Font name"),
508                                                         P_("The name of the selected font"),
509                                                         _("Sans 12"),
510                                                         GTK_PARAM_READWRITE | G_PARAM_DEPRECATED));
511 
512   /**
513    * GtkFontButton:use-font:
514    *
515    * If this property is set to %TRUE, the label will be drawn
516    * in the selected font.
517    *
518    * Since: 2.4
519    */
520   g_object_class_install_property (gobject_class,
521                                    PROP_USE_FONT,
522                                    g_param_spec_boolean ("use-font",
523                                                          P_("Use font in label"),
524                                                          P_("Whether the label is drawn in the selected font"),
525                                                          FALSE,
526                                                          GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
527 
528   /**
529    * GtkFontButton:use-size:
530    *
531    * If this property is set to %TRUE, the label will be drawn
532    * with the selected font size.
533    *
534    * Since: 2.4
535    */
536   g_object_class_install_property (gobject_class,
537                                    PROP_USE_SIZE,
538                                    g_param_spec_boolean ("use-size",
539                                                          P_("Use size in label"),
540                                                          P_("Whether the label is drawn with the selected font size"),
541                                                          FALSE,
542                                                          GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
543 
544   /**
545    * GtkFontButton:show-style:
546    *
547    * If this property is set to %TRUE, the name of the selected font style
548    * will be shown in the label. For a more WYSIWYG way to show the selected
549    * style, see the ::use-font property.
550    *
551    * Since: 2.4
552    */
553   g_object_class_install_property (gobject_class,
554                                    PROP_SHOW_STYLE,
555                                    g_param_spec_boolean ("show-style",
556                                                          P_("Show style"),
557                                                          P_("Whether the selected font style is shown in the label"),
558                                                          TRUE,
559                                                          GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
560   /**
561    * GtkFontButton:show-size:
562    *
563    * If this property is set to %TRUE, the selected font size will be shown
564    * in the label. For a more WYSIWYG way to show the selected size, see the
565    * ::use-size property.
566    *
567    * Since: 2.4
568    */
569   g_object_class_install_property (gobject_class,
570                                    PROP_SHOW_SIZE,
571                                    g_param_spec_boolean ("show-size",
572                                                          P_("Show size"),
573                                                          P_("Whether selected font size is shown in the label"),
574                                                          TRUE,
575                                                          GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
576 
577   /**
578    * GtkFontButton::font-set:
579    * @widget: the object which received the signal.
580    *
581    * The ::font-set signal is emitted when the user selects a font.
582    * When handling this signal, use gtk_font_chooser_get_font()
583    * to find out which font was just selected.
584    *
585    * Note that this signal is only emitted when the user
586    * changes the font. If you need to react to programmatic font changes
587    * as well, use the notify::font signal.
588    *
589    * Since: 2.4
590    */
591   font_button_signals[FONT_SET] = g_signal_new (I_("font-set"),
592                                                 G_TYPE_FROM_CLASS (gobject_class),
593                                                 G_SIGNAL_RUN_FIRST,
594                                                 G_STRUCT_OFFSET (GtkFontButtonClass, font_set),
595                                                 NULL, NULL,
596                                                 NULL,
597                                                 G_TYPE_NONE, 0);
598 
599   /* Bind class to template
600    */
601   gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/ui/gtkfontbutton.ui");
602   gtk_widget_class_bind_template_child_private (widget_class, GtkFontButton, font_label);
603   gtk_widget_class_bind_template_child_private (widget_class, GtkFontButton, size_label);
604   gtk_widget_class_bind_template_child_private (widget_class, GtkFontButton, font_size_box);
605 
606   gtk_widget_class_set_css_name (widget_class, "button");
607 }
608 
609 static void
gtk_font_button_init(GtkFontButton * font_button)610 gtk_font_button_init (GtkFontButton *font_button)
611 {
612   GtkStyleContext *context;
613 
614   font_button->priv = gtk_font_button_get_instance_private (font_button);
615 
616   /* Initialize fields */
617   font_button->priv->use_font = FALSE;
618   font_button->priv->use_size = FALSE;
619   font_button->priv->show_style = TRUE;
620   font_button->priv->show_size = TRUE;
621   font_button->priv->show_preview_entry = TRUE;
622   font_button->priv->font_dialog = NULL;
623   font_button->priv->font_family = NULL;
624   font_button->priv->font_face = NULL;
625   font_button->priv->font_size = -1;
626   font_button->priv->title = g_strdup (_("Pick a Font"));
627   font_button->priv->level = GTK_FONT_CHOOSER_LEVEL_FAMILY |
628                              GTK_FONT_CHOOSER_LEVEL_STYLE |
629                              GTK_FONT_CHOOSER_LEVEL_SIZE;
630   font_button->priv->language = pango_language_get_default ();
631 
632   gtk_widget_init_template (GTK_WIDGET (font_button));
633 
634   gtk_font_button_take_font_desc (font_button, NULL);
635 
636   context = gtk_widget_get_style_context (GTK_WIDGET (font_button));
637   gtk_style_context_add_class (context, "font");
638 }
639 
640 static void
gtk_font_button_finalize(GObject * object)641 gtk_font_button_finalize (GObject *object)
642 {
643   GtkFontButton *font_button = GTK_FONT_BUTTON (object);
644   GtkFontButtonPrivate *priv = font_button->priv;
645 
646   if (priv->font_dialog != NULL)
647     gtk_widget_destroy (priv->font_dialog);
648 
649   g_free (priv->title);
650 
651   clear_font_data (font_button);
652   clear_font_filter_data (font_button);
653 
654   g_free (priv->preview_text);
655 
656   g_clear_object (&priv->provider);
657 
658   G_OBJECT_CLASS (gtk_font_button_parent_class)->finalize (object);
659 }
660 
661 static void
gtk_font_button_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)662 gtk_font_button_set_property (GObject      *object,
663                               guint         param_id,
664                               const GValue *value,
665                               GParamSpec   *pspec)
666 {
667   GtkFontButton *font_button = GTK_FONT_BUTTON (object);
668 
669   switch (param_id)
670     {
671     case GTK_FONT_CHOOSER_PROP_PREVIEW_TEXT:
672       gtk_font_button_set_preview_text (font_button, g_value_get_string (value));
673       break;
674     case GTK_FONT_CHOOSER_PROP_SHOW_PREVIEW_ENTRY:
675       gtk_font_button_set_show_preview_entry (font_button, g_value_get_boolean (value));
676       break;
677     case PROP_TITLE:
678       gtk_font_button_set_title (font_button, g_value_get_string (value));
679       break;
680     case GTK_FONT_CHOOSER_PROP_FONT_DESC:
681       gtk_font_button_take_font_desc (font_button, g_value_dup_boxed (value));
682       break;
683     case GTK_FONT_CHOOSER_PROP_LANGUAGE:
684       gtk_font_button_set_language (font_button, g_value_get_string (value));
685       break;
686     case GTK_FONT_CHOOSER_PROP_LEVEL:
687       gtk_font_button_set_level (font_button, g_value_get_flags (value));
688       break;
689     case GTK_FONT_CHOOSER_PROP_FONT:
690     case PROP_FONT_NAME:
691       font_button_set_font_name (font_button, g_value_get_string (value));
692       break;
693     case PROP_USE_FONT:
694       gtk_font_button_set_use_font (font_button, g_value_get_boolean (value));
695       break;
696     case PROP_USE_SIZE:
697       gtk_font_button_set_use_size (font_button, g_value_get_boolean (value));
698       break;
699     case PROP_SHOW_STYLE:
700       gtk_font_button_set_show_style (font_button, g_value_get_boolean (value));
701       break;
702     case PROP_SHOW_SIZE:
703       gtk_font_button_set_show_size (font_button, g_value_get_boolean (value));
704       break;
705     default:
706       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
707       break;
708   }
709 }
710 
711 static void
gtk_font_button_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)712 gtk_font_button_get_property (GObject    *object,
713                               guint       param_id,
714                               GValue     *value,
715                               GParamSpec *pspec)
716 {
717   GtkFontButton *font_button = GTK_FONT_BUTTON (object);
718   GtkFontButtonPrivate *priv = font_button->priv;
719 
720   switch (param_id)
721     {
722     case GTK_FONT_CHOOSER_PROP_PREVIEW_TEXT:
723       g_value_set_string (value, gtk_font_button_get_preview_text (font_button));
724       break;
725     case GTK_FONT_CHOOSER_PROP_SHOW_PREVIEW_ENTRY:
726       g_value_set_boolean (value, gtk_font_button_get_show_preview_entry (font_button));
727       break;
728     case PROP_TITLE:
729       g_value_set_string (value, gtk_font_button_get_title (font_button));
730       break;
731     case GTK_FONT_CHOOSER_PROP_FONT_DESC:
732       g_value_set_boxed (value, gtk_font_button_get_font_desc (font_button));
733       break;
734     case GTK_FONT_CHOOSER_PROP_FONT_FEATURES:
735       g_value_set_string (value, priv->font_features);
736       break;
737     case GTK_FONT_CHOOSER_PROP_LANGUAGE:
738       g_value_set_string (value, pango_language_to_string (priv->language));
739       break;
740     case GTK_FONT_CHOOSER_PROP_LEVEL:
741       g_value_set_flags (value, priv->level);
742       break;
743     case GTK_FONT_CHOOSER_PROP_FONT:
744     case PROP_FONT_NAME:
745       g_value_set_string (value, font_button->priv->fontname);
746       break;
747     case PROP_USE_FONT:
748       g_value_set_boolean (value, gtk_font_button_get_use_font (font_button));
749       break;
750     case PROP_USE_SIZE:
751       g_value_set_boolean (value, gtk_font_button_get_use_size (font_button));
752       break;
753     case PROP_SHOW_STYLE:
754       g_value_set_boolean (value, gtk_font_button_get_show_style (font_button));
755       break;
756     case PROP_SHOW_SIZE:
757       g_value_set_boolean (value, gtk_font_button_get_show_size (font_button));
758       break;
759     default:
760       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
761       break;
762     }
763 }
764 
765 
766 /**
767  * gtk_font_button_new:
768  *
769  * Creates a new font picker widget.
770  *
771  * Returns: a new font picker widget.
772  *
773  * Since: 2.4
774  */
775 GtkWidget *
gtk_font_button_new(void)776 gtk_font_button_new (void)
777 {
778   return g_object_new (GTK_TYPE_FONT_BUTTON, NULL);
779 }
780 
781 /**
782  * gtk_font_button_new_with_font:
783  * @fontname: Name of font to display in font chooser dialog
784  *
785  * Creates a new font picker widget.
786  *
787  * Returns: a new font picker widget.
788  *
789  * Since: 2.4
790  */
791 GtkWidget *
gtk_font_button_new_with_font(const gchar * fontname)792 gtk_font_button_new_with_font (const gchar *fontname)
793 {
794   return g_object_new (GTK_TYPE_FONT_BUTTON, "font", fontname, NULL);
795 }
796 
797 /**
798  * gtk_font_button_set_title:
799  * @font_button: a #GtkFontButton
800  * @title: a string containing the font chooser dialog title
801  *
802  * Sets the title for the font chooser dialog.
803  *
804  * Since: 2.4
805  */
806 void
gtk_font_button_set_title(GtkFontButton * font_button,const gchar * title)807 gtk_font_button_set_title (GtkFontButton *font_button,
808                            const gchar   *title)
809 {
810   gchar *old_title;
811   g_return_if_fail (GTK_IS_FONT_BUTTON (font_button));
812 
813   old_title = font_button->priv->title;
814   font_button->priv->title = g_strdup (title);
815   g_free (old_title);
816 
817   if (font_button->priv->font_dialog)
818     gtk_window_set_title (GTK_WINDOW (font_button->priv->font_dialog),
819                           font_button->priv->title);
820 
821   g_object_notify (G_OBJECT (font_button), "title");
822 }
823 
824 /**
825  * gtk_font_button_get_title:
826  * @font_button: a #GtkFontButton
827  *
828  * Retrieves the title of the font chooser dialog.
829  *
830  * Returns: an internal copy of the title string which must not be freed.
831  *
832  * Since: 2.4
833  */
834 const gchar*
gtk_font_button_get_title(GtkFontButton * font_button)835 gtk_font_button_get_title (GtkFontButton *font_button)
836 {
837   g_return_val_if_fail (GTK_IS_FONT_BUTTON (font_button), NULL);
838 
839   return font_button->priv->title;
840 }
841 
842 /**
843  * gtk_font_button_get_use_font:
844  * @font_button: a #GtkFontButton
845  *
846  * Returns whether the selected font is used in the label.
847  *
848  * Returns: whether the selected font is used in the label.
849  *
850  * Since: 2.4
851  */
852 gboolean
gtk_font_button_get_use_font(GtkFontButton * font_button)853 gtk_font_button_get_use_font (GtkFontButton *font_button)
854 {
855   g_return_val_if_fail (GTK_IS_FONT_BUTTON (font_button), FALSE);
856 
857   return font_button->priv->use_font;
858 }
859 
860 /**
861  * gtk_font_button_set_use_font:
862  * @font_button: a #GtkFontButton
863  * @use_font: If %TRUE, font name will be written using font chosen.
864  *
865  * If @use_font is %TRUE, the font name will be written using the selected font.
866  *
867  * Since: 2.4
868  */
869 void
gtk_font_button_set_use_font(GtkFontButton * font_button,gboolean use_font)870 gtk_font_button_set_use_font (GtkFontButton *font_button,
871 			      gboolean       use_font)
872 {
873   g_return_if_fail (GTK_IS_FONT_BUTTON (font_button));
874 
875   use_font = (use_font != FALSE);
876 
877   if (font_button->priv->use_font != use_font)
878     {
879       font_button->priv->use_font = use_font;
880 
881       gtk_font_button_label_use_font (font_button);
882 
883       g_object_notify (G_OBJECT (font_button), "use-font");
884     }
885 }
886 
887 
888 /**
889  * gtk_font_button_get_use_size:
890  * @font_button: a #GtkFontButton
891  *
892  * Returns whether the selected size is used in the label.
893  *
894  * Returns: whether the selected size is used in the label.
895  *
896  * Since: 2.4
897  */
898 gboolean
gtk_font_button_get_use_size(GtkFontButton * font_button)899 gtk_font_button_get_use_size (GtkFontButton *font_button)
900 {
901   g_return_val_if_fail (GTK_IS_FONT_BUTTON (font_button), FALSE);
902 
903   return font_button->priv->use_size;
904 }
905 
906 /**
907  * gtk_font_button_set_use_size:
908  * @font_button: a #GtkFontButton
909  * @use_size: If %TRUE, font name will be written using the selected size.
910  *
911  * If @use_size is %TRUE, the font name will be written using the selected size.
912  *
913  * Since: 2.4
914  */
915 void
gtk_font_button_set_use_size(GtkFontButton * font_button,gboolean use_size)916 gtk_font_button_set_use_size (GtkFontButton *font_button,
917                               gboolean       use_size)
918 {
919   g_return_if_fail (GTK_IS_FONT_BUTTON (font_button));
920 
921   use_size = (use_size != FALSE);
922   if (font_button->priv->use_size != use_size)
923     {
924       font_button->priv->use_size = use_size;
925 
926       gtk_font_button_label_use_font (font_button);
927 
928       g_object_notify (G_OBJECT (font_button), "use-size");
929     }
930 }
931 
932 /**
933  * gtk_font_button_get_show_style:
934  * @font_button: a #GtkFontButton
935  *
936  * Returns whether the name of the font style will be shown in the label.
937  *
938  * Returns: whether the font style will be shown in the label.
939  *
940  * Since: 2.4
941  **/
942 gboolean
gtk_font_button_get_show_style(GtkFontButton * font_button)943 gtk_font_button_get_show_style (GtkFontButton *font_button)
944 {
945   g_return_val_if_fail (GTK_IS_FONT_BUTTON (font_button), FALSE);
946 
947   return font_button->priv->show_style;
948 }
949 
950 /**
951  * gtk_font_button_set_show_style:
952  * @font_button: a #GtkFontButton
953  * @show_style: %TRUE if font style should be displayed in label.
954  *
955  * If @show_style is %TRUE, the font style will be displayed along with name of the selected font.
956  *
957  * Since: 2.4
958  */
959 void
gtk_font_button_set_show_style(GtkFontButton * font_button,gboolean show_style)960 gtk_font_button_set_show_style (GtkFontButton *font_button,
961                                 gboolean       show_style)
962 {
963   g_return_if_fail (GTK_IS_FONT_BUTTON (font_button));
964 
965   show_style = (show_style != FALSE);
966   if (font_button->priv->show_style != show_style)
967     {
968       font_button->priv->show_style = show_style;
969 
970       gtk_font_button_update_font_info (font_button);
971 
972       g_object_notify (G_OBJECT (font_button), "show-style");
973     }
974 }
975 
976 
977 /**
978  * gtk_font_button_get_show_size:
979  * @font_button: a #GtkFontButton
980  *
981  * Returns whether the font size will be shown in the label.
982  *
983  * Returns: whether the font size will be shown in the label.
984  *
985  * Since: 2.4
986  **/
987 gboolean
gtk_font_button_get_show_size(GtkFontButton * font_button)988 gtk_font_button_get_show_size (GtkFontButton *font_button)
989 {
990   g_return_val_if_fail (GTK_IS_FONT_BUTTON (font_button), FALSE);
991 
992   return font_button->priv->show_size;
993 }
994 
995 /**
996  * gtk_font_button_set_show_size:
997  * @font_button: a #GtkFontButton
998  * @show_size: %TRUE if font size should be displayed in dialog.
999  *
1000  * If @show_size is %TRUE, the font size will be displayed along with the name of the selected font.
1001  *
1002  * Since: 2.4
1003  */
1004 void
gtk_font_button_set_show_size(GtkFontButton * font_button,gboolean show_size)1005 gtk_font_button_set_show_size (GtkFontButton *font_button,
1006                                gboolean       show_size)
1007 {
1008   g_return_if_fail (GTK_IS_FONT_BUTTON (font_button));
1009 
1010   show_size = (show_size != FALSE);
1011 
1012   if (font_button->priv->show_size != show_size)
1013     {
1014       font_button->priv->show_size = show_size;
1015 
1016       if (font_button->priv->show_size)
1017 	gtk_widget_show (font_button->priv->font_size_box);
1018       else
1019 	gtk_widget_hide (font_button->priv->font_size_box);
1020 
1021       gtk_font_button_update_font_info (font_button);
1022 
1023       g_object_notify (G_OBJECT (font_button), "show-size");
1024     }
1025 }
1026 
1027 
1028 /**
1029  * gtk_font_button_get_font_name:
1030  * @font_button: a #GtkFontButton
1031  *
1032  * Retrieves the name of the currently selected font. This name includes
1033  * style and size information as well. If you want to render something
1034  * with the font, use this string with pango_font_description_from_string() .
1035  * If you’re interested in peeking certain values (family name,
1036  * style, size, weight) just query these properties from the
1037  * #PangoFontDescription object.
1038  *
1039  * Returns: an internal copy of the font name which must not be freed.
1040  *
1041  * Since: 2.4
1042  * Deprecated: 3.22: Use gtk_font_chooser_get_font() instead
1043  */
1044 const gchar *
gtk_font_button_get_font_name(GtkFontButton * font_button)1045 gtk_font_button_get_font_name (GtkFontButton *font_button)
1046 {
1047   g_return_val_if_fail (GTK_IS_FONT_BUTTON (font_button), NULL);
1048 
1049   return font_button->priv->fontname;
1050 }
1051 
1052 static void
font_button_set_font_name(GtkFontButton * font_button,const char * fontname)1053 font_button_set_font_name (GtkFontButton *font_button,
1054                            const char    *fontname)
1055 {
1056   PangoFontDescription *font_desc;
1057 
1058   font_desc = pango_font_description_from_string (fontname);
1059   gtk_font_button_take_font_desc (font_button, font_desc);
1060 }
1061 
1062 /**
1063  * gtk_font_button_set_font_name:
1064  * @font_button: a #GtkFontButton
1065  * @fontname: Name of font to display in font chooser dialog
1066  *
1067  * Sets or updates the currently-displayed font in font picker dialog.
1068  *
1069  * Returns: %TRUE
1070  *
1071  * Since: 2.4
1072  * Deprecated: 3.22: Use gtk_font_chooser_set_font() instead
1073  */
1074 gboolean
gtk_font_button_set_font_name(GtkFontButton * font_button,const gchar * fontname)1075 gtk_font_button_set_font_name (GtkFontButton *font_button,
1076                                const gchar    *fontname)
1077 {
1078   g_return_val_if_fail (GTK_IS_FONT_BUTTON (font_button), FALSE);
1079   g_return_val_if_fail (fontname != NULL, FALSE);
1080 
1081   font_button_set_font_name (font_button, fontname);
1082 
1083   return TRUE;
1084 }
1085 
1086 static void
gtk_font_button_clicked(GtkButton * button)1087 gtk_font_button_clicked (GtkButton *button)
1088 {
1089   GtkFontChooser *font_dialog;
1090   GtkFontButton  *font_button = GTK_FONT_BUTTON (button);
1091   GtkFontButtonPrivate *priv = font_button->priv;
1092 
1093   if (!font_button->priv->font_dialog)
1094     {
1095       GtkWidget *parent;
1096 
1097       parent = gtk_widget_get_toplevel (GTK_WIDGET (font_button));
1098 
1099       priv->font_dialog = gtk_font_chooser_dialog_new (priv->title, NULL);
1100       font_dialog = GTK_FONT_CHOOSER (font_button->priv->font_dialog);
1101 
1102       if (priv->font_map)
1103         gtk_font_chooser_set_font_map (font_dialog, priv->font_map);
1104       gtk_font_chooser_set_show_preview_entry (font_dialog, priv->show_preview_entry);
1105       gtk_font_chooser_set_level (GTK_FONT_CHOOSER (font_dialog), priv->level);
1106       gtk_font_chooser_set_language (GTK_FONT_CHOOSER (font_dialog), pango_language_to_string
1107 (priv->language));
1108 
1109       if (priv->preview_text)
1110         {
1111           gtk_font_chooser_set_preview_text (font_dialog, priv->preview_text);
1112           g_free (priv->preview_text);
1113           priv->preview_text = NULL;
1114         }
1115 
1116       if (priv->font_filter)
1117         {
1118           gtk_font_chooser_set_filter_func (font_dialog,
1119                                             priv->font_filter,
1120                                             priv->font_filter_data,
1121                                             priv->font_filter_data_destroy);
1122           priv->font_filter = NULL;
1123           priv->font_filter_data = NULL;
1124           priv->font_filter_data_destroy = NULL;
1125         }
1126 
1127       if (gtk_widget_is_toplevel (parent) && GTK_IS_WINDOW (parent))
1128         {
1129           if (GTK_WINDOW (parent) != gtk_window_get_transient_for (GTK_WINDOW (font_dialog)))
1130             gtk_window_set_transient_for (GTK_WINDOW (font_dialog), GTK_WINDOW (parent));
1131 
1132           gtk_window_set_modal (GTK_WINDOW (font_dialog),
1133                                 gtk_window_get_modal (GTK_WINDOW (parent)));
1134         }
1135 
1136       g_signal_connect (font_dialog, "notify",
1137                         G_CALLBACK (gtk_font_button_font_chooser_notify), button);
1138 
1139       g_signal_connect (font_dialog, "response",
1140                         G_CALLBACK (response_cb), font_button);
1141 
1142       g_signal_connect (font_dialog, "destroy",
1143                         G_CALLBACK (dialog_destroy), font_button);
1144 
1145       g_signal_connect (font_dialog, "delete-event",
1146                         G_CALLBACK (gtk_widget_hide_on_delete), NULL);
1147     }
1148 
1149   if (!gtk_widget_get_visible (font_button->priv->font_dialog))
1150     {
1151       font_dialog = GTK_FONT_CHOOSER (font_button->priv->font_dialog);
1152       gtk_font_chooser_set_font_desc (font_dialog, font_button->priv->font_desc);
1153     }
1154 
1155   G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1156   gtk_window_present (GTK_WINDOW (font_button->priv->font_dialog));
1157   G_GNUC_END_IGNORE_DEPRECATIONS
1158 }
1159 
1160 
1161 static void
response_cb(GtkDialog * dialog,gint response_id,gpointer data)1162 response_cb (GtkDialog *dialog,
1163              gint       response_id,
1164              gpointer   data)
1165 {
1166   GtkFontButton *font_button = GTK_FONT_BUTTON (data);
1167   GtkFontButtonPrivate *priv = font_button->priv;
1168   GtkFontChooser *font_chooser;
1169   GObject *object;
1170 
1171   gtk_widget_hide (font_button->priv->font_dialog);
1172 
1173   if (response_id != GTK_RESPONSE_OK)
1174     return;
1175 
1176   font_chooser = GTK_FONT_CHOOSER (priv->font_dialog);
1177   object = G_OBJECT (font_chooser);
1178 
1179   g_object_freeze_notify (object);
1180 
1181   clear_font_data (font_button);
1182 
1183   priv->font_desc = gtk_font_chooser_get_font_desc (font_chooser);
1184   if (priv->font_desc)
1185     priv->fontname = pango_font_description_to_string (priv->font_desc);
1186   priv->font_family = gtk_font_chooser_get_font_family (font_chooser);
1187   if (priv->font_family)
1188     g_object_ref (priv->font_family);
1189   priv->font_face = gtk_font_chooser_get_font_face (font_chooser);
1190   if (priv->font_face)
1191     g_object_ref (priv->font_face);
1192   priv->font_size = gtk_font_chooser_get_font_size (font_chooser);
1193   g_free (priv->font_features);
1194   priv->font_features = gtk_font_chooser_get_font_features (font_chooser);
1195   priv->language = pango_language_from_string (gtk_font_chooser_get_language (font_chooser));
1196 
1197   /* Set label font */
1198   gtk_font_button_update_font_info (font_button);
1199 
1200   g_object_notify (G_OBJECT (font_button), "font");
1201   g_object_notify (G_OBJECT (font_button), "font-desc");
1202   g_object_notify (G_OBJECT (font_button), "font-name");
1203   g_object_notify (G_OBJECT (font_button), "font-features");
1204 
1205   g_object_thaw_notify (object);
1206 
1207   /* Emit font_set signal */
1208   g_signal_emit (font_button, font_button_signals[FONT_SET], 0);
1209 }
1210 
1211 static void
dialog_destroy(GtkWidget * widget,gpointer data)1212 dialog_destroy (GtkWidget *widget,
1213                 gpointer   data)
1214 {
1215   GtkFontButton *font_button = GTK_FONT_BUTTON (data);
1216 
1217   /* Dialog will get destroyed so reference is not valid now */
1218   font_button->priv->font_dialog = NULL;
1219 }
1220 
1221 static gchar *
pango_font_description_to_css(PangoFontDescription * desc)1222 pango_font_description_to_css (PangoFontDescription *desc)
1223 {
1224   GString *s;
1225   PangoFontMask set;
1226 
1227   s = g_string_new ("* { ");
1228 
1229   set = pango_font_description_get_set_fields (desc);
1230   if (set & PANGO_FONT_MASK_FAMILY)
1231     {
1232       g_string_append (s, "font-family: ");
1233       g_string_append (s, pango_font_description_get_family (desc));
1234       g_string_append (s, "; ");
1235     }
1236   if (set & PANGO_FONT_MASK_STYLE)
1237     {
1238       switch (pango_font_description_get_style (desc))
1239         {
1240         case PANGO_STYLE_NORMAL:
1241           g_string_append (s, "font-style: normal; ");
1242           break;
1243         case PANGO_STYLE_OBLIQUE:
1244           g_string_append (s, "font-style: oblique; ");
1245           break;
1246         case PANGO_STYLE_ITALIC:
1247           g_string_append (s, "font-style: italic; ");
1248           break;
1249         }
1250     }
1251   if (set & PANGO_FONT_MASK_VARIANT)
1252     {
1253       switch (pango_font_description_get_variant (desc))
1254         {
1255         case PANGO_VARIANT_NORMAL:
1256           g_string_append (s, "font-variant: normal; ");
1257           break;
1258         case PANGO_VARIANT_SMALL_CAPS:
1259           g_string_append (s, "font-variant: small-caps; ");
1260           break;
1261         }
1262     }
1263   if (set & PANGO_FONT_MASK_WEIGHT)
1264     {
1265       switch (pango_font_description_get_weight (desc))
1266         {
1267         case PANGO_WEIGHT_THIN:
1268           g_string_append (s, "font-weight: 100; ");
1269           break;
1270         case PANGO_WEIGHT_ULTRALIGHT:
1271           g_string_append (s, "font-weight: 200; ");
1272           break;
1273         case PANGO_WEIGHT_LIGHT:
1274         case PANGO_WEIGHT_SEMILIGHT:
1275           g_string_append (s, "font-weight: 300; ");
1276           break;
1277         case PANGO_WEIGHT_BOOK:
1278         case PANGO_WEIGHT_NORMAL:
1279           g_string_append (s, "font-weight: 400; ");
1280           break;
1281         case PANGO_WEIGHT_MEDIUM:
1282           g_string_append (s, "font-weight: 500; ");
1283           break;
1284         case PANGO_WEIGHT_SEMIBOLD:
1285           g_string_append (s, "font-weight: 600; ");
1286           break;
1287         case PANGO_WEIGHT_BOLD:
1288           g_string_append (s, "font-weight: 700; ");
1289           break;
1290         case PANGO_WEIGHT_ULTRABOLD:
1291           g_string_append (s, "font-weight: 800; ");
1292           break;
1293         case PANGO_WEIGHT_HEAVY:
1294         case PANGO_WEIGHT_ULTRAHEAVY:
1295           g_string_append (s, "font-weight: 900; ");
1296           break;
1297         }
1298     }
1299   if (set & PANGO_FONT_MASK_STRETCH)
1300     {
1301       switch (pango_font_description_get_stretch (desc))
1302         {
1303         case PANGO_STRETCH_ULTRA_CONDENSED:
1304           g_string_append (s, "font-stretch: ultra-condensed; ");
1305           break;
1306         case PANGO_STRETCH_EXTRA_CONDENSED:
1307           g_string_append (s, "font-stretch: extra-condensed; ");
1308           break;
1309         case PANGO_STRETCH_CONDENSED:
1310           g_string_append (s, "font-stretch: condensed; ");
1311           break;
1312         case PANGO_STRETCH_SEMI_CONDENSED:
1313           g_string_append (s, "font-stretch: semi-condensed; ");
1314           break;
1315         case PANGO_STRETCH_NORMAL:
1316           g_string_append (s, "font-stretch: normal; ");
1317           break;
1318         case PANGO_STRETCH_SEMI_EXPANDED:
1319           g_string_append (s, "font-stretch: semi-expanded; ");
1320           break;
1321         case PANGO_STRETCH_EXPANDED:
1322           g_string_append (s, "font-stretch: expanded; ");
1323           break;
1324         case PANGO_STRETCH_EXTRA_EXPANDED:
1325           g_string_append (s, "font-stretch: extra-expanded; ");
1326           break;
1327         case PANGO_STRETCH_ULTRA_EXPANDED:
1328           g_string_append (s, "font-stretch: ultra-expanded; ");
1329           break;
1330         }
1331     }
1332   if (set & PANGO_FONT_MASK_SIZE)
1333     {
1334       g_string_append_printf (s, "font-size: %dpt", pango_font_description_get_size (desc) / PANGO_SCALE);
1335     }
1336 
1337   g_string_append (s, "}");
1338 
1339   return g_string_free (s, FALSE);
1340 }
1341 
1342 static void
gtk_font_button_label_use_font(GtkFontButton * font_button)1343 gtk_font_button_label_use_font (GtkFontButton *font_button)
1344 {
1345   GtkFontButtonPrivate *priv = font_button->priv;
1346   GtkStyleContext *context;
1347 
1348   context = gtk_widget_get_style_context (priv->font_label);
1349 
1350   if (!priv->use_font)
1351     {
1352       if (priv->provider)
1353         {
1354           gtk_style_context_remove_provider (context, GTK_STYLE_PROVIDER (priv->provider));
1355           g_clear_object (&priv->provider);
1356         }
1357     }
1358   else
1359     {
1360       PangoFontDescription *desc;
1361       gchar *data;
1362 
1363       if (!priv->provider)
1364         {
1365           priv->provider = gtk_css_provider_new ();
1366           gtk_style_context_add_provider (context,
1367                                           GTK_STYLE_PROVIDER (priv->provider),
1368                                           GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
1369         }
1370 
1371       desc = pango_font_description_copy (priv->font_desc);
1372 
1373       if (!priv->use_size)
1374         pango_font_description_unset_fields (desc, PANGO_FONT_MASK_SIZE);
1375 
1376       data = pango_font_description_to_css (desc);
1377       gtk_css_provider_load_from_data (priv->provider, data, -1, NULL);
1378 
1379       g_free (data);
1380       pango_font_description_free (desc);
1381     }
1382 }
1383 
1384 static void
gtk_font_button_update_font_info(GtkFontButton * font_button)1385 gtk_font_button_update_font_info (GtkFontButton *font_button)
1386 {
1387   GtkFontButtonPrivate *priv = font_button->priv;
1388   const gchar *fam_name;
1389   const gchar *face_name;
1390   gchar *family_style;
1391 
1392   if (priv->font_family)
1393     fam_name = pango_font_family_get_name (priv->font_family);
1394   else
1395     fam_name = C_("font", "None");
1396   if (priv->font_face)
1397     face_name = pango_font_face_get_face_name (priv->font_face);
1398   else
1399     face_name = "";
1400 
1401   if (priv->show_style)
1402     family_style = g_strconcat (fam_name, " ", face_name, NULL);
1403   else
1404     family_style = g_strdup (fam_name);
1405 
1406   gtk_label_set_text (GTK_LABEL (font_button->priv->font_label), family_style);
1407   g_free (family_style);
1408 
1409   if (font_button->priv->show_size)
1410     {
1411       /* mirror Pango, which doesn't translate this either */
1412       gchar *size = g_strdup_printf ("%2.4g%s",
1413                                      pango_font_description_get_size (priv->font_desc) / (double)PANGO_SCALE,
1414                                      pango_font_description_get_size_is_absolute (priv->font_desc) ? "px" : "");
1415 
1416       gtk_label_set_text (GTK_LABEL (font_button->priv->size_label), size);
1417 
1418       g_free (size);
1419     }
1420 
1421   gtk_font_button_label_use_font (font_button);
1422 }
1423 
1424 static void
gtk_font_button_set_level(GtkFontButton * button,GtkFontChooserLevel level)1425 gtk_font_button_set_level (GtkFontButton       *button,
1426                            GtkFontChooserLevel  level)
1427 {
1428   GtkFontButtonPrivate *priv = button->priv;
1429 
1430   if (priv->level == level)
1431     return;
1432 
1433   priv->level = level;
1434 
1435   if (priv->font_dialog)
1436     g_object_set (priv->font_dialog, "level", level, NULL);
1437 
1438   g_object_set (button,
1439                 "show-size", (level & GTK_FONT_CHOOSER_LEVEL_SIZE) != 0,
1440                 "show-style", (level & GTK_FONT_CHOOSER_LEVEL_STYLE) != 0,
1441                 NULL);
1442 
1443   g_object_notify (G_OBJECT (button), "level");
1444 }
1445 
1446 static void
gtk_font_button_set_language(GtkFontButton * button,const char * language)1447 gtk_font_button_set_language (GtkFontButton *button,
1448                               const char    *language)
1449 {
1450   GtkFontButtonPrivate *priv = button->priv;
1451 
1452   priv->language = pango_language_from_string (language);
1453 
1454   if (priv->font_dialog)
1455     gtk_font_chooser_set_language (GTK_FONT_CHOOSER (priv->font_dialog), language);
1456 
1457   g_object_notify (G_OBJECT (button), "language");
1458 }
1459