Typo error
[mono.git] / mcs / class / System.Windows.Forms / System.Windows.Forms / FlowLayoutPanel.cs
1 //
2 // FlowLayoutPanel.cs
3 //
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:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
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.
22 //
23 // Copyright (c) 2006 Jonathan Pobst
24 //
25 // Authors:
26 //      Jonathan Pobst (monkey@jpobst.com)
27 //
28
29 using System.Windows.Forms.Layout;
30 using System.ComponentModel;
31 using System.Runtime.InteropServices;
32 using System.Drawing;
33
34 namespace System.Windows.Forms
35 {
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
43         {
44                 private FlowLayoutSettings settings;
45
46                 public FlowLayoutPanel () : base ()
47                 {
48                         CreateDockPadding ();
49                 }
50
51                 #region Properties
52                 [Localizable (true)]
53                 [DefaultValue (FlowDirection.LeftToRight)]
54                 public FlowDirection FlowDirection {
55                         get { return LayoutSettings.FlowDirection; }
56                         set { LayoutSettings.FlowDirection = value; }
57                 }
58
59                 [LocalizableAttribute (true)]
60                 [DefaultValue (true)]
61                 public bool WrapContents {
62                         get { return LayoutSettings.WrapContents; }
63                         set { LayoutSettings.WrapContents = value; }
64                 }
65
66                 public override LayoutEngine LayoutEngine {
67                         get { return this.LayoutSettings.LayoutEngine; }
68                 }
69
70                 internal FlowLayoutSettings LayoutSettings {
71                         get { 
72                                 if (this.settings == null)
73                                         this.settings = new FlowLayoutSettings (this);
74                                         
75                                 return this.settings;
76                         }
77                 }
78                 #endregion
79
80                 #region Public Methods
81                 [DefaultValue (false)]
82                 [DisplayName ("FlowBreak")]
83                 public bool GetFlowBreak (Control control)
84                 {
85                         return LayoutSettings.GetFlowBreak (control);
86                 }
87
88                 [DisplayName ("FlowBreak")]
89                 public void SetFlowBreak (Control control, bool value)
90                 {
91                         LayoutSettings.SetFlowBreak (control, value);
92                 }               
93                 #endregion
94                 
95                 #region IExtenderProvider Members
96                 bool IExtenderProvider.CanExtend (object obj)
97                 {
98                         if (obj is Control)
99                                 if ((obj as Control).Parent == this)
100                                         return true;
101
102                         return false;
103                 }
104                 #endregion
105
106                 #region Internal Methods
107                 internal override void CalculateCanvasSize (bool canOverride)
108                 {
109                         if (canOverride)
110                                 canvas_size = ClientSize;
111                         else
112                                 base.CalculateCanvasSize (canOverride);
113                 }
114
115                protected override void OnLayout (LayoutEventArgs levent)
116                {
117                        base.OnLayout (levent);
118
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;
125                        }
126                        AdjustFormScrollbars (AutoScroll);
127                }
128                 
129                 internal override Size GetPreferredSizeCore (Size proposedSize)
130                 {
131                         int width = 0;
132                         int height = 0;
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;
139                                         else
140                                                 control_preferred_size = control.Size;
141                                         Padding control_margin = control.Margin;
142                                         if (horizontal) {
143                                                 width += control_preferred_size.Width + control_margin.Horizontal;
144                                                 height = Math.Max (height, control_preferred_size.Height + control_margin.Vertical);
145                                         } else {
146                                                 height += control_preferred_size.Height + control_margin.Vertical;
147                                                 width = Math.Max (width, control_preferred_size.Width + control_margin.Horizontal);
148                                         }
149                                 }
150                         } else {
151                                 int size_in_flow_direction = 0;
152                                 int size_in_other_direction = 0;
153                                 int increase;
154                                 foreach (Control control in Controls) {
155                                         Size control_preferred_size;
156                                         if (control.AutoSize)
157                                                 control_preferred_size = control.PreferredSize;
158                                         else
159                                                 control_preferred_size = control.ExplicitBounds.Size;
160                                         Padding control_margin = control.Margin;
161                                         if (horizontal) {
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;
168                                                 }
169                                                 size_in_flow_direction += increase;
170                                                 size_in_other_direction = Math.Max (size_in_other_direction, control_preferred_size.Height + control_margin.Vertical);
171                                         } else {
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;
178                                                 }
179                                                 size_in_flow_direction += increase;
180                                                 size_in_other_direction = Math.Max (size_in_other_direction, control_preferred_size.Width + control_margin.Horizontal);
181                                         }
182                                 }
183                                 if (horizontal) {
184                                         width = Math.Max (width, size_in_flow_direction);
185                                         height += size_in_other_direction;
186                                 } else {
187                                         height = Math.Max (height, size_in_flow_direction);
188                                         width += size_in_other_direction;
189                                 }
190                         }
191                         return new Size (width, height);
192                 }
193                 #endregion
194         }
195 }