[gtk+] shortcuts: Extend the accelerator syntax more



commit 8768c0b8ac1fb6d997ec5708c0d85fa2e0a01148
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Dec 4 10:55:20 2015 -0500

    shortcuts: Extend the accelerator syntax more
    
    Cover cases like left+right control, and render them nicely.
    The gtk3-demo builder shortcuts example shows the new
    possibilities.

 demos/gtk-demo/shortcuts-builder.ui |   38 ++++++++++++
 gtk/gtkshortcutlabel.c              |  107 +++++++++++++++++++++++++++++++++-
 gtk/gtkshortcutsshortcut.c          |   10 ++-
 3 files changed, 148 insertions(+), 7 deletions(-)
---
diff --git a/demos/gtk-demo/shortcuts-builder.ui b/demos/gtk-demo/shortcuts-builder.ui
index 6b587f2..20ed760 100644
--- a/demos/gtk-demo/shortcuts-builder.ui
+++ b/demos/gtk-demo/shortcuts-builder.ui
@@ -502,6 +502,44 @@
 
           </object>
         </child>
+
+        <child>
+          <object class="GtkShortcutsGroup">
+            <property name="visible">1</property>
+            <property name="title" translatable="yes">'Special' combinations</property>
+
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">1</property>
+                <property name="accelerator">t+t</property>
+                <property name="title" translatable="yes">You want tea ?</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">1</property>
+                <property name="accelerator">&lt;shift&gt;&lt;ctrl&gt;</property>
+                <property name="title" translatable="yes">Shift Control</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">1</property>
+                <property name="accelerator">&lt;ctrl&gt;&amp;&lt;ctrl&gt;</property>
+                <property name="title" translatable="yes">Control Control</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">1</property>
+                <property name="accelerator">Control_L&amp;Control_R</property>
+                <property name="title" translatable="yes">Left and right control</property>
+              </object>
+            </child>
+
+          </object>
+        </child>
+
       </object>
     </child>
   </object>
