1 // System.Windows.Forms.ToolBar.cs
3 // Permission is hereby granted, free of charge, to any person obtaining
4 // a copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to
9 // the following conditions:
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 // Ravindra (rkumar@novell.com)
24 // Mike Kestner <mkestner@novell.com>
29 // Copyright (C) 2004-2006 Novell, Inc. (http://www.novell.com)
35 using System.Collections;
36 using System.ComponentModel;
37 using System.ComponentModel.Design;
39 using System.Drawing.Imaging;
40 using System.Runtime.InteropServices;
42 namespace System.Windows.Forms
44 [DefaultEvent ("ButtonClick")]
45 [DefaultProperty ("Buttons")]
46 [Designer ("System.Windows.Forms.Design.ToolBarDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
47 public class ToolBar : Control
49 #region Instance Variables
50 bool size_specified = false;
51 ToolBarButton current_button;
52 #endregion Instance Variables
56 [EditorBrowsable (EditorBrowsableState.Never)]
57 public new event EventHandler BackColorChanged {
58 add { base.BackColorChanged += value; }
59 remove { base.BackColorChanged -= value; }
63 [EditorBrowsable (EditorBrowsableState.Never)]
64 public new event EventHandler BackgroundImageChanged {
65 add { base.BackgroundImageChanged += value; }
66 remove { base.BackgroundImageChanged -= value; }
69 public event ToolBarButtonClickEventHandler ButtonClick;
70 public event ToolBarButtonClickEventHandler ButtonDropDown;
73 [EditorBrowsable (EditorBrowsableState.Never)]
74 public new event EventHandler ForeColorChanged {
75 add { base.ForeColorChanged += value; }
76 remove { base.ForeColorChanged -= value; }
80 [EditorBrowsable (EditorBrowsableState.Never)]
81 public new event EventHandler ImeModeChanged {
82 add { base.ImeModeChanged += value; }
83 remove { base.ImeModeChanged -= value; }
87 [EditorBrowsable (EditorBrowsableState.Never)]
88 public new event PaintEventHandler Paint {
89 add { base.Paint += value; }
90 remove { base.Paint -= value; }
94 [EditorBrowsable (EditorBrowsableState.Never)]
95 public new event EventHandler RightToLeftChanged {
96 add { base.RightToLeftChanged += value; }
97 remove { base.RightToLeftChanged -= value; }
101 [EditorBrowsable (EditorBrowsableState.Never)]
102 public new event EventHandler TextChanged {
103 add { base.TextChanged += value; }
104 remove { base.TextChanged -= value; }
111 background_color = ThemeEngine.Current.DefaultControlBackColor;
112 foreground_color = ThemeEngine.Current.DefaultControlForeColor;
113 buttons = new ToolBarButtonCollection (this);
114 dock_style = DockStyle.Top;
116 MouseDown += new MouseEventHandler (ToolBar_MouseDown);
117 MouseLeave += new EventHandler (ToolBar_MouseLeave);
118 MouseMove += new MouseEventHandler (ToolBar_MouseMove);
119 MouseUp += new MouseEventHandler (ToolBar_MouseUp);
121 SetStyle (ControlStyles.UserPaint, false);
122 SetStyle (ControlStyles.FixedHeight, true);
124 #endregion Constructor
126 #region protected Properties
127 protected override CreateParams CreateParams
129 get { return base.CreateParams; }
132 protected override ImeMode DefaultImeMode {
133 get { return ImeMode.Disable; }
136 protected override Size DefaultSize {
137 get { return ThemeEngine.Current.ToolBarDefaultSize; }
141 ToolBarAppearance appearance = ToolBarAppearance.Normal;
143 #region Public Properties
144 [DefaultValue (ToolBarAppearance.Normal)]
146 public ToolBarAppearance Appearance {
147 get { return appearance; }
149 if (value == appearance)
157 bool autosize = true;
159 [DefaultValue (true)]
161 public bool AutoSize {
162 get { return autosize; }
164 if (value == autosize)
173 [EditorBrowsable (EditorBrowsableState.Never)]
174 public override Color BackColor {
175 get { return background_color; }
177 if (value == background_color)
180 background_color = value;
181 OnBackColorChanged (EventArgs.Empty);
187 [EditorBrowsable (EditorBrowsableState.Never)]
188 public override Image BackgroundImage {
189 get { return background_image; }
191 if (value == background_image)
194 background_image = value;
195 OnBackgroundImageChanged (EventArgs.Empty);
200 [DefaultValue (BorderStyle.None)]
201 [DispIdAttribute (-504)]
202 public BorderStyle BorderStyle {
203 get { return InternalBorderStyle; }
204 set { InternalBorderStyle = value; }
207 ToolBarButtonCollection buttons;
209 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
211 [MergableProperty (false)]
212 public ToolBarButtonCollection Buttons {
213 get { return buttons; }
219 [RefreshProperties (RefreshProperties.All)]
220 public Size ButtonSize {
222 if (button_size.IsEmpty) {
223 if (buttons.Count == 0)
224 return new Size (39, 36);
226 return CalcButtonSize ();
231 size_specified = true;
232 if (button_size == value)
242 [DefaultValue (true)]
243 public bool Divider {
244 get { return divider; }
246 if (value == divider)
254 [DefaultValue (DockStyle.Top)]
256 public override DockStyle Dock {
257 get { return base.Dock; }
258 set { base.Dock = value; }
261 bool drop_down_arrows = false;
263 [DefaultValue (false)]
265 public bool DropDownArrows {
266 get { return drop_down_arrows; }
268 if (value == drop_down_arrows)
271 drop_down_arrows = value;
277 [EditorBrowsable (EditorBrowsableState.Never)]
278 public override Color ForeColor {
279 get { return foreground_color; }
281 if (value == foreground_color)
284 foreground_color = value;
285 OnForeColorChanged (EventArgs.Empty);
290 ImageList image_list;
292 [DefaultValue (null)]
293 public ImageList ImageList {
294 get { return image_list; }
295 set { image_list = value; }
299 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
300 [EditorBrowsable (EditorBrowsableState.Advanced)]
301 public Size ImageSize {
303 if (ImageList == null)
306 return ImageList.ImageSize;
313 [EditorBrowsable (EditorBrowsableState.Never)]
314 public new ImeMode ImeMode {
315 get { return ime_mode; }
317 if (value == ime_mode)
321 OnImeModeChanged (EventArgs.Empty);
326 [EditorBrowsable (EditorBrowsableState.Never)]
327 public override RightToLeft RightToLeft {
328 get { return base.RightToLeft; }
330 if (value == base.RightToLeft)
333 base.RightToLeft = value;
334 OnRightToLeftChanged (EventArgs.Empty);
338 bool show_tooltips = false;
340 [DefaultValue (false)]
342 public bool ShowToolTips {
343 get { return show_tooltips; }
344 set { show_tooltips = value; }
347 [DefaultValue (false)]
348 public new bool TabStop {
349 get { return base.TabStop; }
350 set { base.TabStop = value; }
355 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
356 [EditorBrowsable (EditorBrowsableState.Never)]
357 public override string Text {
365 OnTextChanged (EventArgs.Empty);
369 ToolBarTextAlign text_alignment = ToolBarTextAlign.Underneath;
371 [DefaultValue (ToolBarTextAlign.Underneath)]
373 public ToolBarTextAlign TextAlign {
374 get { return text_alignment; }
376 if (value == text_alignment)
379 text_alignment = value;
384 bool wrappable = true;
386 [DefaultValue (true)]
388 public bool Wrappable {
389 get { return wrappable; }
391 if (value == wrappable)
398 #endregion Public Properties
400 #region Public Methods
401 public override string ToString ()
403 int count = this.Buttons.Count;
406 return string.Format ("System.Windows.Forms.ToolBar, Button.Count: 0");
408 return string.Format ("System.Windows.Forms.ToolBar, Button.Count: {0}, Buttons[0]: {1}",
409 count, this.Buttons [0].ToString ());
411 #endregion Public Methods
413 #region Protected Methods
414 protected override void CreateHandle ()
416 base.CreateHandle ();
419 protected override void Dispose (bool disposing)
424 base.Dispose (disposing);
427 protected virtual void OnButtonClick (ToolBarButtonClickEventArgs e)
429 if (e.Button.Style == ToolBarButtonStyle.ToggleButton) {
430 if (! e.Button.Pushed)
431 e.Button.Pushed = true;
433 e.Button.Pushed = false;
435 e.Button.pressed = false;
437 Invalidate (e.Button.Rectangle);
440 if (ButtonClick != null)
441 ButtonClick (this, e);
444 protected virtual void OnButtonDropDown (ToolBarButtonClickEventArgs e)
446 if (ButtonDropDown != null)
447 ButtonDropDown (this, e);
449 if (e.Button.DropDownMenu == null)
452 Point loc = new Point (e.Button.Rectangle.X + 1, e.Button.Rectangle.Bottom + 1);
453 ((ContextMenu) e.Button.DropDownMenu).Show (this, loc);
455 e.Button.dd_pressed = false;
456 Invalidate (e.Button.Rectangle);
459 protected override void OnFontChanged (EventArgs e)
461 base.OnFontChanged (e);
465 protected override void OnHandleCreated (EventArgs e)
467 base.OnHandleCreated (e);
470 protected override void OnResize (EventArgs e)
474 if (Width <= 0 || Height <= 0 || !Visible)
480 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
482 base.SetBoundsCore (x, y, width, height, specified);
485 protected override void WndProc (ref Message m)
487 base.WndProc (ref m);
490 #endregion Protected Methods
492 #region Private Methods
493 private void ToolBar_MouseDown (object sender, MouseEventArgs me)
498 Point loc = new Point (me.X, me.Y);
500 // draw the pushed button
501 foreach (ToolBarButton button in buttons) {
502 if (button.Enabled && button.Rectangle.Contains (loc)) {
503 // Mark the DropDown rect as pressed.
504 // We don't redraw the dropdown rect.
505 if (button.Style == ToolBarButtonStyle.DropDownButton) {
506 Rectangle rect = button.Rectangle;
507 rect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
508 rect.X = button.Rectangle.Right - rect.Width;
509 if (rect.Contains (loc)) {
510 if (button.DropDownMenu != null) {
511 button.dd_pressed = true;
517 button.pressed = true;
518 button.inside = true;
519 Invalidate (button.Rectangle);
525 private void ToolBar_MouseUp (object sender, MouseEventArgs me)
530 Point loc = new Point (me.X, me.Y);
532 // draw the normal button
533 foreach (ToolBarButton button in buttons) {
534 if (button.Enabled && button.Rectangle.Contains (loc)) {
535 if (button.Style == ToolBarButtonStyle.DropDownButton) {
536 Rectangle ddRect = button.Rectangle;
537 ddRect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
538 ddRect.X = button.Rectangle.Right - ddRect.Width;
539 if (ddRect.Contains (loc)) {
540 if (button.dd_pressed)
541 OnButtonDropDown (new ToolBarButtonClickEventArgs (button));
545 // Fire a ButtonClick
547 OnButtonClick (new ToolBarButtonClickEventArgs (button));
548 } else if (button.pressed) {
549 button.pressed = false;
550 Invalidate (button.Rectangle);
555 private void ToolBar_MouseLeave (object sender, EventArgs e)
557 if (!Enabled || appearance != ToolBarAppearance.Flat || current_button == null)
560 if (current_button.Hilight) {
561 current_button.Hilight = false;
562 Invalidate (current_button.Rectangle);
565 current_button = null;
568 private void ToolBar_MouseMove (object sender, MouseEventArgs me)
573 Point loc = new Point (me.X, me.Y);
576 // If the button was pressed and we leave, release the
577 // button press and vice versa
578 foreach (ToolBarButton button in buttons) {
579 if (button.pressed &&
580 (button.inside != button.Rectangle.Contains (loc))) {
581 button.inside = button.Rectangle.Contains (loc);
582 button.Hilight = false;
583 Invalidate (button.Rectangle);
589 // following is only for flat style toolbar
590 else if (appearance == ToolBarAppearance.Flat) {
591 if (current_button != null && current_button.Rectangle.Contains (loc)) {
592 if (current_button.Hilight || current_button.Pushed)
594 current_button.Hilight = true;
595 Invalidate (current_button.Rectangle);
599 foreach (ToolBarButton button in buttons) {
600 if (button.Rectangle.Contains (loc) && button.Enabled) {
601 current_button = button;
602 if (current_button.Hilight || current_button.Pushed)
604 current_button.Hilight = true;
605 Invalidate (current_button.Rectangle);
608 else if (button.Hilight) {
609 button.Hilight = false;
610 Invalidate (button.Rectangle);
618 internal override void OnPaintInternal (PaintEventArgs pevent)
620 ThemeEngine.Current.DrawToolBar (pevent.Graphics, pevent.ClipRectangle, this);
623 internal void Redraw (bool recalculate)
631 private Size CalcButtonSize ()
633 String longestText = buttons [0].Text;
634 for (int i = 1; i < buttons.Count; i++) {
635 if (buttons[i].Text.Length > longestText.Length)
636 longestText = buttons[i].Text;
639 SizeF sz = this.DeviceContext.MeasureString (longestText, this.Font);
640 Size size = new Size ((int) Math.Ceiling (sz.Width), (int) Math.Ceiling (sz.Height));
642 if (ImageList != null) {
643 // adjustment for the image grip
644 int imgWidth = this.ImageSize.Width + 2 * ThemeEngine.Current.ToolBarImageGripWidth;
645 int imgHeight = this.ImageSize.Height + 2 * ThemeEngine.Current.ToolBarImageGripWidth;
647 if (text_alignment == ToolBarTextAlign.Right) {
648 size.Width = imgWidth + size.Width;
649 size.Height = (size.Height > imgHeight) ? size.Height : imgHeight;
652 size.Height = imgHeight + size.Height;
653 size.Width = (size.Width > imgWidth) ? size.Width : imgWidth;
661 Theme theme = ThemeEngine.Current;
662 int ht = ButtonSize.Height + theme.ToolBarGripWidth;
663 int x = theme.ToolBarGripWidth;
664 int y = theme.ToolBarGripWidth;
667 int separator_index = -1;
669 for (int i = 0; i < buttons.Count; i++) {
670 ToolBarButton button = buttons [i];
676 button.Layout (ButtonSize);
680 bool is_separator = button.Style == ToolBarButtonStyle.Separator;
682 if (x + button.Rectangle.Width < Width || is_separator) {
683 button.Location = new Point (x, y);
684 x += button.Rectangle.Width;
687 } else if (separator_index > 0) {
689 separator_index = -1;
690 x = theme.ToolBarGripWidth;
693 x = theme.ToolBarGripWidth;
695 button.Location = new Point (x, y);
696 x += button.Rectangle.Width;
705 Height = DefaultSize.Height;
706 foreach (ToolBarButton button in buttons) {
708 button.Layout (ButtonSize);
711 button.Location = new Point (x, y);
712 x += button.Rectangle.Width;
716 #endregion Private Methods
719 public class ToolBarButtonCollection : IList, ICollection, IEnumerable
721 #region instance variables
722 private ArrayList list;
723 private ToolBar owner;
727 public ToolBarButtonCollection (ToolBar owner)
730 list = new ArrayList ();
737 get { return list.Count; }
740 public bool IsReadOnly {
741 get { return list.IsReadOnly; }
744 public virtual ToolBarButton this [int index] {
745 get { return (ToolBarButton) list [index]; }
747 value.SetParent (owner);
748 list [index] = value;
753 bool ICollection.IsSynchronized {
754 get { return list.IsSynchronized; }
757 object ICollection.SyncRoot {
758 get { return list.SyncRoot; }
761 bool IList.IsFixedSize {
762 get { return list.IsFixedSize; }
765 object IList.this [int index] {
766 get { return this [index]; }
768 if (! (value is ToolBarButton))
769 throw new ArgumentException("Not of type ToolBarButton", "value");
770 this [index] = (ToolBarButton) value;
776 public int Add (string text)
778 ToolBarButton button = new ToolBarButton (text);
779 return this.Add (button);
782 public int Add (ToolBarButton button)
785 button.SetParent (owner);
786 result = list.Add (button);
791 public void AddRange (ToolBarButton [] buttons)
793 foreach (ToolBarButton button in buttons)
800 owner.Redraw (false);
803 public bool Contains (ToolBarButton button)
805 return list.Contains (button);
808 public IEnumerator GetEnumerator ()
810 return list.GetEnumerator ();
813 void ICollection.CopyTo (Array dest, int index)
815 list.CopyTo (dest, index);
818 int IList.Add (object button)
820 if (! (button is ToolBarButton)) {
821 throw new ArgumentException("Not of type ToolBarButton", "button");
824 return this.Add ((ToolBarButton) button);
827 bool IList.Contains (object button)
829 if (! (button is ToolBarButton)) {
830 throw new ArgumentException("Not of type ToolBarButton", "button");
833 return this.Contains ((ToolBarButton) button);
836 int IList.IndexOf (object button)
838 if (! (button is ToolBarButton)) {
839 throw new ArgumentException("Not of type ToolBarButton", "button");
842 return this.IndexOf ((ToolBarButton) button);
845 void IList.Insert (int index, object button)
847 if (! (button is ToolBarButton)) {
848 throw new ArgumentException("Not of type ToolBarButton", "button");
851 this.Insert (index, (ToolBarButton) button);
854 void IList.Remove (object button)
856 if (! (button is ToolBarButton)) {
857 throw new ArgumentException("Not of type ToolBarButton", "button");
860 this.Remove ((ToolBarButton) button);
863 public int IndexOf (ToolBarButton button)
865 return list.IndexOf (button);
868 public void Insert (int index, ToolBarButton button)
870 list.Insert (index, button);
874 public void Remove (ToolBarButton button)
876 list.Remove (button);
880 public void RemoveAt (int index)
882 list.RemoveAt (index);