2006-12-26 Jonathan Pobst <monkey@jpobst.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ToolBar.cs
index 806fb3ffffdea52c9aa887c171c9d16eb05755f8..27af4c0709d50b80e7c35b41467e99ad2b4269e4 100644 (file)
@@ -52,6 +52,9 @@ namespace System.Windows.Forms
                #endregion Instance Variables
 
                #region Events
+               static object ButtonClickEvent = new object ();
+               static object ButtonDropDownEvent = new object ();
+
                [Browsable (false)]
                [EditorBrowsable (EditorBrowsableState.Never)]
                public new event EventHandler BackColorChanged {
@@ -66,8 +69,15 @@ namespace System.Windows.Forms
                        remove { base.BackgroundImageChanged -= value; }
                }
 
-               public event ToolBarButtonClickEventHandler ButtonClick;
-               public event ToolBarButtonClickEventHandler ButtonDropDown;
+               public event ToolBarButtonClickEventHandler ButtonClick {
+                       add { Events.AddHandler (ButtonClickEvent, value); }
+                       remove {Events.RemoveHandler (ButtonClickEvent, value); }
+               }
+
+               public event ToolBarButtonClickEventHandler ButtonDropDown {
+                       add { Events.AddHandler (ButtonDropDownEvent, value); }
+                       remove {Events.RemoveHandler (ButtonDropDownEvent, value); }
+               }
 
                [Browsable (false)]
                [EditorBrowsable (EditorBrowsableState.Never)]
@@ -116,10 +126,14 @@ namespace System.Windows.Forms
                        GotFocus += new EventHandler (FocusChanged);
                        LostFocus += new EventHandler (FocusChanged);
                        MouseDown += new MouseEventHandler (ToolBar_MouseDown);
+                       MouseHover += new EventHandler (ToolBar_MouseHover);
                        MouseLeave += new EventHandler (ToolBar_MouseLeave);
                        MouseMove += new MouseEventHandler (ToolBar_MouseMove);
                        MouseUp += new MouseEventHandler (ToolBar_MouseUp);
+                       BackgroundImageChanged += new EventHandler (ToolBar_BackgroundImageChanged);
 
+                       TabStop = false;
+                       
                        SetStyle (ControlStyles.UserPaint, false);
                        SetStyle (ControlStyles.FixedHeight, true);
                }
@@ -160,7 +174,7 @@ namespace System.Windows.Forms
 
                [DefaultValue (true)]
                [Localizable (true)]
-               public bool AutoSize {
+               public new bool AutoSize {
                        get { return autosize; }
                        set {
                                if (value == autosize)
@@ -188,15 +202,8 @@ namespace System.Windows.Forms
                [Browsable (false)]
                [EditorBrowsable (EditorBrowsableState.Never)]
                public override Image BackgroundImage {
-                       get { return background_image; }
-                       set {
-                               if (value == background_image)
-                                       return;
-
-                               background_image = value;
-                               OnBackgroundImageChanged (EventArgs.Empty);
-                               Redraw (false);
-                       }
+                       get { return base.BackgroundImage; }
+                       set { base.BackgroundImage = value; }
                }
 
                [DefaultValue (BorderStyle.None)]
@@ -263,7 +270,7 @@ namespace System.Windows.Forms
                        set { base.Dock = value; } 
                }
 
-               bool drop_down_arrows = false;
+               bool drop_down_arrows = true;
 
                [DefaultValue (false)]
                [Localizable (true)]
@@ -317,7 +324,9 @@ namespace System.Windows.Forms
                        }
                }
 
-               ImeMode ime_mode;
+               // XXX this should probably go away and it should call
+               // into Control.ImeMode instead.
+               new ImeMode ime_mode = ImeMode.Disable;
 
                [Browsable (false)]
                [EditorBrowsable (EditorBrowsableState.Never)]
@@ -345,7 +354,8 @@ namespace System.Windows.Forms
                        }
                }
 
-               bool show_tooltips = false;
+               // Default value is "false" but after make a test in .NET we get "true" result as default.  
+               bool show_tooltips = true;
 
                [DefaultValue (false)]
                [Localizable (true)]
@@ -365,14 +375,13 @@ namespace System.Windows.Forms
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [EditorBrowsable (EditorBrowsableState.Never)]
                public override string Text {
-                       get { return text; } 
+                       get { return base.Text; } 
                        set {
-                               if (value == text)
+                               if (value == base.Text)
                                        return;
 
-                               text = value;
+                               base.Text = value;
                                Redraw (true);
-                               OnTextChanged (EventArgs.Empty);
                        }
                }
 
@@ -413,9 +422,9 @@ namespace System.Windows.Forms
                        int count = this.Buttons.Count;
 
                        if (count == 0)
