Index: ChangeLog
===================================================================
--- ChangeLog	(revision 17273)
+++ ChangeLog	(working copy)
@@ -1,3 +1,18 @@
+2007-02-07  Michael Natterer  <mitch@imendio.com>
+
+	Applied patch from Xan Lopez which adds a Center packing style to
+	GtkButtonBox (bug #336159).
+
+	* gtk/gtkenums.h
+	* gtk/gtkvbbox.c
+	* gtk/gtkhbbox.c
+	* gtk/gtkbbox.c: add support for GTK_BUTTONBOX_CENTER.
+
+	* tests/Makefile.am
+	* tests/testbbox.c: new test for button boxes.
+
+	* tests/testgtk.c: show a centered button box in the existing test.
+
 Tue Feb  6 15:53:59 2007  Tim Janik  <timj@imendio.com>
 
 	* gtk/gtktextview.c (gtk_text_view_motion_event):
@@ -7,7 +22,7 @@ Tue Feb  6 15:53:59 2007  Tim Janik  <ti
 	* gtk/gtkvruler.c (gtk_vruler_motion_notify): 
 	* gtk/gtkentry.c (gtk_entry_motion_notify):
 	* gtk/gtktooltip.c (_gtk_tooltip_handle_event):
-	* gtk/gtkhsv.c (gtk_hsv_motion): call gdk_event_request_motions()                              
+	* gtk/gtkhsv.c (gtk_hsv_motion): call gdk_event_request_motions()
 	for new motion events after receiving motion hints.
 
 	* gdk/gdkevents.[hc]: added gdk_event_request_motions().
Index: gtk/gtkvbbox.c
===================================================================
--- gtk/gtkvbbox.c	(revision 17273)
+++ gtk/gtkvbbox.c	(working copy)
@@ -84,7 +84,7 @@ void
 gtk_vbutton_box_set_layout_default (GtkButtonBoxStyle layout)
 {
   g_return_if_fail (layout >= GTK_BUTTONBOX_DEFAULT_STYLE &&
-		    layout <= GTK_BUTTONBOX_END);
+		    layout <= GTK_BUTTONBOX_CENTER);
 
   default_layout_style = layout;
 }
