From 4ca5ac0e8d47a65220ac966e6a7e8a517f506e64 Mon Sep 17 00:00:00 2001
From: Bruce Cowan <bruce@bcowan.me.uk>
Date: Sun, 2 Oct 2022 17:02:21 +0100
Subject: [PATCH] Add keyboard shortcuts

---
 data/gtk/help-overlay.blp | 32 ++++++++++++++++++++++++++++
 data/meson.build          |  1 +
 data/rugby.gresource.xml  |  3 ++-
 data/window.blp           |  6 +++---
 src/main.c                | 12 +++++++++++
 src/rugby-app-window.c    | 45 ++++++++++++++++++++++++++++++++++++++-
 src/rugby-pref-window.c   |  2 +-
 7 files changed, 95 insertions(+), 6 deletions(-)
 create mode 100644 data/gtk/help-overlay.blp

diff --git a/data/gtk/help-overlay.blp b/data/gtk/help-overlay.blp
new file mode 100644
index 0000000..633ef9a
--- /dev/null
+++ b/data/gtk/help-overlay.blp
@@ -0,0 +1,32 @@
+// SPDX-FileCopyrightText: 2022 Bruce Cowan <bruce@bcowan.me.uk>
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+using Gtk 4.0;
+
+ShortcutsWindow help_overlay {
+  ShortcutsSection {
+    ShortcutsGroup {
+      title: "Application";
+
+      ShortcutsShortcut {
+        title: "Preferences";
+        action-name: "app.prefs";
+      }
+    }
+
+    ShortcutsGroup {
+      title: "Score";
+
+      ShortcutsShortcut {
+        title: "Increment score";
+        action-name: "win.score-changed::up";
+      }
+
+      ShortcutsShortcut {
+        title: "Decrement score";
+        action-name: "win.score-changed::down";
+      }
+    }
+  }
+}
diff --git a/data/meson.build b/data/meson.build
index 2632f11..fd78f0c 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -4,6 +4,7 @@
 
 blueprints = custom_target('blueprints',
   input: files(
+    'gtk/help-overlay.blp',
     'prefs.blp',
     'window.blp'
   ),
diff --git a/data/rugby.gresource.xml b/data/rugby.gresource.xml
index 1c63d2e..eb97f5f 100644
--- a/data/rugby.gresource.xml
+++ b/data/rugby.gresource.xml
@@ -5,7 +5,8 @@
   SPDX-License-Identifier: GPL-3.0-or-later
 -->
 <gresources>
-  <gresource prefix="/uk/me/bcowan/rugby">
+  <gresource prefix="/uk/me/bcowan/Rugby">
+    <file preprocess="xml-stripblanks" compressed="true">gtk/help-overlay.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">prefs.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">score-item.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">window.ui</file>
diff --git a/data/window.blp b/data/window.blp
index bba80b1..6c68051 100644
--- a/data/window.blp
+++ b/data/window.blp
@@ -27,6 +27,7 @@ template RugbyAppWindow : Adw.ApplicationWindow {
       MenuButton menu_button {
         direction: none;
         menu-model: app_menu;
+        tooltip-text: "Main Menu";
       }
     }
 
@@ -45,7 +46,7 @@ template RugbyAppWindow : Adw.ApplicationWindow {
             };
           };
           factory: BuilderListItemFactory {
-            resource: "/uk/me/bcowan/rugby/score-item.ui";
+            resource: "/uk/me/bcowan/Rugby/score-item.ui";
           };
         }
       }
@@ -56,8 +57,7 @@ template RugbyAppWindow : Adw.ApplicationWindow {
 menu app_menu {
   section {
     item ("_Preferences", "app.prefs")
-  }
-  section {
+    item ("_Keyboard Shortcuts", "win.show-help-overlay")
     item ("_About Rugby", "app.about")
   }
 }
diff --git a/src/main.c b/src/main.c
index 5b992ab..081eb62 100644
--- a/src/main.c
+++ b/src/main.c
@@ -68,6 +68,18 @@ on_startup (GApplication          *app,
                                      app_entries,
                                      G_N_ELEMENTS (app_entries),
                                      app);
+    gtk_application_set_accels_for_action (GTK_APPLICATION (app),
+                                           "win.show-primary-menu",
+                                           (const char*[]) { "F10", NULL });
+    gtk_application_set_accels_for_action (GTK_APPLICATION (app),
+                                           "app.prefs",
+                                           (const char*[]) { "<Ctrl>comma", NULL });
+    gtk_application_set_accels_for_action (GTK_APPLICATION (app),
+                                           "win.score-changed::up",
+                                           (const char*[]) { "<Ctrl>Up", "<Ctrl>Right", NULL });
+    gtk_application_set_accels_for_action (GTK_APPLICATION (app),
+                                           "win.score-changed::down",
+                                           (const char*[]) { "<Ctrl>Down", "<Ctrl>Left", NULL });
 }
 
 int