-                               return string.Format ("System.Windows.Forms.ToolBar, Button.Count: 0");
+                               return string.Format ("System.Windows.Forms.ToolBar, Buttons.Count: 0");
                        else
-                               return string.Format ("System.Windows.Forms.ToolBar, Button.Count: {0}, Buttons[0]: {1}",
+                               return string.Format ("System.Windows.Forms.ToolBar, Buttons.Count: {0}, Buttons[0]: {1}",
                                                      count, this.Buttons [0].ToString ());
                }
                #endregion Public Methods
@@ -444,16 +453,18 @@ namespace System.Windows.Forms
                        }
                        e.Button.pressed = false;
 
-                       e.Button.InvalidateBorder ();
+                       e.Button.Invalidate ();
 
-                       if (ButtonClick != null)
-                               ButtonClick (this, e);
+                       ToolBarButtonClickEventHandler eh = (ToolBarButtonClickEventHandler)(Events [ButtonClickEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
                protected virtual void OnButtonDropDown (ToolBarButtonClickEventArgs e) 
                {
-                       if (ButtonDropDown != null)
-                               ButtonDropDown (this, e);
+                       ToolBarButtonClickEventHandler eh = (ToolBarButtonClickEventHandler)(Events [ButtonDropDownEvent]);
+                       if (eh != null)
+                               eh (this, e);
 
                        if (e.Button.DropDownMenu == null)
                                return;
@@ -483,18 +494,17 @@ namespace System.Windows.Forms
                        if (Width <= 0 || Height <= 0 || !Visible)
                                return;
 
-                       Redraw (true);
+                       Redraw (true, BackgroundImage != null);
                }
 
-               bool height_specified = false;
                int requested_height = -1;
 
                protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
                {
-                       if ((specified & BoundsSpecified.Height) != 0) {
+                       // New height requested
+                       if (!AutoSize && (requested_height != height) && ((specified & BoundsSpecified.Height) != BoundsSpecified.None)) 
                                requested_height = height;
-                               height_specified = true;
-                       }
+                       
                        base.SetBoundsCore (x, y, width, height, specified);
                }
 
@@ -588,13 +598,27 @@ namespace System.Windows.Forms
                        (enabled [next] as ToolBarButton).Hilight = true;
                }
 
+               private void ToolBar_BackgroundImageChanged (object sender, EventArgs args)
+               {
+                       Redraw (false);
+               }
+
                private void ToolBar_MouseDown (object sender, MouseEventArgs me)
                {
-                       if (!Enabled) 
+                       if ((!Enabled) || ((me.Button & MouseButtons.Left) == 0))
                                return;
 
                        Point loc = new Point (me.X, me.Y);
 
+                       if (ButtonAtPoint (loc) == null)
+                               return;
+                       
+                       // Hide tooltip when left mouse button 
+                       if ((tip_window != null) && (tip_window.Visible) && ((me.Button & MouseButtons.Left) == MouseButtons.Left)) {
+                               TipDownTimer.Stop ();
+                               tip_window.Hide ();
+                       }
+                       
                        // draw the pushed button
                        foreach (ToolBarButton button in buttons) {
                                if (button.Enabled && button.Rectangle.Contains (loc)) {
@@ -602,8 +626,11 @@ namespace System.Windows.Forms
                                        // We don't redraw the dropdown rect.
                                        if (button.Style == ToolBarButtonStyle.DropDownButton) {
                                                Rectangle rect = button.Rectangle;
-                                               rect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
-                                               rect.X = button.Rectangle.Right - rect.Width;
+                                               if (DropDownArrows) {
+                                                       rect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
+                                                       rect.X = button.Rectangle.Right - rect.Width;
+                                               }
+                                               
                                                if (rect.Contains (loc)) {
                                                        if (button.DropDownMenu != null) {
                                                                button.dd_pressed = true;
@@ -614,7 +641,7 @@ namespace System.Windows.Forms
                                        }
                                        button.pressed = true;
                                        button.inside = true;
-                                       button.InvalidateBorder ();
+                                       button.Invalidate ();
                                        break;
                                }
                        }
@@ -622,7 +649,7 @@ namespace System.Windows.Forms
 
                private void ToolBar_MouseUp (object sender, MouseEventArgs me)
                {
-                       if (!Enabled) 
+                       if ((!Enabled) || ((me.Button & MouseButtons.Left) == 0))
                                return;
 
                        Point loc = new Point (me.X, me.Y);
@@ -643,23 +670,75 @@ namespace System.Windows.Forms
                                                }
                                        }
                                        // Fire a ButtonClick
-                                       if (button.pressed)
+                                       if ((button.pressed) && ((me.Button & MouseButtons.Left) == MouseButtons.Left))
                                                OnButtonClick (new ToolBarButtonClickEventArgs (button));
                                } else if (button.pressed) {
                                        button.pressed = false;
-                                       button.InvalidateBorder ();
+                                       button.Invalidate ();
+                               }
+                       }
+               }
+
+               private ToolBarButton ButtonAtPoint (Point pt)
+               {
+                       foreach (ToolBarButton button in buttons)
+                               if (button.Rectangle.Contains (pt)) 
+                                       return button;
+
+                       return null;
+               }
+
+               ToolTip.ToolTipWindow tip_window = null;
+               Timer tipdown_timer = null;
+
+               private void PopDownTip (object o, EventArgs args)
+               {
+                       tip_window.Hide ();
+               }
+
+               private Timer TipDownTimer {
+                       get {
+                               if (tipdown_timer == null) {
+                                       tipdown_timer = new Timer ();
+                                       tipdown_timer.Enabled = false;
+                                       tipdown_timer.Interval = 5000;
+                                       tipdown_timer.Tick += new EventHandler (PopDownTip);
                                }
+                               return tipdown_timer;
                        }
                }
 
