curse you, svn, curse youuuuuuuuu
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / Control.cs
index 7182c0602148babed71894fe919dd3ac2b98238a..b393396fd6ee66c043d269e216904f08ae3dcd70 100644 (file)
@@ -73,6 +73,7 @@ namespace System.Windows.Forms
                internal bool                   is_captured;            // tracks if the control has captured the mouse
                internal bool                   is_toplevel;            // tracks if the control is a toplevel window
                internal bool                   is_recreating;          // tracks if the handle for the control is being recreated
+               internal ArrayList              children_to_recreate;   // keep track of the children which need to be recreated
                internal bool                   causes_validation;      // tracks if validation is executed on changes
                internal int                    tab_index;              // position in tab order of siblings
                internal bool                   tab_stop = true;        // is the control a tab stop?
@@ -117,7 +118,7 @@ namespace System.Windows.Forms
                private Graphics                dc_mem;                 // Graphics context for double buffering
                private GraphicsState           dc_state;               // Pristine graphics context to reset after paint code alters dc_mem
                private Bitmap                  bmp_mem;                // Bitmap for double buffering control
-               private bool                    needs_redraw = true;
+               private Region                  invalid_region;
 
                private ControlBindingsCollection data_bindings;
 
@@ -356,6 +357,10 @@ namespace System.Windows.Forms
                        {
                                if (impl_list == null)
                                        impl_list = new ArrayList ();
+
+                               if (AllContains (control))
+                                       return;
+
                                all_controls = null;
                                impl_list.Add (control);
 
@@ -512,18 +517,14 @@ namespace System.Windows.Forms
                        }
 
                        public virtual void Remove(Control value) {
-                               all_controls = null;
-
                                owner.PerformLayout(value, "Parent");
                                owner.OnControlRemoved(new ControlEventArgs(value));
+
+                               all_controls = null;
                                list.Remove(value);
 
                                value.ChangeParent(null);
 
-                               // Removing this temporarily because we have a bug somewhere else
-                               // that this exposes
-                               // value.Hide ();
-
                                owner.UpdateChildrenZOrder();
                        }
 
@@ -772,6 +773,10 @@ namespace System.Windows.Forms
                                        bmp_mem=null;
                                }
 
+                               if (invalid_region!=null) {
+                                       invalid_region.Dispose();
+                                       invalid_region=null;
+                               }
                                if (this.InvokeRequired) {
                                        if (Application.MessageLoop) {
                                                this.BeginInvokeInternal(new MethodInvoker(DestroyHandle), null, true);
@@ -881,21 +886,28 @@ namespace System.Windows.Forms
                                        return true;
                                }
 
-                               if (parent != null) {
-                                       return parent.IsRecreating;
-                               }
-
-                               return false;
+                               return ParentWaitingOnRecreation(this);
                        }
                }
 
