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_expose_list (GtkWidget *w,
126 GdkEventExpose *event,
129 static void gtk_font_selection_preview_changed (GtkWidget *entry,
130 GtkFontSelection *fontsel);
132 /* Misc. utility functions. */
133 static void gtk_font_selection_load_font (GtkFontSelection *fs);
134 static void gtk_font_selection_update_preview (GtkFontSelection *fs);
136 /* FontSelectionDialog */
137 static void gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass);
138 static void gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag);
140 static gint gtk_font_selection_dialog_on_configure(GtkWidget *widget,
141 GdkEventConfigure *event,
142 GtkFontSelectionDialog *fsd);
144 static GtkWindowClass *font_selection_parent_class = NULL;
145 static GtkVBoxClass *font_selection_dialog_parent_class = NULL;
148 gtk_font_selection_get_type()
150 static GtkType font_selection_type = 0;
152 if(!font_selection_type)
154 static const GtkTypeInfo fontsel_type_info =
157 sizeof (GtkFontSelection),
158 sizeof (GtkFontSelectionClass),
159 (GtkClassInitFunc) gtk_font_selection_class_init,
160 (GtkObjectInitFunc) gtk_font_selection_init,
161 /* reserved_1 */ NULL,
162 /* reserved_2 */ NULL,
163 (GtkClassInitFunc) NULL,
166 font_selection_type = gtk_type_unique (GTK_TYPE_VBOX,
170 return font_selection_type;
174 gtk_font_selection_class_init(GtkFontSelectionClass *klass)
176 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
178 font_selection_parent_class = gtk_type_class (GTK_TYPE_VBOX);
180 gobject_class->set_property = gtk_font_selection_set_property;
181 gobject_class->get_property = gtk_font_selection_get_property;
183 g_object_class_install_property (gobject_class,
185 g_param_spec_string ("font_name",
187 _("The X string that represents this font."),
190 g_object_class_install_property (gobject_class,
192 g_param_spec_boxed ("font",
194 _("The GdkFont that is currently selected."),
197 g_object_class_install_property (gobject_class,
199 g_param_spec_string ("preview_text",
201 _("The text to display in order to demonstrate the selected font."),
204 gobject_class->finalize = gtk_font_selection_finalize;
208 gtk_font_selection_set_property (GObject *object,
213 GtkFontSelection *fontsel;
215 fontsel = GTK_FONT_SELECTION (object);
220 gtk_font_selection_set_font_name (fontsel, g_value_get_string (value));
222 case PROP_PREVIEW_TEXT:
223 gtk_font_selection_set_preview_text (fontsel, g_value_get_string (value));
226 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
231 static void gtk_font_selection_get_property (GObject *object,
236 GtkFontSelection *fontsel;
238 fontsel = GTK_FONT_SELECTION (object);
243 g_value_set_string (value, gtk_font_selection_get_font_name (fontsel));
246 g_value_set_object (value, G_OBJECT (gtk_font_selection_get_font (fontsel)));
248 case PROP_PREVIEW_TEXT:
249 g_value_set_string (value, gtk_font_selection_get_preview_text (fontsel));
252 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
259 gtk_font_selection_init(GtkFontSelection *fontsel)
261 GtkWidget *scrolled_win;
262 GtkWidget *text_frame;
264 GtkWidget *table, *label;
266 fontsel->font_desc = pango_font_description_from_string ("sans 12");
268 /* Create the table of font, style & size. */
269 table = gtk_table_new (3, 3, FALSE);
270 gtk_widget_show (table);
271 gtk_table_set_col_spacings(GTK_TABLE(table), 8);
272 gtk_box_pack_start (GTK_BOX (fontsel), table, TRUE, TRUE, 0);
274 fontsel->font_entry = gtk_entry_new ();
275 gtk_entry_set_editable(GTK_ENTRY(fontsel->font_entry), FALSE);
276 gtk_widget_set_usize (fontsel->font_entry, 20, -1);
277 gtk_widget_show (fontsel->font_entry);
278 gtk_table_attach (GTK_TABLE (table), fontsel->font_entry, 0, 1, 1, 2,
281 fontsel->font_style_entry = gtk_entry_new ();
282 gtk_entry_set_editable (GTK_ENTRY(fontsel->font_style_entry), FALSE);
283 gtk_widget_set_usize (fontsel->font_style_entry, 20, -1);
284 gtk_widget_show (fontsel->font_style_entry);
285 gtk_table_attach (GTK_TABLE (table), fontsel->font_style_entry, 1, 2, 1, 2,
288 fontsel->size_entry = gtk_entry_new ();
289 gtk_widget_set_usize (fontsel->size_entry, 20, -1);
290 gtk_widget_show (fontsel->size_entry);
291 gtk_table_attach (GTK_TABLE (table), fontsel->size_entry, 2, 3, 1, 2,
293 gtk_signal_connect (GTK_OBJECT (fontsel->size_entry), "activate",
294 (GtkSignalFunc) gtk_font_selection_size_activate,
297 fontsel->font_label = gtk_label_new_with_mnemonic (_("_Family:"));
298 gtk_label_set_mnemonic_widget (GTK_LABEL (fontsel->font_label),
299 fontsel->font_entry);
300 gtk_misc_set_alignment (GTK_MISC (fontsel->font_label), 0.0, 0.5);
301 gtk_widget_show (fontsel->font_label);
302 gtk_table_attach (GTK_TABLE (table), fontsel->font_label, 0, 1, 0, 1,
304 label = gtk_label_new_with_mnemonic (_("_Style:"));
305 gtk_label_set_mnemonic_widget (GTK_LABEL (label),
306 fontsel->font_style_entry);
307 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
308 gtk_widget_show (label);
309 gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,
311 label = gtk_label_new_with_mnemonic (_("Si_ze:"));
312 gtk_label_set_mnemonic_widget (GTK_LABEL (label),
313 fontsel->size_entry);
314 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
315 gtk_widget_show (label);
316 gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1,
320 /* Create the clists */
321 fontsel->font_clist = gtk_clist_new (1);
322 gtk_clist_column_titles_hide (GTK_CLIST (fontsel->font_clist));
323 gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_clist), 0, TRUE);
324 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
325 gtk_widget_set_usize (scrolled_win, FONT_LIST_WIDTH, FONT_LIST_HEIGHT);
326 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_clist);
327 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
328 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
329 gtk_widget_show(fontsel->font_clist);
330 gtk_widget_show(scrolled_win);
332 gtk_table_attach (GTK_TABLE (table), scrolled_win, 0, 1, 2, 3,
333 GTK_EXPAND | GTK_FILL,
334 GTK_EXPAND | GTK_FILL, 0, 0);
336 fontsel->font_style_clist = gtk_clist_new (1);
337 gtk_clist_column_titles_hide (GTK_CLIST (fontsel->font_style_clist));
338 gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_style_clist),
340 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
341 gtk_widget_set_usize (scrolled_win, FONT_STYLE_LIST_WIDTH, -1);
342 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_style_clist);
343 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
344 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
345 gtk_widget_show(fontsel->font_style_clist);
346 gtk_widget_show(scrolled_win);
347 gtk_table_attach (GTK_TABLE (table), scrolled_win, 1, 2, 2, 3,
348 GTK_EXPAND | GTK_FILL,
349 GTK_EXPAND | GTK_FILL, 0, 0);
351 fontsel->size_clist = gtk_clist_new (1);
352 gtk_clist_column_titles_hide (GTK_CLIST(fontsel->size_clist));
353 gtk_clist_set_column_width (GTK_CLIST(fontsel->size_clist), 0, 20);
354 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
355 gtk_widget_set_usize (scrolled_win, FONT_SIZE_LIST_WIDTH, -1);
356 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->size_clist);
357 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
358 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
359 gtk_widget_show (fontsel->size_clist);
360 gtk_widget_show (scrolled_win);
361 gtk_table_attach (GTK_TABLE (table), scrolled_win, 2, 3, 2, 3,
362 GTK_FILL, GTK_FILL, 0, 0);
364 /* Insert the fonts. If there exist fonts with the same family but
365 different foundries, then the foundry name is appended in brackets. */
366 gtk_font_selection_show_available_fonts(fontsel);
368 gtk_signal_connect (GTK_OBJECT (fontsel->font_clist), "select_row",
369 GTK_SIGNAL_FUNC(gtk_font_selection_select_font),
371 GTK_WIDGET_SET_FLAGS (fontsel->font_clist, GTK_CAN_FOCUS);
373 gtk_signal_connect_after (GTK_OBJECT (fontsel->font_clist), "expose_event",
374 GTK_SIGNAL_FUNC(gtk_font_selection_expose_list),
377 gtk_font_selection_show_available_styles (fontsel);
379 gtk_signal_connect (GTK_OBJECT (fontsel->font_style_clist), "select_row",
380 GTK_SIGNAL_FUNC(gtk_font_selection_select_style),
382 GTK_WIDGET_SET_FLAGS (fontsel->font_style_clist, GTK_CAN_FOCUS);
384 gtk_font_selection_show_available_sizes (fontsel);
386 gtk_signal_connect (GTK_OBJECT (fontsel->size_clist), "select_row",
387 GTK_SIGNAL_FUNC(gtk_font_selection_select_size),
389 GTK_WIDGET_SET_FLAGS (fontsel->size_clist, GTK_CAN_FOCUS);
391 /* create the text entry widget */
392 text_frame = gtk_frame_new (_("Preview:"));
393 gtk_widget_show (text_frame);
394 gtk_frame_set_shadow_type(GTK_FRAME(text_frame), GTK_SHADOW_ETCHED_IN);
395 gtk_box_pack_start (GTK_BOX (fontsel), text_frame,
398 /* This is just used to get a 4-pixel space around the preview entry. */
399 text_box = gtk_hbox_new (FALSE, 0);
400 gtk_widget_show (text_box);
401 gtk_container_add (GTK_CONTAINER (text_frame), text_box);
402 gtk_container_set_border_width (GTK_CONTAINER (text_box), 4);
404 fontsel->preview_entry = gtk_entry_new ();
405 gtk_widget_show (fontsel->preview_entry);
406 gtk_signal_connect (GTK_OBJECT (fontsel->preview_entry), "changed",
407 (GtkSignalFunc) gtk_font_selection_preview_changed,
409 gtk_widget_set_usize (fontsel->preview_entry, -1, INITIAL_PREVIEW_HEIGHT);
410 gtk_box_pack_start (GTK_BOX (text_box), fontsel->preview_entry,
413 gtk_font_selection_update_preview (fontsel);
417 gtk_font_selection_new()
419 GtkFontSelection *fontsel;
421 fontsel = gtk_type_new (GTK_TYPE_FONT_SELECTION);
423 return GTK_WIDGET (fontsel);
427 gtk_font_selection_finalize (GObject *object)
429 GtkFontSelection *fontsel;
431 g_return_if_fail (object != NULL);
432 g_return_if_fail (GTK_IS_FONT_SELECTION (object));
434 fontsel = GTK_FONT_SELECTION (object);
436 pango_font_description_free (fontsel->font_desc);
439 gdk_font_unref (fontsel->font);
441 if (G_OBJECT_CLASS (font_selection_parent_class)->finalize)
442 (* G_OBJECT_CLASS (font_selection_parent_class)->finalize) (object);
446 gtk_font_selection_preview_changed (GtkWidget *entry,
447 GtkFontSelection *fontsel)
449 g_object_notify (G_OBJECT (fontsel), "preview_text");
452 /* This is called when the clist is exposed. Here we scroll to the current
453 font if necessary. */
455 gtk_font_selection_expose_list (GtkWidget *widget,
456 GdkEventExpose *event,
459 GtkFontSelection *fontsel;
464 g_message("In expose_list\n");
466 fontsel = GTK_FONT_SELECTION(data);
468 /* Try to scroll the font family clist to the selected item */
469 selection = GTK_CLIST(fontsel->font_clist)->selection;
472 index = GPOINTER_TO_INT (selection->data);
473 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_clist), index)
474 != GTK_VISIBILITY_FULL)
475 gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), index, -1, 0.5, 0);
478 /* Try to scroll the font style clist to the selected item */
479 selection = GTK_CLIST(fontsel->font_style_clist)->selection;
482 index = GPOINTER_TO_INT (selection->data);
483 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_style_clist), index)
484 != GTK_VISIBILITY_FULL)
485 gtk_clist_moveto(GTK_CLIST(fontsel->font_style_clist), index, -1,
489 /* Try to scroll the font size clist to the selected item */
490 selection = GTK_CLIST(fontsel->size_clist)->selection;
493 index = GPOINTER_TO_INT (selection->data);
494 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->size_clist), index)
495 != GTK_VISIBILITY_FULL)
496 gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), index, -1, 0.5, 0);
500 /* This is called when a family is selected in the list. */
502 gtk_font_selection_select_font (GtkWidget *w,
505 GdkEventButton *bevent,
508 GtkFontSelection *fontsel;
512 fontsel = GTK_FONT_SELECTION (data);
514 if (GTK_CLIST (fontsel->font_clist)->selection)
516 index = GPOINTER_TO_INT (GTK_CLIST (fontsel->font_clist)->selection->data);
518 if (gtk_clist_get_text (GTK_CLIST (fontsel->font_clist), index, 0, &family_name) &&
519 strcasecmp (fontsel->font_desc->family_name, family_name) != 0)
521 g_free (fontsel->font_desc->family_name);
522 fontsel->font_desc->family_name = g_strdup (family_name);
524 gtk_entry_set_text (GTK_ENTRY (fontsel->font_entry), family_name);
526 gtk_font_selection_show_available_styles (fontsel);
527 gtk_font_selection_select_best_style (fontsel, TRUE);
533 cmp_strings (const void *a, const void *b)
535 return strcasecmp (*(const char **)a, *(const char **)b);
539 gtk_font_selection_show_available_fonts (GtkFontSelection *fontsel)
544 pango_context_list_families (gtk_widget_get_pango_context (GTK_WIDGET (fontsel)),
545 &families, &n_families);
546 qsort (families, n_families, sizeof(char *), cmp_strings);
548 gtk_clist_freeze (GTK_CLIST (fontsel->font_clist));
549 gtk_clist_clear (GTK_CLIST (fontsel->font_clist));
551 for (i=0; i<n_families; i++)
553 gtk_clist_append (GTK_CLIST (fontsel->font_clist), &families[i]);
555 if (!strcasecmp (families[i], fontsel->font_desc->family_name))
557 gtk_clist_select_row (GTK_CLIST(fontsel->font_clist), i, 0);
558 gtk_entry_set_text(GTK_ENTRY(fontsel->font_entry), families[i]);
562 gtk_clist_thaw (GTK_CLIST(fontsel->font_clist));
564 pango_font_map_free_families (families, n_families);
568 compare_font_descriptions (const PangoFontDescription *a, const PangoFontDescription *b)
570 int val = strcasecmp (a->family_name, b->family_name);
574 if (a->weight != b->weight)
575 return a->weight - b->weight;
577 if (a->style != b->style)
578 return a->style - b->style;
580 if (a->stretch != b->stretch)
581 return a->stretch - b->stretch;
583 if (a->variant != b->variant)
584 return a->variant - b->variant;
590 font_description_sort_func (const void *a, const void *b)
592 return compare_font_descriptions (*(PangoFontDescription **)a, *(PangoFontDescription **)b);
595 /* This fills the font style clist with all the possible style combinations
596 for the current font family. */
598 gtk_font_selection_show_available_styles (GtkFontSelection *fontsel)
600 PangoFontDescription **descs;
605 pango_context_list_fonts (gtk_widget_get_pango_context (GTK_WIDGET (fontsel)),
606 fontsel->font_desc->family_name, &descs, &n_descs);
607 qsort (descs, n_descs, sizeof(PangoFontDescription *), font_description_sort_func);
609 gtk_clist_freeze (GTK_CLIST (fontsel->font_style_clist));
610 gtk_clist_clear (GTK_CLIST (fontsel->font_style_clist));
612 for (i=0; i<n_descs; i++)
614 PangoFontDescription tmp_desc;
616 tmp_desc = *descs[i];
617 tmp_desc.family_name = NULL;
620 str = pango_font_description_to_string (&tmp_desc);
621 gtk_clist_append (GTK_CLIST (fontsel->font_style_clist), &str);
623 if (descs[i]->weight == fontsel->font_desc->weight &&
624 descs[i]->style == fontsel->font_desc->style &&
625 descs[i]->stretch == fontsel->font_desc->stretch &&
626 descs[i]->variant == fontsel->font_desc->variant)
632 gtk_clist_select_row (GTK_CLIST (fontsel->font_style_clist), match_row, 0);
635 gtk_clist_get_text (GTK_CLIST (fontsel->font_style_clist), match_row, 0, &str);
636 gtk_entry_set_text (GTK_ENTRY (fontsel->font_style_entry), str);
639 gtk_clist_thaw (GTK_CLIST(fontsel->font_style_clist));
641 pango_font_descriptions_free (descs, n_descs);
645 /* This selects a style when the user selects a font. It just uses the first
646 available style at present. I was thinking of trying to maintain the
647 selected style, e.g. bold italic, when the user selects different fonts.
648 However, the interface is so easy to use now I'm not sure it's worth it.
649 Note: This will load a font. */
651 gtk_font_selection_select_best_style(GtkFontSelection *fontsel,
656 gtk_clist_select_row(GTK_CLIST(fontsel->font_style_clist), best_row, 0);
657 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_style_clist), best_row)
658 != GTK_VISIBILITY_FULL)
659 gtk_clist_moveto(GTK_CLIST(fontsel->font_style_clist), best_row, -1,
661 gtk_font_selection_show_available_sizes (fontsel);
662 gtk_font_selection_select_best_size (fontsel);
666 /* This is called when a style is selected in the list. */
668 gtk_font_selection_select_style (GtkWidget *w,
671 GdkEventButton *bevent,
674 GtkFontSelection *fontsel = GTK_FONT_SELECTION (data);
675 PangoFontDescription *tmp_desc;
679 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
680 gtk_widget_grab_focus (w);
682 if (GTK_CLIST (fontsel->font_style_clist)->selection)
684 index = GPOINTER_TO_INT (GTK_CLIST (fontsel->font_style_clist)->selection->data);
686 if (gtk_clist_get_text (GTK_CLIST (fontsel->font_style_clist), index, 0, &text))
688 tmp_desc = pango_font_description_from_string (text);
690 fontsel->font_desc->style = tmp_desc->style;
691 fontsel->font_desc->variant = tmp_desc->variant;
692 fontsel->font_desc->weight = tmp_desc->weight;
693 fontsel->font_desc->stretch = tmp_desc->stretch;
695 pango_font_description_free (tmp_desc);
699 gtk_font_selection_show_available_sizes (fontsel);
700 gtk_font_selection_select_best_size (fontsel);
704 gtk_font_selection_show_available_sizes (GtkFontSelection *fontsel)
710 /* Insert the standard font sizes */
711 gtk_clist_freeze (GTK_CLIST (fontsel->size_clist));
712 gtk_clist_clear (GTK_CLIST (fontsel->size_clist));
714 for (i = 0; i < G_N_ELEMENTS (font_sizes); i++)
716 sprintf(buffer, "%i", font_sizes[i]);
718 gtk_clist_append (GTK_CLIST(fontsel->size_clist), &size);
719 if (font_sizes[i] * PANGO_SCALE == fontsel->font_desc->size)
720 gtk_clist_select_row(GTK_CLIST(fontsel->size_clist), i, 0);
722 gtk_clist_thaw (GTK_CLIST(fontsel->size_clist));
724 sprintf (buffer, "%i", fontsel->font_desc->size / PANGO_SCALE);
725 gtk_entry_set_text (GTK_ENTRY(fontsel->size_entry), buffer);
729 gtk_font_selection_select_best_size (GtkFontSelection *fontsel)
731 gtk_font_selection_load_font (fontsel);
734 /* If the user hits return in the font size entry, we change to the new font
737 gtk_font_selection_size_activate (GtkWidget *w,
740 GtkFontSelection *fontsel;
744 fontsel = GTK_FONT_SELECTION (data);
746 text = gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry));
747 new_size = atoi (text) * PANGO_SCALE;
749 if (fontsel->font_desc->size != new_size)
751 fontsel->font_desc->size = new_size;
752 gtk_font_selection_load_font (fontsel);
756 /* This is called when a size is selected in the list. */
758 gtk_font_selection_select_size (GtkWidget *w,
761 GdkEventButton *bevent,
764 GtkFontSelection *fontsel;
768 fontsel = GTK_FONT_SELECTION (data);
770 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
771 gtk_widget_grab_focus (w);
773 gtk_clist_get_text(GTK_CLIST(fontsel->size_clist), row, 0, &text);
774 new_size = atoi (text) * PANGO_SCALE;
776 if (fontsel->font_desc->size != new_size)
778 /* If the size was selected by the user we set the selected_size. */
779 fontsel->font_desc->size = new_size;
781 gtk_font_selection_load_font (fontsel);
786 gtk_font_selection_load_font (GtkFontSelection *fontsel)
789 gdk_font_unref (fontsel->font);
790 fontsel->font = NULL;
792 gtk_font_selection_update_preview (fontsel);
795 /* This sets the font in the preview entry to the selected font, and tries to
796 make sure that the preview entry is a reasonable size, i.e. so that the
797 text can be seen with a bit of space to spare. But it tries to avoid
798 resizing the entry every time the font changes.
799 This also used to shrink the preview if the font size was decreased, but
800 that made it awkward if the user wanted to resize the window themself. */
802 gtk_font_selection_update_preview (GtkFontSelection *fontsel)
804 GtkRcStyle *rc_style;
806 GtkRequisition old_requisition;
807 GtkWidget *preview_entry = fontsel->preview_entry;
810 gtk_widget_get_child_requisition (preview_entry, &old_requisition);
812 rc_style = gtk_rc_style_new ();
813 rc_style->font_desc = pango_font_description_copy (fontsel->font_desc);
814 gtk_widget_modify_style (preview_entry, rc_style);
815 gtk_rc_style_unref (rc_style);
817 gtk_widget_size_request (preview_entry, NULL);
819 /* We don't ever want to be over MAX_PREVIEW_HEIGHT pixels high. */
820 new_height = CLAMP (preview_entry->requisition.height, INITIAL_PREVIEW_HEIGHT, MAX_PREVIEW_HEIGHT);
822 if (new_height > old_requisition.height || new_height < old_requisition.height - 30)
823 gtk_widget_set_usize(preview_entry, -1, new_height);
825 /* This sets the preview text, if it hasn't been set already. */
826 text = gtk_entry_get_text(GTK_ENTRY(preview_entry));
827 if (strlen(text) == 0)
828 gtk_entry_set_text(GTK_ENTRY(preview_entry), PREVIEW_TEXT);
829 gtk_entry_set_position(GTK_ENTRY(preview_entry), 0);
832 /*****************************************************************************
833 * These functions are the main public interface for getting/setting the font.
834 *****************************************************************************/
837 gtk_font_selection_get_font (GtkFontSelection *fontsel)
840 fontsel->font = gdk_font_from_description (fontsel->font_desc);
842 return fontsel->font;
847 gtk_font_selection_get_font_name (GtkFontSelection *fontsel)
849 return pango_font_description_to_string (fontsel->font_desc);
853 /* This sets the current font, selecting the appropriate clist rows.
854 First we check the fontname is valid and try to find the font family
855 - i.e. the name in the main list. If we can't find that, then just return.
856 Next we try to set each of the properties according to the fontname.
857 Finally we select the font family & style in the clists. */
859 gtk_font_selection_set_font_name (GtkFontSelection *fontsel,
860 const gchar *fontname)
862 PangoFontDescription *new_desc;
863 PangoFontDescription **descs;
865 gboolean found = FALSE;
867 g_return_val_if_fail (fontsel != NULL, FALSE);
868 g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), FALSE);
870 new_desc = pango_font_description_from_string (fontname);
872 /* Check to make sure that this is in the list of allowed fonts */
874 pango_context_list_fonts (gtk_widget_get_pango_context (GTK_WIDGET (fontsel)),
875 new_desc->family_name, &descs, &n_descs);
877 for (i=0; i<n_descs; i++)
879 if (descs[i]->weight == new_desc->weight &&
880 descs[i]->style == new_desc->style &&
881 descs[i]->stretch == new_desc->stretch &&
882 descs[i]->variant == new_desc->variant)
889 pango_font_descriptions_free (descs, n_descs);
894 pango_font_description_free (fontsel->font_desc);
895 fontsel->font_desc = new_desc;
897 g_object_notify (G_OBJECT (fontsel), "font_name");
898 g_object_notify (G_OBJECT (fontsel), "font");
903 /* This returns the text in the preview entry. You should copy the returned
904 text if you need it. */
906 gtk_font_selection_get_preview_text (GtkFontSelection *fontsel)
908 return gtk_entry_get_text (GTK_ENTRY (fontsel->preview_entry));
912 /* This sets the text in the preview entry. */
914 gtk_font_selection_set_preview_text (GtkFontSelection *fontsel,
917 gtk_entry_set_text (GTK_ENTRY (fontsel->preview_entry), text);
920 /*****************************************************************************
921 * GtkFontSelectionDialog
922 *****************************************************************************/
925 gtk_font_selection_dialog_get_type (void)
927 static guint font_selection_dialog_type = 0;
929 if (!font_selection_dialog_type)
931 GtkTypeInfo fontsel_diag_info =
933 "GtkFontSelectionDialog",
934 sizeof (GtkFontSelectionDialog),
935 sizeof (GtkFontSelectionDialogClass),
936 (GtkClassInitFunc) gtk_font_selection_dialog_class_init,
937 (GtkObjectInitFunc) gtk_font_selection_dialog_init,
938 /* reserved_1 */ NULL,
939 /* reserved_2 */ NULL,
940 (GtkClassInitFunc) NULL,
943 font_selection_dialog_type = gtk_type_unique (GTK_TYPE_DIALOG,
947 return font_selection_dialog_type;
951 gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass)
953 GtkObjectClass *object_class;
955 object_class = (GtkObjectClass*) klass;
957 font_selection_dialog_parent_class = gtk_type_class (GTK_TYPE_DIALOG);
961 gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag)
965 dialog = GTK_DIALOG (fontseldiag);
967 fontseldiag->dialog_width = -1;
968 fontseldiag->auto_resize = TRUE;
970 gtk_widget_set_events(GTK_WIDGET(fontseldiag), GDK_STRUCTURE_MASK);
971 gtk_signal_connect (GTK_OBJECT (fontseldiag), "configure_event",
972 (GtkSignalFunc) gtk_font_selection_dialog_on_configure,
975 gtk_container_set_border_width (GTK_CONTAINER (fontseldiag), 4);
976 gtk_window_set_policy(GTK_WINDOW(fontseldiag), FALSE, TRUE, TRUE);
978 fontseldiag->main_vbox = dialog->vbox;
980 fontseldiag->fontsel = gtk_font_selection_new();
981 gtk_container_set_border_width (GTK_CONTAINER (fontseldiag->fontsel), 4);
982 gtk_widget_show (fontseldiag->fontsel);
983 gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox),
984 fontseldiag->fontsel, TRUE, TRUE, 0);
986 /* Create the action area */
987 fontseldiag->action_area = dialog->action_area;
989 fontseldiag->ok_button = gtk_dialog_add_button (dialog,
992 gtk_widget_grab_default (fontseldiag->ok_button);
994 fontseldiag->apply_button = gtk_dialog_add_button (dialog,
995 GTK_STOCK_BUTTON_APPLY,
997 gtk_widget_hide (fontseldiag->apply_button);
1000 fontseldiag->cancel_button = gtk_dialog_add_button (dialog,
1001 GTK_STOCK_BUTTON_CANCEL,
1002 GTK_RESPONSE_CANCEL);
1004 gtk_window_set_title (GTK_WINDOW (fontseldiag),
1005 _("Font Selection"));
1010 gtk_font_selection_dialog_new (const gchar *title)
1012 GtkFontSelectionDialog *fontseldiag;
1014 fontseldiag = gtk_type_new (GTK_TYPE_FONT_SELECTION_DIALOG);
1017 gtk_window_set_title (GTK_WINDOW (fontseldiag), title);
1019 return GTK_WIDGET (fontseldiag);
1023 gtk_font_selection_dialog_get_font_name (GtkFontSelectionDialog *fsd)
1025 return gtk_font_selection_get_font_name(GTK_FONT_SELECTION(fsd->fontsel));
1029 gtk_font_selection_dialog_get_font (GtkFontSelectionDialog *fsd)
1031 return gtk_font_selection_get_font(GTK_FONT_SELECTION(fsd->fontsel));
1035 gtk_font_selection_dialog_set_font_name (GtkFontSelectionDialog *fsd,
1036 const gchar *fontname)
1038 return gtk_font_selection_set_font_name(GTK_FONT_SELECTION(fsd->fontsel),
1043 gtk_font_selection_dialog_get_preview_text (GtkFontSelectionDialog *fsd)
1045 return gtk_font_selection_get_preview_text(GTK_FONT_SELECTION(fsd->fontsel));
1049 gtk_font_selection_dialog_set_preview_text (GtkFontSelectionDialog *fsd,
1052 gtk_font_selection_set_preview_text(GTK_FONT_SELECTION(fsd->fontsel), text);
1056 /* This turns auto-shrink off if the user resizes the width of the dialog.
1057 It also turns it back on again if the user resizes it back to its normal
1060 gtk_font_selection_dialog_on_configure (GtkWidget *widget,
1061 GdkEventConfigure *event,
1062 GtkFontSelectionDialog *fsd)
1064 /* This sets the initial width. */
1065 if (fsd->dialog_width == -1)
1066 fsd->dialog_width = event->width;
1067 else if (fsd->auto_resize && fsd->dialog_width != event->width)
1069 fsd->auto_resize = FALSE;
1070 gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, FALSE);
1072 else if (!fsd->auto_resize && fsd->dialog_width == event->width)
1074 fsd->auto_resize = TRUE;
1075 gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, TRUE);