2009-01-09 Ivan N. Zlatev <contact@i-nz.net>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms.Layout / FlowLayout.cs
index 321e3c62a5e7fda2e2023cc9ed9e02fe0966bd2a..df5884c61ae2ccd17d635507cb38c7b89aca5836 100644 (file)
-//\r
-// FlowLayout.cs\r
-//\r
-// Permission is hereby granted, free of charge, to any person obtaining\r
-// a copy of this software and associated documentation files (the\r
-// "Software"), to deal in the Software without restriction, including\r
-// without limitation the rights to use, copy, modify, merge, publish,\r
-// distribute, sublicense, and/or sell copies of the Software, and to\r
-// permit persons to whom the Software is furnished to do so, subject to\r
-// the following conditions:\r
-// \r
-// The above copyright notice and this permission notice shall be\r
-// included in all copies or substantial portions of the Software.\r
-// \r
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
-//\r
-// Copyright (c) 2006 Jonathan Pobst\r
-//\r
-// Authors:\r
-//     Jonathan Pobst (monkey@jpobst.com)\r
-//\r
-\r
-#if NET_2_0\r
-using System;\r
-using System.Collections.Generic;\r
-using System.Drawing;\r
-\r
-namespace System.Windows.Forms.Layout\r
-{\r
-       class FlowLayout : LayoutEngine\r
-       {\r
-               public FlowLayout ()\r
-               {\r
-               }\r
-\r
-               public override void InitLayout (object child, BoundsSpecified specified)\r
-               {\r
-                       base.InitLayout (child, specified);\r
-               }\r
-\r
-               public override bool Layout (object container, LayoutEventArgs args)\r
-               {\r
-                       Control parent = container as Control;\r
-                       FlowLayoutSettings settings = (parent as FlowLayoutPanel).LayoutSettings;\r
-\r
-                       // Nothing to layout, exit method\r
-                       if (parent.Controls.Count == 0) return false;\r
-\r
-                       // Use DisplayRectangle so that parent.Padding is honored.\r
-                       Rectangle parentDisplayRectangle = parent.DisplayRectangle;\r
-                       Point currentLocation;\r
-\r
-                       // Set our starting point based on flow direction\r
-                       switch (settings.FlowDirection) {\r
-                               case FlowDirection.BottomUp:\r
-                                       currentLocation = new Point (parentDisplayRectangle.Left, parentDisplayRectangle.Bottom);\r
-                                       break;\r
-                               case FlowDirection.LeftToRight:\r
-                               case FlowDirection.TopDown:\r
-                               default:\r
-                                       currentLocation = parentDisplayRectangle.Location;\r
-                                       break;\r
-                               case FlowDirection.RightToLeft:\r
-                                       currentLocation = new Point (parentDisplayRectangle.Right, parentDisplayRectangle.Top);\r
-                                       break;\r
-                       }\r
-\r
-                       bool forceFlowBreak = false;\r
-\r
-                       List<Control> rowControls = new List<Control> ();\r
-\r
-                       foreach (Control c in parent.Controls) {\r
-                               // Only apply layout to visible controls.\r
-                               if (!c.Visible) { continue; }\r
-\r
-                               // Resize any AutoSize controls to their preferred size\r
-                               if (c.AutoSize == true)\r
-                                       c.Size = c.GetPreferredSize (c.Size);\r
-\r
-                               switch (settings.FlowDirection) {\r
-                                       case FlowDirection.BottomUp:\r
-                                               // Decide if it's time to start a new column\r
-                                               // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true\r
-                                               if (settings.WrapContents)\r
-                                                       if ((currentLocation.Y) < (c.Height + c.Margin.Top + c.Margin.Bottom) || forceFlowBreak) {\r
-\r
-                                                               currentLocation.X = FinishColumn (rowControls);\r
-                                                               currentLocation.Y = parentDisplayRectangle.Bottom;\r
-\r
-                                                               forceFlowBreak = false;\r
-                                                               rowControls.Clear ();\r
-                                                       }\r
-\r
-                                               // Offset the right margin and set the control to our point\r
-                                               currentLocation.Offset (0, c.Margin.Bottom * -1);\r
-                                               c.Location = new Point (currentLocation.X + c.Margin.Left, currentLocation.Y - c.Height);\r
-\r
-                                               // Update our location pointer\r
-                                               currentLocation.Y -= (c.Height + c.Margin.Top);\r
-                                               break;\r
-                                       case FlowDirection.LeftToRight:\r
-                                       default:\r
-                                               // Decide if it's time to start a new row\r
-                                               // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true\r
-                                               if (settings.WrapContents)\r
-                                                       if ((parentDisplayRectangle.Width - currentLocation.X) < (c.Width + c.Margin.Left + c.Margin.Right) || forceFlowBreak) {\r
-\r
-                                                               currentLocation.Y = FinishRow (rowControls);\r
-                                                               currentLocation.X = parentDisplayRectangle.Left;\r
-\r
-                                                               forceFlowBreak = false;\r
-                                                               rowControls.Clear ();\r
-                                                       }\r
-\r
-                                               // Offset the left margin and set the control to our point\r
-                                               currentLocation.Offset (c.Margin.Left, 0);\r
-                                               c.Location = new Point (currentLocation.X, currentLocation.Y + c.Margin.Top);\r
-\r
-                                               // Update our location pointer\r
-                                               currentLocation.X += c.Width + c.Margin.Right;\r
-                                               break;\r
-                                       case FlowDirection.RightToLeft:\r
-                                               // Decide if it's time to start a new row\r
-                                               // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true\r
-                                               if (settings.WrapContents)\r
-                                                       if ((currentLocation.X) < (c.Width + c.Margin.Left + c.Margin.Right) || forceFlowBreak) {\r
-\r
-                                                               currentLocation.Y = FinishRow (rowControls);\r
-                                                               currentLocation.X = parentDisplayRectangle.Right;\r
-\r
-                                                               forceFlowBreak = false;\r
-                                                               rowControls.Clear ();\r
-                                                       }\r
-\r
-                                               // Offset the right margin and set the control to our point\r
-                                               currentLocation.Offset (c.Margin.Right * -1, 0);\r
-                                               c.Location = new Point (currentLocation.X - c.Width, currentLocation.Y + c.Margin.Top);\r
-\r
-                                               // Update our location pointer\r
-                                               currentLocation.X -= (c.Width + c.Margin.Left);\r
-                                               break;\r
-                                       case FlowDirection.TopDown:\r
-                                               // Decide if it's time to start a new column\r
-                                               // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true\r
-                                               if (settings.WrapContents)\r
-                                                       if ((parentDisplayRectangle.Height - currentLocation.Y) < (c.Height + c.Margin.Top + c.Margin.Bottom) || forceFlowBreak) {\r
-\r
-                                                               currentLocation.X = FinishColumn (rowControls);\r
-                                                               currentLocation.Y = parentDisplayRectangle.Top;\r
-\r
-                                                               forceFlowBreak = false;\r
-                                                               rowControls.Clear ();\r
-                                                       }\r
-\r
-                                               // Offset the top margin and set the control to our point\r
-                                               currentLocation.Offset (0, c.Margin.Top);\r
-                                               c.Location = new Point (currentLocation.X + c.Margin.Left, currentLocation.Y);\r
-\r
-                                               // Update our location pointer\r
-                                               currentLocation.Y += c.Height + c.Margin.Bottom;\r
-                                               break;\r
-                               }\r
-                               // Add it to our list of things to adjust the second dimension of\r
-                               rowControls.Add (c);\r
-\r
-                               // If user set a flowbreak on this control, it will be the last one in this row/column\r
-                               if (settings.GetFlowBreak (c))\r
-                                       forceFlowBreak = true;\r
-                       }\r
-\r
-                       // Set the control heights/widths for the last row/column\r
-                       if (settings.FlowDirection == FlowDirection.LeftToRight || settings.FlowDirection == FlowDirection.RightToLeft)\r
-                               FinishRow (rowControls);\r
-                       else\r
-                               FinishColumn (rowControls);\r
-\r
-                       return false;\r
-               }\r
-\r
-               // Calculate the heights of the controls, returns the y coordinate of the greatest height it uses\r
-               private int FinishRow (List<Control> row)\r
-               {\r
-                       // Nothing to do\r
-                       if (row.Count == 0) return 0;\r
-\r
-                       int rowTop = int.MaxValue;\r
-                       int rowBottom = 0;\r
-                       bool allDockFill = true;\r
-                       bool noAuto = true;\r
-\r
-                       // Special semantics if all controls are Dock.Fill/Anchor:Top,Bottom or AutoSize = true\r
-                       foreach (Control c in row) {\r
-                               if (c.Dock != DockStyle.Fill && !((c.Anchor & AnchorStyles.Top) == AnchorStyles.Top && (c.Anchor & AnchorStyles.Bottom) == AnchorStyles.Bottom))\r
-                                       allDockFill = false;\r
-                               if (c.AutoSize == true)\r
-                                       noAuto = false;\r
-                       }\r
-\r
-                       // Find the tallest control with a concrete height\r
-                       foreach (Control c in row) {\r
-                               if (c.Bottom + c.Margin.Bottom > rowBottom && (c.Dock != DockStyle.Fill) && ((c.Anchor & AnchorStyles.Top) != AnchorStyles.Top || (c.Anchor & AnchorStyles.Bottom) != AnchorStyles.Bottom || c.AutoSize == true))\r
-                                       rowBottom = c.Bottom + c.Margin.Bottom;\r
-                               if (c.Top - c.Margin.Top < rowTop)\r
-                                       rowTop = c.Top - c.Margin.Top;\r
-                       }\r
-\r
-                       // Find the tallest control that is AutoSize = true\r
-                       if (rowBottom == 0)\r
-                               foreach (Control c in row)\r
-                                       if (c.Bottom + c.Margin.Bottom > rowBottom && (c.Dock != DockStyle.Fill && c.AutoSize == true))\r
-                                               rowBottom = c.Bottom + c.Margin.Bottom;\r
-\r
-                       // Find the tallest control that is Dock = Fill\r
-                       if (rowBottom == 0)\r
-                               foreach (Control c in row)\r
-                                       if (c.Bottom + c.Margin.Bottom > rowBottom && (c.Dock == DockStyle.Fill))\r
-                                               rowBottom = c.Bottom + c.Margin.Bottom;\r
-\r
-                       // Set the new heights for each control\r
-                       foreach (Control c in row)\r
-                               if (allDockFill && noAuto)\r
-                                       c.Height = 0;\r
-                               else if (c.Dock == DockStyle.Fill || ((c.Anchor & AnchorStyles.Top) == AnchorStyles.Top) && ((c.Anchor & AnchorStyles.Bottom) == AnchorStyles.Bottom))\r
-                                       c.Height = rowBottom - c.Top - c.Margin.Bottom;\r
-                               else if (c.Dock == DockStyle.Bottom || ((c.Anchor & AnchorStyles.Bottom) == AnchorStyles.Bottom))\r
-                                       c.Top = rowBottom - c.Margin.Bottom - c.Height;\r
-                               else if (c.Dock == DockStyle.Top || ((c.Anchor & AnchorStyles.Top) == AnchorStyles.Top))\r
-                                       continue;\r
-                               else\r
-                                       c.Top = ((rowBottom - rowTop) / 2) - (c.Height / 2) + (int)Math.Floor (((c.Margin.Top - c.Margin.Bottom) / 2.0)) + rowTop;\r
-\r
-                       // Return bottom y of this row used\r
-                       if (rowBottom == 0)\r
-                               return rowTop;\r
-\r
-                       return rowBottom;\r
-               }\r
-\r
-               // Calculate the widths of the controls, returns the x coordinate of the greatest width it uses\r
-               private int FinishColumn (List<Control> col)\r
-               {\r
-                       // Nothing to do\r
-                       if (col.Count == 0) return 0;\r
-\r
-                       int rowLeft = int.MaxValue;\r
-                       int rowRight = 0;\r
-                       bool allDockFill = true;\r
-                       bool noAuto = true;\r
-\r
-                       // Special semantics if all controls are Dock.Fill/Anchor:Left,Right or AutoSize = true\r
-                       foreach (Control c in col) {\r
-                               if (c.Dock != DockStyle.Fill && !((c.Anchor & AnchorStyles.Left) == AnchorStyles.Left && (c.Anchor & AnchorStyles.Right) == AnchorStyles.Right))\r
-                                       allDockFill = false;\r
-                               if (c.AutoSize == true)\r
-                                       noAuto = false;\r
-                       }\r
-\r
-                       // Find the widest control with a concrete width\r
-                       foreach (Control c in col) {\r
-                               if (c.Right + c.Margin.Right > rowRight && (c.Dock != DockStyle.Fill) && ((c.Anchor & AnchorStyles.Left) != AnchorStyles.Left || (c.Anchor & AnchorStyles.Right) != AnchorStyles.Right || c.AutoSize == true))\r
-                                       rowRight = c.Right + c.Margin.Right;\r
-                               if (c.Left - c.Margin.Left < rowLeft)\r
-                                       rowLeft = c.Left - c.Margin.Left;\r
-                       }\r
-\r
-                       // Find the widest control that is AutoSize = true\r
-                       if (rowRight == 0)\r
-                               foreach (Control c in col)\r
-                                       if (c.Right + c.Margin.Right > rowRight && (c.Dock != DockStyle.Fill && c.AutoSize == true))\r
-                                               rowRight = c.Right + c.Margin.Right;\r
-\r
-                       // Find the widest control that is Dock = Fill\r
-                       if (rowRight == 0)\r
-                               foreach (Control c in col)\r
-                                       if (c.Right + c.Margin.Right > rowRight && (c.Dock == DockStyle.Fill))\r
-                                               rowRight = c.Right + c.Margin.Right;\r
-\r
-                       // Set the new widths for each control\r
-                       foreach (Control c in col)\r
-                               if (allDockFill && noAuto)\r
-                                       c.Width = 0;\r
-                               else if (c.Dock == DockStyle.Fill || ((c.Anchor & AnchorStyles.Left) == AnchorStyles.Left) && ((c.Anchor & AnchorStyles.Right) == AnchorStyles.Right))\r
-                                       c.Width = rowRight - c.Left - c.Margin.Right;\r
-                               else if (c.Dock == DockStyle.Right || ((c.Anchor & AnchorStyles.Right) == AnchorStyles.Right))\r
-                                       c.Left = rowRight - c.Margin.Right - c.Width;\r
-                               else if (c.Dock == DockStyle.Left || ((c.Anchor & AnchorStyles.Left) == AnchorStyles.Left))\r
-                                       continue;\r
-                               else\r
-                                       c.Left = ((rowRight - rowLeft) / 2) - (c.Width / 2) + (int)Math.Floor (((c.Margin.Left - c.Margin.Right) / 2.0)) + rowLeft;\r
-\r
-                       // Return rightmost x of this row used\r
-                       if (rowRight == 0)\r
-                               return rowLeft;\r
-\r
-                       return rowRight;\r
-               }\r
-       }\r
-}\r
+//
+// FlowLayout.cs
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (c) 2006 Jonathan Pobst
+//
+// Authors:
+//     Jonathan Pobst (monkey@jpobst.com)
+//
+
+#if NET_2_0
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+
+namespace System.Windows.Forms.Layout
+{
+       class FlowLayout : LayoutEngine
+       {
+               private static FlowLayoutSettings default_settings = new FlowLayoutSettings ();
+               
+               public FlowLayout ()
+               {
+               }
+
+               public override void InitLayout (object child, BoundsSpecified specified)
+               {
+                       base.InitLayout (child, specified);
+               }
+
+               public override bool Layout (object container, LayoutEventArgs args)
+               {
+                       if (container is ToolStripPanel)
+                               return false;
+                               
+                       if (container is ToolStrip)
+                               return LayoutToolStrip ((ToolStrip)container);
+                               
+                       Control parent = container as Control;
+                       
+                       FlowLayoutSettings settings;
+                       if (parent is FlowLayoutPanel)
+                               settings = (parent as FlowLayoutPanel).LayoutSettings;
+                       else
+                               settings = default_settings;
+
+                       // Nothing to layout, exit method
+                       if (parent.Controls.Count == 0) return false;
+
+                       // Use DisplayRectangle so that parent.Padding is honored.
+                       Rectangle parentDisplayRectangle = parent.DisplayRectangle;
+                       Point currentLocation;
+
+                       // Set our starting point based on flow direction
+                       switch (settings.FlowDirection) {
+                               case FlowDirection.BottomUp:
+                                       currentLocation = new Point (parentDisplayRectangle.Left, parentDisplayRectangle.Bottom);
+                                       break;
+                               case FlowDirection.LeftToRight:
+                               case FlowDirection.TopDown:
+                               default:
+                                       currentLocation = parentDisplayRectangle.Location;
+                                       break;
+                               case FlowDirection.RightToLeft:
+                                       currentLocation = new Point (parentDisplayRectangle.Right, parentDisplayRectangle.Top);
+                                       break;
+                       }
+
+                       bool forceFlowBreak = false;
+
+                       List<Control> rowControls = new List<Control> ();
+
+                       foreach (Control c in parent.Controls) {
+                               // Only apply layout to visible controls.
+                               if (!c.Visible) { continue; }
+
+                               // Resize any AutoSize controls to their preferred size
+                               if (c.AutoSize == true) {
+                                       Size new_size = c.GetPreferredSize (c.Size);
+                                       c.SetBoundsInternal (c.Left, c.Top, new_size.Width, new_size.Height, BoundsSpecified.None);
+                               }
+
+                               switch (settings.FlowDirection) {
+                                       case FlowDirection.BottomUp:
+                                               // Decide if it's time to start a new column
+                                               // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true
+                                               if (settings.WrapContents)
+                                                       if ((currentLocation.Y) < (c.Height + c.Margin.Top + c.Margin.Bottom) || forceFlowBreak) {
+
+                                                               currentLocation.X = FinishColumn (rowControls);
+                                                               currentLocation.Y = parentDisplayRectangle.Bottom;
+
+                                                               forceFlowBreak = false;
+                                                               rowControls.Clear ();
+                                                       }
+
+                                               // Offset the right margin and set the control to our point
+                                               currentLocation.Offset (0, c.Margin.Bottom * -1);
+                                               c.SetBoundsInternal (currentLocation.X + c.Margin.Left, currentLocation.Y - c.Height, c.Width, c.Height, BoundsSpecified.None);
+
+                                               // Update our location pointer
+                                               currentLocation.Y -= (c.Height + c.Margin.Top);
+                                               break;
+                                       case FlowDirection.LeftToRight:
+                                       default:
+                                               // Decide if it's time to start a new row
+                                               // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true
+                                               if (settings.WrapContents  && !(parent is ToolStripPanel))
+                                                       if ((parentDisplayRectangle.Width + parentDisplayRectangle.Left - currentLocation.X) < (c.Width + c.Margin.Left + c.Margin.Right) || forceFlowBreak) {
+
+                                                               currentLocation.Y = FinishRow (rowControls);
+                                                               currentLocation.X = parentDisplayRectangle.Left;
+
+                                                               forceFlowBreak = false;
+                                                               rowControls.Clear ();
+                                                       }
+
+                                               // Offset the left margin and set the control to our point
+                                               currentLocation.Offset (c.Margin.Left, 0);
+                                               c.SetBoundsInternal (currentLocation.X, currentLocation.Y + c.Margin.Top, c.Width, c.Height, BoundsSpecified.None);
+
+                                               // Update our location pointer
+                                               currentLocation.X += c.Width + c.Margin.Right;
+                                               break;
+                                       case FlowDirection.RightToLeft:
+                                               // Decide if it's time to start a new row
+                                               // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true
+                                               if (settings.WrapContents)
+                                                       if ((currentLocation.X) < (c.Width + c.Margin.Left + c.Margin.Right) || forceFlowBreak) {
+
+                                                               currentLocation.Y = FinishRow (rowControls);
+                                                               currentLocation.X = parentDisplayRectangle.Right;
+
+                                                               forceFlowBreak = false;
+                                                               rowControls.Clear ();
+                                                       }
+
+                                               // Offset the right margin and set the control to our point
+                                               currentLocation.Offset (c.Margin.Right * -1, 0);
+                                               c.SetBoundsInternal (currentLocation.X - c.Width, currentLocation.Y + c.Margin.Top, c.Width, c.Height, BoundsSpecified.None);
+
+                                               // Update our location pointer
+                                               currentLocation.X -= (c.Width + c.Margin.Left);
+                                               break;
+                                       case FlowDirection.TopDown:
+                                               // Decide if it's time to start a new column
+                                               // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true
+                                               if (settings.WrapContents)
+                                                       if ((parentDisplayRectangle.Height + parentDisplayRectangle.Top - currentLocation.Y) < (c.Height + c.Margin.Top + c.Margin.Bottom) || forceFlowBreak) {
+
+                                                               currentLocation.X = FinishColumn (rowControls);
+                                                               currentLocation.Y = parentDisplayRectangle.Top;
+
+                                                               forceFlowBreak = false;
+                                                               rowControls.Clear ();
+                                                       }
+
+                                               // Offset the top margin and set the control to our point
+                                               currentLocation.Offset (0, c.Margin.Top);
+                                               c.SetBoundsInternal (currentLocation.X + c.Margin.Left, currentLocation.Y, c.Width, c.Height, BoundsSpecified.None);
+
+                                               // Update our location pointer
+                                               currentLocation.Y += c.Height + c.Margin.Bottom;
+                                               break;
+                               }
+                               // Add it to our list of things to adjust the second dimension of
+                               rowControls.Add (c);
+
+                               // If user set a flowbreak on this control, it will be the last one in this row/column
+                               if (settings.GetFlowBreak (c))
+                                       forceFlowBreak = true;
+                       }
+
+                       // Set the control heights/widths for the last row/column
+                       if (settings.FlowDirection == FlowDirection.LeftToRight || settings.FlowDirection == FlowDirection.RightToLeft)
+                               FinishRow (rowControls);
+                       else
+                               FinishColumn (rowControls);
+
+                       return false;
+               }
+
+               // Calculate the heights of the controls, returns the y coordinate of the greatest height it uses
+               private int FinishRow (List<Control> row)
+               {
+                       // Nothing to do
+                       if (row.Count == 0) return 0;
+
+                       int rowTop = int.MaxValue;
+                       int rowBottom = 0;
+                       bool allDockFill = true;
+                       bool noAuto = true;
+
+                       // Special semantics if all controls are Dock.Fill/Anchor:Top,Bottom or AutoSize = true
+                       foreach (Control c in row) {
+                               if (c.Dock != DockStyle.Fill && !((c.Anchor & AnchorStyles.Top) == AnchorStyles.Top && (c.Anchor & AnchorStyles.Bottom) == AnchorStyles.Bottom))
+                                       allDockFill = false;
+                               if (c.AutoSize == true)
+                                       noAuto = false;
+                       }
+
+                       // Find the tallest control with a concrete height
+                       foreach (Control c in row) {
+                               if (c.Bottom + c.Margin.Bottom > rowBottom && (c.Dock != DockStyle.Fill) && ((c.Anchor & AnchorStyles.Top) != AnchorStyles.Top || (c.Anchor & AnchorStyles.Bottom) != AnchorStyles.Bottom || c.AutoSize == true))
+                                       rowBottom = c.Bottom + c.Margin.Bottom;
+                               if (c.Top - c.Margin.Top < rowTop)
+                                       rowTop = c.Top - c.Margin.Top;
+                       }
+
+                       // Find the tallest control that is AutoSize = true
+                       if (rowBottom == 0)
+                               foreach (Control c in row)
+                                       if (c.Bottom + c.Margin.Bottom > rowBottom && (c.Dock != DockStyle.Fill && c.AutoSize == true))
+                                               rowBottom = c.Bottom + c.Margin.Bottom;
+
+                       // Find the tallest control that is Dock = Fill
+                       if (rowBottom == 0)
+                               foreach (Control c in row)
+                                       if (c.Bottom + c.Margin.Bottom > rowBottom && (c.Dock == DockStyle.Fill))
+                                               rowBottom = c.Bottom + c.Margin.Bottom;
+
+                       // Set the new heights for each control
+                       foreach (Control c in row)
+                               if (allDockFill && noAuto)
+                                       c.SetBoundsInternal (c.Left, c.Top, c.Width, 0, BoundsSpecified.None);
+                               else if (c.Dock == DockStyle.Fill || ((c.Anchor & AnchorStyles.Top) == AnchorStyles.Top) && ((c.Anchor & AnchorStyles.Bottom) == AnchorStyles.Bottom))
+                                       c.SetBoundsInternal (c.Left, c.Top, c.Width, rowBottom - c.Top - c.Margin.Bottom, BoundsSpecified.None);
+                               else if (c.Dock == DockStyle.Bottom || ((c.Anchor & AnchorStyles.Bottom) == AnchorStyles.Bottom))
+                                       c.SetBoundsInternal (c.Left, rowBottom - c.Margin.Bottom - c.Height, c.Width, c.Height, BoundsSpecified.None);
+                               else if (c.Dock == DockStyle.Top || ((c.Anchor & AnchorStyles.Top) == AnchorStyles.Top))
+                                       continue;
+                               else
+                                       c.SetBoundsInternal (c.Left, ((rowBottom - rowTop) / 2) - (c.Height / 2) + (int)Math.Floor (((c.Margin.Top - c.Margin.Bottom) / 2.0)) + rowTop, c.Width, c.Height, BoundsSpecified.None);
+
+                       // Return bottom y of this row used
+                       if (rowBottom == 0)
+                               return rowTop;
+
+                       return rowBottom;
+               }
+
+               // Calculate the widths of the controls, returns the x coordinate of the greatest width it uses
+               private int FinishColumn (List<Control> col)
+               {
+                       // Nothing to do
+                       if (col.Count == 0) return 0;
+
+                       int rowLeft = int.MaxValue;
+                       int rowRight = 0;
+                       bool allDockFill = true;
+                       bool noAuto = true;
+
+                       // Special semantics if all controls are Dock.Fill/Anchor:Left,Right or AutoSize = true
+                       foreach (Control c in col) {
+                               if (c.Dock != DockStyle.Fill && !((c.Anchor & AnchorStyles.Left) == AnchorStyles.Left && (c.Anchor & AnchorStyles.Right) == AnchorStyles.Right))
+                                       allDockFill = false;
+                               if (c.AutoSize == true)
+                                       noAuto = false;
+                       }
+
+                       // Find the widest control with a concrete width
+                       foreach (Control c in col) {
+                               if (c.Right + c.Margin.Right > rowRight && (c.Dock != DockStyle.Fill) && ((c.Anchor & AnchorStyles.Left) != AnchorStyles.Left || (c.Anchor & AnchorStyles.Right) != AnchorStyles.Right || c.AutoSize == true))
+                                       rowRight = c.Right + c.Margin.Right;
+                               if (c.Left - c.Margin.Left < rowLeft)
+                                       rowLeft = c.Left - c.Margin.Left;
+                       }
+
+                       // Find the widest control that is AutoSize = true
+                       if (rowRight == 0)
+                               foreach (Control c in col)
+                                       if (c.Right + c.Margin.Right > rowRight && (c.Dock != DockStyle.Fill && c.AutoSize == true))
+                                               rowRight = c.Right + c.Margin.Right;
+
+                       // Find the widest control that is Dock = Fill
+                       if (rowRight == 0)
+                               foreach (Control c in col)
+                                       if (c.Right + c.Margin.Right > rowRight && (c.Dock == DockStyle.Fill))
+                                               rowRight = c.Right + c.Margin.Right;
+
+                       // Set the new widths for each control
+                       foreach (Control c in col)
+                               if (allDockFill && noAuto)
+                                       c.SetBoundsInternal (c.Left, c.Top, 0, c.Height, BoundsSpecified.None);
+                               else if (c.Dock == DockStyle.Fill || ((c.Anchor & AnchorStyles.Left) == AnchorStyles.Left) && ((c.Anchor & AnchorStyles.Right) == AnchorStyles.Right))
+                                       c.SetBoundsInternal (c.Left, c.Top, rowRight - c.Left - c.Margin.Right, c.Height, BoundsSpecified.None);
+                               else if (c.Dock == DockStyle.Right || ((c.Anchor & AnchorStyles.Right) == AnchorStyles.Right))
+                                       c.SetBoundsInternal (rowRight - c.Margin.Right - c.Width, c.Top, c.Width, c.Height, BoundsSpecified.None);
+                               else if (c.Dock == DockStyle.Left || ((c.Anchor & AnchorStyles.Left) == AnchorStyles.Left))
+                                       continue;
+                               else
+                                       c.SetBoundsInternal (((rowRight - rowLeft) / 2) - (c.Width / 2) + (int)Math.Floor (((c.Margin.Left - c.Margin.Right) / 2.0)) + rowLeft, c.Top, c.Width, c.Height, BoundsSpecified.None);
+
+                       // Return rightmost x of this row used
+                       if (rowRight == 0)
+                               return rowLeft;
+
+                       return rowRight;
+               }
+
+               #region Layout for ToolStrip
+               // ToolStrips use the same FlowLayout, but is made up of ToolStripItems which
+               // are Components instead of Controls, so we have to duplicate this login for
+               // ToolStripItems.
+               private bool LayoutToolStrip (ToolStrip parent)
+               {
+                       FlowLayoutSettings settings;
+                       settings = (FlowLayoutSettings)parent.LayoutSettings;
+
+                       // Nothing to layout, exit method
+                       if (parent.Items.Count == 0) return false;
+
+                       foreach (ToolStripItem tsi in parent.Items)
+                               tsi.SetPlacement (ToolStripItemPlacement.Main);
+                               
+                       // Use DisplayRectangle so that parent.Padding is honored.
+                       Rectangle parentDisplayRectangle = parent.DisplayRectangle;
+                       Point currentLocation;
+
+                       // Set our starting point based on flow direction
+                       switch (settings.FlowDirection) {
+                               case FlowDirection.BottomUp:
+                                       currentLocation = new Point (parentDisplayRectangle.Left, parentDisplayRectangle.Bottom);
+                                       break;
+                               case FlowDirection.LeftToRight:
+                               case FlowDirection.TopDown:
+                               default:
+                                       currentLocation = parentDisplayRectangle.Location;
+                                       break;
+                               case FlowDirection.RightToLeft:
+                                       currentLocation = new Point (parentDisplayRectangle.Right, parentDisplayRectangle.Top);
+                                       break;
+                       }
+
+                       bool forceFlowBreak = false;
+
+                       List<ToolStripItem> rowControls = new List<ToolStripItem> ();
+
+                       foreach (ToolStripItem c in parent.Items) {
+                               // Only apply layout to visible controls.
+                               if (!c.Available) { continue; }
+
+                               // Resize any AutoSize controls to their preferred size
+                               if (c.AutoSize == true)
+                                       c.SetBounds (new Rectangle (c.Location, c.GetPreferredSize (c.Size)));
+
+                               switch (settings.FlowDirection) {
+                                       case FlowDirection.BottomUp:
+                                               // Decide if it's time to start a new column
+                                               // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true
+                                               if (settings.WrapContents)
+                                                       if ((currentLocation.Y) < (c.Height + c.Margin.Top + c.Margin.Bottom) || forceFlowBreak) {
+
+                                                               currentLocation.X = FinishColumn (rowControls);
+                                                               currentLocation.Y = parentDisplayRectangle.Bottom;
+
+                                                               forceFlowBreak = false;
+                                                               rowControls.Clear ();
+                                                       }
+
+                                               // Offset the right margin and set the control to our point
+                                               currentLocation.Offset (0, c.Margin.Bottom * -1);
+                                               c.Location = new Point (currentLocation.X + c.Margin.Left, currentLocation.Y - c.Height);
+
+                                               // Update our location pointer
+                                               currentLocation.Y -= (c.Height + c.Margin.Top);
+                                               break;
+                                       case FlowDirection.LeftToRight:
+                                       default:
+                                               // Decide if it's time to start a new row
+                                               // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true
+                                               if (settings.WrapContents)
+                                                       if ((parentDisplayRectangle.Width - currentLocation.X) < (c.Width + c.Margin.Left + c.Margin.Right) || forceFlowBreak) {
+
+                                                               currentLocation.Y = FinishRow (rowControls);
+                                                               currentLocation.X = parentDisplayRectangle.Left;
+
+                                                               forceFlowBreak = false;
+                                                               rowControls.Clear ();
+                                                       }
+
+                                               // Offset the left margin and set the control to our point
+                                               currentLocation.Offset (c.Margin.Left, 0);
+                                               c.Location = new Point (currentLocation.X, currentLocation.Y + c.Margin.Top);
+
+                                               // Update our location pointer
+                                               currentLocation.X += c.Width + c.Margin.Right;
+                                               break;
+                                       case FlowDirection.RightToLeft:
+                                               // Decide if it's time to start a new row
+                                               // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true
+                                               if (settings.WrapContents)
+                                                       if ((currentLocation.X) < (c.Width + c.Margin.Left + c.Margin.Right) || forceFlowBreak) {
+
+                                                               currentLocation.Y = FinishRow (rowControls);
+                                                               currentLocation.X = parentDisplayRectangle.Right;
+
+                                                               forceFlowBreak = false;
+                                                               rowControls.Clear ();
+                                                       }
+
+                                               // Offset the right margin and set the control to our point
+                                               currentLocation.Offset (c.Margin.Right * -1, 0);
+                                               c.Location = new Point (currentLocation.X - c.Width, currentLocation.Y + c.Margin.Top);
+
+                                               // Update our location pointer
+                                               currentLocation.X -= (c.Width + c.Margin.Left);
+                                               break;
+                                       case FlowDirection.TopDown:
+                                               // Decide if it's time to start a new column
+                                               // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true
+                                               if (settings.WrapContents)
+                                                       if ((parentDisplayRectangle.Height - currentLocation.Y) < (c.Height + c.Margin.Top + c.Margin.Bottom) || forceFlowBreak) {
+
+                                                               currentLocation.X = FinishColumn (rowControls);
+                                                               currentLocation.Y = parentDisplayRectangle.Top;
+
+                                                               forceFlowBreak = false;
+                                                               rowControls.Clear ();
+                                                       }
+
+                                               // Offset the top margin and set the control to our point
+                                               currentLocation.Offset (0, c.Margin.Top);
+                                               c.Location = new Point (currentLocation.X + c.Margin.Left, currentLocation.Y);
+
+                                               // Update our location pointer
+                                               currentLocation.Y += c.Height + c.Margin.Bottom;
+                                               break;
+                               }
+                               // Add it to our list of things to adjust the second dimension of
+                               rowControls.Add (c);
+
+                               // If user set a flowbreak on this control, it will be the last one in this row/column
+                               if (settings.GetFlowBreak (c))
+                                       forceFlowBreak = true;
+                       }
+
+                       int final_height = 0;
+                       
+                       // Set the control heights/widths for the last row/column
+                       if (settings.FlowDirection == FlowDirection.LeftToRight || settings.FlowDirection == FlowDirection.RightToLeft)
+                               final_height = FinishRow (rowControls);
+                       else
+                               FinishColumn (rowControls);
+
+                       if (final_height > 0)
+                               parent.SetBoundsInternal (parent.Left, parent.Top, parent.Width, final_height + parent.Padding.Bottom, BoundsSpecified.None);
+                               
+                       return false;
+
+               }
+
+               // Calculate the heights of the controls, returns the y coordinate of the greatest height it uses
+               private int FinishRow (List<ToolStripItem> row)
+               {
+                       // Nothing to do
+                       if (row.Count == 0) return 0;
+
+                       int rowTop = int.MaxValue;
+                       int rowBottom = 0;
+                       bool allDockFill = true;
+                       bool noAuto = true;
+
+                       // Special semantics if all controls are Dock.Fill/Anchor:Top,Bottom or AutoSize = true
+                       foreach (ToolStripItem c in row) {
+                               if (c.Dock != DockStyle.Fill && !((c.Anchor & AnchorStyles.Top) == AnchorStyles.Top && (c.Anchor & AnchorStyles.Bottom) == AnchorStyles.Bottom))
+                                       allDockFill = false;
+                               if (c.AutoSize == true)
+                                       noAuto = false;
+                       }
+
+                       // Find the tallest control with a concrete height
+                       foreach (ToolStripItem c in row) {
+                               if (c.Bottom + c.Margin.Bottom > rowBottom && (c.Dock != DockStyle.Fill) && ((c.Anchor & AnchorStyles.Top) != AnchorStyles.Top || (c.Anchor & AnchorStyles.Bottom) != AnchorStyles.Bottom || c.AutoSize == true))
+                                       rowBottom = c.Bottom + c.Margin.Bottom;
+                               if (c.Top - c.Margin.Top < rowTop)
+                                       rowTop = c.Top - c.Margin.Top;
+                       }
+
+                       // Find the tallest control that is AutoSize = true
+                       if (rowBottom == 0)
+                               foreach (ToolStripItem c in row)
+                                       if (c.Bottom + c.Margin.Bottom > rowBottom && (c.Dock != DockStyle.Fill && c.AutoSize == true))
+                                               rowBottom = c.Bottom + c.Margin.Bottom;
+
+                       // Find the tallest control that is Dock = Fill
+                       if (rowBottom == 0)
+                               foreach (ToolStripItem c in row)
+                                       if (c.Bottom + c.Margin.Bottom > rowBottom && (c.Dock == DockStyle.Fill))
+                                               rowBottom = c.Bottom + c.Margin.Bottom;
+
+                       // Set the new heights for each control
+                       foreach (ToolStripItem c in row)
+                               if (allDockFill && noAuto)
+                                       c.Height = 0;
+                               else if (c.Dock == DockStyle.Fill || ((c.Anchor & AnchorStyles.Top) == AnchorStyles.Top) && ((c.Anchor & AnchorStyles.Bottom) == AnchorStyles.Bottom))
+                                       c.Height = rowBottom - c.Top - c.Margin.Bottom;
+                               else if (c.Dock == DockStyle.Bottom || ((c.Anchor & AnchorStyles.Bottom) == AnchorStyles.Bottom))
+                                       c.Top = rowBottom - c.Margin.Bottom - c.Height;
+                               else if (c.Dock == DockStyle.Top || ((c.Anchor & AnchorStyles.Top) == AnchorStyles.Top))
+                                       continue;
+                               else
+                                       c.Top = ((rowBottom - rowTop) / 2) - (c.Height / 2) + (int)Math.Floor (((c.Margin.Top - c.Margin.Bottom) / 2.0)) + rowTop;
+
+                       // Return bottom y of this row used
+                       if (rowBottom == 0)
+                               return rowTop;
+
+                       return rowBottom;
+               }
+
+               // Calculate the widths of the controls, returns the x coordinate of the greatest width it uses
+               private int FinishColumn (List<ToolStripItem> col)
+               {
+                       // Nothing to do
+                       if (col.Count == 0) return 0;
+
+                       int rowLeft = int.MaxValue;
+                       int rowRight = 0;
+                       bool allDockFill = true;
+                       bool noAuto = true;
+
+                       // Special semantics if all controls are Dock.Fill/Anchor:Left,Right or AutoSize = true
+                       foreach (ToolStripItem c in col) {
+                               if (c.Dock != DockStyle.Fill && !((c.Anchor & AnchorStyles.Left) == AnchorStyles.Left && (c.Anchor & AnchorStyles.Right) == AnchorStyles.Right))
+                                       allDockFill = false;
+                               if (c.AutoSize == true)
+                                       noAuto = false;
+                       }
+
+                       // Find the widest control with a concrete width
+                       foreach (ToolStripItem c in col) {
+                               if (c.Right + c.Margin.Right > rowRight && (c.Dock != DockStyle.Fill) && ((c.Anchor & AnchorStyles.Left) != AnchorStyles.Left || (c.Anchor & AnchorStyles.Right) != AnchorStyles.Right || c.AutoSize == true))
+                                       rowRight = c.Right + c.Margin.Right;
+                               if (c.Left - c.Margin.Left < rowLeft)
+                                       rowLeft = c.Left - c.Margin.Left;
+                       }
+
+                       // Find the widest control that is AutoSize = true
+                       if (rowRight == 0)
+                               foreach (ToolStripItem c in col)
+                                       if (c.Right + c.Margin.Right > rowRight && (c.Dock != DockStyle.Fill && c.AutoSize == true))
+                                               rowRight = c.Right + c.Margin.Right;
+
+                       // Find the widest control that is Dock = Fill
+                       if (rowRight == 0)
+                               foreach (ToolStripItem c in col)
+                                       if (c.Right + c.Margin.Right > rowRight && (c.Dock == DockStyle.Fill))
+                                               rowRight = c.Right + c.Margin.Right;
+
+                       // Set the new widths for each control
+                       foreach (ToolStripItem c in col)
+                               if (allDockFill && noAuto)
+                                       c.Width = 0;
+                               else if (c.Dock == DockStyle.Fill || ((c.Anchor & AnchorStyles.Left) == AnchorStyles.Left) && ((c.Anchor & AnchorStyles.Right) == AnchorStyles.Right))
+                                       c.Width = rowRight - c.Left - c.Margin.Right;
+                               else if (c.Dock == DockStyle.Right || ((c.Anchor & AnchorStyles.Right) == AnchorStyles.Right))
+                                       c.Left = rowRight - c.Margin.Right - c.Width;
+                               else if (c.Dock == DockStyle.Left || ((c.Anchor & AnchorStyles.Left) == AnchorStyles.Left))
+                                       continue;
+                               else
+                                       c.Left = ((rowRight - rowLeft) / 2) - (c.Width / 2) + (int)Math.Floor (((c.Margin.Left - c.Margin.Right) / 2.0)) + rowLeft;
+
+                       // Return rightmost x of this row used
+                       if (rowRight == 0)
+                               return rowLeft;
+
+                       return rowRight;
+               }
+               #endregion
+       }
+}
 #endif
\ No newline at end of file