X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkfontchooserwidget.c;h=7454a35186a98fa2db42f83a5161f329a69c5cbe;hb=HEAD;hp=f80c9002133b352fb3585bdea0399f06310c0730;hpb=5a5737e3b6bf400811c32bdfc51dbd6581f9e149;p=~andy%2Fgtk diff --git a/gtk/gtkfontchooserwidget.c b/gtk/gtkfontchooserwidget.c index f80c90021..7454a3518 100644 --- a/gtk/gtkfontchooserwidget.c +++ b/gtk/gtkfontchooserwidget.c @@ -12,9 +12,7 @@ * 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" @@ -26,32 +24,31 @@ #include #include "gtkfontchooserwidget.h" -#include "gtkfontchooser.h" -#include "gtkfontchooserutils.h" + +#include "gtkadjustment.h" +#include "gtkbuildable.h" +#include "gtkbox.h" #include "gtkcellrenderertext.h" #include "gtkentry.h" -#include "gtkframe.h" -#include "gtkbbox.h" -#include "gtkbox.h" +#include "gtksearchentry.h" +#include "gtkgrid.h" +#include "gtkfontchooser.h" +#include "gtkfontchooserutils.h" +#include "gtkintl.h" #include "gtklabel.h" #include "gtkliststore.h" -#include "gtkstock.h" -#include "gtktextview.h" -#include "gtktreeselection.h" -#include "gtktreeview.h" -#include "gtkscrolledwindow.h" -#include "gtkintl.h" -#include "gtkaccessible.h" -#include "gtkbuildable.h" +#include "gtknotebook.h" #include "gtkprivate.h" #include "gtkscale.h" +#include "gtkscrolledwindow.h" #include "gtkspinbutton.h" -#include "gtknotebook.h" +#include "gtktextview.h" +#include "gtktreeselection.h" +#include "gtktreeview.h" #include "gtkwidget.h" -#include "gtkgrid.h" /** - * SECTION:gtkfontchooser + * SECTION:gtkfontchooserwidget * @Short_description: A widget for selecting fonts * @Title: GtkFontChooserWidget * @See_also: #GtkFontChooserDialog @@ -78,6 +75,7 @@ struct _GtkFontChooserWidgetPrivate { GtkWidget *search_entry; GtkWidget *family_face_list; + GtkCellRenderer *family_face_cell; GtkWidget *list_scrolled_window; GtkWidget *empty_list; GtkWidget *list_notebook; @@ -94,9 +92,6 @@ struct _GtkFontChooserWidgetPrivate PangoFontDescription *font_desc; GtkTreeIter font_iter; /* invalid if font not available or pointer into model (not filter_model) to the row containing font */ - PangoFontFace *face; - PangoFontFamily *family; - GtkFontFilterFunc filter_func; gpointer filter_data; GDestroyNotify filter_data_destroy; @@ -112,16 +107,8 @@ struct _GtkFontChooserWidgetPrivate #define FONT_STYLE_LIST_WIDTH 170 #define FONT_SIZE_LIST_WIDTH 60 -#define ROW_FORMAT_STRING "%s\n%s" - #define NO_FONT_MATCHED_SEARCH N_("No fonts matched your search. You can revise your search and try again.") -/* These are what we use as the standard font sizes, for the size list. - */ -static const gint font_sizes[] = { - 6, 8, 9, 10, 11, 12, 13, 14, 16, 20, 24, 36, 48, 72 -}; - enum { FAMILY_COLUMN, FACE_COLUMN, @@ -144,13 +131,19 @@ static void gtk_font_chooser_widget_screen_changed (GtkWidget *widge static void gtk_font_chooser_widget_bootstrap_fontlist (GtkFontChooserWidget *fontchooser); -static void gtk_font_chooser_widget_select_font (GtkFontChooserWidget *fontchooser); +static gboolean gtk_font_chooser_widget_find_font (GtkFontChooserWidget *fontchooser, + const PangoFontDescription *font_desc, + GtkTreeIter *iter); +static void gtk_font_chooser_widget_ensure_selection (GtkFontChooserWidget *fontchooser); static gchar *gtk_font_chooser_widget_get_font (GtkFontChooserWidget *fontchooser); static void gtk_font_chooser_widget_set_font (GtkFontChooserWidget *fontchooser, const gchar *fontname); static PangoFontDescription *gtk_font_chooser_widget_get_font_desc (GtkFontChooserWidget *fontchooser); +static void gtk_font_chooser_widget_merge_font_desc(GtkFontChooserWidget *fontchooser, + PangoFontDescription *font_desc, + GtkTreeIter *iter); static void gtk_font_chooser_widget_take_font_desc (GtkFontChooserWidget *fontchooser, PangoFontDescription *font_desc); @@ -243,53 +236,18 @@ gtk_font_chooser_widget_get_property (GObject *object, } static void -text_changed_cb (GtkEntry *entry, - GParamSpec *pspec, - GtkFontChooserWidget *fc) +gtk_font_chooser_widget_refilter_font_list (GtkFontChooserWidget *fontchooser) { - GtkFontChooserWidgetPrivate *priv = fc->priv; - const gchar *text; - - text = gtk_entry_get_text (entry); - - if (text == NULL || text[0] == '\0') - { - GIcon *icon; - - icon = g_themed_icon_new_with_default_fallbacks ("edit-find-symbolic"); - g_object_set (G_OBJECT (priv->search_entry), - "secondary-icon-gicon", icon, - "secondary-icon-activatable", FALSE, - "secondary-icon-sensitive", FALSE, - NULL); - g_object_unref (icon); - } - else - { - if (!gtk_entry_get_icon_activatable (GTK_ENTRY (priv->search_entry), GTK_ENTRY_ICON_SECONDARY)) - { - GIcon *icon; - - icon = g_themed_icon_new_with_default_fallbacks ("edit-clear-symbolic"); - g_object_set (G_OBJECT (priv->search_entry), - "secondary-icon-gicon", icon, - "secondary-icon-activatable", TRUE, - "secondary-icon-sensitive", TRUE, - NULL); - g_object_unref (icon); - } - } - - gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model)); + gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (fontchooser->priv->filter_model)); + gtk_font_chooser_widget_ensure_selection (fontchooser); } static void -icon_press_cb (GtkEntry *entry, - GtkEntryIconPosition pos, - GdkEvent *event, - gpointer user_data) +text_changed_cb (GtkEntry *entry, + GParamSpec *pspec, + GtkFontChooserWidget *fc) { - gtk_entry_set_text (entry, ""); + gtk_font_chooser_widget_refilter_font_list (fc); } static void @@ -311,38 +269,73 @@ size_change_cb (GtkAdjustment *adjustment, } static void -set_range_marks (GtkFontChooserWidgetPrivate *priv, - GtkWidget *size_slider, - gint *sizes, - gint length) +gtk_font_chooser_widget_update_marks (GtkFontChooserWidget *fontchooser) { + GtkFontChooserWidgetPrivate *priv = fontchooser->priv; GtkAdjustment *adj; - gint i; - gdouble value; + const int *sizes; + gint *font_sizes; + gint i, n_sizes; - if (length < 2) + if (gtk_list_store_iter_is_valid (GTK_LIST_STORE (priv->model), &priv->font_iter)) { - sizes = (gint*)font_sizes; - length = G_N_ELEMENTS (font_sizes); + PangoFontFace *face; + + gtk_tree_model_get (priv->model, &priv->font_iter, + FACE_COLUMN, &face, + -1); + + pango_font_face_list_sizes (face, &font_sizes, &n_sizes); + + /* It seems not many fonts actually have a sane set of sizes */ + for (i = 0; i < n_sizes; i++) + font_sizes[i] = font_sizes[i] / PANGO_SCALE; + + g_object_unref (face); + } + else + { + font_sizes = NULL; + n_sizes = 0; } - gtk_scale_clear_marks (GTK_SCALE (size_slider)); + if (n_sizes < 2) + { + static const gint fallback_sizes[] = { + 6, 8, 9, 10, 11, 12, 13, 14, 16, 20, 24, 36, 48, 72 + }; - adj = gtk_range_get_adjustment(GTK_RANGE (size_slider)); + sizes = fallback_sizes; + n_sizes = G_N_ELEMENTS (fallback_sizes); + } + else + { + sizes = font_sizes; + } - gtk_adjustment_set_lower (adj, (gdouble) sizes[0]); - gtk_adjustment_set_upper (adj, (gdouble) sizes[length-1]); + gtk_scale_clear_marks (GTK_SCALE (priv->size_slider)); - 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]); + adj = gtk_range_get_adjustment(GTK_RANGE (priv->size_slider)); + + /* ensure clamping doesn't callback into font resizing code */ + g_signal_handlers_block_by_func (adj, size_change_cb, fontchooser); + gtk_adjustment_configure (adj, + gtk_adjustment_get_value (adj), + sizes[0], + sizes[n_sizes - 1], + gtk_adjustment_get_step_increment (adj), + gtk_adjustment_get_page_increment (adj), + gtk_adjustment_get_page_size (adj)); + g_signal_handlers_unblock_by_func (adj, size_change_cb, fontchooser); + + for (i = 0; i < n_sizes; i++) + { + gtk_scale_add_mark (GTK_SCALE (priv->size_slider), + sizes[i], + GTK_POS_BOTTOM, NULL); + } - for (i = 0; i < length; i++) - gtk_scale_add_mark (GTK_SCALE (size_slider), - (gdouble) sizes[i], - GTK_POS_BOTTOM, NULL); + g_free (font_sizes); } static void @@ -359,21 +352,50 @@ row_activated_cb (GtkTreeView *view, g_free (fontname); } +static PangoFontDescription * +tree_model_get_font_description (GtkTreeModel *model, + GtkTreeIter *iter) +{ + PangoFontDescription *desc; + PangoFontFace *face; + GtkTreeIter child_iter; + + gtk_tree_model_get (model, iter, + FONT_DESC_COLUMN, &desc, + -1); + if (desc != NULL) + return desc; + + gtk_tree_model_get (model, iter, + FACE_COLUMN, &face, + -1); + desc = pango_font_face_describe (face); + g_object_unref (face); + + if (GTK_IS_TREE_MODEL_FILTER (model)) + { + gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), + &child_iter, + iter); + iter = &child_iter; + model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model)); + } + + gtk_list_store_set (GTK_LIST_STORE (model), iter, + FONT_DESC_COLUMN, desc, + -1); + + return desc; +} + static void cursor_changed_cb (GtkTreeView *treeview, gpointer user_data) { - GtkFontChooserWidget *fontchooser = (GtkFontChooserWidget*)user_data; + GtkFontChooserWidget *fontchooser = user_data; GtkFontChooserWidgetPrivate *priv = fontchooser->priv; - - PangoFontFamily *family; - PangoFontFace *face; PangoFontDescription *desc; - - gint *sizes; - gint i, n_sizes; - - GtkTreeIter iter; + GtkTreeIter filter_iter, iter; GtkTreePath *path = NULL; gtk_tree_view_get_cursor (treeview, &path, NULL); @@ -381,48 +403,20 @@ cursor_changed_cb (GtkTreeView *treeview, if (!path) return; - if (!gtk_tree_model_get_iter (priv->filter_model, &iter, path)) + if (!gtk_tree_model_get_iter (priv->filter_model, &filter_iter, path)) { gtk_tree_path_free (path); return; } - gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (priv->filter_model), - &priv->font_iter, - &iter); - gtk_tree_model_get (priv->filter_model, &iter, - FACE_COLUMN, &face, - FAMILY_COLUMN, &family, - -1); - gtk_tree_path_free (path); - path = NULL; - - desc = pango_font_face_describe (face); - pango_font_description_set_size (desc, pango_font_description_get_size (priv->font_desc)); - gtk_widget_override_font (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; i < n_sizes; i++) - sizes[i] = sizes[i] / PANGO_SCALE; - set_range_marks (priv, priv->size_slider, sizes, n_sizes); - - if (priv->family) - g_object_unref (priv->family); - priv->family = family; - - if (priv->face) - g_object_unref (priv->face); - priv->face = face; - - if (priv->font_desc) - pango_font_description_free (priv->font_desc); - priv->font_desc = desc; + gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (priv->filter_model), + &iter, + &filter_iter); + desc = tree_model_get_font_description (priv->model, &iter); - g_object_notify (G_OBJECT (fontchooser), "font"); - g_object_notify (G_OBJECT (fontchooser), "font-desc"); + gtk_font_chooser_widget_merge_font_desc (fontchooser, desc, &iter); } static gboolean @@ -430,9 +424,8 @@ zoom_preview_cb (GtkWidget *scrolled_window, GdkEventScroll *event, gpointer user_data) { - GtkFontChooserWidget *fc = (GtkFontChooserWidget*)user_data; - GtkFontChooserWidgetPrivate *priv = fc->priv; - + GtkFontChooserWidget *fc = user_data; + GtkFontChooserWidgetPrivate *priv = fc->priv; GtkAdjustment *adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->size_spin)); if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_RIGHT) @@ -452,8 +445,8 @@ row_inserted_cb (GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) { - GtkFontChooserWidget *fontchooser = (GtkFontChooserWidget*)user_data; - GtkFontChooserWidgetPrivate *priv = fontchooser->priv; + GtkFontChooserWidget *fontchooser = user_data; + GtkFontChooserWidgetPrivate *priv = fontchooser->priv; gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->list_notebook), 0); } @@ -463,8 +456,8 @@ row_deleted_cb (GtkTreeModel *model, GtkTreePath *path, gpointer user_data) { - GtkFontChooserWidget *fontchooser = (GtkFontChooserWidget*)user_data; - GtkFontChooserWidgetPrivate *priv = fontchooser->priv; + GtkFontChooserWidget *fontchooser = user_data; + GtkFontChooserWidgetPrivate *priv = fontchooser->priv; if (gtk_tree_model_iter_n_children (model, NULL) == 0) gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->list_notebook), 1); @@ -473,10 +466,9 @@ row_deleted_cb (GtkTreeModel *model, static void gtk_font_chooser_widget_init (GtkFontChooserWidget *fontchooser) { - GIcon *icon; - GtkFontChooserWidgetPrivate *priv; - GtkWidget *scrolled_win; - GtkWidget *grid; + GtkFontChooserWidgetPrivate *priv; + GtkWidget *scrolled_win; + GtkWidget *grid; fontchooser->priv = G_TYPE_INSTANCE_GET_PRIVATE (fontchooser, GTK_TYPE_FONT_CHOOSER_WIDGET, @@ -492,12 +484,13 @@ gtk_font_chooser_widget_init (GtkFontChooserWidget *fontchooser) gtk_widget_push_composite_child (); /* Creating fundamental widgets for the private struct */ - priv->search_entry = gtk_entry_new (); + priv->search_entry = gtk_search_entry_new (); priv->family_face_list = gtk_tree_view_new (); + gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv->family_face_list), FALSE); priv->preview = gtk_entry_new (); priv->size_slider = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, - (gdouble) font_sizes[0], - (gdouble) font_sizes[G_N_ELEMENTS (font_sizes) - 1], + 0.0, + (gdouble)(G_MAXINT / PANGO_SCALE), 1.0); priv->size_spin = gtk_spin_button_new_with_range (0.0, (gdouble)(G_MAXINT / PANGO_SCALE), 1.0); @@ -561,22 +554,11 @@ gtk_font_chooser_widget_init (GtkFontChooserWidget *fontchooser) 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"); - g_object_set (G_OBJECT (priv->search_entry), - "secondary-icon-gicon", icon, - "secondary-icon-activatable", FALSE, - "secondary-icon-sensitive", FALSE, - NULL); - g_object_unref (icon); - gtk_entry_set_placeholder_text (GTK_ENTRY (priv->search_entry), _("Search font name")); - /** Callback connections **/ + /* Callback connections */ g_signal_connect (priv->search_entry, "notify::text", G_CALLBACK (text_changed_cb), fontchooser); - g_signal_connect (priv->search_entry, - "icon-press", G_CALLBACK (icon_press_cb), NULL); g_signal_connect (gtk_range_get_adjustment (GTK_RANGE (priv->size_slider)), "value-changed", G_CALLBACK (size_change_cb), fontchooser); @@ -595,8 +577,6 @@ gtk_font_chooser_widget_init (GtkFontChooserWidget *fontchooser) g_signal_connect (priv->size_slider, "scroll-event", G_CALLBACK (zoom_preview_cb), fontchooser); - set_range_marks (priv, priv->size_slider, (gint*)font_sizes, G_N_ELEMENTS (font_sizes)); - /* Font list empty hides the scrolledwindow */ g_signal_connect (G_OBJECT (priv->filter_model), "row-deleted", G_CALLBACK (row_deleted_cb), fontchooser); @@ -652,7 +632,6 @@ gtk_font_chooser_widget_load_fonts (GtkFontChooserWidget *fontchooser) qsort (families, n_families, sizeof (PangoFontFamily *), cmp_families); gtk_list_store_clear (list_store); - memset (&priv->font_iter, 0, sizeof (GtkTreeIter)); /* Iterate over families and faces */ for (i = 0; i < n_families; i++) @@ -666,10 +645,8 @@ gtk_font_chooser_widget_load_fonts (GtkFontChooserWidget *fontchooser) for (j = 0; j < n_faces; j++) { - PangoFontDescription *pango_desc; const gchar *face_name; - pango_desc = pango_font_face_describe (faces[j]); face_name = pango_font_face_get_face_name (faces[j]); family_and_face = g_strconcat (fam_name, " ", face_name, NULL); @@ -677,11 +654,9 @@ gtk_font_chooser_widget_load_fonts (GtkFontChooserWidget *fontchooser) gtk_list_store_insert_with_values (list_store, &iter, -1, FAMILY_COLUMN, families[i], FACE_COLUMN, faces[j], - FONT_DESC_COLUMN, pango_desc, PREVIEW_TITLE_COLUMN, family_and_face, -1); - pango_font_description_free (pango_desc); g_free (family_and_face); } @@ -689,6 +664,14 @@ gtk_font_chooser_widget_load_fonts (GtkFontChooserWidget *fontchooser) } g_free (families); + + /* now make sure the font list looks right */ + if (!gtk_font_chooser_widget_find_font (fontchooser, + priv->font_desc, + &priv->font_iter)) + memset (&priv->font_iter, 0, sizeof (GtkTreeIter)); + + gtk_font_chooser_widget_ensure_selection (fontchooser); } static gboolean @@ -754,6 +737,58 @@ visible_func (GtkTreeModel *model, return result; } +/* in pango units */ +static int +gtk_font_chooser_widget_get_preview_text_height (GtkFontChooserWidget *fontchooser) +{ + GtkWidget *treeview = fontchooser->priv->family_face_list; + double dpi, font_size; + + dpi = gdk_screen_get_resolution (gtk_widget_get_screen (treeview)); + gtk_style_context_get (gtk_widget_get_style_context (treeview), + gtk_widget_get_state_flags (treeview), + "font-size", &font_size, + NULL); + + return (dpi < 0.0 ? 96.0 : dpi) / 72.0 * PANGO_SCALE_X_LARGE * font_size * PANGO_SCALE; +} + +static PangoAttrList * +gtk_font_chooser_widget_get_preview_attributes (GtkFontChooserWidget *fontchooser, + const PangoFontDescription *font_desc, + gsize first_line_len) +{ + PangoAttribute *attribute; + PangoAttrList *attrs; + + attrs = pango_attr_list_new (); + + attribute = pango_attr_weight_new (PANGO_WEIGHT_BOLD); + attribute->end_index = first_line_len; + pango_attr_list_insert (attrs, attribute); + + attribute = pango_attr_scale_new (PANGO_SCALE_SMALL); + attribute->end_index = first_line_len; + pango_attr_list_insert (attrs, attribute); + + if (font_desc) + { + attribute = pango_attr_font_desc_new (font_desc); + attribute->start_index = first_line_len; + pango_attr_list_insert (attrs, attribute); + } + + attribute = pango_attr_fallback_new (FALSE); + attribute->start_index = first_line_len; + pango_attr_list_insert (attrs, attribute); + + attribute = pango_attr_size_new_absolute (gtk_font_chooser_widget_get_preview_text_height (fontchooser)); + attribute->start_index = first_line_len; + pango_attr_list_insert (attrs, attribute); + + return attrs; +} + static void gtk_font_chooser_widget_cell_data_func (GtkTreeViewColumn *column, GtkCellRenderer *cell, @@ -763,36 +798,73 @@ gtk_font_chooser_widget_cell_data_func (GtkTreeViewColumn *column, { GtkFontChooserWidget *fontchooser = user_data; PangoFontDescription *font_desc; - char *to_string, *markup; + PangoAttrList *attrs; + char *to_string, *text; + gsize first_line_len; - gtk_tree_model_get (tree_model, iter, - FONT_DESC_COLUMN, &font_desc, - -1); + font_desc = tree_model_get_font_description (tree_model, iter); to_string = pango_font_description_to_string (font_desc); - markup = g_markup_printf_escaped (ROW_FORMAT_STRING, - to_string, - to_string, - fontchooser->priv->preview_text); + text = g_strconcat (to_string, "\n", fontchooser->priv->preview_text, NULL); + first_line_len = strlen (to_string) + 1; + + attrs = gtk_font_chooser_widget_get_preview_attributes (fontchooser, + font_desc, + first_line_len); g_object_set (cell, - "markup", markup, + "attributes", attrs, + "text", text, NULL); pango_font_description_free (font_desc); + pango_attr_list_unref (attrs); g_free (to_string); - g_free (markup); + g_free (text); +} + +static void +gtk_font_chooser_widget_set_cell_size (GtkFontChooserWidget *fontchooser) +{ + GtkFontChooserWidgetPrivate *priv = fontchooser->priv; + PangoAttrList *attrs; + GtkRequisition size; + + gtk_cell_renderer_set_fixed_size (priv->family_face_cell, -1, -1); + + attrs = gtk_font_chooser_widget_get_preview_attributes (fontchooser, + NULL, + 1); + + g_object_set (priv->family_face_cell, + "attributes", attrs, + "text", "x\nx", + NULL); + + pango_attr_list_unref (attrs); + + gtk_cell_renderer_get_preferred_size (priv->family_face_cell, + priv->family_face_list, + &size, + NULL); + gtk_cell_renderer_set_fixed_size (priv->family_face_cell, size.width, size.height); } static void gtk_font_chooser_widget_bootstrap_fontlist (GtkFontChooserWidget *fontchooser) { GtkFontChooserWidgetPrivate *priv = fontchooser->priv; - GtkTreeView *treeview = GTK_TREE_VIEW (priv->family_face_list); - GtkCellRenderer *cell; + GtkTreeView *treeview = GTK_TREE_VIEW (priv->family_face_list); GtkTreeViewColumn *col; + g_signal_connect_data (priv->family_face_list, + "style-updated", + G_CALLBACK (gtk_font_chooser_widget_set_cell_size), + fontchooser, + NULL, + G_CONNECT_AFTER | G_CONNECT_SWAPPED); + priv->model = GTK_TREE_MODEL (gtk_list_store_new (4, PANGO_TYPE_FONT_FAMILY, PANGO_TYPE_FONT_FACE, @@ -810,15 +882,17 @@ gtk_font_chooser_widget_bootstrap_fontlist (GtkFontChooserWidget *fontchooser) gtk_tree_view_set_rules_hint (treeview, TRUE); gtk_tree_view_set_headers_visible (treeview, FALSE); + gtk_tree_view_set_fixed_height_mode (treeview, TRUE); - cell = gtk_cell_renderer_text_new (); - g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL); + priv->family_face_cell = gtk_cell_renderer_text_new (); + g_object_set (priv->family_face_cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL); col = gtk_tree_view_column_new (); gtk_tree_view_column_set_title (col, _("Font Family")); - gtk_tree_view_column_pack_start (col, cell, TRUE); + gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED); + gtk_tree_view_column_pack_start (col, priv->family_face_cell, TRUE); gtk_tree_view_column_set_cell_data_func (col, - cell, + priv->family_face_cell, gtk_font_chooser_widget_cell_data_func, fontchooser, NULL); @@ -826,6 +900,8 @@ gtk_font_chooser_widget_bootstrap_fontlist (GtkFontChooserWidget *fontchooser) gtk_tree_view_append_column (treeview, col); gtk_font_chooser_widget_load_fonts (fontchooser); + + gtk_font_chooser_widget_set_cell_size (fontchooser); } static void @@ -837,46 +913,51 @@ gtk_font_chooser_widget_finalize (GObject *object) if (priv->font_desc) pango_font_description_free (priv->font_desc); - if (priv->family) - g_object_unref (priv->family); - - if (priv->face) - g_object_unref (priv->face); - if (priv->filter_data_destroy) priv->filter_data_destroy (priv->filter_data); G_OBJECT_CLASS (gtk_font_chooser_widget_parent_class)->finalize (object); } +static gboolean +my_pango_font_family_equal (const char *familya, + const char *familyb) +{ + return g_ascii_strcasecmp (familya, familyb) == 0; +} + static gboolean gtk_font_chooser_widget_find_font (GtkFontChooserWidget *fontchooser, const PangoFontDescription *font_desc, /* out arguments */ - GtkTreeIter *iter, - PangoFontFamily **family, - PangoFontFace **face) + GtkTreeIter *iter) { GtkFontChooserWidgetPrivate *priv = fontchooser->priv; PangoFontDescription *desc; + PangoFontFamily *family; gboolean valid; + if (pango_font_description_get_family (font_desc) == NULL) + return FALSE; + for (valid = gtk_tree_model_get_iter_first (priv->model, iter); valid; valid = gtk_tree_model_iter_next (priv->model, iter)) { gtk_tree_model_get (priv->model, iter, - FACE_COLUMN, face, - FAMILY_COLUMN, family, - FONT_DESC_COLUMN, &desc, + FAMILY_COLUMN, &family, -1); + if (!my_pango_font_family_equal (pango_font_description_get_family (font_desc), + pango_font_family_get_name (family))) + continue; + + desc = tree_model_get_font_description (priv->model, iter); + pango_font_description_merge_static (desc, font_desc, FALSE); if (pango_font_description_equal (desc, font_desc)) break; - g_object_unref (face); - g_object_unref (family); pango_font_description_free (desc); } @@ -899,24 +980,42 @@ gtk_font_chooser_widget_screen_changed (GtkWidget *widget, return; gtk_font_chooser_widget_load_fonts (fontchooser); - - gtk_font_chooser_widget_select_font (fontchooser); } static PangoFontFamily * gtk_font_chooser_widget_get_family (GtkFontChooser *chooser) { GtkFontChooserWidget *fontchooser = GTK_FONT_CHOOSER_WIDGET (chooser); + GtkFontChooserWidgetPrivate *priv = fontchooser->priv; + PangoFontFamily *family; - return fontchooser->priv->family; + if (!gtk_list_store_iter_is_valid (GTK_LIST_STORE (priv->model), &priv->font_iter)) + return NULL; + + gtk_tree_model_get (priv->model, &priv->font_iter, + FAMILY_COLUMN, &family, + -1); + g_object_unref (family); + + return family; } static PangoFontFace * gtk_font_chooser_widget_get_face (GtkFontChooser *chooser) { GtkFontChooserWidget *fontchooser = GTK_FONT_CHOOSER_WIDGET (chooser); + GtkFontChooserWidgetPrivate *priv = fontchooser->priv; + PangoFontFace *face; - return fontchooser->priv->face; + if (!gtk_list_store_iter_is_valid (GTK_LIST_STORE (priv->model), &priv->font_iter)) + return NULL; + + gtk_tree_model_get (priv->model, &priv->font_iter, + FACE_COLUMN, &face, + -1); + g_object_unref (face); + + return face; } static gint @@ -950,25 +1049,55 @@ gtk_font_chooser_widget_set_font (GtkFontChooserWidget *fontchooser, } static void -gtk_font_chooser_widget_take_font_desc (GtkFontChooserWidget *fontchooser, - PangoFontDescription *font_desc) +gtk_font_chooser_widget_ensure_selection (GtkFontChooserWidget *fontchooser) +{ + GtkFontChooserWidgetPrivate *priv = fontchooser->priv; + GtkTreeSelection *selection; + GtkTreeIter filter_iter; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->family_face_list)); + + if (gtk_list_store_iter_is_valid (GTK_LIST_STORE (priv->model), &priv->font_iter) && + gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (priv->filter_model), + &filter_iter, + &priv->font_iter)) + { + GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->filter_model), + &filter_iter); + + gtk_tree_selection_select_iter (selection, &filter_iter); + gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->family_face_list), + path, NULL, FALSE, 0.0, 0.0); + gtk_tree_path_free (path); + } + else + { + gtk_tree_selection_unselect_all (selection); + } +} + +static void +gtk_font_chooser_widget_merge_font_desc (GtkFontChooserWidget *fontchooser, + PangoFontDescription *font_desc, + GtkTreeIter *iter) { GtkFontChooserWidgetPrivate *priv = fontchooser->priv; PangoFontMask mask; - if (font_desc && priv->font_desc && - pango_font_description_equal (font_desc, priv->font_desc)) + g_assert (font_desc != NULL); + /* iter may be NULL if the font doesn't exist on the list */ + + mask = pango_font_description_get_set_fields (font_desc); + + /* sucky test, because we can't restrict the comparison to + * only the parts that actually do get merged */ + if (pango_font_description_equal (font_desc, priv->font_desc)) { pango_font_description_free (font_desc); return; } - if (font_desc == NULL) - font_desc = pango_font_description_from_string (GTK_FONT_CHOOSER_DEFAULT_FONT_NAME); - pango_font_description_merge (priv->font_desc, font_desc, TRUE); - - mask = pango_font_description_get_set_fields (font_desc); if (mask & PANGO_FONT_MASK_SIZE) { @@ -980,7 +1109,19 @@ gtk_font_chooser_widget_take_font_desc (GtkFontChooserWidget *fontchooser, } if (mask & (PANGO_FONT_MASK_FAMILY | PANGO_FONT_MASK_STYLE | PANGO_FONT_MASK_VARIANT | PANGO_FONT_MASK_WEIGHT | PANGO_FONT_MASK_STRETCH)) - gtk_font_chooser_widget_select_font (fontchooser); + { + if (&priv->font_iter != iter) + { + if (iter == NULL) + memset (&priv->font_iter, 0, sizeof (GtkTreeIter)); + else + memcpy (&priv->font_iter, iter, sizeof (GtkTreeIter)); + + gtk_font_chooser_widget_ensure_selection (fontchooser); + } + + gtk_font_chooser_widget_update_marks (fontchooser); + } gtk_widget_override_font (priv->preview, priv->font_desc); @@ -991,43 +1132,42 @@ gtk_font_chooser_widget_take_font_desc (GtkFontChooserWidget *fontchooser, } static void -gtk_font_chooser_widget_select_font (GtkFontChooserWidget *fontchooser) +gtk_font_chooser_widget_take_font_desc (GtkFontChooserWidget *fontchooser, + PangoFontDescription *font_desc) { GtkFontChooserWidgetPrivate *priv = fontchooser->priv; - GtkTreeIter iter; - - if (priv->family) - g_object_unref (priv->family); - if (priv->face) - g_object_unref (priv->face); - - if (gtk_font_chooser_widget_find_font (fontchooser, - priv->font_desc, - &priv->font_iter, - &priv->family, - &priv->face)) + PangoFontMask mask; + + if (font_desc == NULL) + font_desc = pango_font_description_from_string (GTK_FONT_CHOOSER_DEFAULT_FONT_NAME); + + mask = pango_font_description_get_set_fields (font_desc); + if (mask & (PANGO_FONT_MASK_FAMILY | PANGO_FONT_MASK_STYLE | PANGO_FONT_MASK_VARIANT | + PANGO_FONT_MASK_WEIGHT | PANGO_FONT_MASK_STRETCH)) { - GtkTreeIter filter_iter; + GtkTreeIter iter; - if (gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (priv->filter_model), - &filter_iter, - &iter)) + if (gtk_font_chooser_widget_find_font (fontchooser, + font_desc, + &iter)) + { + gtk_font_chooser_widget_merge_font_desc (fontchooser, + font_desc, + &iter); + } + else { - GtkTreePath *path = gtk_tree_model_get_path (priv->filter_model, &filter_iter); - gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->family_face_list), - path, - NULL, - FALSE); - gtk_tree_path_free (path); + gtk_font_chooser_widget_merge_font_desc (fontchooser, + font_desc, + NULL); } } else { - gtk_tree_selection_unselect_all - (gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->family_face_list))); - priv->face = NULL; - priv->family = NULL; - memset (&priv->font_iter, 0, sizeof (GtkTreeIter)); + gtk_font_chooser_widget_merge_font_desc (fontchooser, + font_desc, + &priv->font_iter); + } } @@ -1086,7 +1226,7 @@ gtk_font_chooser_widget_set_filter_func (GtkFontChooser *chooser, gpointer data, GDestroyNotify destroy) { - GtkFontChooserWidget *fontchooser = GTK_FONT_CHOOSER_WIDGET (chooser); + GtkFontChooserWidget *fontchooser = GTK_FONT_CHOOSER_WIDGET (chooser); GtkFontChooserWidgetPrivate *priv = fontchooser->priv; if (priv->filter_data_destroy) @@ -1096,7 +1236,7 @@ gtk_font_chooser_widget_set_filter_func (GtkFontChooser *chooser, priv->filter_data = data; priv->filter_data_destroy = destroy; - gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model)); + gtk_font_chooser_widget_refilter_font_list (fontchooser); } static void