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
79 static void gtk_font_selection_class_init (GtkFontSelectionClass *klass);
80 static void gtk_font_selection_init (GtkFontSelection *fontsel);
81 static void gtk_font_selection_finalize (GObject *object);
83 /* These are the callbacks & related functions. */
84 static void gtk_font_selection_select_font (GtkWidget *w,
87 GdkEventButton *bevent,
89 static gint gtk_font_selection_on_clist_key_press (GtkWidget *clist,
91 GtkFontSelection *fs);
92 static gboolean gtk_font_selection_select_next (GtkFontSelection *fs,
96 static void gtk_font_selection_show_available_fonts (GtkFontSelection *fs);
98 static void gtk_font_selection_show_available_styles (GtkFontSelection *fs);
99 static void gtk_font_selection_select_best_style (GtkFontSelection *fs,
101 static void gtk_font_selection_select_style (GtkWidget *w,
104 GdkEventButton *bevent,
107 static void gtk_font_selection_select_best_size (GtkFontSelection *fs);
108 static void gtk_font_selection_show_available_sizes (GtkFontSelection *fs);
109 static gint gtk_font_selection_size_key_press (GtkWidget *w,
112 static void gtk_font_selection_select_size (GtkWidget *w,
115 GdkEventButton *bevent,
118 static void gtk_font_selection_expose_list (GtkWidget *w,
119 GdkEventExpose *event,
123 /* Misc. utility functions. */
124 static void gtk_font_selection_load_font (GtkFontSelection *fs);
125 static void gtk_font_selection_update_preview (GtkFontSelection *fs);
127 /* FontSelectionDialog */
128 static void gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass);
129 static void gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag);
131 static gint gtk_font_selection_dialog_on_configure(GtkWidget *widget,
132 GdkEventConfigure *event,
133 GtkFontSelectionDialog *fsd);
135 static GtkWindowClass *font_selection_parent_class = NULL;
136 static GtkVBoxClass *font_selection_dialog_parent_class = NULL;
139 gtk_font_selection_get_type()
141 static GtkType font_selection_type = 0;
143 if(!font_selection_type)
145 static const GtkTypeInfo fontsel_type_info =
148 sizeof (GtkFontSelection),
149 sizeof (GtkFontSelectionClass),
150 (GtkClassInitFunc) gtk_font_selection_class_init,
151 (GtkObjectInitFunc) gtk_font_selection_init,
152 /* reserved_1 */ NULL,
153 /* reserved_2 */ NULL,
154 (GtkClassInitFunc) NULL,
157 font_selection_type = gtk_type_unique (GTK_TYPE_VBOX,
161 return font_selection_type;
165 gtk_font_selection_class_init(GtkFontSelectionClass *klass)
167 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
169 font_selection_parent_class = gtk_type_class (GTK_TYPE_VBOX);
171 gobject_class->finalize = gtk_font_selection_finalize;
175 gtk_font_selection_init(GtkFontSelection *fontsel)
177 GtkWidget *scrolled_win;
178 GtkWidget *text_frame;
180 GtkWidget *table, *label;
182 fontsel->font_desc = pango_font_description_from_string ("sans 12");
184 /* Create the table of font, style & size. */
185 table = gtk_table_new (3, 3, FALSE);
186 gtk_widget_show (table);
187 gtk_table_set_col_spacings(GTK_TABLE(table), 8);
188 gtk_box_pack_start (GTK_BOX (fontsel), table, TRUE, TRUE, 0);
190 fontsel->font_entry = gtk_entry_new ();
191 gtk_entry_set_editable(GTK_ENTRY(fontsel->font_entry), FALSE);
192 gtk_widget_set_usize (fontsel->font_entry, 20, -1);
193 gtk_widget_show (fontsel->font_entry);
194 gtk_table_attach (GTK_TABLE (table), fontsel->font_entry, 0, 1, 1, 2,
197 fontsel->font_style_entry = gtk_entry_new ();
198 gtk_entry_set_editable (GTK_ENTRY(fontsel->font_style_entry), FALSE);
199 gtk_widget_set_usize (fontsel->font_style_entry, 20, -1);
200 gtk_widget_show (fontsel->font_style_entry);
201 gtk_table_attach (GTK_TABLE (table), fontsel->font_style_entry, 1, 2, 1, 2,
204 fontsel->size_entry = gtk_entry_new ();
205 gtk_widget_set_usize (fontsel->size_entry, 20, -1);
206 gtk_widget_show (fontsel->size_entry);
207 gtk_table_attach (GTK_TABLE (table), fontsel->size_entry, 2, 3, 1, 2,
209 gtk_signal_connect (GTK_OBJECT (fontsel->size_entry), "key_press_event",
210 (GtkSignalFunc) gtk_font_selection_size_key_press,
213 fontsel->font_label = gtk_label_new_with_mnemonic (_("_Family:"));
214 gtk_label_set_mnemonic_widget (GTK_LABEL (fontsel->font_label),
215 fontsel->font_entry);
216 gtk_misc_set_alignment (GTK_MISC (fontsel->font_label), 0.0, 0.5);
217 gtk_widget_show (fontsel->font_label);
218 gtk_table_attach (GTK_TABLE (table), fontsel->font_label, 0, 1, 0, 1,
220 label = gtk_label_new_with_mnemonic (_("_Style:"));
221 gtk_label_set_mnemonic_widget (GTK_LABEL (label),
222 fontsel->font_style_entry);
223 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
224 gtk_widget_show (label);
225 gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,
227 label = gtk_label_new_with_mnemonic (_("Si_ze:"));
228 gtk_label_set_mnemonic_widget (GTK_LABEL (label),
229 fontsel->size_entry);
230 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
231 gtk_widget_show (label);
232 gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1,
236 /* Create the clists */
237 fontsel->font_clist = gtk_clist_new (1);
238 gtk_clist_column_titles_hide (GTK_CLIST (fontsel->font_clist));
239 gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_clist), 0, TRUE);
240 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
241 gtk_widget_set_usize (scrolled_win, FONT_LIST_WIDTH, FONT_LIST_HEIGHT);
242 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_clist);
243 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
244 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
245 gtk_widget_show(fontsel->font_clist);
246 gtk_widget_show(scrolled_win);
248 gtk_table_attach (GTK_TABLE (table), scrolled_win, 0, 1, 2, 3,
249 GTK_EXPAND | GTK_FILL,
250 GTK_EXPAND | GTK_FILL, 0, 0);
252 fontsel->font_style_clist = gtk_clist_new (1);
253 gtk_clist_column_titles_hide (GTK_CLIST (fontsel->font_style_clist));
254 gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_style_clist),
256 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
257 gtk_widget_set_usize (scrolled_win, FONT_STYLE_LIST_WIDTH, -1);
258 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_style_clist);
259 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
260 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
261 gtk_widget_show(fontsel->font_style_clist);
262 gtk_widget_show(scrolled_win);
263 gtk_table_attach (GTK_TABLE (table), scrolled_win, 1, 2, 2, 3,
264 GTK_EXPAND | GTK_FILL,
265 GTK_EXPAND | GTK_FILL, 0, 0);
267 fontsel->size_clist = gtk_clist_new (1);
268 gtk_clist_column_titles_hide (GTK_CLIST(fontsel->size_clist));
269 gtk_clist_set_column_width (GTK_CLIST(fontsel->size_clist), 0, 20);
270 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
271 gtk_widget_set_usize (scrolled_win, FONT_SIZE_LIST_WIDTH, -1);
272 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->size_clist);
273 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
274 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
275 gtk_widget_show (fontsel->size_clist);
276 gtk_widget_show (scrolled_win);
277 gtk_table_attach (GTK_TABLE (table), scrolled_win, 2, 3, 2, 3,
278 GTK_FILL, GTK_FILL, 0, 0);
280 /* Insert the fonts. If there exist fonts with the same family but
281 different foundries, then the foundry name is appended in brackets. */
282 gtk_font_selection_show_available_fonts(fontsel);
284 gtk_signal_connect (GTK_OBJECT (fontsel->font_clist), "select_row",
285 GTK_SIGNAL_FUNC(gtk_font_selection_select_font),
287 GTK_WIDGET_SET_FLAGS (fontsel->font_clist, GTK_CAN_FOCUS);
288 gtk_signal_connect (GTK_OBJECT (fontsel->font_clist), "key_press_event",
289 GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press),
292 gtk_font_selection_show_available_styles (fontsel);
294 gtk_signal_connect (GTK_OBJECT (fontsel->font_style_clist), "select_row",
295 GTK_SIGNAL_FUNC(gtk_font_selection_select_style),
297 GTK_WIDGET_SET_FLAGS (fontsel->font_style_clist, GTK_CAN_FOCUS);
298 gtk_signal_connect (GTK_OBJECT (fontsel->font_style_clist),
300 GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press),
303 gtk_font_selection_show_available_sizes (fontsel);
305 gtk_signal_connect (GTK_OBJECT (fontsel->size_clist), "select_row",
306 GTK_SIGNAL_FUNC(gtk_font_selection_select_size),
308 GTK_WIDGET_SET_FLAGS (fontsel->size_clist, GTK_CAN_FOCUS);
309 gtk_signal_connect (GTK_OBJECT (fontsel->size_clist), "key_press_event",
310 GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press),
313 /* create the text entry widget */
314 text_frame = gtk_frame_new (_("Preview:"));
315 gtk_widget_show (text_frame);
316 gtk_frame_set_shadow_type(GTK_FRAME(text_frame), GTK_SHADOW_ETCHED_IN);
317 gtk_box_pack_start (GTK_BOX (fontsel), text_frame,
320 /* This is just used to get a 4-pixel space around the preview entry. */
321 text_box = gtk_hbox_new (FALSE, 0);
322 gtk_widget_show (text_box);
323 gtk_container_add (GTK_CONTAINER (text_frame), text_box);
324 gtk_container_set_border_width (GTK_CONTAINER (text_box), 4);
326 fontsel->preview_entry = gtk_entry_new ();
327 gtk_widget_show (fontsel->preview_entry);
328 gtk_widget_set_usize (fontsel->preview_entry, -1, INITIAL_PREVIEW_HEIGHT);
329 gtk_box_pack_start (GTK_BOX (text_box), fontsel->preview_entry,
332 gtk_font_selection_update_preview (fontsel);
336 gtk_font_selection_new()
338 GtkFontSelection *fontsel;
340 fontsel = gtk_type_new (GTK_TYPE_FONT_SELECTION);
342 return GTK_WIDGET (fontsel);
346 gtk_font_selection_finalize (GObject *object)
348 GtkFontSelection *fontsel;
350 g_return_if_fail (object != NULL);
351 g_return_if_fail (GTK_IS_FONT_SELECTION (object));
353 fontsel = GTK_FONT_SELECTION (object);
355 pango_font_description_free (fontsel->font_desc);
358 gdk_font_unref (fontsel->font);
360 if (G_OBJECT_CLASS (font_selection_parent_class)->finalize)
361 (* G_OBJECT_CLASS (font_selection_parent_class)->finalize) (object);
365 /* This is called when the clist is exposed. Here we scroll to the current
366 font if necessary. */
368 gtk_font_selection_expose_list (GtkWidget *widget,
369 GdkEventExpose *event,
372 GtkFontSelection *fontsel;
377 g_message("In expose_list\n");
379 fontsel = GTK_FONT_SELECTION(data);
381 /* Try to scroll the font family clist to the selected item */
382 selection = GTK_CLIST(fontsel->font_clist)->selection;
385 index = GPOINTER_TO_INT (selection->data);
386 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_clist), index)
387 != GTK_VISIBILITY_FULL)
388 gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), index, -1, 0.5, 0);
391 /* Try to scroll the font style clist to the selected item */
392 selection = GTK_CLIST(fontsel->font_style_clist)->selection;
395 index = GPOINTER_TO_INT (selection->data);
396 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_style_clist), index)
397 != GTK_VISIBILITY_FULL)
398 gtk_clist_moveto(GTK_CLIST(fontsel->font_style_clist), index, -1,
402 /* Try to scroll the font size clist to the selected item */
403 selection = GTK_CLIST(fontsel->size_clist)->selection;
406 index = GPOINTER_TO_INT (selection->data);
407 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->size_clist), index)
408 != GTK_VISIBILITY_FULL)
409 gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), index, -1, 0.5, 0);
413 /* This is called when a family is selected in the list. */
415 gtk_font_selection_select_font (GtkWidget *w,
418 GdkEventButton *bevent,
421 GtkFontSelection *fontsel;
425 fontsel = GTK_FONT_SELECTION (data);
427 if (GTK_CLIST (fontsel->font_clist)->selection)
429 index = GPOINTER_TO_INT (GTK_CLIST (fontsel->font_clist)->selection->data);
431 if (gtk_clist_get_text (GTK_CLIST (fontsel->font_clist), index, 0, &family_name) &&
432 strcasecmp (fontsel->font_desc->family_name, family_name) != 0)
434 g_free (fontsel->font_desc->family_name);
435 fontsel->font_desc->family_name = g_strdup (family_name);
437 gtk_entry_set_text (GTK_ENTRY (fontsel->font_entry), family_name);
439 gtk_font_selection_show_available_styles (fontsel);
440 gtk_font_selection_select_best_style (fontsel, TRUE);
446 cmp_strings (const void *a, const void *b)
448 return strcasecmp (*(const char **)a, *(const char **)b);
452 gtk_font_selection_show_available_fonts (GtkFontSelection *fontsel)
457 pango_context_list_families (gtk_widget_get_pango_context (GTK_WIDGET (fontsel)),
458 &families, &n_families);
459 qsort (families, n_families, sizeof(char *), cmp_strings);
461 gtk_clist_freeze (GTK_CLIST (fontsel->font_clist));
462 gtk_clist_clear (GTK_CLIST (fontsel->font_clist));
464 for (i=0; i<n_families; i++)
466 gtk_clist_append (GTK_CLIST (fontsel->font_clist), &families[i]);
468 if (!strcasecmp (families[i], fontsel->font_desc->family_name))
470 gtk_clist_select_row (GTK_CLIST(fontsel->font_clist), i, 0);
471 gtk_entry_set_text(GTK_ENTRY(fontsel->font_entry), families[i]);
475 gtk_clist_thaw (GTK_CLIST(fontsel->font_clist));
477 pango_font_map_free_families (families, n_families);
481 gtk_font_selection_on_clist_key_press (GtkWidget *clist,
483 GtkFontSelection *fontsel)
486 g_message("In on_clist_key_press\n");
488 if (event->keyval == GDK_Up)
489 return gtk_font_selection_select_next (fontsel, clist, -1);
490 else if (event->keyval == GDK_Down)
491 return gtk_font_selection_select_next (fontsel, clist, 1);
498 gtk_font_selection_select_next (GtkFontSelection *fontsel,
503 gint current_row, row;
505 selection = GTK_CLIST(clist)->selection;
508 current_row = GPOINTER_TO_INT (selection->data);
510 /* Stop the normal clist key handler from being run. */
511 gtk_signal_emit_stop_by_name (GTK_OBJECT (clist), "key_press_event");
513 for (row = current_row + step;
514 row >= 0 && row < GTK_CLIST(clist)->rows;
517 /* If this is the style clist, make sure that the item is not a charset
519 if (clist == fontsel->font_style_clist)
520 if (GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(clist), row)) == -1)
523 /* Now we've found the row to select. */
524 if (gtk_clist_row_is_visible(GTK_CLIST(clist), row)
525 != GTK_VISIBILITY_FULL)
526 gtk_clist_moveto(GTK_CLIST(clist), row, -1, (step < 0) ? 0 : 1, 0);
527 gtk_clist_select_row(GTK_CLIST(clist), row, 0);
534 compare_font_descriptions (const PangoFontDescription *a, const PangoFontDescription *b)
536 int val = strcasecmp (a->family_name, b->family_name);
540 if (a->weight != b->weight)
541 return a->weight - b->weight;
543 if (a->style != b->style)
544 return a->style - b->style;
546 if (a->stretch != b->stretch)
547 return a->stretch - b->stretch;
549 if (a->variant != b->variant)
550 return a->variant - b->variant;
556 font_description_sort_func (const void *a, const void *b)
558 return compare_font_descriptions (*(PangoFontDescription **)a, *(PangoFontDescription **)b);
561 /* This fills the font style clist with all the possible style combinations
562 for the current font family. */
564 gtk_font_selection_show_available_styles (GtkFontSelection *fontsel)
566 PangoFontDescription **descs;
571 pango_context_list_fonts (gtk_widget_get_pango_context (GTK_WIDGET (fontsel)),
572 fontsel->font_desc->family_name, &descs, &n_descs);
573 qsort (descs, n_descs, sizeof(PangoFontDescription *), font_description_sort_func);
575 gtk_clist_freeze (GTK_CLIST (fontsel->font_style_clist));
576 gtk_clist_clear (GTK_CLIST (fontsel->font_style_clist));
578 for (i=0; i<n_descs; i++)
580 PangoFontDescription tmp_desc;
582 tmp_desc = *descs[i];
583 tmp_desc.family_name = NULL;
586 str = pango_font_description_to_string (&tmp_desc);
587 gtk_clist_append (GTK_CLIST (fontsel->font_style_clist), &str);
589 if (descs[i]->weight == fontsel->font_desc->weight &&
590 descs[i]->style == fontsel->font_desc->style &&
591 descs[i]->stretch == fontsel->font_desc->stretch &&
592 descs[i]->variant == fontsel->font_desc->variant)
598 gtk_clist_select_row (GTK_CLIST (fontsel->font_style_clist), match_row, 0);
601 gtk_clist_get_text (GTK_CLIST (fontsel->font_style_clist), match_row, 0, &str);
602 gtk_entry_set_text (GTK_ENTRY (fontsel->font_style_entry), str);
605 gtk_clist_thaw (GTK_CLIST(fontsel->font_style_clist));
607 pango_font_descriptions_free (descs, n_descs);
611 /* This selects a style when the user selects a font. It just uses the first
612 available style at present. I was thinking of trying to maintain the
613 selected style, e.g. bold italic, when the user selects different fonts.
614 However, the interface is so easy to use now I'm not sure it's worth it.
615 Note: This will load a font. */
617 gtk_font_selection_select_best_style(GtkFontSelection *fontsel,
622 gtk_clist_select_row(GTK_CLIST(fontsel->font_style_clist), best_row, 0);
623 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_style_clist), best_row)
624 != GTK_VISIBILITY_FULL)
625 gtk_clist_moveto(GTK_CLIST(fontsel->font_style_clist), best_row, -1,
627 gtk_font_selection_show_available_sizes (fontsel);
628 gtk_font_selection_select_best_size (fontsel);
632 /* This is called when a style is selected in the list. */
634 gtk_font_selection_select_style (GtkWidget *w,
637 GdkEventButton *bevent,
640 GtkFontSelection *fontsel = GTK_FONT_SELECTION (data);
641 PangoFontDescription *tmp_desc;
645 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
646 gtk_widget_grab_focus (w);
648 if (GTK_CLIST (fontsel->font_style_clist)->selection)
650 index = GPOINTER_TO_INT (GTK_CLIST (fontsel->font_style_clist)->selection->data);
652 if (gtk_clist_get_text (GTK_CLIST (fontsel->font_style_clist), index, 0, &text))
654 tmp_desc = pango_font_description_from_string (text);
656 fontsel->font_desc->style = tmp_desc->style;
657 fontsel->font_desc->variant = tmp_desc->variant;
658 fontsel->font_desc->weight = tmp_desc->weight;
659 fontsel->font_desc->stretch = tmp_desc->stretch;
661 pango_font_description_free (tmp_desc);
665 gtk_font_selection_show_available_sizes (fontsel);
666 gtk_font_selection_select_best_size (fontsel);
670 gtk_font_selection_show_available_sizes (GtkFontSelection *fontsel)
676 /* Insert the standard font sizes */
677 gtk_clist_freeze (GTK_CLIST (fontsel->size_clist));
678 gtk_clist_clear (GTK_CLIST (fontsel->size_clist));
680 for (i = 0; i < G_N_ELEMENTS (font_sizes); i++)
682 sprintf(buffer, "%i", font_sizes[i]);
684 gtk_clist_append (GTK_CLIST(fontsel->size_clist), &size);
685 if (font_sizes[i] * PANGO_SCALE == fontsel->font_desc->size)
686 gtk_clist_select_row(GTK_CLIST(fontsel->size_clist), i, 0);
688 gtk_clist_thaw (GTK_CLIST(fontsel->size_clist));
690 sprintf (buffer, "%i", fontsel->font_desc->size / PANGO_SCALE);
691 gtk_entry_set_text (GTK_ENTRY(fontsel->size_entry), buffer);
695 gtk_font_selection_select_best_size (GtkFontSelection *fontsel)
697 gtk_font_selection_load_font (fontsel);
700 /* If the user hits return in the font size entry, we change to the new font
703 gtk_font_selection_size_key_press (GtkWidget *w,
707 GtkFontSelection *fontsel;
711 fontsel = GTK_FONT_SELECTION (data);
713 if (event->keyval == GDK_Return)
715 text = gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry));
716 new_size = atoi (text) * PANGO_SCALE;
718 if (fontsel->font_desc->size != new_size)
720 fontsel->font_desc->size = new_size;
721 gtk_font_selection_load_font (fontsel);
729 /* This is called when a size is selected in the list. */
731 gtk_font_selection_select_size (GtkWidget *w,
734 GdkEventButton *bevent,
737 GtkFontSelection *fontsel;
741 fontsel = GTK_FONT_SELECTION (data);
743 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
744 gtk_widget_grab_focus (w);
746 gtk_clist_get_text(GTK_CLIST(fontsel->size_clist), row, 0, &text);
747 new_size = atoi (text) * PANGO_SCALE;
749 if (fontsel->font_desc->size != new_size)
751 /* If the size was selected by the user we set the selected_size. */
752 fontsel->font_desc->size = new_size;
754 gtk_font_selection_load_font (fontsel);
759 gtk_font_selection_load_font (GtkFontSelection *fontsel)
762 gdk_font_unref (fontsel->font);
763 fontsel->font = NULL;
765 gtk_font_selection_update_preview (fontsel);
768 /* This sets the font in the preview entry to the selected font, and tries to
769 make sure that the preview entry is a reasonable size, i.e. so that the
770 text can be seen with a bit of space to spare. But it tries to avoid
771 resizing the entry every time the font changes.
772 This also used to shrink the preview if the font size was decreased, but
773 that made it awkward if the user wanted to resize the window themself. */
775 gtk_font_selection_update_preview (GtkFontSelection *fontsel)
777 GtkRcStyle *rc_style;
779 GtkRequisition old_requisition;
780 GtkWidget *preview_entry = fontsel->preview_entry;
783 gtk_widget_get_child_requisition (preview_entry, &old_requisition);
785 rc_style = gtk_rc_style_new ();
786 rc_style->font_desc = pango_font_description_copy (fontsel->font_desc);
787 gtk_widget_modify_style (preview_entry, rc_style);
788 gtk_rc_style_unref (rc_style);
790 gtk_widget_size_request (preview_entry, NULL);
792 /* We don't ever want to be over MAX_PREVIEW_HEIGHT pixels high. */
793 new_height = CLAMP (preview_entry->requisition.height, INITIAL_PREVIEW_HEIGHT, MAX_PREVIEW_HEIGHT);
795 if (new_height > old_requisition.height || new_height < old_requisition.height - 30)
796 gtk_widget_set_usize(preview_entry, -1, new_height);
798 /* This sets the preview text, if it hasn't been set already. */
799 text = gtk_entry_get_text(GTK_ENTRY(preview_entry));
800 if (strlen(text) == 0)
801 gtk_entry_set_text(GTK_ENTRY(preview_entry), PREVIEW_TEXT);
802 gtk_entry_set_position(GTK_ENTRY(preview_entry), 0);
805 /*****************************************************************************
806 * These functions are the main public interface for getting/setting the font.
807 *****************************************************************************/
810 gtk_font_selection_get_font (GtkFontSelection *fontsel)
813 fontsel->font = gdk_font_from_description (fontsel->font_desc);
815 return fontsel->font;
820 gtk_font_selection_get_font_name (GtkFontSelection *fontsel)
822 return pango_font_description_to_string (fontsel->font_desc);
826 /* This sets the current font, selecting the appropriate clist rows.
827 First we check the fontname is valid and try to find the font family
828 - i.e. the name in the main list. If we can't find that, then just return.
829 Next we try to set each of the properties according to the fontname.
830 Finally we select the font family & style in the clists. */
832 gtk_font_selection_set_font_name (GtkFontSelection *fontsel,
833 const gchar *fontname)
835 PangoFontDescription *new_desc;
836 PangoFontDescription **descs;
838 gboolean found = FALSE;
840 g_return_val_if_fail (fontsel != NULL, FALSE);
841 g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), FALSE);
843 new_desc = pango_font_description_from_string (fontname);
845 /* Check to make sure that this is in the list of allowed fonts */
847 pango_context_list_fonts (gtk_widget_get_pango_context (GTK_WIDGET (fontsel)),
848 new_desc->family_name, &descs, &n_descs);
850 for (i=0; i<n_descs; i++)
852 if (descs[i]->weight == new_desc->weight &&
853 descs[i]->style == new_desc->style &&
854 descs[i]->stretch == new_desc->stretch &&
855 descs[i]->variant == new_desc->variant)
862 pango_font_descriptions_free (descs, n_descs);
867 pango_font_description_free (fontsel->font_desc);
868 fontsel->font_desc = new_desc;
874 /* This returns the text in the preview entry. You should copy the returned
875 text if you need it. */
877 gtk_font_selection_get_preview_text (GtkFontSelection *fontsel)
879 return gtk_entry_get_text (GTK_ENTRY (fontsel->preview_entry));
883 /* This sets the text in the preview entry. */
885 gtk_font_selection_set_preview_text (GtkFontSelection *fontsel,
888 gtk_entry_set_text (GTK_ENTRY (fontsel->preview_entry), text);
891 /*****************************************************************************
892 * GtkFontSelectionDialog
893 *****************************************************************************/
896 gtk_font_selection_dialog_get_type (void)
898 static guint font_selection_dialog_type = 0;
900 if (!font_selection_dialog_type)
902 GtkTypeInfo fontsel_diag_info =
904 "GtkFontSelectionDialog",
905 sizeof (GtkFontSelectionDialog),
906 sizeof (GtkFontSelectionDialogClass),
907 (GtkClassInitFunc) gtk_font_selection_dialog_class_init,
908 (GtkObjectInitFunc) gtk_font_selection_dialog_init,
909 /* reserved_1 */ NULL,
910 /* reserved_2 */ NULL,
911 (GtkClassInitFunc) NULL,
914 font_selection_dialog_type = gtk_type_unique (GTK_TYPE_DIALOG,
918 return font_selection_dialog_type;
922 gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass)
924 GtkObjectClass *object_class;
926 object_class = (GtkObjectClass*) klass;
928 font_selection_dialog_parent_class = gtk_type_class (GTK_TYPE_DIALOG);
932 gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag)
936 dialog = GTK_DIALOG (fontseldiag);
938 fontseldiag->dialog_width = -1;
939 fontseldiag->auto_resize = TRUE;
941 gtk_widget_set_events(GTK_WIDGET(fontseldiag), GDK_STRUCTURE_MASK);
942 gtk_signal_connect (GTK_OBJECT (fontseldiag), "configure_event",
943 (GtkSignalFunc) gtk_font_selection_dialog_on_configure,
946 gtk_container_set_border_width (GTK_CONTAINER (fontseldiag), 4);
947 gtk_window_set_policy(GTK_WINDOW(fontseldiag), FALSE, TRUE, TRUE);
949 fontseldiag->main_vbox = dialog->vbox;
951 fontseldiag->fontsel = gtk_font_selection_new();
952 gtk_container_set_border_width (GTK_CONTAINER (fontseldiag->fontsel), 4);
953 gtk_widget_show (fontseldiag->fontsel);
954 gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox),
955 fontseldiag->fontsel, TRUE, TRUE, 0);
957 /* Create the action area */
958 fontseldiag->action_area = dialog->action_area;
960 fontseldiag->ok_button = gtk_dialog_add_button (dialog,
963 gtk_widget_grab_default (fontseldiag->ok_button);
965 fontseldiag->apply_button = gtk_dialog_add_button (dialog,
966 GTK_STOCK_BUTTON_APPLY,
968 gtk_widget_hide (fontseldiag->apply_button);
971 fontseldiag->cancel_button = gtk_dialog_add_button (dialog,
972 GTK_STOCK_BUTTON_CANCEL,
973 GTK_RESPONSE_CANCEL);
975 gtk_window_set_title (GTK_WINDOW (fontseldiag),
976 _("Font Selection"));
981 gtk_font_selection_dialog_new (const gchar *title)
983 GtkFontSelectionDialog *fontseldiag;
985 fontseldiag = gtk_type_new (GTK_TYPE_FONT_SELECTION_DIALOG);
988 gtk_window_set_title (GTK_WINDOW (fontseldiag), title);
990 return GTK_WIDGET (fontseldiag);
994 gtk_font_selection_dialog_get_font_name (GtkFontSelectionDialog *fsd)
996 return gtk_font_selection_get_font_name(GTK_FONT_SELECTION(fsd->fontsel));
1000 gtk_font_selection_dialog_get_font (GtkFontSelectionDialog *fsd)
1002 return gtk_font_selection_get_font(GTK_FONT_SELECTION(fsd->fontsel));
1006 gtk_font_selection_dialog_set_font_name (GtkFontSelectionDialog *fsd,
1007 const gchar *fontname)
1009 return gtk_font_selection_set_font_name(GTK_FONT_SELECTION(fsd->fontsel),
1014 gtk_font_selection_dialog_get_preview_text (GtkFontSelectionDialog *fsd)
1016 return gtk_font_selection_get_preview_text(GTK_FONT_SELECTION(fsd->fontsel));
1020 gtk_font_selection_dialog_set_preview_text (GtkFontSelectionDialog *fsd,
1023 gtk_font_selection_set_preview_text(GTK_FONT_SELECTION(fsd->fontsel), text);
1027 /* This turns auto-shrink off if the user resizes the width of the dialog.
1028 It also turns it back on again if the user resizes it back to its normal
1031 gtk_font_selection_dialog_on_configure (GtkWidget *widget,
1032 GdkEventConfigure *event,
1033 GtkFontSelectionDialog *fsd)
1035 /* This sets the initial width. */
1036 if (fsd->dialog_width == -1)
1037 fsd->dialog_width = event->width;
1038 else if (fsd->auto_resize && fsd->dialog_width != event->width)
1040 fsd->auto_resize = FALSE;
1041 gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, FALSE);
1043 else if (!fsd->auto_resize && fsd->dialog_width == event->width)
1045 fsd->auto_resize = TRUE;
1046 gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, TRUE);