X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkfontchooser.c;h=6f16b13a5f6594b2c1902cc7f687bb54be4a066d;hb=51ecaa062dcdd7937c5bd4d611079d590755fd32;hp=70d8cd1e784d573cdc1949da7047b8ac8dd80fd2;hpb=1dda502bcb246171db1e006468a2f4008bb9e96a;p=~andy%2Fgtk diff --git a/gtk/gtkfontchooser.c b/gtk/gtkfontchooser.c index 70d8cd1e7..6f16b13a5 100644 --- a/gtk/gtkfontchooser.c +++ b/gtk/gtkfontchooser.c @@ -1,4 +1,7 @@ /* GTK - The GIMP Toolkit + * gtkfontchooser.c - Abstract interface for font file selectors GUIs + * + * Copyright (C) 2006, Emmanuele Bassi * Copyright (C) 2011 Alberto Ruiz * * This library is free software; you can redistribute it and/or @@ -12,954 +15,166 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ #include "config.h" -#include -#include -#include - -#include - #include "gtkfontchooser.h" -#include "gtkcellrenderertext.h" -#include "gtkentry.h" -#include "gtkframe.h" -#include "gtkhbbox.h" -#include "gtkhbox.h" -#include "gtklabel.h" -#include "gtkliststore.h" -#include "gtkstock.h" -#include "gtktreeselection.h" -#include "gtktreeview.h" -#include "gtkbox.h" -#include "gtkscrolledwindow.h" +#include "gtkfontchooserprivate.h" #include "gtkintl.h" -#include "gtkaccessible.h" -#include "gtkbuildable.h" +#include "gtktypebuiltins.h" #include "gtkprivate.h" -#include "gtkalignment.h" -#include "gtkscale.h" -#include "gtkbox.h" -#include "gtkspinbutton.h" -#include "gtkwidget.h" -#include "gtkgrid.h" /** * SECTION:gtkfontchooser - * @Short_description: A widget for selecting fonts + * @Short_description: Interface implemented by widgets displaying fonts * @Title: GtkFontChooser - * @See_also: #GtkFontChooserDialog - * - * The #GtkFontChooser widget lists the available fonts, styles and sizes, - * allowing the user to select a font. - * It is used in the #GtkFontChooserDialog widget to provide a dialog box for - * selecting fonts. - * - * To set the font which is initially selected, use - * gtk_font_chooser_set_font_name(). + * @See_also: #GtkFontChooserDialog, #GtkFontChooserWidget, #GtkFontButton * - * To get the selected font use gtk_font_chooser_get_font_name(). - * - * To change the text which is shown in the preview area, use - * gtk_font_chooser_set_preview_text(). + * #GtkFontChooser is an interface that can be implemented by widgets + * displaying the list of fonts. In GTK+, the main objects + * that implement this interface are #GtkFontChooserWidget, + * #GtkFontChooserDialog and #GtkFontButton. * * Since: 3.2 */ - -struct _GtkFontChooserPrivate +enum { - GtkWidget *search_entry; - GtkWidget *family_face_list; - GtkListStore *model; - GtkTreeModel *filter; - - GtkWidget *preview; - GtkWidget *preview_scrolled_window; - gchar *preview_text; - gboolean show_preview_entry; - - GtkWidget *size_spin; - GtkWidget *size_slider; - gboolean stop_notify; - - gint size; - PangoFontFace *face; - PangoFontFamily *family; + SIGNAL_FONT_ACTIVATED, + LAST_SIGNAL }; -#define DEFAULT_FONT_NAME "Sans 10" -#define MAX_FONT_SIZE 999 +static guint chooser_signals[LAST_SIGNAL]; -/* This is the initial fixed height and the top padding of the preview entry */ -#define PREVIEW_HEIGHT 72 -#define PREVIEW_TOP_PADDING 6 - -/* These are the sizes of the font, style & size lists. */ -#define FONT_LIST_HEIGHT 136 -#define FONT_LIST_WIDTH 190 -#define FONT_STYLE_LIST_WIDTH 170 -#define FONT_SIZE_LIST_WIDTH 60 - -#define ROW_FORMAT_STRING "%s\n%s" - -/* These are what we use as the standard font sizes, for the size list. - */ -#define FONT_SIZES_LENGTH 14 -static const gint font_sizes[] = { - 6, 8, 9, 10, 11, 12, 13, 14, 16, 20, 24, 36, 48, 72 -}; - -enum { - PROP_0, - PROP_FONT_NAME, - PROP_PREVIEW_TEXT, - PROP_SHOW_PREVIEW_ENTRY -}; - - -enum { - FAMILY_COLUMN, - FACE_COLUMN, - PREVIEW_TEXT_COLUMN, - PREVIEW_TITLE_COLUMN -}; - -static void gtk_font_chooser_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void gtk_font_chooser_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static void gtk_font_chooser_finalize (GObject *object); - -static void gtk_font_chooser_screen_changed (GtkWidget *widget, - GdkScreen *previous_screen); -static void gtk_font_chooser_style_updated (GtkWidget *widget); - -static void gtk_font_chooser_ref_family (GtkFontChooser *fontchooser, - PangoFontFamily *family); -static void gtk_font_chooser_ref_face (GtkFontChooser *fontchooser, - PangoFontFace *face); - -static void gtk_font_chooser_bootstrap_fontlist (GtkFontChooser *fontchooser); - -G_DEFINE_TYPE (GtkFontChooser, gtk_font_chooser, GTK_TYPE_BOX) - -static void -gtk_font_chooser_class_init (GtkFontChooserClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - - widget_class->screen_changed = gtk_font_chooser_screen_changed; - widget_class->style_updated = gtk_font_chooser_style_updated; - - gobject_class->finalize = gtk_font_chooser_finalize; - gobject_class->set_property = gtk_font_chooser_set_property; - gobject_class->get_property = gtk_font_chooser_get_property; - - g_object_class_install_property (gobject_class, - PROP_FONT_NAME, - g_param_spec_string ("font-name", - P_("Font name"), - P_("The string that represents this font"), - DEFAULT_FONT_NAME, - GTK_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, - PROP_PREVIEW_TEXT, - g_param_spec_string ("preview-text", - P_("Preview text"), - P_("The text to display in order to demonstrate the selected font"), - pango_language_get_sample_string (NULL), - GTK_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, - PROP_SHOW_PREVIEW_ENTRY, - g_param_spec_boolean ("show-preview-entry", - P_("Show preview text entry"), - P_("Whether the preview text entry is shown or not"), - TRUE, - GTK_PARAM_READWRITE)); - - g_type_class_add_private (klass, sizeof (GtkFontChooserPrivate)); -} - -static void -gtk_font_chooser_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GtkFontChooser *fontchooser; - - fontchooser = GTK_FONT_CHOOSER (object); - - switch (prop_id) - { - case PROP_FONT_NAME: - gtk_font_chooser_set_font_name (fontchooser, g_value_get_string (value)); - break; - case PROP_PREVIEW_TEXT: - gtk_font_chooser_set_preview_text (fontchooser, g_value_get_string (value)); - break; - case PROP_SHOW_PREVIEW_ENTRY: - gtk_font_chooser_set_show_preview_entry (fontchooser, g_value_get_boolean (value)); - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} +typedef GtkFontChooserIface GtkFontChooserInterface; +G_DEFINE_INTERFACE (GtkFontChooser, gtk_font_chooser, G_TYPE_OBJECT); static void -gtk_font_chooser_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) +gtk_font_chooser_default_init (GtkFontChooserInterface *iface) { - GtkFontChooser *fontchooser; - - fontchooser = GTK_FONT_CHOOSER (object); - - switch (prop_id) - { - case PROP_FONT_NAME: - g_value_take_string (value, gtk_font_chooser_get_font_name (fontchooser)); - break; - case PROP_PREVIEW_TEXT: - g_value_set_string (value, gtk_font_chooser_get_preview_text (fontchooser)); - break; - case PROP_SHOW_PREVIEW_ENTRY: - g_value_set_boolean (value, gtk_font_chooser_get_show_preview_entry (fontchooser)); - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -void -refilter_and_focus (GtkFontChooserPrivate *priv) -{ - GtkTreeIter iter; - GtkTreeView *treeview = GTK_TREE_VIEW (priv->family_face_list); - GtkTreePath *path = gtk_tree_path_new (); - - gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter)); - - if (!path) - return; - - gtk_tree_view_get_cursor (treeview, &path, NULL); - - if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->filter), &iter, path)) - { - gtk_tree_path_free (path); - return; - } - - gtk_tree_view_scroll_to_cell (treeview, path, NULL, FALSE, 0.5, 0.5); - gtk_tree_path_free (path); -} - -void -deleted_text_cb (GtkEntryBuffer *buffer, - guint position, - guint n_chars, - gpointer user_data) -{ - GtkFontChooserPrivate *priv = (GtkFontChooserPrivate*)user_data; - GtkWidget *entry = priv->search_entry; - - if (gtk_entry_buffer_get_length (buffer) == 0) - { - GIcon *icon = g_themed_icon_new_with_default_fallbacks ("edit-find-symbolic"); - gtk_entry_set_icon_from_gicon (GTK_ENTRY (entry), - GTK_ENTRY_ICON_SECONDARY, - icon); - g_object_unref (icon); - } - - gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter)); -} - -void -inserted_text_cb (GtkEntryBuffer *buffer, - guint position, - gchar *chars, - guint n_chars, - gpointer user_data) -{ - GtkFontChooserPrivate *priv = (GtkFontChooserPrivate*)user_data; - GtkWidget *entry = priv->search_entry; - - if (g_strcmp0 (gtk_entry_get_icon_stock (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY), - "edit-clear-symbolic") || - g_strcmp0 (gtk_entry_get_icon_stock (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY), - GTK_STOCK_CLEAR)) - { - GIcon *icon = g_themed_icon_new_with_default_fallbacks ("edit-clear-symbolic"); - gtk_entry_set_icon_from_gicon (GTK_ENTRY (entry), - GTK_ENTRY_ICON_SECONDARY, - icon); - g_object_unref (icon); - } - - gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter)); -} - -void -icon_press_cb (GtkEntry *entry, - GtkEntryIconPosition pos, - GdkEvent *event, - gpointer user_data) -{ - gtk_entry_buffer_delete_text (gtk_entry_get_buffer (entry), 0, -1); -} - -void -slider_change_cb (GtkAdjustment *adjustment, gpointer data) -{ - GtkFontChooserPrivate *priv = (GtkFontChooserPrivate*)data; - GtkAdjustment *spin_adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON (priv->size_spin)); - gdouble slider_value = gtk_adjustment_get_value (adjustment); - gdouble spin_value = gtk_adjustment_get_value (spin_adj); - - if (slider_value != spin_value) - gtk_adjustment_set_value (spin_adj, - gtk_adjustment_get_value (adjustment)); -} - -void -spin_change_cb (GtkAdjustment *adjustment, gpointer data) -{ - PangoFontDescription *desc; - GtkFontChooser *fontchooser = (GtkFontChooser*)data; - GtkFontChooserPrivate *priv = fontchooser->priv; - GtkAdjustment *slider_adj = gtk_range_get_adjustment (GTK_RANGE (priv->size_slider)); - - gdouble size = gtk_adjustment_get_value (adjustment); - priv->size = ((gint)size) * PANGO_SCALE; - - desc = pango_context_get_font_description (gtk_widget_get_pango_context (priv->preview)); - pango_font_description_set_size (desc, priv->size); - gtk_widget_override_font (priv->preview, desc); - - if (priv->stop_notify) - priv->stop_notify = FALSE; - else - g_object_notify (G_OBJECT (fontchooser), "font-name"); - - /* If the new value is lower than the lower bound of the slider, we set - * the slider adjustment to the lower bound value if it is not already set + /** + * GtkFontChooser:font: + * + * The font description as a string, e.g. "Sans Italic 12". */ - if (size < gtk_adjustment_get_lower (slider_adj) && - gtk_adjustment_get_value (slider_adj) != gtk_adjustment_get_lower (slider_adj)) - { - gtk_adjustment_set_value (slider_adj, gtk_adjustment_get_lower (slider_adj)); - priv->stop_notify = TRUE; - } - - /* If the new value is upper than the upper bound of the slider, we set - * the slider adjustment to the upper bound value if it is not already set + g_object_interface_install_property + (iface, + g_param_spec_string ("font", + P_("Font"), + P_("Font description as a string, e.g. \"Sans Italic 12\""), + GTK_FONT_CHOOSER_DEFAULT_FONT_NAME, + GTK_PARAM_READWRITE)); + + /** + * GtkFontChooser:font-desc: + * + * The font description as a #PangoFontDescription. */ - else if (size > gtk_adjustment_get_upper (slider_adj) && - gtk_adjustment_get_value (slider_adj) != gtk_adjustment_get_upper (slider_adj)) - { - gtk_adjustment_set_value (slider_adj, gtk_adjustment_get_upper (slider_adj)); - priv->stop_notify = TRUE; - } - - /* If the new value is not already set on the slider we set it */ - else if (size != gtk_adjustment_get_value (slider_adj)) - { - gtk_adjustment_set_value (slider_adj, size); - priv->stop_notify = TRUE; - } - - gtk_widget_queue_draw (priv->preview); -} - -void -set_range_marks (GtkFontChooserPrivate *priv, - GtkWidget *size_slider, - gint *sizes, - gint length) -{ - GtkAdjustment *adj; - gint i; - gdouble value; - - if (length<2) - { - sizes = (gint*)font_sizes; - length = FONT_SIZES_LENGTH; - } - - gtk_scale_clear_marks (GTK_SCALE (size_slider)); - - adj = gtk_range_get_adjustment(GTK_RANGE (size_slider)); - - gtk_adjustment_set_lower (adj, (gdouble) sizes[0]); - gtk_adjustment_set_upper (adj, (gdouble) sizes[length-1]); - - value = gtk_adjustment_get_value (adj); - if (value > (gdouble) sizes[length-1]) - gtk_adjustment_set_value (adj, (gdouble) sizes[length-1]); - else if (value < (gdouble) sizes[0]) - gtk_adjustment_set_value (adj, (gdouble) sizes[0]); - - for (i=0; ipriv->filter), &iter, path)) - { - gtk_tree_path_free (path); - return; - } - - - gtk_tree_model_get (GTK_TREE_MODEL (fontchooser->priv->filter), &iter, - FACE_COLUMN, &face, - FAMILY_COLUMN, &family, - -1); - - gtk_tree_view_scroll_to_cell (treeview, path, NULL, FALSE, 0.5, 0.5); - - gtk_tree_path_free (path); - path = NULL; - - if (!face || !family) - { - g_object_unref (face); - g_object_unref (family); - return; - } - - desc = pango_font_face_describe (face); - pango_font_description_set_size (desc, fontchooser->priv->size); - gtk_widget_override_font (fontchooser->priv->preview, desc); - - pango_font_face_list_sizes (face, &sizes, &n_sizes); - /* It seems not many fonts actually have a sane set of sizes */ - for (i=0; ipriv, fontchooser->priv->size_slider, sizes, n_sizes); - - gtk_font_chooser_ref_family (fontchooser, family); - gtk_font_chooser_ref_face (fontchooser, face); - - /* Free resources */ - g_object_unref ((gpointer)family); - g_object_unref ((gpointer)face); - pango_font_description_free(desc); - - g_object_notify (G_OBJECT (fontchooser), "font-name"); -} - -gboolean -zoom_preview_cb (GtkWidget *scrolled_window, - GdkEventScroll *event, - gpointer data) -{ - GtkFontChooserPrivate *priv = (GtkFontChooserPrivate*)data; - - GtkAdjustment *adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->size_spin)); - - if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_RIGHT) - gtk_adjustment_set_value (adj, - gtk_adjustment_get_value (adj) + - gtk_adjustment_get_step_increment (adj)); - else if (event->direction == GDK_SCROLL_DOWN || event->direction == GDK_SCROLL_LEFT) - gtk_adjustment_set_value (adj, - gtk_adjustment_get_value (adj) - - gtk_adjustment_get_step_increment (adj)); - return TRUE; -} - -static void -gtk_font_chooser_init (GtkFontChooser *fontchooser) -{ - GIcon *icon; - GtkFontChooserPrivate *priv; - PangoFontDescription *font_desc; - GtkWidget *scrolled_win; - GtkWidget *grid; - GtkWidget *sub_grid; - - fontchooser->priv = G_TYPE_INSTANCE_GET_PRIVATE (fontchooser, - GTK_TYPE_FONT_CHOOSER, - GtkFontChooserPrivate); - - priv = fontchooser->priv; - - /* Default preview string */ - priv->preview_text = g_strdup (pango_language_get_sample_string (NULL)); - priv->show_preview_entry = TRUE; - - /* Getting the default size */ - font_desc = pango_context_get_font_description (gtk_widget_get_pango_context (GTK_WIDGET (fontchooser))); - priv->size = pango_font_description_get_size (font_desc); - priv->face = NULL; - priv->family = NULL; - - gtk_widget_push_composite_child (); - - /* Creating fundamental widgets for the private struct */ - priv->search_entry = gtk_entry_new (); - priv->family_face_list = gtk_tree_view_new (); - priv->preview = gtk_entry_new (); - priv->size_slider = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, - (gdouble) font_sizes[0], - (gdouble) font_sizes[FONT_SIZES_LENGTH - 1], - 1.0); - - priv->size_spin = gtk_spin_button_new_with_range (0.0, (gdouble)(G_MAXINT / PANGO_SCALE), 1.0); - - /** Bootstrapping widget layout **/ - gtk_box_set_spacing (GTK_BOX (fontchooser), 6); - - /* Main font family/face view */ - scrolled_win = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), - GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win), - GTK_SHADOW_ETCHED_IN); - gtk_container_add (GTK_CONTAINER (scrolled_win), priv->family_face_list); - - /* Basic layout */ - grid = gtk_grid_new (); - sub_grid = gtk_grid_new (); - - gtk_grid_attach (GTK_GRID (grid), priv->search_entry, 0, 0, 3, 1); - gtk_grid_attach (GTK_GRID (grid), scrolled_win, 0, 1, 3, 1); - gtk_grid_attach (GTK_GRID (grid), priv->preview, 0, 2, 3, 1); - gtk_grid_attach (GTK_GRID (grid), sub_grid, 0, 3, 3, 1); - - gtk_widget_set_hexpand (GTK_WIDGET (sub_grid), TRUE); - gtk_grid_attach (GTK_GRID (sub_grid), priv->size_slider, 0, 3, 2, 1); - gtk_grid_attach (GTK_GRID (sub_grid), priv->size_spin, 2, 3, 1, 1); - - gtk_widget_set_hexpand (GTK_WIDGET (scrolled_win), TRUE); - gtk_widget_set_vexpand (GTK_WIDGET (scrolled_win), TRUE); - gtk_widget_set_hexpand (GTK_WIDGET (priv->search_entry), TRUE); - - gtk_widget_set_hexpand (GTK_WIDGET (priv->size_slider), TRUE); - gtk_widget_set_hexpand (GTK_WIDGET (priv->size_spin), FALSE); - - gtk_grid_set_column_homogeneous (GTK_GRID (sub_grid), FALSE); - gtk_box_pack_start (GTK_BOX (fontchooser), grid, TRUE, TRUE, 0); - - /* Setting the adjustment values for the size slider */ - gtk_adjustment_set_value (gtk_range_get_adjustment (GTK_RANGE (priv->size_slider)), - (gdouble)(priv->size / PANGO_SCALE)); - gtk_adjustment_set_value (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->size_spin)), - (gdouble)(priv->size / PANGO_SCALE)); - - gtk_widget_show_all (GTK_WIDGET (fontchooser)); - gtk_widget_hide (GTK_WIDGET (fontchooser)); - - /* Treeview column and model bootstrapping */ - gtk_font_chooser_bootstrap_fontlist (fontchooser); - - /* Set default preview text */ - gtk_entry_set_text (GTK_ENTRY (priv->preview), - pango_language_get_sample_string (NULL)); - - /* Set search icon and place holder text */ - icon = g_themed_icon_new_with_default_fallbacks ("edit-find-symbolic"); - gtk_entry_set_icon_from_gicon (GTK_ENTRY (priv->search_entry), - GTK_ENTRY_ICON_SECONDARY, - icon); - g_object_unref (icon); - - gtk_entry_set_placeholder_text (GTK_ENTRY (priv->search_entry), _("Search font name")); - - /** Callback connections **/ - /* Connect to callback for the live search text entry */ - g_signal_connect (G_OBJECT (gtk_entry_get_buffer (GTK_ENTRY (priv->search_entry))), - "deleted-text", G_CALLBACK (deleted_text_cb), priv); - g_signal_connect (G_OBJECT (gtk_entry_get_buffer (GTK_ENTRY (priv->search_entry))), - "inserted-text", G_CALLBACK (inserted_text_cb), priv); - g_signal_connect (G_OBJECT (priv->search_entry), - "icon-press", G_CALLBACK (icon_press_cb), priv); - - /* Size controls callbacks */ - g_signal_connect (G_OBJECT (gtk_range_get_adjustment (GTK_RANGE (priv->size_slider))), - "value-changed", G_CALLBACK (slider_change_cb), priv); - g_signal_connect (G_OBJECT (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->size_spin))), - "value-changed", G_CALLBACK (spin_change_cb), fontchooser); - priv->stop_notify = FALSE; - - /* Font selection callback */ - g_signal_connect (G_OBJECT (priv->family_face_list), "cursor-changed", - G_CALLBACK (cursor_changed_cb), fontchooser); - - /* Zoom on preview scroll*/ - g_signal_connect (G_OBJECT (priv->preview), "scroll-event", - G_CALLBACK (zoom_preview_cb), priv); - - g_signal_connect (G_OBJECT (priv->size_slider), "scroll-event", - G_CALLBACK (zoom_preview_cb), priv); - - set_range_marks (priv, priv->size_slider, (gint*)font_sizes, FONT_SIZES_LENGTH); - - /* Set default focus */ - gtk_widget_pop_composite_child(); -} - -/** - * gtk_font_chooser_new: - * - * Creates a new #GtkFontChooser. - * - * Return value: a new #GtkFontChooser - * - * Since: 3.2 - */ -GtkWidget * -gtk_font_chooser_new (void) -{ - GtkFontChooser *fontchooser; - - fontchooser = g_object_new (GTK_TYPE_FONT_CHOOSER, NULL); - - return GTK_WIDGET (fontchooser); -} - -static int -cmp_families (const void *a, const void *b) -{ - const char *a_name = pango_font_family_get_name (*(PangoFontFamily **)a); - const char *b_name = pango_font_family_get_name (*(PangoFontFamily **)b); - - return g_utf8_collate (a_name, b_name); -} - -static void -populate_list (GtkFontChooser *fontchooser, GtkTreeView* treeview, GtkListStore* model) -{ - GtkStyleContext *style_context; - PangoFontDescription *default_font; - - GtkTreeIter match_row; - GtkTreePath *path; - - gint n_families, i; - PangoFontFamily **families; - - GString *tmp = g_string_new (NULL); - GString *family_and_face = g_string_new (NULL); - - pango_context_list_families (gtk_widget_get_pango_context (GTK_WIDGET (treeview)), - &families, - &n_families); - - qsort (families, n_families, sizeof (PangoFontFamily *), cmp_families); - - gtk_list_store_clear (model); - - /* Get row header font color */ - style_context = gtk_widget_get_style_context (GTK_WIDGET (treeview)); - - /* Get theme font */ - default_font = (PangoFontDescription*) gtk_style_context_get_font (style_context, - GTK_STATE_NORMAL); - - /* Iterate over families and faces */ - for (i=0; istr, - font_desc, - fontchooser->priv->preview_text); - - gtk_list_store_append (model, &iter); - gtk_list_store_set (model, &iter, - FAMILY_COLUMN, families[i], - FACE_COLUMN, faces[j], - PREVIEW_TITLE_COLUMN, family_and_face->str, - PREVIEW_TEXT_COLUMN, tmp->str, - -1); - - /* Select the first font or the default font/face from the style context */ - if ((i == 0 && j == 0) || - (!strcmp (fam_name, pango_font_description_get_family (default_font)) && j == 0)) - match_row = iter; - - pango_font_description_free(pango_desc); - g_free (font_desc); - } - - g_free (faces); - } - - path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &match_row); - - if (path) - { - gtk_tree_view_set_cursor (treeview, path, NULL, FALSE); - gtk_tree_view_scroll_to_cell (treeview, path, NULL, FALSE, 0.5, 0.5); - gtk_tree_path_free(path); - } - - g_string_free (family_and_face, TRUE); - g_string_free (tmp, TRUE); - g_free (families); -} - -gboolean -visible_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer data) -{ - gboolean result = TRUE; - GtkFontChooserPrivate *priv = (GtkFontChooserPrivate*) data; - - const gchar *search_text = (const gchar*)gtk_entry_get_text (GTK_ENTRY (priv->search_entry)); - gchar *font_name; - gchar *term; - gchar **split_terms; - gint n_terms = 0; - - /* If there's no filter string we show the item */ - if (strlen (search_text) == 0) - return TRUE; - - gtk_tree_model_get (model, iter, - PREVIEW_TITLE_COLUMN, &font_name, - -1); - - if (font_name == NULL) - return FALSE; - - split_terms = g_strsplit (search_text, " ", 0); - term = split_terms[0]; - - while (term && result) - { - gchar* font_name_casefold = g_utf8_casefold (font_name, -1); - gchar* term_casefold = g_utf8_casefold (term, -1); - - if (g_strrstr (font_name_casefold, term_casefold)) - result = result && TRUE; - else - result = FALSE; - - n_terms++; - term = split_terms[n_terms]; - - g_free (term_casefold); - g_free (font_name_casefold); - } - - g_free (font_name); - g_strfreev (split_terms); - - return result; -} - -static void -gtk_font_chooser_bootstrap_fontlist (GtkFontChooser* fontchooser) -{ - GtkTreeView *treeview = GTK_TREE_VIEW (fontchooser->priv->family_face_list); - GtkCellRenderer *cell; - GtkTreeViewColumn *col; - - fontchooser->priv->model = gtk_list_store_new (4, - PANGO_TYPE_FONT_FAMILY, - PANGO_TYPE_FONT_FACE, - G_TYPE_STRING, - G_TYPE_STRING); - - fontchooser->priv->filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fontchooser->priv->model), - NULL); - g_object_unref (fontchooser->priv->model); - - gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (fontchooser->priv->filter), - visible_func, - (gpointer)fontchooser->priv, - NULL); - - gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (fontchooser->priv->filter)); - g_object_unref (fontchooser->priv->filter); - - gtk_tree_view_set_rules_hint (treeview, TRUE); - gtk_tree_view_set_headers_visible (treeview, FALSE); - - cell = gtk_cell_renderer_text_new (); - col = gtk_tree_view_column_new_with_attributes ("Family", - cell, - "markup", PREVIEW_TEXT_COLUMN, - NULL); - - g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL); - - gtk_tree_view_append_column (treeview, col); - - populate_list (fontchooser, treeview, fontchooser->priv->model); -} - - -static void -gtk_font_chooser_finalize (GObject *object) -{ - GtkFontChooser *fontchooser = GTK_FONT_CHOOSER (object); - - gtk_font_chooser_ref_family (fontchooser, NULL); - gtk_font_chooser_ref_face (fontchooser, NULL); - - G_OBJECT_CLASS (gtk_font_chooser_parent_class)->finalize (object); -} - - -static void -gtk_font_chooser_screen_changed (GtkWidget *widget, - GdkScreen *previous_screen) -{ - GtkFontChooser *fontchooser = GTK_FONT_CHOOSER (widget); - - populate_list (fontchooser, - GTK_TREE_VIEW (fontchooser->priv->family_face_list), - fontchooser->priv->model); - return; -} - -static void -gtk_font_chooser_style_updated (GtkWidget *widget) -{ - GtkFontChooser *fontchooser = GTK_FONT_CHOOSER (widget); - - GTK_WIDGET_CLASS (gtk_font_chooser_parent_class)->style_updated (widget); - - populate_list (fontchooser, - GTK_TREE_VIEW (fontchooser->priv->family_face_list), - fontchooser->priv->model); - return; -} - -static void -gtk_font_chooser_ref_family (GtkFontChooser *fontchooser, - PangoFontFamily *family) -{ - GtkFontChooserPrivate *priv = fontchooser->priv; - - if (family) - family = g_object_ref (family); - if (priv->family) - g_object_unref (priv->family); - priv->family = family; -} - -static void -gtk_font_chooser_ref_face (GtkFontChooser *fontchooser, - PangoFontFace *face) -{ - GtkFontChooserPrivate *priv = fontchooser->priv; - - if (face) - face = g_object_ref (face); - if (priv->face) - g_object_unref (priv->face); - priv->face = face; + g_object_interface_install_property + (iface, + g_param_spec_boxed ("font-desc", + P_("Font description"), + P_("Font description as a PangoFontDescription struct"), + PANGO_TYPE_FONT_DESCRIPTION, + GTK_PARAM_READWRITE)); + + /** + * GtkFontChooser:preview-text: + * + * The string with which to preview the font. + */ + g_object_interface_install_property + (iface, + g_param_spec_string ("preview-text", + P_("Preview text"), + P_("The text to display in order to demonstrate the selected font"), + pango_language_get_sample_string (NULL), + GTK_PARAM_READWRITE)); + + /** + * GtkFontChooser:show-preview-entry: + * + * Whether to show an entry to change the preview text. + */ + g_object_interface_install_property + (iface, + g_param_spec_boolean ("show-preview-entry", + P_("Show preview text entry"), + P_("Whether the preview text entry is shown or not"), + TRUE, + GTK_PARAM_READWRITE)); + + /** + * GtkFontChooserWidget::font-activated: + * @self: the object which received the signal + * @fontname: the font name + * + * Emitted when a font is activated from the widget's list. + * This usually happens when the user double clicks an item, + * or an item is selected and the user presses one of the keys + * Space, Shift+Space, Return or Enter. + */ + chooser_signals[SIGNAL_FONT_ACTIVATED] = + g_signal_new ("font-activated", + GTK_TYPE_FONT_CHOOSER, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GtkFontChooserIface, font_activated), + NULL, NULL, + NULL, + G_TYPE_NONE, + 1, G_TYPE_STRING); } - -/* - * These functions are the main public interface for getting/setting the font. - */ - /** - * gtk_font_chooser_get_family: + * gtk_font_chooser_get_font_family: * @fontchooser: a #GtkFontChooser * * Gets the #PangoFontFamily representing the selected font family. + * Font families are a collection of font faces. + * + * If the selected font is not installed, returns %NULL. * * Return value: (transfer none): A #PangoFontFamily representing the - * selected font family. Font families are a collection of font - * faces. The returned object is owned by @fontchooser and must not - * be modified or freed. + * selected font family, or %NULL. The returned object is owned by @fontchooser + * and must not be modified or freed. * * Since: 3.2 */ PangoFontFamily * -gtk_font_chooser_get_family (GtkFontChooser *fontchooser) +gtk_font_chooser_get_font_family (GtkFontChooser *fontchooser) { g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), NULL); - return fontchooser->priv->family; + return GTK_FONT_CHOOSER_GET_IFACE (fontchooser)->get_font_family (fontchooser); } /** - * gtk_font_chooser_get_face: + * gtk_font_chooser_get_font_face: * @fontchooser: a #GtkFontChooser * * Gets the #PangoFontFace representing the selected font group * details (i.e. family, slant, weight, width, etc). * + * If the selected font is not installed, returns %NULL. + * * Return value: (transfer none): A #PangoFontFace representing the - * selected font group details. The returned object is owned by + * selected font group details, or %NULL. The returned object is owned by * @fontchooser and must not be modified or freed. * * Since: 3.2 */ PangoFontFace * -gtk_font_chooser_get_face (GtkFontChooser *fontchooser) +gtk_font_chooser_get_font_face (GtkFontChooser *fontchooser) { g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), NULL); - return fontchooser->priv->face; + return GTK_FONT_CHOOSER_GET_IFACE (fontchooser)->get_font_face (fontchooser); } /** - * gtk_font_chooser_get_size: + * gtk_font_chooser_get_font_size: * @fontchooser: a #GtkFontChooser * * The selected font size. @@ -968,163 +183,117 @@ gtk_font_chooser_get_face (GtkFontChooser *fontchooser) * or -1 if no font size is selected. * * Since: 3.2 - **/ + */ gint -gtk_font_chooser_get_size (GtkFontChooser *fontchooser) +gtk_font_chooser_get_font_size (GtkFontChooser *fontchooser) { g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), -1); - return fontchooser->priv->size; + return GTK_FONT_CHOOSER_GET_IFACE (fontchooser)->get_font_size (fontchooser); } /** - * gtk_font_chooser_get_font_name: + * gtk_font_chooser_get_font: * @fontchooser: a #GtkFontChooser - * - * Gets the currently-selected font name. * - * Note that this can be a different string than what you set with - * gtk_font_chooser_set_font_name(), as the font chooser widget may - * normalize font names and thus return a string with a different structure. - * For example, "Helvetica Italic Bold 12" could be normalized to - * "Helvetica Bold Italic 12". Use pango_font_description_equal() - * if you want to compare two font descriptions. - * - * Return value: (transfer full) (allow-none): A string with the name of the - * current font, or %NULL if no font is selected. You must free this - * string with g_free(). + * Gets the currently-selected font name. + * + * Note that this can be a different string than what you set with + * gtk_font_chooser_set_font(), as the font chooser widget may + * normalize font names and thus return a string with a different + * structure. For example, "Helvetica Italic Bold 12" could be + * normalized to "Helvetica Bold Italic 12". + * + * Use pango_font_description_equal() if you want to compare two + * font descriptions. + * + * Return value: (transfer full) (allow-none): A string with the name + * of the current font, or %NULL if no font is selected. You must + * free this string with g_free(). * * Since: 3.2 */ gchar * -gtk_font_chooser_get_font_name (GtkFontChooser *fontchooser) +gtk_font_chooser_get_font (GtkFontChooser *fontchooser) { - gchar *font_name; - PangoFontDescription *desc; + gchar *fontname; - if (!fontchooser->priv->face) - return NULL; + g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), NULL); + + g_object_get (fontchooser, "font", &fontname, NULL); - desc = pango_font_face_describe (fontchooser->priv->face); - font_name = pango_font_description_to_string (desc); - pango_font_description_free (desc); - return font_name; -} -/* This sets the current font, then selecting the appropriate list rows. */ + return fontname; +} /** - * gtk_font_chooser_set_font_name: + * gtk_font_chooser_set_font: * @fontchooser: a #GtkFontChooser * @fontname: a font name like "Helvetica 12" or "Times Bold 18" - * - * Sets the currently-selected font. * - * Note that the @fontchooser needs to know the screen in which it will appear - * for this to work; this can be guaranteed by simply making sure that the - * @fontchooser is inserted in a toplevel window before you call this function. - * - * Return value: %TRUE if the font could be set successfully; %FALSE if no - * such font exists or if the @fontchooser doesn't belong to a particular - * screen yet. + * Sets the currently-selected font. * * Since: 3.2 */ -gboolean -gtk_font_chooser_set_font_name (GtkFontChooser *fontchooser, - const gchar *fontname) +void +gtk_font_chooser_set_font (GtkFontChooser *fontchooser, + const gchar *fontname) { - GtkFontChooserPrivate *priv = fontchooser->priv; - GtkTreeIter iter; - gboolean valid; - gchar *family_name; - PangoFontDescription *desc; - gboolean found = FALSE; - - g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), FALSE); - g_return_val_if_fail (fontname != NULL, FALSE); - - if (!gtk_widget_has_screen (GTK_WIDGET (fontchooser))) - return FALSE; - - desc = pango_font_description_from_string (fontname); - family_name = (gchar*)pango_font_description_get_family (desc); - - if (!family_name) - { - pango_font_description_free (desc); - return FALSE; - } - - /* We make sure the filter is clear */ - gtk_entry_set_text (GTK_ENTRY (priv->search_entry), ""); - - /* We find the matching family/face */ - for (valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->filter), &iter); - valid; - valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->filter), &iter)) - { - PangoFontFace *face; - PangoFontDescription *tmp_desc; - - gtk_tree_model_get (GTK_TREE_MODEL (priv->filter), &iter, - FACE_COLUMN, &face, - -1); - - tmp_desc = pango_font_face_describe (face); - if (pango_font_description_get_size_is_absolute (desc)) - pango_font_description_set_absolute_size (tmp_desc, - pango_font_description_get_size (desc)); - else - pango_font_description_set_size (tmp_desc, - pango_font_description_get_size (desc)); - - - if (pango_font_description_equal (desc, tmp_desc)) - { - GtkTreePath *path; - gint size = pango_font_description_get_size (desc); - - if (size) - { - if (pango_font_description_get_size_is_absolute (desc)) - size = size * PANGO_SCALE; - gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->size_spin), - size / PANGO_SCALE); - } + g_return_if_fail (GTK_IS_FONT_CHOOSER (fontchooser)); + g_return_if_fail (fontname != NULL); - path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->filter), - &iter); + g_object_set (fontchooser, "font", fontname, NULL); +} - if (path) - { - gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->family_face_list), - path, - NULL, - FALSE); - gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->family_face_list), - path, - NULL, - FALSE, - 0.5, - 0.5); - gtk_tree_path_free (path); - } +/** + * gtk_font_chooser_get_font_desc: + * @fontchooser: a #GtkFontChooser + * + * Gets the currently-selected font. + * + * Note that this can be a different string than what you set with + * gtk_font_chooser_set_font(), as the font chooser widget may + * normalize font names and thus return a string with a different + * structure. For example, "Helvetica Italic Bold 12" could be + * normalized to "Helvetica Bold Italic 12". + * + * Use pango_font_description_equal() if you want to compare two + * font descriptions. + * + * Return value: (transfer full) (allow-none): A #PangoFontDescription for the + * current font, or %NULL if no font is selected. + * + * Since: 3.2 + */ +PangoFontDescription * +gtk_font_chooser_get_font_desc (GtkFontChooser *fontchooser) +{ + PangoFontDescription *font_desc; - found = TRUE; - } + g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), NULL); - g_object_unref (face); - pango_font_description_free (tmp_desc); + g_object_get (fontchooser, "font-desc", &font_desc, NULL); - if (found) - break; - } + return font_desc; +} - pango_font_description_free (desc); - g_object_notify (G_OBJECT (fontchooser), "font-name"); +/** + * gtk_font_chooser_set_font_desc: + * @fontchooser: a #GtkFontChooser + * @font_desc: a #PangoFontDescription + * + * Sets the currently-selected font from @font_desc. + * + * Since: 3.2 + */ +void +gtk_font_chooser_set_font_desc (GtkFontChooser *fontchooser, + const PangoFontDescription *font_desc) +{ + g_return_if_fail (GTK_IS_FONT_CHOOSER (fontchooser)); + g_return_if_fail (font_desc != NULL); - return found; + g_object_set (fontchooser, "font-desc", font_desc, NULL); } /** @@ -1132,25 +301,28 @@ gtk_font_chooser_set_font_name (GtkFontChooser *fontchooser, * @fontchooser: a #GtkFontChooser * * Gets the text displayed in the preview area. - * - * Return value: (transfer none): the text displayed in the - * preview area. This string is owned by the widget and - * should not be modified or freed + * + * Return value: (transfer full): the text displayed in the + * preview area * * Since: 3.2 */ -const gchar* +gchar * gtk_font_chooser_get_preview_text (GtkFontChooser *fontchooser) { + char *text; + g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), NULL); - return (const gchar*)fontchooser->priv->preview_text; -} + g_object_get (fontchooser, "preview-text", &text, NULL); + + return text; +} /** * gtk_font_chooser_set_preview_text: * @fontchooser: a #GtkFontChooser - * @text: (transfer none): the text to display in the preview area + * @text: (transfer none): the text to display in the preview area * * Sets the text displayed in the preview area. * The @text is used to show how the selected font looks. @@ -1158,38 +330,36 @@ gtk_font_chooser_get_preview_text (GtkFontChooser *fontchooser) * Since: 3.2 */ void -gtk_font_chooser_set_preview_text (GtkFontChooser *fontchooser, - const gchar *text) +gtk_font_chooser_set_preview_text (GtkFontChooser *fontchooser, + const gchar *text) { g_return_if_fail (GTK_IS_FONT_CHOOSER (fontchooser)); g_return_if_fail (text != NULL); - g_free (fontchooser->priv->preview_text); - fontchooser->priv->preview_text = g_strdup (text); - - populate_list (fontchooser, - GTK_TREE_VIEW (fontchooser->priv->family_face_list), - fontchooser->priv->model); - - gtk_entry_set_text (GTK_ENTRY (fontchooser->priv->preview), text); - - g_object_notify (G_OBJECT (fontchooser), "preview-text"); + g_object_set (fontchooser, "preview-text", text, NULL); } /** * gtk_font_chooser_get_show_preview_entry: * @fontchooser: a #GtkFontChooser * - * Return value: %TRUE if the preview entry is shown or %FALSE if - * it is hidden. + * Returns whether the preview entry is shown or not. + * + * Return value: %TRUE if the preview entry is shown + * or %FALSE if it is hidden. + * * Since: 3.2 */ gboolean gtk_font_chooser_get_show_preview_entry (GtkFontChooser *fontchooser) { + gboolean show; + g_return_val_if_fail (GTK_IS_FONT_CHOOSER (fontchooser), FALSE); - return fontchooser->priv->show_preview_entry; + g_object_get (fontchooser, "show-preview-entry", &show, NULL); + + return show; } /** @@ -1198,19 +368,50 @@ gtk_font_chooser_get_show_preview_entry (GtkFontChooser *fontchooser) * @show_preview_entry: whether to show the editable preview entry or not * * Shows or hides the editable preview entry. + * * Since: 3.2 */ void gtk_font_chooser_set_show_preview_entry (GtkFontChooser *fontchooser, - gboolean show_preview_entry) + gboolean show_preview_entry) { g_return_if_fail (GTK_IS_FONT_CHOOSER (fontchooser)); - if (show_preview_entry) - gtk_widget_show (fontchooser->priv->preview_scrolled_window); - else - gtk_widget_hide (fontchooser->priv->preview_scrolled_window); + show_preview_entry = show_preview_entry != FALSE; + g_object_set (fontchooser, "show-preview-entry", show_preview_entry, NULL); +} + +/** + * gtk_font_chooser_set_filter_func: + * @fontchooser: a #GtkFontChooser + * @filter: (allow-none): a #GtkFontFilterFunc, or %NULL + * @user_data: data to pass to @filter + * @destroy: function to call to free @data when it is no longer needed + * + * Adds a filter function that decides which fonts to display + * in the font chooser. + * + * Since: 3.2 + */ +void +gtk_font_chooser_set_filter_func (GtkFontChooser *fontchooser, + GtkFontFilterFunc filter, + gpointer user_data, + GDestroyNotify destroy) +{ + g_return_if_fail (GTK_IS_FONT_CHOOSER (fontchooser)); + + GTK_FONT_CHOOSER_GET_IFACE (fontchooser)->set_filter_func (fontchooser, + filter, + user_data, + destroy); +} + +void +_gtk_font_chooser_font_activated (GtkFontChooser *chooser, + const gchar *fontname) +{ + g_return_if_fail (GTK_IS_FONT_CHOOSER (chooser)); - fontchooser->priv->show_preview_entry = show_preview_entry; - g_object_notify (G_OBJECT (fontchooser), "show-preview-entry"); + g_signal_emit (chooser, chooser_signals[SIGNAL_FONT_ACTIVATED], 0, fontname); }