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 (24, 22);
225 Size result = CalcButtonSize ();
227 return new Size (24, 22);
234 size_specified = true;
235 if (button_size == value)
245 [DefaultValue (true)]
246 public bool Divider {
247 get { return divider; }
249 if (value == divider)
257 [DefaultValue (DockStyle.Top)]
259 public override DockStyle Dock {
260 get { return base.Dock; }
261 set { base.Dock = value; }
264 bool drop_down_arrows = false;
266 [DefaultValue (false)]
268 public bool DropDownArrows {
269 get { return drop_down_arrows; }
271 if (value == drop_down_arrows)
274 drop_down_arrows = value;
280 [EditorBrowsable (EditorBrowsableState.Never)]
281 public override Color ForeColor {
282 get { return foreground_color; }
284 if (value == foreground_color)
287 foreground_color = value;
288 OnForeColorChanged (EventArgs.Empty);
293 ImageList image_list;
295 [DefaultValue (null)]
296 public ImageList ImageList {
297 get { return image_list; }
298 set { image_list = value; }
302 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
303 [EditorBrowsable (EditorBrowsableState.Advanced)]
304 public Size ImageSize {
306 if (ImageList == null)
309 return ImageList.ImageSize;
316 [EditorBrowsable (EditorBrowsableState.Never)]
317 public new ImeMode ImeMode {
318 get { return ime_mode; }
320 if (value == ime_mode)
324 OnImeModeChanged (EventArgs.Empty);
329 [EditorBrowsable (EditorBrowsableState.Never)]
330 public override RightToLeft RightToLeft {
331 get { return base.RightToLeft; }
333 if (value == base.RightToLeft)
336 base.RightToLeft = value;
337 OnRightToLeftChanged (EventArgs.Empty);
341 bool show_tooltips = false;
343 [DefaultValue (false)]
345 public bool ShowToolTips {
346 get { return show_tooltips; }
347 set { show_tooltips = value; }
350 [DefaultValue (false)]
351 public new bool TabStop {
352 get { return base.TabStop; }
353 set { base.TabStop = value; }
358 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
359 [EditorBrowsable (EditorBrowsableState.Never)]
360 public override string Text {
368 OnTextChanged (EventArgs.Empty);
372 ToolBarTextAlign text_alignment = ToolBarTextAlign.Underneath;
374 [DefaultValue (ToolBarTextAlign.Underneath)]
376 public ToolBarTextAlign TextAlign {
377 get { return text_alignment; }
379 if (value == text_alignment)
382 text_alignment = value;
387 bool wrappable = true;
389 [DefaultValue (true)]
391 public bool Wrappable {
392 get { return wrappable; }
394 if (value == wrappable)
401 #endregion Public Properties
403 #region Public Methods
404 public override string ToString ()
406 int count = this.Buttons.Count;
409 return string.Format ("System.Windows.Forms.ToolBar, Button.Count: 0");
411 return string.Format ("System.Windows.Forms.ToolBar, Button.Count: {0}, Buttons[0]: {1}",
412 count, this.Buttons [0].ToString ());
414 #endregion Public Methods
416 #region Protected Methods
417 protected override void CreateHandle ()
419 base.CreateHandle ();
422 protected override void Dispose (bool disposing)
427 base.Dispose (disposing);
430 protected virtual void OnButtonClick (ToolBarButtonClickEventArgs e)
432 if (e.Button.Style == ToolBarButtonStyle.ToggleButton) {
433 if (! e.Button.Pushed)
434 e.Button.Pushed = true;
436 e.Button.Pushed = false;
438 e.Button.pressed = false;
440 Invalidate (e.Button.Rectangle);
443 if (ButtonClick != null)
444 ButtonClick (this, e);
447 protected virtual void OnButtonDropDown (ToolBarButtonClickEventArgs e)
449 if (ButtonDropDown != null)
450 ButtonDropDown (this, e);
452 if (e.Button.DropDownMenu == null)
455 Point loc = new Point (e.Button.Rectangle.X + 1, e.Button.Rectangle.Bottom + 1);
456 ((ContextMenu) e.Button.DropDownMenu).Show (this, loc);
458 e.Button.dd_pressed = false;
459 Invalidate (e.Button.Rectangle);
462 protected override void OnFontChanged (EventArgs e)
464 base.OnFontChanged (e);
468 protected override void OnHandleCreated (EventArgs e)
470 base.OnHandleCreated (e);
473 protected override void OnResize (EventArgs e)
477 if (Width <= 0 || Height <= 0 || !Visible)
483 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
485 base.SetBoundsCore (x, y, width, height, specified);
488 protected override void WndProc (ref Message m)
490 base.WndProc (ref m);
493 #endregion Protected Methods
495 #region Private Methods
496 private void ToolBar_MouseDown (object sender, MouseEventArgs me)
501 Point loc = new Point (me.X, me.Y);
503 // draw the pushed button
504 foreach (ToolBarButton button in buttons) {
505 if (button.Enabled && button.Rectangle.Contains (loc)) {
506 // Mark the DropDown rect as pressed.
507 // We don't redraw the dropdown rect.
508 if (button.Style == ToolBarButtonStyle.DropDownButton) {
509 Rectangle rect = button.Rectangle;
510 rect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
511 rect.X = button.Rectangle.Right - rect.Width;
512 if (rect.Contains (loc)) {
513 if (button.DropDownMenu != null) {
514 button.dd_pressed = true;
520 button.pressed = true;
521 button.inside = true;
522 Invalidate (button.Rectangle);
528 private void ToolBar_MouseUp (object sender, MouseEventArgs me)
533 Point loc = new Point (me.X, me.Y);
535 // draw the normal button
536 // Make a copy in case the list is modified during enumeration
537 ArrayList buttons = new ArrayList (this.buttons);
538 foreach (ToolBarButton button in buttons) {
539 if (button.Enabled && button.Rectangle.Contains (loc)) {
540 if (button.Style == ToolBarButtonStyle.DropDownButton) {
541 Rectangle ddRect = button.Rectangle;
542 ddRect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
543 ddRect.X = button.Rectangle.Right - ddRect.Width;
544 if (ddRect.Contains (loc)) {
545 if (button.dd_pressed)
546 OnButtonDropDown (new ToolBarButtonClickEventArgs (button));
550 // Fire a ButtonClick
552 OnButtonClick (new ToolBarButtonClickEventArgs (button));
553 } else if (button.pressed) {
554 button.pressed = false;
555 Invalidate (button.Rectangle);
560 private void ToolBar_MouseLeave (object sender, EventArgs e)
562 if (!Enabled || appearance != ToolBarAppearance.Flat || current_button == null)
565 if (current_button.Hilight) {
566 current_button.Hilight = false;
567 Invalidate (current_button.Rectangle);
570 current_button = null;
573 private void ToolBar_MouseMove (object sender, MouseEventArgs me)
578 Point loc = new Point (me.X, me.Y);
581 // If the button was pressed and we leave, release the
582 // button press and vice versa
583 foreach (ToolBarButton button in buttons) {
584 if (button.pressed &&
585 (button.inside != button.Rectangle.Contains (loc))) {
586 button.inside = button.Rectangle.Contains (loc);
587 button.Hilight = false;
588 Invalidate (button.Rectangle);
594 // following is only for flat style toolbar
595 else if (appearance == ToolBarAppearance.Flat) {
596 if (current_button != null && current_button.Rectangle.Contains (loc)) {
597 if (current_button.Hilight || current_button.Pushed)
599 current_button.Hilight = true;
600 Invalidate (current_button.Rectangle);
604 foreach (ToolBarButton button in buttons) {
605 if (button.Rectangle.Contains (loc) && button.Enabled) {
606 current_button = button;
607 if (current_button.Hilight || current_button.Pushed)
609 current_button.Hilight = true;
610 Invalidate (current_button.Rectangle);
613 else if (button.Hilight) {
614 button.Hilight = false;
615 Invalidate (button.Rectangle);
623 internal override void OnPaintInternal (PaintEventArgs pevent)
625 ThemeEngine.Current.DrawToolBar (pevent.Graphics, pevent.ClipRectangle, this);
628 internal void Redraw (bool recalculate)
636 const int text_padding = 3;
638 private Size CalcButtonSize ()
640 string longest_text = buttons [0].Text;
641 for (int i = 1; i < buttons.Count; i++) {
642 if (buttons[i].Text.Length > longest_text.Length)
643 longest_text = buttons[i].Text;
646 Size size = Size.Empty;
647 if (longest_text != null && longest_text.Length > 0) {
648 SizeF sz = this.DeviceContext.MeasureString (longest_text, this.Font);
649 size = new Size ((int) Math.Ceiling (sz.Width) + 2 * text_padding, (int) Math.Ceiling (sz.Height));
652 if (ImageList != null) {
653 // adjustment for the image grip
654 int imgWidth = this.ImageSize.Width + 2 * ThemeEngine.Current.ToolBarImageGripWidth;
655 int imgHeight = this.ImageSize.Height + 2 * ThemeEngine.Current.ToolBarImageGripWidth;
657 if (text_alignment == ToolBarTextAlign.Right) {
658 size.Width = imgWidth + size.Width;
659 size.Height = (size.Height > imgHeight) ? size.Height : imgHeight;
662 size.Height = imgHeight + size.Height;
663 size.Width = (size.Width > imgWidth) ? size.Width : imgWidth;
671 Theme theme = ThemeEngine.Current;
672 int ht = ButtonSize.Height + theme.ToolBarGripWidth;
673 int x = theme.ToolBarGripWidth;
674 int y = theme.ToolBarGripWidth;
677 int separator_index = -1;
679 for (int i = 0; i < buttons.Count; i++) {
680 ToolBarButton button = buttons [i];
686 button.Layout (ButtonSize);
690 bool is_separator = button.Style == ToolBarButtonStyle.Separator;
692 if (x + button.Rectangle.Width < Width || is_separator) {
693 button.Location = new Point (x, y);
694 x += button.Rectangle.Width;
697 } else if (separator_index > 0) {
699 separator_index = -1;
700 x = theme.ToolBarGripWidth;
703 x = theme.ToolBarGripWidth;
705 button.Location = new Point (x, y);
706 x += button.Rectangle.Width;
715 Height = DefaultSize.Height;
716 foreach (ToolBarButton button in buttons) {
718 button.Layout (ButtonSize);
721 button.Location = new Point (x, y);
722 x += button.Rectangle.Width;
726 #endregion Private Methods
729 public class ToolBarButtonCollection : IList, ICollection, IEnumerable
731 #region instance variables
732 private ArrayList list;
733 private ToolBar owner;
737 public ToolBarButtonCollection (ToolBar owner)
740 list = new ArrayList ();
747 get { return list.Count; }
750 public bool IsReadOnly {
751 get { return list.IsReadOnly; }
754 public virtual ToolBarButton this [int index] {
755 get { return (ToolBarButton) list [index]; }
757 value.SetParent (owner);
758 list [index] = value;
763 bool ICollection.IsSynchronized {
764 get { return list.IsSynchronized; }
767 object ICollection.SyncRoot {
768 get { return list.SyncRoot; }
771 bool IList.IsFixedSize {
772 get { return list.IsFixedSize; }
775 object IList.this [int index] {
776 get { return this [index]; }
778 if (! (value is ToolBarButton))
779 throw new ArgumentException("Not of type ToolBarButton", "value");
780 this [index] = (ToolBarButton) value;
786 public int Add (string text)
788 ToolBarButton button = new ToolBarButton (text);
789 return this.Add (button);
792 public int Add (ToolBarButton button)
795 button.SetParent (owner);
796 result = list.Add (button);
801 public void AddRange (ToolBarButton [] buttons)
803 foreach (ToolBarButton button in buttons)
810 owner.Redraw (false);
813 public bool Contains (ToolBarButton button)
815 return list.Contains (button);
818 public IEnumerator GetEnumerator ()
820 return list.GetEnumerator ();
823 void ICollection.CopyTo (Array dest, int index)
825 list.CopyTo (dest, index);
828 int IList.Add (object button)
830 if (! (button is ToolBarButton)) {
831 throw new ArgumentException("Not of type ToolBarButton", "button");
834 return this.Add ((ToolBarButton) button);
837 bool IList.Contains (object button)
839 if (! (button is ToolBarButton)) {
840 throw new ArgumentException("Not of type ToolBarButton", "button");
843 return this.Contains ((ToolBarButton) button);
846 int IList.IndexOf (object button)
848 if (! (button is ToolBarButton)) {
849 throw new ArgumentException("Not of type ToolBarButton", "button");
852 return this.IndexOf ((ToolBarButton) button);
855 void IList.Insert (int index, object button)
857 if (! (button is ToolBarButton)) {
858 throw new ArgumentException("Not of type ToolBarButton", "button");
861 this.Insert (index, (ToolBarButton) button);
864 void IList.Remove (object button)
866 if (! (button is ToolBarButton)) {
867 throw new ArgumentException("Not of type ToolBarButton", "button");
870 this.Remove ((ToolBarButton) button);
873 public int IndexOf (ToolBarButton button)
875 return list.IndexOf (button);
878 public void Insert (int index, ToolBarButton button)
880 list.Insert (index, button);
884 public void Remove (ToolBarButton button)
886 list.Remove (button);
890 public void RemoveAt (int index)
892 list.RemoveAt (index);