diff --git a/src/rugby-app-window.c b/src/rugby-app-window.c
index 1db5220..d9ec1f2 100644
--- a/src/rugby-app-window.c
+++ b/src/rugby-app-window.c
@@ -15,6 +15,9 @@
 struct _RugbyAppWindow
 {
     AdwApplicationWindow parent;
+
+    GtkWidget *scorespin;
+    GtkWidget *menu_button;
 };
 
 G_DEFINE_TYPE (RugbyAppWindow, rugby_app_window, ADW_TYPE_APPLICATION_WINDOW)
@@ -70,10 +73,47 @@ item_tooltip_cb (GtkListItem *item)
     return g_string_free (tooltip, FALSE);
 }
 
+static void
+activate_score_changed (G_GNUC_UNUSED GSimpleAction *action,
+                                      GVariant      *parameter,
+                                      gpointer       user_data)
+{
+    RugbyAppWindow *self = RUGBY_APP_WINDOW (user_data);
+
+    double current_value = gtk_spin_button_get_value (GTK_SPIN_BUTTON (self->scorespin));
+    const char *direction = g_variant_get_string (parameter, NULL);
+
+    if (g_strcmp0 (direction, "up") == 0)
+        gtk_spin_button_set_value (GTK_SPIN_BUTTON (self->scorespin), current_value + 1.0);
+    else if (g_strcmp0 (direction, "down") == 0)
+        gtk_spin_button_set_value (GTK_SPIN_BUTTON (self->scorespin), current_value - 1.0);
+    else
+        g_assert_not_reached ();
+}
+
+static void
+activate_show_primary_menu (G_GNUC_UNUSED GSimpleAction *action,
+                            G_GNUC_UNUSED GVariant      *parameter,
+                                          gpointer       user_data)
+{
+    RugbyAppWindow *self = RUGBY_APP_WINDOW (user_data);
+    gtk_menu_button_popup (GTK_MENU_BUTTON (self->menu_button));
+}
+
+const GActionEntry win_entries[] = {
+    { .name = "score-changed", .activate = activate_score_changed, .parameter_type = "s" },
+    { .name = "show-primary-menu", .activate = activate_show_primary_menu },
+};
+
 static void
 rugby_app_window_init (RugbyAppWindow *self)
 {
     gtk_widget_init_template (GTK_WIDGET (self));
+
+    g_action_map_add_action_entries (G_ACTION_MAP (self),
+                                     win_entries,
+                                     G_N_ELEMENTS (win_entries),
+                                     self);
 }
 
 static void
@@ -85,7 +125,10 @@ rugby_app_window_class_init (RugbyAppWindowClass *klass)
     g_type_ensure (RUGBY_TYPE_LIST_STORE);
 
     gtk_widget_class_set_template_from_resource (widget_class,
-                                                 "/uk/me/bcowan/rugby/window.ui");
+                                                 "/uk/me/bcowan/Rugby/window.ui");
+
+    gtk_widget_class_bind_template_child (widget_class, RugbyAppWindow, scorespin);
+    gtk_widget_class_bind_template_child (widget_class, RugbyAppWindow, menu_button);
 
     gtk_widget_class_bind_template_callback (widget_class, item_tooltip_cb);
 }
diff --git a/src/rugby-pref-window.c b/src/rugby-pref-window.c
index 4234710..79b0b08 100644
--- a/src/rugby-pref-window.c
+++ b/src/rugby-pref-window.c
@@ -38,7 +38,7 @@ rugby_pref_window_class_init (RugbyPrefWindowClass *klass)
   object_class->dispose = rugby_pref_window_dispose;
 
   gtk_widget_class_set_template_from_resource (widget_class,
-                                               "/uk/me/bcowan/rugby/prefs.ui");
+                                               "/uk/me/bcowan/Rugby/prefs.ui");
 
   gtk_widget_class_bind_template_child (widget_class, RugbyPrefWindow, try_spin);
   gtk_widget_class_bind_template_child (widget_class, RugbyPrefWindow, utry_spin);
-- 
GitLab