From dd143479fe85f16e4ea010a7b03d4365d9d9234e Mon Sep 17 00:00:00 2001 From: Ryan Lortie Date: Tue, 11 Sep 2012 11:38:06 -0400 Subject: [PATCH] gtkmodelmenu: simplify logic, expose bind API Make the main (and only) entry-point to gtkmodelmenu.c the now-public gtk_menu_shell_bind_model(). Move the convenience constructors (gtk_menu_new_from_model() and gtk_menu_bar_new_from_model()) to their proper files. Remove the private header file. Simplify the code a bit by making the initial populate part of the bind() call. https://bugzilla.gnome.org/show_bug.cgi?id=682831 --- docs/reference/gtk/gtk3-sections.txt | 1 + gtk/gtk.symbols | 1 + gtk/gtkapplicationwindow.c | 4 +- gtk/gtkmenu.c | 29 +++++ gtk/gtkmenubar.c | 29 +++++ gtk/gtkmenushell.h | 6 + gtk/gtkmodelmenu.c | 176 +++++++++++---------------- gtk/gtkmodelmenu.h | 34 ------ gtk/gtkmodelmenuitem.c | 8 +- 9 files changed, 141 insertions(+), 147 deletions(-) delete mode 100644 gtk/gtkmodelmenu.h diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt index dd1d53618d..ce014ac4ef 100644 --- a/docs/reference/gtk/gtk3-sections.txt +++ b/docs/reference/gtk/gtk3-sections.txt @@ -2246,6 +2246,7 @@ gtk_menu_shell_set_take_focus gtk_menu_shell_get_take_focus gtk_menu_shell_get_selected_item gtk_menu_shell_get_parent_shell +gtk_menu_shell_bind_model GtkMenuDirectionType GTK_MENU_SHELL diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index 40d3a31b5c..2bd830320f 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -1622,6 +1622,7 @@ gtk_menu_set_tearoff_state gtk_menu_set_title gtk_menu_shell_activate_item gtk_menu_shell_append +gtk_menu_shell_bind_model gtk_menu_shell_cancel gtk_menu_shell_deactivate gtk_menu_shell_deselect diff --git a/gtk/gtkapplicationwindow.c b/gtk/gtkapplicationwindow.c index 0632bed5e4..2a9215a4a6 100644 --- a/gtk/gtkapplicationwindow.c +++ b/gtk/gtkapplicationwindow.c @@ -24,9 +24,9 @@ #include "gtkapplicationprivate.h" #include "gtkwidgetprivate.h" #include "gtkwindowprivate.h" -#include "gtkmodelmenu.h" #include "gtkaccelgroup.h" #include "gtkaccelmap.h" +#include "gtkmenubar.h" #include "gtkintl.h" #include "gtksettings.h" @@ -256,7 +256,7 @@ gtk_application_window_update_menubar (GtkApplicationWindow *window) g_menu_append_section (combined, NULL, G_MENU_MODEL (window->priv->app_menu_section)); g_menu_append_section (combined, NULL, G_MENU_MODEL (window->priv->menubar_section)); - window->priv->menubar = gtk_model_menu_create_menu_bar (G_MENU_MODEL (combined)); + window->priv->menubar = gtk_menu_bar_new_from_model (G_MENU_MODEL (combined)); gtk_widget_set_parent (window->priv->menubar, GTK_WIDGET (window)); gtk_widget_show_all (window->priv->menubar); g_object_unref (combined); diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c index 6667ed5f6d..9271c1d52e 100644 --- a/gtk/gtkmenu.c +++ b/gtk/gtkmenu.c @@ -5784,3 +5784,32 @@ gtk_menu_get_reserve_toggle_size (GtkMenu *menu) return !menu->priv->no_toggle_size; } + +/** + * gtk_menu_new_from_model: + * @model: a #GMenuModel + * + * Creates a #GtkMenu and populates it with menu items and + * submenus according to @model. + * + * The created menu items are connected to actions found in the + * #GtkApplicationWindow to which the menu belongs - typically + * by means of being attached to a widget (see gtk_menu_attach_to_widget()) + * that is contained within the #GtkApplicationWindows widget hierarchy. + * + * Returns: a new #GtkMenu + * + * Since: 3.4 + */ +GtkWidget * +gtk_menu_new_from_model (GMenuModel *model) +{ + GtkWidget *menu; + + g_return_val_if_fail (G_IS_MENU_MODEL (model), NULL); + + menu = gtk_menu_new (); + gtk_menu_shell_bind_model (GTK_MENU_SHELL (menu), model, NULL, TRUE); + + return menu; +} diff --git a/gtk/gtkmenubar.c b/gtk/gtkmenubar.c index c4f7e9f0d6..b90e4b8921 100644 --- a/gtk/gtkmenubar.c +++ b/gtk/gtkmenubar.c @@ -1041,3 +1041,32 @@ gtk_menu_bar_set_child_pack_direction (GtkMenuBar *menubar, g_object_notify (G_OBJECT (menubar), "child-pack-direction"); } } + +/** + * gtk_menu_bar_new_from_model: + * @model: a #GMenuModel + * + * Creates a new #GtkMenuBar and populates it with menu items + * and submenus according to @model. + * + * The created menu items are connected to actions found in the + * #GtkApplicationWindow to which the menu bar belongs - typically + * by means of being contained within the #GtkApplicationWindows + * widget hierarchy. + * + * Returns: a new #GtkMenuBar + * + * Since: 3.4 + */ +GtkWidget * +gtk_menu_bar_new_from_model (GMenuModel *model) +{ + GtkWidget *menubar; + + g_return_val_if_fail (G_IS_MENU_MODEL (model), NULL); + + menubar = gtk_menu_bar_new (); + gtk_menu_shell_bind_model (GTK_MENU_SHELL (menubar), model, NULL, FALSE); + + return menubar; +} diff --git a/gtk/gtkmenushell.h b/gtk/gtkmenushell.h index 6e15ffc671..c0479e8ab3 100644 --- a/gtk/gtkmenushell.h +++ b/gtk/gtkmenushell.h @@ -112,6 +112,12 @@ void gtk_menu_shell_set_take_focus (GtkMenuShell *menu_shell, GtkWidget *gtk_menu_shell_get_selected_item (GtkMenuShell *menu_shell); GtkWidget *gtk_menu_shell_get_parent_shell (GtkMenuShell *menu_shell); +GDK_AVAILABLE_IN_3_6 +void gtk_menu_shell_bind_model (GtkMenuShell *menu_shell, + GMenuModel *model, + const gchar *action_namespace, + gboolean with_separators); + G_END_DECLS #endif /* __GTK_MENU_SHELL_H__ */ diff --git a/gtk/gtkmodelmenu.c b/gtk/gtkmodelmenu.c index f2174dd89d..0c3cc5e96c 100644 --- a/gtk/gtkmodelmenu.c +++ b/gtk/gtkmodelmenu.c @@ -21,10 +21,10 @@ #include "config.h" -#include "gtkmodelmenu.h" - -#include "gtkmenu.h" +#include "gtkmenushell.h" #include "gtkmenubar.h" +#include "gtkmenu.h" + #include "gtkseparatormenuitem.h" #include "gtkmodelmenuitem.h" #include "gtkapplicationprivate.h" @@ -243,116 +243,80 @@ gtk_model_menu_binding_items_changed (GMenuModel *model, } } -static void -gtk_model_menu_bind (GtkMenuShell *shell, - GMenuModel *model, - const gchar *action_namespace, - gboolean with_separators) -{ - GtkModelMenuBinding *binding; - - binding = g_slice_new (GtkModelMenuBinding); - binding->model = g_object_ref (model); - binding->shell = shell; - binding->update_idle = 0; - binding->connected = NULL; - binding->with_separators = with_separators; - binding->action_namespace = g_strdup (action_namespace); - - g_object_set_data_full (G_OBJECT (shell), "gtk-model-menu-binding", binding, gtk_model_menu_binding_free); -} - - -static void -gtk_model_menu_populate (GtkMenuShell *shell) -{ - GtkModelMenuBinding *binding; - - binding = (GtkModelMenuBinding*) g_object_get_data (G_OBJECT (shell), "gtk-model-menu-binding"); - - gtk_model_menu_binding_populate (binding); -} - -GtkWidget * -gtk_model_menu_create_menu (GMenuModel *model, - const gchar *action_namespace) -{ - GtkWidget *menu; - - menu = gtk_menu_new (); - - gtk_model_menu_bind (GTK_MENU_SHELL (menu), model, action_namespace, TRUE); - gtk_model_menu_populate (GTK_MENU_SHELL (menu)); - - return menu; -} - /** - * gtk_menu_new_from_model: - * @model: a #GMenuModel + * gtk_menu_shell_bind_model: + * @menu_shell: a #GtkMenuShell + * @model: (allow-none): the #GMenuModel to bind to or %NULL to remove + * binding + * @action_namespace: (allow-none): the namespace for actions in @model + * @with_separators: %TRUE if toplevel items in @shell should have + * separators between them * - * Creates a #GtkMenu and populates it with menu items and - * submenus according to @model. + * Establishes a binding between a #GtkMenuShell and a #GMenuModel. * - * The created menu items are connected to actions found in the - * #GtkApplicationWindow to which the menu belongs - typically - * by means of being attached to a widget (see gtk_menu_attach_to_widget()) - * that is contained within the #GtkApplicationWindows widget hierarchy. + * The contents of @shell are removed and then refilled with menu items + * according to @model. When @model changes, @shell is updated. + * Calling this function twice on @shell with different @model will + * cause the first binding to be replaced with a binding to the new + * model. If @model is %NULL then any previous binding is undone and + * all children are removed. * - * Returns: a new #GtkMenu + * @with_separators determines if toplevel items (eg: sections) have + * separators inserted between them. This is typically desired for + * menus but doesn't make sense for menubars. * - * Since: 3.4 + * If @action_namespace is non-%NULL then the effect is as if all + * actions mentioned in the @model have their names prefixed with the + * namespace, plus a dot. For example, if the action "quit" is + * mentioned and @action_namespace is "app" then the effective action + * name is "app.quit". + * + * For most cases you are probably better off using + * gtk_menu_new_from_model() or gtk_menu_bar_new_from_model() or just + * directly passing the #GMenuModel to gtk_application_set_app_menu() or + * gtk_application_set_menu_bar(). + * + * Since: 3.6 */ -GtkWidget * -gtk_menu_new_from_model (GMenuModel *model) +void +gtk_menu_shell_bind_model (GtkMenuShell *shell, + GMenuModel *model, + const gchar *action_namespace, + gboolean with_separators) { - GtkWidget *menu; + g_return_if_fail (GTK_IS_MENU_SHELL (shell)); + g_return_if_fail (model == NULL || G_IS_MENU_MODEL (model)); - menu = gtk_menu_new (); - gtk_model_menu_bind (GTK_MENU_SHELL (menu), model, NULL, TRUE); - gtk_model_menu_populate (GTK_MENU_SHELL (menu)); + if (model) + { + GtkModelMenuBinding *binding; - return menu; -} - -GtkWidget * -gtk_model_menu_create_menu_bar (GMenuModel *model) -{ - GtkWidget *menubar; - - menubar = gtk_menu_bar_new (); - - gtk_model_menu_bind (GTK_MENU_SHELL (menubar), model, NULL, FALSE); - gtk_model_menu_populate (GTK_MENU_SHELL (menubar)); - - return menubar; -} - -/** - * gtk_menu_bar_new_from_model: - * @model: a #GMenuModel - * - * Creates a new #GtkMenuBar and populates it with menu items - * and submenus according to @model. - * - * The created menu items are connected to actions found in the - * #GtkApplicationWindow to which the menu bar belongs - typically - * by means of being contained within the #GtkApplicationWindows - * widget hierarchy. - * - * Returns: a new #GtkMenuBar - * - * Since: 3.4 - */ -GtkWidget * -gtk_menu_bar_new_from_model (GMenuModel *model) -{ - GtkWidget *menubar; - - menubar = gtk_menu_bar_new (); - - gtk_model_menu_bind (GTK_MENU_SHELL (menubar), model, NULL, FALSE); - gtk_model_menu_populate (GTK_MENU_SHELL (menubar)); - - return menubar; + binding = g_slice_new (GtkModelMenuBinding); + binding->model = g_object_ref (model); + binding->shell = shell; + binding->update_idle = 0; + binding->connected = NULL; + binding->with_separators = with_separators; + binding->action_namespace = g_strdup (action_namespace); + + g_object_set_data_full (G_OBJECT (shell), "gtk-model-menu-binding", binding, gtk_model_menu_binding_free); + + gtk_model_menu_binding_populate (binding); + } + + else + { + GList *children; + + /* break existing binding */ + g_object_set_data (G_OBJECT (shell), "gtk-model-menu-binding", NULL); + + /* remove all children */ + children = gtk_container_get_children (GTK_CONTAINER (shell)); + while (children) + { + gtk_container_remove (GTK_CONTAINER (shell), children->data); + children = g_list_delete_link (children, children); + } + } } diff --git a/gtk/gtkmodelmenu.h b/gtk/gtkmodelmenu.h deleted file mode 100644 index a27c7bda4b..0000000000 --- a/gtk/gtkmodelmenu.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright © 2011 Canonical Limited - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the licence, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - * - * Author: Ryan Lortie - */ - -#ifndef __GTK_MODEL_MENU_H__ -#define __GTK_MODEL_MENU_H__ - -#include -#include -#include - -G_GNUC_INTERNAL -GtkWidget * gtk_model_menu_create_menu_bar (GMenuModel *model); - -G_GNUC_INTERNAL -GtkWidget * gtk_model_menu_create_menu (GMenuModel *model, - const gchar *action_namespace); - -#endif /* __GTK_MODEL_MENU_H__ */ diff --git a/gtk/gtkmodelmenuitem.c b/gtk/gtkmodelmenuitem.c index 61e10e5a3c..6d902c2352 100644 --- a/gtk/gtkmodelmenuitem.c +++ b/gtk/gtkmodelmenuitem.c @@ -23,7 +23,6 @@ #include "gtkaccelmapprivate.h" #include "gtkactionhelper.h" -#include "gtkmodelmenu.h" #include "gtkwidgetprivate.h" #include "gtkaccellabel.h" @@ -121,17 +120,16 @@ gtk_model_menu_item_setup (GtkModelMenuItem *item, GtkWidget *menu; g_menu_model_get_item_attribute (model, item_index, "action-namespace", "s", §ion_namespace); + menu = gtk_menu_new (); if (action_namespace) { gchar *namespace = g_strjoin (".", action_namespace, section_namespace, NULL); - menu = gtk_model_menu_create_menu (submenu, namespace); + gtk_menu_shell_bind_model (GTK_MENU_SHELL (menu), submenu, namespace, TRUE); g_free (namespace); } else - { - menu = gtk_model_menu_create_menu (submenu, section_namespace); - } + gtk_menu_shell_bind_model (GTK_MENU_SHELL (menu), submenu, section_namespace, TRUE); gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);