In .:
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms.Layout / DefaultLayout.cs
1 //
2 // DefaultLayout.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;
30 using System.Drawing;
31
32 namespace System.Windows.Forms.Layout
33 {
34         class DefaultLayout : LayoutEngine
35         {
36                 void LayoutDockedChildren (Control parent, Control[] controls)
37                 {
38                         Rectangle space = parent.DisplayRectangle;
39
40                         // Deal with docking; go through in reverse, MS docs say that lowest Z-order is closest to edge
41                         for (int i = controls.Length - 1; i >= 0; i--) {
42                                 Control child = controls[i];
43
44                                 if (!child.VisibleInternal
45                                     || child.ControlLayoutType == Control.LayoutType.Anchor)
46                                         continue;
47
48                                 switch (child.Dock) {
49                                 case DockStyle.None:
50                                         // Do nothing
51                                         break;
52
53                                 case DockStyle.Left:
54                                         child.SetImplicitBounds (space.Left, space.Y, child.Width, space.Height);
55                                         space.X += child.Width;
56                                         space.Width -= child.Width;
57                                         break;
58
59                                 case DockStyle.Top:
60                                         child.SetImplicitBounds (space.Left, space.Y, space.Width, child.Height);
61                                         space.Y += child.Height;
62                                         space.Height -= child.Height;
63                                         break;
64
65                                 case DockStyle.Right:
66                                         child.SetImplicitBounds (space.Right - child.Width, space.Y, child.Width, space.Height);
67                                         space.Width -= child.Width;
68                                         break;
69
70                                 case DockStyle.Bottom:
71                                         child.SetImplicitBounds (space.Left, space.Bottom - child.Height, space.Width, child.Height);
72                                         space.Height -= child.Height;
73                                         break;
74                                 }
75                         }
76
77                         for (int i = controls.Length - 1; i >= 0; i--) {
78                                 Control child = controls[i];
79
80                                 if (child.VisibleInternal
81                                     && (child.ControlLayoutType == Control.LayoutType.Dock)
82                                     && (child.Dock == DockStyle.Fill))
83                                         child.SetBounds (space.Left, space.Top, space.Width, space.Height);
84                         }
85                 }
86
87                 void LayoutAnchoredChildren (Control parent, Control[] controls)
88                 {
89                         Rectangle space = parent.DisplayRectangle;
90
91                         for (int i = 0; i < controls.Length; i++) {
92                                 int left;
93                                 int top;
94                                 int width;
95                                 int height;
96
97                                 Control child = controls[i];
98
99                                 if (!child.VisibleInternal
100                                     || child.ControlLayoutType == Control.LayoutType.Dock)
101                                         continue;
102
103                                 AnchorStyles anchor = child.Anchor;
104
105                                 left = child.Left;
106                                 top = child.Top;
107                                 width = child.Width;
108                                 height = child.Height;
109
110                                 if ((anchor & AnchorStyles.Right) != 0) {
111                                         if ((anchor & AnchorStyles.Left) != 0)
112                                                 width = space.Width - child.dist_right - left;
113                                         else
114                                                 left = space.Width - child.dist_right - width;
115                                 }
116                                 else if ((anchor & AnchorStyles.Left) == 0) {
117                                         // left+=diff_width/2 will introduce rounding errors (diff_width removed from svn after r51780)
118                                         // This calculates from scratch every time:
119                                         left = left + (space.Width - (left + width + child.dist_right)) / 2;
120                                 }
121
122                                 if ((anchor & AnchorStyles.Bottom) != 0) {
123                                         if ((anchor & AnchorStyles.Top) != 0)
124                                                 height = space.Height - child.dist_bottom - top;
125                                         else
126                                                 top = space.Height - child.dist_bottom - height;
127                                 }
128                                 else if ((anchor & AnchorStyles.Top) == 0) {
129                                         // top += diff_height/2 will introduce rounding errors (diff_height removed from after r51780)
130                                         // This calculates from scratch every time:
131                                         top = top + (space.Height - (top + height + child.dist_bottom)) / 2;
132                                 }
133
134                                 // Sanity
135                                 if (width < 0)
136                                         width = 0;
137
138                                 if (height < 0)
139                                         height = 0;
140
141                                 child.SetBounds (left, top, width, height);
142                         }
143                 }
144
145                 public override bool Layout (object container, LayoutEventArgs args)
146                 {
147                         Control parent = container as Control;
148
149                         Control[] controls = parent.Controls.GetAllControls ();
150
151                         LayoutDockedChildren (parent, controls);
152                         LayoutAnchoredChildren (parent, controls);
153
154                         return false;
155                 }
156         }
157 }