* TabControl.cs: Show the tooltip depending on the value
[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 (ref m, 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 (ref m, 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 && Parent.IsHandleCreated)
193                                 XplatUI.InvalidateNC (Parent.Handle);
194                         // Should probably make this into one loop
195                         SizeScrollBars ();
196                         ArrangeWindows ();
197                 }
198 #if NET_2_0
199                 protected override void ScaleControl (SizeF factor, BoundsSpecified specified)
200                 {
201                         // Never change the MdiClient's location
202                         specified &= ~BoundsSpecified.Location;
203
204                         base.ScaleControl (factor, specified);
205                 }
206                 
207                 [System.ComponentModel.EditorBrowsable (EditorBrowsableState.Never)]
208 #endif
209                 protected override void ScaleCore (float dx, float dy)
210                 {
211                         base.ScaleCore (dx, dy);
212                 }
213
214                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
215                 {
216                         base.SetBoundsCore (x, y, width, height, specified);
217                 }
218
219                 #region Public Instance Properties
220                 [Localizable(true)]
221                 public override System.Drawing.Image BackgroundImage {
222                         get {
223                                 return base.BackgroundImage;
224                         }
225                         set {
226                                 base.BackgroundImage = value;
227                         }
228                 }
229
230 #if NET_2_0
231                 [EditorBrowsable (EditorBrowsableState.Never)]
232                 [Browsable (false)]
233                 public override ImageLayout BackgroundImageLayout {
234                         get {
235                                 return base.BackgroundImageLayout;
236                         }
237                         set {
238                                 base.BackgroundImageLayout = value;
239                         }
240                 }
241 #endif
242
243                 public Form [] MdiChildren {
244                         get {
245                                 if (mdi_child_list == null)
246                                         return new Form [0];
247                                 return (Form []) mdi_child_list.ToArray (typeof (Form));
248                         }
249                 }
250                 #endregion      // Public Instance Properties
251
252 #region Protected Instance Properties
253                 protected override CreateParams CreateParams {
254                         get {
255                                 CreateParams result = base.CreateParams;
256                                 result.ExStyle |= (int) WindowExStyles.WS_EX_CLIENTEDGE;
257                                 return result;
258                         }
259                 }
260                 #endregion      // Protected Instance Properties
261
262                 #region Public Instance Methods
263                 public void LayoutMdi (MdiLayout value) {
264
265                         // Don't forget to always call ArrangeIconicWindows 
266                         ArrangeIconicWindows (true);
267
268                         switch (value) {
269                         case MdiLayout.Cascade: {
270                                 int i = 0;
271                                 for (int c = Controls.Count - 1; c >= 0; c--) {
272                                         Form form = (Form) Controls [c];
273
274                                         if (form.WindowState == FormWindowState.Minimized)
275                                                 continue;
276
277                                         if (form.WindowState == FormWindowState.Maximized)
278                                                 form.WindowState = FormWindowState.Normal;
279
280                                         form.Width = System.Convert.ToInt32 (ClientSize.Width * 0.8);
281                                         form.Height = Math.Max (
282                                                                 System.Convert.ToInt32 (ClientSize.Height * 0.8),
283                                                                 SystemInformation.MinimumWindowSize.Height + 2);
284
285                                         int l = 22 * i;
286                                         int t = 22 * i;
287
288                                         if (i != 0 && (l + form.Width > ClientSize.Width || t + form.Height > ClientSize.Height)) {
289                                                 i = 0;
290                                                 l = 22 * i;
291                                                 t = 22 * i;
292                                         }
293
294                                         form.Left = l;
295                                         form.Top = t;
296
297                                         i++;
298                                 }
299                                 break;
300                                 }
301                         case MdiLayout.TileHorizontal:
302                         case MdiLayout.TileVertical: {
303                                 // First count number of windows to tile
304                                 int total = 0;
305                                 
306                                 // And space used by iconic windows
307                                 int clientHeight = ClientSize.Height;
308                                 
309                                 for (int i = 0; i < Controls.Count; i++) {
310                                         Form form = Controls [i] as Form;
311                                         
312                                         if (form == null)
313                                                 continue;
314                                         
315                                         if (!form.Visible)
316                                                 continue;
317
318                                         if (form.WindowState == FormWindowState.Maximized)
319                                                 form.WindowState = FormWindowState.Normal;
320                                         else if (form.WindowState == FormWindowState.Minimized) {
321                                                 if (form.Bounds.Top < clientHeight)
322                                                         clientHeight = form.Bounds.Top;
323                                                 continue;
324                                         }
325                                                 
326                                         total++;
327                                 }
328                                 if (total <= 0)
329                                         return;
330
331                                 // Calculate desired height and width
332                                 Size newSize;
333                                 Size offset;
334
335                                 if (value == MdiLayout.TileHorizontal) {
336                                         newSize = new Size(ClientSize.Width, clientHeight / total);
337                                         offset = new Size (0, newSize.Height);
338                                 } else {
339                                         newSize = new Size(ClientSize.Width / total, clientHeight);
340                                         offset = new Size (newSize.Width, 0);
341                                 }
342                                 
343                                 // Loop again and set the size and location.
344                                 Point nextLocation = Point.Empty;
345                                 
346                                 for (int i = 0; i < Controls.Count; i++) {
347                                         Form form = Controls [i] as Form;
348
349                                         if (form == null)
350                                                 continue;
351
352                                         if (!form.Visible)
353                                                 continue;
354
355                                         if (form.WindowState == FormWindowState.Minimized)
356                                                 continue;
357
358                                         form.Size = newSize;
359                                         form.Location = nextLocation;
360                                         nextLocation += offset;
361                                 }
362                                 
363                                 break;
364                                 }
365                         }
366                 }
367                 #endregion      // Public Instance Methods
368
369                 #region Protected Instance Methods
370                 #endregion      // Protected Instance Methods
371
372                 internal void SizeScrollBars ()
373                 {
374                         if (lock_sizing)
375                                 return;
376                         
377                         if (!IsHandleCreated)
378                                 return;
379
380                         if (Controls.Count == 0 || ((Form) Controls [0]).WindowState == FormWindowState.Maximized) {
381                                 if (hbar != null)
382                                         hbar.Visible = false;
383                                 if (vbar != null)
384                                         vbar.Visible = false;
385                                 if (sizegrip != null)
386                                         sizegrip.Visible = false;
387                                 return;
388                         }
389
390                         int right = 0;
391                         int left = 0;
392                         int top = 0;
393                         int bottom = 0;
394
395                         foreach (Form child in Controls) {
396                                 if (!child.Visible)
397                                         continue;
398                                 if (child.Right > right)
399                                         right = child.Right;
400                                 if (child.Left < left) {
401                                         left = child.Left;
402                                 }
403                                 
404                                 if (child.Bottom > bottom)
405                                         bottom = child.Bottom;
406                                 if (child.Top < 0) {
407                                         top = child.Top;
408                                 }
409                         }
410
411                         int available_width = ClientSize.Width;
412                         int available_height = ClientSize.Height;
413
414                         bool need_hbar = false;
415                         bool need_vbar = false;
416
417                         if (right - left > available_width || left < 0) {
418                                 need_hbar = true;
419                                 available_height -= SystemInformation.HorizontalScrollBarHeight;
420                         }
421                         if (bottom - top > available_height || top < 0) {
422                                 need_vbar = true;
423                                 available_width -= SystemInformation.VerticalScrollBarWidth;
424
425                                 if (!need_hbar && (right - left > available_width || left < 0)) {
426                                         need_hbar = true;
427                                         available_height -= SystemInformation.HorizontalScrollBarHeight;
428                                 }
429                         }
430                         
431                         if (need_hbar) {
432                                 if (hbar == null) {
433                                         hbar = new ImplicitHScrollBar ();
434                                         Controls.AddImplicit (hbar);
435                                 }
436                                 hbar.Visible = true;
437                                 CalcHBar (left, right, need_vbar);
438                         } else if (hbar != null)
439                                 hbar.Visible = false;
440
441                         if (need_vbar) {
442                                 if (vbar == null) {
443                                         vbar = new ImplicitVScrollBar ();
444                                         Controls.AddImplicit (vbar);
445                                 }
446                                 vbar.Visible = true;
447                                 CalcVBar (top, bottom, need_hbar);
448                         } else if (vbar != null)
449                                 vbar.Visible = false;
450
451                         if (need_hbar && need_vbar) {
452                                 if (sizegrip == null) {
453                                         sizegrip = new SizeGrip (this.ParentForm);
454                                         Controls.AddImplicit (sizegrip);
455                                 }
456                                 sizegrip.Location = new Point (hbar.Right, vbar.Bottom);
457                                 sizegrip.Visible = true;
458                                 XplatUI.SetZOrder (sizegrip.Handle, vbar.Handle, false, false);
459                         } else if (sizegrip != null) {
460                                 sizegrip.Visible = false;
461                         }
462                         
463                         XplatUI.InvalidateNC (Handle);
464                 }
465
466                 private void CalcHBar (int left, int right, bool vert_vis)
467                 {
468                         initializing_scrollbars = true;
469
470                         hbar.Left = 0;
471                         hbar.Top = ClientRectangle.Bottom - hbar.Height;
472                         hbar.Width = ClientRectangle.Width - (vert_vis ? SystemInformation.VerticalScrollBarWidth : 0);
473                         hbar.LargeChange = 50;
474                         hbar.Minimum = Math.Min (left, 0);
475                         hbar.Maximum = Math.Max (right - ClientSize.Width + 51 + (vert_vis ? SystemInformation.VerticalScrollBarWidth : 0), 0);
476                         hbar.Value = 0;
477                         hbar_value = 0;
478                         hbar.ValueChanged += new EventHandler (HBarValueChanged);
479                         XplatUI.SetZOrder (hbar.Handle, IntPtr.Zero, true, false);
480                         
481                         initializing_scrollbars = false;
482                 }
483
484                 private void CalcVBar (int top, int bottom, bool horz_vis)
485                 {
486                         initializing_scrollbars = true;
487                         
488                         vbar.Top = 0;
489                         vbar.Left = ClientRectangle.Right - vbar.Width;
490                         vbar.Height = ClientRectangle.Height - (horz_vis ? SystemInformation.HorizontalScrollBarHeight : 0);
491                         vbar.LargeChange = 50;
492                         vbar.Minimum = Math.Min (top, 0);
493                         vbar.Maximum = Math.Max (bottom - ClientSize.Height + 51 + (horz_vis ? SystemInformation.HorizontalScrollBarHeight : 0), 0);
494                         vbar.Value = 0;
495                         vbar_value = 0;
496                         vbar.ValueChanged += new EventHandler (VBarValueChanged);
497                         XplatUI.SetZOrder (vbar.Handle, IntPtr.Zero, true, false);
498                         
499                         initializing_scrollbars = false;
500                 }
501
502                 private void HBarValueChanged (object sender, EventArgs e)
503                 {
504                         if (initializing_scrollbars)
505                                 return;
506                         
507                         if (hbar.Value == hbar_value)
508                                 return;
509
510                         lock_sizing = true;
511
512                         try {
513                                 int diff = hbar_value - hbar.Value;
514                                 foreach (Form child in Controls) {
515                                         child.Left += diff;
516                                 }
517                         } finally {
518                                 lock_sizing = false;
519                         }
520
521                         hbar_value = hbar.Value;
522                 }
523
524                 private void VBarValueChanged (object sender, EventArgs e)
525                 {
526                         if (initializing_scrollbars)
527                                 return;
528                                 
529                         if (vbar.Value == vbar_value)
530                                 return;
531
532                         lock_sizing = true;
533
534                         try {
535                                 int diff = vbar_value - vbar.Value;
536                                 foreach (Form child in Controls) {
537                                         child.Top += diff;
538                                 }
539                         } finally {
540                                 lock_sizing = false;
541                         }
542
543                         vbar_value = vbar.Value;
544                 }
545
546                 private void ArrangeWindows ()
547                 {
548                         if (!IsHandleCreated)
549                                 return;
550                                 
551                         int change = 0;
552                         if (prev_bottom != -1)
553                                 change = Bottom - prev_bottom;
554
555                         foreach (Control c in Controls) {
556                                 Form child = c as Form;
557
558                                 if (c == null || !child.Visible)
559                                         continue;
560
561                                 MdiWindowManager wm = child.WindowManager as MdiWindowManager;
562                                 if (wm.GetWindowState () == FormWindowState.Maximized)
563                                         child.Bounds = wm.MaximizedBounds;
564
565                                 if (wm.GetWindowState () == FormWindowState.Minimized) {
566                                         child.Top += change;
567                                 }
568                                         
569                         }
570
571                         prev_bottom = Bottom;
572                 }
573
574                 internal void ArrangeIconicWindows (bool rearrange_all)
575                 {
576                         Rectangle rect = Rectangle.Empty;
577
578                         lock_sizing = true;
579                         foreach (Form form in Controls) {
580                                 if (form.WindowState != FormWindowState.Minimized)
581                                         continue;
582
583                                 MdiWindowManager wm = (MdiWindowManager) form.WindowManager;
584                                 
585                                 if (wm.IconicBounds != Rectangle.Empty && !rearrange_all) {
586                                         if (form.Bounds != wm.IconicBounds)
587                                                 form.Bounds = wm.IconicBounds;
588                                         continue;
589                                 }
590                                 
591                                 bool success = true;
592                                 int startx, starty, currentx, currenty;
593
594                                 rect.Size = wm.IconicSize;
595                                 
596                                 startx = 0;
597                                 starty = ClientSize.Height - rect.Height;
598                                 currentx = startx;
599                                 currenty = starty;
600                                 
601                                 do {
602                                         rect.X = currentx;
603                                         rect.Y = currenty;
604                                         success = true;
605                                         foreach (Form form2 in Controls) {
606                                                 if (form2 == form || form2.window_state != FormWindowState.Minimized)
607                                                         continue;
608                                                 
609                                                 if (form2.Bounds.IntersectsWith(rect)) {
610                                                         success = false;
611                                                         break;
612                                                 }
613                                         }
614                                         if (!success) { 
615                                                 currentx += rect.Width;
616                                                 if (currentx + rect.Width > Right) {
617                                                         currentx = startx;
618                                                         currenty -= rect.Height;
619                                                 } 
620                                         }
621                                 } while (!success);
622                                 wm.IconicBounds = rect;
623                                 form.Bounds = wm.IconicBounds;
624                         }
625                         lock_sizing = false;
626                 }
627
628                 internal void ChildFormClosed (Form form)
629                 {
630                         FormWindowState closed_form_windowstate = form.WindowState;
631         
632                         form.Visible = false;
633                         Controls.Remove (form);
634                         
635                         if (Controls.Count == 0) {
636                                 ((MdiWindowManager) form.window_manager).RaiseDeactivate ();
637                         } else if (closed_form_windowstate == FormWindowState.Maximized) {
638                                 Form current = (Form) Controls [0];
639                                 current.WindowState = FormWindowState.Maximized;
640                                 ActivateChild(current);
641                         }
642
643                         if (Controls.Count == 0) {
644                                 XplatUI.RequestNCRecalc (Parent.Handle);
645                                 ParentForm.PerformLayout ();
646
647 #if NET_2_0
648                                 // If we closed the last child, unmerge the menus.
649                                 // If it's not the last child, the menu will be unmerged
650                                 // when another child takes focus.
651                                 MenuStrip parent_menu = form.MdiParent.MainMenuStrip;
652
653                                 if (parent_menu != null)
654                                         if (parent_menu.IsCurrentlyMerged)
655                                                 ToolStripManager.RevertMerge (parent_menu);
656 #endif
657                         }
658                         SizeScrollBars ();
659                         SetParentText (false);
660                         form.Dispose();
661                 }
662
663                 internal void ActivateNextChild ()
664                 {
665                         if (Controls.Count < 1)
666                                 return;
667                         if (Controls.Count == 1 && Controls[0] == ActiveMdiChild)
668                                 return;
669                                 
670                         Form front = (Form) Controls [0];
671                         Form form = (Form) Controls [1];
672
673                         ActivateChild (form);
674                         front.SendToBack ();
675                 }
676
677                 internal void ActivatePreviousChild ()
678                 {
679                         if (Controls.Count <= 1)
680                                 return;
681                         
682                         Form back = (Form) Controls [Controls.Count - 1];
683                         
684                         ActivateChild (back);
685                 }
686
687                 internal void ActivateChild (Form form)
688                 {
689                         if (Controls.Count < 1)
690                                 return;
691
692                         if (ParentForm.is_changing_visible_state > 0)
693                                 return;
694                         
695                         Form current = (Form) Controls [0];
696                         bool raise_deactivate = ParentForm.ActiveControl == current;
697
698                         // We want to resize the new active form before it is 
699                         // made active to avoid flickering. Can't do it in the
700                         // normal way (form.WindowState = Maximized) since it's not
701                         // active yet and everything would just return to before. 
702                         // We also won't suspend layout, this way the layout will
703                         // happen before the form is made active (and in many cases
704                         // before it is visible, which avoids flickering as well).
705                         MdiWindowManager wm = (MdiWindowManager)form.WindowManager;
706                         
707                         if (current.WindowState == FormWindowState.Maximized && form.WindowState != FormWindowState.Maximized && form.Visible) {
708                                 FormWindowState old_state = form.window_state;
709                                 SetWindowState (form, old_state, FormWindowState.Maximized, true);
710                                 wm.was_minimized = form.window_state == FormWindowState.Minimized;
711                                 form.window_state = FormWindowState.Maximized;
712                                 SetParentText (false);
713                         }
714
715                         form.BringToFront ();
716                         form.SendControlFocus (form);
717                         SetWindowStates (wm);
718                         if (current != form) {
719                                 form.has_focus = false;
720                                 if (current.IsHandleCreated)
721                                         XplatUI.InvalidateNC (current.Handle);
722                                 if (form.IsHandleCreated)
723                                         XplatUI.InvalidateNC (form.Handle);
724                                 if (raise_deactivate) {
725                                         MdiWindowManager current_wm = (MdiWindowManager) current.window_manager;
726                                         current_wm.RaiseDeactivate ();
727                                         
728                                 }
729                         }
730                         active_child = (Form) Controls [0];
731                         
732                         if (active_child.Visible) {
733                                 bool raise_activated = ParentForm.ActiveControl != active_child;
734                                 ParentForm.ActiveControl = active_child;
735                                 if (raise_activated) {
736                                         MdiWindowManager active_wm = (MdiWindowManager) active_child.window_manager;
737                                         active_wm.RaiseActivated ();
738                                 }
739                         }
740                 }
741
742                 internal override IntPtr AfterTopMostControl ()
743                 {
744                         // order of scrollbars:
745                         // top = vertical
746                         //       sizegrid
747                         // bottom = horizontal
748                         if (hbar != null && hbar.Visible)
749                                 return hbar.Handle;
750                         // no need to check for sizegrip since it will only
751                         // be visible if hbar is visible.
752                         if (vbar != null && vbar.Visible)
753                                 return vbar.Handle;
754                                 
755                         return base.AfterTopMostControl ();
756                 }
757                 
758                 internal bool SetWindowStates (MdiWindowManager wm)
759                 {
760                 /*
761                         MDI WindowState behaviour:
762                         - If the active window is maximized, all other maximized windows are normalized.
763                         - If a normal window gets focus and the original active window was maximized, 
764                           the normal window gets maximized and the original window gets normalized.
765                         - If a minimized window gets focus and the original window was maximized, 
766                           the minimzed window gets maximized and the original window gets normalized. 
767                           If the ex-minimized window gets deactivated, it will be normalized.
768                 */
769                         Form form = wm.form;
770
771                         if (setting_windowstates) {
772                                 return false;
773                         }
774                         
775                         if (!form.Visible)
776                                 return false;
777                         
778                         bool is_active = wm.IsActive;
779                         bool maximize_this = false;
780                         
781                         if (!is_active){
782                                 return false;
783                         }
784                         
785                         ArrayList minimize_these = new ArrayList ();
786                         ArrayList normalize_these = new ArrayList ();
787
788                         setting_windowstates = true;
789                         foreach (Form frm in mdi_child_list) {
790                                 if (frm == form) {
791                                         continue;
792                                 } else if (!frm.Visible){
793                                         continue;
794                                 }
795                                 if (frm.WindowState == FormWindowState.Maximized && is_active) {
796                                         maximize_this = true;   
797                                         if (((MdiWindowManager) frm.window_manager).was_minimized) {
798                                                 minimize_these.Add (frm); 
799                                         } else {
800                                                 normalize_these.Add (frm); 
801                                         }
802                                 }
803                         }
804
805                         if (maximize_this && form.WindowState != FormWindowState.Maximized) {
806                                 wm.was_minimized = form.window_state == FormWindowState.Minimized;
807                                 form.WindowState = FormWindowState.Maximized;
808                         }
809                         
810                         foreach (Form frm in minimize_these)
811                                 frm.WindowState = FormWindowState.Minimized;
812
813                         foreach (Form frm in normalize_these)
814                                 frm.WindowState = FormWindowState.Normal;
815
816
817                         SetParentText (false);
818                         
819                         XplatUI.RequestNCRecalc (ParentForm.Handle);
820                         XplatUI.RequestNCRecalc (Handle);
821
822                         SizeScrollBars ();
823
824                         setting_windowstates = false;
825
826 #if NET_2_0
827                         if (form.MdiParent.MainMenuStrip != null)
828                                 form.MdiParent.MainMenuStrip.RefreshMdiItems ();
829
830                         // Implicit menu strip merging
831                         // - When child is activated
832                         // - Parent form must have a MainMenuStrip
833                         // - Find the first menustrip on the child
834                         // - Merge
835                         MenuStrip parent_menu = form.MdiParent.MainMenuStrip;
836
837                         if (parent_menu != null) {
838                                 if (parent_menu.IsCurrentlyMerged)
839                                         ToolStripManager.RevertMerge (parent_menu);
840                                         
841                                 MenuStrip child_menu = LookForChildMenu (form);
842
843                                 if (form.WindowState != FormWindowState.Maximized)
844                                         RemoveControlMenuItems (wm);
845                                 
846                                 if (form.WindowState == FormWindowState.Maximized) {
847                                         bool found = false;
848                                         
849                                         foreach (ToolStripItem tsi in parent_menu.Items) {
850                                                 if (tsi is MdiControlStrip.SystemMenuItem) {
851                                                         (tsi as MdiControlStrip.SystemMenuItem).MdiForm = form;
852                                                         found = true;
853                                                 } else if (tsi is MdiControlStrip.ControlBoxMenuItem) {
854                                                         (tsi as MdiControlStrip.ControlBoxMenuItem).MdiForm = form;
855                                                         found = true;
856                                                 }
857                                         }       
858                                         
859                                         if (!found) {
860                                                 parent_menu.SuspendLayout ();
861                                                 parent_menu.Items.Insert (0, new MdiControlStrip.SystemMenuItem (form));
862                                                 parent_menu.Items.Add (new MdiControlStrip.ControlBoxMenuItem (form, MdiControlStrip.ControlBoxType.Close));
863                                                 parent_menu.Items.Add (new MdiControlStrip.ControlBoxMenuItem (form, MdiControlStrip.ControlBoxType.Max));
864                                                 parent_menu.Items.Add (new MdiControlStrip.ControlBoxMenuItem (form, MdiControlStrip.ControlBoxType.Min));
865                                                 parent_menu.ResumeLayout ();
866                                         }
867                                 }
868                                 
869                                 if (child_menu != null)
870                                         ToolStripManager.Merge (child_menu, parent_menu);
871                         }
872 #endif
873
874                         return maximize_this;
875                 }
876
877 #if NET_2_0
878                 private MenuStrip LookForChildMenu (Control parent)
879                 {
880                         foreach (Control c in parent.Controls) {
881                                 if (c is MenuStrip)
882                                         return (MenuStrip)c;
883                                         
884                                 if (c is ToolStripContainer || c is ToolStripPanel) {
885                                         MenuStrip ms = LookForChildMenu (c);
886                                         
887                                         if (ms != null)
888                                                 return ms;
889                                 }
890                         }
891                         
892                         return null;
893                 }
894                 
895                 internal void RemoveControlMenuItems (MdiWindowManager wm)
896                 {
897                         Form form = wm.form;
898                         MenuStrip parent_menu = form.MdiParent.MainMenuStrip;
899
900                         // Only remove the items if the form requesting still owns the menu items
901                         if (parent_menu != null) {
902                                 parent_menu.SuspendLayout ();
903
904                                 for (int i = parent_menu.Items.Count - 1; i >= 0; i--) {
905                                         if (parent_menu.Items[i] is MdiControlStrip.SystemMenuItem) {
906                                                 if ((parent_menu.Items[i] as MdiControlStrip.SystemMenuItem).MdiForm == form)
907                                                         parent_menu.Items.RemoveAt (i);
908                                         } else if (parent_menu.Items[i] is MdiControlStrip.ControlBoxMenuItem) {
909                                                 if ((parent_menu.Items[i] as MdiControlStrip.ControlBoxMenuItem).MdiForm == form)
910                                                         parent_menu.Items.RemoveAt (i);
911                                         }
912                                 }
913                                 
914                                 parent_menu.ResumeLayout ();
915                         }
916                 }
917 #endif
918
919                 internal void SetWindowState (Form form, FormWindowState old_window_state, FormWindowState new_window_state, bool is_activating_child)
920                 {
921                         bool mdiclient_layout;
922
923                         MdiWindowManager wm = (MdiWindowManager) form.window_manager;
924
925                         if (!is_activating_child && new_window_state == FormWindowState.Maximized && !wm.IsActive) {
926                                 ActivateChild (form);
927                                 return;
928                         }
929                                 
930                         if (old_window_state == FormWindowState.Normal)
931                                 wm.NormalBounds = form.Bounds;
932
933                         if (SetWindowStates (wm))
934                                 return;
935
936                         if (old_window_state == new_window_state)
937                                 return;
938
939                         mdiclient_layout = old_window_state == FormWindowState.Maximized || new_window_state == FormWindowState.Maximized;
940
941                         switch (new_window_state) {
942                         case FormWindowState.Minimized:
943                                 ArrangeIconicWindows (false);
944                                 break;
945                         case FormWindowState.Maximized:
946                                 form.Bounds = wm.MaximizedBounds;
947                                 break;
948                         case FormWindowState.Normal:
949                                 form.Bounds = wm.NormalBounds;
950                                 break;
951                         }
952
953                         wm.UpdateWindowDecorations (new_window_state);
954
955                         form.ResetCursor ();
956
957                         if (mdiclient_layout)
958                                 Parent.PerformLayout ();
959
960                         XplatUI.RequestNCRecalc (Parent.Handle);
961                         XplatUI.RequestNCRecalc (form.Handle);
962                         if (!setting_windowstates)
963                                 SizeScrollBars ();
964                 }
965                 internal int ChildrenCreated {
966                         get { return mdi_created; }
967                         set { mdi_created = value; }
968                 }
969
970                 internal Form ActiveMdiChild {
971                         get {
972 #if NET_2_0
973                                 if (ParentForm != null && !ParentForm.Visible)
974                                         return null;
975 #endif
976                                 if (Controls.Count < 1)
977                                         return null;
978                                         
979                                 if (!ParentForm.IsHandleCreated)
980                                         return null;
981                                 
982                                 if (!ParentForm.has_been_visible)
983                                         return null;
984                                         
985                                 if (!ParentForm.Visible)
986                                         return active_child;
987                                 
988                                 active_child = null;
989                                 for (int i = 0; i < Controls.Count; i++) {
990                                         if (Controls [i].Visible) {
991                                                 active_child = (Form) Controls [i];
992                                                 break;
993                                         }
994                                 }
995                                 return active_child;
996                         }
997                         set {
998                                 ActivateChild (value);
999                         }
1000                 }
1001                 
1002                 internal void ActivateActiveMdiChild ()
1003                 {
1004                         if (ParentForm.is_changing_visible_state > 0)
1005                                 return;
1006                                 
1007                         for (int i = 0; i < Controls.Count; i++) {
1008                                 if (Controls [i].Visible) {
1009                                         ActivateChild ((Form) Controls [i]);
1010                                         return;
1011                                 }
1012                         }
1013                 }
1014         }
1015 }
1016