Properly update the combo box selected text when the current item is changed, and...
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / InternalWindowManager.cs
index 8a403903d21336a10cc87927a6343c7cc620c8ba..ea58417925e84ceedb6e206a1c7e674b14f49e53 100644 (file)
@@ -33,7 +33,6 @@ using System.Runtime.InteropServices;
 namespace System.Windows.Forms {
 
        internal abstract class InternalWindowManager {
-               private Size MinTitleBarSize = new Size (115, 25);
                private TitleButtons title_buttons;
                internal Form form;
 
@@ -107,8 +106,7 @@ namespace System.Windows.Forms {
                }
                internal Size IconicSize {
                        get {
-                               int bw = ThemeEngine.Current.ManagedWindowBorderWidth (this);
-                               return new Size (152 + bw * 2, TitleBarHeight + bw * 2);
+                               return SystemInformation.MinimizedWindowSize;
                        }
                }
                
@@ -164,7 +162,8 @@ namespace System.Windows.Forms {
                public virtual void UpdateWindowDecorations (FormWindowState window_state)
                {
                        ThemeEngine.Current.ManagedWindowSetButtonLocations (this);
-                       XplatUI.RequestNCRecalc (form.Handle);
+                       if (form.IsHandleCreated)
+                               XplatUI.RequestNCRecalc (form.Handle);
                }
                
                public virtual bool WndProc (ref Message m)
@@ -225,68 +224,97 @@ namespace System.Windows.Forms {
                                HandleNCMouseLeave (ref m);
                                break;
                        
-                       case Msg.WM_MOUSE_LEAVE:
+                       case Msg.WM_MOUSELEAVE:
                                HandleMouseLeave (ref m);
                                break;
 
                        case Msg.WM_NCCALCSIZE:
-                               HandleNCCalcSize (ref m);
-                               break;
+                               return HandleNCCalcSize (ref m);
 
                        case Msg.WM_NCPAINT:
-                               return HandleNCPaint ();
+                               return HandleNCPaint (ref m);
                        }
 
                        return false;
                }
 
-               protected virtual bool HandleNCPaint ()
+               protected virtual bool HandleNCPaint (ref Message m)
                {
-                       PaintEventArgs pe = XplatUI.PaintEventStart (form.Handle, false);
+                       PaintEventArgs pe = XplatUI.PaintEventStart (ref m, form.Handle, false);
 
                        Rectangle clip;
-                       // clip region is not correct on win32.
-                       // if (m.WParam.ToInt32 () > 1) {
-                       //      Region r = Region.FromHrgn (m.WParam);
-                       //      RectangleF rf = r.GetBounds (pe.Graphics);
-                       //      clip = new Rectangle ((int) rf.X, (int) rf.Y, (int) rf.Width, (int) rf.Height);
-                       //} else {      
-                       clip = new Rectangle (0, 0, form.Width, form.Height);
-                       //}
-
-                       ThemeEngine.Current.DrawManagedWindowDecorations (pe.Graphics, clip, this);
-                       XplatUI.PaintEventEnd (form.Handle, false);
+                       
+                       if (form.ActiveMenu != null) {
+                               Point pnt;
+
+                               pnt = GetMenuOrigin ();
+
+                               // The entire menu has to be in the clip rectangle because the 
+                               // control buttons are right-aligned and otherwise they would
+                               // stay painted when the window gets resized.
+                               clip = new Rectangle (pnt.X, pnt.Y, form.ClientSize.Width, 0);
+                               clip = Rectangle.Union (clip, pe.ClipRectangle);
+                               pe.SetClip (clip);
+                               pe.Graphics.SetClip (clip);
+
+                               form.ActiveMenu.Draw (pe, new Rectangle (pnt.X, pnt.Y, form.ClientSize.Width, 0));
+                       }
+                       if (HasBorders || IsMinimized && !(Form.IsMdiChild && IsMaximized)) {
+                               // clip region is not correct on win32.
+                               // use the entire form's area.
+                               clip = new Rectangle (0, 0, form.Width, form.Height);
+                               ThemeEngine.Current.DrawManagedWindowDecorations (pe.Graphics, clip, this);
+                       }
+                       XplatUI.PaintEventEnd (ref m, form.Handle, false);
                        return true;
                }
 
-               protected virtual void HandleNCCalcSize (ref Message m)
+               protected virtual bool HandleNCCalcSize (ref Message m)
                {
                        XplatUIWin32.NCCALCSIZE_PARAMS ncp;
+                       XplatUIWin32.RECT rect;
 
                        if (m.WParam == (IntPtr)1) {
                                ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (m.LParam,
                                                typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
+                               
+                               ncp.rgrc1 = NCCalcSize (ncp.rgrc1);
 
-                               int bw = ThemeEngine.Current.ManagedWindowBorderWidth (this);
+                               Marshal.StructureToPtr (ncp, m.LParam, true);
+                       } else {
+                               rect = (XplatUIWin32.RECT) Marshal.PtrToStructure (m.LParam, typeof (XplatUIWin32.RECT));
+                               
+                               rect = NCCalcSize (rect);
+                               
+                               Marshal.StructureToPtr (rect, m.LParam, true);
+                       }
+                       
+                       return true;
+               }
 
-                               if (HasBorders) {
-                                       ncp.rgrc1.top += TitleBarHeight + bw;
-                                       ncp.rgrc1.bottom -= bw;
-                                       ncp.rgrc1.left += bw;
-                                       ncp.rgrc1.right -= bw;
-                               }
+               protected virtual XplatUIWin32.RECT NCCalcSize (XplatUIWin32.RECT proposed_window_rect)
+               {
+                       int bw = ThemeEngine.Current.ManagedWindowBorderWidth (this);
 
+                       if (HasBorders) {
+                               proposed_window_rect.top += TitleBarHeight + bw;
+                               proposed_window_rect.bottom -= bw;
+                               proposed_window_rect.left += bw;
+                               proposed_window_rect.right -= bw;
+                       }
+
+                       if (XplatUI.RequiresPositiveClientAreaSize) {
                                // This is necessary for Linux, can't handle <= 0-sized 
                                // client areas correctly.
-                               if (ncp.rgrc1.right <= ncp.rgrc1.left) {
-                                       ncp.rgrc1.right += ncp.rgrc1.left - ncp.rgrc1.right + 1;
-                               }       
-                               if (ncp.rgrc1.top >= ncp.rgrc1.bottom) {
-                                       ncp.rgrc1.bottom += ncp.rgrc1.top - ncp.rgrc1.bottom + 1;
+                               if (proposed_window_rect.right <= proposed_window_rect.left) {
+                                       proposed_window_rect.right += proposed_window_rect.left - proposed_window_rect.right + 1;
+                               }
+                               if (proposed_window_rect.top >= proposed_window_rect.bottom) {
+                                       proposed_window_rect.bottom += proposed_window_rect.top - proposed_window_rect.bottom + 1;
                                }
-                               
-                               Marshal.StructureToPtr (ncp, m.LParam, true);
                        }
+
+                       return proposed_window_rect;
                }
 
                protected virtual bool HandleNCHitTest (ref Message m)
@@ -341,7 +369,9 @@ namespace System.Windows.Forms {
 
                public virtual void UpdateBorderStyle (FormBorderStyle border_style)
                {
-                       XplatUI.SetBorderStyle (form.Handle, border_style);
+                       if (form.IsHandleCreated) {
+                               XplatUI.SetBorderStyle (form.Handle, border_style);
+                       }
 
                        if (ShouldRemoveWindowManager (border_style)) {
                                form.RemoveWindowManager ();
@@ -392,17 +422,31 @@ namespace System.Windows.Forms {
 
                public bool IconRectangleContains (int x, int y)
                {
-                       if (form.Icon == null)
+                       if (!ShowIcon)
                                return false;
 
-                       int bw = ThemeEngine.Current.ManagedWindowBorderWidth (this);
-                       Rectangle icon = new Rectangle (bw + 3, bw + 2, IconWidth, IconWidth);
+                       Rectangle icon = ThemeEngine.Current.ManagedWindowGetTitleBarIconArea (this);
                        return icon.Contains (x, y);
                }
 
+               public bool ShowIcon {
+                       get {
+                               if (!Form.ShowIcon)
+                                       return false;
+                               if (!HasBorders)
+                                       return false;
+                               if (IsMinimized)
+                                       return true;
+                               if (IsToolWindow || Form.FormBorderStyle == FormBorderStyle.FixedDialog)
+                                       return false;
+                               return true;
+                       }
+               }
+
                protected virtual void Activate ()
                {
-                       form.Refresh ();
+                       form.Invalidate (true);
+                       form.Update ();
                }
 
                public virtual bool IsActive {
@@ -414,8 +458,10 @@ namespace System.Windows.Forms {
 
                private void FormSizeChangedHandler (object sender, EventArgs e)
                {
-                       ThemeEngine.Current.ManagedWindowSetButtonLocations (this);
-                       XplatUI.InvalidateNC (form.Handle);
+                       if (form.IsHandleCreated) {
+                               ThemeEngine.Current.ManagedWindowSetButtonLocations (this);
+                               XplatUI.InvalidateNC (form.Handle);
+                       }
                }
 
                protected virtual bool HandleRButtonDown (ref Message m)
@@ -464,6 +510,11 @@ namespace System.Windows.Forms {
                                return true;
                        }
 
+                       if (form.ActiveMenu != null && XplatUI.IsEnabled (form.Handle)) {
+                               MouseEventArgs mea = new MouseEventArgs (Form.FromParamToMouseButtons (m.WParam.ToInt32 ()), form.mouse_clicks, x, y, 0);
+                               form.ActiveMenu.OnMouseMove (form, mea);
+                       }
+
                        return true;
                        
                }
@@ -482,6 +533,11 @@ namespace System.Windows.Forms {
                        NCPointToClient (ref x, ref y);
                        FormPos pos = FormPosForCoords (x, y);
                        
+                       if (form.ActiveMenu != null && XplatUI.IsEnabled (form.Handle)) {
+                               MouseEventArgs mea = new MouseEventArgs (Form.FromParamToMouseButtons (m.WParam.ToInt32 ()), form.mouse_clicks, x, y - TitleBarHeight, 0);
+                               form.ActiveMenu.OnMouseDown (form, mea);
+                       }
+                       
                        if (pos == FormPos.TitleBar) {
                                HandleTitleBarDown (x, y);
                                return true;
@@ -527,16 +583,8 @@ namespace System.Windows.Forms {
                
                protected virtual void HandleTitleBarMouseMove (int x, int y)
                {
-                       bool any_change = false;
-                       
-                       any_change = title_buttons.MouseMove (x, y);
-                       
-                       if (any_change) {
-                               if (IsMaximized && form.IsMdiChild)
-                                       XplatUI.InvalidateNC (form.MdiParent.Handle);
-                               else
-                                       XplatUI.InvalidateNC (form.Handle);
-                       }
+                       if (title_buttons.MouseMove (x, y))
+                               XplatUI.InvalidateNC (form.Handle);
                }
                
                protected virtual void HandleTitleBarUp (int x, int y)
@@ -584,7 +632,7 @@ namespace System.Windows.Forms {
        
                protected virtual void HandleWindowMove (Message m)
                {
-                       Point move = MouseMove (m);
+                       Point move = MouseMove (Cursor.Position);
 
                        UpdateVP (virtual_position.X + move.X, virtual_position.Y + move.Y,
                                        virtual_position.Width, virtual_position.Height);
@@ -593,9 +641,17 @@ namespace System.Windows.Forms {
                private void HandleSizing (Message m)
                {
                        Rectangle pos = virtual_position;
-                       int bw = ThemeEngine.Current.ManagedWindowBorderWidth (this);
-                       int mw = MinTitleBarSize.Width + (bw * 2);
-                       int mh = MinTitleBarSize.Height + (bw * 2);
+                       int mw;
+                       int mh;
+                       if (IsToolWindow) {
+                               int border_width = BorderWidth;
+                               mw = 2 * (border_width + Theme.ManagedWindowSpacingAfterLastTitleButton) + ThemeEngine.Current.ManagedWindowButtonSize (this).Width;
+                               mh = 2 * border_width + TitleBarHeight;
+                       } else {
+                               Size minimum_size = SystemInformation.MinWindowTrackSize;
+                               mw = minimum_size.Width;
+                               mh = minimum_size.Height;
+                       }
                        int x = Cursor.Position.X;
                        int y = Cursor.Position.Y;
 
@@ -657,7 +713,8 @@ namespace System.Windows.Forms {
                public bool IsToolWindow {
                        get {
                                if (form.FormBorderStyle == FormBorderStyle.SizableToolWindow ||
-                                               form.FormBorderStyle == FormBorderStyle.FixedToolWindow)
+                                   form.FormBorderStyle == FormBorderStyle.FixedToolWindow || 
+                                   form.GetCreateParams().IsSet (WindowExStyles.WS_EX_TOOLWINDOW))
                                        return true;
                                return false;
                        }
@@ -669,6 +726,18 @@ namespace System.Windows.Forms {
                        }
                }
 
+               public int BorderWidth {
+                       get {
+                               return ThemeEngine.Current.ManagedWindowBorderWidth (this);
+                       }
+               }
+               
+               public virtual int MenuHeight {
+                       get {
+                               return (form.Menu != null ? ThemeEngine.Current.MenuHeight : 0);
+                       }
+               }
+
                protected void UpdateVP (Rectangle r)
                {
                        UpdateVP (r.X, r.Y, r.Width, r.Height);
@@ -736,19 +805,16 @@ namespace System.Windows.Forms {
                        if (!button.Rectangle.IntersectsWith (clip))
                                return;
 
-                       dc.FillRectangle (SystemBrushes.Control, button.Rectangle);
-                       ControlPaint.DrawCaptionButton (dc, button.Rectangle,
-                                       button.Caption, button.State);
+                       ThemeEngine.Current.ManagedWindowDrawMenuButton (dc, button, clip, this);
                }
 
                public virtual void DrawMaximizedButtons (object sender, PaintEventArgs pe)
                {
                }
 
-               protected Point MouseMove (Message m)
+               protected Point MouseMove (Point pos)
                {
-                       Point cp = Cursor.Position;
-                       return new Point (cp.X - start.X, cp.Y - start.Y);
+                       return new Point (pos.X - start.X, pos.Y - start.Y);
                }
 
                protected virtual void DrawVirtualPosition (Rectangle virtual_position)
@@ -773,12 +839,18 @@ namespace System.Windows.Forms {
 
                protected virtual void NCClientToNC (ref int x, ref int y) {
                        y += TitleBarHeight;
-                       y += ThemeEngine.Current.ManagedWindowBorderWidth (this);
+                       y += BorderWidth;
+                       y += MenuHeight;
+               }
+               
+               internal Point GetMenuOrigin ()
+               {
+                       return new Point (BorderWidth, BorderWidth + TitleBarHeight);
                }
                
                protected FormPos FormPosForCoords (int x, int y)
                {
-                       int bw = ThemeEngine.Current.ManagedWindowBorderWidth (this);
+                       int bw = BorderWidth;
                        if (y < TitleBarHeight + bw) {
                                //      Console.WriteLine ("A");
                                if (y > bw && x > bw &&
@@ -830,6 +902,7 @@ namespace System.Windows.Forms {
                public CaptionButton Caption;
                private EventHandler Clicked;
                public bool Visible;
+               bool entered;
 
                public TitleButton (CaptionButton caption, EventHandler clicked)
                {
@@ -843,6 +916,11 @@ namespace System.Windows.Forms {
                                Clicked (this, EventArgs.Empty);
                        }
                }
+
+               public bool Entered {
+                       get { return entered; }
+                       set { entered = value; }
+               }
        }
 
        internal class TitleButtons : System.Collections.IEnumerable
@@ -979,6 +1057,9 @@ namespace System.Windows.Forms {
                // Called from ToolTipStart if tooltip is already shown (with only_refresh = true)
                public void ToolTipShow (bool only_refresh)
                {
+                       if (!form.Visible)
+                               return;
+
                        string text = Locale.GetText (tooltip_hovered_button.Caption.ToString ());
 
                        tooltip_timer.Interval = tooltip_hide_interval;
@@ -1031,7 +1112,10 @@ namespace System.Windows.Forms {
                        foreach (TitleButton button in this) {
                                if (button == null)
                                        continue;
-
+                               
+                               if (button.State == ButtonState.Inactive)
+                                       continue;
+                                       
                                if (button == over_button) {
                                        if (any_pushed_buttons) {
                                                any_change |= button.State != ButtonState.Pushed;
@@ -1039,11 +1123,21 @@ namespace System.Windows.Forms {
                                        }
                                        ToolTipStart (button);
                                        any_tooltip = true;
+                                       if (!button.Entered) {
+                                               button.Entered = true;
+                                               if (ThemeEngine.Current.ManagedWindowTitleButtonHasHotElementStyle (button, form))
+                                                       any_change = true;
+                                       }
                                } else {
                                        if (any_pushed_buttons) {
                                                any_change |= button.State != ButtonState.Normal;
                                                button.State = ButtonState.Normal;
                                        }
+                                       if (button.Entered) {
+                                               button.Entered = false;
+                                               if (ThemeEngine.Current.ManagedWindowTitleButtonHasHotElementStyle (button, form))
+                                                       any_change = true;
+                                       }
                                }
                        }
 
@@ -1062,12 +1156,12 @@ namespace System.Windows.Forms {
                        ToolTipHide (false);
 
                        foreach (TitleButton button in this) {
-                               if (button != null) {
+                               if (button != null && button.State != ButtonState.Inactive) {
                                        button.State = ButtonState.Normal;
                                }
                        }
                        TitleButton clicked_button = FindButton (x, y);
-                       if (clicked_button != null) {
+                       if (clicked_button != null && clicked_button.State != ButtonState.Inactive) {
                                clicked_button.State = ButtonState.Pushed;
                        }
                }
@@ -1079,16 +1173,21 @@ namespace System.Windows.Forms {
                        }
                        
                        TitleButton clicked_button = FindButton (x, y);
-                       if (clicked_button != null) {
+                       if (clicked_button != null && clicked_button.State != ButtonState.Inactive) {
                                clicked_button.OnClick ();
                        }
 
                        foreach (TitleButton button in this) {
-                               if (button == null)
+                               if (button == null || button.State == ButtonState.Inactive)
                                        continue;
 
                                button.State = ButtonState.Normal;
                        }
+
+                       if (clicked_button == CloseButton && !form.closing)
+                               XplatUI.InvalidateNC (form.Handle);
+                               
+                       ToolTipHide (true);
                }
 
                internal void MouseLeave (int x, int y)
@@ -1098,7 +1197,7 @@ namespace System.Windows.Forms {
                        }
                        
                        foreach (TitleButton button in this) {
-                               if (button == null)
+                               if (button == null || button.State == ButtonState.Inactive)
                                        continue;
 
                                button.State = ButtonState.Normal;