Commit dd143479 authored by Allison Karlitskaya's avatar Allison Karlitskaya

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
parent 778aa7ad
......@@ -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
<SUBSECTION Standard>
GTK_MENU_SHELL
......
......@@ -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
......
......@@ -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);
......
......@@ -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;
}
......@@ -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;
}
......@@ -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__ */
......@@ -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
*
* Establishes a binding between a #GtkMenuShell and a #GMenuModel.
*
* 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.
*
* Creates a #GtkMenu and populates it with menu items and
* submenus according to @model.
* @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.
*
* 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.
* 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".
*
* Returns: a new #GtkMenu
* 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.4
* Since: 3.6
*/
GtkWidget *
gtk_menu_new_from_model (GMenuModel *model)
{
GtkWidget *menu;
menu = gtk_menu_new ();
gtk_model_menu_bind (GTK_MENU_SHELL (menu), model, NULL, TRUE);
gtk_model_menu_populate (GTK_MENU_SHELL (menu));
return menu;
}
GtkWidget *
gtk_model_menu_create_menu_bar (GMenuModel *model)
void
gtk_menu_shell_bind_model (GtkMenuShell *shell,
GMenuModel *model,
const gchar *action_namespace,
gboolean with_separators)
{
GtkWidget *menubar;
g_return_if_fail (GTK_IS_MENU_SHELL (shell));
g_return_if_fail (model == NULL || G_IS_MENU_MODEL (model));
menubar = gtk_menu_bar_new ();
if (model)
{
GtkModelMenuBinding *binding;
gtk_model_menu_bind (GTK_MENU_SHELL (menubar), model, NULL, FALSE);
gtk_model_menu_populate (GTK_MENU_SHELL (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);
return menubar;
}
g_object_set_data_full (G_OBJECT (shell), "gtk-model-menu-binding", binding, gtk_model_menu_binding_free);
/**
* 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;
gtk_model_menu_binding_populate (binding);
}
menubar = gtk_menu_bar_new ();
else
{
GList *children;
gtk_model_menu_bind (GTK_MENU_SHELL (menubar), model, NULL, FALSE);
gtk_model_menu_populate (GTK_MENU_SHELL (menubar));
/* break existing binding */
g_object_set_data (G_OBJECT (shell), "gtk-model-menu-binding", NULL);
return menubar;
/* 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);
}
}
}
/*
* 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 <http://www.gnu.org/licenses/>.
*
* Author: Ryan Lortie <desrt@desrt.ca>
*/
#ifndef __GTK_MODEL_MENU_H__
#define __GTK_MODEL_MENU_H__
#include <gtk/gtkmenushell.h>
#include <gtk/gtkaccelgroup.h>
#include <gio/gio.h>
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__ */
......@@ -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", &section_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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment