[gtk+/wip/gmenu: 63/87] GtkApplication: Merge app menu and menubar



commit c67633bc97cab52108919b8490ba1d5e1029e223
Author: Colin Walters <walters verbum org>
Date:   Thu Dec 1 16:46:36 2011 -0500

    GtkApplication: Merge app menu and menubar
    
    Change bloatpad to have both an app menu and a menubar.

 examples/bloatpad.c        |  148 ++++++++++++++++++++++----------------------
 gtk/gtk.symbols            |    1 -
 gtk/gtkapplicationwindow.c |  104 +++++++++++++++----------------
 3 files changed, 125 insertions(+), 128 deletions(-)
---
diff --git a/examples/bloatpad.c b/examples/bloatpad.c
index 5ec5f39..161d33e 100644
--- a/examples/bloatpad.c
+++ b/examples/bloatpad.c
@@ -1,48 +1,42 @@
 #include <stdlib.h>
 #include <gtk/gtk.h>
 
-static void
-show_about (GSimpleAction *action,
-            GVariant      *parameter,
-            gpointer       user_data)
+static GtkClipboard *
+get_clipboard (GtkWidget *widget)
 {
-  GtkWindow *window = user_data;
-
-  gtk_show_about_dialog (window,
-                         "program-name", "Bloatpad",
-                         "title", "About Bloatpad",
-                         "comments", "Not much to say, really.",
-                         NULL);
+  return gtk_widget_get_clipboard (widget, gdk_atom_intern_static_string ("CLIPBOARD"));
 }
 
 static void
-activate_toggle (GSimpleAction *action,
-                 GVariant      *parameter,
-                 gpointer       user_data)
+window_copy (GSimpleAction *action,
+	     GVariant      *parameter,
+	     gpointer       user_data)
 {
-  GVariant *state;
+  GtkWindow *window = GTK_WINDOW (user_data);
+  GtkTextView *text = g_object_get_data ((GObject*)window, "bloatpad-text");
 
-  state = g_action_get_state (G_ACTION (action));
-  g_action_change_state (G_ACTION (action), g_variant_new_boolean (!g_variant_get_boolean (state)));
-  g_variant_unref (state);
+  gtk_text_buffer_copy_clipboard (gtk_text_view_get_buffer (text),
+				  get_clipboard ((GtkWidget*) text));
 }
 
 static void
-change_fullscreen_state (GSimpleAction *action,
-                         GVariant      *state,
-                         gpointer       user_data)
+window_paste (GSimpleAction *action,
+	      GVariant      *parameter,
+	      gpointer       user_data)
 {
-  if (g_variant_get_boolean (state))
-    gtk_window_fullscreen (user_data);
-  else
-    gtk_window_unfullscreen (user_data);
+  GtkWindow *window = GTK_WINDOW (user_data);
+  GtkTextView *text = g_object_get_data ((GObject*)window, "bloatpad-text");
+  
+  gtk_text_buffer_paste_clipboard (gtk_text_view_get_buffer (text),
+				   get_clipboard ((GtkWidget*) text),
+				   NULL,
+				   TRUE);
 
-  g_simple_action_set_state (action, state);
 }
 
 static GActionEntry win_entries[] = {
-  { "about", show_about },
-  { "fullscreen", activate_toggle, NULL, "false", change_fullscreen_state }
+  { "copy", window_copy, NULL, NULL, NULL },
+  { "paste", window_paste, NULL, NULL, NULL },
 };
 
 static void
@@ -63,6 +57,8 @@ new_window (GApplication *app,
   gtk_widget_set_vexpand (scrolled, TRUE);
   view = gtk_text_view_new ();
 
+  g_object_set_data ((GObject*)window, "bloatpad-text", view);
+
   gtk_container_add (GTK_CONTAINER (scrolled), view);
 
   gtk_grid_attach (GTK_GRID (grid), scrolled, 0, 0, 1, 1);
@@ -115,13 +111,20 @@ bloat_pad_finalize (GObject *object)
 }
 
 static void
