1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
3
/* Metacity hacked-up GtkAccelLabel */
4
/* Copyright (C) 2002 Red Hat, Inc. */
5
/* GTK - The GIMP Toolkit
6
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
8
* MetaAccelLabel: GtkLabel with accelerator monitoring facilities.
9
* Copyright (C) 1998 Tim Janik
11
* This library is free software; you can redistribute it and/or
12
* modify it under the terms of the GNU Lesser General Public
13
* License as published by the Free Software Foundation; either
14
* version 2 of the License, or (at your option) any later version.
16
* This library is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
* Lesser General Public License for more details.
21
* You should have received a copy of the GNU Lesser General Public
22
* License along with this library; if not, write to the
23
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24
* Boston, MA 02111-1307, USA.
28
* Modified by the GTK+ Team and others 1997-2001. See the AUTHORS
29
* file for a list of people on the GTK+ Team. See the ChangeLog
30
* files for a list of changes. These files are distributed with
31
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
35
#include "metaaccellabel.h"
40
static void meta_accel_label_class_init (MetaAccelLabelClass *klass);
41
static void meta_accel_label_init (MetaAccelLabel *accel_label);
42
static void meta_accel_label_destroy (GtkObject *object);
43
static void meta_accel_label_finalize (GObject *object);
44
static void meta_accel_label_size_request (GtkWidget *widget,
45
GtkRequisition *requisition);
46
static gboolean meta_accel_label_expose_event (GtkWidget *widget,
47
GdkEventExpose *event);
49
static void meta_accel_label_update (MetaAccelLabel *accel_label);
50
static int meta_accel_label_get_accel_width (MetaAccelLabel *accel_label);
53
static GtkLabelClass *parent_class = NULL;
57
meta_accel_label_get_type (void)
59
static GtkType accel_label_type = 0;
61
if (!accel_label_type)
63
static const GtkTypeInfo accel_label_info =
66
sizeof (MetaAccelLabel),
67
sizeof (MetaAccelLabelClass),
68
(GtkClassInitFunc) meta_accel_label_class_init,
69
(GtkObjectInitFunc) meta_accel_label_init,
70
/* reserved_1 */ NULL,
71
/* reserved_2 */ NULL,
72
(GtkClassInitFunc) NULL,
75
accel_label_type = gtk_type_unique (GTK_TYPE_LABEL, &accel_label_info);
78
return accel_label_type;
82
meta_accel_label_class_init (MetaAccelLabelClass *class)
84
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
85
GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
86
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
88
parent_class = g_type_class_peek_parent (class);
90
gobject_class->finalize = meta_accel_label_finalize;
92
object_class->destroy = meta_accel_label_destroy;
94
widget_class->size_request = meta_accel_label_size_request;
95
widget_class->expose_event = meta_accel_label_expose_event;
97
class->signal_quote1 = g_strdup ("<:");
98
class->signal_quote2 = g_strdup (":>");
99
/* This is the text that should appear next to menu accelerators
100
* that use the shift key. If the text on this key isn't typically
101
* translated on keyboards used for your language, don't translate
104
class->mod_name_shift = g_strdup (_("Shift"));
105
/* This is the text that should appear next to menu accelerators
106
* that use the control key. If the text on this key isn't typically
107
* translated on keyboards used for your language, don't translate
110
class->mod_name_control = g_strdup (_("Ctrl"));
111
/* This is the text that should appear next to menu accelerators
112
* that use the alt key. If the text on this key isn't typically
113
* translated on keyboards used for your language, don't translate
116
class->mod_name_alt = g_strdup (_("Alt"));
117
/* This is the text that should appear next to menu accelerators
118
* that use the meta key. If the text on this key isn't typically
119
* translated on keyboards used for your language, don't translate
122
class->mod_name_meta = g_strdup (_("Meta"));
123
/* This is the text that should appear next to menu accelerators
124
* that use the super key. If the text on this key isn't typically
125
* translated on keyboards used for your language, don't translate
128
class->mod_name_super = g_strdup (_("Super"));
129
/* This is the text that should appear next to menu accelerators
130
* that use the hyper key. If the text on this key isn't typically
131
* translated on keyboards used for your language, don't translate
134
class->mod_name_hyper = g_strdup (_("Hyper"));
135
/* This is the text that should appear next to menu accelerators
136
* that use the mod2 key. If the text on this key isn't typically
137
* translated on keyboards used for your language, don't translate
140
class->mod_name_mod2 = g_strdup (_("Mod2"));
141
/* This is the text that should appear next to menu accelerators
142
* that use the mod3 key. If the text on this key isn't typically
143
* translated on keyboards used for your language, don't translate
146
class->mod_name_mod3 = g_strdup (_("Mod3"));
147
/* This is the text that should appear next to menu accelerators
148
* that use the mod4 key. If the text on this key isn't typically
149
* translated on keyboards used for your language, don't translate
152
class->mod_name_mod4 = g_strdup (_("Mod4"));
153
/* This is the text that should appear next to menu accelerators
154
* that use the mod5 key. If the text on this key isn't typically
155
* translated on keyboards used for your language, don't translate
158
class->mod_name_mod5 = g_strdup (_("Mod5"));
160
class->mod_separator = g_strdup ("+");
161
class->accel_seperator = g_strdup (" / ");
162
class->latin1_to_char = TRUE;
166
meta_accel_label_init (MetaAccelLabel *accel_label)
168
accel_label->accel_padding = 3;
169
accel_label->accel_string = NULL;
171
meta_accel_label_update (accel_label);
175
meta_accel_label_new_with_mnemonic (const gchar *string)
177
MetaAccelLabel *accel_label;
179
g_return_val_if_fail (string != NULL, NULL);
181
accel_label = g_object_new (META_TYPE_ACCEL_LABEL, NULL);
183
gtk_label_set_text_with_mnemonic (GTK_LABEL (accel_label), string);
185
return GTK_WIDGET (accel_label);
189
meta_accel_label_destroy (GtkObject *object)
191
MetaAccelLabel *accel_label = META_ACCEL_LABEL (object);
194
g_free (accel_label->accel_string);
195
accel_label->accel_string = NULL;
197
accel_label->accel_mods = 0;
198
accel_label->accel_key = 0;
200
GTK_OBJECT_CLASS (parent_class)->destroy (object);
204
meta_accel_label_finalize (GObject *object)
206
MetaAccelLabel *accel_label = META_ACCEL_LABEL (object);
208
g_free (accel_label->accel_string);
210
G_OBJECT_CLASS (parent_class)->finalize (object);
214
meta_accel_label_set_accelerator (MetaAccelLabel *accel_label,
215
guint accelerator_key,
216
MetaVirtualModifier accelerator_mods)
218
g_return_if_fail (META_IS_ACCEL_LABEL (accel_label));
220
if (accelerator_key != accel_label->accel_key ||
221
accelerator_mods != accel_label->accel_mods)
223
accel_label->accel_mods = accelerator_mods;
224
accel_label->accel_key = accelerator_key;
226
meta_accel_label_update (accel_label);
231
meta_accel_label_get_accel_width (MetaAccelLabel *accel_label)
233
g_return_val_if_fail (META_IS_ACCEL_LABEL (accel_label), 0);
235
return (accel_label->accel_string_width +
236
(accel_label->accel_string_width ? accel_label->accel_padding : 0));
240
meta_accel_label_size_request (GtkWidget *widget,
241
GtkRequisition *requisition)
243
MetaAccelLabel *accel_label = META_ACCEL_LABEL (widget);
247
if (GTK_WIDGET_CLASS (parent_class)->size_request)
248
GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
250
layout = gtk_widget_create_pango_layout (widget, accel_label->accel_string);
251
pango_layout_get_pixel_size (layout, &width, NULL);
252
accel_label->accel_string_width = width;
254
g_object_unref (G_OBJECT (layout));
258
meta_accel_label_expose_event (GtkWidget *widget,
259
GdkEventExpose *event)
261
MetaAccelLabel *accel_label = META_ACCEL_LABEL (widget);
262
GtkMisc *misc = GTK_MISC (accel_label);
265
if (GTK_WIDGET_DRAWABLE (accel_label))
269
ac_width = meta_accel_label_get_accel_width (accel_label);
271
if (widget->allocation.width >= widget->requisition.width + ac_width)
273
GtkTextDirection direction = gtk_widget_get_direction (widget);
277
if (direction == GTK_TEXT_DIR_RTL)
279
widget->allocation.x += ac_width;
281
widget->allocation.width -= ac_width;
283
if (GTK_WIDGET_CLASS (parent_class)->expose_event)
284
GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
286
if (direction == GTK_TEXT_DIR_RTL)
288
widget->allocation.x -= ac_width;
290
widget->allocation.width += ac_width;
292
if (direction == GTK_TEXT_DIR_RTL)
294
x = widget->allocation.x + misc->xpad;
298
x = widget->allocation.x + widget->allocation.width - misc->xpad - ac_width;
301
y = (widget->allocation.y * (1.0 - misc->yalign) +
302
(widget->allocation.y + widget->allocation.height -
303
(widget->requisition.height - misc->ypad * 2)) *
306
layout = gtk_widget_create_pango_layout (widget, accel_label->accel_string);
308
gtk_paint_layout (widget->style,
310
GTK_WIDGET_STATE (widget),
318
g_object_unref (G_OBJECT (layout));
322
if (GTK_WIDGET_CLASS (parent_class)->expose_event)
323
GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
331
meta_accel_label_update (MetaAccelLabel *accel_label)
333
MetaAccelLabelClass *class;
335
gboolean seen_mod = FALSE;
338
g_return_if_fail (META_IS_ACCEL_LABEL (accel_label));
340
class = META_ACCEL_LABEL_GET_CLASS (accel_label);
342
g_free (accel_label->accel_string);
343
accel_label->accel_string = NULL;
345
gstring = g_string_new (accel_label->accel_string);
346
g_string_append (gstring, gstring->len ? class->accel_seperator : " ");
348
if (accel_label->accel_mods & META_VIRTUAL_SHIFT_MASK)
350
g_string_append (gstring, class->mod_name_shift);
353
if (accel_label->accel_mods & META_VIRTUAL_CONTROL_MASK)
356
g_string_append (gstring, class->mod_separator);
357
g_string_append (gstring, class->mod_name_control);
360
if (accel_label->accel_mods & META_VIRTUAL_ALT_MASK)
363
g_string_append (gstring, class->mod_separator);
364
g_string_append (gstring, class->mod_name_alt);
367
if (accel_label->accel_mods & META_VIRTUAL_META_MASK)
370
g_string_append (gstring, class->mod_separator);
371
g_string_append (gstring, class->mod_name_meta);
374
if (accel_label->accel_mods & META_VIRTUAL_SUPER_MASK)
377
g_string_append (gstring, class->mod_separator);
378
g_string_append (gstring, class->mod_name_super);
381
if (accel_label->accel_mods & META_VIRTUAL_HYPER_MASK)
384
g_string_append (gstring, class->mod_separator);
385
g_string_append (gstring, class->mod_name_hyper);
388
if (accel_label->accel_mods & META_VIRTUAL_MOD2_MASK)
391
g_string_append (gstring, class->mod_separator);
392
g_string_append (gstring, class->mod_name_mod2);
395
if (accel_label->accel_mods & META_VIRTUAL_MOD3_MASK)
398
g_string_append (gstring, class->mod_separator);
399
g_string_append (gstring, class->mod_name_mod3);
402
if (accel_label->accel_mods & META_VIRTUAL_MOD4_MASK)
405
g_string_append (gstring, class->mod_separator);
406
g_string_append (gstring, class->mod_name_mod4);
409
if (accel_label->accel_mods & META_VIRTUAL_MOD5_MASK)
412
g_string_append (gstring, class->mod_separator);
413
g_string_append (gstring, class->mod_name_mod5);
418
g_string_append (gstring, class->mod_separator);
420
ch = gdk_keyval_to_unicode (accel_label->accel_key);
421
if (ch && (g_unichar_isgraph (ch) || ch == ' ') &&
422
(ch < 0x80 || class->latin1_to_char))
427
g_string_append (gstring, "Space");
430
g_string_append (gstring, "Backslash");
433
g_string_append_unichar (gstring, g_unichar_toupper (ch));
441
tmp = gtk_accelerator_name (accel_label->accel_key, 0);
442
if (tmp[0] != 0 && tmp[1] == 0)
443
tmp[0] = g_ascii_toupper (tmp[0]);
444
g_string_append (gstring, tmp);
448
g_free (accel_label->accel_string);
449
accel_label->accel_string = gstring->str;
450
g_string_free (gstring, FALSE);
452
g_assert (accel_label->accel_string);
453
/* accel_label->accel_string = g_strdup ("-/-"); */
455
gtk_widget_queue_resize (GTK_WIDGET (accel_label));