2007-03-21 Jonathan Pobst <monkey@jpobst.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / Control.cs
index e0b8e0136c6b39c0ed9f4a415d369af2ecddd61f..a2766d204e8e517a21714a9400d3c70550c09636 100644 (file)
@@ -485,13 +485,19 @@ namespace System.Windows.Forms
                                if (value == null)
                                        return;
 
-                               bool owner_permits_toplevels = (owner is MdiClient) || (owner is Form && ((Form)owner).IsMdiContainer);
-                               bool child_is_toplevel = ((Control)value).GetTopLevel();
-                               bool child_is_mdichild = (value is Form && ((Form)value).IsMdiChild);
+                               Form form_value = value as Form;
+                               Form form_owner = owner as Form;
+                               bool owner_permits_toplevels = (owner is MdiClient) || (form_owner != null && form_owner.IsMdiContainer);
+                               bool child_is_toplevel = value.GetTopLevel();
+                               bool child_is_mdichild = form_value != null && form_value.IsMdiChild;
 
                                if (child_is_toplevel && !(owner_permits_toplevels && child_is_mdichild))
                                        throw new ArgumentException("Cannot add a top level control to a control.", "value");
                                
+                               if (child_is_mdichild && form_value.MdiParent != null && form_value.MdiParent != owner && form_value.MdiParent != owner.Parent) {
+                                       throw new ArgumentException ("Form cannot be added to the Controls collection that has a valid MDI parent.", "value");
+                               }
+                               
                                if (Contains (value)) {
                                        owner.PerformLayout();
                                        return;
@@ -555,8 +561,11 @@ namespace System.Windows.Forms
                                control.InitLayout ();
                                if (owner.Visible)
                                        owner.UpdateChildrenZOrder ();
-                               owner.PerformLayout (control, "Parent");
-                               owner.OnControlAdded (new ControlEventArgs (control));
+                               
+                               // If we are adding a new control that isn't
+                               // visible, don't trigger a layout
+                               if (control.VisibleInternal)
+                                       owner.PerformLayout (control, "Parent");
                        }
 #if NET_2_0
                        [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
@@ -1055,8 +1064,8 @@ namespace System.Windows.Forms
                                }
                                
                                if (this.InvokeRequired) {
-                                       if (Application.MessageLoop) {
-                                               this.BeginInvokeInternal(new MethodInvoker(DestroyHandle), null, true);
+                                       if (Application.MessageLoop && IsHandleCreated) {
+                                               this.BeginInvokeInternal(new MethodInvoker(DestroyHandle), null);
                                        }
                                } else {
                                        DestroyHandle();
@@ -1156,23 +1165,18 @@ namespace System.Windows.Forms
                }
 #endif
 
-               internal IAsyncResult BeginInvokeInternal (Delegate method, object [] args, bool disposing) {
+               internal IAsyncResult BeginInvokeInternal (Delegate method, object [] args) {
+                       return BeginInvokeInternal (method, args, FindControlToInvokeOn ());
+               }
+
+               internal IAsyncResult BeginInvokeInternal (Delegate method, object [] args, Control control) {
                        AsyncMethodResult       result;
                        AsyncMethodData         data;
 
-                       if (!disposing) {
-                               Control p = this;
-                               do {
-                                       if (!p.IsHandleCreated)
-                                               throw new InvalidOperationException("Cannot call Invoke or BeginInvoke on a control until the window handle is created");
-                                       p = p.parent;
-                               } while (p != null);
-                       }
-
                        result = new AsyncMethodResult ();
                        data = new AsyncMethodData ();
 
-                       data.Handle = window.Handle;
+                       data.Handle = control.Handle;
                        data.Method = method;
                        data.Args = args;
                        data.Result = result;
@@ -1217,6 +1221,21 @@ namespace System.Windows.Forms
                                return bmp_g;
                        }
                }
+               
+               private Control FindControlToInvokeOn ()
+               {
+                       Control p = this;
+                       do {
+                               if (p.IsHandleCreated)
+                                       break;
+                               p = p.parent;
+                       } while (p != null);
+
+                       if (p == null || !p.IsHandleCreated)
+                               throw new InvalidOperationException ("Cannot call Invoke or BeginInvoke on a control until the window handle is created");
+                       
+                       return p;
+               }
 
                private void InvalidateBackBuffer () {
                        if (backbuffer != null)
@@ -2769,6 +2788,9 @@ namespace System.Windows.Forms
                                // set. 
                                if (attrs != null && attrs.Length > 0)
                                        a = (AssemblyProductAttribute) attrs [0];
+                               if (a == null) {
+                                       return GetType ().Namespace;
+                               }
                                return a.Product;
                        }
                }