diff --git a/gtk/gtkshortcutlabel.c b/gtk/gtkshortcutlabel.c
index 24c4f1b..ef7d462 100644
--- a/gtk/gtkshortcutlabel.c
+++ b/gtk/gtkshortcutlabel.c
@@ -46,14 +46,71 @@ enum {
 
 static GParamSpec *properties[LAST_PROP];
 
+static gchar *
+get_modifier_label (guint key)
+{
+  const gchar *subscript;
+  const gchar *label;
+
+  switch (key)
+    {
+    case GDK_KEY_Shift_L:
+    case GDK_KEY_Control_L:
+    case GDK_KEY_Alt_L:
+    case GDK_KEY_Meta_L:
+    case GDK_KEY_Super_L:
+    case GDK_KEY_Hyper_L:
+      subscript = "L";
+      break;
+    case GDK_KEY_Shift_R:
+    case GDK_KEY_Control_R:
+    case GDK_KEY_Alt_R:
+    case GDK_KEY_Meta_R:
+    case GDK_KEY_Super_R:
+    case GDK_KEY_Hyper_R:
+      subscript = "R";
+      break;
+    default:
+      g_assert_not_reached ();
+   }
+
+ switch (key)
+   {
+   case GDK_KEY_Shift_L:   case GDK_KEY_Shift_R:
+     label = C_("keyboard label", "Shift");
+     break;
+   case GDK_KEY_Control_L: case GDK_KEY_Control_R:
+     label = C_("keyboard label", "Ctrl");
+     break;
+   case GDK_KEY_Alt_L:     case GDK_KEY_Alt_R:
+     label = C_("keyboard label", "Alt");
+     break;
+   case GDK_KEY_Meta_L:    case GDK_KEY_Meta_R:
+     label = C_("keyboard label", "Meta");
+     break;
+   case GDK_KEY_Super_L:   case GDK_KEY_Super_R:
+     label = C_("keyboard label", "Super");
+     break;
+   case GDK_KEY_Hyper_L:   case GDK_KEY_Hyper_R:
+     label = C_("keyboard label", "Hyper");
+     break;
+    default:
+      g_assert_not_reached ();
+   }
+
+  return g_strdup_printf ("%s<sub>%s</sub>", label, subscript);
+}
+
 static gchar **
 get_labels (guint key, GdkModifierType modifier, guint *n_mods)
 {
   const gchar *labels[16];
+  GList *freeme = NULL;
   gchar key_label[6];
   gchar *tmp;
   gunichar ch;
   gint i = 0;
+  gchar **retval;
 
   if (modifier & GDK_SHIFT_MASK)
     labels[i++] = C_("keyboard label", "Shift");
@@ -97,6 +154,15 @@ get_labels (guint key, GdkModifierType modifier, guint *n_mods)
     {
       switch (key)
         {
+        case GDK_KEY_Shift_L:   case GDK_KEY_Shift_R:
+        case GDK_KEY_Control_L: case GDK_KEY_Control_R:
+        case GDK_KEY_Alt_L:     case GDK_KEY_Alt_R:
+        case GDK_KEY_Meta_L:    case GDK_KEY_Meta_R:
+        case GDK_KEY_Super_L:   case GDK_KEY_Super_R:
+        case GDK_KEY_Hyper_L:   case GDK_KEY_Hyper_R:
+          freeme = g_list_prepend (freeme, get_modifier_label (key));
+          labels[i++] = (const gchar*)freeme->data;
+           break;
         case GDK_KEY_Left:
           labels[i++] = "\xe2\x86\x90";
           break;
@@ -141,7 +207,11 @@ get_labels (guint key, GdkModifierType modifier, guint *n_mods)
 
   labels[i] = NULL;
 
-  return g_strdupv ((gchar **)labels);
+  retval = g_strdupv ((gchar **)labels);
+
+  g_list_free_full (freeme, g_free);
+
+  return retval;
 }
 
 static GtkWidget *
@@ -184,6 +254,8 @@ display_shortcut (GtkContainer    *self,
         gtk_widget_set_size_request (frame, 50, -1);
 
       disp = gtk_label_new (keys[i]);
+      gtk_label_set_use_markup (GTK_LABEL (disp), TRUE);
+
       gtk_widget_show (disp);
       gtk_container_add (GTK_CONTAINER (frame), disp);
     }
@@ -191,8 +263,8 @@ display_shortcut (GtkContainer    *self,
 }
 
 static gboolean
-parse_sequence (GtkShortcutLabel *self,
-                const gchar      *str)
+parse_combination (GtkShortcutLabel *self,
+                   const gchar      *str)
 {
   gchar **accels;
   gint k;
@@ -200,7 +272,7 @@ parse_sequence (GtkShortcutLabel *self,
   guint key = 0;
   gboolean retval = TRUE;
 
-  accels = g_strsplit (str, "+", 0);
+  accels = g_strsplit (str, "&", 0);
   for (k = 0; accels[k]; k++)
     {
       gtk_accelerator_parse (accels[k], &key, &modifier);
@@ -209,6 +281,9 @@ parse_sequence (GtkShortcutLabel *self,
           retval = FALSE;
           break;
         }
+      if (k > 0)
+        gtk_container_add (GTK_CONTAINER (self), dim_label ("+"));
+
       display_shortcut (GTK_CONTAINER (self), key, modifier);
     }
   g_strfreev (accels);
@@ -217,6 +292,29 @@ parse_sequence (GtkShortcutLabel *self,
 }
 
 static gboolean
+parse_sequence (GtkShortcutLabel *self,
+                const gchar      *str)
+{
+  gchar **accels;
+  gint k;
+  gboolean retval = TRUE;
+
+  accels = g_strsplit (str, "+", 0);
+  for (k = 0; accels[k]; k++)
+    {
+      if (!parse_combination (self, accels[k]))
+        {
+          retval = FALSE;
+          break;
+        }
+    }
+
+  g_strfreev (accels);
+
+  return retval;
+}
+
+static gboolean
 parse_range (GtkShortcutLabel *self,
              const gchar      *str)
 {
@@ -231,6 +329,7 @@ parse_range (GtkShortcutLabel *self,
     return FALSE;
 
   gtk_container_add (GTK_CONTAINER (self), dim_label ("⋯"));
+
   if (!parse_sequence (self, dots + 3))
     return FALSE;
 
diff --git a/gtk/gtkshortcutsshortcut.c b/gtk/gtkshortcutsshortcut.c
index 28aab42..af5515d 100644
--- a/gtk/gtkshortcutsshortcut.c
+++ b/gtk/gtkshortcutsshortcut.c
@@ -464,15 +464,19 @@ gtk_shortcuts_shortcut_class_init (GtkShortcutsShortcutClass *klass)
    * gtk_accelerator_parse(). Multiple accelerators can be specified by separating
    * them with a space, but keep in mind that the available width is limited.
    * It is also possible to specify ranges of shortcuts, using ... between the keys.
-   * Sequences of keys can be specified using a + between the keys.
+   * Sequences of keys can be specified using a + or & between the keys.
    *
    * Examples:
    * - A single shortcut: <ctl><alt>delete
    * - Two alternative shortcuts: <shift>a Home
    * - A range of shortcuts: <alt>1...<alt>9
-   * - A sequence of key combinations: <ctl>c+<ctl>x
+   * - Several keys pressed together: Control_L&Control_R
+   * - A sequence of shortcuts or keys: <ctl>c+<ctl>x
    *
-   * Note that < and > need to be escaped as &lt; and &gt; when used
+   * Use + instead of & when the keys may (or have to be) pressed sequentially (e.g
+   * use t+t for 'press the t key twice').
+   *
+   * Note that <, > and & need to be escaped as &lt;, &gt; and &amp; when used
    * in .ui files.
    */
   properties[PROP_ACCELERATOR] =


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]