Allow to construct menu tool buttons.

2005-06-18  Matthias Clasen  <mclasen@redhat.com>

	* gtk/gtkuimanager.c: Allow to construct menu tool buttons.

	* demos/gtk-demo/appwindow.c: Demonstrate menu tool buttons
	constructed with GtkUIManager.
This commit is contained in:
Matthias Clasen 2005-06-19 03:20:07 +00:00 committed by Matthias Clasen
parent 58a30d5f5a
commit 64bfd86b5b
7 changed files with 129 additions and 32 deletions

View File

@ -1,5 +1,10 @@
2005-06-18 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkuimanager.c: Allow to construct menu tool buttons.
* demos/gtk-demo/appwindow.c: Demonstrate menu tool buttons
constructed with GtkUIManager.
* gtk/gtk.symbols:
* gtk/gtkimage.h:
* gtk/gtkimage.c (gtk_image_clear): Make this function

View File

@ -1,5 +1,10 @@
2005-06-18 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkuimanager.c: Allow to construct menu tool buttons.
* demos/gtk-demo/appwindow.c: Demonstrate menu tool buttons
constructed with GtkUIManager.
* gtk/gtk.symbols:
* gtk/gtkimage.h:
* gtk/gtkimage.c (gtk_image_clear): Make this function

View File

@ -1,5 +1,10 @@
2005-06-18 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkuimanager.c: Allow to construct menu tool buttons.
* demos/gtk-demo/appwindow.c: Demonstrate menu tool buttons
constructed with GtkUIManager.
* gtk/gtk.symbols:
* gtk/gtkimage.h:
* gtk/gtkimage.c (gtk_image_clear): Make this function

View File

