diff --git a/ChangeLog b/ChangeLog index c3303544dc..37701b0115 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,52 @@ +2005-02-11 Matthias Clasen + + Support vertical menubars (#166632): + + * gtk/gtkenums.h (GtkPackDirection): New enumeration for pack + directions, with values for left-to-right, right-to-left, + top-to-bottom and bottom-to-top. + + * gtk/gtk.symbols: + * gtk/gtkmenubar.h: + * gtk/gtkmenubar.c: Add two properties, pack-direction and + child-pack-direction, which specify how children and + grandchildren of a menubar are packed, with getters and setters. + + * gtk/gtkmenubar.c (gtk_menu_bar_set_property): + (gtk_menu_bar_get_property): Implement set_property and get_property. + + * gtk/gtkmenubar.c (gtk_menu_bar_size_request): + (gtk_menu_bar_size_allocate): Take pack direction into account. + + * gtk/gtkmenubar.c (gtk_menu_bar_move_current): Implement + move_current here move all the menubar-specific direction + tweaking from the generic menushell implementation here. + + * gtk/gtkmenu.c (gtk_menu_move_current): Move menu-specific + direction tweaking from the generic menushell implementation here. + + * gtk/gtkmenuitem.c (gtk_menu_item_size_request): + (gtk_menu_bar_size_allocate): Take pack direction into account. + + * gtk/gtkimagemenuitem.c (gtk_image_menu_item_size_request) + (gtk_image_menu_item_size_allocate): + (gtk_image_menu_item_toggle_size_request): Take child pack + direction into account and pack the image vertically if + necessary. + + * gtk/gtkmenushell.c (gtk_menu_shell_real_select_item): + Set the submenu direction to left-right for menuitems in + vertical menubars. + (gtk_real_menu_shell_move_current): Simplify by moving + direction tweaking to menu- and menubar-specific + implementations. Take pack direction into account when + doing fallbacks. + + * tests/testmenubars.c: Test menubars in various packing + direction combinations. + + * tests/Makefile.am (noinst_PROGRAMS): Add testmenubars. + 2005-02-11 Matthias Clasen Complete the fix for #165770, Vincent Untz: diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index c3303544dc..37701b0115 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,52 @@ +2005-02-11 Matthias Clasen + + Support vertical menubars (#166632): + + * gtk/gtkenums.h (GtkPackDirection): New enumeration for pack + directions, with values for left-to-right, right-to-left, + top-to-bottom and bottom-to-top. + + * gtk/gtk.symbols: + * gtk/gtkmenubar.h: + * gtk/gtkmenubar.c: Add two properties, pack-direction and + child-pack-direction, which specify how children and + grandchildren of a menubar are packed, with getters and setters. + + * gtk/gtkmenubar.c (gtk_menu_bar_set_property): + (gtk_menu_bar_get_property): Implement set_property and get_property. + + * gtk/gtkmenubar.c (gtk_menu_bar_size_request): + (gtk_menu_bar_size_allocate): Take pack direction into account. + + * gtk/gtkmenubar.c (gtk_menu_bar_move_current): Implement + move_current here move all the menubar-specific direction + tweaking from the generic menushell implementation here. + + * gtk/gtkmenu.c (gtk_menu_move_current): Move menu-specific + direction tweaking from the generic menushell implementation here. + + * gtk/gtkmenuitem.c (gtk_menu_item_size_request): + (gtk_menu_bar_size_allocate): Take pack direction into account. + + * gtk/gtkimagemenuitem.c (gtk_image_menu_item_size_request) + (gtk_image_menu_item_size_allocate): + (gtk_image_menu_item_toggle_size_request): Take child pack + direction into account and pack the image vertically if + necessary. + + * gtk/gtkmenushell.c (gtk_menu_shell_real_select_item): + Set the submenu direction to left-right for menuitems in + vertical menubars. + (gtk_real_menu_shell_move_current): Simplify by moving + direction tweaking to menu- and menubar-specific + implementations. Take pack direction into account when + doing fallbacks. + + * tests/testmenubars.c: Test menubars in various packing + direction combinations. + + * tests/Makefile.am (noinst_PROGRAMS): Add testmenubars. + 2005-02-11 Matthias Clasen Complete the fix for #165770, Vincent Untz: diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index c3303544dc..37701b0115 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,52 @@ +2005-02-11 Matthias Clasen + + Support vertical menubars (#166632): + + * gtk/gtkenums.h (GtkPackDirection): New enumeration for pack + directions, with values for left-to-right, right-to-left, + top-to-bottom and bottom-to-top. + + * gtk/gtk.symbols: + * gtk/gtkmenubar.h: + * gtk/gtkmenubar.c: Add two properties, pack-direction and + child-pack-direction, which specify how children and + grandchildren of a menubar are packed, with getters and setters. + + * gtk/gtkmenubar.c (gtk_menu_bar_set_property): + (gtk_menu_bar_get_property): Implement set_property and get_property. + + * gtk/gtkmenubar.c (gtk_menu_bar_size_request): + (gtk_menu_bar_size_allocate): Take pack direction into account. + + * gtk/gtkmenubar.c (gtk_menu_bar_move_current): Implement + move_current here move all the menubar-specific direction + tweaking from the generic menushell implementation here. + + * gtk/gtkmenu.c (gtk_menu_move_current): Move menu-specific + direction tweaking from the generic menushell implementation here. + + * gtk/gtkmenuitem.c (gtk_menu_item_size_request): + (gtk_menu_bar_size_allocate): Take pack direction into account. + + * gtk/gtkimagemenuitem.c (gtk_image_menu_item_size_request) + (gtk_image_menu_item_size_allocate): + (gtk_image_menu_item_toggle_size_request): Take child pack + direction into account and pack the image vertically if + necessary. + + * gtk/gtkmenushell.c (gtk_menu_shell_real_select_item): + Set the submenu direction to left-right for menuitems in + vertical menubars. + (gtk_real_menu_shell_move_current): Simplify by moving + direction tweaking to menu- and menubar-specific + implementations. Take pack direction into account when + doing fallbacks. + + * tests/testmenubars.c: Test menubars in various packing + direction combinations. + + * tests/Makefile.am (noinst_PROGRAMS): Add testmenubars. + 2005-02-11 Matthias Clasen Complete the fix for #165770, Vincent Untz: diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index ae018f88f7..2b9e03d4fb 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,8 @@ +2005-02-11 Matthias Clasen + + * gtk/gtk-sections.txt: Add GtkPackDirection and + related functions. + 2005-02-08 Matthias Clasen * gtk/tmpl/gtkuimanager.sgml: Mention the expanding diff --git a/docs/reference/gtk/gtk-sections.txt b/docs/reference/gtk/gtk-sections.txt index 67d90fcd69..a30075c96b 100644 --- a/docs/reference/gtk/gtk-sections.txt +++ b/docs/reference/gtk/gtk-sections.txt @@ -2100,6 +2100,11 @@ gtk_menu_bar_new gtk_menu_bar_append gtk_menu_bar_prepend gtk_menu_bar_insert +GtkPackDirection +gtk_menu_bar_set_pack_direction +gtk_menu_bar_get_pack_direction +gtk_menu_bar_set_child_pack_direction +gtk_menu_bar_get_child_pack_direction GTK_MENU_BAR GTK_IS_MENU_BAR diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index bd5c90e63b..9e1011e5c2 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -1452,8 +1452,12 @@ gtk_marshal_VOID__UINT_STRING gtk_match_type_get_type G_GNUC_CONST gtk_menu_attach gtk_menu_attach_to_widget +gtk_menu_bar_get_child_pack_direction +gtk_menu_bar_get_pack_direction gtk_menu_bar_get_type G_GNUC_CONST gtk_menu_bar_new +gtk_menu_bar_set_child_pack_direction +gtk_menu_bar_set_pack_direction gtk_menu_detach gtk_menu_direction_type_get_type G_GNUC_CONST gtk_menu_get_accel_group diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h index f8c0fab048..b55d31cd75 100644 --- a/gtk/gtkenums.h +++ b/gtk/gtkenums.h @@ -29,10 +29,7 @@ #include -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - +G_BEGIN_DECLS /* Anchor types */ typedef enum @@ -453,9 +450,14 @@ typedef enum GTK_IM_STATUS_NONE } GtkIMStatusStyle; -#ifdef __cplusplus -} -#endif /* __cplusplus */ +typedef enum +{ + GTK_PACK_DIRECTION_LTR, + GTK_PACK_DIRECTION_RTL, + GTK_PACK_DIRECTION_TTB, + GTK_PACK_DIRECTION_BTT +} GtkPackDirection; +G_END_DECLS #endif /* __GTK_ENUMS_H__ */ diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c index 0595301d59..c34a408f76 100644 --- a/gtk/gtkmenu.c +++ b/gtk/gtkmenu.c @@ -4068,15 +4068,27 @@ gtk_menu_move_current (GtkMenuShell *menu_shell, GtkMenuDirectionType direction) { GtkMenu *menu = GTK_MENU (menu_shell); + gint i; + guint l, r, t, b; + GtkWidget *match = NULL; + + if (gtk_widget_get_direction (GTK_WIDGET (menu_shell)) == GTK_TEXT_DIR_RTL) + { + switch (direction) + { + case GTK_MENU_DIR_CHILD: + direction = GTK_MENU_DIR_PARENT; + break; + case GTK_MENU_DIR_PARENT: + direction = GTK_MENU_DIR_CHILD; + break; + default: ; + } + } /* use special table menu key bindings */ if (menu_shell->active_menu_item && gtk_menu_get_n_columns (menu) > 1) { - int i; - guint l, r, t, b; - gboolean rtl = (gtk_widget_get_direction (GTK_WIDGET (menu_shell)) == GTK_TEXT_DIR_RTL); - GtkWidget *match = NULL; - get_effective_child_attach (menu_shell->active_menu_item, &l, &r, &t, &b); if (direction == GTK_MENU_DIR_NEXT) @@ -4121,8 +4133,7 @@ gtk_menu_move_current (GtkMenuShell *menu_shell, } } } - else if ((!rtl && direction == GTK_MENU_DIR_PARENT) - || (rtl && direction == GTK_MENU_DIR_CHILD)) + else if (direction == GTK_MENU_DIR_PARENT) { /* we go one left if possible */ if (l > 0) @@ -4137,8 +4148,7 @@ gtk_menu_move_current (GtkMenuShell *menu_shell, match = menu_shell->active_menu_item; } } - else if ((!rtl && direction == GTK_MENU_DIR_CHILD) - || (rtl && direction == GTK_MENU_DIR_PARENT)) + else if (direction == GTK_MENU_DIR_CHILD) { /* we go one right if possible */ if (r < gtk_menu_get_n_columns (menu)) diff --git a/gtk/gtkmenubar.c b/gtk/gtkmenubar.c index 7c588d1e38..102fb126a8 100644 --- a/gtk/gtkmenubar.c +++ b/gtk/gtkmenubar.c @@ -42,7 +42,33 @@ #define BORDER_SPACING 0 #define DEFAULT_IPADDING 1 +/* Properties */ +enum { + PROP_0, + PROP_PACK_DIRECTION, + PROP_CHILD_PACK_DIRECTION +}; + +typedef struct _GtkMenuBarPrivate GtkMenuBarPrivate; +struct _GtkMenuBarPrivate +{ + GtkPackDirection pack_direction; + GtkPackDirection child_pack_direction; +}; + +#define GTK_MENU_BAR_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_MENU_BAR, GtkMenuBarPrivate)) + + static void gtk_menu_bar_class_init (GtkMenuBarClass *klass); +static void gtk_menu_bar_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_menu_bar_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); static void gtk_menu_bar_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gtk_menu_bar_size_allocate (GtkWidget *widget, @@ -53,7 +79,9 @@ static gint gtk_menu_bar_expose (GtkWidget *widget, GdkEventExpose *event); static void gtk_menu_bar_hierarchy_changed (GtkWidget *widget, GtkWidget *old_toplevel); -static gint gtk_menu_bar_get_popup_delay (GtkMenuShell *menu_shell); +static gint gtk_menu_bar_get_popup_delay (GtkMenuShell *menu_shell); +static void gtk_menu_bar_move_current (GtkMenuShell *menu_shell, + GtkMenuDirectionType direction); static GtkShadowType get_shadow_type (GtkMenuBar *menubar); @@ -90,6 +118,7 @@ gtk_menu_bar_get_type (void) static void gtk_menu_bar_class_init (GtkMenuBarClass *class) { + GObjectClass *gobject_class; GtkObjectClass *object_class; GtkWidgetClass *widget_class; GtkMenuShellClass *menu_shell_class; @@ -98,10 +127,14 @@ gtk_menu_bar_class_init (GtkMenuBarClass *class) parent_class = g_type_class_peek_parent (class); + gobject_class = (GObjectClass*) class; object_class = (GtkObjectClass*) class; widget_class = (GtkWidgetClass*) class; menu_shell_class = (GtkMenuShellClass*) class; + gobject_class->get_property = gtk_menu_bar_get_property; + gobject_class->set_property = gtk_menu_bar_set_property; + widget_class->size_request = gtk_menu_bar_size_request; widget_class->size_allocate = gtk_menu_bar_size_allocate; widget_class->expose_event = gtk_menu_bar_expose; @@ -109,6 +142,7 @@ gtk_menu_bar_class_init (GtkMenuBarClass *class) menu_shell_class->submenu_placement = GTK_TOP_BOTTOM; menu_shell_class->get_popup_delay = gtk_menu_bar_get_popup_delay; + menu_shell_class->move_current = gtk_menu_bar_move_current; binding_set = gtk_binding_set_by_class (class); gtk_binding_entry_add_signal (binding_set, @@ -152,6 +186,41 @@ gtk_menu_bar_class_init (GtkMenuBarClass *class) GTK_TYPE_MENU_DIRECTION_TYPE, GTK_MENU_DIR_CHILD); + /** + * GtkMenuBar:pack-direction: + * + * The pack direction of the menubar. It determines how + * menuitems are arranged in the menubar. + * + * Since: 2.8 + */ + g_object_class_install_property (gobject_class, + PROP_PACK_DIRECTION, + g_param_spec_enum ("pack_direction", + P_("Pack direction"), + P_("The pack direction of the menubar"), + GTK_TYPE_PACK_DIRECTION, + GTK_PACK_DIRECTION_LTR, + G_PARAM_READWRITE)); + + /** + * GtkMenuBar:child-pack-direction: + * + * The pack direction of the menubar. It determines how + * the widgets contained in child menuitems are arranged. + * + * Since: 2.8 + */ + g_object_class_install_property (gobject_class, + PROP_CHILD_PACK_DIRECTION, + g_param_spec_enum ("child_pack_direction", + P_("Child Pack direction"), + P_("The child pack direction of the menubar"), + GTK_TYPE_PACK_DIRECTION, + GTK_PACK_DIRECTION_LTR, + G_PARAM_READWRITE)); + + gtk_widget_class_install_style_property (widget_class, g_param_spec_enum ("shadow_type", P_("Shadow type"), @@ -176,6 +245,8 @@ gtk_menu_bar_class_init (GtkMenuBarClass *class) G_MAXINT, 0, G_PARAM_READWRITE)); + + g_type_class_add_private (gobject_class, sizeof (GtkMenuBarPrivate)); } GtkWidget* @@ -184,11 +255,56 @@ gtk_menu_bar_new (void) return g_object_new (GTK_TYPE_MENU_BAR, NULL); } +static void +gtk_menu_bar_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkMenuBar *menubar = GTK_MENU_BAR (object); + + switch (prop_id) + { + case PROP_PACK_DIRECTION: + gtk_menu_bar_set_pack_direction (menubar, g_value_get_enum (value)); + break; + case PROP_CHILD_PACK_DIRECTION: + gtk_menu_bar_set_child_pack_direction (menubar, g_value_get_enum (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gtk_menu_bar_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkMenuBar *menubar = GTK_MENU_BAR (object); + + switch (prop_id) + { + case PROP_PACK_DIRECTION: + g_value_set_enum (value, gtk_menu_bar_get_pack_direction (menubar)); + break; + case PROP_CHILD_PACK_DIRECTION: + g_value_set_enum (value, gtk_menu_bar_get_child_pack_direction (menubar)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + static void gtk_menu_bar_size_request (GtkWidget *widget, GtkRequisition *requisition) { GtkMenuBar *menu_bar; + GtkMenuBarPrivate *priv; GtkMenuShell *menu_shell; GtkWidget *child; GList *children; @@ -206,6 +322,7 @@ gtk_menu_bar_size_request (GtkWidget *widget, { menu_bar = GTK_MENU_BAR (widget); menu_shell = GTK_MENU_SHELL (widget); + priv = GTK_MENU_BAR_GET_PRIVATE (menu_bar); nchildren = 0; children = menu_shell->children; @@ -218,16 +335,29 @@ gtk_menu_bar_size_request (GtkWidget *widget, if (GTK_WIDGET_VISIBLE (child)) { gint toggle_size; - + GTK_MENU_ITEM (child)->show_submenu_indicator = FALSE; gtk_widget_size_request (child, &child_requisition); gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child), &toggle_size); - - requisition->width += child_requisition.width; - requisition->width += toggle_size; - - requisition->height = MAX (requisition->height, child_requisition.height); + + if (priv->child_pack_direction == GTK_PACK_DIRECTION_LTR || + priv->child_pack_direction == GTK_PACK_DIRECTION_RTL) + child_requisition.width += toggle_size; + else + child_requisition.height += toggle_size; + + if (priv->pack_direction == GTK_PACK_DIRECTION_LTR || + priv->pack_direction == GTK_PACK_DIRECTION_RTL) + { + requisition->width += child_requisition.width; + requisition->height = MAX (requisition->height, child_requisition.height); + } + else + { + requisition->width = MAX (requisition->width, child_requisition.width); + requisition->height += child_requisition.height; + } nchildren += 1; } } @@ -255,13 +385,14 @@ gtk_menu_bar_size_allocate (GtkWidget *widget, { GtkMenuBar *menu_bar; GtkMenuShell *menu_shell; + GtkMenuBarPrivate *priv; GtkWidget *child; GList *children; GtkAllocation child_allocation; GtkRequisition child_requisition; guint offset; GtkTextDirection direction; - gint ltr_x; + gint ltr_x, ltr_y; gint ipadding; g_return_if_fail (GTK_IS_MENU_BAR (widget)); @@ -269,6 +400,7 @@ gtk_menu_bar_size_allocate (GtkWidget *widget, menu_bar = GTK_MENU_BAR (widget); menu_shell = GTK_MENU_SHELL (widget); + priv = GTK_MENU_BAR_GET_PRIVATE (menu_bar); direction = gtk_widget_get_direction (widget); @@ -287,54 +419,112 @@ gtk_menu_bar_size_allocate (GtkWidget *widget, BORDER_SPACING); child_allocation.y = (GTK_CONTAINER (menu_bar)->border_width + BORDER_SPACING); - + if (get_shadow_type (menu_bar) != GTK_SHADOW_NONE) { child_allocation.x += widget->style->xthickness; child_allocation.y += widget->style->ythickness; } - child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2); - - offset = child_allocation.x; /* Window edge to menubar start */ - ltr_x = child_allocation.x; - - children = menu_shell->children; - while (children) + if (priv->pack_direction == GTK_PACK_DIRECTION_LTR || + priv->pack_direction == GTK_PACK_DIRECTION_RTL) { - gint toggle_size; - - child = children->data; - children = children->next; - - gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child), - &toggle_size); - gtk_widget_get_child_requisition (child, &child_requisition); - - child_requisition.width += toggle_size; - - /* Support for the right justified help menu */ - if ((children == NULL) && (GTK_IS_MENU_ITEM(child)) - && (GTK_MENU_ITEM(child)->right_justify)) + child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2); + + offset = child_allocation.x; /* Window edge to menubar start */ + ltr_x = child_allocation.x; + + children = menu_shell->children; + while (children) { - ltr_x = allocation->width - - child_requisition.width - offset; - } - if (GTK_WIDGET_VISIBLE (child)) - { - if (direction == GTK_TEXT_DIR_LTR) - child_allocation.x = ltr_x; + gint toggle_size; + + child = children->data; + children = children->next; + + gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child), + &toggle_size); + gtk_widget_get_child_requisition (child, &child_requisition); + + if (priv->child_pack_direction == GTK_PACK_DIRECTION_LTR || + priv->child_pack_direction == GTK_PACK_DIRECTION_RTL) + child_requisition.width += toggle_size; else - child_allocation.x = allocation->width - - child_requisition.width - ltr_x; - - child_allocation.width = child_requisition.width; - - gtk_menu_item_toggle_size_allocate (GTK_MENU_ITEM (child), - toggle_size); - gtk_widget_size_allocate (child, &child_allocation); - - ltr_x += child_allocation.width; + child_requisition.height += toggle_size; + + /* Support for the right justified help menu */ + if ((children == NULL) && (GTK_IS_MENU_ITEM(child)) + && (GTK_MENU_ITEM(child)->right_justify)) + { + ltr_x = allocation->width - + child_requisition.width - offset; + } + if (GTK_WIDGET_VISIBLE (child)) + { + if ((direction == GTK_TEXT_DIR_LTR) == (priv->pack_direction == GTK_PACK_DIRECTION_LTR)) + child_allocation.x = ltr_x; + else + child_allocation.x = allocation->width - + child_requisition.width - ltr_x; + + child_allocation.width = child_requisition.width; + + gtk_menu_item_toggle_size_allocate (GTK_MENU_ITEM (child), + toggle_size); + gtk_widget_size_allocate (child, &child_allocation); + + ltr_x += child_allocation.width; + } + } + } + else + { + child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2); + + offset = child_allocation.y; /* Window edge to menubar start */ + ltr_y = child_allocation.y; + + children = menu_shell->children; + while (children) + { + gint toggle_size; + + child = children->data; + children = children->next; + + gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child), + &toggle_size); + gtk_widget_get_child_requisition (child, &child_requisition); + + if (priv->child_pack_direction == GTK_PACK_DIRECTION_LTR || + priv->child_pack_direction == GTK_PACK_DIRECTION_RTL) + child_requisition.width += toggle_size; + else + child_requisition.height += toggle_size; + + /* Support for the right justified help menu */ + if ((children == NULL) && (GTK_IS_MENU_ITEM(child)) + && (GTK_MENU_ITEM(child)->right_justify)) + { + ltr_y = allocation->height - + child_requisition.height - offset; + } + if (GTK_WIDGET_VISIBLE (child)) + { + if ((direction == GTK_TEXT_DIR_LTR) == + (priv->pack_direction == GTK_PACK_DIRECTION_TTB)) + child_allocation.y = ltr_y; + else + child_allocation.y = allocation->height - + child_requisition.height - ltr_y; + child_allocation.height = child_requisition.height; + + gtk_menu_item_toggle_size_allocate (GTK_MENU_ITEM (child), + toggle_size); + gtk_widget_size_allocate (child, &child_allocation); + + ltr_y += child_allocation.height; + } } } } @@ -601,3 +791,167 @@ gtk_menu_bar_get_popup_delay (GtkMenuShell *menu_shell) return popup_delay; } + +static void +gtk_menu_bar_move_current (GtkMenuShell *menu_shell, + GtkMenuDirectionType direction) +{ + GtkMenuBar *menubar = GTK_MENU_BAR (menu_shell); + GtkTextDirection text_dir; + GtkPackDirection pack_dir; + + text_dir = gtk_widget_get_direction (GTK_WIDGET (menubar)); + pack_dir = gtk_menu_bar_get_pack_direction (menubar); + + if (pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) + { + if ((text_dir == GTK_TEXT_DIR_RTL) == (pack_dir == GTK_PACK_DIRECTION_LTR)) + { + switch (direction) + { + case GTK_MENU_DIR_PREV: + direction = GTK_MENU_DIR_NEXT; + break; + case GTK_MENU_DIR_NEXT: + direction = GTK_MENU_DIR_PREV; + break; + default: ; + } + } + } + else + { + switch (direction) + { + case GTK_MENU_DIR_PARENT: + if ((text_dir == GTK_TEXT_DIR_LTR) == (pack_dir == GTK_PACK_DIRECTION_TTB)) + direction = GTK_MENU_DIR_PREV; + else + direction = GTK_MENU_DIR_NEXT; + break; + case GTK_MENU_DIR_CHILD: + if ((text_dir == GTK_TEXT_DIR_LTR) == (pack_dir == GTK_PACK_DIRECTION_TTB)) + direction = GTK_MENU_DIR_NEXT; + else + direction = GTK_MENU_DIR_PREV; + break; + case GTK_MENU_DIR_PREV: + if (text_dir == GTK_TEXT_DIR_RTL) + direction = GTK_MENU_DIR_CHILD; + else + direction = GTK_MENU_DIR_PARENT; + break; + case GTK_MENU_DIR_NEXT: + if (text_dir == GTK_TEXT_DIR_RTL) + direction = GTK_MENU_DIR_PARENT; + else + direction = GTK_MENU_DIR_CHILD; + break; + default: ; + } + } + + GTK_MENU_SHELL_CLASS (parent_class)->move_current (menu_shell, direction); +} + +/** + * gtk_menu_bar_get_pack_direction: + * @menubar: a #GtkMenuBar + * + * Retrieves the current pack direction of the menubar. See + * gtk_menu_bar_set_pack_direction(). + * + * Return value: the pack direction + * + * Since: 2.8 + **/ +GtkPackDirection +gtk_menu_bar_get_pack_direction (GtkMenuBar *menubar) +{ + GtkMenuBarPrivate *priv; + + g_return_val_if_fail (GTK_IS_MENU_BAR (menubar), + GTK_PACK_DIRECTION_LTR); + + priv = GTK_MENU_BAR_GET_PRIVATE (menubar); + + return priv->pack_direction; +} + +/** + * gtk_menu_bar_set_pack_direction: + * @menubar: a #GtkMenuBar. + * @pack_dir: a new #GtkPackDirection. + * + * Sets how items should be packed inside a menubar. + * + * Since: 2.8 + **/ +void gtk_menu_bar_set_pack_direction (GtkMenuBar *menubar, + GtkPackDirection pack_dir) +{ + GtkMenuBarPrivate *priv; + + g_return_if_fail (GTK_IS_MENU_BAR (menubar)); + + priv = GTK_MENU_BAR_GET_PRIVATE (menubar); + + if (priv->pack_direction != pack_dir) + { + priv->pack_direction = pack_dir; + + gtk_widget_queue_resize (GTK_WIDGET (menubar)); + g_object_notify (G_OBJECT (menubar), "pack-direction"); + } +} + +/** + * gtk_menu_bar_get_child_pack_direction: + * @menubar: a #GtkMenuBar + * + * Retrieves the current child pack direction of the menubar. See + * gtk_menu_bar_set_child_pack_direction(). + * + * Return value: the child pack direction + * + * Since: 2.8 + **/ +GtkPackDirection +gtk_menu_bar_get_child_pack_direction (GtkMenuBar *menubar) +{ + GtkMenuBarPrivate *priv; + + g_return_val_if_fail (GTK_IS_MENU_BAR (menubar), + GTK_PACK_DIRECTION_LTR); + + priv = GTK_MENU_BAR_GET_PRIVATE (menubar); + + return priv->child_pack_direction; +} + +/** + * gtk_menu_bar_set_child_pack_direction: + * @menubar: a #GtkMenuBar. + * @child_pack_dir: a new #GtkPackDirection. + * + * Sets how widgets should be packed inside the children of a menubar. + * + * Since: 2.8 + **/ +void gtk_menu_bar_set_child_pack_direction (GtkMenuBar *menubar, + GtkPackDirection child_pack_dir) +{ + GtkMenuBarPrivate *priv; + + g_return_if_fail (GTK_IS_MENU_BAR (menubar)); + + priv = GTK_MENU_BAR_GET_PRIVATE (menubar); + + if (priv->child_pack_direction != child_pack_dir) + { + priv->child_pack_direction = child_pack_dir; + + gtk_widget_queue_resize (GTK_WIDGET (menubar)); + g_object_notify (G_OBJECT (menubar), "child-pack-direction"); + } +} diff --git a/gtk/gtkmenubar.h b/gtk/gtkmenubar.h index f7a1831e64..f315c32a2a 100644 --- a/gtk/gtkmenubar.h +++ b/gtk/gtkmenubar.h @@ -44,7 +44,6 @@ extern "C" { #define GTK_IS_MENU_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_MENU_BAR)) #define GTK_MENU_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_MENU_BAR, GtkMenuBarClass)) - typedef struct _GtkMenuBar GtkMenuBar; typedef struct _GtkMenuBarClass GtkMenuBarClass; @@ -68,6 +67,13 @@ struct _GtkMenuBarClass GType gtk_menu_bar_get_type (void) G_GNUC_CONST; GtkWidget* gtk_menu_bar_new (void); +GtkPackDirection gtk_menu_bar_get_pack_direction (GtkMenuBar *menubar); +void gtk_menu_bar_set_pack_direction (GtkMenuBar *menubar, + GtkPackDirection pack_dir); +GtkPackDirection gtk_menu_bar_get_child_pack_direction (GtkMenuBar *menubar); +void gtk_menu_bar_set_child_pack_direction (GtkMenuBar *menubar, + GtkPackDirection child_pack_dir); + #ifndef GTK_DISABLE_DEPRECATED #define gtk_menu_bar_append(menu,child) gtk_menu_shell_append ((GtkMenuShell *)(menu),(child)) #define gtk_menu_bar_prepend(menu,child) gtk_menu_shell_prepend ((GtkMenuShell *)(menu),(child)) diff --git a/gtk/gtkmenuitem.c b/gtk/gtkmenuitem.c index c0b966fa6d..a06ddf4874 100644 --- a/gtk/gtkmenuitem.c +++ b/gtk/gtkmenuitem.c @@ -498,6 +498,8 @@ gtk_menu_item_size_request (GtkWidget *widget, GtkBin *bin; guint accel_width; guint horizontal_padding; + GtkPackDirection pack_dir; + GtkPackDirection child_pack_dir; g_return_if_fail (GTK_IS_MENU_ITEM (widget)); g_return_if_fail (requisition != NULL); @@ -509,11 +511,29 @@ gtk_menu_item_size_request (GtkWidget *widget, bin = GTK_BIN (widget); menu_item = GTK_MENU_ITEM (widget); + if (GTK_IS_MENU_BAR (widget->parent)) + { + pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (widget->parent)); + child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (widget->parent)); + } + else + { + pack_dir = GTK_PACK_DIRECTION_LTR; + child_pack_dir = GTK_PACK_DIRECTION_LTR; + } + requisition->width = (GTK_CONTAINER (widget)->border_width + - widget->style->xthickness + horizontal_padding) * 2; + widget->style->xthickness) * 2; requisition->height = (GTK_CONTAINER (widget)->border_width + widget->style->ythickness) * 2; + if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) && + (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL)) + requisition->width += 2 * horizontal_padding; + else if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) && + (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT)) + requisition->height += 2 * horizontal_padding; + if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) { GtkRequisition child_requisition; @@ -558,6 +578,8 @@ gtk_menu_item_size_allocate (GtkWidget *widget, GtkBin *bin; GtkAllocation child_allocation; GtkTextDirection direction; + GtkPackDirection pack_dir; + GtkPackDirection child_pack_dir; g_return_if_fail (GTK_IS_MENU_ITEM (widget)); g_return_if_fail (allocation != NULL); @@ -567,6 +589,17 @@ gtk_menu_item_size_allocate (GtkWidget *widget, direction = gtk_widget_get_direction (widget); + if (GTK_IS_MENU_BAR (widget->parent)) + { + pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (widget->parent)); + child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (widget->parent)); + } + else + { + pack_dir = GTK_PACK_DIRECTION_LTR; + child_pack_dir = GTK_PACK_DIRECTION_LTR; + } + widget->allocation = *allocation; if (bin->child) @@ -577,17 +610,34 @@ gtk_menu_item_size_allocate (GtkWidget *widget, gtk_widget_style_get (widget, "horizontal_padding", &horizontal_padding, NULL); + + child_allocation.x = GTK_CONTAINER (widget)->border_width + widget->style->xthickness; + child_allocation.y = GTK_CONTAINER (widget)->border_width + widget->style->ythickness; + + if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) && + (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL)) + child_allocation.x += horizontal_padding; + else if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) && + (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT)) + child_allocation.y += horizontal_padding; - child_allocation.x = (GTK_CONTAINER (widget)->border_width + - widget->style->xthickness + - horizontal_padding); - child_allocation.y = (GTK_CONTAINER (widget)->border_width + - widget->style->ythickness); child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2); child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2); - if (direction == GTK_TEXT_DIR_LTR) - child_allocation.x += GTK_MENU_ITEM (widget)->toggle_size; - child_allocation.width -= GTK_MENU_ITEM (widget)->toggle_size; + + if (child_pack_dir == GTK_PACK_DIRECTION_LTR || + child_pack_dir == GTK_PACK_DIRECTION_RTL) + { + if ((direction == GTK_TEXT_DIR_LTR) == (child_pack_dir != GTK_PACK_DIRECTION_RTL)) + child_allocation.x += GTK_MENU_ITEM (widget)->toggle_size; + child_allocation.width -= GTK_MENU_ITEM (widget)->toggle_size; + } + else + { + if ((direction == GTK_TEXT_DIR_LTR) == (child_pack_dir != GTK_PACK_DIRECTION_BTT)) + child_allocation.y += GTK_MENU_ITEM (widget)->toggle_size; + child_allocation.height -= GTK_MENU_ITEM (widget)->toggle_size; + } + child_allocation.x += widget->allocation.x; child_allocation.y += widget->allocation.y; @@ -1103,7 +1153,10 @@ gtk_menu_item_position_menu (GtkMenu *menu, break; case GTK_LEFT_RIGHT: - parent_menu_item = GTK_MENU (widget->parent)->parent_menu_item; + if (GTK_IS_MENU (widget->parent)) + parent_menu_item = GTK_MENU (widget->parent)->parent_menu_item; + else + parent_menu_item = NULL; parent_xthickness = widget->parent->style->xthickness; if (parent_menu_item && !GTK_MENU (widget->parent)->torn_off) menu_item->submenu_direction = GTK_MENU_ITEM (parent_menu_item)->submenu_direction; diff --git a/gtk/gtkmenushell.c b/gtk/gtkmenushell.c index 1c910476c2..248053334a 100644 --- a/gtk/gtkmenushell.c +++ b/gtk/gtkmenushell.c @@ -42,6 +42,11 @@ #define MENU_SHELL_TIMEOUT 500 +#define PACK_DIRECTION(m) \ + (GTK_IS_MENU_BAR (m) \ + ? gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (m)) \ + : GTK_PACK_DIRECTION_LTR) + enum { DEACTIVATE, SELECTION_DONE, @@ -104,6 +109,10 @@ typedef void (*GtkMenuShellSignal2) (GtkObject *object, * - For 'child', if there is no child, then current is * moved to the next item in the parent. * + * Note that the above explanation of ::move_current was written + * before menus and menubars had support for RTL flipping and + * different packing directions, and therefore only applies for + * when text direction and packing direction are both left-to-right. * * ::activate_current (GBoolean *force_hide) * Activate the current item. If 'force_hide' is true, hide @@ -874,14 +883,20 @@ static void gtk_menu_shell_real_select_item (GtkMenuShell *menu_shell, GtkWidget *menu_item) { + GtkPackDirection pack_dir = PACK_DIRECTION (menu_shell); + gtk_menu_shell_deselect (menu_shell); if (!_gtk_menu_item_is_selectable (menu_item)) return; menu_shell->active_menu_item = menu_item; - _gtk_menu_item_set_placement (GTK_MENU_ITEM (menu_shell->active_menu_item), - GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement); + if (pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) + _gtk_menu_item_set_placement (GTK_MENU_ITEM (menu_shell->active_menu_item), + GTK_LEFT_RIGHT); + else + _gtk_menu_item_set_placement (GTK_MENU_ITEM (menu_shell->active_menu_item), + GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement); gtk_menu_item_select (GTK_MENU_ITEM (menu_shell->active_menu_item)); /* This allows the bizarre radio buttons-with-submenus-display-history @@ -1091,31 +1106,7 @@ gtk_real_menu_shell_move_current (GtkMenuShell *menu_shell, if (menu_shell->parent_menu_shell) parent_menu_shell = GTK_MENU_SHELL (menu_shell->parent_menu_shell); - - if (gtk_widget_get_direction (GTK_WIDGET (menu_shell)) == GTK_TEXT_DIR_RTL) - { - switch (direction) - { - case GTK_MENU_DIR_PARENT: - if (GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement != GTK_TOP_BOTTOM) - direction = GTK_MENU_DIR_CHILD; - break; - case GTK_MENU_DIR_CHILD: - if (GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement != GTK_TOP_BOTTOM) - direction = GTK_MENU_DIR_PARENT; - break; - case GTK_MENU_DIR_PREV: - if (GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement == GTK_TOP_BOTTOM) - direction = GTK_MENU_DIR_NEXT; - break; - case GTK_MENU_DIR_NEXT: - if (GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement == GTK_TOP_BOTTOM) - direction = GTK_MENU_DIR_PREV; - break; - default: ; - } - } - + switch (direction) { case GTK_MENU_DIR_PARENT: @@ -1126,7 +1117,10 @@ gtk_real_menu_shell_move_current (GtkMenuShell *menu_shell, gtk_menu_shell_deselect (menu_shell); else { - gtk_menu_shell_move_selected (parent_menu_shell, -1); + if (PACK_DIRECTION (parent_menu_shell) == GTK_PACK_DIRECTION_LTR) + gtk_menu_shell_move_selected (parent_menu_shell, -1); + else + gtk_menu_shell_move_selected (parent_menu_shell, 1); gtk_menu_shell_select_submenu_first (parent_menu_shell); } } @@ -1170,7 +1164,11 @@ gtk_real_menu_shell_move_current (GtkMenuShell *menu_shell, if (parent_menu_shell) { - gtk_menu_shell_move_selected (parent_menu_shell, 1); + if (PACK_DIRECTION (parent_menu_shell) == GTK_PACK_DIRECTION_LTR) + gtk_menu_shell_move_selected (parent_menu_shell, 1); + else + gtk_menu_shell_move_selected (parent_menu_shell, -1); + gtk_menu_shell_select_submenu_first (parent_menu_shell); } break; @@ -1190,7 +1188,6 @@ gtk_real_menu_shell_move_current (GtkMenuShell *menu_shell, gtk_menu_shell_select_first (menu_shell, TRUE); break; } - } static void diff --git a/tests/Makefile.am b/tests/Makefile.am index 56cad51240..ea7a885518 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -43,6 +43,7 @@ noinst_PROGRAMS = \ testimage \ testinput \ testmenus \ + testmenubars \ testmultidisplay \ testmultiscreen \ testrgb \ @@ -86,6 +87,7 @@ testgtk_DEPENDENCIES = $(TEST_DEPS) testinput_DEPENDENCIES = $(TEST_DEPS) testimage_DEPENDENCIES = $(TEST_DEPS) testmenus_DEPENDENCIES = $(TEST_DEPS) +testmenubars_DEPENDENCIES = $(TEST_DEPS) testmultidisplay_DEPENDENCIES = $(TEST_DEPS) testmultiscreen_DEPENDENCIES = $(TEST_DEPS) testrgb_DEPENDENCIES = $(TEST_DEPS) @@ -123,6 +125,7 @@ testiconview_LDADD = $(LDADDS) testinput_LDADD = $(LDADDS) testimage_LDADD = $(LDADDS) testmenus_LDADD = $(LDADDS) +testmenubars_LDADD = $(LDADDS) testmultidisplay_LDADD = $(LDADDS) testmultiscreen_LDADD = $(LDADDS) testrgb_LDADD = $(LDADDS) diff --git a/tests/testmenubars.c b/tests/testmenubars.c new file mode 100644 index 0000000000..741bf4685d --- /dev/null +++ b/tests/testmenubars.c @@ -0,0 +1,170 @@ +/* Menubars + * + * This program tests different packing directions + * of menu bars. + * + * Written by Matthias Clasen + */ + +#include + +static GtkWidget * +create_menu (depth) +{ + GtkWidget *menu; + GtkWidget *menuitem; + + if (depth < 1) + return NULL; + + menu = gtk_menu_new (); + + menuitem = gtk_menu_item_new_with_label ("One"); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + gtk_widget_show (menuitem); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), + create_menu (depth - 1)); + + menuitem = gtk_menu_item_new_with_mnemonic ("Two"); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + gtk_widget_show (menuitem); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), + create_menu (depth - 1)); + + menuitem = gtk_menu_item_new_with_mnemonic ("Three"); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + gtk_widget_show (menuitem); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), + create_menu (depth - 1)); + + return menu; +} + +static GtkWidget* +create_menubar (GtkPackDirection pack_dir, + GtkPackDirection child_pack_dir, + gdouble angle) +{ + GtkWidget *menubar; + GtkWidget *menuitem; + GtkWidget *menu; + + menubar = gtk_menu_bar_new (); + gtk_menu_bar_set_pack_direction (GTK_MENU_BAR (menubar), + pack_dir); + gtk_menu_bar_set_child_pack_direction (GTK_MENU_BAR (menubar), + child_pack_dir); + + menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_HOME, NULL); + gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem); + gtk_label_set_angle (GTK_LABEL (GTK_BIN (menuitem)->child), angle); + menu = create_menu (2, TRUE); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu); + + menuitem = gtk_menu_item_new_with_label ("foo"); + gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem); + gtk_label_set_angle (GTK_LABEL (GTK_BIN (menuitem)->child), angle); + menu = create_menu (2, TRUE); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu); + + menuitem = gtk_menu_item_new_with_label ("bar"); + gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem); + gtk_label_set_angle (GTK_LABEL (GTK_BIN (menuitem)->child), angle); + menu = create_menu (2, TRUE); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu); + + return menubar; +} + +int +main (int argc, char **argv) +{ + static GtkWidget *window = NULL; + GtkWidget *box1; + GtkWidget *box2; + GtkWidget *box3; + GtkWidget *button; + GtkWidget *separator; + + gtk_init (&argc, &argv); + + if (!window) + { + GtkWidget *menubar1; + GtkWidget *menubar2; + GtkWidget *menubar3; + GtkWidget *menubar4; + GtkWidget *menubar5; + GtkWidget *menubar6; + GtkAccelGroup *accel_group; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + + g_signal_connect (window, "destroy", + G_CALLBACK(gtk_main_quit), NULL); + g_signal_connect (window, "delete-event", + G_CALLBACK (gtk_true), NULL); + + accel_group = gtk_accel_group_new (); + gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); + + gtk_window_set_title (GTK_WINDOW (window), "menus"); + gtk_container_set_border_width (GTK_CONTAINER (window), 0); + + box1 = gtk_vbox_new (FALSE, 0); + box2 = gtk_hbox_new (FALSE, 0); + box3 = gtk_vbox_new (FALSE, 0); + + /* Rotation by 0 and 180 degrees is broken in Pango, #166832 */ + menubar1 = create_menubar (GTK_PACK_DIRECTION_LTR, GTK_PACK_DIRECTION_LTR, 0.01); + menubar2 = create_menubar (GTK_PACK_DIRECTION_BTT, GTK_PACK_DIRECTION_BTT, 90); + menubar3 = create_menubar (GTK_PACK_DIRECTION_TTB, GTK_PACK_DIRECTION_TTB, 270); + menubar4 = create_menubar (GTK_PACK_DIRECTION_RTL, GTK_PACK_DIRECTION_RTL, 180.01); + menubar5 = create_menubar (GTK_PACK_DIRECTION_LTR, GTK_PACK_DIRECTION_BTT, 90); + menubar6 = create_menubar (GTK_PACK_DIRECTION_BTT, GTK_PACK_DIRECTION_LTR, 0.01); + + gtk_container_add (GTK_CONTAINER (window), box1); + gtk_box_pack_start (GTK_BOX (box1), menubar1, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (box2), menubar2, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (box2), box3, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (box2), menubar3, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (box1), menubar4, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (box3), menubar5, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (box3), menubar6, TRUE, TRUE, 0); + + gtk_widget_show_all (box1); + + separator = gtk_hseparator_new (); + gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0); + gtk_widget_show (separator); + + box2 = gtk_vbox_new (FALSE, 10); + gtk_container_set_border_width (GTK_CONTAINER (box2), 10); + gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0); + gtk_widget_show (box2); + + button = gtk_button_new_with_label ("close"); + g_signal_connect_swapped (button, "clicked", + G_CALLBACK(gtk_widget_destroy), window); + gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); + GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); + gtk_widget_grab_default (button); + gtk_widget_show (button); + } + + if (!GTK_WIDGET_VISIBLE (window)) + { + gtk_widget_show (window); + } + else + { + gtk_widget_destroy (window); + window = NULL; + } + + gtk_main (); + + return 0; +} +