+               private void ToolBar_MouseHover (object sender, EventArgs e)
+               {
+                       if (Capture)
+                               return;
+
+                       if (tip_window == null)
+                               tip_window = new ToolTip.ToolTipWindow ();
+
+                       ToolBarButton btn = ButtonAtPoint (PointToClient (Control.MousePosition));
+                       current_button = btn;
+
+                       if (btn == null || btn.ToolTipText.Length == 0)
+                               return;
+
+                       tip_window.Present (this, btn.ToolTipText);
+                       TipDownTimer.Start ();
+               }
+
                private void ToolBar_MouseLeave (object sender, EventArgs e)
                {
-                       if (!Enabled || appearance != ToolBarAppearance.Flat || current_button == null) 
+                       if (tipdown_timer != null)
+                               tipdown_timer.Dispose ();
+                       tipdown_timer = null;
+                       if (tip_window != null)
+                               tip_window.Dispose ();
+                       tip_window = null;
+
+                       if (!Enabled || current_button == null) 
                                return;
 
-                       if (current_button.Hilight) {
-                               current_button.Hilight = false;
-                       }
+                       current_button.Hilight = false;
                        current_button = null;
                }
 
@@ -668,9 +747,14 @@ namespace System.Windows.Forms
                        if (!Enabled) 
                                return;
 
+                       if (tip_window != null && tip_window.Visible) {
+                               TipDownTimer.Stop ();
+                               TipDownTimer.Start ();
+                       }
+
                        Point loc = new Point (me.X, me.Y);
 
