[goffice] Font Selector: make the style (face) selector an option menu too.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] Font Selector: make the style (face) selector an option menu too.
- Date: Sun, 17 Mar 2013 01:50:45 +0000 (UTC)
commit f29be34de40bb058ebd83ae81f92b1b01c9a6a2f
Author: Morten Welinder <terra gnome org>
Date: Sat Mar 16 21:49:41 2013 -0400
Font Selector: make the style (face) selector an option menu too.
This, more or less, completes a rewrite of the font selector. There
is no interesting code left from the old one.
ChangeLog | 5 +
NEWS | 1 +
goffice/gtk/go-font-sel.c | 557 +++++++++++++++++++++++++++-----------------
goffice/gtk/go-font-sel.ui | 40 +---
goffice/gtk/goffice-gtk.c | 66 ++++++
goffice/gtk/goffice-gtk.h | 1 +
6 files changed, 420 insertions(+), 250 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 1964513..43295ad 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2013-03-16 Morten Welinder <terra gnome org>
+
+ * goffice/gtk/goffice-gtk.c (go_gtk_grid_remove_row): New
+ function.
+
2013-03-14 Morten Welinder <terra gnome org>
* goffice/gtk/go-font-sel.c (gfs_fill_font_name_list): Implement
diff --git a/NEWS b/NEWS
index 7d59721..d3b22f0 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,7 @@ Morten:
* Fix gtk-doc problems --without-long-double. [#695550]
* Widget cleanups.
* Add dialog version of the font selector.
+ * Rewrite font selector. [#695031]
--------------------------------------------------------------------------
goffice 0.10.1:
diff --git a/goffice/gtk/go-font-sel.c b/goffice/gtk/go-font-sel.c
index 7ff5dac..cf87d40 100644
--- a/goffice/gtk/go-font-sel.c
+++ b/goffice/gtk/go-font-sel.c
@@ -1,11 +1,7 @@
/*
- * A font selector widget. This is a simplified version of the
- * GnomePrint font selector widget.
+ * A font selector widget.
*
- * Authors:
- * Jody Goldberg (jody gnome org)
- * Miguel de Icaza (miguel gnu org)
- * Almer S. Tigelaar (almer gnome org)
+ * Copyright 2013 by Morten Welinder (terra gnome org)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -38,24 +34,25 @@ struct _GOFontSel {
GtkBuilder *gui;
GtkWidget *family_picker;
- GtkWidget *font_style_entry;
- GtkWidget *font_size_entry;
- GtkWidget *size_picker;
- GtkTreeView *font_style_list;
-
- GtkWidget *preview_label;
-
- PangoAttrList *modifications;
-
- GPtrArray *family_faces;
+ PangoFontFamily *current_family;
GHashTable *family_by_name;
GHashTable *item_by_family;
+ GHashTable *faces_by_family;
+
+ gboolean show_style;
+ GtkWidget *face_picker;
+ PangoFontFace *current_face;
+ GHashTable *item_by_face;
+ GtkWidget *font_size_entry;
+ GtkWidget *size_picker;
GSList *font_sizes;
- gboolean show_style;
- char *preview_text;
gboolean show_preview_entry;
+ GtkWidget *preview_label;
+ char *preview_text;
+
+ PangoAttrList *modifications;
GtkFontFilterFunc filter_func;
gpointer filter_data;
@@ -132,39 +129,6 @@ go_font_sel_emit_changed (GOFontSel *gfs)
update_preview (gfs);
}
-static void
-cb_list_adjust (GtkTreeView* view)
-{
- GtkTreeModel *model;
- GtkTreeIter iter;
- GtkTreePath *path;
-
- if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (view), &model, &iter)) {
- path = gtk_tree_model_get_path (model, &iter);
- gtk_tree_view_set_cursor (view, path, NULL, FALSE);
- gtk_tree_path_free (path);
- }
-}
-
-static void
-list_init (GtkTreeView* view)
-{
- GtkCellRenderer *renderer;
- GtkListStore *store;
- GtkTreeViewColumn *column;
-
- gtk_tree_view_set_headers_visible (view, FALSE);
- store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_OBJECT);
- gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));
- g_object_unref (store);
- renderer = gtk_cell_renderer_text_new ();
- column = gtk_tree_view_column_new_with_attributes (
- NULL, renderer, "text", COL_TEXT, NULL);
- gtk_tree_view_column_set_expand (column, TRUE);
- gtk_tree_view_append_column (view, column);
- g_signal_connect (view, "realize", G_CALLBACK (cb_list_adjust), NULL);
-}
-
static int
by_family_name (gconstpointer a_, gconstpointer b_)
{
@@ -177,33 +141,65 @@ by_family_name (gconstpointer a_, gconstpointer b_)
static void
dispose_families (GOFontSel *gfs)
{
- if (gfs->family_by_name) {
- g_hash_table_destroy (gfs->family_by_name);
- gfs->family_by_name = NULL;
- }
+ g_hash_table_remove_all (gfs->family_by_name);
+ g_hash_table_remove_all (gfs->item_by_family);
+ g_hash_table_remove_all (gfs->faces_by_family);
+ g_hash_table_remove_all (gfs->item_by_face);
+}
- if (gfs->item_by_family) {
- g_hash_table_destroy (gfs->item_by_family);
- gfs->item_by_family = NULL;
- }
+static void
+update_preview_after_face_change (GOFontSel *gfs, gboolean signal_change)
+{
+ PangoFontDescription *desc =
+ pango_font_face_describe (gfs->current_face);
+ /*
+ * This isn't 100% right: we are ignoring other attributes.
+ * We could fix that but unsetting extra atttributes might
+ * not be so easy.
+ */
+ PangoWeight weight = pango_font_description_get_weight (desc);
+ PangoWeight style = pango_font_description_get_style (desc);
+ go_font_sel_add_attr (gfs, pango_attr_weight_new (weight));
+ go_font_sel_add_attr (gfs, pango_attr_style_new (style));
+ pango_font_description_free (desc);
+ // reload_size (gfs);
+ if (signal_change)
+ go_font_sel_emit_changed (gfs);
+}
- if (gfs->family_faces) {
- g_ptr_array_foreach (gfs->family_faces,
- (GFunc)g_object_unref, NULL);
- g_ptr_array_free (gfs->family_faces, TRUE);
- gfs->family_faces = NULL;
- }
+/*
+ * In the real world we observe fonts with typos in face names...
+ */
+static const char *
+my_get_face_name (PangoFontFace *face)
+{
+ const char *name = face ? pango_font_face_get_face_name (face) : NULL;
+
+ if (!name)
+ return NULL;
+ if (strcmp (name, "BoldItalic") == 0)
+ return "Bold Italic";
+ if (strcmp (name, "BoldOblique") == 0)
+ return "Bold Oblique";
+ if (strcmp (name, "LightOblique") == 0)
+ return "Light Oblique";
+ if (strcmp (name, "ExtraLight") == 0)
+ return "Extra Light";
+
+ return name;
}
-static void
-add_font_to_menu (GtkWidget *m, const char *name, PangoFontFamily *family,
- GHashTable *ibf)
+static GtkMenuItem *
+add_font_to_menu (GtkWidget *m, const char *name,
+ const char *what, gpointer obj,
+ GHashTable *itemhash)
{
GtkWidget *w = gtk_menu_item_new_with_label (name);
gtk_menu_shell_append (GTK_MENU_SHELL (m), w);
- g_object_set_data (G_OBJECT (w), "family", family);
- if (!g_hash_table_lookup (ibf, family))
- g_hash_table_insert (ibf, family, w);
+ g_object_set_data (G_OBJECT (w), what, obj);
+ if (!g_hash_table_lookup (itemhash, obj))
+ g_hash_table_insert (itemhash, obj, w);
+ return GTK_MENU_ITEM (w);
}
static void
@@ -215,6 +211,61 @@ add_submenu_to_menu (GtkWidget *m, const char *name, GtkWidget *m2)
}
static void
+reload_faces (GOFontSel *gfs)
+{
+ GtkWidget *m;
+ GSList *faces;
+ char *current_face_name;
+ GtkMenuItem *selected_item = NULL, *first_item = NULL;
+
+ current_face_name = g_strdup (my_get_face_name (gfs->current_face));
+ gfs->current_face = NULL;
+
+ g_hash_table_remove_all (gfs->item_by_face);
+
+ m = gtk_menu_new ();
+ gtk_menu_set_title (GTK_MENU (m), _("Faces"));
+ for (faces = g_hash_table_lookup (gfs->faces_by_family, gfs->current_family);
+ faces;
+ faces = faces->next) {
+ PangoFontFace *face = faces->data;
+ const char *name = my_get_face_name (face);
+ GtkMenuItem *w = add_font_to_menu
+ (m, g_dpgettext2 (NULL, "FontFace", name),
+ "face", face, gfs->item_by_face);
+
+ if (!first_item)
+ first_item = w;
+
+ if (g_strcmp0 (current_face_name, name) == 0)
+ selected_item = w;
+ }
+ if (!selected_item)
+ selected_item = first_item;
+
+ gtk_widget_show_all (m);
+ go_option_menu_set_menu (GO_OPTION_MENU (gfs->face_picker), m);
+ if (selected_item)
+ go_option_menu_select_item (GO_OPTION_MENU (gfs->face_picker),
+ selected_item);
+
+ if (selected_item) {
+ const char *new_face_name;
+ gboolean changed;
+
+ gfs->current_face =
+ g_object_get_data (G_OBJECT (selected_item), "face");
+
+ new_face_name = my_get_face_name (gfs->current_face);
+ changed = g_strcmp0 (current_face_name, new_face_name) != 0;
+ update_preview_after_face_change (gfs, changed);
+ }
+ g_free (current_face_name);
+}
+
+#define ADD_OBSERVED(it) g_hash_table_insert (observed_faces, (gpointer)(it), (gpointer)(it))
+
+static void
reload_families (GOFontSel *gfs)
{
PangoContext *context;
@@ -224,9 +275,58 @@ reload_families (GOFontSel *gfs)
gunichar uc = 0;
static const char *priority[] = { "Sans", "Serif", "Monospace" };
gboolean has_priority;
+ char *current_family_name;
+ GHashTable *observed_faces = NULL;
+ gboolean debug_font = go_debug_flag ("font");
+
+ if (debug_font) {
+ observed_faces = g_hash_table_new (g_str_hash, g_str_equal);
+
+ /*
+ * List of observed face names. Translators: these represent
+ * attributes of a font face, i.e., how bold the letters are
+ * and whether it is an italic or regular face.
+ */
+ ADD_OBSERVED (NC_("FontFace", "Bold"));
+ ADD_OBSERVED (NC_("FontFace", "Bold Condensed"));
+ ADD_OBSERVED (NC_("FontFace", "Bold Condensed Italic"));
+ ADD_OBSERVED (NC_("FontFace", "Bold Italic"));
+ ADD_OBSERVED (NC_("FontFace", "Bold Oblique"));
+ ADD_OBSERVED (NC_("FontFace", "Book"));
+ ADD_OBSERVED (NC_("FontFace", "Book Oblique"));
+ ADD_OBSERVED (NC_("FontFace", "Condensed"));
+ ADD_OBSERVED (NC_("FontFace", "Condensed Bold"));
+ ADD_OBSERVED (NC_("FontFace", "Condensed Bold Italic"));
+ ADD_OBSERVED (NC_("FontFace", "Condensed Bold Oblique"));
+ ADD_OBSERVED (NC_("FontFace", "Condensed Italic"));
+ ADD_OBSERVED (NC_("FontFace", "Condensed Oblique"));
+ ADD_OBSERVED (NC_("FontFace", "Demi"));
+ ADD_OBSERVED (NC_("FontFace", "Demi Bold"));
+ ADD_OBSERVED (NC_("FontFace", "Demi Bold Italic"));
+ ADD_OBSERVED (NC_("FontFace", "Demi Oblique"));
+ ADD_OBSERVED (NC_("FontFace", "Extra Light"));
+ ADD_OBSERVED (NC_("FontFace", "Italic"));
+ ADD_OBSERVED (NC_("FontFace", "Light"));
+ ADD_OBSERVED (NC_("FontFace", "Light Italic"));
+ ADD_OBSERVED (NC_("FontFace", "Light Oblique"));
+ ADD_OBSERVED (NC_("FontFace", "Medium"));
+ ADD_OBSERVED (NC_("FontFace", "Medium Italic"));
+ ADD_OBSERVED (NC_("FontFace", "Normal"));
+ ADD_OBSERVED (NC_("FontFace", "Oblique"));
+ ADD_OBSERVED (NC_("FontFace", "Regular"));
+ ADD_OBSERVED (NC_("FontFace", "Regular Condensed"));
+ ADD_OBSERVED (NC_("FontFace", "Regular Condensed Italic"));
+ ADD_OBSERVED (NC_("FontFace", "Regular Italic"));
+ ADD_OBSERVED (NC_("FontFace", "Regular Oblique"));
+ ADD_OBSERVED (NC_("FontFace", "Roman"));
+ }
- if (!gtk_widget_get_screen (GTK_WIDGET (gfs)))
- return;
+ if (debug_font)
+ g_printerr ("Reloading fonts\n");
+
+ current_family_name = gfs->current_family
+ ? g_strdup (pango_font_family_get_name (gfs->current_family))
+ : NULL;
dispose_families (gfs);
@@ -235,10 +335,6 @@ reload_families (GOFontSel *gfs)
qsort (pango_families, n_families,
sizeof (pango_families[0]), by_family_name);
- gfs->family_by_name = g_hash_table_new_full
- (g_str_hash, g_str_equal, (GDestroyNotify)g_free, NULL);
- gfs->item_by_family =
- g_hash_table_new (g_direct_hash, g_direct_equal);
for (i = 0; i < n_families; i++) {
PangoFontFamily *family = pango_families[i];
const char *name = pango_font_family_get_name (family);
@@ -257,7 +353,9 @@ reload_families (GOFontSel *gfs)
g_hash_table_lookup (gfs->family_by_name, name);
if (family) {
has_priority = TRUE;
- add_font_to_menu (m, name, family, gfs->item_by_family);
+ add_font_to_menu (m, name,
+ "family", family,
+ gfs->item_by_family);
}
}
if (has_priority)
@@ -268,14 +366,42 @@ reload_families (GOFontSel *gfs)
for (i = 0; i < n_families; i++) {
PangoFontFamily *family = pango_families[i];
const char *name = pango_font_family_get_name (family);
- gunichar fc;
+ gunichar fc = g_unichar_toupper (g_utf8_get_char (name));
+ GSList *ok_faces = NULL;
+ PangoFontFace **faces;
+ int j, n_faces;
+
+ pango_font_family_list_faces (family, &faces, &n_faces);
+ for (j = 0; j < n_faces; j++) {
+ PangoFontFace *face = faces[j];
+ const char *name;
+
+ if (debug_font &&
+ (name = my_get_face_name (face)) &&
+ !g_hash_table_lookup (observed_faces, name)) {
+ g_printerr ("New observed face: %s\n",
+ name);
+ ADD_OBSERVED (name);
+ }
+
+ if (gfs->filter_func &&
+ !gfs->filter_func (family, face, gfs->filter_data))
+ continue;
+
+ ok_faces = g_slist_append (ok_faces, face);
+ }
+ g_free (faces);
+ if (!ok_faces)
+ continue;
- fc = g_unichar_toupper (g_utf8_get_char (name));
+ g_hash_table_insert (gfs->faces_by_family, family, ok_faces);
if (!g_unichar_isalpha (fc)) {
if (!mother)
mother = gtk_menu_new ();
- add_font_to_menu (mother, name, family, gfs->item_by_family);
+ add_font_to_menu (mother, name,
+ "family", family,
+ gfs->item_by_family);
continue;
}
@@ -288,7 +414,9 @@ reload_families (GOFontSel *gfs)
add_submenu_to_menu (mall, txt, msingle);
}
- add_font_to_menu (msingle, name, family, gfs->item_by_family);
+ add_font_to_menu (msingle, name,
+ "family", family,
+ gfs->item_by_family);
}
if (mother)
add_submenu_to_menu (mall, _("Other"), mother);
@@ -298,22 +426,40 @@ reload_families (GOFontSel *gfs)
g_free (pango_families);
go_option_menu_set_menu (GO_OPTION_MENU (gfs->family_picker), m);
+
+ if (current_family_name) {
+ gfs->current_family = NULL;
+ go_font_sel_set_family (gfs, current_family_name);
+ g_free (current_family_name);
+ }
+
+ if (observed_faces)
+ g_hash_table_destroy (observed_faces);
+
+ reload_faces (gfs);
}
+#undef ADD_OBSERVED
static void
-gfs_screen_changed (GOFontSel *gfs)
+gfs_screen_changed (GtkWidget *w, GdkScreen *previous_screen)
{
int width;
PangoFontDescription *desc;
-
- if (!gtk_widget_get_screen (GTK_WIDGET (gfs)))
+ GdkScreen *screen;
+ GOFontSel *gfs = GO_FONT_SEL (w);
+
+ screen = gtk_widget_get_screen (w);
+ if (!previous_screen)
+ previous_screen = gdk_screen_get_default ();
+ if (screen == previous_screen &&
+ g_hash_table_size (gfs->family_by_name) > 0)
return;
reload_families (gfs);
desc = pango_font_description_from_string ("Sans 72");
width = go_pango_measure_string
- (gtk_widget_get_pango_context (GTK_WIDGET (gfs)),
+ (gtk_widget_get_pango_context (w),
desc,
"M");
pango_font_description_free (desc);
@@ -322,59 +468,6 @@ gfs_screen_changed (GOFontSel *gfs)
5 * width, width * 11 / 10);
}
-static char const *styles[] = {
- N_("Normal"),
- N_("Bold"),
- N_("Bold italic"),
- N_("Italic"),
- NULL
-};
-
-static void
-style_selected (GtkTreeSelection *selection,
- GOFontSel *gfs)
-{
- GtkTreeModel *model;
- GtkTreeIter iter;
- GtkTreePath *path;
- int row;
-
- if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
- path = gtk_tree_model_get_path (model, &iter);
- row = *gtk_tree_path_get_indices (path);
- gtk_tree_path_free (path);
- gtk_entry_set_text (GTK_ENTRY (gfs->font_style_entry), _(styles[row]));
- go_font_sel_add_attr (gfs,
- pango_attr_weight_new ((row == 1 || row == 2)
- ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL));
- go_font_sel_add_attr (gfs,
- pango_attr_style_new ((row == 2 || row == 3)
- ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL));
- go_font_sel_emit_changed (gfs);
- }
-}
-
-static void
-gfs_fill_font_style_list (GOFontSel *gfs)
-{
- int i;
- GtkListStore *store;
- GtkTreeIter iter;
-
- store = GTK_LIST_STORE (gtk_tree_view_get_model (gfs->font_style_list));
- for (i = 0; styles[i] != NULL; i++) {
- PangoFontFace *face = NULL;
- gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter,
- COL_TEXT, _(styles[i]),
- COL_OBJ, face,
- -1);
- }
- g_signal_connect (gtk_tree_view_get_selection (gfs->font_style_list),
- "changed",
- G_CALLBACK (style_selected), gfs);
-}
-
static void
update_sizes (GOFontSel *gfs)
{
@@ -392,18 +485,15 @@ update_sizes (GOFontSel *gfs)
static void
-select_row (GtkTreeView *list, int row)
+cb_face_changed (GOOptionMenu *om, GOFontSel *gfs)
{
- if (row < 0)
- gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (list));
- else {
- GtkTreePath *path = gtk_tree_path_new_from_indices (row, -1);
-
- gtk_tree_selection_select_path (gtk_tree_view_get_selection (list), path);
- gtk_tree_path_free (path);
-
- if (gtk_widget_get_realized (GTK_WIDGET (list)))
- cb_list_adjust (list);
+ GtkWidget *selected = go_option_menu_get_history (om);
+ PangoFontFace *face = selected
+ ? g_object_get_data (G_OBJECT (selected), "face")
+ : NULL;
+ if (face && face != gfs->current_face) {
+ gfs->current_face = face;
+ update_preview_after_face_change (gfs, TRUE);
}
}
@@ -414,9 +504,11 @@ cb_font_changed (GOOptionMenu *om, GOFontSel *gfs)
PangoFontFamily *family = selected
? g_object_get_data (G_OBJECT (selected), "family")
: NULL;
- if (family) {
+ if (family && family != gfs->current_family) {
const char *name = pango_font_family_get_name (family);
go_font_sel_add_attr (gfs, pango_attr_family_new (name));
+ gfs->current_family = family;
+ reload_faces (gfs);
go_font_sel_emit_changed (gfs);
}
}
@@ -466,6 +558,16 @@ cb_size_picker_changed (GtkButton *button, GOFontSel *gfs)
static void
gfs_init (GOFontSel *gfs)
{
+ gfs->family_by_name = g_hash_table_new_full
+ (g_str_hash, g_str_equal, (GDestroyNotify)g_free, NULL);
+ gfs->item_by_family =
+ g_hash_table_new (g_direct_hash, g_direct_equal);
+ gfs->item_by_face =
+ g_hash_table_new (g_direct_hash, g_direct_equal);
+ gfs->faces_by_family = g_hash_table_new_full
+ (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify)g_slist_free);
+
gfs->show_preview_entry = TRUE;
gfs->preview_text = g_strdup (pango_language_get_sample_string (NULL));
gfs->font_sizes = go_fonts_list_sizes ();
@@ -476,7 +578,7 @@ gfs_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_params)
{
- GtkWidget *fontsel;
+ GtkWidget *fontsel, *placeholder;
GOFontSel *gfs = (GOFontSel *)
(gfs_parent_class->constructor (type,
n_construct_properties,
@@ -495,24 +597,15 @@ gfs_constructor (GType type,
fontsel = go_gtk_builder_get_widget (gfs->gui, "font-selector");
gtk_container_add (GTK_CONTAINER (gfs), fontsel);
- gfs->font_style_entry = go_gtk_builder_get_widget (gfs->gui, "font-style-entry");
- gfs->font_style_list = GTK_TREE_VIEW (gtk_builder_get_object (gfs->gui, "font-style-list"));
-
- if (!gfs->show_style) {
- gtk_widget_destroy (gfs->font_style_entry);
- gfs->font_style_entry = NULL;
- gtk_widget_destroy (go_gtk_builder_get_widget (gfs->gui, "font-style-window"));
- gfs->font_style_list = NULL;
- gtk_widget_destroy (go_gtk_builder_get_widget (gfs->gui, "font-style-label"));
- }
gfs->preview_label = go_gtk_builder_get_widget (gfs->gui, "preview-label");
/* ---------------------------------------- */
+ placeholder = go_gtk_builder_get_widget
+ (gfs->gui, "family-picker-placeholder");
gfs->family_picker = go_option_menu_new ();
gtk_widget_show_all (gfs->family_picker);
- go_gtk_widget_replace (go_gtk_builder_get_widget (gfs->gui, "family-picker-placeholder"),
- gfs->family_picker);
+ go_gtk_widget_replace (placeholder, gfs->family_picker);
g_signal_connect (gfs->family_picker,
"changed",
G_CALLBACK (cb_font_changed),
@@ -520,9 +613,24 @@ gfs_constructor (GType type,
/* ---------------------------------------- */
+ placeholder = go_gtk_builder_get_widget
+ (gfs->gui, "face-picker-placeholder");
+ gfs->face_picker = go_option_menu_new ();
+ g_object_ref_sink (gfs->face_picker);
+ gtk_widget_show_all (gfs->face_picker);
+ go_gtk_widget_replace (placeholder, gfs->face_picker);
if (gfs->show_style) {
- list_init (gfs->font_style_list);
- gfs_fill_font_style_list (gfs);
+ g_signal_connect (gfs->face_picker,
+ "changed",
+ G_CALLBACK (cb_face_changed),
+ gfs);
+ } else {
+ int row;
+ GtkGrid *grid = GTK_GRID (gtk_widget_get_parent (gfs->face_picker));
+ gtk_container_child_get (GTK_CONTAINER (grid), gfs->face_picker,
+ "top-attach", &row,
+ NULL);
+ go_gtk_grid_remove_row (grid, row);
}
/* ---------------------------------------- */
@@ -539,27 +647,39 @@ gfs_constructor (GType type,
/* ---------------------------------------- */
- g_signal_connect (gfs,
- "screen-changed",
- G_CALLBACK (gfs_screen_changed),
- NULL);
-
gtk_widget_show_all (fontsel);
+ gfs_screen_changed (GTK_WIDGET (gfs), NULL);
+
return (GObject *)gfs;
}
+static void
+gfs_finalize (GObject *obj)
+{
+ GOFontSel *gfs = GO_FONT_SEL (obj);
+ g_hash_table_destroy (gfs->family_by_name);
+ g_hash_table_destroy (gfs->item_by_family);
+ g_hash_table_destroy (gfs->item_by_face);
+ g_hash_table_destroy (gfs->faces_by_family);
+ gfs_parent_class->finalize (obj);
+}
static void
gfs_dispose (GObject *obj)
{
GOFontSel *gfs = GO_FONT_SEL (obj);
+ if (gfs->face_picker) {
+ /* We actually own a ref. */
+ g_object_unref (gfs->face_picker);
+ gfs->face_picker = NULL;
+ }
+
if (gfs->gui) {
g_object_unref (gfs->gui);
gfs->gui = NULL;
gfs->family_picker = NULL;
- gfs->font_style_list = NULL;
gfs->size_picker = NULL;
}
if (gfs->modifications != NULL) {
@@ -644,9 +764,7 @@ gfs_set_property (GObject *object,
break;
case GFS_GTK_FONT_CHOOSER_PROP_PREVIEW_TEXT:
- g_free (gfs->preview_text);
- gfs->preview_text = g_value_dup_string (value);
- update_preview (gfs);
+ go_font_sel_set_sample_text (gfs, g_value_get_string (value));
break;
case GFS_GTK_FONT_CHOOSER_PROP_SHOW_PREVIEW_ENTRY:
@@ -663,11 +781,16 @@ gfs_set_property (GObject *object,
static void
gfs_class_init (GObjectClass *klass)
{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
klass->constructor = gfs_constructor;
+ klass->finalize = gfs_finalize;
klass->dispose = gfs_dispose;
klass->get_property = gfs_get_property;
klass->set_property = gfs_set_property;
+ widget_class->screen_changed = gfs_screen_changed;
+
gfs_parent_class = g_type_class_peek_parent (klass);
g_object_class_install_property
@@ -718,24 +841,15 @@ gfs_font_chooser_set_filter_func (GtkFontChooser *chooser,
gfs->filter_data = filter_data;
gfs->filter_data_destroy = data_destroy;
- if (gfs->family_picker) {
- PangoFontDescription *desc = go_font_sel_get_font_desc (gfs);
+ if (gfs->family_picker)
reload_families (gfs);
- go_font_sel_set_font_desc (gfs, desc);
- pango_font_description_free (desc);
- }
}
static PangoFontFamily *
gfs_font_chooser_get_font_family (GtkFontChooser *chooser)
{
GOFontSel *gfs = GO_FONT_SEL (chooser);
- PangoFontDescription *desc = go_font_sel_get_font_desc (gfs);
- const char *name = pango_font_description_get_family (desc);
- PangoFontFamily *family = g_hash_table_lookup (gfs->family_by_name,
- name);
- pango_font_description_free (desc);
- return family;
+ return gfs->current_family;
}
static int
@@ -752,8 +866,7 @@ static PangoFontFace *
gfs_font_chooser_get_font_face (GtkFontChooser *chooser)
{
GOFontSel *gfs = GO_FONT_SEL (chooser);
- (void)gfs;
- return NULL;
+ return gfs->current_face;
}
static void
@@ -784,9 +897,6 @@ go_font_sel_new (void)
void
go_font_sel_editable_enters (GOFontSel *gfs, GtkWindow *dialog)
{
- if (gfs->font_style_entry)
- go_gtk_editable_enters (dialog,
- GTK_WIDGET (gfs->font_style_entry));
go_gtk_editable_enters (dialog,
GTK_WIDGET (gfs->font_size_entry));
}
@@ -796,7 +906,13 @@ go_font_sel_set_sample_text (GOFontSel *gfs, char const *text)
{
g_return_if_fail (GO_IS_FONT_SEL (gfs));
- g_object_set (gfs, "preview-text", text, NULL);
+ if (!text) text = "";
+ if (g_strcmp0 (text, gfs->preview_text)) {
+ g_free (gfs->preview_text);
+ gfs->preview_text = g_strdup (text);
+ g_object_notify (G_OBJECT (gfs), "preview-text");
+ update_preview (gfs);
+ }
}
PangoAttrList *
@@ -833,40 +949,53 @@ go_font_sel_set_family (GOFontSel *fs, char const *font_name)
PangoFontFamily *family =
g_hash_table_lookup (fs->family_by_name, font_name);
GtkMenuItem *item = g_hash_table_lookup (fs->item_by_family, family);
- if (item) {
+ if (item && family != fs->current_family) {
go_option_menu_select_item (GO_OPTION_MENU (fs->family_picker),
item);
go_font_sel_add_attr (fs, pango_attr_family_new (font_name));
+ fs->current_family = family;
update_preview (fs);
+ reload_faces (fs);
}
}
void
go_font_sel_set_style (GOFontSel *fs, PangoWeight weight, PangoStyle style)
-{
- gboolean is_bold = (weight >= PANGO_WEIGHT_BOLD);
- gboolean is_italic = (style != PANGO_STYLE_NORMAL);
- int n;
+{
+ PangoFontFamily *family;
+ int best_badness = G_MAXINT;
+ PangoFontFace *best = NULL;
+ GSList *faces;
- if (is_bold) {
- if (is_italic)
- n = 2;
- else
- n = 1;
- } else {
- if (is_italic)
- n = 3;
- else
- n = 0;
- }
+ g_return_if_fail (GO_IS_FONT_SEL (fs));
- if (fs->font_style_list)
- select_row (fs->font_style_list, n);
+ family = fs->current_family;
+ faces = g_hash_table_lookup (fs->faces_by_family, family);
+
+ for (; faces; faces = faces->next) {
+ PangoFontFace *face = faces->data;
+ PangoFontDescription *desc = pango_font_face_describe (face);
+ PangoWeight fweight = pango_font_description_get_weight (desc);
+ PangoWeight fstyle = pango_font_description_get_style (desc);
+ int badness =
+ (500 * ABS ((int)style - (int)fstyle) +
+ ABS ((int)weight - (int)fweight));
+ pango_font_description_free (desc);
- go_font_sel_add_attr (fs, pango_attr_weight_new (weight));
- go_font_sel_add_attr (fs, pango_attr_style_new (style));
+ if (badness < best_badness) {
+ best_badness = badness;
+ best = face;
+ }
+ }
- update_preview (fs);
+ if (best && best != fs->current_face) {
+ GtkMenuItem *item;
+ fs->current_face = best;
+ item = g_hash_table_lookup (fs->item_by_face, best);
+ go_option_menu_select_item (GO_OPTION_MENU (fs->face_picker),
+ item);
+ update_preview_after_face_change (fs, FALSE);
+ }
}
static void
diff --git a/goffice/gtk/go-font-sel.ui b/goffice/gtk/go-font-sel.ui
index 317f2a4..45dbcb8 100644
--- a/goffice/gtk/go-font-sel.ui
+++ b/goffice/gtk/go-font-sel.ui
@@ -59,7 +59,7 @@
</packing>
</child>
<child>
- <object class="GtkLabel" id="font-style-label">
+ <object class="GtkLabel" id="face-label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
@@ -74,43 +74,11 @@
</packing>
</child>
<child>
- <object class="GtkBox" id="style-picker-placeholder">
+ <object class="GtkBox" id="face-picker-placeholder">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="orientation">vertical</property>
<child>
- <object class="GtkEntry" id="font-style-entry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="editable">False</property>
- <property name="invisible_char">●</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrolledWindow" id="font-style-window">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkTreeView" id="font-style-list">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <child internal-child="selection">
- <object class="GtkTreeSelection" id="treeview-selection"/>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
+ <placeholder/>
</child>
</object>
<packing>
@@ -129,7 +97,7 @@
<property name="id_column">1</property>
<child internal-child="entry">
<object class="GtkEntry" id="comboboxtext-entry2">
- <property name="can_focus">False</property>
+ <property name="can_focus">True</property>
</object>
</child>
</object>
diff --git a/goffice/gtk/goffice-gtk.c b/goffice/gtk/goffice-gtk.c
index 812fd35..397af54 100644
--- a/goffice/gtk/goffice-gtk.c
+++ b/goffice/gtk/goffice-gtk.c
@@ -512,6 +512,7 @@ go_gtk_widget_replace (GtkWidget *victim, GtkWidget *replacement)
"width", &width,
"height", &height,
NULL);
+ gtk_container_remove (parent, victim);
gtk_grid_attach (GTK_GRID (parent), replacement,
col, row, width, height);
} else if (GTK_IS_BOX (parent)) {
@@ -538,6 +539,71 @@ go_gtk_widget_replace (GtkWidget *victim, GtkWidget *replacement)
}
}
+struct go_gtk_grid_data {
+ GtkWidget *child;
+ int top_attach, left_attach, height, width;
+};
+
+static GList *
+get_grid_data (GtkGrid *grid)
+{
+ GtkContainer *cont = GTK_CONTAINER (grid);
+ GList *children = gtk_container_get_children (cont);
+ GList *p;
+
+ for (p = children; p; p = p->next) {
+ GtkWidget *child = p->data;
+ struct go_gtk_grid_data *data = g_new (struct go_gtk_grid_data, 1);
+ data->child = child;
+ gtk_container_child_get (cont, child,
+ "top-attach", &data->top_attach,
+ "height", &data->height,
+ "left-attach", &data->left_attach,
+ "width", &data->width,
+ NULL);
+ p->data = data;
+ }
+
+ return children;
+}
+
+static int
+by_row (struct go_gtk_grid_data *a, struct go_gtk_grid_data *b)
+{
+ return a->top_attach - b->top_attach;
+}
+
+
+void
+go_gtk_grid_remove_row (GtkGrid *grid, int row)
+{
+ GtkContainer *cont = GTK_CONTAINER (grid);
+ GList *children =
+ g_list_sort (get_grid_data (grid), (GCompareFunc)by_row);
+ GList *p;
+
+ for (p = children; p; p = p->next) {
+ struct go_gtk_grid_data *data = p->data;
+
+ if (data->top_attach <= row &&
+ data->top_attach + data->height > row)
+ data->height--;
+
+ if (data->top_attach > row)
+ data->top_attach--;
+
+ if (data->height <= 0)
+ gtk_container_remove (cont, data->child);
+ else
+ gtk_container_child_set (cont, data->child,
+ "height", data->height,
+ "top-attach", data->top_attach,
+ NULL);
+ }
+ g_list_free_full (children, (GDestroyNotify)g_free);
+}
+
+
/**
* go_gtk_widget_disable_focus:
* @w: #GtkWidget
diff --git a/goffice/gtk/goffice-gtk.h b/goffice/gtk/goffice-gtk.h
index 35d1c0e..f7701f6 100644
--- a/goffice/gtk/goffice-gtk.h
+++ b/goffice/gtk/goffice-gtk.h
@@ -109,6 +109,7 @@ GtkWidget *go_gtk_button_new_with_stock (char const *text,
#endif
void go_gtk_widget_replace (GtkWidget *victim,
GtkWidget *replacement);
+void go_gtk_grid_remove_row (GtkGrid *grid, int row);
void go_gtk_widget_disable_focus (GtkWidget *w);
void go_gtk_window_set_transient (GtkWindow *toplevel, GtkWindow *window);
void go_gtk_help_button_init (GtkWidget *w, char const *data_dir,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]