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