-                       if (this.Capture) {
+                       if (Capture) {
                                // If the button was pressed and we leave, release the 
                                // button press and vice versa
                                foreach (ToolBarButton button in buttons) {
@@ -681,15 +765,29 @@ namespace System.Windows.Forms
                                                break;
                                        }
                                }
-                       }
-                       // following is only for flat style toolbar
-                       else if (appearance == ToolBarAppearance.Flat) {
-                               if (current_button != null && current_button.Rectangle.Contains (loc)) {
-                                       if (current_button.Hilight || current_button.Pushed)
+                               return;
+                       } 
+
+                       if (current_button != null && current_button.Rectangle.Contains (loc)) {
+                               if (appearance == ToolBarAppearance.Flat) {
+                                       if (current_button.Hilight || current_button.Pushed || !current_button.Enabled)
                                                return;
                                        current_button.Hilight = true;
                                }
-                               else {
+                       } else {
+                               if (tip_window != null) {
+                                       if (tip_window.Visible) {
+                                               tip_window.Hide ();
+                                               TipDownTimer.Stop ();
+                                       }
+                                       current_button = ButtonAtPoint (loc);
+                                       if (current_button != null && current_button.ToolTipText.Length > 0) {
+                                               tip_window.Present (this, current_button.ToolTipText);
+                                               TipDownTimer.Start ();
+                                       }
+                               }
+
+                               if (appearance == ToolBarAppearance.Flat) {
                                        foreach (ToolBarButton button in buttons) {
                                                if (button.Rectangle.Contains (loc) && button.Enabled) {
                                                        current_button = button;
@@ -712,10 +810,18 @@ namespace System.Windows.Forms
 
                internal void Redraw (bool recalculate)
                {
-                       if (recalculate)
-                               Layout ();
+                       Redraw (recalculate, true);
+               }
 
-                       Invalidate ();
+               internal void Redraw (bool recalculate, bool force)
+               {
+                       bool invalidate = true;
+                       if (recalculate) {
+                               invalidate = LayoutToolBar ();
+                       }
+
+                       if (force || invalidate)
+                               Invalidate ();
                }
 
                internal bool SizeSpecified {
@@ -781,65 +887,62 @@ namespace System.Windows.Forms
                        }
                }
 
-               void Layout ()
+               bool LayoutToolBar ()
                {
+                       bool changed = false;
                        Theme theme = ThemeEngine.Current;
                        int x = theme.ToolBarGripWidth;
                        int y = theme.ToolBarGripWidth;
 
-                       Size button_size = AdjustedButtonSize;
+                       Size adjusted_size = AdjustedButtonSize;
+                       int ht = adjusted_size.Height + theme.ToolBarGripWidth;
 
-                       int ht = button_size.Height + theme.ToolBarGripWidth;
+                       int separator_index = -1;
 
-                       if (Wrappable && Parent != null) {
-                               int separator_index = -1;
+                       for (int i = 0; i < buttons.Count; i++) {
+                               ToolBarButton button = buttons [i];
 
-                               for (int i = 0; i < buttons.Count; i++) {
-                                       ToolBarButton button = buttons [i];
+                               if (!button.Visible)
+                                       continue;
 
-                                       if (!button.Visible)
-                                               continue;
+                               if (size_specified && (button.Style != ToolBarButtonStyle.Separator))
+                                       changed = button.Layout (adjusted_size);
+                               else
+                                       changed = button.Layout ();
+                               
+                               bool is_separator = button.Style == ToolBarButtonStyle.Separator;
 
-                                       if (size_specified)
-                                               button.Layout (button_size);
-                                       else
-                                               button.Layout ();
-
-                                       bool is_separator = button.Style == ToolBarButtonStyle.Separator;
-
-                                       if (x + button.Rectangle.Width < Width || is_separator) {
-                                               button.Location = new Point (x, y);
-                                               x += button.Rectangle.Width;
-                                               if (is_separator)
-                                                       separator_index = i;
-                                       } else if (separator_index > 0) { 
-                                               i = separator_index;
-                                               separator_index = -1;
-                                               x = theme.ToolBarGripWidth;
-                                               y += ht; 
-                                       } else {
-                                               x = theme.ToolBarGripWidth;
-                                               y += ht; 
-                                               button.Location = new Point (x, y);
-                                               x += button.Rectangle.Width;
-                                       }
-                               }
-                               if (AutoSize)
-                                       Height = y + ht;
-                       } else {
-                               if (AutoSize)
-                                       Height = ht;
-                               else if (!height_specified)
-                                       Height = DefaultSize.Height;
-                               foreach (ToolBarButton button in buttons) {
-                                       if (size_specified)
-                                               button.Layout (button_size);
-                                       else
-                                               button.Layout ();
+                               if (x + button.Rectangle.Width < Width || is_separator || !Wrappable) {
+                                       if (button.Location.X != x || button.Location.Y != y)
+                                               changed = true;
+                                       button.Location = new Point (x, y);
+                                       x += button.Rectangle.Width;
+                                       if (is_separator)
+                                               separator_index = i;
+                               } else if (separator_index > 0) {
+                                       i = separator_index;
+                                       separator_index = -1;
+                                       x = theme.ToolBarGripWidth;
+                                       y += ht; 
+                               } else {
+                                       x = theme.ToolBarGripWidth;
+                                       y += ht; 
+                                       if (button.Location.X != x || button.Location.Y != y)
+                                               changed = true;
                                        button.Location = new Point (x, y);
                                        x += button.Rectangle.Width;
                                }
                        }
+                       
+                       if (Parent == null)
+                               return changed;
+                       
+                       if (AutoSize)
+                               Height = ht + (Wrappable ? y : 0);
+                       else
+                               Height = requested_height;
+                       
+                       return changed;
                }
                #endregion Private Methods
 
@@ -849,6 +952,7 @@ namespace System.Windows.Forms
                        #region instance variables
                        private ArrayList list;
                        private ToolBar owner;
+                       private bool redraw;
                        #endregion
 
                        #region constructors
@@ -856,6 +960,7 @@ namespace System.Windows.Forms
                        {
                                this.owner = owner;
                                list = new ArrayList ();
+                               redraw = true;
                        }
                        #endregion
 
@@ -912,14 +1017,22 @@ namespace System.Windows.Forms
                                int result;
                                button.SetParent (owner);
                                result = list.Add (button);
-                               owner.Redraw (true);
+                               if (redraw)
+                                       owner.Redraw (true);
                                return result;
                        }
 
                        public void AddRange (ToolBarButton [] buttons)
                        {
-                               foreach (ToolBarButton button in buttons)
-                                       Add (button);
+                               try {
+                                       redraw = false;
+                                       foreach (ToolBarButton button in buttons)
+                                               Add (button);
+                               }
+                               finally {
+                                       redraw = true;
+                                       owner.Redraw (true);
+                               }
                        }
 
                        public void Clear ()