In .:
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / MdiClient.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //      Peter Bartok    pbartok@novell.com
24 //
25 //
26
27 // NOT COMPLETE
28
29 using System.Collections;
30 using System.ComponentModel;
31 using System.Drawing;
32
33 namespace System.Windows.Forms {
34         [DesignTimeVisible(false)]
35         [ToolboxItem(false)]
36         public sealed class MdiClient : Control {
37                 #region Local Variables
38                 private int mdi_created;
39                 private Form active;
40                 private HScrollBar hbar;
41                 private VScrollBar vbar;
42                 private SizeGrip sizegrip;
43                 private int hbar_value;
44                 private int vbar_value;
45                 private bool lock_sizing;
46                 
47                 #endregion      // Local Variables
48
49                 #region Public Classes
50                 public new class ControlCollection : Control.ControlCollection {
51                         MdiClient       owner;
52                         
53                         public ControlCollection(MdiClient owner) : base(owner) {
54                                 this.owner = owner;
55                                 controls = new ArrayList ();
56                         }
57
58                         public override void Add(Control value) {
59                                 if ((value is Form) == false || !(((Form)value).IsMdiChild)) {
60                                         throw new ArgumentException("Form must be MdiChild");
61                                 }
62                                 base.Add (value);
63                                 SetChildIndex (value, 0); // always insert at front
64                                 // newest member is the active one
65                                 owner.ActiveMdiChild = (Form) value;
66
67                                 value.LocationChanged += new EventHandler (owner.FormLocationChanged);
68                         }
69
70                         public override void Remove(Control value) {
71                                 base.Remove (value);
72                         }
73                 }
74                 #endregion      // Public Classes
75
76                 #region Public Constructors
77                 public MdiClient() {
78                         BackColor = SystemColors.AppWorkspace;
79                         Dock = DockStyle.Fill;
80                         SetStyle (ControlStyles.Selectable, false);
81                 }
82                 #endregion      // Public Constructors
83
84                 protected override Control.ControlCollection CreateControlsInstance ()
85                 {
86                         return new MdiClient.ControlCollection (this);
87                 }
88
89                 protected override void WndProc(ref Message m) {
90                         /*
91                         switch ((Msg) m.Msg) {
92                                 case Msg.WM_PAINT: {                            
93                                         Console.WriteLine ("ignoring paint");
94                                         return;
95                                 }
96                         }
97                         */
98                         base.WndProc (ref m);
99                 }
100
101                 protected override void OnResize (EventArgs e)
102                 {
103                         base.OnResize (e);
104
105                         // Should probably make this into one loop
106                         SizeScrollBars ();
107                         SizeMaximized ();
108                 }
109
110                 protected override void ScaleCore (float dx, float dy)
111                 {
112                         base.ScaleCore (dx, dy);
113                 }
114
115                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
116                 {
117                         base.SetBoundsCore (x, y, width, height, specified);
118                 }
119
120                 #region Public Instance Properties
121                 [Localizable(true)]
122                 public override System.Drawing.Image BackgroundImage {
123                         get {
124                                 return base.BackgroundImage;
125                         }
126                         set {
127                                 base.BackgroundImage = value;
128                         }
129                 }
130
131                 public Form[] MdiChildren {
132                         get {
133                                 Form[]  children;
134
135                                 children = new Form[Controls.Count];
136                                 Controls.CopyTo(children, 0);
137
138                                 return children;
139                         }
140                 }
141                 #endregion      // Public Instance Properties
142
143 #region Protected Instance Properties
144                 protected override CreateParams CreateParams {
145                         get {
146                                 return base.CreateParams;
147                         }
148                 }
149                 #endregion      // Protected Instance Properties
150
151                 #region Public Instance Methods
152                 public void LayoutMdi(MdiLayout value) {
153                         throw new NotImplementedException();
154                 }
155                 #endregion      // Public Instance Methods
156
157                 #region Protected Instance Methods
158                 #endregion      // Protected Instance Methods
159
160                 private void SizeScrollBars ()
161                 {
162                         if (lock_sizing)
163                                 return;
164
165                         if (Controls.Count == 0 || ((Form) Controls [0]).WindowState == FormWindowState.Maximized) {
166                                 if (hbar != null)
167                                         hbar.Visible = false;
168                                 if (vbar != null)
169                                         vbar.Visible = false;
170                                 return;
171                         }
172                                 
173                         bool hbar_required = false;
174                         bool vbar_required = false;
175
176                         int right = 0;
177                         int left = 0;
178                         foreach (Form child in Controls) {
179                                 if (!child.Visible)
180                                         continue;
181                                 if (child.Right > right)
182                                         right = child.Right;
183                                 if (child.Left < left) {
184                                         hbar_required = true;
185                                         left = child.Left;
186                                 }
187                         }
188
189                         int top = 0;
190                         int bottom = 0;
191                         foreach (Form child in Controls) {
192                                 if (!child.Visible)
193                                         continue;
194                                 if (child.Bottom > bottom)
195                                         bottom = child.Bottom;
196                                 if (child.Top < 0) {
197                                         vbar_required = true;
198                                         top = child.Top;
199                                 }
200                         }
201
202                         int right_edge = Right;
203                         int bottom_edge = Bottom;
204                         int prev_right_edge;
205                         int prev_bottom_edge;
206
207                         bool need_hbar = false;
208                         bool need_vbar = false;
209
210                         do {
211                                 prev_right_edge = right_edge;
212                                 prev_bottom_edge = bottom_edge;
213
214                                 if (hbar_required || right > right_edge) {
215                                         need_hbar = true;
216                                         bottom_edge = Bottom - SystemInformation.HorizontalScrollBarHeight;
217                                 } else {
218                                         need_hbar = false;
219                                         bottom_edge = Bottom;
220                                 }
221
222                                 if (vbar_required || bottom > bottom_edge) {
223                                         need_vbar = true;
224                                         right_edge = Right - SystemInformation.VerticalScrollBarWidth;
225                                 } else {
226                                         need_vbar = false;
227                                         right_edge = Right;
228                                 }
229
230                         } while (right_edge != prev_right_edge || bottom_edge != prev_bottom_edge);
231
232                         if (need_hbar) {
233                                 if (hbar == null) {
234                                         hbar = new HScrollBar ();
235                                         Controls.AddImplicit (hbar);
236                                 }
237                                 hbar.Visible = true;
238                                 CalcHBar (left, right, right_edge, need_vbar);
239                         } else if (hbar != null)
240                                 hbar.Visible = false;
241
242                         if (need_vbar) {
243                                 if (vbar == null) {
244                                         vbar = new VScrollBar ();
245                                         Controls.AddImplicit (vbar);
246                                 }
247                                 vbar.Visible = true;
248                                 CalcVBar (top, bottom, bottom_edge, need_hbar);
249                         } else if (vbar != null)
250                                 vbar.Visible = false;
251
252                         if (need_hbar && need_vbar) {
253                                 if (sizegrip == null) {
254                                         sizegrip = new SizeGrip ();
255                                         Controls.AddImplicit (sizegrip);
256                                 }
257                                 sizegrip.Location = new Point (hbar.Right, vbar.Bottom);
258                                 sizegrip.Width = vbar.Width;
259                                 sizegrip.Height = hbar.Height;
260                                 sizegrip.Visible = true;
261                         } else if (sizegrip != null) {
262                                 sizegrip.Visible = false;
263                         }
264                 }
265
266                 private void CalcHBar (int left, int right, int right_edge, bool vert_vis)
267                 {
268                         int virtual_left = Math.Min (left, 0);
269                         int virtual_right = Math.Max (right, right_edge);
270                         int diff = (virtual_right - virtual_left) - right_edge;
271                         hbar.Left = 0;
272                         hbar.Top = Height - hbar.Height;
273                         hbar.Width = Width - (vert_vis ? SystemInformation.VerticalScrollBarWidth : 0);
274                         hbar.LargeChange = 50;
275                         hbar.Maximum = diff + 51;
276                         hbar.Value = -virtual_left;
277                         hbar.ValueChanged += new EventHandler (HBarValueChanged);
278                 }
279
280                 private void CalcVBar (int top, int bottom, int bottom_edge, bool horz_vis)
281                 {
282                         int virtual_top = Math.Min (top, 0);
283                         int virtual_bottom = Math.Max (bottom, bottom_edge);
284                         int diff = (virtual_bottom - virtual_top) - bottom_edge;
285                         vbar.Top = 0;
286                         vbar.Left = Width - vbar.Width;
287                         vbar.Height = Height - (horz_vis ? SystemInformation.HorizontalScrollBarHeight : 0);
288                         vbar.LargeChange = 50;
289                         vbar.Maximum = diff + 51;
290                         vbar.Value = -virtual_top;
291                         vbar.ValueChanged += new EventHandler (VBarValueChanged);
292                         
293                 }
294
295                 private void HBarValueChanged (object sender, EventArgs e)
296                 {
297                         if (hbar.Value == hbar_value)
298                                 return;
299
300                         lock_sizing = true;
301
302                         try {
303                                 foreach (Form child in Controls) {
304                                         child.Left += hbar_value - hbar.Value;
305                                 }
306                         } finally {
307                                 lock_sizing = false;
308                         }
309
310                         hbar_value = hbar.Value;
311                         lock_sizing = false;
312                 }
313
314                 private void VBarValueChanged (object sender, EventArgs e)
315                 {
316                         if (vbar.Value == vbar_value)
317                                 return;
318
319                         lock_sizing = true;
320
321                         try {
322                                 foreach (Form child in Controls) {
323                                         child.Top += vbar_value - vbar.Value;
324                                 }
325                         } finally {
326                                 lock_sizing = false;
327                         }
328
329                         vbar_value = vbar.Value;
330                         lock_sizing = false;
331                 }
332
333                 private void SizeMaximized ()
334                 {
335                         foreach (Form child in Controls) {
336                                 if (!child.Visible)
337                                         continue;
338                                 MdiWindowManager wm = (MdiWindowManager) child.WindowManager;
339                                 if (wm.GetWindowState () == FormWindowState.Maximized)
340                                         wm.SizeMaximized ();
341                         }
342                 }
343
344                 private void FormLocationChanged (object sender, EventArgs e)
345                 {
346                         SizeScrollBars ();
347                 }
348
349                 private int iconic_x = -1;
350                 private int iconic_y = -1;
351                 internal void ArrangeIconicWindows ()
352                 {
353                         int xspacing = 160;
354                         int yspacing = 25;
355
356                         if (iconic_x == -1 && iconic_y == -1) {
357                                 iconic_x = Left;
358                                 iconic_y = Bottom - yspacing;
359                         }
360
361                         lock_sizing = true;
362                         foreach (Form form in Controls) {
363                                 if (form.WindowState != FormWindowState.Minimized)
364                                         continue;
365
366                                 MdiWindowManager wm = (MdiWindowManager) form.WindowManager;
367
368                                 if (wm.IconicBounds != Rectangle.Empty) {
369                                         form.Bounds = wm.IconicBounds;
370                                         continue;
371                                 }
372                                         
373                                 // The extra one pixel is a cheap hack for now until we
374                                 // handle 0 client sizes properly in the driver
375                                 int height = wm.TitleBarHeight + (wm.BorderWidth * 2) + 1; 
376                                 Rectangle rect = new Rectangle (iconic_x, iconic_y, xspacing, height);
377                                 form.Bounds = wm.IconicBounds = rect;
378
379                                 iconic_x += xspacing;
380                                 if (iconic_x >= Right) {
381                                         iconic_x = Left;
382                                         iconic_y -= height;
383                                 }
384                         }
385                         lock_sizing = false;
386                 }
387
388                 internal void ActivateChild (Form form)
389                 {
390                         form.BringToFront ();
391                         active = form;
392
393                         foreach (Form child in Controls) {
394                                 if (child == form)
395                                         continue;
396                                 // TODO: We need to repaint the decorations here
397                         }
398                 }
399
400                 internal int ChildrenCreated {
401                         get { return mdi_created; }
402                         set { mdi_created = value; }
403                 }
404
405                 internal Form ActiveMdiChild {
406                         get { return active; }
407                         set { active = value; }
408                 }
409         }
410 }