X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkfontbutton.c;h=f65b905b2d45a8e1fda13b49f8ba9a40ecf87374;hb=0cc688aa92b8fe5452b63fb49c51204498a2988b;hp=05a5ee41d31709c419ecb9e99b58878671f3a382;hpb=eb9efc9fd2f23217cb4f1053737d27c8b0e22f6a;p=~andy%2Fgtk diff --git a/gtk/gtkfontbutton.c b/gtk/gtkfontbutton.c index 05a5ee41d..f65b905b2 100644 --- a/gtk/gtkfontbutton.c +++ b/gtk/gtkfontbutton.c @@ -16,8 +16,7 @@ * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Cambridge, MA 02139, USA. + * License along with this library. If not, see . */ /* * Modified by the GTK+ Team and others 2003. See the AUTHORS @@ -43,6 +42,7 @@ #include #include +#include "gtkfontchooserutils.h" /** @@ -60,18 +60,28 @@ struct _GtkFontButtonPrivate { gchar *title; - + gchar *fontname; guint use_font : 1; guint use_size : 1; guint show_style : 1; guint show_size : 1; + guint show_preview_entry : 1; GtkWidget *font_dialog; GtkWidget *inside; GtkWidget *font_label; GtkWidget *size_label; + + PangoFontDescription *font_desc; + PangoFontFamily *font_family; + PangoFontFace *font_face; + gint font_size; + gchar *preview_text; + GtkFontFilterFunc font_filter; + gpointer font_filter_data; + GDestroyNotify font_filter_data_destroy; }; /* Signals */ @@ -119,7 +129,278 @@ static void gtk_font_button_update_font_info (GtkFontButton *gfs); static guint font_button_signals[LAST_SIGNAL] = { 0 }; -G_DEFINE_TYPE (GtkFontButton, gtk_font_button, GTK_TYPE_BUTTON) +static void +clear_font_data (GtkFontButton *font_button) +{ + GtkFontButtonPrivate *priv = font_button->priv; + + if (priv->font_family) + g_object_unref (priv->font_family); + priv->font_family = NULL; + + if (priv->font_face) + g_object_unref (priv->font_face); + priv->font_face = NULL; + + if (priv->font_desc) + pango_font_description_free (priv->font_desc); + priv->font_desc = NULL; + + g_free (priv->fontname); + priv->fontname = NULL; +} + +static void +clear_font_filter_data (GtkFontButton *font_button) +{ + GtkFontButtonPrivate *priv = font_button->priv; + + if (priv->font_filter_data_destroy) + priv->font_filter_data_destroy (priv->font_filter_data); + priv->font_filter = NULL; + priv->font_filter_data = NULL; + priv->font_filter_data_destroy = NULL; +} + +static gboolean +font_description_style_equal (const PangoFontDescription *a, + const PangoFontDescription *b) +{ + return (pango_font_description_get_weight (a) == pango_font_description_get_weight (b) && + pango_font_description_get_style (a) == pango_font_description_get_style (b) && + pango_font_description_get_stretch (a) == pango_font_description_get_stretch (b) && + pango_font_description_get_variant (a) == pango_font_description_get_variant (b)); +} + +static void +gtk_font_button_update_font_data (GtkFontButton *font_button) +{ + GtkFontButtonPrivate *priv = font_button->priv; + PangoFontFamily **families; + PangoFontFace **faces; + gint n_families, n_faces, i; + const gchar *family; + + g_assert (priv->font_desc != NULL); + + priv->fontname = pango_font_description_to_string (priv->font_desc); + + family = pango_font_description_get_family (priv->font_desc); + if (family == NULL) + return; + + n_families = 0; + families = NULL; + pango_context_list_families (gtk_widget_get_pango_context (GTK_WIDGET (font_button)), + &families, &n_families); + n_faces = 0; + faces = NULL; + for (i = 0; i < n_families; i++) + { + const gchar *name = pango_font_family_get_name (families[i]); + + if (!g_ascii_strcasecmp (name, family)) + { + priv->font_family = g_object_ref (families[i]); + + pango_font_family_list_faces (families[i], &faces, &n_faces); + break; + } + } + g_free (families); + + for (i = 0; i < n_faces; i++) + { + PangoFontDescription *tmp_desc = pango_font_face_describe (faces[i]); + + if (font_description_style_equal (tmp_desc, priv->font_desc)) + { + priv->font_face = g_object_ref (faces[i]); + + pango_font_description_free (tmp_desc); + break; + } + else + pango_font_description_free (tmp_desc); + } + + g_free (faces); +} + +static gchar * +gtk_font_button_get_preview_text (GtkFontButton *font_button) +{ + GtkFontButtonPrivate *priv = font_button->priv; + + if (priv->font_dialog) + return gtk_font_chooser_get_preview_text (GTK_FONT_CHOOSER (priv->font_dialog)); + + return g_strdup (priv->preview_text); +} + +static void +gtk_font_button_set_preview_text (GtkFontButton *font_button, + const gchar *preview_text) +{ + GtkFontButtonPrivate *priv = font_button->priv; + + if (priv->font_dialog) + { + gtk_font_chooser_set_preview_text (GTK_FONT_CHOOSER (priv->font_dialog), + preview_text); + return; + } + + g_free (priv->preview_text); + priv->preview_text = g_strdup (preview_text); +} + + +static gboolean +gtk_font_button_get_show_preview_entry (GtkFontButton *font_button) +{ + GtkFontButtonPrivate *priv = font_button->priv; + + if (priv->font_dialog) + return gtk_font_chooser_get_show_preview_entry (GTK_FONT_CHOOSER (priv->font_dialog)); + + return priv->show_preview_entry; +} + +static void +gtk_font_button_set_show_preview_entry (GtkFontButton *font_button, + gboolean show) +{ + GtkFontButtonPrivate *priv = font_button->priv; + + if (priv->font_dialog) + gtk_font_chooser_set_show_preview_entry (GTK_FONT_CHOOSER (priv->font_dialog), show); + else + priv->show_preview_entry = show != FALSE; +} + +static PangoFontFamily * +gtk_font_button_font_chooser_get_font_family (GtkFontChooser *chooser) +{ + GtkFontButton *font_button = GTK_FONT_BUTTON (chooser); + GtkFontButtonPrivate *priv = font_button->priv; + + return priv->font_family; +} + +static PangoFontFace * +gtk_font_button_font_chooser_get_font_face (GtkFontChooser *chooser) +{ + GtkFontButton *font_button = GTK_FONT_BUTTON (chooser); + GtkFontButtonPrivate *priv = font_button->priv; + + return priv->font_face; +} + +static int +gtk_font_button_font_chooser_get_font_size (GtkFontChooser *chooser) +{ + GtkFontButton *font_button = GTK_FONT_BUTTON (chooser); + GtkFontButtonPrivate *priv = font_button->priv; + + return priv->font_size; +} + +static void +gtk_font_button_font_chooser_set_filter_func (GtkFontChooser *chooser, + GtkFontFilterFunc filter_func, + gpointer filter_data, + GDestroyNotify data_destroy) +{ + GtkFontButton *font_button = GTK_FONT_BUTTON (chooser); + GtkFontButtonPrivate *priv = font_button->priv; + + if (priv->font_dialog) + { + gtk_font_chooser_set_filter_func (GTK_FONT_CHOOSER (priv->font_dialog), + filter_func, + filter_data, + data_destroy); + return; + } + + clear_font_filter_data (font_button); + priv->font_filter = filter_func; + priv->font_filter_data = filter_data; + priv->font_filter_data_destroy = data_destroy; +} + +static void +gtk_font_button_take_font_desc (GtkFontButton *font_button, + PangoFontDescription *font_desc) +{ + GtkFontButtonPrivate *priv = font_button->priv; + GObject *object = G_OBJECT (font_button); + + if (priv->font_desc && font_desc && + pango_font_description_equal (priv->font_desc, font_desc)) + { + pango_font_description_free (font_desc); + return; + } + + g_object_freeze_notify (object); + + clear_font_data (font_button); + + if (font_desc) + priv->font_desc = font_desc; /* adopted */ + else + priv->font_desc = pango_font_description_from_string (_("Sans 12")); + + if (pango_font_description_get_size_is_absolute (priv->font_desc)) + priv->font_size = pango_font_description_get_size (priv->font_desc); + else + priv->font_size = pango_font_description_get_size (priv->font_desc) / PANGO_SCALE; + + gtk_font_button_update_font_data (font_button); + gtk_font_button_update_font_info (font_button); + + if (priv->font_dialog) + gtk_font_chooser_set_font_desc (GTK_FONT_CHOOSER (priv->font_dialog), + priv->font_desc); + + g_object_notify (G_OBJECT (font_button), "font"); + g_object_notify (G_OBJECT (font_button), "font-desc"); + g_object_notify (G_OBJECT (font_button), "font-name"); + + g_object_thaw_notify (object); +} + +static const PangoFontDescription * +gtk_font_button_get_font_desc (GtkFontButton *font_button) +{ + return font_button->priv->font_desc; +} + +static void +gtk_font_button_font_chooser_notify (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + /* We do not forward the notification of the "font" property to the dialog! */ + if (pspec->name == I_("preview-text") || + pspec->name == I_("show-preview-entry")) + g_object_notify_by_pspec (user_data, pspec); +} + +static void +gtk_font_button_font_chooser_iface_init (GtkFontChooserIface *iface) +{ + iface->get_font_family = gtk_font_button_font_chooser_get_font_family; + iface->get_font_face = gtk_font_button_font_chooser_get_font_face; + iface->get_font_size = gtk_font_button_font_chooser_get_font_size; + iface->set_filter_func = gtk_font_button_font_chooser_set_filter_func; +} + +G_DEFINE_TYPE_WITH_CODE (GtkFontButton, gtk_font_button, GTK_TYPE_BUTTON, + G_IMPLEMENT_INTERFACE (GTK_TYPE_FONT_CHOOSER, + gtk_font_button_font_chooser_iface_init)) static void gtk_font_button_class_init (GtkFontButtonClass *klass) @@ -138,6 +419,8 @@ gtk_font_button_class_init (GtkFontButtonClass *klass) klass->font_set = NULL; + _gtk_font_chooser_install_properties (gobject_class); + /** * GtkFontButton:title: * @@ -268,21 +551,23 @@ gtk_font_button_init (GtkFontButton *font_button) GtkFontButtonPrivate); /* Initialize fields */ - font_button->priv->fontname = g_strdup (_("Sans 12")); font_button->priv->use_font = FALSE; font_button->priv->use_size = FALSE; font_button->priv->show_style = TRUE; font_button->priv->show_size = TRUE; + font_button->priv->show_preview_entry = FALSE; font_button->priv->font_dialog = NULL; + font_button->priv->font_family = NULL; + font_button->priv->font_face = NULL; + font_button->priv->font_size = -1; font_button->priv->title = g_strdup (_("Pick a Font")); font_button->priv->inside = gtk_font_button_create_inside (font_button); gtk_container_add (GTK_CONTAINER (font_button), font_button->priv->inside); - gtk_font_button_update_font_info (font_button); + gtk_font_button_take_font_desc (font_button, NULL); } - static void gtk_font_button_finalize (GObject *object) { @@ -292,12 +577,15 @@ gtk_font_button_finalize (GObject *object) gtk_widget_destroy (font_button->priv->font_dialog); font_button->priv->font_dialog = NULL; - g_free (font_button->priv->fontname); - font_button->priv->fontname = NULL; - g_free (font_button->priv->title); font_button->priv->title = NULL; - + + clear_font_data (font_button); + clear_font_filter_data (font_button); + + g_free (font_button->priv->preview_text); + font_button->priv->preview_text = NULL; + G_OBJECT_CLASS (gtk_font_button_parent_class)->finalize (object); } @@ -308,12 +596,22 @@ gtk_font_button_set_property (GObject *object, GParamSpec *pspec) { GtkFontButton *font_button = GTK_FONT_BUTTON (object); - + switch (param_id) { + case GTK_FONT_CHOOSER_PROP_PREVIEW_TEXT: + gtk_font_button_set_preview_text (font_button, g_value_get_string (value)); + break; + case GTK_FONT_CHOOSER_PROP_SHOW_PREVIEW_ENTRY: + gtk_font_button_set_show_preview_entry (font_button, g_value_get_boolean (value)); + break; case PROP_TITLE: gtk_font_button_set_title (font_button, g_value_get_string (value)); break; + case GTK_FONT_CHOOSER_PROP_FONT_DESC: + gtk_font_button_take_font_desc (font_button, g_value_dup_boxed (value)); + break; + case GTK_FONT_CHOOSER_PROP_FONT: case PROP_FONT_NAME: gtk_font_button_set_font_name (font_button, g_value_get_string (value)); break; @@ -345,9 +643,19 @@ gtk_font_button_get_property (GObject *object, switch (param_id) { + case GTK_FONT_CHOOSER_PROP_PREVIEW_TEXT: + g_value_set_string (value, gtk_font_button_get_preview_text (font_button)); + break; + case GTK_FONT_CHOOSER_PROP_SHOW_PREVIEW_ENTRY: + g_value_set_boolean (value, gtk_font_button_get_show_preview_entry (font_button)); + break; case PROP_TITLE: g_value_set_string (value, gtk_font_button_get_title (font_button)); break; + case GTK_FONT_CHOOSER_PROP_FONT_DESC: + g_value_set_boxed (value, gtk_font_button_get_font_desc (font_button)); + break; + case GTK_FONT_CHOOSER_PROP_FONT: case PROP_FONT_NAME: g_value_set_string (value, gtk_font_button_get_font_name (font_button)); break; @@ -485,12 +793,9 @@ gtk_font_button_set_use_font (GtkFontButton *font_button, { font_button->priv->use_font = use_font; - if (use_font) - gtk_font_button_label_use_font (font_button); - else - gtk_widget_set_style (font_button->priv->font_label, NULL); + gtk_font_button_label_use_font (font_button); - g_object_notify (G_OBJECT (font_button), "use-font"); + g_object_notify (G_OBJECT (font_button), "use-font"); } } @@ -533,8 +838,7 @@ gtk_font_button_set_use_size (GtkFontButton *font_button, { font_button->priv->use_size = use_size; - if (font_button->priv->use_font) - gtk_font_button_label_use_font (font_button); + gtk_font_button_label_use_font (font_button); g_object_notify (G_OBJECT (font_button), "use-size"); } @@ -654,7 +958,7 @@ const gchar * gtk_font_button_get_font_name (GtkFontButton *font_button) { g_return_val_if_fail (GTK_IS_FONT_BUTTON (font_button), NULL); - + return font_button->priv->fontname; } @@ -665,8 +969,7 @@ gtk_font_button_get_font_name (GtkFontButton *font_button) * * Sets or updates the currently-displayed font in font picker dialog. * - * Returns: Return value of gtk_font_chooser_dialog_set_font_name() if the - * font chooser dialog exists, otherwise %FALSE. + * Returns: %TRUE * * Since: 2.4 */ @@ -674,30 +977,15 @@ gboolean gtk_font_button_set_font_name (GtkFontButton *font_button, const gchar *fontname) { - gboolean result; - gchar *old_fontname; + PangoFontDescription *font_desc; g_return_val_if_fail (GTK_IS_FONT_BUTTON (font_button), FALSE); g_return_val_if_fail (fontname != NULL, FALSE); - - if (g_ascii_strcasecmp (font_button->priv->fontname, fontname)) - { - old_fontname = font_button->priv->fontname; - font_button->priv->fontname = g_strdup (fontname); - g_free (old_fontname); - } - - gtk_font_button_update_font_info (font_button); - - if (font_button->priv->font_dialog) - result = gtk_font_chooser_set_font (GTK_FONT_CHOOSER (font_button->priv->font_dialog), - font_button->priv->fontname); - else - result = FALSE; - g_object_notify (G_OBJECT (font_button), "font-name"); + font_desc = pango_font_description_from_string (fontname); + gtk_font_button_take_font_desc (font_button, font_desc); - return result; + return TRUE; } static void @@ -705,18 +993,37 @@ gtk_font_button_clicked (GtkButton *button) { GtkFontChooser *font_dialog; GtkFontButton *font_button = GTK_FONT_BUTTON (button); + GtkFontButtonPrivate *priv = font_button->priv; if (!font_button->priv->font_dialog) { GtkWidget *parent; parent = gtk_widget_get_toplevel (GTK_WIDGET (font_button)); - - font_button->priv->font_dialog = gtk_font_chooser_dialog_new (font_button->priv->title, - NULL); - + + priv->font_dialog = gtk_font_chooser_dialog_new (priv->title, NULL); font_dialog = GTK_FONT_CHOOSER (font_button->priv->font_dialog); - + + gtk_font_chooser_set_show_preview_entry (font_dialog, priv->show_preview_entry); + + if (priv->preview_text) + { + gtk_font_chooser_set_preview_text (font_dialog, priv->preview_text); + g_free (priv->preview_text); + priv->preview_text = NULL; + } + + if (priv->font_filter) + { + gtk_font_chooser_set_filter_func (font_dialog, + priv->font_filter, + priv->font_filter_data, + priv->font_filter_data_destroy); + priv->font_filter = NULL; + priv->font_filter_data = NULL; + priv->font_filter_data_destroy = NULL; + } + if (gtk_widget_is_toplevel (parent) && GTK_IS_WINDOW (parent)) { if (GTK_WINDOW (parent) != gtk_window_get_transient_for (GTK_WINDOW (font_dialog))) @@ -726,6 +1033,9 @@ gtk_font_button_clicked (GtkButton *button) gtk_window_get_modal (GTK_WINDOW (parent))); } + g_signal_connect (font_dialog, "notify", + G_CALLBACK (gtk_font_button_font_chooser_notify), button); + g_signal_connect (font_dialog, "response", G_CALLBACK (response_cb), font_button); @@ -736,7 +1046,7 @@ gtk_font_button_clicked (GtkButton *button) if (!gtk_widget_get_visible (font_button->priv->font_dialog)) { font_dialog = GTK_FONT_CHOOSER (font_button->priv->font_dialog); - gtk_font_chooser_set_font (font_dialog, font_button->priv->fontname); + gtk_font_chooser_set_font_desc (font_dialog, font_button->priv->font_desc); } gtk_window_present (GTK_WINDOW (font_button->priv->font_dialog)); @@ -749,19 +1059,42 @@ response_cb (GtkDialog *dialog, gpointer data) { GtkFontButton *font_button = GTK_FONT_BUTTON (data); + GtkFontButtonPrivate *priv = font_button->priv; + GtkFontChooser *font_chooser; + GObject *object; + gtk_widget_hide (font_button->priv->font_dialog); if (response_id != GTK_RESPONSE_OK) return; - g_free (font_button->priv->fontname); - font_button->priv->fontname = gtk_font_chooser_get_font (GTK_FONT_CHOOSER (font_button->priv->font_dialog)); - + font_chooser = GTK_FONT_CHOOSER (priv->font_dialog); + object = G_OBJECT (font_chooser); + + g_object_freeze_notify (object); + + clear_font_data (font_button); + + priv->font_desc = gtk_font_chooser_get_font_desc (font_chooser); + if (priv->font_desc) + priv->fontname = pango_font_description_to_string (priv->font_desc); + priv->font_family = gtk_font_chooser_get_font_family (font_chooser); + if (priv->font_family) + g_object_ref (priv->font_family); + priv->font_face = gtk_font_chooser_get_font_face (font_chooser); + if (priv->font_face) + g_object_ref (priv->font_face); + priv->font_size = gtk_font_chooser_get_font_size (font_chooser); + /* Set label font */ gtk_font_button_update_font_info (font_button); + g_object_notify (G_OBJECT (font_button), "font"); + g_object_notify (G_OBJECT (font_button), "font-desc"); g_object_notify (G_OBJECT (font_button), "font-name"); - + + g_object_thaw_notify (object); + /* Emit font_set signal */ g_signal_emit (font_button, font_button_signals[FONT_SET], 0); } @@ -809,104 +1142,50 @@ gtk_font_button_label_use_font (GtkFontButton *font_button) { PangoFontDescription *desc; - if (!font_button->priv->use_font) - return; + if (font_button->priv->use_font) + { + desc = pango_font_description_copy (font_button->priv->font_desc); - desc = pango_font_description_from_string (font_button->priv->fontname); - - if (!font_button->priv->use_size) - pango_font_description_unset_fields (desc, PANGO_FONT_MASK_SIZE); + if (!font_button->priv->use_size) + pango_font_description_unset_fields (desc, PANGO_FONT_MASK_SIZE); + } + else + desc = NULL; - gtk_widget_modify_font (font_button->priv->font_label, desc); + gtk_widget_override_font (font_button->priv->font_label, desc); - pango_font_description_free (desc); -} - -static gboolean -font_description_style_equal (const PangoFontDescription *a, - const PangoFontDescription *b) -{ - return (pango_font_description_get_weight (a) == pango_font_description_get_weight (b) && - pango_font_description_get_style (a) == pango_font_description_get_style (b) && - pango_font_description_get_stretch (a) == pango_font_description_get_stretch (b) && - pango_font_description_get_variant (a) == pango_font_description_get_variant (b)); + if (desc) + pango_font_description_free (desc); } static void gtk_font_button_update_font_info (GtkFontButton *font_button) { - PangoFontDescription *desc; - const gchar *family; - gchar *style; + GtkFontButtonPrivate *priv = font_button->priv; gchar *family_style; - - desc = pango_font_description_from_string (font_button->priv->fontname); - family = pango_font_description_get_family (desc); - -#if 0 - /* This gives the wrong names, e.g. Italic when the font chooser - * dialog displayed Oblique. - */ - pango_font_description_unset_fields (desc, PANGO_FONT_MASK_FAMILY | PANGO_FONT_MASK_SIZE); - style = pango_font_description_to_string (desc); - gtk_label_set_text (GTK_LABEL (font_button->priv->style_label), style); -#endif - style = NULL; - if (font_button->priv->show_style && family) + g_assert (priv->font_desc != NULL); + + if (priv->show_style) { - PangoFontFamily **families; - PangoFontFace **faces; - gint n_families, n_faces, i; - - n_families = 0; - families = NULL; - pango_context_list_families (gtk_widget_get_pango_context (GTK_WIDGET (font_button)), - &families, &n_families); - n_faces = 0; - faces = NULL; - for (i = 0; i < n_families; i++) - { - const gchar *name = pango_font_family_get_name (families[i]); - - if (!g_ascii_strcasecmp (name, family)) - { - pango_font_family_list_faces (families[i], &faces, &n_faces); - break; - } - } - g_free (families); - - for (i = 0; i < n_faces; i++) - { - PangoFontDescription *tmp_desc = pango_font_face_describe (faces[i]); - - if (font_description_style_equal (tmp_desc, desc)) - { - style = g_strdup (pango_font_face_get_face_name (faces[i])); - pango_font_description_free (tmp_desc); - break; - } - else - pango_font_description_free (tmp_desc); - } - g_free (faces); - } + PangoFontDescription *desc = pango_font_description_copy_static (priv->font_desc); - if (style == NULL || !g_ascii_strcasecmp (style, "Regular")) - family_style = g_strdup (family); + pango_font_description_unset_fields (desc, PANGO_FONT_MASK_SIZE); + family_style = pango_font_description_to_string (desc); + pango_font_description_free (desc); + } else - family_style = g_strdup_printf ("%s %s", family, style); - + family_style = g_strdup (pango_font_description_get_family (priv->font_desc)); + gtk_label_set_text (GTK_LABEL (font_button->priv->font_label), family_style); - - g_free (style); g_free (family_style); if (font_button->priv->show_size) { - gchar *size = g_strdup_printf ("%g", - pango_font_description_get_size (desc) / (double)PANGO_SCALE); + /* mirror Pango, which doesn't translate this either */ + gchar *size = g_strdup_printf ("%g%s", + pango_font_description_get_size (priv->font_desc) / (double)PANGO_SCALE, + pango_font_description_get_size_is_absolute (priv->font_desc) ? "px" : ""); gtk_label_set_text (GTK_LABEL (font_button->priv->size_label), size); @@ -914,6 +1193,4 @@ gtk_font_button_update_font_info (GtkFontButton *font_button) } gtk_font_button_label_use_font (font_button); - - pango_font_description_free (desc); }