Merge pull request #268 from pcc/menudeactivate
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ToolBar.cs
index 3a6af0527464f96820e1869068be79a3f3990322..37e8f29eb2a949a1e9188dec9478ed0c69143087 100644 (file)
@@ -36,7 +36,9 @@ using System.Drawing.Imaging;
 using System.Runtime.InteropServices;
 
 namespace System.Windows.Forms
-{      
+{
+       [ComVisible (true)]
+       [ClassInterface (ClassInterfaceType.AutoDispatch)]
        [DefaultEvent ("ButtonClick")]
        [DefaultProperty ("Buttons")]
        [Designer ("System.Windows.Forms.Design.ToolBarDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
@@ -53,6 +55,13 @@ namespace System.Windows.Forms
                static object ButtonClickEvent = new object ();
                static object ButtonDropDownEvent = new object ();
 
+               [Browsable (true)]
+               [EditorBrowsable (EditorBrowsableState.Always)]
+               public new event EventHandler AutoSizeChanged {
+                       add { base.AutoSizeChanged += value; }
+                       remove { base.AutoSizeChanged -= value; }
+               }
+
                [Browsable (false)]
                [EditorBrowsable (EditorBrowsableState.Never)]
                public new event EventHandler BackColorChanged {
@@ -67,6 +76,13 @@ namespace System.Windows.Forms
                        remove { base.BackgroundImageChanged -= value; }
                }
 
+               [Browsable (false)]
+               [EditorBrowsable (EditorBrowsableState.Never)]
+               public new event EventHandler BackgroundImageLayoutChanged {
+                       add { base.BackgroundImageLayoutChanged += value; }
+                       remove { base.BackgroundImageLayoutChanged -= value; }
+               }
+
                public event ToolBarButtonClickEventHandler ButtonClick {
                        add { Events.AddHandler (ButtonClickEvent, value); }
                        remove {Events.RemoveHandler (ButtonClickEvent, value); }
@@ -140,7 +156,15 @@ namespace System.Windows.Forms
 
                #region protected Properties
                protected override CreateParams CreateParams {
-                       get { return base.CreateParams; }
+                       get { 
+                               CreateParams create_params = base.CreateParams;
+                               
+                               if (appearance == ToolBarAppearance.Flat) {
+                                       create_params.Style |= (int) ToolBarStyles.TBSTYLE_FLAT;
+                               }
+                               
+                               return create_params;
+                       }
                }
 
                protected override ImeMode DefaultImeMode {
@@ -150,6 +174,12 @@ namespace System.Windows.Forms
                protected override Size DefaultSize {
                        get { return ThemeEngine.Current.ToolBarDefaultSize; }
                }
+
+               [EditorBrowsable (EditorBrowsableState.Never)]
+               protected override bool DoubleBuffered {
+                       get { return base.DoubleBuffered; }
+                       set { base.DoubleBuffered = value; }
+               }
                #endregion
 
                ToolBarAppearance appearance = ToolBarAppearance.Normal;
@@ -170,21 +200,21 @@ namespace System.Windows.Forms
 
                bool autosize = true;
 
-#if NET_2_0
                [Browsable (true)]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
                [EditorBrowsable (EditorBrowsableState.Always)]
-#endif
                [DefaultValue (true)]
                [Localizable (true)]
-               public new bool AutoSize {
+               public override bool AutoSize {
                        get { return autosize; }
                        set {
                                if (value == autosize)
                                        return;
 
                                autosize = value;
-                               Redraw (true);
+                               
+                               if (IsHandleCreated)
+                                       Redraw (true);
                        }
                }
 
@@ -209,6 +239,13 @@ namespace System.Windows.Forms
                        set { base.BackgroundImage = value; }
                }
 
+               [Browsable (false)]
+               [EditorBrowsable (EditorBrowsableState.Never)]
+               public override ImageLayout BackgroundImageLayout {
+                       get { return base.BackgroundImageLayout; }
+                       set { base.BackgroundImageLayout = value; }
+               }
+
                [DefaultValue (BorderStyle.None)]
                [DispIdAttribute (-504)]
                public BorderStyle BorderStyle {
@@ -272,8 +309,12 @@ namespace System.Windows.Forms
                public override DockStyle Dock {
                        get { return base.Dock; }
                        set {
-                               if (base.Dock == value)
+                               if (base.Dock == value) {
+                                       // Call base anyways so layout_type gets set correctly
+                                       if (value != DockStyle.None)
+                                               base.Dock = value;
                                        return;
+                               }
                                        
                                if (Vertical) {
                                        SetStyle (ControlStyles.FixedWidth, AutoSize);
@@ -345,7 +386,7 @@ namespace System.Windows.Forms
 
                // XXX this should probably go away and it should call
                // into Control.ImeMode instead.
-               new ImeMode ime_mode = ImeMode.Disable;
+               ImeMode ime_mode = ImeMode.Disable;
 
                [Browsable (false)]
                [EditorBrowsable (EditorBrowsableState.Never)]
@@ -467,8 +508,31 @@ namespace System.Windows.Forms
                        base.Dispose (disposing);
                }
 
-               protected virtual void OnButtonClick (ToolBarButtonClickEventArgs e)
+               private ToolBarButton button_for_focus = null;
+               
+               internal void UIAPerformClick (ToolBarButton button)
                {
+                       ToolBarItem previous_item = current_item;
+                       current_item = null;
+                       
+                       foreach (ToolBarItem item in items)
+                               if (item.Button == button) {
+                                       current_item = item;
+                                       break;
+                               }
+
+                       try {
+                               if (current_item == null)
+                                       throw new ArgumentException ("button", "The button specified is not part of this toolbar");
+                               PerformButtonClick (new ToolBarButtonClickEventArgs (button));
+                       } finally {
+                               current_item = previous_item;
+                       }
+               }
+               
+               void PerformButtonClick (ToolBarButtonClickEventArgs e)
+               {
+                       // Only change pushed for ToogleButton
                        if (e.Button.Style == ToolBarButtonStyle.ToggleButton) {
                                if (! e.Button.Pushed)
                                        e.Button.Pushed = true;
@@ -479,6 +543,14 @@ namespace System.Windows.Forms
                        current_item.Pressed = false;
                        current_item.Invalidate ();
                        
+                       button_for_focus = current_item.Button;
+                       button_for_focus.UIAHasFocus = true;
+
+                       OnButtonClick (e);
+               }
+
+               protected virtual void OnButtonClick (ToolBarButtonClickEventArgs e)
+               {                       
                        ToolBarButtonClickEventHandler eh = (ToolBarButtonClickEventHandler)(Events [ButtonClickEvent]);
                        if (eh != null)
                                eh (this, e);
@@ -493,12 +565,17 @@ namespace System.Windows.Forms
                        if (e.Button.DropDownMenu == null)
                                return;
 
-                       Point loc = new Point (current_item.Rectangle.X + 1, current_item.Rectangle.Bottom + 1);
-                       ((ContextMenu) e.Button.DropDownMenu).Show (this, loc);
+                       ShowDropDownMenu (current_item);
+               }
 
-                       current_item.DDPressed = false;
-                       current_item.Hilight = false;
-                       Invalidate (current_item.Rectangle);
+               internal void ShowDropDownMenu (ToolBarItem item)
+               {
+                       Point loc = new Point (item.Rectangle.X + 1, item.Rectangle.Bottom + 1);
+                       ((ContextMenu) item.Button.DropDownMenu).Show (this, loc);
+
+                       item.DDPressed = false;
+                       item.Hilight = false;
+                       item.Invalidate ();
                }
 
                protected override void OnFontChanged (EventArgs e)
@@ -518,6 +595,21 @@ namespace System.Windows.Forms
                        LayoutToolBar ();
                }
 
+               protected override void ScaleControl (SizeF factor, BoundsSpecified specified)
+               {
+                       specified &= ~BoundsSpecified.Height;
+                       
+                       base.ScaleControl (factor, specified);
+               }
+
+               [EditorBrowsable (EditorBrowsableState.Never)]
+               protected override void ScaleCore (float dx, float dy)
+               {
+                       dy = 1.0f;
+                       
+                       base.ScaleCore (dx, dy);
+               }
+
                private int requested_size = -1;
 
                protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
@@ -542,7 +634,7 @@ namespace System.Windows.Forms
                {
                        if (msg.Msg == (int)Msg.WM_KEYDOWN) {
                                Keys key_data = (Keys)msg.WParam.ToInt32();
-                               if (HandleKeyDown (key_data))
+                               if (HandleKeyDown (ref msg, key_data))
                                        return true;
                        } 
                        return base.InternalPreProcessMessage (ref msg);
@@ -551,8 +643,28 @@ namespace System.Windows.Forms
                #endregion Protected Methods
 
                #region Private Methods
+               internal int CurrentItem {
+                       get {
+                               return Array.IndexOf (items, current_item);
+                       }
+                       set {
+                               if (current_item != null)
+                                       current_item.Hilight = false;
+
+                               current_item = value == -1 ? null : items [value];
+
+                               if (current_item != null)
+                                       current_item.Hilight = true;
+                       }
+
+               }
+
                private void FocusChanged (object sender, EventArgs args)
                {
+                       if (!Focused && button_for_focus != null)
+                               button_for_focus.UIAHasFocus = false;
+                       button_for_focus = null;
+                       
                        if (Appearance != ToolBarAppearance.Flat || Buttons.Count == 0)
                                return;
 
@@ -576,11 +688,15 @@ namespace System.Windows.Forms
                        }
                }
 
-               private bool HandleKeyDown (Keys key_data)
+               private bool HandleKeyDown (ref Message msg, Keys key_data)
                {
                        if (Appearance != ToolBarAppearance.Flat || Buttons.Count == 0)
                                return false;
 
+                       // Handle the key as needed if the current item is a dropdownbutton.
+                       if (HandleKeyOnDropDown (ref msg, key_data))
+                               return true;
+
                        switch (key_data) {
                                case Keys.Left:
                                case Keys.Up:
@@ -590,9 +706,39 @@ namespace System.Windows.Forms
                                case Keys.Down:
                                        HighlightButton (1);
                                        return true;
-                               default:
-                                       return false;
+                               case Keys.Enter:
+                               case Keys.Space:
+                                       if (current_item != null) {
+                                               OnButtonClick (new ToolBarButtonClickEventArgs (current_item.Button));
+                                               return true;
+                                       }
+                                       break;
+                       }
+
+                       return false;
+               }
+
+               bool HandleKeyOnDropDown (ref Message msg, Keys key_data)
+               {
+                       if (current_item == null || current_item.Button.Style != ToolBarButtonStyle.DropDownButton ||
+                                       current_item.Button.DropDownMenu == null)
+                               return false;
+
+                       Menu dropdown_menu = current_item.Button.DropDownMenu;
+
+                       if (dropdown_menu.Tracker.active) {
+                               dropdown_menu.ProcessCmdKey (ref msg, key_data);
+                               return true; // always true if the menu is active
+                       }
+
+                       if (key_data == Keys.Up || key_data == Keys.Down) {
+                               current_item.DDPressed = true;
+                               current_item.Invalidate ();
+                               OnButtonDropDown (new ToolBarButtonClickEventArgs (current_item.Button));
+                               return true;
                        }
+
+                       return false;
                }
 
                void HighlightButton (int offset)
@@ -622,7 +768,9 @@ namespace System.Windows.Forms
 
                        if (curr_item != null)
                                curr_item.Hilight = false;
-                       (enabled [next] as ToolBarItem).Hilight = true;
+
+                       current_item = enabled [next] as ToolBarItem;
+                       current_item.Hilight = true;
                }
 
                private void ToolBar_BackgroundImageChanged (object sender, EventArgs args)
@@ -643,7 +791,7 @@ namespace System.Windows.Forms
                        // Hide tooltip when left mouse button 
                        if ((tip_window != null) && (tip_window.Visible) && ((me.Button & MouseButtons.Left) == MouseButtons.Left)) {
                                TipDownTimer.Stop ();
-                               tip_window.Hide ();
+                               tip_window.Hide (this);
                        }
                        
                        // draw the pushed button
@@ -700,7 +848,7 @@ namespace System.Windows.Forms
                                        // Fire a ButtonClick
                                        current_item = item;
                                        if ((item.Pressed) && ((me.Button & MouseButtons.Left) == MouseButtons.Left))
-                                               OnButtonClick (new ToolBarButtonClickEventArgs (item.Button));
+                                               PerformButtonClick (new ToolBarButtonClickEventArgs (item.Button));
                                } else if (item.Pressed) {
                                        item.Pressed = false;
                                        item.Invalidate ();
@@ -717,12 +865,12 @@ namespace System.Windows.Forms
                        return null;
                }
 
-               ToolTip.ToolTipWindow tip_window = null;
+               ToolTip tip_window = null;
                Timer tipdown_timer = null;
 
                private void PopDownTip (object o, EventArgs args)
                {
-                       tip_window.Hide ();
+                       tip_window.Hide (this);
                }
 
                private Timer TipDownTimer {
@@ -743,7 +891,7 @@ namespace System.Windows.Forms
                                return;
 
                        if (tip_window == null)
-                               tip_window = new ToolTip.ToolTipWindow ();
+                               tip_window = new ToolTip ();
 
                        ToolBarItem item = ItemAtPoint (PointToClient (Control.MousePosition));
                        current_item = item;
@@ -798,15 +946,15 @@ namespace System.Windows.Forms
                        } 
 
                        if (current_item != null && current_item.Rectangle.Contains (loc)) {
-                               if (appearance == ToolBarAppearance.Flat) {
-                                       if (current_item.Hilight || current_item.Button.Pushed || !current_item.Button.Enabled)
+                               if (ThemeEngine.Current.ToolBarHasHotElementStyles (this)) {
+                                       if (current_item.Hilight || (!ThemeEngine.Current.ToolBarHasHotCheckedElementStyles && current_item.Button.Pushed) || !current_item.Button.Enabled)
                                                return;
                                        current_item.Hilight = true;
                                }
                        } else {
                                if (tip_window != null) {
                                        if (tip_window.Visible) {
-                                               tip_window.Hide ();
+                                               tip_window.Hide (this);
                                                TipDownTimer.Stop ();
                                        }
                                        current_item = ItemAtPoint (loc);
@@ -816,11 +964,11 @@ namespace System.Windows.Forms
                                        }
                                }
 
-                               if (appearance == ToolBarAppearance.Flat) {
+                               if (ThemeEngine.Current.ToolBarHasHotElementStyles (this)) {
                                        foreach (ToolBarItem item in items) {
                                                if (item.Rectangle.Contains (loc) && item.Button.Enabled) {
                                                        current_item = item;
-                                                       if (current_item.Hilight || current_item.Button.Pushed)
+                                                       if (current_item.Hilight || (!ThemeEngine.Current.ToolBarHasHotCheckedElementStyles && current_item.Button.Pushed))
                                                                continue;
                                                        current_item.Hilight = true;
                                                }
@@ -834,7 +982,13 @@ namespace System.Windows.Forms
 
                internal override void OnPaintInternal (PaintEventArgs pevent)
                {
+                       if (GetStyle (ControlStyles.UserPaint))
+                               return;
+                               
                        ThemeEngine.Current.DrawToolBar (pevent.Graphics, pevent.ClipRectangle, this);
+                       
+                       // Toolbars do not raise OnPaint unless UserPaint is set
+                       pevent.Handled = true;
                }
 
                internal void Redraw (bool recalculate)
@@ -857,7 +1011,7 @@ namespace System.Windows.Forms
                        get { return size_specified; }
                }
                
-               private bool Vertical {
+               internal bool Vertical {
                        get { return (Dock == DockStyle.Left) || (Dock == DockStyle.Right); }
                }
 
@@ -876,7 +1030,7 @@ namespace System.Windows.Forms
 
                        Size size = Size.Empty;
                        if (longest_text != null && longest_text.Length > 0) {
-                               SizeF sz = DeviceContext.MeasureString (longest_text, Font);
+                               SizeF sz = TextRenderer.MeasureString (longest_text, Font);
                                if (sz != SizeF.Empty)
                                        size = new Size ((int) Math.Ceiling (sz.Width) + 2 * text_padding, (int) Math.Ceiling (sz.Height));
                        }
@@ -904,7 +1058,12 @@ namespace System.Windows.Forms
                // button size to be at least large enough to show the image.
                private Size AdjustedButtonSize {
                        get {
-                               Size size = default_size.IsEmpty ? ButtonSize : default_size;
+                               Size size;
+
+                               if (default_size.IsEmpty || Appearance == ToolBarAppearance.Normal) 
+                                       size = ButtonSize;
+                               else
+                                       size = default_size;
                                
                                if (size_specified) {
                                        if (Appearance == ToolBarAppearance.Flat)
@@ -1003,12 +1162,12 @@ namespace System.Windows.Forms
                        if (Wrappable)
                                calculated_size += Vertical ? x : y;
                        
-                       if (Vertical)
-                               if (requested_size >= 0)
-                                       SetBounds (Bounds.X, Bounds.Y, AutoSize ? calculated_size : requested_size, Width, BoundsSpecified.None);
-                       else
-                               if (requested_size >= 0)
-                                       SetBounds (Bounds.X, Bounds.Y, Height, AutoSize ? calculated_size : requested_size, BoundsSpecified.None);
+                       if (IsHandleCreated) {
+                               if (Vertical)
+                                       Width = calculated_size;
+                               else
+                                       Height = calculated_size; 
+                       }
                        
                        return changed;
                }
@@ -1023,6 +1182,23 @@ namespace System.Windows.Forms
                        private bool redraw;    // Flag if needs to redraw after add/remove operations
                        #endregion
 
+                       #region UIA Framework Events
+                       static object UIACollectionChangedEvent = new object ();
+                       
+                       internal event CollectionChangeEventHandler UIACollectionChanged {
+                               add { owner.Events.AddHandler (UIACollectionChangedEvent, value); }
+                               remove { owner.Events.RemoveHandler (UIACollectionChangedEvent, value); }
+                       }
+
+                       internal void OnUIACollectionChanged (CollectionChangeEventArgs e)
+                       {
+                               CollectionChangeEventHandler eh
+                                       = (CollectionChangeEventHandler) owner.Events [UIACollectionChangedEvent];
+                               if (eh != null)
+                                       eh (owner, e);
+                       }
+                       #endregion
+
                        #region constructors
                        public ToolBarButtonCollection (ToolBar owner)
                        {
@@ -1045,9 +1221,28 @@ namespace System.Windows.Forms
                        public virtual ToolBarButton this [int index] {
                                get { return (ToolBarButton) list [index]; }
                                set {
+                                       // UIA Framework Event: Button Removed
+                                       OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
+
                                        value.SetParent (owner);
                                        list [index] = value;
                                        owner.Redraw (true);
+
+                               // UIA Framework Event: Button Added
+                               OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
+                               }
+                       }
+
+                       public virtual ToolBarButton this[string key] {
+                               get {
+                                       if (string.IsNullOrEmpty (key))
+                                               return null;
+                                               
+                                       foreach (ToolBarButton b in list)
+                                               if (string.Compare (b.Name, key, true) == 0)
+                                                       return b;
+                                                       
+                                       return null;
                                }
                        }
 
@@ -1087,6 +1282,10 @@ namespace System.Windows.Forms
                                result = list.Add (button);
                                if (redraw)
                                        owner.Redraw (true);
+
+                               // UIA Framework Event: Button Added
+                               OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, result));
+
                                return result;
                        }
 
@@ -1107,6 +1306,9 @@ namespace System.Windows.Forms
                        {
                                list.Clear ();
                                owner.Redraw (false);
+
+                               // UIA Framework Event: Button Cleared
+                               OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, -1));
                        }
 
                        public bool Contains (ToolBarButton button)
@@ -1114,6 +1316,11 @@ namespace System.Windows.Forms
                                return list.Contains (button);
                        }
 
+                       public virtual bool ContainsKey (string key)
+                       {
+                               return !(this[key] == null);
+                       }
+
                        public IEnumerator GetEnumerator ()
                        {
                                return list.GetEnumerator ();
@@ -1174,10 +1381,18 @@ namespace System.Windows.Forms
                                return list.IndexOf (button);
                        }
 
+                       public virtual int IndexOfKey (string key)
+                       {
+                               return IndexOf (this[key]);
+                       }
+
                        public void Insert (int index, ToolBarButton button)
                        {
                                list.Insert (index, button);
                                owner.Redraw (true);
+
+                               // UIA Framework Event: Button Added
+                               OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
                        }
 
                        public void Remove (ToolBarButton button)
@@ -1190,6 +1405,14 @@ namespace System.Windows.Forms
                        {
                                list.RemoveAt (index);
                                owner.Redraw (true);
+
+                               // UIA Framework Event: Button Removed
+                               OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
+                       }
+
+                       public virtual void RemoveByKey (string key)
+                       {
+                               Remove (this[key]);
                        }
                        #endregion methods
                }
@@ -1277,7 +1500,7 @@ namespace System.Windows.Forms
                                StringFormat text_format = new StringFormat ();
                                text_format.HotkeyPrefix = HotkeyPrefix.Hide;
 
-                               SizeF sz = toolbar.DeviceContext.MeasureString (button.Text, toolbar.Font, SizeF.Empty, text_format);
+                               SizeF sz = TextRenderer.MeasureString (button.Text, toolbar.Font, SizeF.Empty, text_format);
                                if (sz == SizeF.Empty)
                                        return Size.Empty;
                                return new Size ((int) Math.Ceiling (sz.Width) + 2 * ToolBar.text_padding, (int) Math.Ceiling (sz.Height));
@@ -1323,7 +1546,11 @@ namespace System.Windows.Forms
                        if (button.Style == ToolBarButtonStyle.Separator)
                                return new Size (theme.ToolBarSeparatorWidth, ht);
 
-                       Size size = TextSize.IsEmpty ? toolbar.default_size : TextSize;
+                       Size size;
+                       if (TextSize.IsEmpty && (button.Image == null))
+                               size = toolbar.default_size;
+                       else
+                               size = TextSize;
                        
                        Size image_size = (toolbar.ImageSize == Size.Empty) ? new Size (16, 16) : toolbar.ImageSize;