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)
29 using System.Windows.Forms.Layout;
30 using System.ComponentModel;
31 using System.Runtime.InteropServices;
34 namespace System.Windows.Forms
36 [ComVisibleAttribute (true)]
37 [ClassInterfaceAttribute (ClassInterfaceType.AutoDispatch)]
38 [ProvideProperty ("FlowBreak", typeof (Control))]
39 [DefaultProperty ("FlowDirection")]
40 [Docking (DockingBehavior.Ask)]
41 [Designer ("System.Windows.Forms.Design.FlowLayoutPanelDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
42 public class FlowLayoutPanel : Panel, IExtenderProvider
44 private FlowLayoutSettings settings;
46 public FlowLayoutPanel () : base ()
53 [DefaultValue (FlowDirection.LeftToRight)]
54 public FlowDirection FlowDirection {
55 get { return LayoutSettings.FlowDirection; }
56 set { LayoutSettings.FlowDirection = value; }
59 [LocalizableAttribute (true)]
61 public bool WrapContents {
62 get { return LayoutSettings.WrapContents; }
63 set { LayoutSettings.WrapContents = value; }
66 public override LayoutEngine LayoutEngine {
67 get { return this.LayoutSettings.LayoutEngine; }
70 internal FlowLayoutSettings LayoutSettings {
72 if (this.settings == null)
73 this.settings = new FlowLayoutSettings (this);
80 #region Public Methods
81 [DefaultValue (false)]
82 [DisplayName ("FlowBreak")]
83 public bool GetFlowBreak (Control control)
85 return LayoutSettings.GetFlowBreak (control);
88 [DisplayName ("FlowBreak")]
89 public void SetFlowBreak (Control control, bool value)
91 LayoutSettings.SetFlowBreak (control, value);
95 #region IExtenderProvider Members
96 bool IExtenderProvider.CanExtend (object obj)
99 if ((obj as Control).Parent == this)
106 #region Internal Methods
107 internal override void CalculateCanvasSize (bool canOverride)
110 canvas_size = ClientSize;
112 base.CalculateCanvasSize (canOverride);
115 protected override void OnLayout (LayoutEventArgs levent)
117 base.OnLayout (levent);
119 // base.OnLayout() calls CalculateCanvasSize(true) in which we just set the canvas to
120 // clientsize so we could re-layout everything according to the flow.
121 // This time we want to actually calculate the canvas.
122 CalculateCanvasSize (false);
123 if (AutoSize && (canvas_size.Width > ClientSize.Width || canvas_size.Height > ClientSize.Height)) {
124 ClientSize = canvas_size;
126 AdjustFormScrollbars (AutoScroll);
129 internal override Size GetPreferredSizeCore (Size proposedSize)
133 bool horizontal = FlowDirection == FlowDirection.LeftToRight || FlowDirection == FlowDirection.RightToLeft;
134 if (!WrapContents || (horizontal && proposedSize.Width == 0) || (!horizontal && proposedSize.Height == 0)) {
135 foreach (Control control in Controls) {
136 Size control_preferred_size;
137 if (control.AutoSize)
138 control_preferred_size = control.PreferredSize;
140 control_preferred_size = control.Size;
141 Padding control_margin = control.Margin;
143 width += control_preferred_size.Width + control_margin.Horizontal;
144 height = Math.Max (height, control_preferred_size.Height + control_margin.Vertical);
146 height += control_preferred_size.Height + control_margin.Vertical;
147 width = Math.Max (width, control_preferred_size.Width + control_margin.Horizontal);
151 int size_in_flow_direction = 0;
152 int size_in_other_direction = 0;
154 foreach (Control control in Controls) {
155 Size control_preferred_size;
156 if (control.AutoSize)
157 control_preferred_size = control.PreferredSize;
159 control_preferred_size = control.ExplicitBounds.Size;
160 Padding control_margin = control.Margin;
162 increase = control_preferred_size.Width + control_margin.Horizontal;
163 if (size_in_flow_direction != 0 && size_in_flow_direction + increase >= proposedSize.Width) {
164 width = Math.Max (width, size_in_flow_direction);
165 size_in_flow_direction = 0;
166 height += size_in_other_direction;
167 size_in_other_direction = 0;
169 size_in_flow_direction += increase;
170 size_in_other_direction = Math.Max (size_in_other_direction, control_preferred_size.Height + control_margin.Vertical);
172 increase = control_preferred_size.Height + control_margin.Vertical;
173 if (size_in_flow_direction != 0 && size_in_flow_direction + increase >= proposedSize.Height) {
174 height = Math.Max (height, size_in_flow_direction);
175 size_in_flow_direction = 0;
176 width += size_in_other_direction;
177 size_in_other_direction = 0;
179 size_in_flow_direction += increase;
180 size_in_other_direction = Math.Max (size_in_other_direction, control_preferred_size.Width + control_margin.Horizontal);
184 width = Math.Max (width, size_in_flow_direction);
185 height += size_in_other_direction;
187 height = Math.Max (height, size_in_flow_direction);
188 width += size_in_other_direction;
191 return new Size (width, height);