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

source code of gtk/gtk/gtkfontbutton.c