[gnome-builder] wip: start implementing shortcuts idea with beautiful XMACROs



commit 5f5259854ce06ba71ef74ec37b3fccbe2615c883
Author: Christian Hergert <christian hergert me>
Date:   Wed Aug 26 00:13:18 2015 -0700

    wip: start implementing shortcuts idea with beautiful XMACROs

 data/theme/shared.css                     |   10 ++
 data/ui/gb-shortcuts-window.ui            |   67 +++++++++
 src/Makefile.am                           |    4 +
 src/app/gb-application-actions.c          |   20 +++
 src/app/gb-application.c                  |    1 +
 src/keybindings/gb-shortcuts-window.c     |  218 +++++++++++++++++++++++++++++
 src/keybindings/gb-shortcuts-window.defs  |   48 +++++++
 src/keybindings/gb-shortcuts-window.h     |   34 +++++
 src/resources/gnome-builder.gresource.xml |    1 +
 9 files changed, 403 insertions(+), 0 deletions(-)
---
diff --git a/data/theme/shared.css b/data/theme/shared.css
index 0f0c577..e00c859 100644
--- a/data/theme/shared.css
+++ b/data/theme/shared.css
@@ -125,3 +125,13 @@ GbWorkspacePane {
 GbWorkspacePane .pane-separator {
   background-color: @borders;
 }
+
+
+.round .button {
+  border-radius: 20px;
+  outline-radius: 20px;
+}
+.round GtkLabel {
+  padding-left: 0px;
+  padding-right: 0px;
+}
diff --git a/data/ui/gb-shortcuts-window.ui b/data/ui/gb-shortcuts-window.ui
new file mode 100644
index 0000000..465b78a
--- /dev/null
+++ b/data/ui/gb-shortcuts-window.ui
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.16 -->
+  <template class="GbShortcutsWindow" parent="GtkWindow">
+    <property name="resizable">false</property>
+    <child type="titlebar">
+      <object class="GtkHeaderBar">
+        <property name="show-close-button">true</property>
+        <property name="visible">true</property>
+        <child type="title">
+          <object class="GtkMenuButton" id="menu_button">
+            <property name="visible">true</property>
+            <style>
+              <class name="flat"/>
+            </style>
+          </object>
+        </child>
+        <child>
+          <object class="GtkToggleButton">
+            <property name="active" bind-source="search_bar" bind-property="search-mode-enabled" 
bind-flags="bidirectional">false</property>
+            <property name="visible">true</property>
+            <style>
+              <class name="image-button"/>
+            </style>
+            <child>
+              <object class="GtkImage">
+                <property name="icon-name">edit-find-symbolic</property>
+                <property name="visible">true</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+    <child>
+      <object class="GtkBox">
+        <property name="orientation">vertical</property>
+        <property name="visible">true</property>
+        <child>
+          <object class="EggSearchBar" id="search_bar">
+            <property name="visible">true</property>
+            <child internal-child="entry">
+              <object class="GtkSearchEntry">
+                <property name="placeholder-text" translatable="yes">Search keyboard shortcuts</property>
+                <property name="width-chars">50</property>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkStack" id="stack">
+            <property name="vexpand">true</property>
+            <property name="visible">true</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkStackSwitcher" id="switcher">
+            <property name="visible">true</property>
+            <style>
+              <class name="round"/>
+            </style>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/Makefile.am b/src/Makefile.am
index ce9dcd6..d74050f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -60,6 +60,8 @@ libgnome_builder_la_SOURCES = \
        html/gb-html-view.h \
        keybindings/gb-keybindings.c \
        keybindings/gb-keybindings.h \
+       keybindings/gb-shortcuts-window.c \
+       keybindings/gb-shortcuts-window.h \
        preferences/gb-preferences-page-editor.c \
        preferences/gb-preferences-page-editor.h \
        preferences/gb-preferences-page-insight.c \
@@ -164,6 +166,8 @@ libgnome_builder_la_SOURCES = \
        util/gb-settings.h \
        $(NULL)
 
+EXTRA_DIST += keybindings/gb-shortcuts-window.defs
+
 nodist_libgnome_builder_la_SOURCES = \
        resources/gb-resources.c \
        resources/gb-resources.h \
diff --git a/src/app/gb-application-actions.c b/src/app/gb-application-actions.c
index 43aa8c8..c959694 100644
--- a/src/app/gb-application-actions.c
+++ b/src/app/gb-application-actions.c
@@ -29,6 +29,7 @@
 #include "gb-application-private.h"
 #include "gb-greeter-window.h"
 #include "gb-new-project-dialog.h"
+#include "gb-shortcuts-window.h"
 #include "gb-support.h"
 #include "gb-workbench.h"
 
@@ -280,12 +281,31 @@ cleanup:
   g_list_free (windows);
 }
 
