1/* GTK - The GIMP Toolkit
2 * Copyright (C) 2011 Alberto Ruiz <aruiz@gnome.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "config.h"
19
20#include <stdlib.h>
21#include <glib/gprintf.h>
22#include <string.h>
23
24#include "gtkfontchooserdialog.h"
25#include "gtkfontchooser.h"
26#include "gtkfontchooserwidget.h"
27#include "gtkfontchooserwidgetprivate.h"
28#include "gtkfontchooserutils.h"
29#include "gtkbox.h"
30#include "gtkintl.h"
31#include "gtkbuildable.h"
32#include "gtkprivate.h"
33#include "gtkwidget.h"
34#include "gtksettings.h"
35#include "gtkdialogprivate.h"
36#include "gtktogglebutton.h"
37#include "gtkheaderbar.h"
38#include "gtkactionable.h"
39#include "gtkeventcontrollerkey.h"
40
41typedef struct _GtkFontChooserDialogClass GtkFontChooserDialogClass;
42
43struct _GtkFontChooserDialog
44{
45 GtkDialog parent_instance;
46
47 GtkWidget *fontchooser;
48 GtkWidget *select_button;
49 GtkWidget *cancel_button;
50 GtkWidget *tweak_button;
51};
52
53struct _GtkFontChooserDialogClass
54{
55 GtkDialogClass parent_class;
56};
57
58/**
59 * GtkFontChooserDialog:
60 *
61 * The `GtkFontChooserDialog` widget is a dialog for selecting a font.
62 *
63 * ![An example GtkFontChooserDialog](fontchooser.png)
64 *
65 * `GtkFontChooserDialog` implements the [iface@Gtk.FontChooser] interface
66 * and does not provide much API of its own.
67 *
68 * To create a `GtkFontChooserDialog`, use [ctor@Gtk.FontChooserDialog.new].
69 *
70 * # GtkFontChooserDialog as GtkBuildable
71 *
72 * The `GtkFontChooserDialog` implementation of the `GtkBuildable`
73 * interface exposes the buttons with the names “select_button”
74 * and “cancel_button”.
75 */
76
77static void gtk_font_chooser_dialog_buildable_interface_init (GtkBuildableIface *iface);
78static GObject *gtk_font_chooser_dialog_buildable_get_internal_child (GtkBuildable *buildable,
79 GtkBuilder *builder,
80 const char *childname);
81
82G_DEFINE_TYPE_WITH_CODE (GtkFontChooserDialog, gtk_font_chooser_dialog, GTK_TYPE_DIALOG,
83 G_IMPLEMENT_INTERFACE (GTK_TYPE_FONT_CHOOSER,
84 _gtk_font_chooser_delegate_iface_init)
85 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
86 gtk_font_chooser_dialog_buildable_interface_init))
87
88static GtkBuildableIface *parent_buildable_iface;
89
90static void
91gtk_font_chooser_dialog_set_property (GObject *object,
92 guint prop_id,
93 const GValue *value,
94 GParamSpec *pspec)
95{
96 GtkFontChooserDialog *dialog = GTK_FONT_CHOOSER_DIALOG (object);
97
98 switch (prop_id)
99 {
100 default:
101 g_object_set_property (G_OBJECT (dialog->fontchooser), property_name: pspec->name, value);
102 break;
103 }
104}
105
106static void
107gtk_font_chooser_dialog_get_property (GObject *object,
108 guint prop_id,
109 GValue *value,
110 GParamSpec *pspec)
111{
112 GtkFontChooserDialog *dialog = GTK_FONT_CHOOSER_DIALOG (object);
113
114 switch (prop_id)
115 {
116 default:
117 g_object_get_property (G_OBJECT (dialog->fontchooser), property_name: pspec->name, value);
118 break;
119 }
120}
121
122static void
123font_activated_cb (GtkFontChooser *fontchooser,
124 const char *fontname,
125 gpointer user_data)
126{
127 GtkDialog *dialog = user_data;
128
129 gtk_dialog_response (dialog, response_id: GTK_RESPONSE_OK);
130}
131
132static gboolean
133dialog_forward_key (GtkEventControllerKey *controller,
134 guint keyval,
135 guint keycode,
136 GdkModifierType modifiers,
137 GtkWidget *widget)
138{
139 GtkFontChooserDialog *dialog = GTK_FONT_CHOOSER_DIALOG (widget);
140
141 return gtk_event_controller_key_forward (controller, widget: dialog->fontchooser);
142}
143
144static void
145update_tweak_button (GtkFontChooserDialog *dialog)
146{
147 GtkFontChooserLevel level;
148
149 if (!dialog->tweak_button)
150 return;
151
152 g_object_get (object: dialog->fontchooser, first_property_name: "level", &level, NULL);
153 if ((level & (GTK_FONT_CHOOSER_LEVEL_FEATURES | GTK_FONT_CHOOSER_LEVEL_VARIATIONS)) != 0)
154 gtk_widget_show (widget: dialog->tweak_button);
155 else
156 gtk_widget_hide (widget: dialog->tweak_button);
157}
158
159static void
160setup_tweak_button (GtkFontChooserDialog *dialog)
161{
162 gboolean use_header;
163
164 if (dialog->tweak_button)
165 return;
166
167 g_object_get (object: dialog, first_property_name: "use-header-bar", &use_header, NULL);
168 if (use_header)
169 {
170 GtkWidget *button;
171 GtkWidget *header;
172 GActionGroup *actions;
173
174 actions = G_ACTION_GROUP (g_simple_action_group_new ());
175 g_action_map_add_action (G_ACTION_MAP (actions), action: gtk_font_chooser_widget_get_tweak_action (fontchooser: dialog->fontchooser));
176 gtk_widget_insert_action_group (GTK_WIDGET (dialog), name: "font", group: actions);
177 g_object_unref (object: actions);
178
179 button = gtk_toggle_button_new ();
180 gtk_actionable_set_action_name (GTK_ACTIONABLE (button), action_name: "font.tweak");
181 gtk_widget_set_focus_on_click (widget: button, FALSE);
182 gtk_widget_set_valign (widget: button, align: GTK_ALIGN_CENTER);
183 gtk_button_set_icon_name (GTK_BUTTON (button), icon_name: "emblem-system-symbolic");
184
185 header = gtk_dialog_get_header_bar (GTK_DIALOG (dialog));
186 gtk_header_bar_pack_end (GTK_HEADER_BAR (header), child: button);
187
188 dialog->tweak_button = button;
189
190 update_tweak_button (dialog);
191 }
192}
193
194static void
195gtk_font_chooser_dialog_map (GtkWidget *widget)
196{
197 GtkFontChooserDialog *dialog = GTK_FONT_CHOOSER_DIALOG (widget);
198
199 setup_tweak_button (dialog);
200
201 GTK_WIDGET_CLASS (gtk_font_chooser_dialog_parent_class)->map (widget);
202}
203
204static void
205update_button (GtkFontChooserDialog *dialog)
206{
207 PangoFontDescription *desc;
208
209 desc = gtk_font_chooser_get_font_desc (GTK_FONT_CHOOSER (dialog->fontchooser));
210
211 gtk_widget_set_sensitive (widget: dialog->select_button, sensitive: desc != NULL);
212
213 if (desc)
214 pango_font_description_free (desc);
215}
216
217static void
218gtk_font_chooser_dialog_dispose (GObject *object)
219{
220 GtkFontChooserDialog *dialog = GTK_FONT_CHOOSER_DIALOG (object);
221
222 if (dialog->fontchooser)
223 {
224 g_signal_handlers_disconnect_by_func (dialog->fontchooser,
225 update_button,
226 dialog);
227 g_signal_handlers_disconnect_by_func (dialog->fontchooser,
228 update_tweak_button,
229 dialog);
230 }
231
232 g_clear_pointer (&dialog->select_button, gtk_widget_unparent);
233 g_clear_pointer (&dialog->cancel_button, gtk_widget_unparent);
234 g_clear_pointer (&dialog->tweak_button, gtk_widget_unparent);
235 g_clear_pointer (&dialog->fontchooser, gtk_widget_unparent);
236
237 G_OBJECT_CLASS (gtk_font_chooser_dialog_parent_class)->dispose (object);
238}
239
240static void
241gtk_font_chooser_dialog_class_init (GtkFontChooserDialogClass *klass)
242{
243 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
244 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
245
246 gobject_class->dispose = gtk_font_chooser_dialog_dispose;
247 gobject_class->get_property = gtk_font_chooser_dialog_get_property;
248 gobject_class->set_property = gtk_font_chooser_dialog_set_property;
249
250 widget_class->map = gtk_font_chooser_dialog_map;
251
252 _gtk_font_chooser_install_properties (klass: gobject_class);
253
254 /* Bind class to template
255 */
256 gtk_widget_class_set_template_from_resource (widget_class,
257 resource_name: "/org/gtk/libgtk/ui/gtkfontchooserdialog.ui");
258
259 gtk_widget_class_bind_template_child (widget_class, GtkFontChooserDialog, fontchooser);
260 gtk_widget_class_bind_template_child (widget_class, GtkFontChooserDialog, select_button);
261 gtk_widget_class_bind_template_child (widget_class, GtkFontChooserDialog, cancel_button);
262 gtk_widget_class_bind_template_callback (widget_class, font_activated_cb);
263 gtk_widget_class_bind_template_callback (widget_class, dialog_forward_key);
264}
265
266static void
267gtk_font_chooser_dialog_init (GtkFontChooserDialog *dialog)
268{
269 gtk_widget_init_template (GTK_WIDGET (dialog));
270 gtk_dialog_set_use_header_bar_from_setting (GTK_DIALOG (dialog));
271
272 _gtk_font_chooser_set_delegate (GTK_FONT_CHOOSER (dialog),
273 GTK_FONT_CHOOSER (dialog->fontchooser));
274
275 g_signal_connect_swapped (dialog->fontchooser, "notify::font-desc",
276 G_CALLBACK (update_button), dialog);
277 update_button (dialog);
278 g_signal_connect_swapped (dialog->fontchooser, "notify::level",
279 G_CALLBACK (update_tweak_button), dialog);
280}
281
282/**
283 * gtk_font_chooser_dialog_new:
284 * @title: (nullable): Title of the dialog
285 * @parent: (nullable): Transient parent of the dialog
286 *
287 * Creates a new `GtkFontChooserDialog`.
288 *
289 * Returns: a new `GtkFontChooserDialog`
290 */
291GtkWidget*
292gtk_font_chooser_dialog_new (const char *title,
293 GtkWindow *parent)
294{
295 GtkFontChooserDialog *dialog;
296
297 dialog = g_object_new (GTK_TYPE_FONT_CHOOSER_DIALOG,
298 first_property_name: "title", title,
299 "transient-for", parent,
300 NULL);
301
302 return GTK_WIDGET (dialog);
303}
304
305static void
306gtk_font_chooser_dialog_buildable_interface_init (GtkBuildableIface *iface)
307{
308 parent_buildable_iface = g_type_interface_peek_parent (g_iface: iface);
309 iface->get_internal_child = gtk_font_chooser_dialog_buildable_get_internal_child;
310}
311
312static GObject *
313gtk_font_chooser_dialog_buildable_get_internal_child (GtkBuildable *buildable,
314 GtkBuilder *builder,
315 const char *childname)
316{
317 GtkFontChooserDialog *dialog = GTK_FONT_CHOOSER_DIALOG (buildable);
318
319 if (g_strcmp0 (str1: childname, str2: "select_button") == 0)
320 return G_OBJECT (dialog->select_button);
321 else if (g_strcmp0 (str1: childname, str2: "cancel_button") == 0)
322 return G_OBJECT (dialog->cancel_button);
323
324 return parent_buildable_iface->get_internal_child (buildable, builder, childname);
325}
326

source code of gtk/gtk/gtkfontchooserdialog.c