[gtk+] Add automatic help overlay support to GtkApplication



commit f6d9f9f93de1c3c5a7ab5d9c64783e941189d9b5
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Oct 21 00:11:59 2015 -0400

    Add automatic help overlay support to GtkApplication
    
    When the $(resource_prefix)/gtk/help-overlay.ui resource exists,
    load a GtkShortcutsWindow from it for each GtkApplicationWindow,
    and set up a win.show-help-overlay action with accels <Primary>F1
    and <Primary>? to show it.

 docs/reference/gtk/gtk3-sections.txt |    2 +
 gtk/gtkapplication.c                 |   56 +++++++++++++++++++++----
 gtk/gtkapplicationwindow.c           |   78 +++++++++++++++++++++++++++++++++-
 gtk/gtkapplicationwindow.h           |    8 ++++
 4 files changed, 134 insertions(+), 10 deletions(-)
---
diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt
index f4482e1..d6274d7 100644
--- a/docs/reference/gtk/gtk3-sections.txt
+++ b/docs/reference/gtk/gtk3-sections.txt
@@ -7545,6 +7545,8 @@ gtk_application_window_new
 gtk_application_window_set_show_menubar
 gtk_application_window_get_show_menubar
 gtk_application_window_get_id
+gtk_application_window_set_help_overlay
+gtk_application_window_get_help_overlay
 
 <SUBSECTION Standard>
 GTK_TYPE_APPLICATION_WINDOW
diff --git a/gtk/gtkapplication.c b/gtk/gtkapplication.c
index 0edfe92..0a6e668 100644
--- a/gtk/gtkapplication.c
+++ b/gtk/gtkapplication.c
@@ -38,6 +38,7 @@
 #include "gtkaccelmapprivate.h"
 #include "gtkicontheme.h"
 #include "gtkbuilder.h"
+#include "gtkshortcutswindow.h"
 #include "gtkintl.h"
 
 /* NB: please do not add backend-specific GDK headers here.  This should
@@ -74,7 +75,7 @@
  * ## Automatic resources ## {#automatic-resources}
  *
  * #GtkApplication will automatically load menus from the #GtkBuilder
- * file located at "gtk/menus.ui", relative to the application's
+ * resource located at "gtk/menus.ui", relative to the application's
  * resource base path (see g_application_set_resource_base_path()).  The
  * menu with the ID "app-menu" is taken as the application's app menu
  * and the menu with the ID "menubar" is taken as the application's
@@ -82,7 +83,7 @@
  * and accessed via gtk_application_get_menu_by_id() which allows for
  * dynamic population of a part of the menu structure.
  *
- * If the files "gtk/menus-appmenu.ui" or "gtk/menus-traditional.ui" are
+ * If the resources "gtk/menus-appmenu.ui" or "gtk/menus-traditional.ui" are
  * present then these files will be used in preference, depending on the
  * value of gtk_application_prefers_app_menu().
  *
@@ -95,6 +96,12 @@
  * resources.  See gtk_icon_theme_add_resource_path() for more
  * information.
  *
+ * If there is a resource located at "gtk/help-overlay.ui" which is
+ * defining a #GtkShortcutsWindow with ID "help_overlay" then GtkApplication
+ * associates an instance of this shortcuts window with each
+ * #GtkApplicationWindow and sets up keyboard accelerators (Control-F1
+ * and Control-?) to open it.
+ *
  * ## A simple application ## {#gtkapplication}
  *
  * [A simple example](https://git.gnome.org/browse/gtk+/tree/examples/bp/bloatpad.c)
@@ -485,9 +492,10 @@ struct _GtkApplicationPrivate
   Accels           accels;
   guint            last_window_id;
 
-  gboolean register_session;
+  gboolean         register_session;
   GtkActionMuxer  *muxer;
   GtkBuilder      *menus_builder;
+  gchar           *help_overlay_path;
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (GtkApplication, gtk_application, G_TYPE_APPLICATION)
@@ -588,6 +596,22 @@ gtk_application_load_resources (GtkApplication *application)
           gtk_application_set_menubar (application, G_MENU_MODEL (menu));
       }
   }
+
+  /* Help overlay */
+  {
+    gchar *path;
+
+    path = g_strconcat (base_path, "/gtk/help-overlay.ui", NULL);
+    if (g_resources_get_info (path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL, NULL, NULL))
+    {
+      const gchar * const accels[] = { "<Primary>F1", "<Primary>question", NULL };
+
+      application->priv->help_overlay_path = path;
+      gtk_application_set_accels_for_action (application, "win.show-help-overlay", accels);
+    }
+  else
+    g_free (path);
+  }
 }
 
 
