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, G_OBJECT (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->font_desc = pango_font_description_from_string ("sans 12");
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 pango_font_description_free (fontsel->font_desc);
437 gdk_font_unref (fontsel->font);
439 if (G_OBJECT_CLASS (font_selection_parent_class)->finalize)
440 (* G_OBJECT_CLASS (font_selection_parent_class)->finalize) (object);
444 gtk_font_selection_preview_changed (GtkWidget *entry,
445 GtkFontSelection *fontsel)
447 g_object_notify (G_OBJECT (fontsel), "preview_text");
450 /* This is called when the clist is mapped. Here we scroll to the current
451 font if necessary. */
453 gtk_font_selection_scroll_on_map (GtkWidget *widget,
456 GtkFontSelection *fontsel;
461 g_message ("In expose_list\n");
463 fontsel = GTK_FONT_SELECTION (data);
465 /* Try to scroll the font family clist to the selected item */
466 selection = GTK_CLIST (fontsel->font_clist)->selection;
469 index = GPOINTER_TO_INT (selection->data);
470 if (gtk_clist_row_is_visible (GTK_CLIST (fontsel->font_clist), index)
471 != GTK_VISIBILITY_FULL)
472 gtk_clist_moveto (GTK_CLIST (fontsel->font_clist), index, -1, 0.5, 0);
475 /* Try to scroll the font style clist to the selected item */
476 selection = GTK_CLIST (fontsel->font_style_clist)->selection;
479 index = GPOINTER_TO_INT (selection->data);
480 if (gtk_clist_row_is_visible (GTK_CLIST (fontsel->font_style_clist), index)
481 != GTK_VISIBILITY_FULL)
482 gtk_clist_moveto (GTK_CLIST (fontsel->font_style_clist), index, -1,
486 /* Try to scroll the font size clist to the selected item */
487 selection = GTK_CLIST (fontsel->size_clist)->selection;
490 index = GPOINTER_TO_INT (selection->data);
491 if (gtk_clist_row_is_visible (GTK_CLIST (fontsel->size_clist), index)
492 != GTK_VISIBILITY_FULL)
493 gtk_clist_moveto (GTK_CLIST (fontsel->size_clist), index, -1, 0.5, 0);
497 /* This is called when a family is selected in the list. */
499 gtk_font_selection_select_font (GtkWidget *w,
502 GdkEventButton *bevent,
505 GtkFontSelection *fontsel;
509 fontsel = GTK_FONT_SELECTION (data);
511 if (GTK_CLIST (fontsel->font_clist)->selection)
513 index = GPOINTER_TO_INT (GTK_CLIST (fontsel->font_clist)->selection->data);
515 if (gtk_clist_get_text (GTK_CLIST (fontsel->font_clist), index, 0, &family_name) &&
516 strcasecmp (fontsel->font_desc->family_name, family_name) != 0)
518 g_free (fontsel->font_desc->family_name);
519 fontsel->font_desc->family_name = g_strdup (family_name);
521 gtk_entry_set_text (GTK_ENTRY (fontsel->font_entry), family_name);
523 gtk_font_selection_show_available_styles (fontsel);
524 gtk_font_selection_select_best_style (fontsel, TRUE);
530 cmp_strings (const void *a, const void *b)
532 return strcasecmp (*(const char **)a, *(const char **)b);
536 gtk_font_selection_show_available_fonts (GtkFontSelection *fontsel)
541 pango_context_list_families (gtk_widget_get_pango_context (GTK_WIDGET (fontsel)),
542 &families, &n_families);
543 qsort (families, n_families, sizeof (char *), cmp_strings);
545 gtk_clist_freeze (GTK_CLIST (fontsel->font_clist));
546 gtk_clist_clear (GTK_CLIST (fontsel->font_clist));
548 for (i=0; i<n_families; i++)
550 gtk_clist_append (GTK_CLIST (fontsel->font_clist), &families[i]);
552 if (!strcasecmp (families[i], fontsel->font_desc->family_name))
554 gtk_clist_select_row (GTK_CLIST (fontsel->font_clist), i, 0);
555 gtk_entry_set_text (GTK_ENTRY (fontsel->font_entry), families[i]);
559 gtk_clist_thaw (GTK_CLIST (fontsel->font_clist));
561 pango_font_map_free_families (families, n_families);
565 compare_font_descriptions (const PangoFontDescription *a, const PangoFontDescription *b)
567 int val = strcasecmp (a->family_name, b->family_name);
571 if (a->weight != b->weight)
572 return a->weight - b->weight;
574 if (a->style != b->style)
575 return a->style - b->style;
577 if (a->stretch != b->stretch)
578 return a->stretch - b->stretch;
580 if (a->variant != b->variant)
581 return a->variant - b->variant;
587 font_description_sort_func (const void *a, const void *b)
589 return compare_font_descriptions (*(PangoFontDescription **)a, *(PangoFontDescription **)b);
592 /* This fills the font style clist with all the possible style combinations
593 for the current font family. */
595 gtk_font_selection_show_available_styles (GtkFontSelection *fontsel)
597 PangoFontDescription **descs;
602 pango_context_list_fonts (gtk_widget_get_pango_context (GTK_WIDGET (fontsel)),
603 fontsel->font_desc->family_name, &descs, &n_descs);
604 qsort (descs, n_descs, sizeof (PangoFontDescription *), font_description_sort_func);
606 gtk_clist_freeze (GTK_CLIST (fontsel->font_style_clist));
607 gtk_clist_clear (GTK_CLIST (fontsel->font_style_clist));
609 for (i=0; i<n_descs; i++)
611 PangoFontDescription tmp_desc;
613 tmp_desc = *descs[i];
614 tmp_desc.family_name = NULL;
617 str = pango_font_description_to_string (&tmp_desc);
618 gtk_clist_append (GTK_CLIST (fontsel->font_style_clist), &str);
620 if (descs[i]->weight == fontsel->font_desc->weight &&
621 descs[i]->style == fontsel->font_desc->style &&
622 descs[i]->stretch == fontsel->font_desc->stretch &&
623 descs[i]->variant == fontsel->font_desc->variant)
629 gtk_clist_select_row (GTK_CLIST (fontsel->font_style_clist), match_row, 0);
632 gtk_clist_get_text (GTK_CLIST (fontsel->font_style_clist), match_row, 0, &str);
633 gtk_entry_set_text (GTK_ENTRY (fontsel->font_style_entry), str);
636 gtk_clist_thaw (GTK_CLIST (fontsel->font_style_clist));
638 pango_font_descriptions_free (descs, n_descs);
642 /* This selects a style when the user selects a font. It just uses the first
643 available style at present. I was thinking of trying to maintain the
644 selected style, e.g. bold italic, when the user selects different fonts.
645 However, the interface is so easy to use now I'm not sure it's worth it.
646 Note: This will load a font. */
648 gtk_font_selection_select_best_style (GtkFontSelection *fontsel,
653 gtk_clist_select_row (GTK_CLIST (fontsel->font_style_clist), best_row, 0);
654 if (gtk_clist_row_is_visible (GTK_CLIST (fontsel->font_style_clist), best_row)
655 != GTK_VISIBILITY_FULL)
656 gtk_clist_moveto (GTK_CLIST (fontsel->font_style_clist), best_row, -1,
658 gtk_font_selection_show_available_sizes (fontsel);
659 gtk_font_selection_select_best_size (fontsel);
663 /* This is called when a style is selected in the list. */
665 gtk_font_selection_select_style (GtkWidget *w,
668 GdkEventButton *bevent,
671 GtkFontSelection *fontsel = GTK_FONT_SELECTION (data);
672 PangoFontDescription *tmp_desc;
676 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
677 gtk_widget_grab_focus (w);
679 if (GTK_CLIST (fontsel->font_style_clist)->selection)
681 index = GPOINTER_TO_INT (GTK_CLIST (fontsel->font_style_clist)->selection->data);
683 if (gtk_clist_get_text (GTK_CLIST (fontsel->font_style_clist), index, 0, &text))
685 tmp_desc = pango_font_description_from_string (text);
687 fontsel->font_desc->style = tmp_desc->style;
688 fontsel->font_desc->variant = tmp_desc->variant;
689 fontsel->font_desc->weight = tmp_desc->weight;
690 fontsel->font_desc->stretch = tmp_desc->stretch;
692 pango_font_description_free (tmp_desc);
696 gtk_font_selection_show_available_sizes (fontsel);
697 gtk_font_selection_select_best_size (fontsel);
701 gtk_font_selection_show_available_sizes (GtkFontSelection *fontsel)
707 /* Insert the standard font sizes */
708 gtk_clist_freeze (GTK_CLIST (fontsel->size_clist));
709 gtk_clist_clear (GTK_CLIST (fontsel->size_clist));
711 for (i = 0; i < G_N_ELEMENTS (font_sizes); i++)
713 sprintf (buffer, "%i", font_sizes[i]);
715 gtk_clist_append (GTK_CLIST (fontsel->size_clist), &size);
716 if (font_sizes[i] * PANGO_SCALE == fontsel->font_desc->size)
717 gtk_clist_select_row (GTK_CLIST (fontsel->size_clist), i, 0);
719 gtk_clist_thaw (GTK_CLIST (fontsel->size_clist));
721 sprintf (buffer, "%i", fontsel->font_desc->size / PANGO_SCALE);
722 gtk_entry_set_text (GTK_ENTRY (fontsel->size_entry), buffer);
726 gtk_font_selection_select_best_size (GtkFontSelection *fontsel)
728 gtk_font_selection_load_font (fontsel);
731 /* If the user hits return in the font size entry, we change to the new font
734 gtk_font_selection_size_activate (GtkWidget *w,
737 GtkFontSelection *fontsel;
741 fontsel = GTK_FONT_SELECTION (data);
743 text = gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry));
744 new_size = atoi (text) * PANGO_SCALE;
746 if (fontsel->font_desc->size != new_size)
748 fontsel->font_desc->size = new_size;
749 gtk_font_selection_load_font (fontsel);
753 /* This is called when a size is selected in the list. */
755 gtk_font_selection_select_size (GtkWidget *w,
758 GdkEventButton *bevent,
761 GtkFontSelection *fontsel;
765 fontsel = GTK_FONT_SELECTION (data);
767 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
768 gtk_widget_grab_focus (w);
770 gtk_clist_get_text (GTK_CLIST (fontsel->size_clist), row, 0, &text);
771 new_size = atoi (text) * PANGO_SCALE;
773 if (fontsel->font_desc->size != new_size)
775 /* If the size was selected by the user we set the selected_size. */
776 fontsel->font_desc->size = new_size;
778 gtk_font_selection_load_font (fontsel);
783 gtk_font_selection_load_font (GtkFontSelection *fontsel)
786 gdk_font_unref (fontsel->font);
787 fontsel->font = NULL;
789 gtk_font_selection_update_preview (fontsel);
792 /* This sets the font in the preview entry to the selected font, and tries to
793 make sure that the preview entry is a reasonable size, i.e. so that the
794 text can be seen with a bit of space to spare. But it tries to avoid
795 resizing the entry every time the font changes.
796 This also used to shrink the preview if the font size was decreased, but
797 that made it awkward if the user wanted to resize the window themself. */
799 gtk_font_selection_update_preview (GtkFontSelection *fontsel)
801 GtkRcStyle *rc_style;
803 GtkRequisition old_requisition;
804 GtkWidget *preview_entry = fontsel->preview_entry;
807 gtk_widget_get_child_requisition (preview_entry, &old_requisition);
809 rc_style = gtk_rc_style_new ();
810 rc_style->font_desc = pango_font_description_copy (fontsel->font_desc);
811 gtk_widget_modify_style (preview_entry, rc_style);
812 gtk_rc_style_unref (rc_style);
814 gtk_widget_size_request (preview_entry, NULL);
816 /* We don't ever want to be over MAX_PREVIEW_HEIGHT pixels high. */
817 new_height = CLAMP (preview_entry->requisition.height, INITIAL_PREVIEW_HEIGHT, MAX_PREVIEW_HEIGHT);
819 if (new_height > old_requisition.height || new_height < old_requisition.height - 30)
820 gtk_widget_set_usize (preview_entry, -1, new_height);
822 /* This sets the preview text, if it hasn't been set already. */
823 text = gtk_entry_get_text (GTK_ENTRY (preview_entry));
824 if (strlen (text) == 0)
825 gtk_entry_set_text (GTK_ENTRY (preview_entry), PREVIEW_TEXT);
826 gtk_entry_set_position (GTK_ENTRY (preview_entry), 0);
829 /*****************************************************************************
830 * These functions are the main public interface for getting/setting the font.
831 *****************************************************************************/
834 gtk_font_selection_get_font (GtkFontSelection *fontsel)
837 fontsel->font = gdk_font_from_description (fontsel->font_desc);
839 return fontsel->font;
844 gtk_font_selection_get_font_name (GtkFontSelection *fontsel)
846 return pango_font_description_to_string (fontsel->font_desc);
850 /* This sets the current font, selecting the appropriate clist rows.
851 First we check the fontname is valid and try to find the font family
852 - i.e. the name in the main list. If we can't find that, then just return.
853 Next we try to set each of the properties according to the fontname.
854 Finally we select the font family & style in the clists. */
856 gtk_font_selection_set_font_name (GtkFontSelection *fontsel,
857 const gchar *fontname)
859 PangoFontDescription *new_desc;
860 PangoFontDescription **descs;
862 gboolean found = FALSE;
864 g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), FALSE);
866 new_desc = pango_font_description_from_string (fontname);
868 /* Check to make sure that this is in the list of allowed fonts */
870 pango_context_list_fonts (gtk_widget_get_pango_context (GTK_WIDGET (fontsel)),
871 new_desc->family_name, &descs, &n_descs);
873 for (i=0; i<n_descs; i++)
875 if (descs[i]->weight == new_desc->weight &&
876 descs[i]->style == new_desc->style &&
877 descs[i]->stretch == new_desc->stretch &&
878 descs[i]->variant == new_desc->variant)
885 pango_font_descriptions_free (descs, n_descs);
890 pango_font_description_free (fontsel->font_desc);
891 fontsel->font_desc = new_desc;
893 g_object_notify (G_OBJECT (fontsel), "font_name");
894 g_object_notify (G_OBJECT (fontsel), "font");
899 /* This returns the text in the preview entry. You should copy the returned
900 text if you need it. */
902 gtk_font_selection_get_preview_text (GtkFontSelection *fontsel)
904 return gtk_entry_get_text (GTK_ENTRY (fontsel->preview_entry));
908 /* This sets the text in the preview entry. */
910 gtk_font_selection_set_preview_text (GtkFontSelection *fontsel,
913 gtk_entry_set_text (GTK_ENTRY (fontsel->preview_entry), text);
916 /*****************************************************************************
917 * GtkFontSelectionDialog
918 *****************************************************************************/
921 gtk_font_selection_dialog_get_type (void)
923 static guint font_selection_dialog_type = 0;
925 if (!font_selection_dialog_type)
927 GtkTypeInfo fontsel_diag_info =
929 "GtkFontSelectionDialog",
930 sizeof (GtkFontSelectionDialog),
931 sizeof (GtkFontSelectionDialogClass),
932 (GtkClassInitFunc) gtk_font_selection_dialog_class_init,
933 (GtkObjectInitFunc) gtk_font_selection_dialog_init,
934 /* reserved_1 */ NULL,
935 /* reserved_2 */ NULL,
936 (GtkClassInitFunc) NULL,
939 font_selection_dialog_type = gtk_type_unique (GTK_TYPE_DIALOG,
943 return font_selection_dialog_type;
947 gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass)
949 GtkObjectClass *object_class;
951 object_class = (GtkObjectClass*) klass;
953 font_selection_dialog_parent_class = gtk_type_class (GTK_TYPE_DIALOG);
957 gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag)
961 dialog = GTK_DIALOG (fontseldiag);
963 fontseldiag->dialog_width = -1;
964 fontseldiag->auto_resize = TRUE;
966 gtk_widget_set_events (GTK_WIDGET (fontseldiag), GDK_STRUCTURE_MASK);
967 gtk_signal_connect (GTK_OBJECT (fontseldiag), "configure_event",
968 (GtkSignalFunc) gtk_font_selection_dialog_on_configure,
971 gtk_container_set_border_width (GTK_CONTAINER (fontseldiag), 4);
972 gtk_window_set_policy (GTK_WINDOW (fontseldiag), FALSE, TRUE, TRUE);
974 fontseldiag->main_vbox = dialog->vbox;
976 fontseldiag->fontsel = gtk_font_selection_new ();
977 gtk_container_set_border_width (GTK_CONTAINER (fontseldiag->fontsel), 4);
978 gtk_widget_show (fontseldiag->fontsel);
979 gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox),
980 fontseldiag->fontsel, TRUE, TRUE, 0);
982 /* Create the action area */
983 fontseldiag->action_area = dialog->action_area;
985 fontseldiag->ok_button = gtk_dialog_add_button (dialog,
988 gtk_widget_grab_default (fontseldiag->ok_button);
990 fontseldiag->apply_button = gtk_dialog_add_button (dialog,
993 gtk_widget_hide (fontseldiag->apply_button);
996 fontseldiag->cancel_button = gtk_dialog_add_button (dialog,
998 GTK_RESPONSE_CANCEL);
1000 gtk_window_set_title (GTK_WINDOW (fontseldiag),
1001 _("Font Selection"));
1006 gtk_font_selection_dialog_new (const gchar *title)
1008 GtkFontSelectionDialog *fontseldiag;
1010 fontseldiag = gtk_type_new (GTK_TYPE_FONT_SELECTION_DIALOG);
1013 gtk_window_set_title (GTK_WINDOW (fontseldiag), title);
1015 return GTK_WIDGET (fontseldiag);
1019 gtk_font_selection_dialog_get_font_name (GtkFontSelectionDialog *fsd)
1021 return gtk_font_selection_get_font_name (GTK_FONT_SELECTION (fsd->fontsel));
1025 gtk_font_selection_dialog_get_font (GtkFontSelectionDialog *fsd)
1027 return gtk_font_selection_get_font (GTK_FONT_SELECTION (fsd->fontsel));
1031 gtk_font_selection_dialog_set_font_name (GtkFontSelectionDialog *fsd,
1032 const gchar *fontname)
1034 return gtk_font_selection_set_font_name (GTK_FONT_SELECTION (fsd->fontsel), fontname);
1038 gtk_font_selection_dialog_get_preview_text (GtkFontSelectionDialog *fsd)
1040 return gtk_font_selection_get_preview_text (GTK_FONT_SELECTION (fsd->fontsel));
1044 gtk_font_selection_dialog_set_preview_text (GtkFontSelectionDialog *fsd,
1047 gtk_font_selection_set_preview_text (GTK_FONT_SELECTION (fsd->fontsel), text);
1051 /* This turns auto-shrink off if the user resizes the width of the dialog.
1052 It also turns it back on again if the user resizes it back to its normal
1055 gtk_font_selection_dialog_on_configure (GtkWidget *widget,
1056 GdkEventConfigure *event,
1057 GtkFontSelectionDialog *fsd)
1059 /* This sets the initial width. */
1060 if (fsd->dialog_width == -1)
1061 fsd->dialog_width = event->width;
1062 else if (fsd->auto_resize && fsd->dialog_width != event->width)
1064 fsd->auto_resize = FALSE;
1065 gtk_window_set_policy (GTK_WINDOW (fsd), FALSE, TRUE, FALSE);
1067 else if (!fsd->auto_resize && fsd->dialog_width == event->width)
1069 fsd->auto_resize = TRUE;
1070 gtk_window_set_policy (GTK_WINDOW (fsd), FALSE, TRUE, TRUE);