1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * Massively updated for Pango by Owen Taylor, May 2000
5 * GtkFontSelection widget for Gtk+, by Damon Chaplin, May 1998.
6 * Based on the GnomeFontSelector widget, by Elliot Lee, but major changes.
7 * The GnomeFontSelector was derived from app/text_tool.c in the GIMP.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
26 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
27 * file for a list of people on the GTK+ Team. See the ChangeLog
28 * files for a list of changes. These files are distributed with
29 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
38 #include "gdk/gdkkeysyms.h"
40 #include "gtkfontsel.h"
42 #include "gtkbutton.h"
50 #include "gtksignal.h"
54 #include "gtkscrolledwindow.h"
57 /* This is the default text shown in the preview entry, though the user
58 can set it. Remember that some fonts only have capital letters. */
59 #define PREVIEW_TEXT "abcdefghijk ABCDEFGHIJK"
61 /* This is the initial and maximum height of the preview entry (it expands
62 when large font sizes are selected). Initial height is also the minimum. */
63 #define INITIAL_PREVIEW_HEIGHT 44
64 #define MAX_PREVIEW_HEIGHT 300
66 /* These are the sizes of the font, style & size clists. */
67 #define FONT_LIST_HEIGHT 136
68 #define FONT_LIST_WIDTH 190
69 #define FONT_STYLE_LIST_WIDTH 170
70 #define FONT_SIZE_LIST_WIDTH 60
72 /* These are what we use as the standard font sizes, for the size clist.
74 static const guint16 font_sizes[] = {
75 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 26, 28,
76 32, 36, 40, 48, 56, 64, 72
86 static void gtk_font_selection_class_init (GtkFontSelectionClass *klass);
87 static void gtk_font_selection_set_property (GObject *object,
91 static void gtk_font_selection_get_property (GObject *object,
95 static void gtk_font_selection_init (GtkFontSelection *fontsel);
96 static void gtk_font_selection_finalize (GObject *object);
98 /* These are the callbacks & related functions. */
99 static void gtk_font_selection_select_font (GtkWidget *w,
102 GdkEventButton *bevent,
104 static void gtk_font_selection_show_available_fonts (GtkFontSelection *fs);
106 static void gtk_font_selection_show_available_styles (GtkFontSelection *fs);
107 static void gtk_font_selection_select_best_style (GtkFontSelection *fs,
109 static void gtk_font_selection_select_style (GtkWidget *w,
112 GdkEventButton *bevent,
115 static void gtk_font_selection_select_best_size (GtkFontSelection *fs);
116 static void gtk_font_selection_show_available_sizes (GtkFontSelection *fs);
117 static void gtk_font_selection_size_activate (GtkWidget *w,
119 static void gtk_font_selection_select_size (GtkWidget *w,
122 GdkEventButton *bevent,
125 static void gtk_font_selection_scroll_on_map (GtkWidget *w,
128 static void gtk_font_selection_preview_changed (GtkWidget *entry,
129 GtkFontSelection *fontsel);
131 /* Misc. utility functions. */
132 static void gtk_font_selection_load_font (GtkFontSelection *fs);
133 static void gtk_font_selection_update_preview (GtkFontSelection *fs);
135 /* FontSelectionDialog */
136 static void gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass);
137 static void gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag);
139 static gint gtk_font_selection_dialog_on_configure (GtkWidget *widget,
140 GdkEventConfigure *event,
141 GtkFontSelectionDialog *fsd);
143 static GtkWindowClass *font_selection_parent_class = NULL;
144 static GtkVBoxClass *font_selection_dialog_parent_class = NULL;
147 gtk_font_selection_get_type ()
149 static GtkType font_selection_type = 0;
151 if (!font_selection_type)
153 static const GtkTypeInfo fontsel_type_info =
156 sizeof (GtkFontSelection),
157 sizeof (GtkFontSelectionClass),
158 (GtkClassInitFunc) gtk_font_selection_class_init,
159 (GtkObjectInitFunc) gtk_font_selection_init,
160 /* reserved_1 */ NULL,
161 /* reserved_2 */ NULL,
162 (GtkClassInitFunc) NULL,
165 font_selection_type = gtk_type_unique (GTK_TYPE_VBOX,
169 return font_selection_type;
173 gtk_font_selection_class_init (GtkFontSelectionClass *klass)
175 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
177 font_selection_parent_class = gtk_type_class (GTK_TYPE_VBOX);
179 gobject_class->set_property = gtk_font_selection_set_property;
180 gobject_class->get_property = gtk_font_selection_get_property;
182 g_object_class_install_property (gobject_class,
184 g_param_spec_string ("font_name",
186 _("The X string that represents this font."),
189 g_object_class_install_property (gobject_class,
191 g_param_spec_boxed ("font",
193 _("The GdkFont that is currently selected."),
196 g_object_class_install_property (gobject_class,
198 g_param_spec_string ("preview_text",
200 _("The text to display in order to demonstrate the selected font."),
203 gobject_class->finalize = gtk_font_selection_finalize;
207 gtk_font_selection_set_property (GObject *object,
212 GtkFontSelection *fontsel;
214 fontsel = GTK_FONT_SELECTION (object);
219 gtk_font_selection_set_font_name (fontsel, g_value_get_string (value));
221 case PROP_PREVIEW_TEXT:
222 gtk_font_selection_set_preview_text (fontsel, g_value_get_string (value));
225 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
230 static void gtk_font_selection_get_property (GObject *object,
235 GtkFontSelection *fontsel;
237 fontsel = GTK_FONT_SELECTION (object);
242 g_value_set_string (value, gtk_font_selection_get_font_name (fontsel));
245 g_value_set_object (value, gtk_font_selection_get_font (fontsel));
247 case PROP_PREVIEW_TEXT:
248 g_value_set_string (value, gtk_font_selection_get_preview_text (fontsel));
251 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
258 gtk_font_selection_init (GtkFontSelection *fontsel)
260 GtkWidget *scrolled_win;
261 GtkWidget *text_frame;
263 GtkWidget *table, *label;
265 fontsel->size = 12 * PANGO_SCALE;
267 /* Create the table of font, style & size. */
268 table = gtk_table_new (3, 3, FALSE);
269 gtk_widget_show (table);
270 gtk_table_set_col_spacings (GTK_TABLE (table), 8);
271 gtk_box_pack_start (GTK_BOX (fontsel), table, TRUE, TRUE, 0);
273 fontsel->font_entry = gtk_entry_new ();
274 gtk_entry_set_editable (GTK_ENTRY (fontsel->font_entry), FALSE);
275 gtk_widget_set_usize (fontsel->font_entry, 20, -1);
276 gtk_widget_show (fontsel->font_entry);
277 gtk_table_attach (GTK_TABLE (table), fontsel->font_entry, 0, 1, 1, 2,
280 fontsel->font_style_entry = gtk_entry_new ();
281 gtk_entry_set_editable (GTK_ENTRY (fontsel->font_style_entry), FALSE);
282 gtk_widget_set_usize (fontsel->font_style_entry, 20, -1);
283 gtk_widget_show (fontsel->font_style_entry);
284 gtk_table_attach (GTK_TABLE (table), fontsel->font_style_entry, 1, 2, 1, 2,
287 fontsel->size_entry = gtk_entry_new ();
288 gtk_widget_set_usize (fontsel->size_entry, 20, -1);
289 gtk_widget_show (fontsel->size_entry);
290 gtk_table_attach (GTK_TABLE (table), fontsel->size_entry, 2, 3, 1, 2,
292 gtk_signal_connect (GTK_OBJECT (fontsel->size_entry), "activate",
293 (GtkSignalFunc) gtk_font_selection_size_activate,
296 fontsel->font_label = gtk_label_new_with_mnemonic (_("_Family:"));
297 gtk_label_set_mnemonic_widget (GTK_LABEL (fontsel->font_label),
298 fontsel->font_entry);
299 gtk_misc_set_alignment (GTK_MISC (fontsel->font_label), 0.0, 0.5);
300 gtk_widget_show (fontsel->font_label);
301 gtk_table_attach (GTK_TABLE (table), fontsel->font_label, 0, 1, 0, 1,
303 label = gtk_label_new_with_mnemonic (_("_Style:"));
304 gtk_label_set_mnemonic_widget (GTK_LABEL (label),
305 fontsel->font_style_entry);
306 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
307 gtk_widget_show (label);
308 gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,
310 label = gtk_label_new_with_mnemonic (_("Si_ze:"));
311 gtk_label_set_mnemonic_widget (GTK_LABEL (label),
312 fontsel->size_entry);
313 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
314 gtk_widget_show (label);
315 gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1,
319 /* Create the clists */
320 fontsel->font_clist = gtk_clist_new (1);
321 gtk_clist_column_titles_hide (GTK_CLIST (fontsel->font_clist));
322 gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_clist), 0, TRUE);
323 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
324 gtk_widget_set_usize (scrolled_win, FONT_LIST_WIDTH, FONT_LIST_HEIGHT);
325 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_clist);
326 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
327 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
328 gtk_widget_show (fontsel->font_clist);
329 gtk_widget_show (scrolled_win);
331 gtk_table_attach (GTK_TABLE (table), scrolled_win, 0, 1, 2, 3,
332 GTK_EXPAND | GTK_FILL,
333 GTK_EXPAND | GTK_FILL, 0, 0);
335 fontsel->font_style_clist = gtk_clist_new (1);
336 gtk_clist_column_titles_hide (GTK_CLIST (fontsel->font_style_clist));
337 gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_style_clist),
339 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
340 gtk_widget_set_usize (scrolled_win, FONT_STYLE_LIST_WIDTH, -1);
341 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_style_clist);
342 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
343 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
344 gtk_widget_show (fontsel->font_style_clist);
345 gtk_widget_show (scrolled_win);
346 gtk_table_attach (GTK_TABLE (table), scrolled_win, 1, 2, 2, 3,
347 GTK_EXPAND | GTK_FILL,
348 GTK_EXPAND | GTK_FILL, 0, 0);
350 fontsel->size_clist = gtk_clist_new (1);
351 gtk_clist_column_titles_hide (GTK_CLIST (fontsel->size_clist));
352 gtk_clist_set_column_width (GTK_CLIST (fontsel->size_clist), 0, 20);
353 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
354 gtk_widget_set_usize (scrolled_win, FONT_SIZE_LIST_WIDTH, -1);
355 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->size_clist);
356 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
357 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
358 gtk_widget_show (fontsel->size_clist);
359 gtk_widget_show (scrolled_win);
360 gtk_table_attach (GTK_TABLE (table), scrolled_win, 2, 3, 2, 3,
361 GTK_FILL, GTK_FILL, 0, 0);
363 /* Insert the fonts. If there exist fonts with the same family but
364 different foundries, then the foundry name is appended in brackets. */
365 gtk_font_selection_show_available_fonts (fontsel);
367 gtk_signal_connect (GTK_OBJECT (fontsel->font_clist), "select_row",
368 GTK_SIGNAL_FUNC (gtk_font_selection_select_font),
370 GTK_WIDGET_SET_FLAGS (fontsel->font_clist, GTK_CAN_FOCUS);
372 gtk_signal_connect_after (GTK_OBJECT (fontsel->font_clist), "map",
373 GTK_SIGNAL_FUNC (gtk_font_selection_scroll_on_map),
376 gtk_font_selection_show_available_styles (fontsel);
378 gtk_signal_connect (GTK_OBJECT (fontsel->font_style_clist), "select_row",
379 GTK_SIGNAL_FUNC (gtk_font_selection_select_style),
381 GTK_WIDGET_SET_FLAGS (fontsel->font_style_clist, GTK_CAN_FOCUS);
383 gtk_font_selection_show_available_sizes (fontsel);
385 gtk_signal_connect (GTK_OBJECT (fontsel->size_clist), "select_row",
386 GTK_SIGNAL_FUNC (gtk_font_selection_select_size),
388 GTK_WIDGET_SET_FLAGS (fontsel->size_clist, GTK_CAN_FOCUS);
390 /* create the text entry widget */
391 text_frame = gtk_frame_new (_("Preview:"));
392 gtk_widget_show (text_frame);
393 gtk_frame_set_shadow_type (GTK_FRAME (text_frame), GTK_SHADOW_ETCHED_IN);
394 gtk_box_pack_start (GTK_BOX (fontsel), text_frame,
397 /* This is just used to get a 4-pixel space around the preview entry. */
398 text_box = gtk_hbox_new (FALSE, 0);
399 gtk_widget_show (text_box);
400 gtk_container_add (GTK_CONTAINER (text_frame), text_box);
401 gtk_container_set_border_width (GTK_CONTAINER (text_box), 4);
403 fontsel->preview_entry = gtk_entry_new ();
404 gtk_widget_show (fontsel->preview_entry);
405 gtk_signal_connect (GTK_OBJECT (fontsel->preview_entry), "changed",
406 (GtkSignalFunc) gtk_font_selection_preview_changed,
408 gtk_widget_set_usize (fontsel->preview_entry, -1, INITIAL_PREVIEW_HEIGHT);
409 gtk_box_pack_start (GTK_BOX (text_box), fontsel->preview_entry,
412 gtk_font_selection_update_preview (fontsel);
416 gtk_font_selection_new ()
418 GtkFontSelection *fontsel;
420 fontsel = gtk_type_new (GTK_TYPE_FONT_SELECTION);
422 return GTK_WIDGET (fontsel);
426 gtk_font_selection_finalize (GObject *object)
428 GtkFontSelection *fontsel;
430 g_return_if_fail (GTK_IS_FONT_SELECTION (object));
432 fontsel = GTK_FONT_SELECTION (object);
434 g_free (fontsel->families);
435 g_free (fontsel->faces);
438 gdk_font_unref (fontsel->font);
440 if (G_OBJECT_CLASS (font_selection_parent_class)->finalize)
441 (* G_OBJECT_CLASS (font_selection_parent_class)->finalize) (object);
445 gtk_font_selection_preview_changed (GtkWidget *entry,
446 GtkFontSelection *fontsel)
448 g_object_notify (G_OBJECT (fontsel), "preview_text");
451 /* This is called when the clist is mapped. Here we scroll to the current
452 font if necessary. */
454 gtk_font_selection_scroll_on_map (GtkWidget *widget,
457 GtkFontSelection *fontsel;
462 g_message ("In expose_list\n");
464 fontsel = GTK_FONT_SELECTION (data);
466 /* Try to scroll the font family clist to the selected item */
467 selection = GTK_CLIST (fontsel->font_clist)->selection;
470 index = GPOINTER_TO_INT (selection->data);
471 if (gtk_clist_row_is_visible (GTK_CLIST (fontsel->font_clist), index)
472 != GTK_VISIBILITY_FULL)
473 gtk_clist_moveto (GTK_CLIST (fontsel->font_clist), index, -1, 0.5, 0);
476 /* Try to scroll the font style clist to the selected item */
477 selection = GTK_CLIST (fontsel->font_style_clist)->selection;
480 index = GPOINTER_TO_INT (selection->data);
481 if (gtk_clist_row_is_visible (GTK_CLIST (fontsel->font_style_clist), index)
482 != GTK_VISIBILITY_FULL)
483 gtk_clist_moveto (GTK_CLIST (fontsel->font_style_clist), index, -1,
487 /* Try to scroll the font size clist to the selected item */
488 selection = GTK_CLIST (fontsel->size_clist)->selection;
491 index = GPOINTER_TO_INT (selection->data);
492 if (gtk_clist_row_is_visible (GTK_CLIST (fontsel->size_clist), index)
493 != GTK_VISIBILITY_FULL)
494 gtk_clist_moveto (GTK_CLIST (fontsel->size_clist), index, -1, 0.5, 0);
498 /* This is called when a family is selected in the list. */
500 gtk_font_selection_select_font (GtkWidget *w,
503 GdkEventButton *bevent,
506 GtkFontSelection *fontsel;
507 const gchar *family_name;
510 fontsel = GTK_FONT_SELECTION (data);
512 if (GTK_CLIST (fontsel->font_clist)->selection)
514 index = GPOINTER_TO_INT (GTK_CLIST (fontsel->font_clist)->selection->data);
516 if (fontsel->family != fontsel->families[index])
518 fontsel->family = fontsel->families[index];
520 family_name = pango_font_family_get_name (fontsel->family);
522 gtk_entry_set_text (GTK_ENTRY (fontsel->font_entry), family_name);
524 gtk_font_selection_show_available_styles (fontsel);
525 gtk_font_selection_select_best_style (fontsel, TRUE);
531 cmp_families (const void *a, const void *b)
533 const char *a_name = pango_font_family_get_name (*(PangoFontFamily **)a);
534 const char *b_name = pango_font_family_get_name (*(PangoFontFamily **)b);
536 return strcmp (a_name, b_name);
540 gtk_font_selection_show_available_fonts (GtkFontSelection *fontsel)
545 pango_context_list_families (gtk_widget_get_pango_context (GTK_WIDGET (fontsel)),
546 &fontsel->families, &n_families);
547 qsort (fontsel->families, n_families, sizeof (PangoFontFamily *), cmp_families);
549 gtk_clist_freeze (GTK_CLIST (fontsel->font_clist));
550 gtk_clist_clear (GTK_CLIST (fontsel->font_clist));
552 for (i=0; i<n_families; i++)
554 const gchar *name = pango_font_family_get_name (fontsel->families[i]);
556 gtk_clist_append (GTK_CLIST (fontsel->font_clist), (char **)&name);
558 if (!g_strcasecmp (name, "sans"))
565 gtk_clist_select_row (GTK_CLIST (fontsel->font_clist), match_row, 0);
566 gtk_entry_set_text (GTK_ENTRY (fontsel->font_entry),
567 pango_font_family_get_name (fontsel->families[match_row]));
568 fontsel->family = fontsel->families[match_row];
570 gtk_clist_thaw (GTK_CLIST (fontsel->font_clist));
574 compare_font_descriptions (const PangoFontDescription *a, const PangoFontDescription *b)
576 int val = strcmp (pango_font_description_get_family (a), pango_font_description_get_family (b));
580 if (pango_font_description_get_weight (a) != pango_font_description_get_weight (b))
581 return pango_font_description_get_weight (a) - pango_font_description_get_weight (b);
583 if (pango_font_description_get_style (a) != pango_font_description_get_style (b))
584 return pango_font_description_get_style (a) - pango_font_description_get_style (b);
586 if (pango_font_description_get_stretch (a) != pango_font_description_get_stretch (b))
587 return pango_font_description_get_stretch (a) - pango_font_description_get_stretch (b);
589 if (pango_font_description_get_variant (a) != pango_font_description_get_variant (b))
590 return pango_font_description_get_variant (a) - pango_font_description_get_variant (b);
596 faces_sort_func (const void *a, const void *b)
598 PangoFontDescription *desc_a = pango_font_face_describe (*(PangoFontFace **)a);
599 PangoFontDescription *desc_b = pango_font_face_describe (*(PangoFontFace **)b);
601 int ord = compare_font_descriptions (desc_a, desc_b);
603 pango_font_description_free (desc_a);
604 pango_font_description_free (desc_b);
610 font_description_style_equal (const PangoFontDescription *a,
611 const PangoFontDescription *b)
613 return (pango_font_description_get_weight (a) == pango_font_description_get_weight (b) &&
614 pango_font_description_get_style (a) == pango_font_description_get_style (b) &&
615 pango_font_description_get_stretch (a) == pango_font_description_get_stretch (b) &&
616 pango_font_description_get_variant (a) == pango_font_description_get_variant (b));
619 /* This fills the font style clist with all the possible style combinations
620 for the current font family. */
622 gtk_font_selection_show_available_styles (GtkFontSelection *fontsel)
627 PangoFontDescription *old_desc;
630 old_desc = pango_font_face_describe (fontsel->face);
635 g_free (fontsel->faces);
637 pango_font_family_list_faces (fontsel->family, &fontsel->faces, &n_faces);
638 qsort (fontsel->faces, n_faces, sizeof (PangoFontFace *), faces_sort_func);
640 gtk_clist_freeze (GTK_CLIST (fontsel->font_style_clist));
641 gtk_clist_clear (GTK_CLIST (fontsel->font_style_clist));
643 for (i=0; i < n_faces; i++)
645 str = pango_font_face_get_face_name (fontsel->faces[i]);
646 gtk_clist_append (GTK_CLIST (fontsel->font_style_clist), (char **)&str);
650 PangoFontDescription *tmp_desc = pango_font_face_describe (fontsel->faces[i]);
652 if (font_description_style_equal (tmp_desc, old_desc))
655 pango_font_description_free (tmp_desc);
660 pango_font_description_free (old_desc);
662 if (match_row < 0 && n_faces)
667 fontsel->face = fontsel->faces[match_row];
668 gtk_clist_select_row (GTK_CLIST (fontsel->font_style_clist), match_row, 0);
670 str = pango_font_face_get_face_name (fontsel->face);
671 gtk_entry_set_text (GTK_ENTRY (fontsel->font_style_entry), str);
674 fontsel->face = NULL;
676 gtk_clist_thaw (GTK_CLIST (fontsel->font_style_clist));
680 /* This selects a style when the user selects a font. It just uses the first
681 available style at present. I was thinking of trying to maintain the
682 selected style, e.g. bold italic, when the user selects different fonts.
683 However, the interface is so easy to use now I'm not sure it's worth it.
684 Note: This will load a font. */
686 gtk_font_selection_select_best_style (GtkFontSelection *fontsel,
691 gtk_clist_select_row (GTK_CLIST (fontsel->font_style_clist), best_row, 0);
692 if (gtk_clist_row_is_visible (GTK_CLIST (fontsel->font_style_clist), best_row)
693 != GTK_VISIBILITY_FULL)
694 gtk_clist_moveto (GTK_CLIST (fontsel->font_style_clist), best_row, -1,
696 gtk_font_selection_show_available_sizes (fontsel);
697 gtk_font_selection_select_best_size (fontsel);
701 /* This is called when a style is selected in the list. */
703 gtk_font_selection_select_style (GtkWidget *w,
706 GdkEventButton *bevent,
709 GtkFontSelection *fontsel = GTK_FONT_SELECTION (data);
712 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
713 gtk_widget_grab_focus (w);
715 if (GTK_CLIST (fontsel->font_style_clist)->selection)
717 index = GPOINTER_TO_INT (GTK_CLIST (fontsel->font_style_clist)->selection->data);
718 fontsel->face = fontsel->faces[index];
721 gtk_font_selection_show_available_sizes (fontsel);
722 gtk_font_selection_select_best_size (fontsel);
726 gtk_font_selection_show_available_sizes (GtkFontSelection *fontsel)
729 gint current_size = fontsel->size;
733 /* Insert the standard font sizes */
734 gtk_clist_freeze (GTK_CLIST (fontsel->size_clist));
735 gtk_clist_clear (GTK_CLIST (fontsel->size_clist));
737 for (i = 0; i < G_N_ELEMENTS (font_sizes); i++)
739 sprintf (buffer, "%i", font_sizes[i]);
741 gtk_clist_append (GTK_CLIST (fontsel->size_clist), &size);
742 if (font_sizes[i] * PANGO_SCALE == current_size)
743 gtk_clist_select_row (GTK_CLIST (fontsel->size_clist), i, 0);
745 gtk_clist_thaw (GTK_CLIST (fontsel->size_clist));
747 sprintf (buffer, "%i", current_size / PANGO_SCALE);
748 gtk_entry_set_text (GTK_ENTRY (fontsel->size_entry), buffer);
752 gtk_font_selection_select_best_size (GtkFontSelection *fontsel)
754 gtk_font_selection_load_font (fontsel);
757 /* If the user hits return in the font size entry, we change to the new font
760 gtk_font_selection_size_activate (GtkWidget *w,
763 GtkFontSelection *fontsel;
767 fontsel = GTK_FONT_SELECTION (data);
769 text = gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry));
770 new_size = atoi (text) * PANGO_SCALE;
772 if (fontsel->size != new_size)
774 fontsel->size = new_size;
775 gtk_font_selection_load_font (fontsel);
779 /* This is called when a size is selected in the list. */
781 gtk_font_selection_select_size (GtkWidget *w,
784 GdkEventButton *bevent,
787 GtkFontSelection *fontsel;
791 fontsel = GTK_FONT_SELECTION (data);
793 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
794 gtk_widget_grab_focus (w);
796 gtk_clist_get_text (GTK_CLIST (fontsel->size_clist), row, 0, &text);
797 new_size = atoi (text) * PANGO_SCALE;
799 if (fontsel->size != new_size)
801 /* If the size was selected by the user we set the selected_size. */
802 fontsel->size = new_size;
803 gtk_font_selection_load_font (fontsel);
808 gtk_font_selection_load_font (GtkFontSelection *fontsel)
811 gdk_font_unref (fontsel->font);
812 fontsel->font = NULL;
814 gtk_font_selection_update_preview (fontsel);
817 static PangoFontDescription *
818 gtk_font_selection_get_font_description (GtkFontSelection *fontsel)
820 PangoFontDescription *font_desc = pango_font_face_describe (fontsel->face);
821 pango_font_description_set_size (font_desc, fontsel->size);
826 /* This sets the font in the preview entry to the selected font, and tries to
827 make sure that the preview entry is a reasonable size, i.e. so that the
828 text can be seen with a bit of space to spare. But it tries to avoid
829 resizing the entry every time the font changes.
830 This also used to shrink the preview if the font size was decreased, but
831 that made it awkward if the user wanted to resize the window themself. */
833 gtk_font_selection_update_preview (GtkFontSelection *fontsel)
835 GtkRcStyle *rc_style;
837 GtkRequisition old_requisition;
838 GtkWidget *preview_entry = fontsel->preview_entry;
841 gtk_widget_get_child_requisition (preview_entry, &old_requisition);
843 rc_style = gtk_rc_style_new ();
844 rc_style->font_desc = gtk_font_selection_get_font_description (fontsel);
846 gtk_widget_modify_style (preview_entry, rc_style);
847 gtk_rc_style_unref (rc_style);
849 gtk_widget_size_request (preview_entry, NULL);
851 /* We don't ever want to be over MAX_PREVIEW_HEIGHT pixels high. */
852 new_height = CLAMP (preview_entry->requisition.height, INITIAL_PREVIEW_HEIGHT, MAX_PREVIEW_HEIGHT);
854 if (new_height > old_requisition.height || new_height < old_requisition.height - 30)
855 gtk_widget_set_usize (preview_entry, -1, new_height);
857 /* This sets the preview text, if it hasn't been set already. */
858 text = gtk_entry_get_text (GTK_ENTRY (preview_entry));
859 if (strlen (text) == 0)
860 gtk_entry_set_text (GTK_ENTRY (preview_entry), PREVIEW_TEXT);
861 gtk_entry_set_position (GTK_ENTRY (preview_entry), 0);
864 /*****************************************************************************
865 * These functions are the main public interface for getting/setting the font.
866 *****************************************************************************/
869 gtk_font_selection_get_font (GtkFontSelection *fontsel)
873 PangoFontDescription *font_desc = gtk_font_selection_get_font_description (fontsel);
874 fontsel->font = gdk_font_from_description (font_desc);
875 pango_font_description_free (font_desc);
878 return fontsel->font;
883 gtk_font_selection_get_font_name (GtkFontSelection *fontsel)
887 PangoFontDescription *font_desc = gtk_font_selection_get_font_description (fontsel);
888 result = pango_font_description_to_string (font_desc);
889 pango_font_description_free (font_desc);
895 /* This sets the current font, selecting the appropriate clist rows.
896 First we check the fontname is valid and try to find the font family
897 - i.e. the name in the main list. If we can't find that, then just return.
898 Next we try to set each of the properties according to the fontname.
899 Finally we select the font family & style in the clists. */
901 gtk_font_selection_set_font_name (GtkFontSelection *fontsel,
902 const gchar *fontname)
904 PangoFontFamily *new_family = NULL;
905 PangoFontFace *new_face = NULL;
906 PangoFontDescription *new_desc;
907 gint n_families, n_faces, i;
909 g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), FALSE);
911 new_desc = pango_font_description_from_string (fontname);
913 /* Check to make sure that this is in the list of allowed fonts */
915 n_families = GTK_CLIST (fontsel->font_clist)->rows;
916 for (i = 0; i < n_families; i++)
918 if (g_strcasecmp (pango_font_family_get_name (fontsel->families[i]),
919 pango_font_description_get_family (new_desc)) == 0)
920 new_family = fontsel->families[i];
926 fontsel->family = new_family;
927 gtk_font_selection_show_available_styles (fontsel);
929 n_faces = GTK_CLIST (fontsel->font_style_clist)->rows;
930 for (i=0; i < n_faces; i++)
932 PangoFontDescription *tmp_desc = pango_font_face_describe (fontsel->faces[i]);
934 if (font_description_style_equal (tmp_desc, new_desc))
935 new_face = fontsel->faces[i];
937 pango_font_description_free (tmp_desc);
944 new_face = fontsel->faces[0];
946 fontsel->face = new_face;
947 gtk_font_selection_select_best_size (fontsel);
949 g_object_freeze_notify (G_OBJECT (fontsel));
950 g_object_notify (G_OBJECT (fontsel), "font_name");
951 g_object_notify (G_OBJECT (fontsel), "font");
952 g_object_thaw_notify (G_OBJECT (fontsel));
958 /* This returns the text in the preview entry. You should copy the returned
959 text if you need it. */
960 G_CONST_RETURN gchar*
961 gtk_font_selection_get_preview_text (GtkFontSelection *fontsel)
963 return gtk_entry_get_text (GTK_ENTRY (fontsel->preview_entry));
967 /* This sets the text in the preview entry. */
969 gtk_font_selection_set_preview_text (GtkFontSelection *fontsel,
972 gtk_entry_set_text (GTK_ENTRY (fontsel->preview_entry), text);
975 /*****************************************************************************
976 * GtkFontSelectionDialog
977 *****************************************************************************/
980 gtk_font_selection_dialog_get_type (void)
982 static GtkType font_selection_dialog_type = 0;
984 if (!font_selection_dialog_type)
986 GtkTypeInfo fontsel_diag_info =
988 "GtkFontSelectionDialog",
989 sizeof (GtkFontSelectionDialog),
990 sizeof (GtkFontSelectionDialogClass),
991 (GtkClassInitFunc) gtk_font_selection_dialog_class_init,
992 (GtkObjectInitFunc) gtk_font_selection_dialog_init,
993 /* reserved_1 */ NULL,
994 /* reserved_2 */ NULL,
995 (GtkClassInitFunc) NULL,
998 font_selection_dialog_type = gtk_type_unique (GTK_TYPE_DIALOG,
1002 return font_selection_dialog_type;
1006 gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass)
1008 GtkObjectClass *object_class;
1010 object_class = (GtkObjectClass*) klass;
1012 font_selection_dialog_parent_class = gtk_type_class (GTK_TYPE_DIALOG);
1016 gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag)
1020 dialog = GTK_DIALOG (fontseldiag);
1022 fontseldiag->dialog_width = -1;
1023 fontseldiag->auto_resize = TRUE;
1025 gtk_widget_set_events (GTK_WIDGET (fontseldiag), GDK_STRUCTURE_MASK);
1026 gtk_signal_connect (GTK_OBJECT (fontseldiag), "configure_event",
1027 (GtkSignalFunc) gtk_font_selection_dialog_on_configure,
1030 gtk_container_set_border_width (GTK_CONTAINER (fontseldiag), 4);
1031 gtk_window_set_policy (GTK_WINDOW (fontseldiag), FALSE, TRUE, TRUE);
1033 fontseldiag->main_vbox = dialog->vbox;
1035 fontseldiag->fontsel = gtk_font_selection_new ();
1036 gtk_container_set_border_width (GTK_CONTAINER (fontseldiag->fontsel), 4);
1037 gtk_widget_show (fontseldiag->fontsel);
1038 gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox),
1039 fontseldiag->fontsel, TRUE, TRUE, 0);
1041 /* Create the action area */
1042 fontseldiag->action_area = dialog->action_area;
1044 fontseldiag->cancel_button = gtk_dialog_add_button (dialog,
1046 GTK_RESPONSE_CANCEL);
1048 fontseldiag->apply_button = gtk_dialog_add_button (dialog,
1050 GTK_RESPONSE_APPLY);
1051 gtk_widget_hide (fontseldiag->apply_button);
1053 fontseldiag->ok_button = gtk_dialog_add_button (dialog,
1056 gtk_widget_grab_default (fontseldiag->ok_button);
1058 gtk_window_set_title (GTK_WINDOW (fontseldiag),
1059 _("Font Selection"));
1064 gtk_font_selection_dialog_new (const gchar *title)
1066 GtkFontSelectionDialog *fontseldiag;
1068 fontseldiag = gtk_type_new (GTK_TYPE_FONT_SELECTION_DIALOG);
1071 gtk_window_set_title (GTK_WINDOW (fontseldiag), title);
1073 return GTK_WIDGET (fontseldiag);
1077 gtk_font_selection_dialog_get_font_name (GtkFontSelectionDialog *fsd)
1079 return gtk_font_selection_get_font_name (GTK_FONT_SELECTION (fsd->fontsel));
1083 gtk_font_selection_dialog_get_font (GtkFontSelectionDialog *fsd)
1085 return gtk_font_selection_get_font (GTK_FONT_SELECTION (fsd->fontsel));
1089 gtk_font_selection_dialog_set_font_name (GtkFontSelectionDialog *fsd,
1090 const gchar *fontname)
1092 return gtk_font_selection_set_font_name (GTK_FONT_SELECTION (fsd->fontsel), fontname);
1095 G_CONST_RETURN gchar*
1096 gtk_font_selection_dialog_get_preview_text (GtkFontSelectionDialog *fsd)
1098 return gtk_font_selection_get_preview_text (GTK_FONT_SELECTION (fsd->fontsel));
1102 gtk_font_selection_dialog_set_preview_text (GtkFontSelectionDialog *fsd,
1105 gtk_font_selection_set_preview_text (GTK_FONT_SELECTION (fsd->fontsel), text);
1109 /* This turns auto-shrink off if the user resizes the width of the dialog.
1110 It also turns it back on again if the user resizes it back to its normal
1113 gtk_font_selection_dialog_on_configure (GtkWidget *widget,
1114 GdkEventConfigure *event,
1115 GtkFontSelectionDialog *fsd)
1117 /* This sets the initial width. */
1118 if (fsd->dialog_width == -1)
1119 fsd->dialog_width = event->width;
1120 else if (fsd->auto_resize && fsd->dialog_width != event->width)
1122 fsd->auto_resize = FALSE;
1123 gtk_window_set_policy (GTK_WINDOW (fsd), FALSE, TRUE, FALSE);
1125 else if (!fsd->auto_resize && fsd->dialog_width == event->width)
1127 fsd->auto_resize = TRUE;
1128 gtk_window_set_policy (GTK_WINDOW (fsd), FALSE, TRUE, TRUE);