-show_help (GSimpleAction *action,
-           GVariant      *parameter,
-           gpointer       user_data)
+show_about (GSimpleAction *action,
+            GVariant      *parameter,
+            gpointer       user_data)
 {
-  g_print ("Want help, eh ?!\n");
+  GtkWindow *window = user_data;
+
+  gtk_show_about_dialog (window,
+                         "program-name", "Bloatpad",
+                         "title", "About Bloatpad",
+                         "comments", "Not much to say, really.",
+                         NULL);
 }
 
+
 static void
 quit_app (GSimpleAction *action,
           GVariant      *parameter,
@@ -144,46 +147,15 @@ quit_app (GSimpleAction *action,
     }
 }
 
-static GSimpleActionGroup *actions = NULL;
-static GMenu *menu = NULL;
-
-static void
-remove_action (GSimpleAction *action,
-               GVariant      *parameter,
-               gpointer       user_data)
-{
-  GAction *add;
-
-  g_menu_remove (menu, g_menu_model_get_n_items (G_MENU_MODEL (menu)) - 1);
-  g_simple_action_set_enabled (action, FALSE);
-  add = g_simple_action_group_lookup (actions, "add");
-  g_simple_action_set_enabled (G_SIMPLE_ACTION (add), TRUE);
-}
-
-static void
-add_action (GSimpleAction *action,
-            GVariant      *parameter,
-            gpointer       user_data)
-{
-  GAction *remove;
-
-  g_menu_append (menu, "Remove", "app.remove");
-  g_simple_action_set_enabled (action, FALSE);
-  remove = g_simple_action_group_lookup (actions, "remove");
-  g_simple_action_set_enabled (G_SIMPLE_ACTION (remove), TRUE);
-}
-
 static GActionEntry app_entries[] = {
-  { "help", show_help, NULL, NULL, NULL },
+  { "about", show_about, NULL, NULL, NULL },
   { "quit", quit_app, NULL, NULL, NULL },
-  { "add", add_action, NULL, NULL, NULL },
-  { "remove", remove_action, NULL, NULL, NULL }
 };
 
 static GActionGroup *
-get_actions (void)
+create_app_actions (void)
 {
-  actions = g_simple_action_group_new ();
+  GSimpleActionGroup *actions = g_simple_action_group_new ();
   g_simple_action_group_add_entries (actions,
                                      app_entries, G_N_ELEMENTS (app_entries),
                                      NULL);
@@ -192,14 +164,29 @@ get_actions (void)
 }
 
 static GMenuModel *
-get_menu (void)
+create_app_menu (void)
 {
-  menu = g_menu_new ();
-  g_menu_append (menu, "_Help", "app.help");
-  g_menu_append (menu, "_About Bloatpad", "win.about");
-  g_menu_append (menu, "_Fullscreen", "win.fullscreen");
+  GMenu *menu = g_menu_new ();
+  g_menu_append (menu, "_About Bloatpad", "app.about");
   g_menu_append (menu, "_Quit", "app.quit");
-  g_menu_append (menu, "Add", "app.add");
+
+  return G_MENU_MODEL (menu);
+}
+
+static GMenuModel *
+create_window_menu (void)
+{
+  GMenu *menu;
+  GMenu *edit_menu;
+
+  edit_menu = g_menu_new ();
+  g_menu_append (edit_menu, "_Copy", "win.copy");
+  g_menu_append (edit_menu, "_Paste", "win.paste");
+
+  g_menu_append (edit_menu, "_Fullscreen", "win.fullscreen");
+
+  menu = g_menu_new ();
+  g_menu_append_section (menu, "_Edit", (GMenuModel*)edit_menu);
 
   return G_MENU_MODEL (menu);
 }
