summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--ChangeLog.pre-2-105
-rw-r--r--ChangeLog.pre-2-85
-rw-r--r--demos/gtk-demo/appwindow.c47
-rw-r--r--docs/reference/ChangeLog3
-rw-r--r--docs/reference/gtk/tmpl/gtkuimanager.sgml5
-rw-r--r--gtk/gtkuimanager.c91
7 files changed, 129 insertions, 32 deletions
diff --git a/ChangeLog b/ChangeLog
index 98ecaf8076..825d2dec2a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
index 98ecaf8076..825d2dec2a 100644
--- a/ChangeLog.pre-2-10
+++ b/ChangeLog.pre-2-10
@@ -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
diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8
index 98ecaf8076..825d2dec2a 100644
--- a/ChangeLog.pre-2-8
+++ b/ChangeLog.pre-2-8
@@ -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
diff --git a/demos/gtk-demo/appwindow.c b/demos/gtk-demo/appwindow.c
index 5cf00815d3..7f2d7986a9 100644
--- a/demos/gtk-demo/appwindow.c
+++ b/demos/gtk-demo/appwindow.c
@@ -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);
diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog
index 42d5fdcd5a..ad452d8d38 100644
--- a/docs/reference/ChangeLog
+++ b/docs/reference/ChangeLog
@@ -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>
diff --git a/docs/reference/gtk/tmpl/gtkuimanager.sgml b/docs/reference/gtk/tmpl/gtkuimanager.sgml
index ac3b5aa995..956617f290 100644
--- a/docs/reference/gtk/tmpl/gtkuimanager.sgml
+++ b/docs/reference/gtk/tmpl/gtkuimanager.sgml
@@ -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
diff --git a/gtk/gtkuimanager.c b/gtk/gtkuimanager.c
index d5e759c59d..ee690925bc 100644
--- a/gtk/gtkuimanager.c
+++ b/gtk/gtkuimanager.c
@@ -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)
@@ -1215,6 +1211,21 @@ start_element_handler (GMarkupParseContext *context,
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"))
{
GNode *node;
@@ -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))
{
@@ -2422,7 +2463,7 @@ update_node (GtkUIManager *self,
break;
case NODE_TYPE_TOOLITEM:
/* remove the proxy if it is of the wrong type ... */
- if (info->proxy &&
+ if (info->proxy &&
G_OBJECT_TYPE (info->proxy) != GTK_ACTION_GET_CLASS (action)->toolbar_item_type)
{
g_signal_handlers_disconnect_by_func (info->proxy,
@@ -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);
}