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 Library 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 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library 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-1999. 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"
53 #include "gtkscrolledwindow.h"
56 /* This is the default text shown in the preview entry, though the user
57 can set it. Remember that some fonts only have capital letters. */
58 #define PREVIEW_TEXT "abcdefghijk ABCDEFGHIJK"
60 /* This is the initial and maximum height of the preview entry (it expands
61 when large font sizes are selected). Initial height is also the minimum. */
62 #define INITIAL_PREVIEW_HEIGHT 44
63 #define MAX_PREVIEW_HEIGHT 300
65 /* These are the sizes of the font, style & size clists. */
66 #define FONT_LIST_HEIGHT 136
67 #define FONT_LIST_WIDTH 190
68 #define FONT_STYLE_LIST_WIDTH 170
69 #define FONT_SIZE_LIST_WIDTH 60
71 /* These are what we use as the standard font sizes, for the size clist.
73 static const guint16 font_sizes[] = {
74 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 26, 28,
75 32, 36, 40, 48, 56, 64, 72
78 static void gtk_font_selection_class_init (GtkFontSelectionClass *klass);
79 static void gtk_font_selection_init (GtkFontSelection *fontsel);
80 static void gtk_font_selection_finalize (GObject *object);
82 /* These are the callbacks & related functions. */
83 static void gtk_font_selection_select_font (GtkWidget *w,
86 GdkEventButton *bevent,
88 static gint gtk_font_selection_on_clist_key_press (GtkWidget *clist,
90 GtkFontSelection *fs);
91 static gboolean gtk_font_selection_select_next (GtkFontSelection *fs,
95 static void gtk_font_selection_show_available_fonts (GtkFontSelection *fs);
97 static void gtk_font_selection_show_available_styles (GtkFontSelection *fs);
98 static void gtk_font_selection_select_best_style (GtkFontSelection *fs,
100 static void gtk_font_selection_select_style (GtkWidget *w,
103 GdkEventButton *bevent,
106 static void gtk_font_selection_select_best_size (GtkFontSelection *fs);
107 static void gtk_font_selection_show_available_sizes (GtkFontSelection *fs);
108 static gint gtk_font_selection_size_key_press (GtkWidget *w,
111 static void gtk_font_selection_select_size (GtkWidget *w,
114 GdkEventButton *bevent,
117 static void gtk_font_selection_expose_list (GtkWidget *w,
118 GdkEventExpose *event,
122 /* Misc. utility functions. */
123 static void gtk_font_selection_load_font (GtkFontSelection *fs);
124 static void gtk_font_selection_update_preview (GtkFontSelection *fs);
126 /* FontSelectionDialog */
127 static void gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass);
128 static void gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag);
130 static gint gtk_font_selection_dialog_on_configure(GtkWidget *widget,
131 GdkEventConfigure *event,
132 GtkFontSelectionDialog *fsd);
134 static GtkWindowClass *font_selection_parent_class = NULL;
135 static GtkVBoxClass *font_selection_dialog_parent_class = NULL;
138 gtk_font_selection_get_type()
140 static GtkType font_selection_type = 0;
142 if(!font_selection_type)
144 static const GtkTypeInfo fontsel_type_info =
147 sizeof (GtkFontSelection),
148 sizeof (GtkFontSelectionClass),
149 (GtkClassInitFunc) gtk_font_selection_class_init,
150 (GtkObjectInitFunc) gtk_font_selection_init,
151 /* reserved_1 */ NULL,
152 /* reserved_2 */ NULL,
153 (GtkClassInitFunc) NULL,
156 font_selection_type = gtk_type_unique (GTK_TYPE_VBOX,
160 return font_selection_type;
164 gtk_font_selection_class_init(GtkFontSelectionClass *klass)
166 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
168 font_selection_parent_class = gtk_type_class (GTK_TYPE_VBOX);
170 gobject_class->finalize = gtk_font_selection_finalize;
174 gtk_font_selection_init(GtkFontSelection *fontsel)
176 GtkWidget *scrolled_win;
177 GtkWidget *text_frame;
179 GtkWidget *table, *label;
181 fontsel->context = gtk_widget_create_pango_context (GTK_WIDGET (fontsel));
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_label = gtk_label_new(_("Family:"));
191 gtk_misc_set_alignment (GTK_MISC (fontsel->font_label), 0.0, 0.5);
192 gtk_widget_show (fontsel->font_label);
193 gtk_table_attach (GTK_TABLE (table), fontsel->font_label, 0, 1, 0, 1,
195 label = gtk_label_new(_("Style:"));
196 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
197 gtk_widget_show (label);
198 gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,
200 label = gtk_label_new(_("Size:"));
201 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
202 gtk_widget_show (label);
203 gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1,
206 fontsel->font_entry = gtk_entry_new ();
207 gtk_entry_set_editable(GTK_ENTRY(fontsel->font_entry), FALSE);
208 gtk_widget_set_usize (fontsel->font_entry, 20, -1);
209 gtk_widget_show (fontsel->font_entry);
210 gtk_table_attach (GTK_TABLE (table), fontsel->font_entry, 0, 1, 1, 2,
213 fontsel->font_style_entry = gtk_entry_new ();
214 gtk_entry_set_editable (GTK_ENTRY(fontsel->font_style_entry), FALSE);
215 gtk_widget_set_usize (fontsel->font_style_entry, 20, -1);
216 gtk_widget_show (fontsel->font_style_entry);
217 gtk_table_attach (GTK_TABLE (table), fontsel->font_style_entry, 1, 2, 1, 2,
220 fontsel->size_entry = gtk_entry_new ();
221 gtk_widget_set_usize (fontsel->size_entry, 20, -1);
222 gtk_widget_show (fontsel->size_entry);
223 gtk_table_attach (GTK_TABLE (table), fontsel->size_entry, 2, 3, 1, 2,
225 gtk_signal_connect (GTK_OBJECT (fontsel->size_entry), "key_press_event",
226 (GtkSignalFunc) gtk_font_selection_size_key_press,
229 /* Create the clists */
230 fontsel->font_clist = gtk_clist_new (1);
231 gtk_clist_column_titles_hide (GTK_CLIST (fontsel->font_clist));
232 gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_clist), 0, TRUE);
233 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
234 gtk_widget_set_usize (scrolled_win, FONT_LIST_WIDTH, FONT_LIST_HEIGHT);
235 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_clist);
236 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
237 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
238 gtk_widget_show(fontsel->font_clist);
239 gtk_widget_show(scrolled_win);
241 gtk_table_attach (GTK_TABLE (table), scrolled_win, 0, 1, 2, 3,
242 GTK_EXPAND | GTK_FILL,
243 GTK_EXPAND | GTK_FILL, 0, 0);
245 fontsel->font_style_clist = gtk_clist_new (1);
246 gtk_clist_column_titles_hide (GTK_CLIST (fontsel->font_style_clist));
247 gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_style_clist),
249 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
250 gtk_widget_set_usize (scrolled_win, FONT_STYLE_LIST_WIDTH, -1);
251 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_style_clist);
252 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
253 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
254 gtk_widget_show(fontsel->font_style_clist);
255 gtk_widget_show(scrolled_win);
256 gtk_table_attach (GTK_TABLE (table), scrolled_win, 1, 2, 2, 3,
257 GTK_EXPAND | GTK_FILL,
258 GTK_EXPAND | GTK_FILL, 0, 0);
260 fontsel->size_clist = gtk_clist_new (1);
261 gtk_clist_column_titles_hide (GTK_CLIST(fontsel->size_clist));
262 gtk_clist_set_column_width (GTK_CLIST(fontsel->size_clist), 0, 20);
263 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
264 gtk_widget_set_usize (scrolled_win, FONT_SIZE_LIST_WIDTH, -1);
265 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->size_clist);
266 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
267 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
268 gtk_widget_show (fontsel->size_clist);
269 gtk_widget_show (scrolled_win);
270 gtk_table_attach (GTK_TABLE (table), scrolled_win, 2, 3, 2, 3,
271 GTK_FILL, GTK_FILL, 0, 0);
273 /* Insert the fonts. If there exist fonts with the same family but
274 different foundries, then the foundry name is appended in brackets. */
275 gtk_font_selection_show_available_fonts(fontsel);
277 gtk_signal_connect (GTK_OBJECT (fontsel->font_clist), "select_row",
278 GTK_SIGNAL_FUNC(gtk_font_selection_select_font),
280 GTK_WIDGET_SET_FLAGS (fontsel->font_clist, GTK_CAN_FOCUS);
281 gtk_signal_connect (GTK_OBJECT (fontsel->font_clist), "key_press_event",
282 GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press),
284 gtk_signal_connect_after (GTK_OBJECT (fontsel->font_clist), "expose_event",
285 GTK_SIGNAL_FUNC(gtk_font_selection_expose_list),
288 gtk_font_selection_show_available_styles (fontsel);
290 gtk_signal_connect (GTK_OBJECT (fontsel->font_style_clist), "select_row",
291 GTK_SIGNAL_FUNC(gtk_font_selection_select_style),
293 GTK_WIDGET_SET_FLAGS (fontsel->font_style_clist, GTK_CAN_FOCUS);
294 gtk_signal_connect (GTK_OBJECT (fontsel->font_style_clist),
296 GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press),
299 gtk_font_selection_show_available_sizes (fontsel);
301 gtk_signal_connect (GTK_OBJECT (fontsel->size_clist), "select_row",
302 GTK_SIGNAL_FUNC(gtk_font_selection_select_size),
304 GTK_WIDGET_SET_FLAGS (fontsel->size_clist, GTK_CAN_FOCUS);
305 gtk_signal_connect (GTK_OBJECT (fontsel->size_clist), "key_press_event",
306 GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press),
309 /* create the text entry widget */
310 text_frame = gtk_frame_new (_("Preview:"));
311 gtk_widget_show (text_frame);
312 gtk_frame_set_shadow_type(GTK_FRAME(text_frame), GTK_SHADOW_ETCHED_IN);
313 gtk_box_pack_start (GTK_BOX (fontsel), text_frame,
316 /* This is just used to get a 4-pixel space around the preview entry. */
317 text_box = gtk_hbox_new (FALSE, 0);
318 gtk_widget_show (text_box);
319 gtk_container_add (GTK_CONTAINER (text_frame), text_box);
320 gtk_container_set_border_width (GTK_CONTAINER (text_box), 4);
322 fontsel->preview_entry = gtk_entry_new ();
323 gtk_widget_show (fontsel->preview_entry);
324 gtk_widget_set_usize (fontsel->preview_entry, -1, INITIAL_PREVIEW_HEIGHT);
325 gtk_box_pack_start (GTK_BOX (text_box), fontsel->preview_entry,
328 gtk_font_selection_update_preview (fontsel);
332 gtk_font_selection_new()
334 GtkFontSelection *fontsel;
336 fontsel = gtk_type_new (GTK_TYPE_FONT_SELECTION);
338 return GTK_WIDGET (fontsel);
342 gtk_font_selection_finalize (GObject *object)
344 GtkFontSelection *fontsel;
346 g_return_if_fail (object != NULL);
347 g_return_if_fail (GTK_IS_FONT_SELECTION (object));
349 fontsel = GTK_FONT_SELECTION (object);
351 pango_context_unref (fontsel->context);
352 pango_font_description_free (fontsel->font_desc);
355 gdk_font_unref (fontsel->font);
357 if (G_OBJECT_CLASS (font_selection_parent_class)->finalize)
358 (* G_OBJECT_CLASS (font_selection_parent_class)->finalize) (object);
362 /* This is called when the clist is exposed. Here we scroll to the current
363 font if necessary. */
365 gtk_font_selection_expose_list (GtkWidget *widget,
366 GdkEventExpose *event,
369 GtkFontSelection *fontsel;
374 g_message("In expose_list\n");
376 fontsel = GTK_FONT_SELECTION(data);
378 /* Try to scroll the font family clist to the selected item */
379 selection = GTK_CLIST(fontsel->font_clist)->selection;
382 index = GPOINTER_TO_INT (selection->data);
383 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_clist), index)
384 != GTK_VISIBILITY_FULL)
385 gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), index, -1, 0.5, 0);
388 /* Try to scroll the font style clist to the selected item */
389 selection = GTK_CLIST(fontsel->font_style_clist)->selection;
392 index = GPOINTER_TO_INT (selection->data);
393 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_style_clist), index)
394 != GTK_VISIBILITY_FULL)
395 gtk_clist_moveto(GTK_CLIST(fontsel->font_style_clist), index, -1,
399 /* Try to scroll the font size clist to the selected item */
400 selection = GTK_CLIST(fontsel->size_clist)->selection;
403 index = GPOINTER_TO_INT (selection->data);
404 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->size_clist), index)
405 != GTK_VISIBILITY_FULL)
406 gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), index, -1, 0.5, 0);
410 /* This is called when a family is selected in the list. */
412 gtk_font_selection_select_font (GtkWidget *w,
415 GdkEventButton *bevent,
418 GtkFontSelection *fontsel;
422 fontsel = GTK_FONT_SELECTION (data);
424 if (GTK_CLIST (fontsel->font_clist)->selection)
426 index = GPOINTER_TO_INT (GTK_CLIST (fontsel->font_clist)->selection->data);
428 if (gtk_clist_get_text (GTK_CLIST (fontsel->font_clist), index, 0, &family_name) &&
429 strcasecmp (fontsel->font_desc->family_name, family_name) != 0)
431 g_free (fontsel->font_desc->family_name);
432 fontsel->font_desc->family_name = g_strdup (family_name);
434 gtk_font_selection_show_available_styles (fontsel);
435 gtk_font_selection_select_best_style (fontsel, TRUE);
441 cmp_strings (const void *a, const void *b)
443 return strcasecmp (*(const char **)a, *(const char **)b);
447 gtk_font_selection_show_available_fonts (GtkFontSelection *fontsel)
452 pango_context_list_families (fontsel->context, &families, &n_families);
453 qsort (families, n_families, sizeof(char *), cmp_strings);
455 gtk_clist_freeze (GTK_CLIST (fontsel->font_clist));
456 gtk_clist_clear (GTK_CLIST (fontsel->font_clist));
458 for (i=0; i<n_families; i++)
460 gtk_clist_append (GTK_CLIST (fontsel->font_clist), &families[i]);
462 if (!strcasecmp (families[i], fontsel->font_desc->family_name))
464 gtk_clist_select_row (GTK_CLIST(fontsel->font_clist), i, 0);
465 gtk_entry_set_text(GTK_ENTRY(fontsel->font_entry), families[i]);
469 gtk_clist_thaw (GTK_CLIST(fontsel->font_clist));
471 pango_font_map_free_families (families, n_families);
475 gtk_font_selection_on_clist_key_press (GtkWidget *clist,
477 GtkFontSelection *fontsel)
480 g_message("In on_clist_key_press\n");
482 if (event->keyval == GDK_Up)
483 return gtk_font_selection_select_next (fontsel, clist, -1);
484 else if (event->keyval == GDK_Down)
485 return gtk_font_selection_select_next (fontsel, clist, 1);
492 gtk_font_selection_select_next (GtkFontSelection *fontsel,
497 gint current_row, row;
499 selection = GTK_CLIST(clist)->selection;
502 current_row = GPOINTER_TO_INT (selection->data);
504 /* Stop the normal clist key handler from being run. */
505 gtk_signal_emit_stop_by_name (GTK_OBJECT (clist), "key_press_event");
507 for (row = current_row + step;
508 row >= 0 && row < GTK_CLIST(clist)->rows;
511 /* If this is the style clist, make sure that the item is not a charset
513 if (clist == fontsel->font_style_clist)
514 if (GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(clist), row)) == -1)
517 /* Now we've found the row to select. */
518 if (gtk_clist_row_is_visible(GTK_CLIST(clist), row)
519 != GTK_VISIBILITY_FULL)
520 gtk_clist_moveto(GTK_CLIST(clist), row, -1, (step < 0) ? 0 : 1, 0);
521 gtk_clist_select_row(GTK_CLIST(clist), row, 0);
528 compare_font_descriptions (const PangoFontDescription *a, const PangoFontDescription *b)
530 int val = strcasecmp (a->family_name, b->family_name);
534 if (a->weight != b->weight)
535 return a->weight - b->weight;
537 if (a->style != b->style)
538 return a->style - b->style;
540 if (a->stretch != b->stretch)
541 return a->stretch - b->stretch;
543 if (a->variant != b->variant)
544 return a->variant - b->variant;
550 font_description_sort_func (const void *a, const void *b)
552 return compare_font_descriptions (*(PangoFontDescription **)a, *(PangoFontDescription **)b);
555 /* This fills the font style clist with all the possible style combinations
556 for the current font family. */
558 gtk_font_selection_show_available_styles (GtkFontSelection *fontsel)
560 PangoFontDescription **descs;
565 pango_context_list_fonts (fontsel->context, fontsel->font_desc->family_name, &descs, &n_descs);
566 qsort (descs, n_descs, sizeof(PangoFontDescription *), font_description_sort_func);
568 gtk_clist_freeze (GTK_CLIST (fontsel->font_style_clist));
569 gtk_clist_clear (GTK_CLIST (fontsel->font_style_clist));
571 for (i=0; i<n_descs; i++)
573 PangoFontDescription tmp_desc;
575 tmp_desc = *descs[i];
576 tmp_desc.family_name = NULL;
579 str = pango_font_description_to_string (&tmp_desc);
580 gtk_clist_append (GTK_CLIST (fontsel->font_style_clist), &str);
582 if (descs[i]->weight == fontsel->font_desc->weight &&
583 descs[i]->style == fontsel->font_desc->style &&
584 descs[i]->stretch == fontsel->font_desc->stretch &&
585 descs[i]->variant == fontsel->font_desc->variant)
591 gtk_clist_select_row (GTK_CLIST (fontsel->font_style_clist), match_row, 0);
592 gtk_clist_get_text (GTK_CLIST (fontsel->font_style_clist), match_row, 0, &str);
593 gtk_entry_set_text (GTK_ENTRY (fontsel->font_style_entry), str);
595 gtk_clist_thaw (GTK_CLIST(fontsel->font_style_clist));
597 pango_font_descriptions_free (descs, n_descs);
601 /* This selects a style when the user selects a font. It just uses the first
602 available style at present. I was thinking of trying to maintain the
603 selected style, e.g. bold italic, when the user selects different fonts.
604 However, the interface is so easy to use now I'm not sure it's worth it.
605 Note: This will load a font. */
607 gtk_font_selection_select_best_style(GtkFontSelection *fontsel,
612 gtk_clist_select_row(GTK_CLIST(fontsel->font_style_clist), best_row, 0);
613 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_style_clist), best_row)
614 != GTK_VISIBILITY_FULL)
615 gtk_clist_moveto(GTK_CLIST(fontsel->font_style_clist), best_row, -1,
617 gtk_font_selection_show_available_sizes (fontsel);
618 gtk_font_selection_select_best_size (fontsel);
622 /* This is called when a style is selected in the list. */
624 gtk_font_selection_select_style (GtkWidget *w,
627 GdkEventButton *bevent,
630 GtkFontSelection *fontsel = GTK_FONT_SELECTION (data);
631 PangoFontDescription *tmp_desc;
635 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
636 gtk_widget_grab_focus (w);
638 if (GTK_CLIST (fontsel->font_style_clist)->selection)
640 index = GPOINTER_TO_INT (GTK_CLIST (fontsel->font_style_clist)->selection->data);
642 if (gtk_clist_get_text (GTK_CLIST (fontsel->font_style_clist), index, 0, &text))
644 tmp_desc = pango_font_description_from_string (text);
646 fontsel->font_desc->style = tmp_desc->style;
647 fontsel->font_desc->variant = tmp_desc->variant;
648 fontsel->font_desc->weight = tmp_desc->weight;
649 fontsel->font_desc->stretch = tmp_desc->stretch;
651 pango_font_description_free (tmp_desc);
655 gtk_font_selection_show_available_sizes (fontsel);
656 gtk_font_selection_select_best_size (fontsel);
660 gtk_font_selection_show_available_sizes (GtkFontSelection *fontsel)
666 /* Insert the standard font sizes */
667 gtk_clist_freeze (GTK_CLIST (fontsel->size_clist));
668 gtk_clist_clear (GTK_CLIST (fontsel->size_clist));
670 for (i = 0; i < G_N_ELEMENTS (font_sizes); i++)
672 sprintf(buffer, "%i", font_sizes[i]);
674 gtk_clist_append (GTK_CLIST(fontsel->size_clist), &size);
675 if (font_sizes[i] * PANGO_SCALE == fontsel->font_desc->size)
676 gtk_clist_select_row(GTK_CLIST(fontsel->size_clist), i, 0);
678 gtk_clist_thaw (GTK_CLIST(fontsel->size_clist));
680 sprintf (buffer, "%i", fontsel->font_desc->size / PANGO_SCALE);
681 gtk_entry_set_text (GTK_ENTRY(fontsel->size_entry), buffer);
685 gtk_font_selection_select_best_size (GtkFontSelection *fontsel)
687 gtk_font_selection_load_font (fontsel);
690 /* If the user hits return in the font size entry, we change to the new font
693 gtk_font_selection_size_key_press (GtkWidget *w,
697 GtkFontSelection *fontsel;
701 fontsel = GTK_FONT_SELECTION (data);
703 if (event->keyval == GDK_Return)
705 text = gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry));
706 new_size = atoi (text) * PANGO_SCALE;
708 if (fontsel->font_desc->size != new_size)
710 fontsel->font_desc->size = new_size;
711 gtk_font_selection_load_font (fontsel);
718 /* This is called when a size is selected in the list. */
720 gtk_font_selection_select_size (GtkWidget *w,
723 GdkEventButton *bevent,
726 GtkFontSelection *fontsel;
730 fontsel = GTK_FONT_SELECTION (data);
732 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
733 gtk_widget_grab_focus (w);
735 gtk_clist_get_text(GTK_CLIST(fontsel->size_clist), row, 0, &text);
736 new_size = atoi (text) * PANGO_SCALE;
738 if (fontsel->font_desc->size != new_size)
740 /* If the size was selected by the user we set the selected_size. */
741 fontsel->font_desc->size = new_size;
743 gtk_font_selection_load_font (fontsel);
748 gtk_font_selection_load_font (GtkFontSelection *fontsel)
751 gdk_font_unref (fontsel->font);
752 fontsel->font = NULL;
754 gtk_font_selection_update_preview (fontsel);
757 /* This sets the font in the preview entry to the selected font, and tries to
758 make sure that the preview entry is a reasonable size, i.e. so that the
759 text can be seen with a bit of space to spare. But it tries to avoid
760 resizing the entry every time the font changes.
761 This also used to shrink the preview if the font size was decreased, but
762 that made it awkward if the user wanted to resize the window themself. */
764 gtk_font_selection_update_preview (GtkFontSelection *fontsel)
766 GtkRcStyle *rc_style;
768 GtkRequisition old_requisition;
769 GtkWidget *preview_entry = fontsel->preview_entry;
772 gtk_widget_get_child_requisition (preview_entry, &old_requisition);
774 rc_style = gtk_rc_style_new ();
775 rc_style->font_desc = pango_font_description_copy (fontsel->font_desc);
776 gtk_widget_modify_style (preview_entry, rc_style);
777 gtk_rc_style_unref (rc_style);
779 gtk_widget_size_request (preview_entry, NULL);
781 /* We don't ever want to be over MAX_PREVIEW_HEIGHT pixels high. */
782 new_height = CLAMP (preview_entry->requisition.height, INITIAL_PREVIEW_HEIGHT, MAX_PREVIEW_HEIGHT);
784 if (new_height > old_requisition.height || new_height < old_requisition.height - 30)
785 gtk_widget_set_usize(preview_entry, -1, new_height);
787 /* This sets the preview text, if it hasn't been set already. */
788 text = gtk_entry_get_text(GTK_ENTRY(preview_entry));
789 if (strlen(text) == 0)
790 gtk_entry_set_text(GTK_ENTRY(preview_entry), PREVIEW_TEXT);
791 gtk_entry_set_position(GTK_ENTRY(preview_entry), 0);
794 /*****************************************************************************
795 * These functions are the main public interface for getting/setting the font.
796 *****************************************************************************/
799 gtk_font_selection_get_font (GtkFontSelection *fontsel)
802 fontsel->font = gdk_font_from_description (fontsel->font_desc);
804 return fontsel->font;
809 gtk_font_selection_get_font_name (GtkFontSelection *fontsel)
811 return pango_font_description_to_string (fontsel->font_desc);
815 /* This sets the current font, selecting the appropriate clist rows.
816 First we check the fontname is valid and try to find the font family
817 - i.e. the name in the main list. If we can't find that, then just return.
818 Next we try to set each of the properties according to the fontname.
819 Finally we select the font family & style in the clists. */
821 gtk_font_selection_set_font_name (GtkFontSelection *fontsel,
822 const gchar *fontname)
824 PangoFontDescription *new_desc;
825 PangoFontDescription **descs;
827 gboolean found = FALSE;
829 g_return_val_if_fail (fontsel != NULL, FALSE);
830 g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), FALSE);
832 new_desc = pango_font_description_from_string (fontname);
834 /* Check to make sure that this is in the list of allowed fonts */
836 pango_context_list_fonts (fontsel->context, new_desc->family_name, &descs, &n_descs);
838 for (i=0; i<n_descs; i++)
840 if (descs[i]->weight == new_desc->weight &&
841 descs[i]->style == new_desc->style &&
842 descs[i]->stretch == new_desc->stretch &&
843 descs[i]->variant == new_desc->variant)
850 pango_font_descriptions_free (descs, n_descs);
855 pango_font_description_free (fontsel->font_desc);
856 fontsel->font_desc = new_desc;
862 /* This returns the text in the preview entry. You should copy the returned
863 text if you need it. */
865 gtk_font_selection_get_preview_text (GtkFontSelection *fontsel)
867 return gtk_entry_get_text (GTK_ENTRY (fontsel->preview_entry));
871 /* This sets the text in the preview entry. */
873 gtk_font_selection_set_preview_text (GtkFontSelection *fontsel,
876 gtk_entry_set_text (GTK_ENTRY (fontsel->preview_entry), text);
879 /*****************************************************************************
880 * GtkFontSelectionDialog
881 *****************************************************************************/
884 gtk_font_selection_dialog_get_type (void)
886 static guint font_selection_dialog_type = 0;
888 if (!font_selection_dialog_type)
890 GtkTypeInfo fontsel_diag_info =
892 "GtkFontSelectionDialog",
893 sizeof (GtkFontSelectionDialog),
894 sizeof (GtkFontSelectionDialogClass),
895 (GtkClassInitFunc) gtk_font_selection_dialog_class_init,
896 (GtkObjectInitFunc) gtk_font_selection_dialog_init,
897 /* reserved_1 */ NULL,
898 /* reserved_2 */ NULL,
899 (GtkClassInitFunc) NULL,
902 font_selection_dialog_type = gtk_type_unique (GTK_TYPE_WINDOW, &fontsel_diag_info);
905 return font_selection_dialog_type;
909 gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass)
911 GtkObjectClass *object_class;
913 object_class = (GtkObjectClass*) klass;
915 font_selection_dialog_parent_class = gtk_type_class (GTK_TYPE_WINDOW);
919 gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag)
921 fontseldiag->dialog_width = -1;
922 fontseldiag->auto_resize = TRUE;
924 gtk_widget_set_events(GTK_WIDGET(fontseldiag), GDK_STRUCTURE_MASK);
925 gtk_signal_connect (GTK_OBJECT (fontseldiag), "configure_event",
926 (GtkSignalFunc) gtk_font_selection_dialog_on_configure,
929 gtk_container_set_border_width (GTK_CONTAINER (fontseldiag), 4);
930 gtk_window_set_policy(GTK_WINDOW(fontseldiag), FALSE, TRUE, TRUE);
932 fontseldiag->main_vbox = gtk_vbox_new (FALSE, 4);
933 gtk_widget_show (fontseldiag->main_vbox);
934 gtk_container_add (GTK_CONTAINER (fontseldiag), fontseldiag->main_vbox);
936 fontseldiag->fontsel = gtk_font_selection_new();
937 gtk_container_set_border_width (GTK_CONTAINER (fontseldiag->fontsel), 4);
938 gtk_widget_show (fontseldiag->fontsel);
939 gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox),
940 fontseldiag->fontsel, TRUE, TRUE, 0);
942 /* Create the action area */
943 fontseldiag->action_area = gtk_hbutton_box_new ();
944 gtk_button_box_set_layout(GTK_BUTTON_BOX(fontseldiag->action_area),
946 gtk_button_box_set_spacing(GTK_BUTTON_BOX(fontseldiag->action_area), 5);
947 gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox),
948 fontseldiag->action_area, FALSE, FALSE, 0);
949 gtk_widget_show (fontseldiag->action_area);
951 fontseldiag->ok_button = gtk_button_new_with_label(_("OK"));
952 GTK_WIDGET_SET_FLAGS (fontseldiag->ok_button, GTK_CAN_DEFAULT);
953 gtk_widget_show(fontseldiag->ok_button);
954 gtk_box_pack_start (GTK_BOX (fontseldiag->action_area),
955 fontseldiag->ok_button, TRUE, TRUE, 0);
956 gtk_widget_grab_default (fontseldiag->ok_button);
958 fontseldiag->apply_button = gtk_button_new_with_label(_("Apply"));
959 GTK_WIDGET_SET_FLAGS (fontseldiag->apply_button, GTK_CAN_DEFAULT);
960 /*gtk_widget_show(fontseldiag->apply_button);*/
961 gtk_box_pack_start (GTK_BOX(fontseldiag->action_area),
962 fontseldiag->apply_button, TRUE, TRUE, 0);
964 fontseldiag->cancel_button = gtk_button_new_with_label(_("Cancel"));
965 GTK_WIDGET_SET_FLAGS (fontseldiag->cancel_button, GTK_CAN_DEFAULT);
966 gtk_widget_show(fontseldiag->cancel_button);
967 gtk_box_pack_start (GTK_BOX(fontseldiag->action_area),
968 fontseldiag->cancel_button, TRUE, TRUE, 0);
974 gtk_font_selection_dialog_new (const gchar *title)
976 GtkFontSelectionDialog *fontseldiag;
978 fontseldiag = gtk_type_new (GTK_TYPE_FONT_SELECTION_DIALOG);
979 gtk_window_set_title (GTK_WINDOW (fontseldiag),
980 title ? title : _("Font Selection"));
982 return GTK_WIDGET (fontseldiag);
986 gtk_font_selection_dialog_get_font_name (GtkFontSelectionDialog *fsd)
988 return gtk_font_selection_get_font_name(GTK_FONT_SELECTION(fsd->fontsel));
992 gtk_font_selection_dialog_get_font (GtkFontSelectionDialog *fsd)
994 return gtk_font_selection_get_font(GTK_FONT_SELECTION(fsd->fontsel));
998 gtk_font_selection_dialog_set_font_name (GtkFontSelectionDialog *fsd,
999 const gchar *fontname)
1001 return gtk_font_selection_set_font_name(GTK_FONT_SELECTION(fsd->fontsel),
1006 gtk_font_selection_dialog_get_preview_text (GtkFontSelectionDialog *fsd)
1008 return gtk_font_selection_get_preview_text(GTK_FONT_SELECTION(fsd->fontsel));
1012 gtk_font_selection_dialog_set_preview_text (GtkFontSelectionDialog *fsd,
1015 gtk_font_selection_set_preview_text(GTK_FONT_SELECTION(fsd->fontsel), text);
1019 /* This turns auto-shrink off if the user resizes the width of the dialog.
1020 It also turns it back on again if the user resizes it back to its normal
1023 gtk_font_selection_dialog_on_configure (GtkWidget *widget,
1024 GdkEventConfigure *event,
1025 GtkFontSelectionDialog *fsd)
1027 /* This sets the initial width. */
1028 if (fsd->dialog_width == -1)
1029 fsd->dialog_width = event->width;
1030 else if (fsd->auto_resize && fsd->dialog_width != event->width)
1032 fsd->auto_resize = FALSE;
1033 gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, FALSE);
1035 else if (!fsd->auto_resize && fsd->dialog_width == event->width)
1037 fsd->auto_resize = TRUE;
1038 gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, TRUE);