@@ -698,7 +722,21 @@ gtk_application_window_added (GtkApplication *application,
   GtkApplicationPrivate *priv = application->priv;
 
   if (GTK_IS_APPLICATION_WINDOW (window))
-    gtk_application_window_set_id (GTK_APPLICATION_WINDOW (window), ++application->priv->last_window_id);
+    {
+      gtk_application_window_set_id (GTK_APPLICATION_WINDOW (window), ++priv->last_window_id);
+      if (priv->help_overlay_path)
+        {
+          GtkBuilder *builder;
+          GtkWidget *help_overlay;
+
+          builder = gtk_builder_new_from_resource (priv->help_overlay_path);
+          help_overlay = GTK_WIDGET (gtk_builder_get_object (builder, "help_overlay"));
+          if (GTK_IS_SHORTCUTS_WINDOW (help_overlay))
+            gtk_application_window_set_help_overlay (GTK_APPLICATION_WINDOW (window),
+                                                     GTK_SHORTCUTS_WINDOW (help_overlay));
+          g_object_unref (builder);
+        }
+    }
 
   priv->windows = g_list_prepend (priv->windows, window);
   gtk_window_set_application (window, application);
@@ -708,9 +746,10 @@ gtk_application_window_added (GtkApplication *application,
                     G_CALLBACK (gtk_application_focus_in_event_cb),
                     application);
 
-  gtk_application_impl_window_added (application->priv->impl, window);
+  gtk_application_impl_window_added (priv->impl, window);
+
+  gtk_application_impl_active_window_changed (priv->impl, window);
 
-  gtk_application_impl_active_window_changed (application->priv->impl, window);
   g_object_notify_by_pspec (G_OBJECT (application), gtk_application_props[PROP_ACTIVE_WINDOW]);
 }
 
@@ -870,8 +909,9 @@ gtk_application_finalize (GObject *object)
 
   accels_finalize (&application->priv->accels);
 
-  G_OBJECT_CLASS (gtk_application_parent_class)
-    ->finalize (object);
+  g_free (application->priv->help_overlay_path);
+
+  G_OBJECT_CLASS (gtk_application_parent_class)->finalize (object);
 }
 
 static void
diff --git a/gtk/gtkapplicationwindow.c b/gtk/gtkapplicationwindow.c
index 8602a98..919d92c 100644
--- a/gtk/gtkapplicationwindow.c
+++ b/gtk/gtkapplicationwindow.c
@@ -228,6 +228,8 @@ struct _GtkApplicationWindowPrivate
   GMenu *menubar_section;
 
   guint            id;
+
+  GtkShortcutsWindow *help_overlay;
 };
 
 static void
@@ -788,9 +790,9 @@ gtk_application_window_dispose (GObject *object)
 
   g_clear_object (&window->priv->app_menu_section);
   g_clear_object (&window->priv->menubar_section);
+  g_clear_object (&window->priv->help_overlay);
 