@@ -3232,7 +3254,7 @@ namespace System.Windows.Forms
                        object [] prms = null;
                        if (method is EventHandler)
                                prms = new object [] { this, EventArgs.Empty };
-                       return BeginInvokeInternal(method, prms, false);
+                       return BeginInvokeInternal(method, prms);
                }
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
@@ -3242,7 +3264,7 @@ namespace System.Windows.Forms
                public IAsyncResult BeginInvoke (Delegate method, object[] args)
 #endif
                {
-                       return BeginInvokeInternal (method, args, false);
+                       return BeginInvokeInternal (method, args);
                }
 
                public void BringToFront() {
@@ -3272,19 +3294,23 @@ namespace System.Windows.Forms
                                return;
                        }
 
+                       if (!is_visible) {
+                               return;
+                       }
+                       
                        if (!IsHandleCreated) {
                                CreateHandle();
                        }
 
                        if (!is_created) {
                                is_created = true;
-                       }
 
-                       if (binding_context == null) {  // seem to be sent whenever it's null?
-                               OnBindingContextChanged(EventArgs.Empty);
-                       }
+                               if (binding_context == null) {  // seem to be sent whenever it's null?
+                                       OnBindingContextChanged(EventArgs.Empty);
+                               }
 
-                       OnCreateControl();
+                               OnCreateControl();
+                       }
                }
 
                public Graphics CreateGraphics() {
@@ -3323,7 +3349,11 @@ namespace System.Windows.Forms
                [EditorBrowsable (EditorBrowsableState.Advanced)]
 #endif
                public bool Focus() {
-                       if (CanFocus && IsHandleCreated && !has_focus && !is_focusing) {
+                       return FocusInternal (false);
+               }
+
+               internal virtual bool FocusInternal (bool skip_check) {
+                       if (skip_check || (CanFocus && IsHandleCreated && !has_focus && !is_focusing)) {
                                is_focusing = true;
                                Select(this);
                                is_focusing = false;
@@ -3331,12 +3361,6 @@ namespace System.Windows.Forms
                        return has_focus;
                }
 
-               internal void FocusInternal () {
-                       is_focusing = true;
-                       Select(this);
-                       is_focusing = false;
-               }
-
                public Control GetChildAtPoint(Point pt) {
                        // MS's version causes the handle to be created.  The stack trace shows that get_Handle is called here, but
                        // we'll just call CreateHandle instead.
@@ -3459,20 +3483,18 @@ namespace System.Windows.Forms
 
                        return Invoke(method, prms);
                }
-
+#if NET_2_0
+               public object Invoke (Delegate method, params object [] args) {
+#else
                public object Invoke (Delegate method, object[] args) {
-                       Control p = this;
-                       do {
-                               if (!p.IsHandleCreated)
-                                       throw new InvalidOperationException("Cannot call Invoke or BeginInvoke on a control until the window handle is created");
-                               p = p.parent;
-                       } while (p != null);
+#endif
+                       Control control = FindControlToInvokeOn ();
                        
                        if (!this.InvokeRequired) {
                                return method.DynamicInvoke(args);
                        }
 
-                       IAsyncResult result = BeginInvoke (method, args);
+                       IAsyncResult result = BeginInvokeInternal (method, args, control);
                        return EndInvoke(result);
                }
 
@@ -3792,7 +3814,8 @@ namespace System.Windows.Forms
                                return;
                        }
 
-                       window.CreateHandle(CreateParams);
+                       CreateParams create_params = CreateParams;
+                       window.CreateHandle(create_params);
 
                        if (window.Handle != IntPtr.Zero) {
                                creator_thread = Thread.CurrentThread;
@@ -4216,19 +4239,13 @@ namespace System.Windows.Forms
                                throw new ArgumentException ("Cannot change toplevel style of a parented control.");
                        }
 
-                       // XXX MS.NET causes handle to be created here
-                       CreateHandle ();
-
                        if (this is Form) {
-                               if (value == true) {
-                                       if (!Visible) {
-                                               Visible = true;
-                                       }
-                               } else {
-                                       if (Visible) {
-                                               Visible = false;
-                                       }
+                               if (IsHandleCreated && value != Visible) {
+                                       Visible = value;
                                }
+                       } else {
+                               // XXX MS.NET causes handle to be created here
+                               CreateHandle ();
                        }
                        is_toplevel = value;
                }
@@ -4629,33 +4646,35 @@ namespace System.Windows.Forms
                private void WmPaint (ref Message m) {
                        PaintEventArgs  paint_event;
 
-                       paint_event = XplatUI.PaintEventStart(Handle, true);
+                       IntPtr handle = Handle;
+
+                       paint_event = XplatUI.PaintEventStart (handle, true);
 
-                       if (paint_event == null) {
+                       if (paint_event == null)
                                return;
-                       }
+
                        DoubleBuffer current_buffer = null;
                        if (UseDoubleBuffering) {
                                current_buffer = GetBackBuffer ();
                                if (!current_buffer.InvalidRegion.IsVisible (paint_event.ClipRectangle)) {
                                        // Just blit the previous image
                                        current_buffer.Blit (paint_event);
-                                       XplatUI.PaintEventEnd (Handle, true);
+                                       XplatUI.PaintEventEnd (handle, true);
                                        return;
                                }
                                current_buffer.Start (paint_event);
                        }
                                
                        if (!GetStyle(ControlStyles.Opaque)) {
-                               OnPaintBackground(paint_event);
+                               OnPaintBackground (paint_event);
                        }
 
                        // Button-derived controls choose to ignore their Opaque style, give them a chance to draw their background anyways
-                       OnPaintBackgroundInternal(paint_event);
+                       OnPaintBackgroundInternal (paint_event);
 
                        OnPaintInternal(paint_event);
                        if (!paint_event.Handled) {
-                               OnPaint(paint_event);
+                               OnPaint (paint_event);
                        }
 
                        if (current_buffer != null) {
@@ -4663,8 +4682,7 @@ namespace System.Windows.Forms
                        }
 
 
-                       XplatUI.PaintEventEnd(Handle, true);
-
+                       XplatUI.PaintEventEnd (handle, true);
                }
 
                private void WmEraseBackground (ref Message m) {
@@ -4860,6 +4878,7 @@ namespace System.Windows.Forms
 
                private void WmShowWindow (ref Message m) {
                        if (m.WParam.ToInt32() != 0) {
+                               CreateControl ();
                                /* if we're being shown, make sure our child controls all have their handles created */
                                Control [] controls = child_controls.GetAllControls ();
                                for (int i=0; i<controls.Length; i++) {
@@ -4881,7 +4900,7 @@ namespace System.Windows.Forms
                                }
                        }
 
-                       if (is_toplevel) /* XXX make sure this works for mdi forms */
+                       if (is_toplevel || (this is Form && ((Form) this).IsMdiChild)) /* XXX make sure this works for mdi forms */
                                OnVisibleChanged(EventArgs.Empty);
                }