+static void
+gb_application_actions_shortcuts (GSimpleAction *action,
+                                  GVariant      *variant,
+                                  gpointer       user_data)
+{
+  GbApplication *self = user_data;
+  GbShortcutsWindow *window;
+
+  g_assert (GB_IS_APPLICATION (self));
+
+  window = g_object_new (GB_TYPE_SHORTCUTS_WINDOW,
+                         "default-width", 800,
+                         "default-height", 600,
+                         NULL);
+
+  gtk_window_present (GTK_WINDOW (window));
+}
+
 static const GActionEntry GbApplicationActions[] = {
   { "about",        gb_application_actions_about },
   { "open-project", gb_application_actions_open_project },
   { "new-project",  gb_application_actions_new_project },
   { "preferences",  gb_application_actions_preferences },
   { "quit",         gb_application_actions_quit },
+  { "shortcuts",    gb_application_actions_shortcuts },
   { "support",      gb_application_actions_support },
 };
 
diff --git a/src/app/gb-application.c b/src/app/gb-application.c
index cfac756..b5af586 100644
--- a/src/app/gb-application.c
+++ b/src/app/gb-application.c
@@ -142,6 +142,7 @@ gb_application_load_keybindings (GbApplication *self)
     { "workbench.show-gear-menu", "F10" },
     { "workbench.global-search", "<ctrl>period" },
     { "app.preferences", "<ctrl>comma" },
+    { "app.shortcuts", "<ctrl>question" },
     { NULL }
   };
   gsize i;