@@ -207,8 +194,21 @@ get_menu (void)
 static void
 bloat_pad_init (BloatPad *app)
 {
-  g_application_set_action_group (G_APPLICATION (app), get_actions ());
-  g_application_set_app_menu (G_APPLICATION (app), get_menu ());
+  GActionGroup *actions;
+  GMenuModel *app_menu;
+  GMenuModel *window_menu;
+
+  actions = create_app_actions ();
+  g_application_set_action_group (G_APPLICATION (app), actions);
+  g_object_unref (actions);
+
+  app_menu = create_app_menu ();
+  g_application_set_app_menu (G_APPLICATION (app), app_menu);
+  g_object_unref (app_menu);
+
+  window_menu = create_window_menu ();
+  g_application_set_menubar (G_APPLICATION (app), window_menu);
+  g_object_unref (window_menu);
 }
 
 static void
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index 18e8079..88fdfb3 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -222,7 +222,6 @@ gtk_application_get_type
 gtk_application_get_windows
 gtk_application_new
 gtk_application_remove_window
-gtk_application_window_get_app_menu
 gtk_application_window_get_show_app_menu
 gtk_application_window_get_type
 gtk_application_window_new
diff --git a/gtk/gtkapplicationwindow.c b/gtk/gtkapplicationwindow.c
index 807caa3..d2cb264 100644
--- a/gtk/gtkapplicationwindow.c
+++ b/gtk/gtkapplicationwindow.c
@@ -64,6 +64,8 @@ struct _GtkApplicationWindowPrivate
 
 static void
 recalculate_app_menu_state (GtkApplicationWindow *window);
+static GtkWidget *
+gtk_application_window_create_menubar (GtkApplicationWindow *window);
 
 static void
 on_shell_shows_app_menu_changed (GtkSettings *settings,
@@ -478,15 +480,8 @@ recalculate_app_menu_state (GtkApplicationWindow *window)
        && window->priv->override_show_app_menu)
       || window->priv->default_show_app_menu)
     {
-      GtkWidget *menubar;
-      GtkWidget *item;
-
-      item = gtk_menu_item_new_with_label (_("Application"));
-      gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), gtk_application_window_get_app_menu (window));
-
-      menubar = gtk_menu_bar_new ();
+      GtkWidget *menubar = gtk_application_window_create_menubar (window);
       window->priv->menubar = g_object_ref_sink (menubar);
-      gtk_menu_shell_append (GTK_MENU_SHELL (menubar), item);
       gtk_widget_set_parent (menubar, GTK_WIDGET (window));
       gtk_widget_show_all (menubar);
     }