@@ -151,6 +151,7 @@ gtk_vbutton_box_size_request (GtkWidget 
       case GTK_BUTTONBOX_EDGE:
       case GTK_BUTTONBOX_START:
       case GTK_BUTTONBOX_END:
+      case GTK_BUTTONBOX_CENTER:
         requisition->height =
 		nvis_children*child_height + ((nvis_children-1)*spacing);
 	break;
@@ -239,6 +240,16 @@ gtk_vbutton_box_size_allocate (GtkWidget
       - GTK_CONTAINER (box)->border_width;
     secondary_y = allocation->y + GTK_CONTAINER (box)->border_width;
     break;
+  case GTK_BUTTONBOX_CENTER:
+    childspacing = spacing;
+    y = allocation->y + 
+      (allocation->height
+       - (child_height * (nvis_children - n_secondaries)
+	  + spacing * (nvis_children - n_secondaries - 1)))/2
+      + (n_secondaries * child_height + n_secondaries * spacing)/2
+      + GTK_CONTAINER (box)->border_width;
+    secondary_y = allocation->y + GTK_CONTAINER (box)->border_width;
+    break;
   default:
     g_assert_not_reached();
     break;
Index: gtk/gtkhbbox.c
===================================================================
--- gtk/gtkhbbox.c	(revision 17273)
+++ gtk/gtkhbbox.c	(working copy)
@@ -83,7 +83,7 @@ void 
 gtk_hbutton_box_set_layout_default (GtkButtonBoxStyle layout)
 {
   g_return_if_fail (layout >= GTK_BUTTONBOX_DEFAULT_STYLE &&
-		    layout <= GTK_BUTTONBOX_END);
+		    layout <= GTK_BUTTONBOX_CENTER);
 
   default_layout_style = layout;
 }
@@ -148,6 +148,7 @@ gtk_hbutton_box_size_request (GtkWidget 
     case GTK_BUTTONBOX_EDGE:
     case GTK_BUTTONBOX_START:
     case GTK_BUTTONBOX_END:
+    case GTK_BUTTONBOX_CENTER:
       requisition->width = nvis_children*child_width + ((nvis_children-1)*spacing);
       break;
     default:
@@ -235,6 +236,16 @@ gtk_hbutton_box_size_allocate (GtkWidget
       - GTK_CONTAINER (box)->border_width;
     secondary_x = allocation->x + GTK_CONTAINER (box)->border_width;
     break;
+  case GTK_BUTTONBOX_CENTER:
+    childspacing = spacing;
+    x = allocation->x + 
+      (allocation->width
+       - (child_width * (nvis_children - n_secondaries)
+	  + spacing * (nvis_children - n_secondaries - 1)))/2
+      + (n_secondaries * child_width + n_secondaries * spacing)/2
+      + GTK_CONTAINER (box)->border_width;
+    secondary_x = allocation->x + GTK_CONTAINER (box)->border_width;
+    break;
   default:
     g_assert_not_reached();
     break;
Index: gtk/gtkbbox.c
===================================================================
--- gtk/gtkbbox.c	(revision 17273)
+++ gtk/gtkbbox.c	(working copy)
@@ -253,7 +253,7 @@ gtk_button_box_set_layout (GtkButtonBox 
 {
   g_return_if_fail (GTK_IS_BUTTON_BOX (widget));
   g_return_if_fail (layout_style >= GTK_BUTTONBOX_DEFAULT_STYLE &&
-		    layout_style <= GTK_BUTTONBOX_END);
+		    layout_style <= GTK_BUTTONBOX_CENTER);
 
   if (widget->layout_style != layout_style)
     {
Index: gtk/gtkenums.h
===================================================================
--- gtk/gtkenums.h	(revision 17273)
+++ gtk/gtkenums.h	(working copy)
@@ -78,7 +78,8 @@ typedef enum 
   GTK_BUTTONBOX_SPREAD,
   GTK_BUTTONBOX_EDGE,
   GTK_BUTTONBOX_START,
-  GTK_BUTTONBOX_END
+  GTK_BUTTONBOX_END,
+  GTK_BUTTONBOX_CENTER
 } GtkButtonBoxStyle;
 
 /* Curve types */
Index: tests/Makefile.am
===================================================================
--- tests/Makefile.am	(revision 17273)
+++ tests/Makefile.am	(working copy)
@@ -33,6 +33,7 @@ noinst_PROGRAMS =			\
 	print-editor			\
 	testaccel			\
 	testassistant			\
+	testbbox			\
 	testcairo			\
 	testcalendar			\
 	testcombo			\
@@ -93,6 +94,7 @@ testicontheme_DEPENDENCIES = $(TEST_DEPS
 testiconview_DEPENDENCIES = $(TEST_DEPS)
 testaccel_DEPENDENCIES = $(TEST_DEPS)
 testassistant_DEPENDENCIES = $(TEST_DEPS)
+testbbox_DEPENDENCIES = $(TEST_DEPS)
 testcairo_DEPENDENCIES = $(TEST_DEPS)
 testcalendar_DEPENDENCIES = $(TEST_DEPS)
 testcombo_DEPENDENCIES = $(TEST_DEPS)
@@ -143,6 +145,7 @@ floatingtest_LDADD = $(LDADDS)
 print_editor_LDADD = $(LDADDS)
 testaccel_LDADD = $(LDADDS)
 testassistant_LDADD = $(LDADDS)
+testbbox_LDADD = $(LDADDS)
 testcairo_LDADD = $(LDADDS)
 testcalendar_LDADD = $(LDADDS)
 testcombo_LDADD = $(LDADDS)
@@ -259,6 +262,9 @@ testmerge_SOURCES = 		\
 testactions_SOURCES = 		\
 	testactions.c
 
+testbbox_SOURCES = 		\
+	testbbox.c
+
 testiconview_SOURCES = 		\
 	testiconview.c		\
 	prop-editor.c
Index: tests/testgtk.c
===================================================================
--- tests/testgtk.c	(revision 17273)
+++ tests/testgtk.c	(working copy)
@@ -1150,6 +1150,10 @@ create_button_box (GtkWidget *widget)
 	   create_bbox (TRUE, "End", 40, 85, 20, GTK_BUTTONBOX_END),
 			TRUE, TRUE, 5);
 
+    gtk_box_pack_start (GTK_BOX (vbox),
+	   create_bbox (TRUE, "Center", 40, 85, 20, GTK_BUTTONBOX_CENTER),
+			TRUE, TRUE, 5);
+
     frame_vert = gtk_frame_new ("Vertical Button Boxes");
     gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10);
     
@@ -1172,6 +1176,10 @@ create_button_box (GtkWidget *widget)
     gtk_box_pack_start (GTK_BOX (hbox), 
 	   create_bbox (FALSE, "End", 30, 85, 20, GTK_BUTTONBOX_END),
 			TRUE, TRUE, 5);
+
+    gtk_box_pack_start (GTK_BOX (hbox),
+	   create_bbox (FALSE, "Center", 30, 85, 20, GTK_BUTTONBOX_CENTER),
+			TRUE, TRUE, 5);
   }
 
   if (!GTK_WIDGET_VISIBLE (window))
Index: tests/testbbox.c
===================================================================
--- tests/testbbox.c	(revision 0)
+++ tests/testbbox.c	(revision 0)
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2006 Nokia Corporation.
+ * Author: Xan Lopez <xan.lopez@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <gtk/gtk.h>
+
+#define N_BUTTONS 3
+
+GtkWidget *bbox = NULL;
+GtkWidget *hbbox = NULL, *vbbox = NULL;
+
+static const char* styles[] = { "GTK_BUTTONBOX_DEFAULT_STYLE",
+				"GTK_BUTTONBOX_SPREAD",
+				"GTK_BUTTONBOX_EDGE",
+				"GTK_BUTTONBOX_START",
+				"GTK_BUTTONBOX_END",
+				"GTK_BUTTONBOX_CENTER",
+				NULL};
+
+static const char* types[] = { "GtkHButtonBox",
+			       "GtkVButtonBox",
+			       NULL};
+
+static void
+populate_combo_with (GtkComboBox *combo, const char** elements)
+{
+  int i;
+
+  for (i = 0; elements[i] != NULL; i++) {
+    gtk_combo_box_append_text (combo, elements[i]);
+  }
+
+  gtk_combo_box_set_active (combo, 0);
+}
+
+static void
+combo_changed_cb (GtkComboBox *combo,
+		  gpointer user_data)
+{
+  char *text;
+  int i;
+
+  text = gtk_combo_box_get_active_text (combo);
+
+  for (i = 0; styles[i]; i++) {
+    if (g_str_equal (text, styles[i])) {
+      gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), (GtkButtonBoxStyle)i);
+    }
+  }
+}
+
+static void
+reparent_widget (GtkWidget *widget,
+		 GtkWidget *old_parent,
+		 GtkWidget *new_parent)
+{
+  gtk_widget_ref (widget);
+  gtk_container_remove (GTK_CONTAINER (old_parent), widget);
+  gtk_container_add (GTK_CONTAINER (new_parent), widget);
+  gtk_widget_unref (widget);
+}
+
+static void
+combo_types_changed_cb (GtkComboBox *combo,
+			GtkWidget **buttons)
+{
+  int i;
+  char *text;
+  GtkWidget *old_parent, *new_parent;
+  GtkButtonBoxStyle style;
+
+  text = gtk_combo_box_get_active_text (combo);
+
+  if (g_str_equal (text, "GtkHButtonBox")) {
+    old_parent = vbbox;
+    new_parent = hbbox;
+  } else {
+    old_parent = hbbox;
+    new_parent = vbbox;
+  }
+
+  bbox = new_parent;
+
+  for (i = 0; i < N_BUTTONS; i++) {
+    reparent_widget (buttons[i], old_parent, new_parent);
+  }
+
+  gtk_widget_hide (old_parent);
+  style = gtk_button_box_get_layout (GTK_BUTTON_BOX (old_parent));
+  gtk_button_box_set_layout (GTK_BUTTON_BOX (new_parent), style);
+  gtk_widget_show (new_parent);
+}
+
+static void
+option_cb (GtkToggleButton *option,
+	   GtkWidget *button)
+{
+  gboolean active = gtk_toggle_button_get_active (option);
+
+  gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (bbox),
+				      button, active);
+}
+
+static const char* strings[] = { "Ok", "Cancel", "Help" };
+
+int main (int argc, char **argv)
+{
+  GtkWidget *window, *buttons[N_BUTTONS];
+  GtkWidget *vbox, *hbox, *combo_styles, *combo_types, *option;
+  int i;
+
+  gtk_init (&argc, &argv);
+
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  g_signal_connect (G_OBJECT (window), "delete-event", G_CALLBACK (gtk_main_quit), NULL);
+
+  vbox = gtk_vbox_new (FALSE, 0);
+  gtk_container_add (GTK_CONTAINER (window), vbox);
+
+  /* GtkHButtonBox */
+
+  hbbox = gtk_hbutton_box_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), hbbox, TRUE, TRUE, 5);
+
+  for (i = 0; i < N_BUTTONS; i++) {
+    buttons[i] = gtk_button_new_with_label (strings[i]);
+    gtk_container_add (GTK_CONTAINER (hbbox), buttons[i]);
+  }
+
+  bbox = hbbox;
+
+  /* GtkVButtonBox */
+  vbbox = gtk_vbutton_box_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), vbbox, TRUE, TRUE, 5);
+
+  /* Options */
+
+  hbox = gtk_hbox_new (FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+  combo_types = gtk_combo_box_new_text ();
+  populate_combo_with (GTK_COMBO_BOX (combo_types), types);
+  g_signal_connect (G_OBJECT (combo_types), "changed", G_CALLBACK (combo_types_changed_cb), buttons);
+  gtk_box_pack_start (GTK_BOX (hbox), combo_types, TRUE, TRUE, 0);
+
+  combo_styles = gtk_combo_box_new_text ();
+  populate_combo_with (GTK_COMBO_BOX (combo_styles), styles);
+  g_signal_connect (G_OBJECT (combo_styles), "changed", G_CALLBACK (combo_changed_cb), NULL);
+  gtk_box_pack_start (GTK_BOX (hbox), combo_styles, TRUE, TRUE, 0);
+
+  option = gtk_check_button_new_with_label ("Help is secondary");
+  g_signal_connect (G_OBJECT (option), "toggled", G_CALLBACK (option_cb), buttons[N_BUTTONS - 1]);
+
+  gtk_box_pack_start (GTK_BOX (hbox), option, FALSE, FALSE, 0);
+
+  gtk_widget_show_all (window);
+  gtk_widget_hide (vbbox);
+
+  gtk_main ();
+
+  return 0;
+}
