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/.
34 #include <glib/gprintf.h>
40 #include "gdk/gdkkeysyms.h"
42 #include "gtkfontsel.h"
44 #include "gtkbutton.h"
45 #include "gtkcellrenderertext.h"
51 #include "gtkliststore.h"
55 #include "gtktreeselection.h"
56 #include "gtktreeview.h"
58 #include "gtkscrolledwindow.h"
60 #include "gtkaccessible.h"
61 #include "gtkprivate.h"
64 /* We don't enable the font and style entries because they don't add
65 * much in terms of visible effect and have a weird effect on keynav.
66 * the Windows font selector has entries similarly positioned but they
67 * act in conjunction with the associated lists to form a single focus
70 #undef INCLUDE_FONT_ENTRIES
72 /* This is the default text shown in the preview entry, though the user
73 can set it. Remember that some fonts only have capital letters. */
74 #define PREVIEW_TEXT N_("abcdefghijk ABCDEFGHIJK")
76 /* This is the initial and maximum height of the preview entry (it expands
77 when large font sizes are selected). Initial height is also the minimum. */
78 #define INITIAL_PREVIEW_HEIGHT 44
79 #define MAX_PREVIEW_HEIGHT 300
81 /* These are the sizes of the font, style & size lists. */
82 #define FONT_LIST_HEIGHT 136
83 #define FONT_LIST_WIDTH 190
84 #define FONT_STYLE_LIST_WIDTH 170
85 #define FONT_SIZE_LIST_WIDTH 60
87 /* These are what we use as the standard font sizes, for the size list.
89 static const guint16 font_sizes[] = {
90 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 26, 28,
91 32, 36, 40, 48, 56, 64, 72
116 static void gtk_font_selection_class_init (GtkFontSelectionClass *klass);
117 static void gtk_font_selection_set_property (GObject *object,
121 static void gtk_font_selection_get_property (GObject *object,
125 static void gtk_font_selection_init (GtkFontSelection *fontsel);
126 static void gtk_font_selection_finalize (GObject *object);
127 static void gtk_font_selection_screen_changed (GtkWidget *widget,
128 GdkScreen *previous_screen);
130 /* These are the callbacks & related functions. */
131 static void gtk_font_selection_select_font (GtkTreeSelection *selection,
133 static void gtk_font_selection_show_available_fonts (GtkFontSelection *fs);
135 static void gtk_font_selection_show_available_styles (GtkFontSelection *fs);
136 static void gtk_font_selection_select_best_style (GtkFontSelection *fs,
138 static void gtk_font_selection_select_style (GtkTreeSelection *selection,
141 static void gtk_font_selection_select_best_size (GtkFontSelection *fs);
142 static void gtk_font_selection_show_available_sizes (GtkFontSelection *fs,
143 gboolean first_time);
144 static void gtk_font_selection_size_activate (GtkWidget *w,
146 static gboolean gtk_font_selection_size_focus_out (GtkWidget *w,
147 GdkEventFocus *event,
149 static void gtk_font_selection_select_size (GtkTreeSelection *selection,
152 static void gtk_font_selection_scroll_on_map (GtkWidget *w,
155 static void gtk_font_selection_preview_changed (GtkWidget *entry,
156 GtkFontSelection *fontsel);
158 /* Misc. utility functions. */
159 static void gtk_font_selection_load_font (GtkFontSelection *fs);
160 static void gtk_font_selection_update_preview (GtkFontSelection *fs);
162 static GdkFont* gtk_font_selection_get_font_internal (GtkFontSelection *fontsel);
164 /* FontSelectionDialog */
165 static void gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass);
166 static void gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag);
168 static GtkVBoxClass *font_selection_parent_class = NULL;
169 static GtkWindowClass *font_selection_dialog_parent_class = NULL;
173 gtk_font_selection_get_type (void)
175 static GType font_selection_type = 0;
177 if (!font_selection_type)
179 static const GTypeInfo fontsel_type_info =
181 sizeof (GtkFontSelectionClass),
182 NULL, /* base_init */
183 NULL, /* base_finalize */
184 (GClassInitFunc) gtk_font_selection_class_init,
185 NULL, /* class_finalize */
186 NULL, /* class_data */
187 sizeof (GtkFontSelection),
189 (GInstanceInitFunc) gtk_font_selection_init,
192 font_selection_type =
193 g_type_register_static (GTK_TYPE_VBOX, I_("GtkFontSelection"),
194 &fontsel_type_info, 0);
197 return font_selection_type;
201 gtk_font_selection_class_init (GtkFontSelectionClass *klass)
203 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
204 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
206 font_selection_parent_class = g_type_class_peek_parent (klass);
208 gobject_class->set_property = gtk_font_selection_set_property;
209 gobject_class->get_property = gtk_font_selection_get_property;
211 widget_class->screen_changed = gtk_font_selection_screen_changed;
213 g_object_class_install_property (gobject_class,
215 g_param_spec_string ("font-name",
217 P_("The X string that represents this font"),
219 GTK_PARAM_READWRITE));
220 g_object_class_install_property (gobject_class,
222 g_param_spec_boxed ("font",
224 P_("The GdkFont that is currently selected"),
226 GTK_PARAM_READABLE));
227 g_object_class_install_property (gobject_class,
229 g_param_spec_string ("preview-text",
231 P_("The text to display in order to demonstrate the selected font"),
233 GTK_PARAM_READWRITE));
234 gobject_class->finalize = gtk_font_selection_finalize;
238 gtk_font_selection_set_property (GObject *object,
243 GtkFontSelection *fontsel;
245 fontsel = GTK_FONT_SELECTION (object);
250 gtk_font_selection_set_font_name (fontsel, g_value_get_string (value));
252 case PROP_PREVIEW_TEXT:
253 gtk_font_selection_set_preview_text (fontsel, g_value_get_string (value));
256 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
261 static void gtk_font_selection_get_property (GObject *object,
266 GtkFontSelection *fontsel;
268 fontsel = GTK_FONT_SELECTION (object);
273 g_value_set_string (value, gtk_font_selection_get_font_name (fontsel));
276 g_value_set_object (value, gtk_font_selection_get_font_internal (fontsel));
278 case PROP_PREVIEW_TEXT:
279 g_value_set_string (value, gtk_font_selection_get_preview_text (fontsel));
282 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
287 /* Handles key press events on the lists, so that we can trap Enter to
288 * activate the default button on our own.
291 list_row_activated (GtkWidget *widget)
295 window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (widget)));
296 if (!GTK_WIDGET_TOPLEVEL (window))
300 && widget != window->default_widget
301 && !(widget == window->focus_widget &&
302 (!window->default_widget || !GTK_WIDGET_SENSITIVE (window->default_widget))))
304 gtk_window_activate_default (window);
311 gtk_font_selection_init (GtkFontSelection *fontsel)
313 GtkWidget *scrolled_win;
314 GtkWidget *text_frame;
316 GtkWidget *table, *label;
317 GtkWidget *font_label, *style_label;
319 GtkTreeViewColumn *column;
320 GList *focus_chain = NULL;
323 gtk_widget_push_composite_child ();
325 fontsel->size = 12 * PANGO_SCALE;
327 /* Create the table of font, style & size. */
328 table = gtk_table_new (3, 3, FALSE);
329 gtk_widget_show (table);
330 gtk_table_set_col_spacings (GTK_TABLE (table), 8);
331 gtk_box_pack_start (GTK_BOX (fontsel), table, TRUE, TRUE, 0);
333 #ifdef INCLUDE_FONT_ENTRIES
334 fontsel->font_entry = gtk_entry_new ();
335 gtk_editable_set_editable (GTK_EDITABLE (fontsel->font_entry), FALSE);
336 gtk_widget_set_size_request (fontsel->font_entry, 20, -1);
337 gtk_widget_show (fontsel->font_entry);
338 gtk_table_attach (GTK_TABLE (table), fontsel->font_entry, 0, 1, 1, 2,
341 fontsel->font_style_entry = gtk_entry_new ();
342 gtk_editable_set_editable (GTK_EDITABLE (fontsel->font_style_entry), FALSE);
343 gtk_widget_set_size_request (fontsel->font_style_entry, 20, -1);
344 gtk_widget_show (fontsel->font_style_entry);
345 gtk_table_attach (GTK_TABLE (table), fontsel->font_style_entry, 1, 2, 1, 2,
347 #endif /* INCLUDE_FONT_ENTRIES */
349 fontsel->size_entry = gtk_entry_new ();
350 gtk_widget_set_size_request (fontsel->size_entry, 20, -1);
351 gtk_widget_show (fontsel->size_entry);
352 gtk_table_attach (GTK_TABLE (table), fontsel->size_entry, 2, 3, 1, 2,
354 g_signal_connect (fontsel->size_entry, "activate",
355 G_CALLBACK (gtk_font_selection_size_activate),
357 g_signal_connect_after (fontsel->size_entry, "focus_out_event",
358 G_CALLBACK (gtk_font_selection_size_focus_out),
361 font_label = gtk_label_new_with_mnemonic (_("_Family:"));
362 gtk_misc_set_alignment (GTK_MISC (font_label), 0.0, 0.5);
363 gtk_widget_show (font_label);
364 gtk_table_attach (GTK_TABLE (table), font_label, 0, 1, 0, 1,
367 style_label = gtk_label_new_with_mnemonic (_("_Style:"));
368 gtk_misc_set_alignment (GTK_MISC (style_label), 0.0, 0.5);
369 gtk_widget_show (style_label);
370 gtk_table_attach (GTK_TABLE (table), style_label, 1, 2, 0, 1,
373 label = gtk_label_new_with_mnemonic (_("Si_ze:"));
374 gtk_label_set_mnemonic_widget (GTK_LABEL (label),
375 fontsel->size_entry);
376 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
377 gtk_widget_show (label);
378 gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1,
382 /* Create the lists */
384 model = gtk_list_store_new (2,
385 G_TYPE_OBJECT, /* FAMILY_COLUMN */
386 G_TYPE_STRING); /* FAMILY_NAME_COLUMN */
387 fontsel->family_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
388 g_object_unref (model);
390 g_signal_connect (fontsel->family_list, "row-activated",
391 G_CALLBACK (list_row_activated), fontsel);
393 column = gtk_tree_view_column_new_with_attributes ("Family",
394 gtk_cell_renderer_text_new (),
395 "text", FAMILY_NAME_COLUMN,
397 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
398 gtk_tree_view_append_column (GTK_TREE_VIEW (fontsel->family_list), column);
400 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (fontsel->family_list), FALSE);
401 gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (fontsel->family_list)),
402 GTK_SELECTION_BROWSE);
404 gtk_label_set_mnemonic_widget (GTK_LABEL (font_label), fontsel->family_list);
406 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
407 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win), GTK_SHADOW_IN);
408 gtk_widget_set_size_request (scrolled_win,
409 FONT_LIST_WIDTH, FONT_LIST_HEIGHT);
410 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->family_list);
411 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
412 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
413 gtk_widget_show (fontsel->family_list);
414 gtk_widget_show (scrolled_win);
416 gtk_table_attach (GTK_TABLE (table), scrolled_win, 0, 1, 1, 3,
417 GTK_EXPAND | GTK_FILL,
418 GTK_EXPAND | GTK_FILL, 0, 0);
419 focus_chain = g_list_append (focus_chain, scrolled_win);
421 model = gtk_list_store_new (2,
422 G_TYPE_OBJECT, /* FACE_COLUMN */
423 G_TYPE_STRING); /* FACE_NAME_COLUMN */
424 fontsel->face_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
425 g_object_unref (model);
426 g_signal_connect (fontsel->face_list, "row-activated",
427 G_CALLBACK (list_row_activated), fontsel);
429 gtk_label_set_mnemonic_widget (GTK_LABEL (style_label), fontsel->face_list);
431 column = gtk_tree_view_column_new_with_attributes ("Face",
432 gtk_cell_renderer_text_new (),
433 "text", FACE_NAME_COLUMN,
435 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
436 gtk_tree_view_append_column (GTK_TREE_VIEW (fontsel->face_list), column);
438 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (fontsel->face_list), FALSE);
439 gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (fontsel->face_list)),
440 GTK_SELECTION_BROWSE);
442 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
443 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win), GTK_SHADOW_IN);
444 gtk_widget_set_size_request (scrolled_win,
445 FONT_STYLE_LIST_WIDTH, FONT_LIST_HEIGHT);
446 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->face_list);
447 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
448 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
449 gtk_widget_show (fontsel->face_list);
450 gtk_widget_show (scrolled_win);
451 gtk_table_attach (GTK_TABLE (table), scrolled_win, 1, 2, 1, 3,
452 GTK_EXPAND | GTK_FILL,
453 GTK_EXPAND | GTK_FILL, 0, 0);
454 focus_chain = g_list_append (focus_chain, scrolled_win);
456 focus_chain = g_list_append (focus_chain, fontsel->size_entry);
458 model = gtk_list_store_new (1, G_TYPE_INT);
459 fontsel->size_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
460 g_object_unref (model);
461 g_signal_connect (fontsel->size_list, "row-activated",
462 G_CALLBACK (list_row_activated), fontsel);
464 column = gtk_tree_view_column_new_with_attributes ("Size",
465 gtk_cell_renderer_text_new (),
468 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
469 gtk_tree_view_append_column (GTK_TREE_VIEW (fontsel->size_list), column);
471 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (fontsel->size_list), FALSE);
472 gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (fontsel->size_list)),
473 GTK_SELECTION_BROWSE);
475 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
476 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win), GTK_SHADOW_IN);
477 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->size_list);
478 gtk_widget_set_size_request (scrolled_win, -1, FONT_LIST_HEIGHT);
479 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
480 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
481 gtk_widget_show (fontsel->size_list);
482 gtk_widget_show (scrolled_win);
483 gtk_table_attach (GTK_TABLE (table), scrolled_win, 2, 3, 2, 3,
484 GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
485 focus_chain = g_list_append (focus_chain, scrolled_win);
487 gtk_container_set_focus_chain (GTK_CONTAINER (table), focus_chain);
488 g_list_free (focus_chain);
490 /* Insert the fonts. */
491 g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (fontsel->family_list)), "changed",
492 G_CALLBACK (gtk_font_selection_select_font), fontsel);
494 g_signal_connect_after (fontsel->family_list, "map",
495 G_CALLBACK (gtk_font_selection_scroll_on_map),
498 g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (fontsel->face_list)), "changed",
499 G_CALLBACK (gtk_font_selection_select_style), fontsel);
501 g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (fontsel->size_list)), "changed",
502 G_CALLBACK (gtk_font_selection_select_size), fontsel);
503 atk_obj = gtk_widget_get_accessible (fontsel->size_list);
504 if (GTK_IS_ACCESSIBLE (atk_obj))
506 /* Accessibility support is enabled.
507 * Make the label ATK_RELATON_LABEL_FOR for the size list as well.
509 AtkObject *atk_label;
510 AtkRelationSet *relation_set;
511 AtkRelation *relation;
512 AtkObject *obj_array[1];
515 atk_label = gtk_widget_get_accessible (label);
516 relation_set = atk_object_ref_relation_set (atk_obj);
517 relation = atk_relation_set_get_relation_by_type (relation_set, ATK_RELATION_LABELLED_BY);
520 array = atk_relation_get_target (relation);
521 g_ptr_array_add (array, atk_label);
525 obj_array[0] = atk_label;
526 relation = atk_relation_new (obj_array, 1, ATK_RELATION_LABELLED_BY);
527 atk_relation_set_add (relation_set, relation);
529 g_object_unref (relation_set);
531 relation_set = atk_object_ref_relation_set (atk_label);
532 relation = atk_relation_set_get_relation_by_type (relation_set, ATK_RELATION_LABEL_FOR);
535 array = atk_relation_get_target (relation);
536 g_ptr_array_add (array, atk_obj);
540 obj_array[0] = atk_obj;
541 relation = atk_relation_new (obj_array, 1, ATK_RELATION_LABEL_FOR);
542 atk_relation_set_add (relation_set, relation);
544 g_object_unref (relation_set);
548 /* create the text entry widget */
549 label = gtk_label_new_with_mnemonic (_("_Preview:"));
550 gtk_widget_show (label);
552 text_frame = gtk_frame_new (NULL);
553 gtk_frame_set_label_widget (GTK_FRAME (text_frame), label);
555 gtk_widget_show (text_frame);
556 gtk_frame_set_shadow_type (GTK_FRAME (text_frame), GTK_SHADOW_ETCHED_IN);
557 gtk_box_pack_start (GTK_BOX (fontsel), text_frame,
560 /* This is just used to get a 4-pixel space around the preview entry. */
561 text_box = gtk_hbox_new (FALSE, 0);
562 gtk_widget_show (text_box);
563 gtk_container_add (GTK_CONTAINER (text_frame), text_box);
564 gtk_container_set_border_width (GTK_CONTAINER (text_box), 4);
566 fontsel->preview_entry = gtk_entry_new ();
567 gtk_label_set_mnemonic_widget (GTK_LABEL (label), fontsel->preview_entry);
569 gtk_widget_show (fontsel->preview_entry);
570 g_signal_connect (fontsel->preview_entry, "changed",
571 G_CALLBACK (gtk_font_selection_preview_changed), fontsel);
572 gtk_widget_set_size_request (fontsel->preview_entry,
573 -1, INITIAL_PREVIEW_HEIGHT);
574 gtk_box_pack_start (GTK_BOX (text_box), fontsel->preview_entry,
577 gtk_widget_pop_composite_child();
581 gtk_font_selection_new (void)
583 GtkFontSelection *fontsel;
585 fontsel = g_object_new (GTK_TYPE_FONT_SELECTION, NULL);
587 return GTK_WIDGET (fontsel);
591 gtk_font_selection_finalize (GObject *object)
593 GtkFontSelection *fontsel;
595 g_return_if_fail (GTK_IS_FONT_SELECTION (object));
597 fontsel = GTK_FONT_SELECTION (object);
600 gdk_font_unref (fontsel->font);
602 (* G_OBJECT_CLASS (font_selection_parent_class)->finalize) (object);
606 gtk_font_selection_screen_changed (GtkWidget *widget,
607 GdkScreen *previous_screen)
609 GtkFontSelection *fontsel = GTK_FONT_SELECTION (widget);
611 if (gtk_widget_has_screen (GTK_WIDGET (fontsel)))
613 gtk_font_selection_show_available_fonts (fontsel);
614 gtk_font_selection_show_available_sizes (fontsel, TRUE);
615 gtk_font_selection_show_available_styles (fontsel);
620 gtk_font_selection_preview_changed (GtkWidget *entry,
621 GtkFontSelection *fontsel)
623 g_object_notify (G_OBJECT (fontsel), "preview_text");
627 scroll_to_selection (GtkTreeView *tree_view)
629 GtkTreeSelection *selection = gtk_tree_view_get_selection (tree_view);
633 if (gtk_tree_selection_get_selected (selection, &model, &iter))
635 GtkTreePath *path = gtk_tree_model_get_path (model, &iter);
636 gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5, 0.5);
637 gtk_tree_path_free (path);
642 set_cursor_to_iter (GtkTreeView *view,
645 GtkTreeModel *model = gtk_tree_view_get_model (view);
646 GtkTreePath *path = gtk_tree_model_get_path (model, iter);
648 gtk_tree_view_set_cursor (view, path, NULL, FALSE);
650 gtk_tree_path_free (path);
653 /* This is called when the list is mapped. Here we scroll to the current
654 font if necessary. */
656 gtk_font_selection_scroll_on_map (GtkWidget *widget,
659 GtkFontSelection *fontsel;
662 g_message ("In expose_list\n");
664 fontsel = GTK_FONT_SELECTION (data);
666 /* Try to scroll the font family list to the selected item */
667 scroll_to_selection (GTK_TREE_VIEW (fontsel->family_list));
669 /* Try to scroll the font family list to the selected item */
670 scroll_to_selection (GTK_TREE_VIEW (fontsel->face_list));
672 /* Try to scroll the font family list to the selected item */
673 scroll_to_selection (GTK_TREE_VIEW (fontsel->size_list));
676 /* This is called when a family is selected in the list. */
678 gtk_font_selection_select_font (GtkTreeSelection *selection,
681 GtkFontSelection *fontsel;
684 #ifdef INCLUDE_FONT_ENTRIES
685 const gchar *family_name;
688 fontsel = GTK_FONT_SELECTION (data);
690 if (gtk_tree_selection_get_selected (selection, &model, &iter))
692 PangoFontFamily *family;
694 gtk_tree_model_get (model, &iter, FAMILY_COLUMN, &family, -1);
695 if (fontsel->family != family)
697 fontsel->family = family;
699 #ifdef INCLUDE_FONT_ENTRIES
700 family_name = pango_font_family_get_name (fontsel->family);
701 gtk_entry_set_text (GTK_ENTRY (fontsel->font_entry), family_name);
704 gtk_font_selection_show_available_styles (fontsel);
705 gtk_font_selection_select_best_style (fontsel, TRUE);
708 g_object_unref (family);
713 cmp_families (const void *a, const void *b)
715 const char *a_name = pango_font_family_get_name (*(PangoFontFamily **)a);
716 const char *b_name = pango_font_family_get_name (*(PangoFontFamily **)b);
718 return g_utf8_collate (a_name, b_name);
722 gtk_font_selection_show_available_fonts (GtkFontSelection *fontsel)
725 PangoFontFamily **families;
726 PangoFontFamily *match_family = NULL;
728 GtkTreeIter match_row;
730 model = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (fontsel->family_list)));
732 pango_context_list_families (gtk_widget_get_pango_context (GTK_WIDGET (fontsel)),
733 &families, &n_families);
734 qsort (families, n_families, sizeof (PangoFontFamily *), cmp_families);
736 gtk_list_store_clear (model);
738 for (i=0; i<n_families; i++)
740 const gchar *name = pango_font_family_get_name (families[i]);
743 gtk_list_store_append (model, &iter);
744 gtk_list_store_set (model, &iter,
745 FAMILY_COLUMN, families[i],
746 FAMILY_NAME_COLUMN, name,
749 if (i == 0 || !g_ascii_strcasecmp (name, "sans"))
751 match_family = families[i];
756 fontsel->family = match_family;
759 set_cursor_to_iter (GTK_TREE_VIEW (fontsel->family_list), &match_row);
760 #ifdef INCLUDE_FONT_ENTRIES
761 gtk_entry_set_text (GTK_ENTRY (fontsel->font_entry),
762 pango_font_family_get_name (match_family));
763 #endif /* INCLUDE_FONT_ENTRIES */
770 compare_font_descriptions (const PangoFontDescription *a, const PangoFontDescription *b)
772 int val = strcmp (pango_font_description_get_family (a), pango_font_description_get_family (b));
776 if (pango_font_description_get_weight (a) != pango_font_description_get_weight (b))
777 return pango_font_description_get_weight (a) - pango_font_description_get_weight (b);
779 if (pango_font_description_get_style (a) != pango_font_description_get_style (b))
780 return pango_font_description_get_style (a) - pango_font_description_get_style (b);
782 if (pango_font_description_get_stretch (a) != pango_font_description_get_stretch (b))
783 return pango_font_description_get_stretch (a) - pango_font_description_get_stretch (b);
785 if (pango_font_description_get_variant (a) != pango_font_description_get_variant (b))
786 return pango_font_description_get_variant (a) - pango_font_description_get_variant (b);
792 faces_sort_func (const void *a, const void *b)
794 PangoFontDescription *desc_a = pango_font_face_describe (*(PangoFontFace **)a);
795 PangoFontDescription *desc_b = pango_font_face_describe (*(PangoFontFace **)b);
797 int ord = compare_font_descriptions (desc_a, desc_b);
799 pango_font_description_free (desc_a);
800 pango_font_description_free (desc_b);
806 font_description_style_equal (const PangoFontDescription *a,
807 const PangoFontDescription *b)
809 return (pango_font_description_get_weight (a) == pango_font_description_get_weight (b) &&
810 pango_font_description_get_style (a) == pango_font_description_get_style (b) &&
811 pango_font_description_get_stretch (a) == pango_font_description_get_stretch (b) &&
812 pango_font_description_get_variant (a) == pango_font_description_get_variant (b));
815 /* This fills the font style list with all the possible style combinations
816 for the current font family. */
818 gtk_font_selection_show_available_styles (GtkFontSelection *fontsel)
821 PangoFontFace **faces;
822 PangoFontDescription *old_desc;
824 GtkTreeIter match_row;
825 PangoFontFace *match_face = NULL;
827 model = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (fontsel->face_list)));
830 old_desc = pango_font_face_describe (fontsel->face);
834 pango_font_family_list_faces (fontsel->family, &faces, &n_faces);
835 qsort (faces, n_faces, sizeof (PangoFontFace *), faces_sort_func);
837 gtk_list_store_clear (model);
839 for (i=0; i < n_faces; i++)
842 const gchar *str = pango_font_face_get_face_name (faces[i]);
844 gtk_list_store_append (model, &iter);
845 gtk_list_store_set (model, &iter,
846 FACE_COLUMN, faces[i],
847 FACE_NAME_COLUMN, str,
853 match_face = faces[i];
857 PangoFontDescription *tmp_desc = pango_font_face_describe (faces[i]);
859 if (font_description_style_equal (tmp_desc, old_desc))
862 match_face = faces[i];
865 pango_font_description_free (tmp_desc);
870 pango_font_description_free (old_desc);
872 fontsel->face = match_face;
875 #ifdef INCLUDE_FONT_ENTRIES
876 const gchar *str = pango_font_face_get_face_name (fontsel->face);
878 gtk_entry_set_text (GTK_ENTRY (fontsel->font_style_entry), str);
880 set_cursor_to_iter (GTK_TREE_VIEW (fontsel->face_list), &match_row);
886 /* This selects a style when the user selects a font. It just uses the first
887 available style at present. I was thinking of trying to maintain the
888 selected style, e.g. bold italic, when the user selects different fonts.
889 However, the interface is so easy to use now I'm not sure it's worth it.
890 Note: This will load a font. */
892 gtk_font_selection_select_best_style (GtkFontSelection *fontsel,
898 model = gtk_tree_view_get_model (GTK_TREE_VIEW (fontsel->face_list));
900 if (gtk_tree_model_get_iter_first (model, &iter))
902 set_cursor_to_iter (GTK_TREE_VIEW (fontsel->face_list), &iter);
903 scroll_to_selection (GTK_TREE_VIEW (fontsel->face_list));
906 gtk_font_selection_show_available_sizes (fontsel, FALSE);
907 gtk_font_selection_select_best_size (fontsel);
911 /* This is called when a style is selected in the list. */
913 gtk_font_selection_select_style (GtkTreeSelection *selection,
916 GtkFontSelection *fontsel = GTK_FONT_SELECTION (data);
920 if (gtk_tree_selection_get_selected (selection, &model, &iter))
924 gtk_tree_model_get (model, &iter, FACE_COLUMN, &face, -1);
925 fontsel->face = face;
927 g_object_unref (face);
930 gtk_font_selection_show_available_sizes (fontsel, FALSE);
931 gtk_font_selection_select_best_size (fontsel);
935 gtk_font_selection_show_available_sizes (GtkFontSelection *fontsel,
943 model = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (fontsel->size_list)));
945 /* Insert the standard font sizes */
948 gtk_list_store_clear (model);
950 for (i = 0; i < G_N_ELEMENTS (font_sizes); i++)
954 gtk_list_store_append (model, &iter);
955 gtk_list_store_set (model, &iter, SIZE_COLUMN, font_sizes[i], -1);
957 if (font_sizes[i] * PANGO_SCALE == fontsel->size)
958 set_cursor_to_iter (GTK_TREE_VIEW (fontsel->size_list), &iter);
964 gboolean found = FALSE;
966 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter);
967 for (i = 0; i < G_N_ELEMENTS (font_sizes) && !found; i++)
969 if (font_sizes[i] * PANGO_SCALE == fontsel->size)
971 set_cursor_to_iter (GTK_TREE_VIEW (fontsel->size_list), &iter);
975 gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &iter);
980 GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (fontsel->size_list));
981 gtk_tree_selection_unselect_all (selection);
985 /* Set the entry to the new size, rounding to 1 digit,
986 * trimming of trailing 0's and a trailing period
988 g_snprintf (buffer, sizeof (buffer), "%.1f", fontsel->size / (1.0 * PANGO_SCALE));
989 if (strchr (buffer, '.'))
991 p = buffer + strlen (buffer) - 1;
999 /* Compare, to avoid moving the cursor unecessarily */
1000 if (strcmp (gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry)), buffer) != 0)
1001 gtk_entry_set_text (GTK_ENTRY (fontsel->size_entry), buffer);
1005 gtk_font_selection_select_best_size (GtkFontSelection *fontsel)
1007 gtk_font_selection_load_font (fontsel);
1011 gtk_font_selection_set_size (GtkFontSelection *fontsel,
1014 if (fontsel->size != new_size)
1016 fontsel->size = new_size;
1018 gtk_font_selection_show_available_sizes (fontsel, FALSE);
1019 gtk_font_selection_load_font (fontsel);
1023 /* If the user hits return in the font size entry, we change to the new font
1026 gtk_font_selection_size_activate (GtkWidget *w,
1029 GtkFontSelection *fontsel;
1033 fontsel = GTK_FONT_SELECTION (data);
1035 text = gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry));
1036 new_size = MAX (0.1, atof (text) * PANGO_SCALE + 0.5);
1038 if (fontsel->size != new_size)
1039 gtk_font_selection_set_size (fontsel, new_size);
1041 list_row_activated (w);
1045 gtk_font_selection_size_focus_out (GtkWidget *w,
1046 GdkEventFocus *event,
1049 GtkFontSelection *fontsel;
1053 fontsel = GTK_FONT_SELECTION (data);
1055 text = gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry));
1056 new_size = MAX (0.1, atof (text) * PANGO_SCALE + 0.5);
1058 gtk_font_selection_set_size (fontsel, new_size);
1063 /* This is called when a size is selected in the list. */
1065 gtk_font_selection_select_size (GtkTreeSelection *selection,
1068 GtkFontSelection *fontsel;
1069 GtkTreeModel *model;
1073 fontsel = GTK_FONT_SELECTION (data);
1075 if (gtk_tree_selection_get_selected (selection, &model, &iter))
1077 gtk_tree_model_get (model, &iter, SIZE_COLUMN, &new_size, -1);
1078 gtk_font_selection_set_size (fontsel, new_size * PANGO_SCALE);
1083 gtk_font_selection_load_font (GtkFontSelection *fontsel)
1086 gdk_font_unref (fontsel->font);
1087 fontsel->font = NULL;
1089 gtk_font_selection_update_preview (fontsel);
1092 static PangoFontDescription *
1093 gtk_font_selection_get_font_description (GtkFontSelection *fontsel)
1095 PangoFontDescription *font_desc;
1099 font_desc = pango_font_face_describe (fontsel->face);
1100 pango_font_description_set_size (font_desc, fontsel->size);
1103 font_desc = pango_font_description_from_string ("Sans 10");
1108 /* This sets the font in the preview entry to the selected font, and tries to
1109 make sure that the preview entry is a reasonable size, i.e. so that the
1110 text can be seen with a bit of space to spare. But it tries to avoid
1111 resizing the entry every time the font changes.
1112 This also used to shrink the preview if the font size was decreased, but
1113 that made it awkward if the user wanted to resize the window themself. */
1115 gtk_font_selection_update_preview (GtkFontSelection *fontsel)
1117 GtkRcStyle *rc_style;
1119 GtkRequisition old_requisition;
1120 GtkWidget *preview_entry = fontsel->preview_entry;
1123 gtk_widget_get_child_requisition (preview_entry, &old_requisition);
1125 rc_style = gtk_rc_style_new ();
1126 rc_style->font_desc = gtk_font_selection_get_font_description (fontsel);
1128 gtk_widget_modify_style (preview_entry, rc_style);
1129 gtk_rc_style_unref (rc_style);
1131 gtk_widget_size_request (preview_entry, NULL);
1133 /* We don't ever want to be over MAX_PREVIEW_HEIGHT pixels high. */
1134 new_height = CLAMP (preview_entry->requisition.height, INITIAL_PREVIEW_HEIGHT, MAX_PREVIEW_HEIGHT);
1136 if (new_height > old_requisition.height || new_height < old_requisition.height - 30)
1137 gtk_widget_set_size_request (preview_entry, -1, new_height);
1139 /* This sets the preview text, if it hasn't been set already. */
1140 text = gtk_entry_get_text (GTK_ENTRY (preview_entry));
1141 if (strlen (text) == 0)
1142 gtk_entry_set_text (GTK_ENTRY (preview_entry), _(PREVIEW_TEXT));
1143 gtk_editable_set_position (GTK_EDITABLE (preview_entry), 0);
1147 gtk_font_selection_get_font_internal (GtkFontSelection *fontsel)
1151 PangoFontDescription *font_desc = gtk_font_selection_get_font_description (fontsel);
1152 fontsel->font = gdk_font_from_description_for_display (gtk_widget_get_display (GTK_WIDGET (fontsel)), font_desc);
1153 pango_font_description_free (font_desc);
1156 return fontsel->font;
1160 /*****************************************************************************
1161 * These functions are the main public interface for getting/setting the font.
1162 *****************************************************************************/
1165 gtk_font_selection_get_font (GtkFontSelection *fontsel)
1167 return gtk_font_selection_get_font_internal (fontsel);
1171 * gtk_font_selection_get_font_name:
1172 * @fontsel: a #GtkFontSelection
1174 * Gets the currently-selected font name. Note that this can be a different
1175 * string than what you set with gtk_font_selection_set_font_name(), as
1176 * the font selection widget may normalize font names and thus return a string
1177 * with a different structure. For example, "Helvetica Italic Bold 12" could be
1178 * normalized to "Helvetica Bold Italic 12". Use pango_font_description_equal()
1179 * if you want to compare two font descriptions.
1181 * Return value: A string with the name of the current font, or #NULL if no font
1182 * is selected. You must free this string with g_free().
1185 gtk_font_selection_get_font_name (GtkFontSelection *fontsel)
1189 PangoFontDescription *font_desc = gtk_font_selection_get_font_description (fontsel);
1190 result = pango_font_description_to_string (font_desc);
1191 pango_font_description_free (font_desc);
1197 /* This sets the current font, selecting the appropriate list rows.
1198 First we check the fontname is valid and try to find the font family
1199 - i.e. the name in the main list. If we can't find that, then just return.
1200 Next we try to set each of the properties according to the fontname.
1201 Finally we select the font family & style in the lists. */
1204 * gtk_font_selection_set_font_name:
1205 * @fontsel: a #GtkFontSelection
1206 * @fontname: a font name like "Helvetica 12" or "Times Bold 18"
1208 * Sets the currently-selected font. Note that the @fontsel needs to know the
1209 * screen in which it will appear for this to work; this can be guaranteed by
1210 * simply making sure that the @fontsel is inserted in a toplevel window before
1211 * you call this function.
1213 * Return value: #TRUE if the font could be set successfully; #FALSE if no such
1214 * font exists or if the @fontsel doesn't belong to a particular screen yet.
1217 gtk_font_selection_set_font_name (GtkFontSelection *fontsel,
1218 const gchar *fontname)
1220 PangoFontFamily *new_family = NULL;
1221 PangoFontFace *new_face = NULL;
1222 PangoFontFace *fallback_face = NULL;
1223 PangoFontDescription *new_desc;
1224 GtkTreeModel *model;
1226 GtkTreeIter match_iter;
1228 const gchar *new_family_name;
1230 g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), FALSE);
1231 g_return_val_if_fail (gtk_widget_has_screen (GTK_WIDGET (fontsel)), FALSE);
1233 new_desc = pango_font_description_from_string (fontname);
1234 new_family_name = pango_font_description_get_family (new_desc);
1236 if (!new_family_name)
1239 /* Check to make sure that this is in the list of allowed fonts
1241 model = gtk_tree_view_get_model (GTK_TREE_VIEW (fontsel->family_list));
1242 for (valid = gtk_tree_model_get_iter_first (model, &iter);
1244 valid = gtk_tree_model_iter_next (model, &iter))
1246 PangoFontFamily *family;
1248 gtk_tree_model_get (model, &iter, FAMILY_COLUMN, &family, -1);
1250 if (g_ascii_strcasecmp (pango_font_family_get_name (family),
1251 new_family_name) == 0)
1252 new_family = family;
1254 g_object_unref (family);
1263 fontsel->family = new_family;
1264 set_cursor_to_iter (GTK_TREE_VIEW (fontsel->family_list), &iter);
1265 gtk_font_selection_show_available_styles (fontsel);
1267 model = gtk_tree_view_get_model (GTK_TREE_VIEW (fontsel->face_list));
1268 for (valid = gtk_tree_model_get_iter_first (model, &iter);
1270 valid = gtk_tree_model_iter_next (model, &iter))
1272 PangoFontFace *face;
1273 PangoFontDescription *tmp_desc;
1275 gtk_tree_model_get (model, &iter, FACE_COLUMN, &face, -1);
1276 tmp_desc = pango_font_face_describe (face);
1278 if (font_description_style_equal (tmp_desc, new_desc))
1283 fallback_face = face;
1287 pango_font_description_free (tmp_desc);
1288 g_object_unref (face);
1298 new_face = fallback_face;
1300 fontsel->face = new_face;
1301 set_cursor_to_iter (GTK_TREE_VIEW (fontsel->face_list), &match_iter);
1303 gtk_font_selection_set_size (fontsel, pango_font_description_get_size (new_desc));
1305 g_object_freeze_notify (G_OBJECT (fontsel));
1306 g_object_notify (G_OBJECT (fontsel), "font_name");
1307 g_object_notify (G_OBJECT (fontsel), "font");
1308 g_object_thaw_notify (G_OBJECT (fontsel));
1310 pango_font_description_free (new_desc);
1316 /* This returns the text in the preview entry. You should copy the returned
1317 text if you need it. */
1318 G_CONST_RETURN gchar*
1319 gtk_font_selection_get_preview_text (GtkFontSelection *fontsel)
1321 return gtk_entry_get_text (GTK_ENTRY (fontsel->preview_entry));
1325 /* This sets the text in the preview entry. */
1327 gtk_font_selection_set_preview_text (GtkFontSelection *fontsel,
1330 gtk_entry_set_text (GTK_ENTRY (fontsel->preview_entry), text);
1333 /*****************************************************************************
1334 * GtkFontSelectionDialog
1335 *****************************************************************************/
1338 gtk_font_selection_dialog_get_type (void)
1340 static GType font_selection_dialog_type = 0;
1342 if (!font_selection_dialog_type)
1344 static const GTypeInfo fontsel_diag_info =
1346 sizeof (GtkFontSelectionDialogClass),
1347 NULL, /* base_init */
1348 NULL, /* base_finalize */
1349 (GClassInitFunc) gtk_font_selection_dialog_class_init,
1350 NULL, /* class_finalize */
1351 NULL, /* class_data */
1352 sizeof (GtkFontSelectionDialog),
1353 0, /* n_preallocs */
1354 (GInstanceInitFunc) gtk_font_selection_dialog_init,
1357 font_selection_dialog_type =
1358 g_type_register_static (GTK_TYPE_DIALOG, I_("GtkFontSelectionDialog"),
1359 &fontsel_diag_info, 0);
1362 return font_selection_dialog_type;
1366 gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass)
1368 font_selection_dialog_parent_class = g_type_class_peek_parent (klass);
1372 gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag)
1376 gtk_widget_push_composite_child ();
1378 dialog = GTK_DIALOG (fontseldiag);
1380 gtk_container_set_border_width (GTK_CONTAINER (fontseldiag), 4);
1381 gtk_window_set_resizable (GTK_WINDOW (fontseldiag), TRUE);
1383 fontseldiag->main_vbox = dialog->vbox;
1385 fontseldiag->fontsel = gtk_font_selection_new ();
1386 gtk_container_set_border_width (GTK_CONTAINER (fontseldiag->fontsel), 4);
1387 gtk_widget_show (fontseldiag->fontsel);
1388 gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox),
1389 fontseldiag->fontsel, TRUE, TRUE, 0);
1391 /* Create the action area */
1392 fontseldiag->action_area = dialog->action_area;
1394 fontseldiag->cancel_button = gtk_dialog_add_button (dialog,
1396 GTK_RESPONSE_CANCEL);
1398 fontseldiag->apply_button = gtk_dialog_add_button (dialog,
1400 GTK_RESPONSE_APPLY);
1401 gtk_widget_hide (fontseldiag->apply_button);
1403 fontseldiag->ok_button = gtk_dialog_add_button (dialog,
1406 gtk_widget_grab_default (fontseldiag->ok_button);
1408 gtk_dialog_set_alternative_button_order (GTK_DIALOG (fontseldiag),
1411 GTK_RESPONSE_CANCEL,
1415 gtk_window_set_title (GTK_WINDOW (fontseldiag),
1416 _("Font Selection"));
1418 gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
1420 gtk_widget_pop_composite_child ();
1424 gtk_font_selection_dialog_new (const gchar *title)
1426 GtkFontSelectionDialog *fontseldiag;
1428 fontseldiag = g_object_new (GTK_TYPE_FONT_SELECTION_DIALOG, NULL);
1431 gtk_window_set_title (GTK_WINDOW (fontseldiag), title);
1433 return GTK_WIDGET (fontseldiag);
1437 * gtk_font_selection_dialog_get_font_name:
1438 * @fsd: a #GtkFontSelectionDialog
1440 * Gets the currently-selected font name. Note that this can be a different
1441 * string than what you set with gtk_font_selection_dialog_set_font_name(), as
1442 * the font selection widget may normalize font names and thus return a string
1443 * with a different structure. For example, "Helvetica Italic Bold 12" could be
1444 * normalized to "Helvetica Bold Italic 12". Use pango_font_description_equal()
1445 * if you want to compare two font descriptions.
1447 * Return value: A string with the name of the current font, or #NULL if no font
1448 * is selected. You must free this string with g_free().
1451 gtk_font_selection_dialog_get_font_name (GtkFontSelectionDialog *fsd)
1453 return gtk_font_selection_get_font_name (GTK_FONT_SELECTION (fsd->fontsel));
1457 gtk_font_selection_dialog_get_font (GtkFontSelectionDialog *fsd)
1459 return gtk_font_selection_get_font (GTK_FONT_SELECTION (fsd->fontsel));
1463 gtk_font_selection_dialog_set_font_name (GtkFontSelectionDialog *fsd,
1464 const gchar *fontname)
1466 return gtk_font_selection_set_font_name (GTK_FONT_SELECTION (fsd->fontsel), fontname);
1469 G_CONST_RETURN gchar*
1470 gtk_font_selection_dialog_get_preview_text (GtkFontSelectionDialog *fsd)
1472 return gtk_font_selection_get_preview_text (GTK_FONT_SELECTION (fsd->fontsel));
1476 gtk_font_selection_dialog_set_preview_text (GtkFontSelectionDialog *fsd,
1479 gtk_font_selection_set_preview_text (GTK_FONT_SELECTION (fsd->fontsel), text);
1482 #define __GTK_FONTSEL_C__
1483 #include "gtkaliasdef.c"