aboutsummaryrefslogtreecommitdiff
path: root/source/ShiftUI/Internal/FlowLayout.cs
diff options
context:
space:
mode:
authorMichael VanOverbeek <[email protected]>2016-07-25 12:57:52 -0400
committerGitHub <[email protected]>2016-07-25 12:57:52 -0400
commit46c1c31302f111a1f3ec23a70e6f3986a9aa2a27 (patch)
treef00af7ea3f6ad2641fb26fa1d310fd8b7179b39c /source/ShiftUI/Internal/FlowLayout.cs
parentaf48e774189596b8d7a058c564a7d6d75205ca03 (diff)
parent6fa16209519896de09949a27425dff00ebf2970a (diff)
downloadshiftos-c--46c1c31302f111a1f3ec23a70e6f3986a9aa2a27.tar.gz
shiftos-c--46c1c31302f111a1f3ec23a70e6f3986a9aa2a27.tar.bz2
shiftos-c--46c1c31302f111a1f3ec23a70e6f3986a9aa2a27.zip
Merge pull request #17 from MichaelTheShifter/shiftui_integration
Shiftui integration
Diffstat (limited to 'source/ShiftUI/Internal/FlowLayout.cs')
-rw-r--r--source/ShiftUI/Internal/FlowLayout.cs589
1 files changed, 589 insertions, 0 deletions
diff --git a/source/ShiftUI/Internal/FlowLayout.cs b/source/ShiftUI/Internal/FlowLayout.cs
new file mode 100644
index 0000000..5eb55a5
--- /dev/null
+++ b/source/ShiftUI/Internal/FlowLayout.cs
@@ -0,0 +1,589 @@
+//
+// 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 ([email protected])
+//
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+
+namespace ShiftUI.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);
+
+ Widget parent = container as Widget;
+
+ FlowLayoutSettings settings;
+ if (parent is FlowLayoutPanel)
+ settings = (parent as FlowLayoutPanel).LayoutSettings;
+ else
+ settings = default_settings;
+
+ // Nothing to layout, exit method
+ if (parent.Widgets.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<Widget> rowWidgets = new List<Widget> ();
+
+ foreach (Widget c in parent.Widgets) {
+ // Only apply layout to visible Widgets.
+ if (!c.Visible) { continue; }
+
+ // Resize any AutoSize Widgets 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 Widget's FlowBreak == true
+ if (settings.WrapContents)
+ if ((currentLocation.Y) < (c.Height + c.Margin.Top + c.Margin.Bottom) || forceFlowBreak) {
+
+ currentLocation.X = FinishColumn (rowWidgets);
+ currentLocation.Y = parentDisplayRectangle.Bottom;
+
+ forceFlowBreak = false;
+ rowWidgets.Clear ();
+ }
+
+ // Offset the right margin and set the Widget 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 Widget'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 (rowWidgets);
+ currentLocation.X = parentDisplayRectangle.Left;
+
+ forceFlowBreak = false;
+ rowWidgets.Clear ();
+ }
+
+ // Offset the left margin and set the Widget 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 Widget's FlowBreak == true
+ if (settings.WrapContents)
+ if ((currentLocation.X) < (c.Width + c.Margin.Left + c.Margin.Right) || forceFlowBreak) {
+
+ currentLocation.Y = FinishRow (rowWidgets);
+ currentLocation.X = parentDisplayRectangle.Right;
+
+ forceFlowBreak = false;
+ rowWidgets.Clear ();
+ }
+
+ // Offset the right margin and set the Widget 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 Widget'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 (rowWidgets);
+ currentLocation.Y = parentDisplayRectangle.Top;
+
+ forceFlowBreak = false;
+ rowWidgets.Clear ();
+ }
+
+ // Offset the top margin and set the Widget 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
+ rowWidgets.Add (c);
+
+ // If user set a flowbreak on this Widget, it will be the last one in this row/column
+ if (settings.GetFlowBreak (c))
+ forceFlowBreak = true;
+ }
+
+ // Set the Widget heights/widths for the last row/column
+ if (settings.FlowDirection == FlowDirection.LeftToRight || settings.FlowDirection == FlowDirection.RightToLeft)
+ FinishRow (rowWidgets);
+ else
+ FinishColumn (rowWidgets);
+
+ return false;
+ }
+
+ // Calculate the heights of the Widgets, returns the y coordinate of the greatest height it uses
+ private int FinishRow (List<Widget> 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 Widgets are Dock.Fill/Anchor:Top,Bottom or AutoSize = true
+ foreach (Widget 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 Widget with a concrete height
+ foreach (Widget 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 Widget that is AutoSize = true
+ if (rowBottom == 0)
+ foreach (Widget 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 Widget that is Dock = Fill
+ if (rowBottom == 0)
+ foreach (Widget 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 Widget
+ foreach (Widget 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 Widgets, returns the x coordinate of the greatest width it uses
+ private int FinishColumn (List<Widget> 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 Widgets are Dock.Fill/Anchor:Left,Right or AutoSize = true
+ foreach (Widget 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 Widget with a concrete width
+ foreach (Widget 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 Widget that is AutoSize = true
+ if (rowRight == 0)
+ foreach (Widget 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 Widget that is Dock = Fill
+ if (rowRight == 0)
+ foreach (Widget 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 Widget
+ foreach (Widget 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 Widgets, 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> rowWidgets = new List<ToolStripItem> ();
+
+ foreach (ToolStripItem c in parent.Items) {
+ // Only apply layout to visible Widgets.
+ if (!c.Available) { continue; }
+
+ // Resize any AutoSize Widgets 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 Widget's FlowBreak == true
+ if (settings.WrapContents)
+ if ((currentLocation.Y) < (c.Height + c.Margin.Top + c.Margin.Bottom) || forceFlowBreak) {
+
+ currentLocation.X = FinishColumn (rowWidgets);
+ currentLocation.Y = parentDisplayRectangle.Bottom;
+
+ forceFlowBreak = false;
+ rowWidgets.Clear ();
+ }
+
+ // Offset the right margin and set the Widget 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 Widget's FlowBreak == true
+ if (settings.WrapContents)
+ if ((parentDisplayRectangle.Width - currentLocation.X) < (c.Width + c.Margin.Left + c.Margin.Right) || forceFlowBreak) {
+
+ currentLocation.Y = FinishRow (rowWidgets);
+ currentLocation.X = parentDisplayRectangle.Left;
+
+ forceFlowBreak = false;
+ rowWidgets.Clear ();
+ }
+
+ // Offset the left margin and set the Widget 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 Widget's FlowBreak == true
+ if (settings.WrapContents)
+ if ((currentLocation.X) < (c.Width + c.Margin.Left + c.Margin.Right) || forceFlowBreak) {
+
+ currentLocation.Y = FinishRow (rowWidgets);
+ currentLocation.X = parentDisplayRectangle.Right;
+
+ forceFlowBreak = false;
+ rowWidgets.Clear ();
+ }
+
+ // Offset the right margin and set the Widget 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 Widget's FlowBreak == true
+ if (settings.WrapContents)
+ if ((parentDisplayRectangle.Height - currentLocation.Y) < (c.Height + c.Margin.Top + c.Margin.Bottom) || forceFlowBreak) {
+
+ currentLocation.X = FinishColumn (rowWidgets);
+ currentLocation.Y = parentDisplayRectangle.Top;
+
+ forceFlowBreak = false;
+ rowWidgets.Clear ();
+ }
+
+ // Offset the top margin and set the Widget 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
+ rowWidgets.Add (c);
+
+ // If user set a flowbreak on this Widget, it will be the last one in this row/column
+ if (settings.GetFlowBreak (c))
+ forceFlowBreak = true;
+ }
+
+ int final_height = 0;
+
+ // Set the Widget heights/widths for the last row/column
+ if (settings.FlowDirection == FlowDirection.LeftToRight || settings.FlowDirection == FlowDirection.RightToLeft)
+ final_height = FinishRow (rowWidgets);
+ else
+ FinishColumn (rowWidgets);
+
+ 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 Widgets, 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 Widgets 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 Widget 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 Widget 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 Widget 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 Widget
+ 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 Widgets, 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 Widgets 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 Widget 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 Widget 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 Widget 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 Widget
+ 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
+ }
+}