diff --git a/src/keybindings/gb-shortcuts-window.c b/src/keybindings/gb-shortcuts-window.c
new file mode 100644
index 0000000..4a2fafc
--- /dev/null
+++ b/src/keybindings/gb-shortcuts-window.c
@@ -0,0 +1,218 @@
+/* gb-shortcuts-window.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n.h>
+
+#include "gb-shortcuts-window.h"
+
+struct _GbShortcutsWindow
+{
+  GtkWindow      parent_instance;
+
+  GtkStack      *stack;
+  GtkMenuButton *menu_button;
+};
+
+G_DEFINE_TYPE (GbShortcutsWindow, gb_shortcuts_window, GTK_TYPE_WINDOW)
+
+GtkWidget *
+gb_shortcuts_window_new (void)
+{
+  return g_object_new (GB_TYPE_SHORTCUTS_WINDOW, NULL);
+}
+
+static void
+gb_shortcuts_window_set_view (GbShortcutsWindow *self,
+                              const gchar       *name)
+{
+  g_assert (GB_IS_SHORTCUTS_WINDOW (self));
+
+  gtk_stack_set_visible_child_name (self->stack, name);
+}
+
+static void
+adjust_page_buttons (GtkWidget *widget,
+                     gpointer   data)
+{
+  /*
+   * TODO: This is a hack to get the GtkStackSwitcher radio
+   *       buttons to look how we want. However, it's very
+   *       much font size specific.
+   */
+  gtk_widget_set_size_request (widget, 34, 34);
+}
+
+static void
+gb_shortcuts_window_build (GbShortcutsWindow *self)
+{
+  g_assert (GB_IS_SHORTCUTS_WINDOW (self));
+
+#define VIEWS(_views) { _views }
+#define VIEW(_ident, _name, _pages) \
+  { \
+    GtkBox *view; \
+    GtkStack *stack; \
+    GtkStackSwitcher *switcher; \
+    guint page_count = 0; \
+    view = g_object_new (GTK_TYPE_BOX, \
+                         "border-width", 24, \
+                         "spacing", 22, \
+                         "orientation", GTK_ORIENTATION_VERTICAL, \
+                         "visible", TRUE, \
+                         "vexpand", TRUE, \
+                         NULL); \
+    stack = g_object_new (GTK_TYPE_STACK, \
+                          "visible", TRUE, \
+                          "vexpand", TRUE, \
+                          "transition-type", GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT, \
+                          "homogeneous", TRUE, \
+                          NULL); \
+    gtk_container_add (GTK_CONTAINER (view), GTK_WIDGET (stack)); \
+    switcher = g_object_new (GTK_TYPE_STACK_SWITCHER, \
+                             "halign", GTK_ALIGN_CENTER, \
+                             "spacing", 12, \
+                             "stack", stack, \
+                             NULL); \
+    gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (switcher)), "round"); \
+    gtk_container_add (GTK_CONTAINER (view), GTK_WIDGET (switcher)); \
+    gtk_stack_add_titled (self->stack, GTK_WIDGET (view), _ident, _name); \
+    _pages \
+    if (page_count > 1) \
+      gtk_widget_show (GTK_WIDGET (switcher)); \
+    gtk_style_context_remove_class (gtk_widget_get_style_context (GTK_WIDGET (switcher)), "linked"); \
+    gtk_container_foreach (GTK_CONTAINER (switcher), adjust_page_buttons, NULL); \
+  }
+#define PAGE(_columns) \
+  { \
+    g_autofree gchar *title = g_strdup_printf ("%u", ++page_count); \
+    GtkBox *page; \
+    page = g_object_new (GTK_TYPE_BOX, \
+                         "homogeneous", TRUE, \
+                         "orientation", GTK_ORIENTATION_HORIZONTAL, \
+                         "visible", TRUE, \
+                         NULL); \
+    _columns \
+    gtk_stack_add_titled (stack, GTK_WIDGET (page), title, title); \
+  }
+#define COLUMN(_groups) \
+  { \
+    GtkBox *column; \
+    GtkSizeGroup *size_group; \
+    column = g_object_new (GTK_TYPE_BOX, \
+                           "orientation", GTK_ORIENTATION_VERTICAL, \
+                           "spacing", 22, \
+                           "visible", TRUE, \
+                           NULL); \
+    gtk_container_add (GTK_CONTAINER (page), GTK_WIDGET (column)); \
+    size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); \
+    _groups \
+    g_clear_object (&size_group); \
+  }
+#define GROUP(_group_name, _shortcuts) \
+  { \
+    g_autofree gchar *title_markup = g_strdup_printf ("<b>%s</b>", _group_name); \
+    GtkBox *group; \
+    GtkBox *title_label; \
+    group = g_object_new (GTK_TYPE_BOX, \
+                          "orientation", GTK_ORIENTATION_VERTICAL, \
+                          "spacing", 11, \
+                          "visible", TRUE, \
+                          NULL); \
+    gtk_container_add (GTK_CONTAINER (column), GTK_WIDGET (group)); \
+    title_label = g_object_new (GTK_TYPE_LABEL, \
+                                "visible", TRUE, \
+                                "label", title_markup, \
+                                "use-markup", TRUE, \
+                                "xalign", 0.0f, \
+                                NULL); \
+    gtk_container_add (GTK_CONTAINER (group), GTK_WIDGET (title_label)); \
+    _shortcuts \
+  }
+#define SHORTCUT(_accel, _desc) \
+  { \
+    GtkBox *shortcut; \
+    GtkLabel *accel; \
+    GtkLabel *desc; \
+    shortcut = g_object_new (GTK_TYPE_BOX, \
+                             "orientation", GTK_ORIENTATION_HORIZONTAL, \
+                             "spacing", 11, \
+                             "visible", TRUE, \
+                             NULL); \
+    gtk_container_add (GTK_CONTAINER (group), GTK_WIDGET (shortcut)); \
+    accel = g_object_new (GTK_TYPE_LABEL, \
+                          "label", _accel, \
+                          "visible", TRUE, \
+                          "xalign", 0.0f, \
+                          NULL); \
+    gtk_size_group_add_widget (size_group, GTK_WIDGET (accel)); \
+    gtk_container_add (GTK_CONTAINER (shortcut), GTK_WIDGET (accel)); \
+    desc = g_object_new (GTK_TYPE_LABEL, \
+                         "label", _desc, \
+                         "visible", TRUE, \
+                         "xalign", 0.0f, \
+                         "hexpand", TRUE, \
+                         NULL); \
+    gtk_container_add (GTK_CONTAINER (shortcut), GTK_WIDGET (desc)); \
+  }
+#define GESTURE(_accel, _title, _subtitle)
+
+
+#include "gb-shortcuts-window.defs"
+
+
+#undef VIEWS
+#undef VIEW
+#undef PAGE
+#undef COLUMN
+#undef GROUP
+#undef SHORTCUT
+#undef GESTURE
+}
+
+static void
+gb_shortcuts_window_constructed (GObject *object)
+{
+  GbShortcutsWindow *self = (GbShortcutsWindow *)object;
+
+  g_assert (GB_IS_SHORTCUTS_WINDOW (self));
+
+  G_OBJECT_CLASS (gb_shortcuts_window_parent_class)->constructed (object);
+
+  gb_shortcuts_window_set_view (self, "editor");
+}
+
+static void
+gb_shortcuts_window_class_init (GbShortcutsWindowClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructed = gb_shortcuts_window_constructed;
+
+  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/builder/ui/gb-shortcuts-window.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, GbShortcutsWindow, stack);
+  gtk_widget_class_bind_template_child (widget_class, GbShortcutsWindow, menu_button);
+}
+
+static void
+gb_shortcuts_window_init (GbShortcutsWindow *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+  gb_shortcuts_window_build (self);
+}
diff --git a/src/keybindings/gb-shortcuts-window.defs b/src/keybindings/gb-shortcuts-window.defs
new file mode 100644
index 0000000..cd80a07
--- /dev/null
+++ b/src/keybindings/gb-shortcuts-window.defs
@@ -0,0 +1,48 @@
+#define GENERAL_GROUP \
+        GROUP ( \
+          _("General"), \
+          SHORTCUT ("F1", _("Editor")) \
+          SHORTCUT ("F2", _("Designer")) \
+          SHORTCUT ("F3", _("Debugger")) \
+          SHORTCUT ("F4", _("Version Control")) \
+        )
+
+VIEWS (
+  VIEW (
+    "editor",
+    _("Editor Shortcuts"),
+    PAGE (
+      COLUMN (
+        GENERAL_GROUP
+        GROUP (
+          _("Touchpad gestures"),
+          GESTURE ("swipe-right", _("Switch to the next document"), _("Two-finger swipe right"))
+          GESTURE ("swipe-left", _("Switch to the previous document"), _("Two-finger swipe left"))
+        )
+      )
+      COLUMN (
+        GROUP (
+          _("Files"),
+          SHORTCUT ("<ctrl>n", _("Create new document"))
+          SHORTCUT ("<ctrl>o", _("Open a document"))
+          SHORTCUT ("<ctrl>s", _("Save the document"))
+          SHORTCUT ("<ctrl>w", _("Close the document"))
+          SHORTCUT ("<ctrl><alt>Page_Down", _("Switch to the next document"))
+          SHORTCUT ("<ctrl><alt>Page_Up", _("Switch to the previous document"))
+        )
+        GROUP (
+          _("Find and replace"),
+          SHORTCUT ("<ctrl>f", _("Find"))
+          SHORTCUT ("<ctrl>g", _("Find the next match"))
+          SHORTCUT ("<ctrl><shift>g", _("Find the previous match"))
+          SHORTCUT ("<ctrl>h", _("Find and replace"))
+          SHORTCUT ("<ctrl><shift>k", _("Clear highlight"))
+          SHORTCUT ("<ctrl>l", _("Go to line"))
+        )
+      )
+    )
+    PAGE ()
+  )
+)
+
+#undef GENERAL_GROUP
diff --git a/src/keybindings/gb-shortcuts-window.h b/src/keybindings/gb-shortcuts-window.h
new file mode 100644
index 0000000..ec9e6a0
--- /dev/null
+++ b/src/keybindings/gb-shortcuts-window.h
@@ -0,0 +1,34 @@
+/* gb-shortcuts-window.h
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GB_SHORTCUTS_WINDOW_H
+#define GB_SHORTCUTS_WINDOW_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GB_TYPE_SHORTCUTS_WINDOW (gb_shortcuts_window_get_type())
+
+G_DECLARE_FINAL_TYPE (GbShortcutsWindow, gb_shortcuts_window, GB, SHORTCUTS_WINDOW, GtkWindow)
+
+GtkWidget *gb_shortcuts_window_new (void);
+
+G_END_DECLS
+
+#endif /* GB_SHORTCUTS_WINDOW_H */
diff --git a/src/resources/gnome-builder.gresource.xml b/src/resources/gnome-builder.gresource.xml
index c2805df..d84ef05 100644
--- a/src/resources/gnome-builder.gresource.xml
+++ b/src/resources/gnome-builder.gresource.xml
@@ -41,6 +41,7 @@
     <file alias="ui/gb-search-box.ui">../../data/ui/gb-search-box.ui</file>
     <file alias="ui/gb-search-display-group.ui">../../data/ui/gb-search-display-group.ui</file>
     <file alias="ui/gb-search-display-row.ui">../../data/ui/gb-search-display-row.ui</file>
+    <file alias="ui/gb-shortcuts-window.ui">../../data/ui/gb-shortcuts-window.ui</file>
     <file alias="ui/gb-view-stack.ui">../../data/ui/gb-view-stack.ui</file>
     <file alias="ui/gb-workbench.ui">../../data/ui/gb-workbench.ui</file>
     <file alias="ui/gb-workspace.ui">../../data/ui/gb-workspace.ui</file>


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