X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;ds=sidebyside;f=gtk%2Fgtkaccellabel.c;h=c60f308cd9764b6189ed7ca1b945b6bb3d857a4f;hb=0a28c9f67842d02bce2b93a1bd829b7491c180af;hp=efa096fd35e856e43cfb233809aa997f79d6ce1a;hpb=2394977634817390b27a13de8577f865f3ef7e6f;p=~andy%2Fgtk diff --git a/gtk/gtkaccellabel.c b/gtk/gtkaccellabel.c index efa096fd3..c60f308cd 100644 --- a/gtk/gtkaccellabel.c +++ b/gtk/gtkaccellabel.c @@ -26,14 +26,16 @@ * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ + +#include +#include + #include "gtkaccellabel.h" #include "gtkaccelmap.h" #include "gtkmain.h" -#include "gtksignal.h" +#include "gtkprivate.h" #include "gtkintl.h" - -#include -#include +#include "gtkalias.h" enum { PROP_0, @@ -41,48 +43,50 @@ enum { PROP_ACCEL_WIDGET }; -static void gtk_accel_label_class_init (GtkAccelLabelClass *klass); -static void gtk_accel_label_init (GtkAccelLabel *accel_label); -static void gtk_accel_label_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void gtk_accel_label_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static void gtk_accel_label_destroy (GtkObject *object); -static void gtk_accel_label_finalize (GObject *object); -static void gtk_accel_label_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static gboolean gtk_accel_label_expose_event (GtkWidget *widget, - GdkEventExpose *event); -static gboolean gtk_accel_label_refetch_idle (GtkAccelLabel *accel_label); - -static GtkAccelLabelClass *accel_label_class = NULL; -static GtkLabelClass *parent_class = NULL; +static void gtk_accel_label_class_init (GtkAccelLabelClass *klass); +static void gtk_accel_label_init (GtkAccelLabel *accel_label); +static void gtk_accel_label_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_accel_label_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void gtk_accel_label_destroy (GtkObject *object); +static void gtk_accel_label_finalize (GObject *object); +static void gtk_accel_label_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static gboolean gtk_accel_label_expose_event (GtkWidget *widget, + GdkEventExpose *event); +static const gchar *gtk_accel_label_get_string (GtkAccelLabel *accel_label); -GtkType +static GtkLabelClass *parent_class = NULL; + +GType gtk_accel_label_get_type (void) { - static GtkType accel_label_type = 0; + static GType accel_label_type = 0; if (!accel_label_type) { - static const GtkTypeInfo accel_label_info = + static const GTypeInfo accel_label_info = { - "GtkAccelLabel", - sizeof (GtkAccelLabel), sizeof (GtkAccelLabelClass), - (GtkClassInitFunc) gtk_accel_label_class_init, - (GtkObjectInitFunc) gtk_accel_label_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gtk_accel_label_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GtkAccelLabel), + 0, /* n_preallocs */ + (GInstanceInitFunc) gtk_accel_label_init, }; - accel_label_type = gtk_type_unique (GTK_TYPE_LABEL, &accel_label_info); + accel_label_type = + g_type_register_static (GTK_TYPE_LABEL, "GtkAccelLabel", + &accel_label_info, 0); } return accel_label_type; @@ -95,7 +99,6 @@ gtk_accel_label_class_init (GtkAccelLabelClass *class) GtkObjectClass *object_class = GTK_OBJECT_CLASS (class); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); - accel_label_class = class; parent_class = g_type_class_peek_parent (class); gobject_class->finalize = gtk_accel_label_finalize; @@ -109,27 +112,42 @@ gtk_accel_label_class_init (GtkAccelLabelClass *class) class->signal_quote1 = g_strdup ("<:"); class->signal_quote2 = g_strdup (":>"); - class->mod_name_shift = g_strdup ("Shift"); - class->mod_name_control = g_strdup ("Ctrl"); - class->mod_name_alt = g_strdup ("Alt"); + /* This is the text that should appear next to menu accelerators + * that use the shift key. If the text on this key isn't typically + * translated on keyboards used for your language, don't translate + * this. + */ + class->mod_name_shift = g_strdup (_("Shift")); + /* This is the text that should appear next to menu accelerators + * that use the control key. If the text on this key isn't typically + * translated on keyboards used for your language, don't translate + * this. + */ + class->mod_name_control = g_strdup (_("Ctrl")); + /* This is the text that should appear next to menu accelerators + * that use the alt key. If the text on this key isn't typically + * translated on keyboards used for your language, don't translate + * this. + */ + class->mod_name_alt = g_strdup (_("Alt")); class->mod_separator = g_strdup ("+"); class->accel_seperator = g_strdup (" / "); class->latin1_to_char = TRUE; - g_object_class_install_property (G_OBJECT_CLASS (object_class), + g_object_class_install_property (gobject_class, PROP_ACCEL_CLOSURE, - g_param_spec_boxed ("accel_closure", - _("Accelerator Closure"), - _("The closure to be monitored for accelerator changes"), + g_param_spec_boxed ("accel-closure", + P_("Accelerator Closure"), + P_("The closure to be monitored for accelerator changes"), G_TYPE_CLOSURE, - G_PARAM_READABLE | G_PARAM_WRITABLE)); - g_object_class_install_property (G_OBJECT_CLASS (object_class), + GTK_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, PROP_ACCEL_WIDGET, - g_param_spec_object ("accel_widget", - _("Accelerator Widget"), - _("The widget to be monitored for accelerator changes"), + g_param_spec_object ("accel-widget", + P_("Accelerator Widget"), + P_("The widget to be monitored for accelerator changes"), GTK_TYPE_WIDGET, - G_PARAM_READABLE | G_PARAM_WRITABLE)); + GTK_PARAM_READWRITE)); } static void @@ -183,14 +201,11 @@ gtk_accel_label_get_property (GObject *object, static void gtk_accel_label_init (GtkAccelLabel *accel_label) { - accel_label->queue_id = 0; accel_label->accel_padding = 3; accel_label->accel_widget = NULL; accel_label->accel_closure = NULL; accel_label->accel_group = NULL; accel_label->accel_string = NULL; - - gtk_accel_label_refetch (accel_label); } GtkWidget* @@ -200,7 +215,7 @@ gtk_accel_label_new (const gchar *string) g_return_val_if_fail (string != NULL, NULL); - accel_label = gtk_type_new (GTK_TYPE_ACCEL_LABEL); + accel_label = g_object_new (GTK_TYPE_ACCEL_LABEL, NULL); gtk_label_set_text (GTK_LABEL (accel_label), string); @@ -210,11 +225,7 @@ gtk_accel_label_new (const gchar *string) static void gtk_accel_label_destroy (GtkObject *object) { - GtkAccelLabel *accel_label; - - g_return_if_fail (GTK_IS_ACCEL_LABEL (object)); - - accel_label = GTK_ACCEL_LABEL (object); + GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (object); gtk_accel_label_set_accel_widget (accel_label, NULL); gtk_accel_label_set_accel_closure (accel_label, NULL); @@ -227,11 +238,6 @@ gtk_accel_label_finalize (GObject *object) { GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (object); - if (accel_label->queue_id) - { - gtk_idle_remove (accel_label->queue_id); - accel_label->queue_id = 0; - } g_free (accel_label->accel_string); G_OBJECT_CLASS (parent_class)->finalize (object); @@ -268,39 +274,43 @@ static void gtk_accel_label_size_request (GtkWidget *widget, GtkRequisition *requisition) { - GtkAccelLabel *accel_label; + GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (widget); PangoLayout *layout; gint width; - g_return_if_fail (GTK_IS_ACCEL_LABEL (widget)); - g_return_if_fail (requisition != NULL); - - accel_label = GTK_ACCEL_LABEL (widget); - if (GTK_WIDGET_CLASS (parent_class)->size_request) GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition); - layout = gtk_widget_create_pango_layout (widget, accel_label->accel_string); + layout = gtk_widget_create_pango_layout (widget, gtk_accel_label_get_string (accel_label)); pango_layout_get_pixel_size (layout, &width, NULL); accel_label->accel_string_width = width; - g_object_unref (G_OBJECT (layout)); + g_object_unref (layout); +} + +static gint +get_first_baseline (PangoLayout *layout) +{ + PangoLayoutIter *iter; + gint result; + + iter = pango_layout_get_iter (layout); + result = pango_layout_iter_get_baseline (iter); + pango_layout_iter_free (iter); + + return PANGO_PIXELS (result); } static gboolean gtk_accel_label_expose_event (GtkWidget *widget, GdkEventExpose *event) { - GtkMisc *misc; - GtkAccelLabel *accel_label; - PangoLayout *layout; - - g_return_val_if_fail (GTK_IS_ACCEL_LABEL (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - - accel_label = GTK_ACCEL_LABEL (widget); - misc = GTK_MISC (accel_label); - + GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (widget); + GtkMisc *misc = GTK_MISC (accel_label); + GtkTextDirection direction; + + direction = gtk_widget_get_direction (widget); + if (GTK_WIDGET_DRAWABLE (accel_label)) { guint ac_width; @@ -309,22 +319,43 @@ gtk_accel_label_expose_event (GtkWidget *widget, if (widget->allocation.width >= widget->requisition.width + ac_width) { - guint x; - guint y; + PangoLayout *label_layout; + PangoLayout *accel_layout; + GtkLabel *label = GTK_LABEL (widget); + + gint x; + gint y; + label_layout = gtk_label_get_layout (GTK_LABEL (accel_label)); + + if (direction == GTK_TEXT_DIR_RTL) + widget->allocation.x += ac_width; widget->allocation.width -= ac_width; + if (gtk_label_get_ellipsize (label)) + pango_layout_set_width (label_layout, + pango_layout_get_width (label_layout) + - ac_width * PANGO_SCALE); + if (GTK_WIDGET_CLASS (parent_class)->expose_event) GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event); + if (direction == GTK_TEXT_DIR_RTL) + widget->allocation.x -= ac_width; widget->allocation.width += ac_width; + if (gtk_label_get_ellipsize (label)) + pango_layout_set_width (label_layout, + pango_layout_get_width (label_layout) + + ac_width * PANGO_SCALE); - x = widget->allocation.x + widget->allocation.width - misc->xpad - ac_width; - - y = (widget->allocation.y * (1.0 - misc->yalign) + - (widget->allocation.y + widget->allocation.height - - (widget->requisition.height - misc->ypad * 2)) * - misc->yalign) + 1.5; - - layout = gtk_widget_create_pango_layout (widget, accel_label->accel_string); + if (direction == GTK_TEXT_DIR_RTL) + x = widget->allocation.x + misc->xpad; + else + x = widget->allocation.x + widget->allocation.width - misc->xpad - ac_width; + + gtk_label_get_layout_offsets (GTK_LABEL (accel_label), NULL, &y); + + accel_layout = gtk_widget_create_pango_layout (widget, gtk_accel_label_get_string (accel_label)); + + y += get_first_baseline (label_layout) - get_first_baseline (accel_layout); gtk_paint_layout (widget->style, widget->window, @@ -334,9 +365,9 @@ gtk_accel_label_expose_event (GtkWidget *widget, widget, "accellabel", x, y, - layout); + accel_layout); - g_object_unref (G_OBJECT (layout)); + g_object_unref (accel_layout); } else { @@ -345,27 +376,36 @@ gtk_accel_label_expose_event (GtkWidget *widget, } } - return TRUE; + return FALSE; } static void refetch_widget_accel_closure (GtkAccelLabel *accel_label) { - GSList *slist; - + GClosure *closure = NULL; + GList *clist, *list; + g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label)); g_return_if_fail (GTK_IS_WIDGET (accel_label->accel_widget)); - for (slist = _gtk_widget_get_accel_closures (accel_label->accel_widget); slist; slist = slist->next) - if (gtk_accel_group_from_accel_closure (slist->data)) - { - /* we just take the first correctly used closure */ - gtk_accel_label_set_accel_closure (accel_label, slist->data); - return; - } - gtk_accel_label_set_accel_closure (accel_label, NULL); + clist = gtk_widget_list_accel_closures (accel_label->accel_widget); + for (list = clist; list; list = list->next) + { + /* we just take the first closure used */ + closure = list->data; + break; + } + g_list_free (clist); + gtk_accel_label_set_accel_closure (accel_label, closure); } +/** + * 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. + **/ void gtk_accel_label_set_accel_widget (GtkAccelLabel *accel_label, GtkWidget *accel_widget) @@ -380,7 +420,7 @@ gtk_accel_label_set_accel_widget (GtkAccelLabel *accel_label, { gtk_accel_label_set_accel_closure (accel_label, NULL); g_signal_handlers_disconnect_by_func (accel_label->accel_widget, - G_CALLBACK (refetch_widget_accel_closure), + refetch_widget_accel_closure, accel_label); g_object_unref (accel_label->accel_widget); } @@ -393,19 +433,20 @@ gtk_accel_label_set_accel_widget (GtkAccelLabel *accel_label, accel_label, G_CONNECT_SWAPPED); refetch_widget_accel_closure (accel_label); } - g_object_notify (G_OBJECT (accel_label), "accel_widget"); + g_object_notify (G_OBJECT (accel_label), "accel-widget"); } } static void -gtk_accel_label_queue_refetch (GtkAccelLabel *accel_label) +gtk_accel_label_reset (GtkAccelLabel *accel_label) { - g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label)); - - if (accel_label->queue_id == 0) - accel_label->queue_id = gtk_idle_add_priority (G_PRIORITY_HIGH_IDLE, - (GtkFunction) gtk_accel_label_refetch_idle, - accel_label); + if (accel_label->accel_string) + { + g_free (accel_label->accel_string); + accel_label->accel_string = NULL; + } + + gtk_widget_queue_resize (GTK_WIDGET (accel_label)); } static void @@ -416,9 +457,17 @@ check_accel_changed (GtkAccelGroup *accel_group, GtkAccelLabel *accel_label) { if (accel_closure == accel_label->accel_closure) - gtk_accel_label_queue_refetch (accel_label); + gtk_accel_label_reset (accel_label); } +/** + * gtk_accel_label_set_accel_closure: + * @accel_label: a #GtkAccelLabel + * @accel_closure: the closure to monitor for accelerator changes. + * + * Sets the closure to be monitored by this accelerator label. The closure + * must be connected to an accelerator group; see gtk_accel_group_connect(). + **/ void gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label, GClosure *accel_closure) @@ -432,7 +481,7 @@ gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label, if (accel_label->accel_closure) { g_signal_handlers_disconnect_by_func (accel_label->accel_group, - G_CALLBACK (check_accel_changed), + check_accel_changed, accel_label); accel_label->accel_group = NULL; g_closure_unref (accel_label->accel_closure); @@ -446,43 +495,120 @@ gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label, G_CALLBACK (check_accel_changed), accel_label, 0); } - gtk_accel_label_queue_refetch (accel_label); - g_object_notify (G_OBJECT (accel_label), "accel_closure"); + gtk_accel_label_reset (accel_label); + g_object_notify (G_OBJECT (accel_label), "accel-closure"); } } static gboolean -gtk_accel_label_refetch_idle (GtkAccelLabel *accel_label) +find_accel (GtkAccelKey *key, + GClosure *closure, + gpointer data) { - gboolean retval; + return data == (gpointer) closure; +} - GDK_THREADS_ENTER (); - retval = gtk_accel_label_refetch (accel_label); - GDK_THREADS_LEAVE (); +static const gchar * +gtk_accel_label_get_string (GtkAccelLabel *accel_label) +{ + if (!accel_label->accel_string) + gtk_accel_label_refetch (accel_label); + + return accel_label->accel_string; +} - return retval; +/* Underscores in key names are better displayed as spaces + * E.g., Page_Up should be "Page Up" + */ +static void +substitute_underscores (char *str) +{ + char *p; + + for (p = str; *p; p++) + if (*p == '_') + *p = ' '; } -static gboolean -find_accel (GtkAccelKey *key, - GClosure *closure, - gpointer data) +gchar * +_gtk_accel_label_class_get_accelerator_label (GtkAccelLabelClass *klass, + guint accelerator_key, + GdkModifierType accelerator_mods) { - return data == (gpointer) closure; + GString *gstring; + gboolean seen_mod = FALSE; + gunichar ch; + + gstring = g_string_new (""); + + if (accelerator_mods & GDK_SHIFT_MASK) + { + g_string_append (gstring, klass->mod_name_shift); + seen_mod = TRUE; + } + if (accelerator_mods & GDK_CONTROL_MASK) + { + if (seen_mod) + g_string_append (gstring, klass->mod_separator); + g_string_append (gstring, klass->mod_name_control); + seen_mod = TRUE; + } + if (accelerator_mods & GDK_MOD1_MASK) + { + if (seen_mod) + g_string_append (gstring, klass->mod_separator); + g_string_append (gstring, klass->mod_name_alt); + seen_mod = TRUE; + } + if (seen_mod) + g_string_append (gstring, klass->mod_separator); + + ch = gdk_keyval_to_unicode (accelerator_key); + if (ch && (g_unichar_isgraph (ch) || ch == ' ') && + (ch < 0x80 || klass->latin1_to_char)) + { + switch (ch) + { + case ' ': + g_string_append (gstring, "Space"); + break; + case '\\': + g_string_append (gstring, "Backslash"); + break; + default: + g_string_append_unichar (gstring, g_unichar_toupper (ch)); + break; + } + } + else + { + gchar *tmp; + + tmp = gtk_accelerator_name (accelerator_key, 0); + if (tmp[0] != 0 && tmp[1] == 0) + tmp[0] = g_ascii_toupper (tmp[0]); + substitute_underscores (tmp); + g_string_append (gstring, tmp); + g_free (tmp); + } + + return g_string_free (gstring, FALSE); } gboolean gtk_accel_label_refetch (GtkAccelLabel *accel_label) { GtkAccelLabelClass *class; - gchar *utf8; g_return_val_if_fail (GTK_IS_ACCEL_LABEL (accel_label), FALSE); class = GTK_ACCEL_LABEL_GET_CLASS (accel_label); - g_free (accel_label->accel_string); - accel_label->accel_string = NULL; + if (accel_label->accel_string) + { + g_free (accel_label->accel_string); + accel_label->accel_string = NULL; + } if (accel_label->accel_closure) { @@ -490,64 +616,15 @@ gtk_accel_label_refetch (GtkAccelLabel *accel_label) if (key && key->accel_flags & GTK_ACCEL_VISIBLE) { - GString *gstring; - gboolean seen_mod = FALSE; - - gstring = g_string_new (accel_label->accel_string); - g_string_append (gstring, gstring->len ? class->accel_seperator : " "); - - if (key->accel_mods & GDK_SHIFT_MASK) - { - g_string_append (gstring, class->mod_name_shift); - seen_mod = TRUE; - } - if (key->accel_mods & GDK_CONTROL_MASK) - { - if (seen_mod) - g_string_append (gstring, class->mod_separator); - g_string_append (gstring, class->mod_name_control); - seen_mod = TRUE; - } - if (key->accel_mods & GDK_MOD1_MASK) - { - if (seen_mod) - g_string_append (gstring, class->mod_separator); - g_string_append (gstring, class->mod_name_alt); - seen_mod = TRUE; - } - if (seen_mod) - g_string_append (gstring, class->mod_separator); - if (key->accel_key < 0x80 || - (key->accel_key > 0x80 && - key->accel_key <= 0xff && - class->latin1_to_char)) - { - switch (key->accel_key) - { - case ' ': - g_string_append (gstring, "Space"); - break; - case '\\': - g_string_append (gstring, "Backslash"); - break; - default: - g_string_append_c (gstring, toupper (key->accel_key)); - break; - } - } - else - { - gchar *tmp; - - tmp = gtk_accelerator_name (key->accel_key, 0); - if (tmp[0] != 0 && tmp[1] == 0) - tmp[0] = toupper (tmp[0]); - g_string_append (gstring, tmp); - g_free (tmp); - } - g_free (accel_label->accel_string); - accel_label->accel_string = gstring->str; - g_string_free (gstring, FALSE); + 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); + accel_label->accel_string = g_strconcat (" ", tmp, NULL); + g_free (tmp); } if (!accel_label->accel_string) accel_label->accel_string = g_strdup ("-/-"); @@ -556,20 +633,10 @@ gtk_accel_label_refetch (GtkAccelLabel *accel_label) if (!accel_label->accel_string) accel_label->accel_string = g_strdup (""); - utf8 = g_locale_to_utf8 (accel_label->accel_string, -1, NULL, NULL, NULL); - if (utf8) - { - g_free (accel_label->accel_string); - accel_label->accel_string = utf8; - } - - if (accel_label->queue_id) - { - gtk_idle_remove (accel_label->queue_id); - accel_label->queue_id = 0; - } - gtk_widget_queue_resize (GTK_WIDGET (accel_label)); return FALSE; } + +#define __GTK_ACCEL_LABEL_C__ +#include "gtkaliasdef.c"