2008-12-06 Ivan N. Zlatev <contact@i-nz.net>
[mono.git] / mcs / class / Managed.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 #if NET_2_0
30 using System.Windows.Forms.Layout;
31 using System.ComponentModel;
32 using System.Runtime.InteropServices;
33 using System.Drawing;
34
35 namespace System.Windows.Forms
36 {
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
44         {
45                 private FlowLayoutSettings settings;
46
47                 public FlowLayoutPanel () : base ()
48                 {
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                 internal override Size GetPreferredSizeCore (Size proposedSize)
116                 {
117                         int width = 0;
118                         int height = 0;
119                         bool horizontal = FlowDirection == FlowDirection.LeftToRight || FlowDirection == FlowDirection.RightToLeft;
120                         if (!WrapContents || (horizontal && proposedSize.Width == 0) || (!horizontal && proposedSize.Height == 0)) {
121                                 foreach (Control control in Controls) {
122                                         Size control_preferred_size;
123                                         if (control.AutoSize)
124                                                 control_preferred_size = control.PreferredSize;
125                                         else
126                                                 control_preferred_size = control.Size;
127                                         Padding control_margin = control.Margin;
128                                         if (horizontal) {
129                                                 width += control_preferred_size.Width + control_margin.Horizontal;
130                                                 height = Math.Max (height, control_preferred_size.Height + control_margin.Vertical);
131                                         } else {
132                                                 height += control_preferred_size.Height + control_margin.Vertical;
133                                                 width = Math.Max (width, control_preferred_size.Width + control_margin.Horizontal);
134                                         }
135                                 }
136                         } else {
137                                 int size_in_flow_direction = 0;
138                                 int size_in_other_direction = 0;
139                                 int increase;
140                                 foreach (Control control in Controls) {
141                                         Size control_preferred_size;
142                                         if (control.AutoSize)
143                                                 control_preferred_size = control.PreferredSize;
144                                         else
145                                                 control_preferred_size = control.ExplicitBounds.Size;
146                                         Padding control_margin = control.Margin;
147                                         if (horizontal) {
148                                                 increase = control_preferred_size.Width + control_margin.Horizontal;
149                                                 if (size_in_flow_direction != 0 && size_in_flow_direction + increase >= proposedSize.Width) {
150                                                         width = Math.Max (width, size_in_flow_direction);
151                                                         size_in_flow_direction = 0;
152                                                         height += size_in_other_direction;
153                                                         size_in_other_direction = 0;
154                                                 }
155                                                 size_in_flow_direction += increase;
156                                                 size_in_other_direction = Math.Max (size_in_other_direction, control_preferred_size.Height + control_margin.Vertical);
157                                         } else {
158                                                 increase = control_preferred_size.Height + control_margin.Vertical;
159                                                 if (size_in_flow_direction != 0 && size_in_flow_direction + increase >= proposedSize.Height) {
160                                                         height = Math.Max (height, size_in_flow_direction);
161                                                         size_in_flow_direction = 0;
162                                                         width += size_in_other_direction;
163                                                         size_in_other_direction = 0;
164                                                 }
165                                                 size_in_flow_direction += increase;
166                                                 size_in_other_direction = Math.Max (size_in_other_direction, control_preferred_size.Width + control_margin.Horizontal);
167                                         }
168                                 }
169                                 if (horizontal) {
170                                         width = Math.Max (width, size_in_flow_direction);
171                                         height += size_in_other_direction;
172                                 } else {
173                                         height = Math.Max (height, size_in_flow_direction);
174                                         width += size_in_other_direction;
175                                 }
176                         }
177                         return new Size (width, height);
178                 }
179                 #endregion
180         }
181 }
182 #endif