4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 // Copyright (c) 2006 Jonathan Pobst
26 // Jonathan Pobst (monkey@jpobst.com)
31 using System
.Collections
.Generic
;
34 namespace System
.Windows
.Forms
.Layout
36 class FlowLayout
: LayoutEngine
38 private static FlowLayoutSettings default_settings
= new FlowLayoutSettings ();
44 public override void InitLayout (object child
, BoundsSpecified specified
)
46 base.InitLayout (child
, specified
);
49 public override bool Layout (object container
, LayoutEventArgs args
)
51 if (container
is ToolStripPanel
)
54 if (container
is ToolStrip
)
55 return LayoutToolStrip ((ToolStrip
)container
);
57 Control parent
= container
as Control
;
59 FlowLayoutSettings settings
;
60 if (parent
is FlowLayoutPanel
)
61 settings
= (parent
as FlowLayoutPanel
).LayoutSettings
;
63 settings
= default_settings
;
65 // Nothing to layout, exit method
66 if (parent
.Controls
.Count
== 0) return false;
68 // Use DisplayRectangle so that parent.Padding is honored.
69 Rectangle parentDisplayRectangle
= parent
.DisplayRectangle
;
70 Point currentLocation
;
72 // Set our starting point based on flow direction
73 switch (settings
.FlowDirection
) {
74 case FlowDirection
.BottomUp
:
75 currentLocation
= new Point (parentDisplayRectangle
.Left
, parentDisplayRectangle
.Bottom
);
77 case FlowDirection
.LeftToRight
:
78 case FlowDirection
.TopDown
:
80 currentLocation
= parentDisplayRectangle
.Location
;
82 case FlowDirection
.RightToLeft
:
83 currentLocation
= new Point (parentDisplayRectangle
.Right
, parentDisplayRectangle
.Top
);
87 bool forceFlowBreak
= false;
89 List
<Control
> rowControls
= new List
<Control
> ();
91 foreach (Control c
in parent
.Controls
) {
92 // Only apply layout to visible controls.
93 if (!c
.Visible
) { continue; }
95 // Resize any AutoSize controls to their preferred size
96 if (c
.AutoSize
== true) {
97 Size new_size
= c
.GetPreferredSize (c
.Size
);
98 c
.SetBoundsInternal (c
.Left
, c
.Top
, new_size
.Width
, new_size
.Height
, BoundsSpecified
.None
);
101 switch (settings
.FlowDirection
) {
102 case FlowDirection
.BottomUp
:
103 // Decide if it's time to start a new column
104 // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true
105 if (settings
.WrapContents
)
106 if ((currentLocation
.Y
) < (c
.Height
+ c
.Margin
.Top
+ c
.Margin
.Bottom
) || forceFlowBreak
) {
108 currentLocation
.X
= FinishColumn (rowControls
);
109 currentLocation
.Y
= parentDisplayRectangle
.Bottom
;
111 forceFlowBreak
= false;
112 rowControls
.Clear ();
115 // Offset the right margin and set the control to our point
116 currentLocation
.Offset (0, c
.Margin
.Bottom
* -1);
117 c
.SetBoundsInternal (currentLocation
.X
+ c
.Margin
.Left
, currentLocation
.Y
- c
.Height
, c
.Width
, c
.Height
, BoundsSpecified
.None
);
119 // Update our location pointer
120 currentLocation
.Y
-= (c
.Height
+ c
.Margin
.Top
);
122 case FlowDirection
.LeftToRight
:
124 // Decide if it's time to start a new row
125 // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true
126 if (settings
.WrapContents
&& !(parent
is ToolStripPanel
))
127 if ((parentDisplayRectangle
.Width
+ parentDisplayRectangle
.Left
- currentLocation
.X
) < (c
.Width
+ c
.Margin
.Left
+ c
.Margin
.Right
) || forceFlowBreak
) {
129 currentLocation
.Y
= FinishRow (rowControls
);
130 currentLocation
.X
= parentDisplayRectangle
.Left
;
132 forceFlowBreak
= false;
133 rowControls
.Clear ();
136 // Offset the left margin and set the control to our point
137 currentLocation
.Offset (c
.Margin
.Left
, 0);
138 c
.SetBoundsInternal (currentLocation
.X
, currentLocation
.Y
+ c
.Margin
.Top
, c
.Width
, c
.Height
, BoundsSpecified
.None
);
140 // Update our location pointer
141 currentLocation
.X
+= c
.Width
+ c
.Margin
.Right
;
143 case FlowDirection
.RightToLeft
:
144 // Decide if it's time to start a new row
145 // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true
146 if (settings
.WrapContents
)
147 if ((currentLocation
.X
) < (c
.Width
+ c
.Margin
.Left
+ c
.Margin
.Right
) || forceFlowBreak
) {
149 currentLocation
.Y
= FinishRow (rowControls
);
150 currentLocation
.X
= parentDisplayRectangle
.Right
;
152 forceFlowBreak
= false;
153 rowControls
.Clear ();
156 // Offset the right margin and set the control to our point
157 currentLocation
.Offset (c
.Margin
.Right
* -1, 0);
158 c
.SetBoundsInternal (currentLocation
.X
- c
.Width
, currentLocation
.Y
+ c
.Margin
.Top
, c
.Width
, c
.Height
, BoundsSpecified
.None
);
160 // Update our location pointer
161 currentLocation
.X
-= (c
.Width
+ c
.Margin
.Left
);
163 case FlowDirection
.TopDown
:
164 // Decide if it's time to start a new column
165 // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true
166 if (settings
.WrapContents
)
167 if ((parentDisplayRectangle
.Height
+ parentDisplayRectangle
.Top
- currentLocation
.Y
) < (c
.Height
+ c
.Margin
.Top
+ c
.Margin
.Bottom
) || forceFlowBreak
) {
169 currentLocation
.X
= FinishColumn (rowControls
);
170 currentLocation
.Y
= parentDisplayRectangle
.Top
;
172 forceFlowBreak
= false;
173 rowControls
.Clear ();
176 // Offset the top margin and set the control to our point
177 currentLocation
.Offset (0, c
.Margin
.Top
);
178 c
.SetBoundsInternal (currentLocation
.X
+ c
.Margin
.Left
, currentLocation
.Y
, c
.Width
, c
.Height
, BoundsSpecified
.None
);
180 // Update our location pointer
181 currentLocation
.Y
+= c
.Height
+ c
.Margin
.Bottom
;
184 // Add it to our list of things to adjust the second dimension of
187 // If user set a flowbreak on this control, it will be the last one in this row/column
188 if (settings
.GetFlowBreak (c
))
189 forceFlowBreak
= true;
192 // Set the control heights/widths for the last row/column
193 if (settings
.FlowDirection
== FlowDirection
.LeftToRight
|| settings
.FlowDirection
== FlowDirection
.RightToLeft
)
194 FinishRow (rowControls
);
196 FinishColumn (rowControls
);
201 // Calculate the heights of the controls, returns the y coordinate of the greatest height it uses
202 private int FinishRow (List
<Control
> row
)
205 if (row
.Count
== 0) return 0;
207 int rowTop
= int.MaxValue
;
209 bool allDockFill
= true;
212 // Special semantics if all controls are Dock.Fill/Anchor:Top,Bottom or AutoSize = true
213 foreach (Control c
in row
) {
214 if (c
.Dock
!= DockStyle
.Fill
&& !((c
.Anchor
& AnchorStyles
.Top
) == AnchorStyles
.Top
&& (c
.Anchor
& AnchorStyles
.Bottom
) == AnchorStyles
.Bottom
))
216 if (c
.AutoSize
== true)
220 // Find the tallest control with a concrete height
221 foreach (Control c
in row
) {
222 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))
223 rowBottom
= c
.Bottom
+ c
.Margin
.Bottom
;
224 if (c
.Top
- c
.Margin
.Top
< rowTop
)
225 rowTop
= c
.Top
- c
.Margin
.Top
;
228 // Find the tallest control that is AutoSize = true
230 foreach (Control c
in row
)
231 if (c
.Bottom
+ c
.Margin
.Bottom
> rowBottom
&& (c
.Dock
!= DockStyle
.Fill
&& c
.AutoSize
== true))
232 rowBottom
= c
.Bottom
+ c
.Margin
.Bottom
;
234 // Find the tallest control that is Dock = Fill
236 foreach (Control c
in row
)
237 if (c
.Bottom
+ c
.Margin
.Bottom
> rowBottom
&& (c
.Dock
== DockStyle
.Fill
))
238 rowBottom
= c
.Bottom
+ c
.Margin
.Bottom
;
240 // Set the new heights for each control
241 foreach (Control c
in row
)
242 if (allDockFill
&& noAuto
)
243 c
.SetBoundsInternal (c
.Left
, c
.Top
, c
.Width
, 0, BoundsSpecified
.None
);
244 else if (c
.Dock
== DockStyle
.Fill
|| ((c
.Anchor
& AnchorStyles
.Top
) == AnchorStyles
.Top
) && ((c
.Anchor
& AnchorStyles
.Bottom
) == AnchorStyles
.Bottom
))
245 c
.SetBoundsInternal (c
.Left
, c
.Top
, c
.Width
, rowBottom
- c
.Top
- c
.Margin
.Bottom
, BoundsSpecified
.None
);
246 else if (c
.Dock
== DockStyle
.Bottom
|| ((c
.Anchor
& AnchorStyles
.Bottom
) == AnchorStyles
.Bottom
))
247 c
.SetBoundsInternal (c
.Left
, rowBottom
- c
.Margin
.Bottom
- c
.Height
, c
.Width
, c
.Height
, BoundsSpecified
.None
);
248 else if (c
.Dock
== DockStyle
.Top
|| ((c
.Anchor
& AnchorStyles
.Top
) == AnchorStyles
.Top
))
251 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
);
253 // Return bottom y of this row used
260 // Calculate the widths of the controls, returns the x coordinate of the greatest width it uses
261 private int FinishColumn (List
<Control
> col
)
264 if (col
.Count
== 0) return 0;
266 int rowLeft
= int.MaxValue
;
268 bool allDockFill
= true;
271 // Special semantics if all controls are Dock.Fill/Anchor:Left,Right or AutoSize = true
272 foreach (Control c
in col
) {
273 if (c
.Dock
!= DockStyle
.Fill
&& !((c
.Anchor
& AnchorStyles
.Left
) == AnchorStyles
.Left
&& (c
.Anchor
& AnchorStyles
.Right
) == AnchorStyles
.Right
))
275 if (c
.AutoSize
== true)
279 // Find the widest control with a concrete width
280 foreach (Control c
in col
) {
281 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))
282 rowRight
= c
.Right
+ c
.Margin
.Right
;
283 if (c
.Left
- c
.Margin
.Left
< rowLeft
)
284 rowLeft
= c
.Left
- c
.Margin
.Left
;
287 // Find the widest control that is AutoSize = true
289 foreach (Control c
in col
)
290 if (c
.Right
+ c
.Margin
.Right
> rowRight
&& (c
.Dock
!= DockStyle
.Fill
&& c
.AutoSize
== true))
291 rowRight
= c
.Right
+ c
.Margin
.Right
;
293 // Find the widest control that is Dock = Fill
295 foreach (Control c
in col
)
296 if (c
.Right
+ c
.Margin
.Right
> rowRight
&& (c
.Dock
== DockStyle
.Fill
))
297 rowRight
= c
.Right
+ c
.Margin
.Right
;
299 // Set the new widths for each control
300 foreach (Control c
in col
)
301 if (allDockFill
&& noAuto
)
302 c
.SetBoundsInternal (c
.Left
, c
.Top
, 0, c
.Height
, BoundsSpecified
.None
);
303 else if (c
.Dock
== DockStyle
.Fill
|| ((c
.Anchor
& AnchorStyles
.Left
) == AnchorStyles
.Left
) && ((c
.Anchor
& AnchorStyles
.Right
) == AnchorStyles
.Right
))
304 c
.SetBoundsInternal (c
.Left
, c
.Top
, rowRight
- c
.Left
- c
.Margin
.Right
, c
.Height
, BoundsSpecified
.None
);
305 else if (c
.Dock
== DockStyle
.Right
|| ((c
.Anchor
& AnchorStyles
.Right
) == AnchorStyles
.Right
))
306 c
.SetBoundsInternal (rowRight
- c
.Margin
.Right
- c
.Width
, c
.Top
, c
.Width
, c
.Height
, BoundsSpecified
.None
);
307 else if (c
.Dock
== DockStyle
.Left
|| ((c
.Anchor
& AnchorStyles
.Left
) == AnchorStyles
.Left
))
310 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
);
312 // Return rightmost x of this row used
319 #region Layout for ToolStrip
320 // ToolStrips use the same FlowLayout, but is made up of ToolStripItems which
321 // are Components instead of Controls, so we have to duplicate this login for
323 private bool LayoutToolStrip (ToolStrip parent
)
325 FlowLayoutSettings settings
;
326 settings
= (FlowLayoutSettings
)parent
.LayoutSettings
;
328 // Nothing to layout, exit method
329 if (parent
.Items
.Count
== 0) return false;
331 foreach (ToolStripItem tsi
in parent
.Items
)
332 tsi
.SetPlacement (ToolStripItemPlacement
.Main
);
334 // Use DisplayRectangle so that parent.Padding is honored.
335 Rectangle parentDisplayRectangle
= parent
.DisplayRectangle
;
336 Point currentLocation
;
338 // Set our starting point based on flow direction
339 switch (settings
.FlowDirection
) {
340 case FlowDirection
.BottomUp
:
341 currentLocation
= new Point (parentDisplayRectangle
.Left
, parentDisplayRectangle
.Bottom
);
343 case FlowDirection
.LeftToRight
:
344 case FlowDirection
.TopDown
:
346 currentLocation
= parentDisplayRectangle
.Location
;
348 case FlowDirection
.RightToLeft
:
349 currentLocation
= new Point (parentDisplayRectangle
.Right
, parentDisplayRectangle
.Top
);
353 bool forceFlowBreak
= false;
355 List
<ToolStripItem
> rowControls
= new List
<ToolStripItem
> ();
357 foreach (ToolStripItem c
in parent
.Items
) {
358 // Only apply layout to visible controls.
359 if (!c
.Available
) { continue; }
361 // Resize any AutoSize controls to their preferred width
362 // (the height should fill the ToolStrip)
363 if (c
.AutoSize
== true) {
364 Size preferred_size
= c
.GetPreferredSize (c
.Size
);
365 preferred_size
.Height
= parentDisplayRectangle
.Height
;
366 c
.SetBounds (new Rectangle (c
.Location
, preferred_size
));
369 switch (settings
.FlowDirection
) {
370 case FlowDirection
.BottomUp
:
371 // Decide if it's time to start a new column
372 // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true
373 if (settings
.WrapContents
)
374 if ((currentLocation
.Y
) < (c
.Height
+ c
.Margin
.Top
+ c
.Margin
.Bottom
) || forceFlowBreak
) {
376 currentLocation
.X
= FinishColumn (rowControls
);
377 currentLocation
.Y
= parentDisplayRectangle
.Bottom
;
379 forceFlowBreak
= false;
380 rowControls
.Clear ();
383 // Offset the right margin and set the control to our point
384 currentLocation
.Offset (0, c
.Margin
.Bottom
* -1);
385 c
.Location
= new Point (currentLocation
.X
+ c
.Margin
.Left
, currentLocation
.Y
- c
.Height
);
387 // Update our location pointer
388 currentLocation
.Y
-= (c
.Height
+ c
.Margin
.Top
);
390 case FlowDirection
.LeftToRight
:
392 // Decide if it's time to start a new row
393 // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true
394 if (settings
.WrapContents
)
395 if ((parentDisplayRectangle
.Width
- currentLocation
.X
) < (c
.Width
+ c
.Margin
.Left
+ c
.Margin
.Right
) || forceFlowBreak
) {
397 currentLocation
.Y
= FinishRow (rowControls
);
398 currentLocation
.X
= parentDisplayRectangle
.Left
;
400 forceFlowBreak
= false;
401 rowControls
.Clear ();
404 // Offset the left margin and set the control to our point
405 currentLocation
.Offset (c
.Margin
.Left
, 0);
406 c
.Location
= new Point (currentLocation
.X
, currentLocation
.Y
+ c
.Margin
.Top
);
408 // Update our location pointer
409 currentLocation
.X
+= c
.Width
+ c
.Margin
.Right
;
411 case FlowDirection
.RightToLeft
:
412 // Decide if it's time to start a new row
413 // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true
414 if (settings
.WrapContents
)
415 if ((currentLocation
.X
) < (c
.Width
+ c
.Margin
.Left
+ c
.Margin
.Right
) || forceFlowBreak
) {
417 currentLocation
.Y
= FinishRow (rowControls
);
418 currentLocation
.X
= parentDisplayRectangle
.Right
;
420 forceFlowBreak
= false;
421 rowControls
.Clear ();
424 // Offset the right margin and set the control to our point
425 currentLocation
.Offset (c
.Margin
.Right
* -1, 0);
426 c
.Location
= new Point (currentLocation
.X
- c
.Width
, currentLocation
.Y
+ c
.Margin
.Top
);
428 // Update our location pointer
429 currentLocation
.X
-= (c
.Width
+ c
.Margin
.Left
);
431 case FlowDirection
.TopDown
:
432 // Decide if it's time to start a new column
433 // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true
434 if (settings
.WrapContents
)
435 if ((parentDisplayRectangle
.Height
- currentLocation
.Y
) < (c
.Height
+ c
.Margin
.Top
+ c
.Margin
.Bottom
) || forceFlowBreak
) {
437 currentLocation
.X
= FinishColumn (rowControls
);
438 currentLocation
.Y
= parentDisplayRectangle
.Top
;
440 forceFlowBreak
= false;
441 rowControls
.Clear ();
444 // Offset the top margin and set the control to our point
445 currentLocation
.Offset (0, c
.Margin
.Top
);
446 c
.Location
= new Point (currentLocation
.X
+ c
.Margin
.Left
, currentLocation
.Y
);
448 // Update our location pointer
449 currentLocation
.Y
+= c
.Height
+ c
.Margin
.Bottom
;
452 // Add it to our list of things to adjust the second dimension of
455 // If user set a flowbreak on this control, it will be the last one in this row/column
456 if (settings
.GetFlowBreak (c
))
457 forceFlowBreak
= true;
460 int final_height
= 0;
462 // Set the control heights/widths for the last row/column
463 if (settings
.FlowDirection
== FlowDirection
.LeftToRight
|| settings
.FlowDirection
== FlowDirection
.RightToLeft
)
464 final_height
= FinishRow (rowControls
);
466 FinishColumn (rowControls
);
468 if (final_height
> 0)
469 parent
.SetBoundsInternal (parent
.Left
, parent
.Top
, parent
.Width
, final_height
+ parent
.Padding
.Bottom
, BoundsSpecified
.None
);
475 // Calculate the heights of the controls, returns the y coordinate of the greatest height it uses
476 private int FinishRow (List
<ToolStripItem
> row
)
479 if (row
.Count
== 0) return 0;
481 int rowTop
= int.MaxValue
;
483 bool allDockFill
= true;
486 // Special semantics if all controls are Dock.Fill/Anchor:Top,Bottom or AutoSize = true
487 foreach (ToolStripItem c
in row
) {
488 if (c
.Dock
!= DockStyle
.Fill
&& !((c
.Anchor
& AnchorStyles
.Top
) == AnchorStyles
.Top
&& (c
.Anchor
& AnchorStyles
.Bottom
) == AnchorStyles
.Bottom
))
490 if (c
.AutoSize
== true)
494 // Find the tallest control with a concrete height
495 foreach (ToolStripItem c
in row
) {
496 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))
497 rowBottom
= c
.Bottom
+ c
.Margin
.Bottom
;
498 if (c
.Top
- c
.Margin
.Top
< rowTop
)
499 rowTop
= c
.Top
- c
.Margin
.Top
;
502 // Find the tallest control that is AutoSize = true
504 foreach (ToolStripItem c
in row
)
505 if (c
.Bottom
+ c
.Margin
.Bottom
> rowBottom
&& (c
.Dock
!= DockStyle
.Fill
&& c
.AutoSize
== true))
506 rowBottom
= c
.Bottom
+ c
.Margin
.Bottom
;
508 // Find the tallest control that is Dock = Fill
510 foreach (ToolStripItem c
in row
)
511 if (c
.Bottom
+ c
.Margin
.Bottom
> rowBottom
&& (c
.Dock
== DockStyle
.Fill
))
512 rowBottom
= c
.Bottom
+ c
.Margin
.Bottom
;
514 // Set the new heights for each control
515 foreach (ToolStripItem c
in row
)
516 if (allDockFill
&& noAuto
)
518 else if (c
.Dock
== DockStyle
.Fill
|| ((c
.Anchor
& AnchorStyles
.Top
) == AnchorStyles
.Top
) && ((c
.Anchor
& AnchorStyles
.Bottom
) == AnchorStyles
.Bottom
))
519 c
.Height
= rowBottom
- c
.Top
- c
.Margin
.Bottom
;
520 else if (c
.Dock
== DockStyle
.Bottom
|| ((c
.Anchor
& AnchorStyles
.Bottom
) == AnchorStyles
.Bottom
))
521 c
.Top
= rowBottom
- c
.Margin
.Bottom
- c
.Height
;
522 else if (c
.Dock
== DockStyle
.Top
|| ((c
.Anchor
& AnchorStyles
.Top
) == AnchorStyles
.Top
))
525 c
.Top
= ((rowBottom
- rowTop
) / 2) - (c
.Height
/ 2) + (int)Math
.Floor (((c
.Margin
.Top
- c
.Margin
.Bottom
) / 2.0)) + rowTop
;
527 // Return bottom y of this row used
534 // Calculate the widths of the controls, returns the x coordinate of the greatest width it uses
535 private int FinishColumn (List
<ToolStripItem
> col
)
538 if (col
.Count
== 0) return 0;
540 int rowLeft
= int.MaxValue
;
542 bool allDockFill
= true;
545 // Special semantics if all controls are Dock.Fill/Anchor:Left,Right or AutoSize = true
546 foreach (ToolStripItem c
in col
) {
547 if (c
.Dock
!= DockStyle
.Fill
&& !((c
.Anchor
& AnchorStyles
.Left
) == AnchorStyles
.Left
&& (c
.Anchor
& AnchorStyles
.Right
) == AnchorStyles
.Right
))
549 if (c
.AutoSize
== true)
553 // Find the widest control with a concrete width
554 foreach (ToolStripItem c
in col
) {
555 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))
556 rowRight
= c
.Right
+ c
.Margin
.Right
;
557 if (c
.Left
- c
.Margin
.Left
< rowLeft
)
558 rowLeft
= c
.Left
- c
.Margin
.Left
;
561 // Find the widest control that is AutoSize = true
563 foreach (ToolStripItem c
in col
)
564 if (c
.Right
+ c
.Margin
.Right
> rowRight
&& (c
.Dock
!= DockStyle
.Fill
&& c
.AutoSize
== true))
565 rowRight
= c
.Right
+ c
.Margin
.Right
;
567 // Find the widest control that is Dock = Fill
569 foreach (ToolStripItem c
in col
)
570 if (c
.Right
+ c
.Margin
.Right
> rowRight
&& (c
.Dock
== DockStyle
.Fill
))
571 rowRight
= c
.Right
+ c
.Margin
.Right
;
573 // Set the new widths for each control
574 foreach (ToolStripItem c
in col
)
575 if (allDockFill
&& noAuto
)
577 else if (c
.Dock
== DockStyle
.Fill
|| ((c
.Anchor
& AnchorStyles
.Left
) == AnchorStyles
.Left
) && ((c
.Anchor
& AnchorStyles
.Right
) == AnchorStyles
.Right
))
578 c
.Width
= rowRight
- c
.Left
- c
.Margin
.Right
;
579 else if (c
.Dock
== DockStyle
.Right
|| ((c
.Anchor
& AnchorStyles
.Right
) == AnchorStyles
.Right
))
580 c
.Left
= rowRight
- c
.Margin
.Right
- c
.Width
;
581 else if (c
.Dock
== DockStyle
.Left
|| ((c
.Anchor
& AnchorStyles
.Left
) == AnchorStyles
.Left
))
584 c
.Left
= ((rowRight
- rowLeft
) / 2) - (c
.Width
/ 2) + (int)Math
.Floor (((c
.Margin
.Left
- c
.Margin
.Right
) / 2.0)) + rowLeft
;
586 // Return rightmost x of this row used