@@ -768,8 +763,8 @@ append_items_from_model (GtkMenuShell *menu,
 
 static void
 populate_menu_from_model (GtkMenuShell *menu,
-                          GMenuModel   *model,
-                          GActionGroup *group)
+			  GMenuModel   *model,
+			  GActionGroup *group)
 {
   gboolean need_separator;
 
@@ -778,7 +773,9 @@ populate_menu_from_model (GtkMenuShell *menu,
 }
 
 typedef struct {
+  GActionMuxer *muxer;
   GtkApplication *application;
+  GtkApplicationWindow *window;
   GtkMenuShell   *menu;
   guint           update_idle;
   GHashTable     *connected;
@@ -789,6 +786,8 @@ free_items_changed_data (gpointer data)
 {
   ItemsChangedData *d = data;
 
+  g_object_unref (d->muxer);
+  g_object_unref (d->window);
   g_object_unref (d->application);
 
   if (d->update_idle != 0)
@@ -805,7 +804,9 @@ repopulate_menu (gpointer data)
   ItemsChangedData *d = data;
   GList *children, *l;
   GtkWidget *child;
-  GMenuModel *model;
+  GtkMenuShell *app_shell;
+  GMenuModel *app_model;
+  GMenuModel *window_model;
 
   /* remove current children */
   children = gtk_container_get_children (GTK_CONTAINER (d->menu));
@@ -816,9 +817,23 @@ repopulate_menu (gpointer data)
     }
   g_list_free (children);
 
-  /* repopulate */
-  model = g_application_get_app_menu (G_APPLICATION (d->application));
-  populate_menu_from_model (d->menu, model, G_ACTION_GROUP (d->application));
+  app_model = g_application_get_app_menu (G_APPLICATION (d->application));
+
+  if (app_model)
+    {
+      child = gtk_menu_item_new_with_label (_("Application"));
+      app_shell = (GtkMenuShell*)gtk_menu_new ();
+      gtk_menu_item_set_submenu ((GtkMenuItem*)child, (GtkWidget*)app_shell);
+      /* repopulate */
+      populate_menu_from_model (app_shell, app_model, (GActionGroup*)d->muxer);
+      gtk_menu_shell_append ((GtkMenuShell*)d->menu, child);
+    }
+
+  window_model = g_application_get_menubar (G_APPLICATION (d->application));
+  if (window_model)
+    {
+      populate_menu_from_model (d->menu, window_model, (GActionGroup*)d->muxer);
+    }
 
   d->update_idle = 0;
 
@@ -868,60 +883,43 @@ items_changed (GMenuModel *model,
   connect_to_items_changed (model, G_CALLBACK (items_changed), data);
 }
 
-/**
- * gtk_application_window_get_app_menu:
- * @window: a #GtkApplicationWindow
- *
- * Populates a menu widget from a menu model that is
- * associated with @window. See g_application_set_menu().
- * The menu items will be connected to actions of @window or
- * its associated #GtkApplication, as indicated by the menu model.
- * The menus contents will be updated automatically in response
- * to menu model changes.
- *
- * It is the callers responsibility to add the menu at a
- * suitable place in the widget hierarchy.
- *
- * This function returns %NULL if @window has no associated
- * menu model.
- *
- * Returns: A #GtkMenu that has been populated from the
- *     #GMenuModel that is associated with @window, or %NULL
- */
-GtkWidget *
-gtk_application_window_get_app_menu (GtkApplicationWindow *window)
+static GtkWidget *
+gtk_application_window_create_menubar (GtkApplicationWindow *window)
 {
   GtkApplication *application;
-  GtkWidget *menu;
-  GMenuModel *model;
+  GMenuModel *app_model;
+  GMenuModel *win_model;
   ItemsChangedData *data;
-  GActionMuxer *muxer;
+  GtkWidget *menubar;
 
   application = gtk_window_get_application (GTK_WINDOW (window));
+  app_model = g_application_get_app_menu (G_APPLICATION (application));
+  win_model = g_application_get_menubar (G_APPLICATION (application));
 
-  model = g_application_get_app_menu (G_APPLICATION (application));
-
-  if (!model)
+  if (!(app_model || win_model))
     return NULL;
 
-  menu = gtk_menu_new ();
-
-  muxer = g_action_muxer_new ();
-  g_action_muxer_insert (muxer, "app", G_ACTION_GROUP (application));
-  g_action_muxer_insert (muxer, "win", G_ACTION_GROUP (window));
-  populate_menu_from_model (GTK_MENU_SHELL (menu), model, G_ACTION_GROUP (muxer));
-  g_object_unref (muxer);
+  menubar = gtk_menu_bar_new ();
 
   data = g_new (ItemsChangedData, 1);
+  data->muxer = g_action_muxer_new ();
+  g_action_muxer_insert (data->muxer, "app", G_ACTION_GROUP (application));
+  g_action_muxer_insert (data->muxer, "win", G_ACTION_GROUP (window));
+  data->window = g_object_ref (window);
   data->application = g_object_ref (application);
-  data->menu = GTK_MENU_SHELL (menu);
+  data->menu = GTK_MENU_SHELL (menubar);
   data->update_idle = 0;
   data->connected = g_hash_table_new (NULL, NULL);
 
-  g_object_set_data_full (G_OBJECT (menu), "gtk-application-menu-data",
+  g_object_set_data_full (G_OBJECT (menubar), "gtk-application-menu-data",
                           data, free_items_changed_data);
 
-  connect_to_items_changed (model, G_CALLBACK (items_changed), data);
+  if (app_model)
+    connect_to_items_changed (app_model, G_CALLBACK (items_changed), data);
+  if (win_model)
+    connect_to_items_changed (win_model, G_CALLBACK (items_changed), data);
+
+  repopulate_menu (data);
 
-  return menu;
+  return menubar;
 }



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