@ -1,6 +1,6 @@
/* Application main window
*
* Demonstrates a typical application window, with menubar, toolbar, statusbar.
* Demonstrates a typical application window with menubar, toolbar, statusbar.
*/
#include <gtk/gtk.h>
@ -144,9 +144,32 @@ about_cb (GtkAction *action,
g_object_unref (transparent);
}
typedef struct
{
GtkAction action;
} ToolMenuAction;
typedef struct
{
GtkActionClass parent_class;
} ToolMenuActionClass;
G_DEFINE_TYPE(ToolMenuAction, tool_menu_action, GTK_TYPE_ACTION);
static void
tool_menu_action_class_init (ToolMenuActionClass *class)
{
GTK_ACTION_CLASS (class)->toolbar_item_type = GTK_TYPE_MENU_TOOL_BUTTON;
}
static void
tool_menu_action_init (ToolMenuAction *action)
{
}
static GtkActionEntry entries[] = {
{ "FileMenu", NULL, "_File" }, /* name, stock id, label */
{ "OpenMenu", NULL, "_Open" }, /* name, stock id, label */
{ "PreferencesMenu", NULL, "_Preferences" }, /* name, stock id, label */
{ "ColorMenu", NULL, "_Color" }, /* name, stock id, label */
{ "ShapeMenu", NULL, "_Shape" }, /* name, stock id, label */
@ -155,9 +178,9 @@ static GtkActionEntry entries[] = {
"_New", "<control>N", /* label, accelerator */
"Create a new file", /* tooltip */
G_CALLBACK (activate_action) },
{ "Open", GTK_STOCK_OPEN, /* name, stock id */
"_Open","<control>O", /* label, accelerator */
"Open a file", /* tooltip */
{ "File1", NULL, /* name, stock id */
"File1", NULL, /* label, accelerator */
"Open first file", /* tooltip */
G_CALLBACK (activate_action) },
{ "Save", GTK_STOCK_SAVE, /* name, stock id */
"_Save","<control>S", /* label, accelerator */
@ -258,8 +281,12 @@ static const gchar *ui_info =
" <menuitem action='About'/>"
" </menu>"
" </menubar>"
" <toolbar name='ToolBar'>"
" <toolitem action='Open'/>"
" <toolbar name='ToolBar'>"
" <toolitem action='Open'>"
" <menu action='OpenMenu'>"
" <menuitem action='File1'/>"
" </menu>"
" </toolitem>"
" <toolitem action='Quit'/>"
" <separator action='Sep1'/>"
" <toolitem action='Logo'/>"
@ -394,6 +421,7 @@ do_appwindow (GtkWidget *do_widget)
GtkWidget *bar;
GtkTextBuffer *buffer;
GtkActionGroup *action_group;
GtkAction *open_action;
GtkUIManager *merge;
GError *error = NULL;
@ -421,6 +449,13 @@ do_appwindow (GtkWidget *do_widget)
*/
action_group = gtk_action_group_new ("AppWindowActions");
open_action = g_object_new (tool_menu_action_get_type (),
"name", "Open",
"label", "_Open",
"tooltip", "Open a file",
"stock-id", GTK_STOCK_OPEN,
NULL);
gtk_action_group_add_action (action_group, open_action);
gtk_action_group_add_actions (action_group,
entries, n_entries,
window);

View File

@ -1,5 +1,8 @@
2005-06-18 Matthias Clasen <mclasen@redhat.com>
* gtk/tmpl/gtkuimanager.sgml: Document that
toolitem elements may have menu subelements.
* gtk/gtk-sections.txt: Updates
2005-06-17 Matthias Clasen <mclasen@redhat.com>

View File

@ -22,7 +22,7 @@ roughly described by the following DTD.
&lt;!ELEMENT toolbar (toolitem|separator|placeholder)* &gt;
&lt;!ELEMENT placeholder (menuitem|toolitem|separator|placeholder|menu)* &gt;
&lt;!ELEMENT menuitem EMPTY &gt;
&lt;!ELEMENT toolitem EMPTY &gt;
&lt;!ELEMENT toolitem (menu?) &gt;
&lt;!ELEMENT separator EMPTY &gt;
&lt;!ELEMENT accelerator EMPTY &gt;
&lt;!ATTLIST menubar name &num;IMPLIED
@ -115,7 +115,8 @@ action</para></listitem>
</varlistentry>
<varlistentry><term>toolitem</term>
<listitem><para>a #GtkToolItem subclass, the exact type depends on the
action</para></listitem>
action. Note that toolitem elements may contain a menu element, but only
if their associated action specifies a #GtkMenuToolButton as proxy.</para></listitem>
</varlistentry>
<varlistentry><term>separator</term>
<listitem><para>a #GtkSeparatorMenuItem or

View File

@ -36,6 +36,7 @@
#include "gtkmenu.h"
#include "gtkmenubar.h"
#include "gtkmenushell.h"
#include "gtkmenutoolbutton.h"
#include "gtkseparatormenuitem.h"
#include "gtkseparatortoolitem.h"
#include "gtktearoffmenuitem.h"
@ -859,11 +860,6 @@ get_child_node (GtkUIManager *self,
{
GNode *child = NULL;
g_return_val_if_fail (parent == NULL ||
(NODE_INFO (parent)->type != NODE_TYPE_MENUITEM &&
NODE_INFO (parent)->type != NODE_TYPE_TOOLITEM),
NULL);
if (parent)
{
if (childname)
@ -1213,6 +1209,21 @@ start_element_handler (GMarkupParseContext *context,
node_prepend_ui_reference (ctx->current, ctx->merge_id, action_quark);
raise_error = FALSE;
}
else if (ctx->state == STATE_TOOLITEM && !strcmp (element_name, "menu"))
{
ctx->state = STATE_MENU;
ctx->current = get_child_node (self, g_node_last_child (ctx->current),
node_name, strlen (node_name),
NODE_TYPE_MENU,
TRUE, top);
if (NODE_INFO (ctx->current)->action_name == 0)
NODE_INFO (ctx->current)->action_name = action_quark;
node_prepend_ui_reference (ctx->current, ctx->merge_id, action_quark);
raise_error = FALSE;
}
else if (ctx->state == STATE_MENU && !strcmp (element_name, "menuitem"))
@ -1373,6 +1384,11 @@ end_element_handler (GMarkupParseContext *context,
ctx->current = ctx->current->parent;
if (NODE_INFO (ctx->current)->type == NODE_TYPE_ROOT)
ctx->state = STATE_ROOT;
else if (NODE_INFO (ctx->current)->type == NODE_TYPE_TOOLITEM)
{
ctx->current = ctx->current->parent;
ctx->state = STATE_TOOLITEM;
}
/* else, stay in same state */
break;
case STATE_MENUITEM:
@ -2141,7 +2157,10 @@ update_node (GtkUIManager *self,
GtkWidget *menu;
GList *siblings;
menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (info->proxy));
if (GTK_IS_MENU (info->proxy))
menu = info->proxy;
else
menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (info->proxy));
siblings = gtk_container_get_children (GTK_CONTAINER (menu));
if (siblings != NULL && GTK_IS_TEAROFF_MENU_ITEM (siblings->data))
{
@ -2187,12 +2206,16 @@ update_node (GtkUIManager *self,
if (info->proxy &&
G_OBJECT_TYPE (info->proxy) != GTK_ACTION_GET_CLASS (action)->menu_item_type)
{
prev_submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (info->proxy));
if (prev_submenu)
if (GTK_IS_MENU_ITEM (info->proxy))
{
g_object_ref (prev_submenu);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (info->proxy), NULL);
prev_submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (info->proxy));
if (prev_submenu)
{
g_object_ref (prev_submenu);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (info->proxy), NULL);
}
}
gtk_action_disconnect_proxy (info->action, info->proxy);
gtk_container_remove (GTK_CONTAINER (info->proxy->parent),
info->proxy);
@ -2205,16 +2228,13 @@ update_node (GtkUIManager *self,
GtkWidget *menushell;
gint pos;
if (find_menu_position (node, &menushell, &pos))
if (NODE_INFO (node->parent)->type == NODE_TYPE_TOOLITEM ||
find_menu_position (node, &menushell, &pos))
{
GtkWidget *tearoff;
GtkWidget *filler;
info->proxy = gtk_action_create_menu_item (action);
g_object_ref (info->proxy);
gtk_object_sink (GTK_OBJECT (info->proxy));
menu = gtk_menu_new ();
gtk_widget_set_name (info->proxy, info->name);
gtk_widget_set_name (menu, info->name);
tearoff = gtk_tearoff_menu_item_new ();
gtk_widget_set_no_show_all (tearoff, TRUE);
@ -2226,10 +2246,27 @@ update_node (GtkUIManager *self,
gtk_widget_set_sensitive (filler, FALSE);
gtk_widget_set_no_show_all (filler, TRUE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), filler);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (info->proxy), menu);
gtk_menu_shell_insert (GTK_MENU_SHELL (menushell), info->proxy, pos);
g_signal_connect (info->proxy, "notify::visible",
G_CALLBACK (update_smart_separators), NULL);
if (NODE_INFO (node->parent)->type == NODE_TYPE_TOOLITEM)
{
info->proxy = menu;
g_object_ref (info->proxy);
gtk_object_sink (GTK_OBJECT (info->proxy));
gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (NODE_INFO (node->parent)->proxy),
menu);
}
else
{
info->proxy = gtk_action_create_menu_item (action);
g_object_ref (info->proxy);
gtk_object_sink (GTK_OBJECT (info->proxy));
g_signal_connect (info->proxy, "notify::visible",
G_CALLBACK (update_smart_separators), NULL);
gtk_widget_set_name (info->proxy, info->name);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (info->proxy), menu);
gtk_menu_shell_insert (GTK_MENU_SHELL (menushell), info->proxy, pos);
}
}
}
else
@ -2241,7 +2278,11 @@ update_node (GtkUIManager *self,
prev_submenu);
g_object_unref (prev_submenu);
}
menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (info->proxy));
if (GTK_IS_MENU (info->proxy))
menu = info->proxy;
else
menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (info->proxy));
siblings = gtk_container_get_children (GTK_CONTAINER (menu));
if (siblings != NULL && GTK_IS_TEAROFF_MENU_ITEM (siblings->data))
{
@ -2454,7 +2495,7 @@ update_node (GtkUIManager *self,
* tooltips on toolitems can't be set before the toolitem
* is added to the toolbar.
*/
g_object_notify (G_OBJECT (action), "tooltip");
g_object_notify (G_OBJECT (action), "tooltip");
}
}
else
@ -2560,9 +2601,11 @@ update_node (GtkUIManager *self,
if (info->proxy)
{
if (info->type == NODE_TYPE_MENU)
if (info->type == NODE_TYPE_MENU && GTK_IS_MENU_ITEM (info->proxy))
update_smart_separators (gtk_menu_item_get_submenu (GTK_MENU_ITEM (info->proxy)));
else if (info->type == NODE_TYPE_TOOLBAR || info->type == NODE_TYPE_POPUP)
else if (info->type == NODE_TYPE_MENU ||
info->type == NODE_TYPE_TOOLBAR ||
info->type == NODE_TYPE_POPUP)
update_smart_separators (info->proxy);
}