-  G_OBJECT_CLASS (gtk_application_window_parent_class)
-    ->dispose (object);
+  G_OBJECT_CLASS (gtk_application_window_parent_class)->dispose (object);
 
   /* We do this below the chain-up above to give us a chance to be
    * removed from the GtkApplication (which is done in the dispose
@@ -959,3 +961,75 @@ gtk_application_window_set_id (GtkApplicationWindow *window,
   g_return_if_fail (GTK_IS_APPLICATION_WINDOW (window));
   window->priv->id = id;
 }
+
+static void
+show_help_overlay (GSimpleAction *action,
+                   GVariant      *parameter,
+                   gpointer       user_data)
+{
+  GtkApplicationWindow *window = user_data;
+
+  if (window->priv->help_overlay)
+    gtk_widget_show (GTK_WIDGET (window->priv->help_overlay));
+}
+
+/**
+ * gtk_application_window_set_help_overlay:
+ * @window: a #GtkApplicationWindow
+ * @help_overlay: a #GtkShortcutsWindow
+ *
+ * Associates a shortcuts window with the application window, and
+ * sets up a action with the name win.show-help-overay to present
+ * it.
+ *
+ * Since: 3.20
+ */
+void
+gtk_application_window_set_help_overlay (GtkApplicationWindow *window,
+                                         GtkShortcutsWindow   *help_overlay)
+{
+  g_return_if_fail (GTK_IS_APPLICATION_WINDOW (window));
+  g_return_if_fail (help_overlay == NULL || GTK_IS_SHORTCUTS_WINDOW (help_overlay));
+
+  if (window->priv->help_overlay)
+    g_signal_handlers_disconnect_by_func (window->priv->help_overlay,
+                                          G_CALLBACK (gtk_widget_hide_on_delete), NULL);
+  g_set_object (&window->priv->help_overlay, help_overlay);
+
+  if (!window->priv->help_overlay)
+    return;
+
+  gtk_window_set_modal (GTK_WINDOW (help_overlay), TRUE);
+  gtk_window_set_transient_for (GTK_WINDOW (help_overlay), GTK_WINDOW (window));
+  g_signal_connect (help_overlay, "delete-event",
+                    G_CALLBACK (gtk_widget_hide_on_delete), NULL);
+
+  if (!g_action_map_lookup_action (G_ACTION_MAP (window->priv->actions), "show-help-overlay"))
+    {
+      GSimpleAction *action;
+
+      action = g_simple_action_new ("show-help-overlay", NULL);
+      g_signal_connect (action, "activate", G_CALLBACK (show_help_overlay), window);
+
+      g_action_map_add_action (G_ACTION_MAP (window->priv->actions), G_ACTION (action));
+    }
+}
+
+/**
+ * gtk_application_window_get_help_overlay:
+ * @window: a #GtkApplicationWindow
+ *
+ * Gets the #GtkShortcutsWindow that has been set up with
+ * a prior call to gtk_application_window_set_help_overlay().
+ *
+ * Returns: the help overlay associated with @window, or %NULL
+ *
+ * Since: 3.20
+ */
+GtkShortcutsWindow *
+gtk_application_window_get_help_overlay (GtkApplicationWindow *window)
+{
+  g_return_val_if_fail (GTK_IS_APPLICATION_WINDOW (window), NULL);
+
+  return window->priv->help_overlay;
+}
diff --git a/gtk/gtkapplicationwindow.h b/gtk/gtkapplicationwindow.h
index 234283c..abe41c9 100644
--- a/gtk/gtkapplicationwindow.h
+++ b/gtk/gtkapplicationwindow.h
@@ -25,6 +25,7 @@
 #endif
 
 #include <gtk/gtkwindow.h>
+#include <gtk/gtkshortcutswindow.h>
 
 G_BEGIN_DECLS
 
@@ -78,6 +79,13 @@ gboolean    gtk_application_window_get_show_menubar (GtkApplicationWindow *windo
 GDK_AVAILABLE_IN_3_6
 guint       gtk_application_window_get_id           (GtkApplicationWindow *window);
 
+GDK_AVAILABLE_IN_3_20
+void        gtk_application_window_set_help_overlay (GtkApplicationWindow *window,
+                                                     GtkShortcutsWindow   *help_overlay);
+GDK_AVAILABLE_IN_3_20
+GtkShortcutsWindow *
+            gtk_application_window_get_help_overlay (GtkApplicationWindow *window);
+
 G_END_DECLS
 
 #endif /* __GTK_APPLICATION_WINDOW_H__ */


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