2007-01-23 Rolf Bjarne Kvinge <RKvinge@novell.com>
[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 using System.Runtime.InteropServices;
33
34 namespace System.Windows.Forms {
35 #if NET_2_0
36         [ComVisible (true)]
37         [ClassInterface(ClassInterfaceType.AutoDispatch)]
38 #endif
39         [DesignTimeVisible(false)]
40         [ToolboxItem(false)]
41         public sealed class MdiClient : Control {
42                 #region Local Variables
43                 private int mdi_created;
44                 private ImplicitHScrollBar hbar;
45                 private ImplicitVScrollBar vbar;
46                 private SizeGrip sizegrip;
47                 private int hbar_value;
48                 private int vbar_value;
49                 private bool lock_sizing;
50                 private bool initializing_scrollbars;
51                 private int prev_bottom;
52                 private bool setting_windowstates = false;
53                 internal ArrayList mdi_child_list;
54                 private string form_text;
55                 private bool setting_form_text;
56                 private Form active_child;
57
58                 #endregion      // Local Variables
59
60                 #region Public Classes
61 #if NET_2_0
62                 [ComVisible (false)]
63 #endif
64                 public new class ControlCollection : Control.ControlCollection {
65
66                         private MdiClient owner;
67                         
68                         public ControlCollection(MdiClient owner) : base(owner) {
69                                 this.owner = owner;
70                         }
71
72                         public override void Add(Control value) {
73                                 if ((value is Form) == false || !(((Form)value).IsMdiChild)) {
74                                         throw new ArgumentException("Form must be MdiChild");
75                                 }
76                                 owner.mdi_child_list.Add (value);
77                                 base.Add (value);
78
79                                 // newest member is the active one
80                                 Form form = (Form) value;
81                                 owner.ActiveMdiChild = form;
82                         }
83
84                         public override void Remove(Control value)
85                         {
86                                 Form form = value as Form;
87                                 if (form != null) {
88                                         MdiWindowManager wm = form.WindowManager as MdiWindowManager;
89                                         if (wm != null) {
90                                                 form.Closed -= wm.form_closed_handler;
91                                         }
92                                 }
93
94                                 owner.mdi_child_list.Remove (value);
95                                 base.Remove (value);
96                         }
97                 }
98                 #endregion      // Public Classes
99
100                 #region Public Constructors
101                 public MdiClient()
102                 {
103                         mdi_child_list = new ArrayList ();
104                         BackColor = SystemColors.AppWorkspace;
105                         Dock = DockStyle.Fill;
106                         SetStyle (ControlStyles.Selectable, false);
107                 }
108                 #endregion      // Public Constructors
109
110                 internal void SendFocusToActiveChild ()
111                 {
112                         Form active = this.ActiveMdiChild;
113                         if (active == null) {
114                                 ParentForm.SendControlFocus (this);
115                         } else {
116                                 active.SendControlFocus (active);
117                                 ParentForm.ActiveControl = active;
118                         }
119                 }
120
121                 internal bool HorizontalScrollbarVisible {
122                         get { return hbar != null && hbar.Visible; }
123                 }
124                 internal bool VerticalScrollbarVisible {
125                         get { return vbar != null && vbar.Visible; }
126                 }
127
128                 internal void SetParentText(bool text_changed)
129                 {
130                         if (setting_form_text)
131                                 return;
132
133                         setting_form_text = true;
134
135                         if (text_changed)
136                                 form_text = ParentForm.Text;
137
138                         if (ParentForm.ActiveMaximizedMdiChild == null) {
139                                 ParentForm.Text = form_text;
140                         } else {
141                                 string childText = ParentForm.ActiveMaximizedMdiChild.form.Text;
142                                 if (childText.Length > 0) {
143                                         ParentForm.Text = form_text + " - [" + ParentForm.ActiveMaximizedMdiChild.form.Text + "]";
144                                 } else {
145                                         ParentForm.Text = form_text;
146                                 }
147                         }
148
149                         setting_form_text = false;
150                 }
151
152                 internal override void OnPaintBackgroundInternal (PaintEventArgs pe)
153                 {
154                         if (BackgroundImage != null)
155                                 return;
156
157                         if (Parent == null || Parent.BackgroundImage == null)
158                                 return;
159                         Parent.PaintControlBackground (pe);
160                 }
161
162                 internal Form ParentForm {
163                         get { return (Form) Parent; }
164                 }
165
166                 protected override Control.ControlCollection CreateControlsInstance ()
167                 {
168                         return new MdiClient.ControlCollection (this);
169                 }
170
171                 protected override void WndProc(ref Message m) {
172                         switch ((Msg)m.Msg) {
173                         case Msg.WM_NCPAINT:
174                                 PaintEventArgs pe = XplatUI.PaintEventStart (Handle, false);
175
176                                 Rectangle clip;
177                                 clip = new Rectangle (0, 0, Width, Height);
178
179                                 ControlPaint.DrawBorder3D (pe.Graphics, clip, Border3DStyle.Sunken);
180                                 XplatUI.PaintEventEnd (Handle, false);
181                                 m.Result = IntPtr.Zero;
182                                 return ;
183                         }
184
185                         base.WndProc (ref m);
186                 }
187
188                 protected override void OnResize (EventArgs e)
189                 {
190                         base.OnResize (e);
191
192                         if (Parent != null)
193                                 XplatUI.InvalidateNC (Parent.Handle);
194                         // Should probably make this into one loop
195                         SizeScrollBars ();
196                         ArrangeWindows ();
197                 }
198 #if NET_2_0
199                 [System.ComponentModel.EditorBrowsable (EditorBrowsableState.Never)]
200 #endif
201                 protected override void ScaleCore (float dx, float dy)
202                 {
203                         base.ScaleCore (dx, dy);
204                 }
205
206                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
207                 {
208                         base.SetBoundsCore (x, y, width, height, specified);
209                 }
210
211                 #region Public Instance Properties
212                 [Localizable(true)]
213                 public override System.Drawing.Image BackgroundImage {
214                         get {
215                                 return base.BackgroundImage;
216                         }
217                         set {
218                                 base.BackgroundImage = value;
219                         }
220                 }
221
222 #if NET_2_0
223                 [EditorBrowsable (EditorBrowsableState.Never)]
224                 [Browsable (false)]
225                 public override ImageLayout BackgroundImageLayout {
226                         get {
227                                 return base.BackgroundImageLayout;
228                         }
229                         set {
230                                 base.BackgroundImageLayout = value;
231                         }
232                 }
233 #endif
234
235                 public Form [] MdiChildren {
236                         get {
237                                 if (mdi_child_list == null)
238                                         return new Form [0];
239                                 return (Form []) mdi_child_list.ToArray (typeof (Form));
240                         }
241                 }
242                 #endregion      // Public Instance Properties
243
244 #region Protected Instance Properties
245                 protected override CreateParams CreateParams {
246                         get {
247                                 CreateParams result = base.CreateParams;
248                                 result.ExStyle |= (int) WindowExStyles.WS_EX_CLIENTEDGE;
249                                 return result;
250                         }
251                 }
252                 #endregion      // Protected Instance Properties
253
254                 #region Public Instance Methods
255                 public void LayoutMdi (MdiLayout value) {
256
257                         int max_width = Int32.MaxValue;
258                         int max_height = Int32.MaxValue;
259
260                         if (Parent != null) {
261                                 max_width = Parent.Width;
262                                 max_height = Parent.Height;
263                         }
264
265                         switch (value) {
266                         case MdiLayout.Cascade: {
267                                 int i = 0;
268                                 for (int c = Controls.Count - 1; c >= 0; c--) {
269                                         Form form = (Form) Controls [c];
270
271                                         if (form.WindowState == FormWindowState.Minimized)
272                                                 continue;
273                 
274                                         int l = 22 * i;
275                                         int t = 22 * i;
276
277                                         if (i != 0 && (l + form.Width > max_width || t + form.Height > max_height)) {
278                                                 i = 0;
279                                                 l = 22 * i;
280                                                 t = 22 * i;
281                                         }
282
283                                         form.Left = l;
284                                         form.Top = t;
285
286                                         i++;
287                                 }
288                                 break;
289                                 }
290                         case MdiLayout.ArrangeIcons:
291                                 ArrangeIconicWindows (true);
292                                 break;
293                         case MdiLayout.TileHorizontal:
294                         case MdiLayout.TileVertical: {
295                                 // First count number of windows to tile
296                                 int total = 0;
297                                 for (int i = 0; i < Controls.Count; i++) {
298                                         Form form = Controls [i] as Form;
299                                         
300                                         if (form == null)
301                                                 continue;
302                                         
303                                         if (!form.Visible)
304                                                 continue;
305                                         
306                                         if (form.WindowState == FormWindowState.Minimized)
307                                                 continue;
308                                                 
309                                         total++;
310                                 }
311                                 if (total <= 0)
312                                         return;
313
314                                 // Calculate desired height and width
315                                 Size newSize;
316                                 Size offset;
317                                 if (value == MdiLayout.TileHorizontal) {
318                                         newSize = new Size (ClientSize.Width, ClientSize.Height / total);
319                                         offset = new Size (0, newSize.Height);
320                                 } else {
321                                         newSize = new Size (ClientSize.Width / total, ClientSize.Height);
322                                         offset = new Size (newSize.Width, 0);
323                                 }
324                                 
325                                 // Loop again and set the size and location.
326                                 Point nextLocation = Point.Empty;
327                                 
328                                 for (int i = 0; i < Controls.Count; i++) {
329                                         Form form = Controls [i] as Form;
330
331                                         if (form == null)
332                                                 continue;
333
334                                         if (!form.Visible)
335                                                 continue;
336
337                                         if (form.WindowState == FormWindowState.Minimized)
338                                                 continue;
339
340                                         form.Size = newSize;
341                                         form.Location = nextLocation;
342                                         nextLocation += offset;
343                                 }
344                                 
345                                 break;
346                                 }
347                         }
348                 }
349                 #endregion      // Public Instance Methods
350
351                 #region Protected Instance Methods
352                 #endregion      // Protected Instance Methods
353
354                 internal void SizeScrollBars ()
355                 {
356                         if (lock_sizing)
357                                 return;
358
359                         if (Controls.Count == 0 || ((Form) Controls [0]).WindowState == FormWindowState.Maximized) {
360                                 if (hbar != null)
361                                         hbar.Visible = false;
362                                 if (vbar != null)
363                                         vbar.Visible = false;
364                                 if (sizegrip != null)
365                                         sizegrip.Visible = false;
366                                 return;
367                         }
368
369                         int right = 0;
370                         int left = 0;
371                         int top = 0;
372                         int bottom = 0;
373
374                         foreach (Form child in Controls) {
375                                 if (!child.Visible)
376                                         continue;
377                                 if (child.Right > right)
378                                         right = child.Right;
379                                 if (child.Left < left) {
380                                         left = child.Left;
381                                 }
382                                 
383                                 if (child.Bottom > bottom)
384                                         bottom = child.Bottom;
385                                 if (child.Top < 0) {
386                                         top = child.Top;
387                                 }
388                         }
389
390                         int available_width = ClientSize.Width;
391                         int available_height = ClientSize.Height;
392
393                         bool need_hbar = false;
394                         bool need_vbar = false;
395
396                         if (right - left > available_width || left < 0) {
397                                 need_hbar = true;
398                                 available_height -= SystemInformation.HorizontalScrollBarHeight;
399                         }
400                         if (bottom - top > available_height || top < 0) {
401                                 need_vbar = true;
402                                 available_width -= SystemInformation.VerticalScrollBarWidth;
403
404                                 if (!need_hbar && (right - left > available_width || left < 0)) {
405                                         need_hbar = true;
406                                         available_height -= SystemInformation.HorizontalScrollBarHeight;
407                                 }
408                         }
409                         
410                         if (need_hbar) {
411                                 if (hbar == null) {
412                                         hbar = new ImplicitHScrollBar ();
413                                         Controls.AddImplicit (hbar);
414                                 }
415                                 hbar.Visible = true;
416                                 CalcHBar (left, right, need_vbar);
417                         } else if (hbar != null)
418                                 hbar.Visible = false;
419
420                         if (need_vbar) {
421                                 if (vbar == null) {
422                                         vbar = new ImplicitVScrollBar ();
423                                         Controls.AddImplicit (vbar);
424                                 }
425                                 vbar.Visible = true;
426                                 CalcVBar (top, bottom, need_hbar);
427                         } else if (vbar != null)
428                                 vbar.Visible = false;
429
430                         if (need_hbar && need_vbar) {
431                                 if (sizegrip == null) {
432                                         sizegrip = new SizeGrip ();
433                                         sizegrip.CapturedControl = this.ParentForm;
434                                         Controls.AddImplicit (sizegrip);
435                                 }
436                                 sizegrip.Location = new Point (hbar.Right, vbar.Bottom);
437                                 sizegrip.Width = vbar.Width;
438                                 sizegrip.Height = hbar.Height;
439                                 sizegrip.Visible = true;
440                                 XplatUI.SetZOrder (sizegrip.Handle, vbar.Handle, false, false);
441                         } else if (sizegrip != null) {
442                                 sizegrip.Visible = false;
443                         }
444                 }
445
446                 private void CalcHBar (int left, int right, bool vert_vis)
447                 {
448                         initializing_scrollbars = true;
449
450                         hbar.Left = 0;
451                         hbar.Top = ClientRectangle.Bottom - hbar.Height;
452                         hbar.Width = ClientRectangle.Width - (vert_vis ? SystemInformation.VerticalScrollBarWidth : 0);
453                         hbar.LargeChange = 50;
454                         hbar.Minimum = Math.Min (left, 0);
455                         hbar.Maximum = Math.Max (right - ClientSize.Width + 51 + (vert_vis ? SystemInformation.VerticalScrollBarWidth : 0), 0);
456                         hbar.Value = 0;
457                         hbar_value = 0;
458                         hbar.ValueChanged += new EventHandler (HBarValueChanged);
459                         XplatUI.SetZOrder (hbar.Handle, IntPtr.Zero, true, false);
460                         
461                         initializing_scrollbars = false;
462                 }
463
464                 private void CalcVBar (int top, int bottom, bool horz_vis)
465                 {
466                         initializing_scrollbars = true;
467                         
468                         vbar.Top = 0;
469                         vbar.Left = ClientRectangle.Right - vbar.Width;
470                         vbar.Height = ClientRectangle.Height - (horz_vis ? SystemInformation.HorizontalScrollBarHeight : 0);
471                         vbar.LargeChange = 50;
472                         vbar.Minimum = Math.Min (top, 0);
473                         vbar.Maximum = Math.Max (bottom - ClientSize.Height + 51 + (horz_vis ? SystemInformation.HorizontalScrollBarHeight : 0), 0);
474                         vbar.Value = 0;
475                         vbar_value = 0;
476                         vbar.ValueChanged += new EventHandler (VBarValueChanged);
477                         XplatUI.SetZOrder (vbar.Handle, IntPtr.Zero, true, false);
478                         
479                         initializing_scrollbars = false;
480                 }
481
482                 private void HBarValueChanged (object sender, EventArgs e)
483                 {
484                         if (initializing_scrollbars)
485                                 return;
486                         
487                         if (hbar.Value == hbar_value)
488                                 return;
489
490                         lock_sizing = true;
491
492                         try {
493                                 int diff = hbar_value - hbar.Value;
494                                 foreach (Form child in Controls) {
495                                         child.Left += diff;
496                                 }
497                         } finally {
498                                 lock_sizing = false;
499                         }
500
501                         hbar_value = hbar.Value;
502                 }
503
504                 private void VBarValueChanged (object sender, EventArgs e)
505                 {
506                         if (initializing_scrollbars)
507                                 return;
508                                 
509                         if (vbar.Value == vbar_value)
510                                 return;
511
512                         lock_sizing = true;
513
514                         try {
515                                 int diff = vbar_value - vbar.Value;
516                                 foreach (Form child in Controls) {
517                                         child.Top += diff;
518                                 }
519                         } finally {
520                                 lock_sizing = false;
521                         }
522
523                         vbar_value = vbar.Value;
524                 }
525
526                 private void ArrangeWindows ()
527                 {
528                         int change = 0;
529                         if (prev_bottom != -1)
530                                 change = Bottom - prev_bottom;
531
532                         foreach (Control c in Controls) {
533                                 Form child = c as Form;
534
535                                 if (c == null || !child.Visible)
536                                         continue;
537
538                                 MdiWindowManager wm = child.WindowManager as MdiWindowManager;
539                                 if (wm.GetWindowState () == FormWindowState.Maximized)
540                                         child.Bounds = wm.MaximizedBounds;
541
542                                 if (wm.GetWindowState () == FormWindowState.Minimized) {
543                                         child.Top += change;
544                                 }
545                                         
546                         }
547
548                         prev_bottom = Bottom;
549                 }
550
551                 internal void ArrangeIconicWindows (bool rearrange_all)
552                 {
553                         int xspacing = 160;
554                         int yspacing = 27;
555
556                         Rectangle rect = new Rectangle (0, 0, xspacing, yspacing);
557
558                         lock_sizing = true;
559                         foreach (Form form in Controls) {
560                                 if (form.WindowState != FormWindowState.Minimized)
561                                         continue;
562
563                                 MdiWindowManager wm = (MdiWindowManager) form.WindowManager;
564                                 
565                                 if (wm.IconicBounds != Rectangle.Empty && !rearrange_all) {
566                                         if (form.Bounds != wm.IconicBounds)
567                                                 form.Bounds = wm.IconicBounds;
568                                         continue;
569                                 }
570                                 
571                                 // Need to get the width in the loop cause some themes might have
572                                 // different widths for different styles
573                                 int bw = ThemeEngine.Current.ManagedWindowBorderWidth (wm);
574                                 
575                                 int height = wm.TitleBarHeight + (bw * 2);
576                                 
577                                 bool success = true;
578                                 int startx, starty, currentx, currenty;
579                                 
580                                 startx = 0;
581                                 starty = ClientSize.Height - yspacing;
582                                 currentx = startx;
583                                 currenty = starty;
584                                 
585                                 do {
586                                         rect.X = currentx;
587                                         rect.Y = currenty;
588                                         rect.Height = height;
589                                         success = true;
590                                         foreach (Form form2 in Controls) {
591                                                 if (form2 == form || form2.window_state != FormWindowState.Minimized)
592                                                         continue;
593                                                 
594                                                 if (form2.Bounds.IntersectsWith(rect)) {
595                                                         success = false;
596                                                         break;
597                                                 }
598                                         }
599                                         if (!success) { 
600                                                 currentx += xspacing;
601                                                 if (currentx + xspacing > Right) {
602                                                         currentx = startx;
603                                                         currenty -= Math.Max(yspacing, height);
604                                                 } 
605                                         }
606                                 } while (!success);
607                                 wm.IconicBounds = rect;
608                                 form.Bounds = wm.IconicBounds;
609                         }
610                         lock_sizing = false;
611                 }
612
613                 internal void CloseChildForm (Form form)
614                 {
615                         if (Controls.Count > 1) {
616                                 Form next = (Form) Controls [1];
617                                 if (form.WindowState == FormWindowState.Maximized)
618                                         next.WindowState = FormWindowState.Maximized;
619                                 ActivateChild (next);
620                         }
621
622                         Controls.Remove (form);
623                         form.Close ();
624
625                         if (Controls.Count == 0) {
626                                 XplatUI.RequestNCRecalc (Parent.Handle);
627                                 ParentForm.PerformLayout ();
628                         }
629                         SizeScrollBars ();
630                         SetParentText (false);
631                 }
632
633                 internal void ActivateNextChild ()
634                 {
635                         if (Controls.Count < 1)
636                                 return;
637                         if (Controls.Count == 1 && Controls[0] == ActiveMdiChild)
638                                 return;
639                                 
640                         Form front = (Form) Controls [0];
641                         Form form = (Form) Controls [1];
642
643                         ActivateChild (form);
644                         front.SendToBack ();
645                 }
646
647                 internal void ActivatePreviousChild ()
648                 {
649                         if (Controls.Count <= 1)
650                                 return;
651                         
652                         Form back = (Form) Controls [Controls.Count - 1];
653                         
654                         ActivateChild (back);
655                 }
656
657                 internal void ActivateChild (Form form)
658                 {
659                         if (Controls.Count < 1)
660                                 return;
661                         
662                         if (ParentForm.is_changing_visible_state)
663                                 return;
664                         
665                         Form current = (Form) Controls [0];
666
667                         // We want to resize the new active form before it is 
668                         // made active to avoid flickering. Can't do it in the
669                         // normal way (form.WindowState = Maximized) since it's not
670                         // active yet and everything would just return to before. 
671                         // We also won't suspend layout, this way the layout will
672                         // happen before the form is made active (and in many cases
673                         // before it is visible, which avoids flickering as well).
674                         MdiWindowManager wm = (MdiWindowManager)form.WindowManager;
675                         if (current.WindowState == FormWindowState.Maximized && form.WindowState != FormWindowState.Maximized && form.Visible) {
676                                 FormWindowState old_state = form.window_state;
677                                 SetWindowState (form, old_state, FormWindowState.Maximized, true);
678                                 wm.was_minimized = form.window_state == FormWindowState.Minimized;
679                                 form.window_state = FormWindowState.Maximized;
680                                 SetParentText (false);
681                         }
682                         form.BringToFront ();
683                         form.SendControlFocus (form);
684                         SetWindowStates (wm);
685                         if (current != form) {
686                                 form.has_focus = false;
687                                 XplatUI.InvalidateNC (current.Handle);
688                                 XplatUI.InvalidateNC (form.Handle);
689                         }
690                         active_child = (Form) Controls [0];
691                         
692                         if (active_child.Visible)
693                                 ParentForm.ActiveControl = active_child;
694                 }
695
696                 internal override IntPtr AfterTopMostControl ()
697                 {
698                         // order of scrollbars:
699                         // top = vertical
700                         //       sizegrid
701                         // bottom = horizontal
702                         if (hbar != null && hbar.Visible)
703                                 return hbar.Handle;
704                         // no need to check for sizegrip since it will only
705                         // be visible if hbar is visible.
706                         if (vbar != null && vbar.Visible)
707                                 return vbar.Handle;
708                                 
709                         return base.AfterTopMostControl ();
710                 }
711                 
712                 internal bool SetWindowStates (MdiWindowManager wm)
713                 {
714                 /*
715                         MDI WindowState behaviour:
716                         - If the active window is maximized, all other maximized windows are normalized.
717                         - If a normal window gets focus and the original active window was maximized, 
718                           the normal window gets maximized and the original window gets normalized.
719                         - If a minimized window gets focus and the original window was maximized, 
720                           the minimzed window gets maximized and the original window gets normalized. 
721                           If the ex-minimized window gets deactivated, it will be normalized.
722                 */
723                         Form form = wm.form;
724
725                         if (setting_windowstates) {
726                                 return false;
727                         }
728                         
729                         if (!form.Visible)
730                                 return false;
731                         
732                         bool is_active = wm.IsActive();
733                         bool maximize_this = false;
734                         
735                         if (!is_active){
736                                 return false;
737                         }
738                         
739                         ArrayList minimize_these = new ArrayList ();
740                         ArrayList normalize_these = new ArrayList ();
741
742                         setting_windowstates = true;
743                         foreach (Form frm in mdi_child_list) {
744                                 if (frm == form) {
745                                         continue;
746                                 } else if (!frm.Visible){
747                                         continue;
748                                 }
749                                 if (frm.WindowState == FormWindowState.Maximized && is_active) {
750                                         maximize_this = true;   
751                                         if (((MdiWindowManager) frm.window_manager).was_minimized) {
752                                                 minimize_these.Add (frm); 
753                                         } else {
754                                                 normalize_these.Add (frm); 
755                                         }
756                                 }
757                         }
758
759                         if (maximize_this && form.WindowState != FormWindowState.Maximized) {
760                                 wm.was_minimized = form.window_state == FormWindowState.Minimized;
761                                 form.WindowState = FormWindowState.Maximized;
762                         }
763                         
764                         foreach (Form frm in minimize_these)
765                                 frm.WindowState = FormWindowState.Minimized;
766
767                         foreach (Form frm in normalize_these)
768                                 frm.WindowState = FormWindowState.Normal;
769
770
771                         SetParentText (false);
772                         
773                         XplatUI.RequestNCRecalc (ParentForm.Handle);
774                         XplatUI.RequestNCRecalc (Handle);
775
776                         SizeScrollBars ();
777
778                         setting_windowstates = false;
779
780 #if NET_2_0
781                         if (form.MdiParent.MainMenuStrip != null)
782                                 form.MdiParent.MainMenuStrip.RefreshMdiItems ();
783 #endif
784
785                         return maximize_this;
786                 }
787
788                 internal void SetWindowState (Form form, FormWindowState old_window_state, FormWindowState new_window_state, bool is_activating_child)
789                 {
790                         bool mdiclient_layout;
791
792                         MdiWindowManager wm = (MdiWindowManager) form.window_manager;
793
794                         if (!is_activating_child && new_window_state == FormWindowState.Maximized && !wm.IsActive ()) {
795                                 ActivateChild (form);
796                                 return;
797                         }
798
799                         if (SetWindowStates (wm))
800                                 return;
801
802                         if (old_window_state == new_window_state)
803                                 return;
804                                 
805                         if (old_window_state == FormWindowState.Normal)
806                                 wm.NormalBounds = form.Bounds;
807
808                         mdiclient_layout = old_window_state == FormWindowState.Maximized || new_window_state == FormWindowState.Maximized;
809
810                         switch (new_window_state) {
811                         case FormWindowState.Minimized:
812                                 ArrangeIconicWindows (false);
813                                 break;
814                         case FormWindowState.Maximized:
815                                 form.Bounds = wm.MaximizedBounds;
816                                 break;
817                         case FormWindowState.Normal:
818                                 form.Bounds = wm.NormalBounds;
819                                 break;
820                         }
821
822                         wm.UpdateWindowDecorations (new_window_state);
823
824                         form.ResetCursor ();
825
826                         if (mdiclient_layout)
827                                 Parent.PerformLayout ();
828
829                         //XplatUI.RequestNCRecalc (Parent.Handle);
830                         //XplatUI.RequestNCRecalc (form.Handle);
831                         if (!setting_windowstates)
832                                 SizeScrollBars ();
833                 }
834                 internal int ChildrenCreated {
835                         get { return mdi_created; }
836                         set { mdi_created = value; }
837                 }
838
839                 internal Form ActiveMdiChild {
840                         get {
841 #if NET_2_0
842                                 if (!ParentForm.Visible)
843                                         return null;
844 #endif
845                                 if (Controls.Count < 1)
846                                         return null;
847                                         
848                                 if (!ParentForm.IsHandleCreated)
849                                         return null;
850                                 
851                                 if (!ParentForm.has_been_visible)
852                                         return null;
853                                         
854                                 if (!ParentForm.Visible)
855                                         return active_child;
856                                 
857                                 active_child = null;
858                                 for (int i = 0; i < Controls.Count; i++) {
859                                         if (Controls [i].Visible) {
860                                                 active_child = (Form) Controls [i];
861                                                 break;
862                                         }
863                                 }
864                                 return active_child;
865                         }
866                         set {
867                                 ActivateChild (value);
868                         }
869                 }
870                 
871                 internal void ActivateActiveMdiChild ()
872                 {
873                         if (ParentForm.is_changing_visible_state)
874                                 return;
875                                 
876                         for (int i = 0; i < Controls.Count; i++) {
877                                 if (Controls [i].Visible) {
878                                         ActivateChild ((Form) Controls [i]);
879                                         return;
880                                 }
881                         }
882                 }
883         }
884 }
885