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 // Make a copy in case the list is modified during enumeration
534 ArrayList buttons = new ArrayList (this.buttons);
535 foreach (ToolBarButton button in buttons) {
536 if (button.Enabled && button.Rectangle.Contains (loc)) {
537 if (button.Style == ToolBarButtonStyle.DropDownButton) {
538 Rectangle ddRect = button.Rectangle;
539 ddRect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
540 ddRect.X = button.Rectangle.Right - ddRect.Width;
541 if (ddRect.Contains (loc)) {
542 if (button.dd_pressed)
543 OnButtonDropDown (new ToolBarButtonClickEventArgs (button));
547 // Fire a ButtonClick
549 OnButtonClick (new ToolBarButtonClickEventArgs (button));
550 } else if (button.pressed) {
551 button.pressed = false;
552 Invalidate (button.Rectangle);
557 private void ToolBar_MouseLeave (object sender, EventArgs e)
559 if (!Enabled || appearance != ToolBarAppearance.Flat || current_button == null)
562 if (current_button.Hilight) {
563 current_button.Hilight = false;
564 Invalidate (current_button.Rectangle);
567 current_button = null;
570 private void ToolBar_MouseMove (object sender, MouseEventArgs me)
575 Point loc = new Point (me.X, me.Y);
578 // If the button was pressed and we leave, release the
579 // button press and vice versa
580 foreach (ToolBarButton button in buttons) {
581 if (button.pressed &&
582 (button.inside != button.Rectangle.Contains (loc))) {
583 button.inside = button.Rectangle.Contains (loc);
584 button.Hilight = false;
585 Invalidate (button.Rectangle);
591 // following is only for flat style toolbar
592 else if (appearance == ToolBarAppearance.Flat) {
593 if (current_button != null && current_button.Rectangle.Contains (loc)) {
594 if (current_button.Hilight || current_button.Pushed)
596 current_button.Hilight = true;
597 Invalidate (current_button.Rectangle);
601 foreach (ToolBarButton button in buttons) {
602 if (button.Rectangle.Contains (loc) && button.Enabled) {
603 current_button = button;
604 if (current_button.Hilight || current_button.Pushed)
606 current_button.Hilight = true;
607 Invalidate (current_button.Rectangle);
610 else if (button.Hilight) {
611 button.Hilight = false;
612 Invalidate (button.Rectangle);
620 internal override void OnPaintInternal (PaintEventArgs pevent)
622 ThemeEngine.Current.DrawToolBar (pevent.Graphics, pevent.ClipRectangle, this);
625 internal void Redraw (bool recalculate)
633 private Size CalcButtonSize ()
635 String longestText = buttons [0].Text;
636 for (int i = 1; i < buttons.Count; i++) {
637 if (buttons[i].Text.Length > longestText.Length)
638 longestText = buttons[i].Text;
641 SizeF sz = this.DeviceContext.MeasureString (longestText, this.Font);
642 Size size = new Size ((int) Math.Ceiling (sz.Width), (int) Math.Ceiling (sz.Height));
644 if (ImageList != null) {
645 // adjustment for the image grip
646 int imgWidth = this.ImageSize.Width + 2 * ThemeEngine.Current.ToolBarImageGripWidth;
647 int imgHeight = this.ImageSize.Height + 2 * ThemeEngine.Current.ToolBarImageGripWidth;
649 if (text_alignment == ToolBarTextAlign.Right) {
650 size.Width = imgWidth + size.Width;
651 size.Height = (size.Height > imgHeight) ? size.Height : imgHeight;
654 size.Height = imgHeight + size.Height;
655 size.Width = (size.Width > imgWidth) ? size.Width : imgWidth;
663 Theme theme = ThemeEngine.Current;
664 int ht = ButtonSize.Height + theme.ToolBarGripWidth;
665 int x = theme.ToolBarGripWidth;
666 int y = theme.ToolBarGripWidth;
669 int separator_index = -1;
671 for (int i = 0; i < buttons.Count; i++) {
672 ToolBarButton button = buttons [i];
678 button.Layout (ButtonSize);
682 bool is_separator = button.Style == ToolBarButtonStyle.Separator;
684 if (x + button.Rectangle.Width < Width || is_separator) {
685 button.Location = new Point (x, y);
686 x += button.Rectangle.Width;
689 } else if (separator_index > 0) {
691 separator_index = -1;
692 x = theme.ToolBarGripWidth;
695 x = theme.ToolBarGripWidth;
697 button.Location = new Point (x, y);
698 x += button.Rectangle.Width;
707 Height = DefaultSize.Height;
708 foreach (ToolBarButton button in buttons) {
710 button.Layout (ButtonSize);
713 button.Location = new Point (x, y);
714 x += button.Rectangle.Width;
718 #endregion Private Methods
721 public class ToolBarButtonCollection : IList, ICollection, IEnumerable
723 #region instance variables
724 private ArrayList list;
725 private ToolBar owner;
729 public ToolBarButtonCollection (ToolBar owner)
732 list = new ArrayList ();
739 get { return list.Count; }
742 public bool IsReadOnly {
743 get { return list.IsReadOnly; }
746 public virtual ToolBarButton this [int index] {
747 get { return (ToolBarButton) list [index]; }
749 value.SetParent (owner);
750 list [index] = value;
755 bool ICollection.IsSynchronized {
756 get { return list.IsSynchronized; }
759 object ICollection.SyncRoot {
760 get { return list.SyncRoot; }
763 bool IList.IsFixedSize {
764 get { return list.IsFixedSize; }
767 object IList.this [int index] {
768 get { return this [index]; }
770 if (! (value is ToolBarButton))
771 throw new ArgumentException("Not of type ToolBarButton", "value");
772 this [index] = (ToolBarButton) value;
778 public int Add (string text)
780 ToolBarButton button = new ToolBarButton (text);
781 return this.Add (button);
784 public int Add (ToolBarButton button)
787 button.SetParent (owner);
788 result = list.Add (button);
793 public void AddRange (ToolBarButton [] buttons)
795 foreach (ToolBarButton button in buttons)
802 owner.Redraw (false);
805 public bool Contains (ToolBarButton button)
807 return list.Contains (button);
810 public IEnumerator GetEnumerator ()
812 return list.GetEnumerator ();
815 void ICollection.CopyTo (Array dest, int index)
817 list.CopyTo (dest, index);
820 int IList.Add (object button)
822 if (! (button is ToolBarButton)) {
823 throw new ArgumentException("Not of type ToolBarButton", "button");
826 return this.Add ((ToolBarButton) button);
829 bool IList.Contains (object button)
831 if (! (button is ToolBarButton)) {
832 throw new ArgumentException("Not of type ToolBarButton", "button");
835 return this.Contains ((ToolBarButton) button);
838 int IList.IndexOf (object button)
840 if (! (button is ToolBarButton)) {
841 throw new ArgumentException("Not of type ToolBarButton", "button");
844 return this.IndexOf ((ToolBarButton) button);
847 void IList.Insert (int index, object button)
849 if (! (button is ToolBarButton)) {
850 throw new ArgumentException("Not of type ToolBarButton", "button");
853 this.Insert (index, (ToolBarButton) button);
856 void IList.Remove (object button)
858 if (! (button is ToolBarButton)) {
859 throw new ArgumentException("Not of type ToolBarButton", "button");
862 this.Remove ((ToolBarButton) button);
865 public int IndexOf (ToolBarButton button)
867 return list.IndexOf (button);
870 public void Insert (int index, ToolBarButton button)
872 list.Insert (index, button);
876 public void Remove (ToolBarButton button)
878 list.Remove (button);
882 public void RemoveAt (int index)
884 list.RemoveAt (index);