-               private bool ParentIsRecreating {
-                       get {
-                               if (parent != null) {
-                                       return parent.IsRecreating;
-                               }
-                               return false;
+               internal bool ChildNeedsRecreating (Control child)
+               {
+                       if (children_to_recreate != null && children_to_recreate.Contains (child))
+                                       return true;
+                       return ParentWaitingOnRecreation (this);
+               }
+
+               internal void RemoveChildFromRecreateList (Control child)
+               {
+                       if (children_to_recreate != null)
+                               children_to_recreate.Remove (child);
+               }
+
+               private bool ParentWaitingOnRecreation (Control c) {
+                       if (parent != null) {
+                               return parent.ChildNeedsRecreating (c);
                        }
+                       return false;
                }
 
                internal Graphics DeviceContext {
@@ -913,6 +925,12 @@ namespace System.Windows.Forms
                        dc_state = dc_mem.Save();
                }
 
+               private void ImageBufferNeedsRedraw () {
+                       if (invalid_region != null)
+                               invalid_region.Dispose();
+                       invalid_region = new Region (ClientRectangle);
+               }
+
                private Bitmap ImageBuffer {
                        get {
                                if (bmp_mem==null) {
@@ -939,7 +957,7 @@ namespace System.Windows.Forms
 
                        bmp_mem = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                        dc_mem = Graphics.FromImage (bmp_mem);
-                       needs_redraw = true;
+                       ImageBufferNeedsRedraw ();
                }
 
                internal void InvalidateBuffers ()
@@ -952,7 +970,7 @@ namespace System.Windows.Forms
 
                        dc_mem = null;
                        bmp_mem = null;
-                       needs_redraw = true;
+                       ImageBufferNeedsRedraw ();
                }
 
                internal static void SetChildColor(Control parent) {
@@ -1336,9 +1354,9 @@ namespace System.Windows.Forms
 
                        parent = new_parent;
 
-                       if (IsHandleCreated && (new_parent != null) && new_parent.IsHandleCreated) {
-                               XplatUI.SetParent(Handle, new_parent.Handle);
-                       }
+                       if (IsHandleCreated)
+                               XplatUI.SetParent(Handle,
+                                                 (new_parent == null || !new_parent.IsHandleCreated) ? IntPtr.Zero : new_parent.Handle);
 
                        OnParentChanged(EventArgs.Empty);
 
@@ -2133,7 +2151,9 @@ namespace System.Windows.Forms
                public bool IsHandleCreated {
                        get {
                                if ((window != null) && (window.Handle != IntPtr.Zero)) {
-                                       return true;
+                                       Hwnd hwnd = Hwnd.ObjectFromHandle (window.Handle);
+                                       if (hwnd != null && !hwnd.zombie)
+                                               return true;
                                }
 
                                return false;
@@ -2218,6 +2238,7 @@ namespace System.Windows.Forms
                                if (parent!=value) {
                                        if (value==null) {
                                                parent.Controls.Remove(this);
+                                               parent = null;
                                                return;
                                        }
 
@@ -2412,6 +2433,10 @@ namespace System.Windows.Forms
                                if (text!=value) {
                                        text=value;
                                        if (IsHandleCreated) {
+                                               /* we need to call .SetWindowStyle here instead of just .Text
+                                                  because the presence/absence of Text (== "" or not) can cause
+                                                  other window style things to appear/disappear */
+                                               XplatUI.SetWindowStyle(window.Handle, CreateParams);
                                                XplatUI.Text(Handle, text);
                                        }
                                        OnTextChanged (EventArgs.Empty);
@@ -3312,7 +3337,6 @@ namespace System.Windows.Forms
                }
 
                public void Update() {
-                       needs_redraw = true;
                        if (IsHandleCreated) {
                                XplatUI.UpdateWindow(window.Handle);
                        }
@@ -3570,6 +3594,8 @@ namespace System.Windows.Forms
                        is_recreating=true;
 
                        if (IsHandleCreated) {
+                               children_to_recreate = new ArrayList();
+                               children_to_recreate.AddRange (child_controls.GetAllControls ());
                                DestroyHandle();
                                // WM_DESTROY will CreateHandle for us
                        } else {
@@ -3578,6 +3604,8 @@ namespace System.Windows.Forms
                                } else {
                                        CreateHandle();
                                }
+                               if (parent != null)
+                                       parent.RemoveChildFromRecreateList (this);
                        }
 
                        is_recreating = false;
@@ -3920,7 +3948,7 @@ namespace System.Windows.Forms
                                        OnHandleDestroyed(EventArgs.Empty);
                                        window.InvalidateHandle();
 
-                                       if (ParentIsRecreating) {
+                                       if (ParentWaitingOnRecreation (this)) {
                                                RecreateHandle();
                                        } else if (is_recreating) {
                                                CreateHandle();
@@ -3952,7 +3980,7 @@ namespace System.Windows.Forms
                                                return;
                                        }
 
-                                       if (!needs_redraw) {
+                                       if (invalid_region != null && !invalid_region.IsVisible (paint_event.ClipRectangle)) {
                                                // Just blit the previous image
                                                paint_event.Graphics.DrawImage (ImageBuffer, paint_event.ClipRectangle, paint_event.ClipRectangle, GraphicsUnit.Pixel);
                                                XplatUI.PaintEventEnd(Handle, true);
@@ -3960,6 +3988,7 @@ namespace System.Windows.Forms
                                        }
 
                                        Graphics dc = null;
+                                       Rectangle old_clip_rect = Rectangle.Empty;
                                        if (ThemeEngine.Current.DoubleBufferingSupported) {
                                                if ((control_style & ControlStyles.DoubleBuffer) != 0) {
                                                        dc = paint_event.SetGraphics (DeviceContext);
@@ -3981,9 +4010,10 @@ namespace System.Windows.Forms
 
                                        if (ThemeEngine.Current.DoubleBufferingSupported)
                                                if ((control_style & ControlStyles.DoubleBuffer) != 0) {
+                                                       paint_event.SetClipRectangle (old_clip_rect);
                                                        dc.DrawImage (ImageBuffer, paint_event.ClipRectangle, paint_event.ClipRectangle, GraphicsUnit.Pixel);
                                                        paint_event.SetGraphics (dc);
-                                                       needs_redraw = false;
+                                                       invalid_region.Exclude (paint_event.ClipRectangle);
                                                }
 
                                        XplatUI.PaintEventEnd(Handle, true);
@@ -4430,7 +4460,20 @@ namespace System.Windows.Forms
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
                protected virtual void OnInvalidated(InvalidateEventArgs e) {
-                       needs_redraw = true;
+                       // should this block be here?  seems like it
+                       // would be more at home in
+                       // NotifyInvalidated..
+                       if (e.InvalidRect == ClientRectangle) {
+                               ImageBufferNeedsRedraw ();
+                       }
+                       else {
+                               // we need this Inflate call here so
+                               // that the border of the rectangle is
+                               // considered Visible (the
+                               // invalid_region.IsVisible call) in
+                               // the WM_PAINT handling below.
+                               invalid_region.Union (Rectangle.Inflate(e.InvalidRect, 1,1));
+                       }
                        if (Invalidated!=null) Invalidated(this, e);
                }
 
@@ -4683,8 +4726,6 @@ namespace System.Windows.Forms
                                }
                        }
 
-                       needs_redraw = true;
-                       
                        if (VisibleChanged!=null) VisibleChanged(this, e);
 
                        // We need to tell our kids