]> Pileus Git - ~andy/gtk/commitdiff
Support vertical menubars (#166632):
authorMatthias Clasen <mclasen@redhat.com>
Fri, 11 Feb 2005 07:15:11 +0000 (07:15 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Fri, 11 Feb 2005 07:15:11 +0000 (07:15 +0000)
2005-02-11  Matthias Clasen  <mclasen@redhat.com>

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.

14 files changed:
ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-8
docs/reference/ChangeLog
docs/reference/gtk/gtk-sections.txt
gtk/gtk.symbols
gtk/gtkenums.h
gtk/gtkmenu.c
gtk/gtkmenubar.c
gtk/gtkmenubar.h
gtk/gtkmenuitem.c
gtk/gtkmenushell.c
tests/Makefile.am
tests/testmenubars.c [new file with mode: 0644]

index c3303544dcd3d526cce3775f4c71dd962edf2c2e..37701b0115b3d2b1408be1f65ee21d0eafa88eab 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,52 @@
+2005-02-11  Matthias Clasen  <mclasen@redhat.com>
+
+       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  <mclasen@redhat.com>
 
        Complete the fix for #165770, Vincent Untz:
index c3303544dcd3d526cce3775f4c71dd962edf2c2e..37701b0115b3d2b1408be1f65ee21d0eafa88eab 100644 (file)
@@ -1,3 +1,52 @@
+2005-02-11  Matthias Clasen  <mclasen@redhat.com>
+
+       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  <mclasen@redhat.com>
 
        Complete the fix for #165770, Vincent Untz:
index c3303544dcd3d526cce3775f4c71dd962edf2c2e..37701b0115b3d2b1408be1f65ee21d0eafa88eab 100644 (file)
@@ -1,3 +1,52 @@
+2005-02-11  Matthias Clasen  <mclasen@redhat.com>
+
+       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  <mclasen@redhat.com>
 
        Complete the fix for #165770, Vincent Untz:
index ae018f88f772bd1b74c6a228479fcb2fb992f6be..2b9e03d4fb2c4bb7cae49f11ea6e3f732ba5b5a0 100644 (file)
@@ -1,3 +1,8 @@
+2005-02-11  Matthias Clasen  <mclasen@redhat.com>
+
+       * gtk/gtk-sections.txt: Add GtkPackDirection and 
+       related functions.
+
 2005-02-08  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/tmpl/gtkuimanager.sgml: Mention the expanding
index 67d90fcd69fe60c65e40c8b079d8991bc604b1b4..a30075c96b6956492ba327e406276fcbe4567769 100644 (file)
@@ -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
 <SUBSECTION Standard>
 GTK_MENU_BAR
 GTK_IS_MENU_BAR
index bd5c90e63b0556b48794ab50b8343fa89d686e1b..9e1011e5c2bdba852015ad66b0971cc34b478110 100644 (file)
@@ -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
index f8c0fab0486d4f52dd6b7df518ef1c7654dd4fd7..b55d31cd75007d03cc590dda429fdd5304631979 100644 (file)
 
 #include <glib-object.h>
 
-#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__ */
index 0595301d5978d7db4582909f4bc7434cb3eada02..c34a408f76c0139fd41b3c82d20c2389b79735a3 100644 (file)
@@ -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))
index 7c588d1e38dd2641dd40adbe75eb6f0364a8d3a4..102fb126a8f0dc8c5b85b522d862e8b11a7b3f63 100644 (file)
 #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;
+             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_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;
+               }
            }
-         if (GTK_WIDGET_VISIBLE (child))
+       }
+      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)
            {
-             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_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");
+    }
+}
index f7a1831e64440ac8fff1b5a40416dad88a1aa637..f315c32a2a735ab1548fb2931fff15a6dcdbdc58 100644 (file)
@@ -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))
index c0b966fa6d30a0d9daa2781cd0f65b666cc8312a..a06ddf48747c5d706b877a07436d4c7a098594dc 100644 (file)
@@ -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;
index 1c910476c237e20886d295fe702c86607b7e753c..248053334a425936a2ac6b9f6e20c409d3e93683 100644 (file)
 
 #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
index 56cad512404a436bc50e8d4c02e83740d18a0f92..ea7a8855185f7daf3511b99ef06991866fe0c931 100644 (file)
@@ -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 (file)
index 0000000..741bf46
--- /dev/null
@@ -0,0 +1,170 @@
+/* Menubars
+ *
+ * This program tests different packing directions
+ * of menu bars.
+ *
+ * Written by Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include <gtk/gtk.h>
+
+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;
+}
+