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)
30 using System.Windows.Forms.Layout;
31 using System.ComponentModel;
32 using System.Runtime.InteropServices;
35 namespace System.Windows.Forms
37 [ComVisibleAttribute (true)]
38 [ClassInterfaceAttribute (ClassInterfaceType.AutoDispatch)]
39 [ProvideProperty ("FlowBreak", typeof (Control))]
40 [DefaultProperty ("FlowDirection")]
41 [Docking (DockingBehavior.Ask)]
42 [Designer ("System.Windows.Forms.Design.FlowLayoutPanelDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
43 public class FlowLayoutPanel : Panel, IExtenderProvider
45 private FlowLayoutSettings settings;
47 public FlowLayoutPanel () : base ()
54 [DefaultValue (FlowDirection.LeftToRight)]
55 public FlowDirection FlowDirection {
56 get { return LayoutSettings.FlowDirection; }
57 set { LayoutSettings.FlowDirection = value; }
60 [LocalizableAttribute (true)]
62 public bool WrapContents {
63 get { return LayoutSettings.WrapContents; }
64 set { LayoutSettings.WrapContents = value; }
67 public override LayoutEngine LayoutEngine {
68 get { return this.LayoutSettings.LayoutEngine; }
71 internal FlowLayoutSettings LayoutSettings {
73 if (this.settings == null)
74 this.settings = new FlowLayoutSettings (this);
81 #region Public Methods
82 [DefaultValue (false)]
83 [DisplayName ("FlowBreak")]
84 public bool GetFlowBreak (Control control)
86 return LayoutSettings.GetFlowBreak (control);
89 [DisplayName ("FlowBreak")]
90 public void SetFlowBreak (Control control, bool value)
92 LayoutSettings.SetFlowBreak (control, value);
96 #region IExtenderProvider Members
97 bool IExtenderProvider.CanExtend (object obj)
100 if ((obj as Control).Parent == this)
107 #region Internal Methods
108 internal override void CalculateCanvasSize (bool canOverride)
111 canvas_size = ClientSize;
113 base.CalculateCanvasSize (canOverride);
116 internal override Size GetPreferredSizeCore (Size proposedSize)
120 bool horizontal = FlowDirection == FlowDirection.LeftToRight || FlowDirection == FlowDirection.RightToLeft;
121 if (!WrapContents || (horizontal && proposedSize.Width == 0) || (!horizontal && proposedSize.Height == 0)) {
122 foreach (Control control in Controls) {
123 Size control_preferred_size;
124 if (control.AutoSize)
125 control_preferred_size = control.PreferredSize;
127 control_preferred_size = control.Size;
128 Padding control_margin = control.Margin;
130 width += control_preferred_size.Width + control_margin.Horizontal;
131 height = Math.Max (height, control_preferred_size.Height + control_margin.Vertical);
133 height += control_preferred_size.Height + control_margin.Vertical;
134 width = Math.Max (width, control_preferred_size.Width + control_margin.Horizontal);
138 int size_in_flow_direction = 0;
139 int size_in_other_direction = 0;
141 foreach (Control control in Controls) {
142 Size control_preferred_size;
143 if (control.AutoSize)
144 control_preferred_size = control.PreferredSize;
146 control_preferred_size = control.ExplicitBounds.Size;
147 Padding control_margin = control.Margin;
149 increase = control_preferred_size.Width + control_margin.Horizontal;
150 if (size_in_flow_direction != 0 && size_in_flow_direction + increase >= proposedSize.Width) {
151 width = Math.Max (width, size_in_flow_direction);
152 size_in_flow_direction = 0;
153 height += size_in_other_direction;
154 size_in_other_direction = 0;
156 size_in_flow_direction += increase;
157 size_in_other_direction = Math.Max (size_in_other_direction, control_preferred_size.Height + control_margin.Vertical);
159 increase = control_preferred_size.Height + control_margin.Vertical;
160 if (size_in_flow_direction != 0 && size_in_flow_direction + increase >= proposedSize.Height) {
161 height = Math.Max (height, size_in_flow_direction);
162 size_in_flow_direction = 0;
163 width += size_in_other_direction;
164 size_in_other_direction = 0;
166 size_in_flow_direction += increase;
167 size_in_other_direction = Math.Max (size_in_other_direction, control_preferred_size.Width + control_margin.Horizontal);
171 width = Math.Max (width, size_in_flow_direction);
172 height += size_in_other_direction;
174 height = Math.Max (height, size_in_flow_direction);
175 width += size_in_other_direction;
178 return new Size (width, height);