X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkaccellabel.c;h=d8bb7e96fa4069247059cc3183863c7fdc3af6ec;hb=32825a66ac8e65bf98cafed26a339fa1f31eddd4;hp=0b0e1bc780de06e3f54b157102cfe3b64648e60c;hpb=b6783933c9dbf6bf29c8177f2d0d1eec09119f3b;p=~andy%2Fgtk diff --git a/gtk/gtkaccellabel.c b/gtk/gtkaccellabel.c index 0b0e1bc78..d8bb7e96f 100644 --- a/gtk/gtkaccellabel.c +++ b/gtk/gtkaccellabel.c @@ -15,9 +15,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 . */ /* @@ -87,7 +85,7 @@ * GtkAccelLabel is automatically set up to display the GtkMenuItem * accelerators. We just need to make sure we use GTK_ACCEL_VISIBLE here. */ * gtk_widget_add_accelerator (save_item, "activate", accel_group, - * GDK_s, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + * GDK_KEY_s, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); * * */ @@ -100,12 +98,15 @@ enum { struct _GtkAccelLabelPrivate { - guint accel_padding; /* should be style property? */ - GtkWidget *accel_widget; /* done*/ + GtkWidget *accel_widget; /* done */ GClosure *accel_closure; /* has set function */ GtkAccelGroup *accel_group; /* set by set_accel_closure() */ gchar *accel_string; /* has set function */ + guint accel_padding; /* should be style property? */ guint16 accel_string_width; /* seems to be private */ + + guint accel_key; /* manual accel key specification if != 0 */ + GdkModifierType accel_mods; }; static void gtk_accel_label_set_property (GObject *object, @@ -127,8 +128,6 @@ static void gtk_accel_label_get_preferred_width (GtkWidget *wi gint *min_width, gint *nat_width); -#define GTK_ACCEL_LABEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_ACCEL_LABEL, GtkAccelLabelPrivate)) - G_DEFINE_TYPE (GtkAccelLabel, gtk_accel_label, GTK_TYPE_LABEL) @@ -146,6 +145,8 @@ gtk_accel_label_class_init (GtkAccelLabelClass *class) widget_class->get_preferred_width = gtk_accel_label_get_preferred_width; widget_class->destroy = gtk_accel_label_destroy; + gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_ACCEL_LABEL); + class->signal_quote1 = g_strdup ("<:"); class->signal_quote2 = g_strdup (":>"); @@ -250,15 +251,18 @@ gtk_accel_label_get_property (GObject *object, static void gtk_accel_label_init (GtkAccelLabel *accel_label) { - GtkAccelLabelPrivate *priv = GTK_ACCEL_LABEL_GET_PRIVATE (accel_label); + GtkAccelLabelPrivate *priv; + + accel_label->priv = G_TYPE_INSTANCE_GET_PRIVATE (accel_label, + GTK_TYPE_ACCEL_LABEL, + GtkAccelLabelPrivate); + priv = accel_label->priv; priv->accel_padding = 3; priv->accel_widget = NULL; priv->accel_closure = NULL; priv->accel_group = NULL; priv->accel_string = NULL; - - accel_label->priv = priv; } /** @@ -386,7 +390,7 @@ gtk_accel_label_draw (GtkWidget *widget, direction = gtk_widget_get_direction (widget); ac_width = gtk_accel_label_get_accel_width (accel_label); gtk_widget_get_allocation (widget, &allocation); - gtk_widget_get_preferred_size (widget, &requisition, NULL); + gtk_widget_get_preferred_size (widget, NULL, &requisition); if (allocation.width >= requisition.width + ac_width) { @@ -442,7 +446,6 @@ gtk_accel_label_draw (GtkWidget *widget, gtk_style_context_save (context); gtk_style_context_add_class (context, GTK_STYLE_CLASS_ACCELERATOR); - gtk_style_context_set_state (context, gtk_widget_get_state_flags (widget)); gtk_render_layout (context, cr, x, y, accel_layout); gtk_style_context_restore (context); @@ -478,40 +481,56 @@ refetch_widget_accel_closure (GtkAccelLabel *accel_label) gtk_accel_label_set_accel_closure (accel_label, closure); } +static void +accel_widget_weak_ref_cb (GtkAccelLabel *accel_label, + GtkWidget *old_accel_widget) +{ + g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label)); + g_return_if_fail (GTK_IS_WIDGET (accel_label->priv->accel_widget)); + + g_signal_handlers_disconnect_by_func (accel_label->priv->accel_widget, + refetch_widget_accel_closure, + accel_label); + accel_label->priv->accel_widget = NULL; + g_object_notify (G_OBJECT (accel_label), "accel-widget"); +} + /** * gtk_accel_label_set_accel_widget: * @accel_label: a #GtkAccelLabel * @accel_widget: the widget to be monitored. * - * Sets the widget to be monitored by this accelerator label. - **/ + * Sets the widget to be monitored by this accelerator label. + */ void gtk_accel_label_set_accel_widget (GtkAccelLabel *accel_label, - GtkWidget *accel_widget) + GtkWidget *accel_widget) { g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label)); if (accel_widget) g_return_if_fail (GTK_IS_WIDGET (accel_widget)); - + if (accel_widget != accel_label->priv->accel_widget) { if (accel_label->priv->accel_widget) - { - gtk_accel_label_set_accel_closure (accel_label, NULL); - g_signal_handlers_disconnect_by_func (accel_label->priv->accel_widget, - refetch_widget_accel_closure, - accel_label); - g_object_unref (accel_label->priv->accel_widget); - } + { + gtk_accel_label_set_accel_closure (accel_label, NULL); + g_signal_handlers_disconnect_by_func (accel_label->priv->accel_widget, + refetch_widget_accel_closure, + accel_label); + g_object_weak_unref (G_OBJECT (accel_label->priv->accel_widget), + (GWeakNotify) accel_widget_weak_ref_cb, accel_label); + } accel_label->priv->accel_widget = accel_widget; if (accel_label->priv->accel_widget) - { - g_object_ref (accel_label->priv->accel_widget); - g_signal_connect_object (accel_label->priv->accel_widget, "accel-closures-changed", - G_CALLBACK (refetch_widget_accel_closure), - accel_label, G_CONNECT_SWAPPED); - refetch_widget_accel_closure (accel_label); - } + { + g_object_weak_ref (G_OBJECT (accel_label->priv->accel_widget), + (GWeakNotify) accel_widget_weak_ref_cb, accel_label); + g_signal_connect_object (accel_label->priv->accel_widget, "accel-closures-changed", + G_CALLBACK (refetch_widget_accel_closure), + accel_label, G_CONNECT_SWAPPED); + refetch_widget_accel_closure (accel_label); + } g_object_notify (G_OBJECT (accel_label), "accel-widget"); } } @@ -597,30 +616,34 @@ gtk_accel_label_get_string (GtkAccelLabel *accel_label) } /* Underscores in key names are better displayed as spaces - * E.g., Page_Up should be "Page Up" + * E.g., Page_Up should be "Page Up". + * + * Some keynames also have prefixes that are not suitable + * for display, e.g XF86AudioMute, so strip those out, too. + * + * This function is only called on untranslated keynames, + * so no need to be UTF-8 safe. */ static void -substitute_underscores (gchar *str) +append_without_underscores (GString *s, + gchar *str) { - char *p; - - for (p = str; *p; p++) - if (*p == '_') - *p = ' '; -} + gchar *p; -/* Some keynames have prefixes that are not suitable - * for display, e.g XF86AudioMute - */ -static gchar * -strip_prefix (gchar *str) -{ if (g_str_has_prefix (str, "XF86")) - return str + 4; + p = str + 4; else if (g_str_has_prefix (str, "ISO_")) - return str + 4; + p = str + 4; + else + p = str; - return str; + for ( ; *p; p++) + { + if (*p == '_') + g_string_append_c (s, ' '); + else + g_string_append_c (s, *p); + } } /* On Mac, if the key has symbolic representation (e.g. arrow keys), @@ -813,12 +836,13 @@ _gtk_accel_label_class_get_accelerator_label (GtkAccelLabelClass *klass, #endif seen_mod = TRUE; } - if (seen_mod) - g_string_append (gstring, klass->mod_separator); ch = gdk_keyval_to_unicode (accelerator_key); if (ch && ch < 0x80 && (g_unichar_isgraph (ch) || ch == ' ')) { + if (seen_mod) + g_string_append (gstring, klass->mod_separator); + switch (ch) { case ' ': @@ -839,6 +863,9 @@ _gtk_accel_label_class_get_accelerator_label (GtkAccelLabelClass *klass, tmp = gdk_keyval_name (gdk_keyval_to_lower (accelerator_key)); if (tmp != NULL) { + if (seen_mod) + g_string_append (gstring, klass->mod_separator); + if (tmp[0] != 0 && tmp[1] == 0) g_string_append_c (gstring, g_ascii_toupper (tmp[0])); else @@ -846,11 +873,7 @@ _gtk_accel_label_class_get_accelerator_label (GtkAccelLabelClass *klass, const gchar *str; str = g_dpgettext2 (GETTEXT_PACKAGE, "keyboard label", tmp); if (str == tmp) - { - substitute_underscores (tmp); - tmp = strip_prefix (tmp); - g_string_append (gstring, tmp); - } + append_without_underscores (gstring, tmp); else g_string_append (gstring, str); } @@ -887,26 +910,52 @@ gtk_accel_label_refetch (GtkAccelLabel *accel_label) "gtk-enable-accels", &enable_accels, NULL); - if (enable_accels && accel_label->priv->accel_closure) + if (enable_accels && (accel_label->priv->accel_closure || accel_label->priv->accel_key)) { - GtkAccelKey *key = gtk_accel_group_find (accel_label->priv->accel_group, find_accel, accel_label->priv->accel_closure); - - if (key && key->accel_flags & GTK_ACCEL_VISIBLE) + gboolean have_accel = FALSE; + guint accel_key; + GdkModifierType accel_mods; + + /* First check for a manual accel set with _set_accel() */ + if (accel_label->priv->accel_key) + { + accel_mods = accel_label->priv->accel_mods; + accel_key = accel_label->priv->accel_key; + have_accel = TRUE; + } + + /* If we don't have a hardcoded value, check the accel group */ + if (!have_accel) + { + GtkAccelKey *key; + + key = gtk_accel_group_find (accel_label->priv->accel_group, find_accel, accel_label->priv->accel_closure); + + if (key && key->accel_flags & GTK_ACCEL_VISIBLE) + { + accel_key = key->accel_key; + accel_mods = key->accel_mods; + have_accel = TRUE; + } + } + + /* If we found a key using either method, set it */ + if (have_accel) { GtkAccelLabelClass *klass; gchar *tmp; klass = GTK_ACCEL_LABEL_GET_CLASS (accel_label); - tmp = _gtk_accel_label_class_get_accelerator_label (klass, - key->accel_key, - key->accel_mods); + tmp = _gtk_accel_label_class_get_accelerator_label (klass, accel_key, accel_mods); accel_label->priv->accel_string = g_strconcat (" ", tmp, NULL); g_free (tmp); } - if (!accel_label->priv->accel_string) - accel_label->priv->accel_string = g_strdup ("-/-"); + + else + /* Otherwise we have a closure with no key. Show "-/-". */ + accel_label->priv->accel_string = g_strdup ("-/-"); } - + if (!accel_label->priv->accel_string) accel_label->priv->accel_string = g_strdup (""); @@ -914,3 +963,30 @@ gtk_accel_label_refetch (GtkAccelLabel *accel_label) return FALSE; } + +/** + * gtk_accel_label_set_accel: + * @accel_label: a #GtkAccelLabel + * @accelerator_key: a keyval, or 0 + * @accelerator_mods: the modifier mask for the accel + * + * Manually sets a keyval and modifier mask as the accelerator rendered + * by @accel_label. + * + * If a keyval and modifier are explicitly set then these values are + * used regardless of any associated accel closure or widget. + * + * Providing an @accelerator_key of 0 removes the manual setting. + * + * Since: 3.6 + */ +void +gtk_accel_label_set_accel (GtkAccelLabel *accel_label, + guint accelerator_key, + GdkModifierType accelerator_mods) +{ + accel_label->priv->accel_key = accelerator_key; + accel_label->priv->accel_mods = accelerator_mods; + + gtk_accel_label_reset (accel_label); +}