shortcuts: Support ranges in the display of shortcuts

Repeating Alt-1 to Alt-9 as individual shortcuts looks really boring,
so allow compressing such ranges by specifying <Alt>1...9.
This commit is contained in:
Matthias Clasen 2015-10-22 14:31:06 -04:00
parent 6cf7c03334
commit 67a54bf4ef
2 changed files with 67 additions and 23 deletions

View File

@ -156,15 +156,48 @@ dim_label (const gchar *text)
return label;
}
static void
display_shortcut (GtkContainer *self,
guint key,
GdkModifierType modifier)
{
gchar **keys = NULL;
gint i;
guint n_mods;
keys = get_labels (key, modifier, &n_mods);
for (i = 0; keys[i]; i++)
{
GtkWidget *frame;
GtkWidget *disp;
if (i > 0)
gtk_container_add (self, dim_label ("+"));
frame = gtk_frame_new (NULL);
gtk_widget_show (frame);
gtk_container_add (self, frame);
if (i < n_mods)
gtk_widget_set_size_request (frame, 50, -1);
disp = gtk_label_new (keys[i]);
gtk_widget_show (disp);
gtk_container_add (GTK_CONTAINER (frame), disp);
}
g_strfreev (keys);
}
static void
gtk_shortcut_label_rebuild (GtkShortcutLabel *self)
{
gchar **accels = NULL;
gchar **keys = NULL;
GdkModifierType modifier = 0;
GdkModifierType modifier2 = 0;
guint key = 0;
guint i, k;
guint n_mods;
guint key2 = 0;
guint k;
gtk_container_foreach (GTK_CONTAINER (self), (GtkCallback)gtk_widget_destroy, NULL);
@ -174,37 +207,43 @@ gtk_shortcut_label_rebuild (GtkShortcutLabel *self)
accels = g_strsplit (self->accelerator, " ", 0);
for (k = 0; accels[k]; k++)
{
gchar *dots;
dots = strstr (accels[k], "...");
if (dots)
{
dots[0] = '\0';
gtk_accelerator_parse (dots + 3, &key2, &modifier2);
if ((key2 == 0) && (modifier2 == 0))
{
g_warning ("Failed to parse %s, part of accelerator '%s'", dots + 3, self->accelerator);
goto out;
}
}
else
key2 = 0;
gtk_accelerator_parse (accels[k], &key, &modifier);
if ((key == 0) && (modifier == 0))
{
g_warning ("Failed to parse accelerator '%s'", self->accelerator);
g_warning ("Failed to parse %s, part of accelerator '%s'", accels[k], self->accelerator);
goto out;
}
if (k > 0)
gtk_container_add (GTK_CONTAINER (self), dim_label ("/"));
keys = get_labels (key, modifier, &n_mods);
for (i = 0; keys[i]; i++)
{
GtkWidget *frame;
GtkWidget *disp;
display_shortcut (GTK_CONTAINER (self), key, modifier);
if (i > 0)
gtk_container_add (GTK_CONTAINER (self), dim_label ("+"));
if (key2 == 0)
continue;
frame = gtk_frame_new (NULL);
gtk_widget_show (frame);
gtk_container_add (GTK_CONTAINER (self), frame);
if (modifier2 == modifier)
modifier2 = 0;
if (i < n_mods)
gtk_widget_set_size_request (frame, 50, -1);
gtk_container_add (GTK_CONTAINER (self), dim_label (""));
disp = gtk_label_new (keys[i]);
gtk_widget_show (disp);
gtk_container_add (GTK_CONTAINER (frame), disp);
}
g_strfreev (keys);
display_shortcut (GTK_CONTAINER (self), key2, modifier2);
}
out:

View File

@ -185,9 +185,14 @@ gtk_shortcuts_shortcut_class_init (GtkShortcutsShortcutClass *klass)
* The accelerator(s) represented by this object, in the syntax
* understood by gtk_accelerator_parse(). Multiple accelerators
* can be specified by separating them with a space, but keep in
* mind that the available width is limited.
* mind that the available width is limited. It is also possible
* to specify ranges of shortcuts, using ... between the keys.
*
* Here is an example: <ctrl>? F1
* Examples:
*
* - A single shortcut: <ctrl><alt>delete
* - Two alternative shortcuts: <shift>a Home
* - A range: <alt>1...9
*
* Note that < and > need to escaped as &lt; and &gt; when used
* in .ui files.