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);
120 Paint += new PaintEventHandler (ToolBar_Paint);
122 SetStyle (ControlStyles.UserPaint, false);
123 SetStyle (ControlStyles.FixedHeight, true);
125 #endregion Constructor
127 #region protected Properties
128 protected override CreateParams CreateParams
130 get { return base.CreateParams; }
133 protected override ImeMode DefaultImeMode {
134 get { return ImeMode.Disable; }
137 protected override Size DefaultSize {
138 get { return ThemeEngine.Current.ToolBarDefaultSize; }
142 ToolBarAppearance appearance = ToolBarAppearance.Normal;
144 #region Public Properties
145 [DefaultValue (ToolBarAppearance.Normal)]
147 public ToolBarAppearance Appearance {
148 get { return appearance; }
150 if (value == appearance)
158 bool autosize = true;
160 [DefaultValue (true)]
162 public bool AutoSize {
163 get { return autosize; }
165 if (value == autosize)
174 [EditorBrowsable (EditorBrowsableState.Never)]
175 public override Color BackColor {
176 get { return background_color; }
178 if (value == background_color)
181 background_color = value;
182 OnBackColorChanged (EventArgs.Empty);
188 [EditorBrowsable (EditorBrowsableState.Never)]
189 public override Image BackgroundImage {
190 get { return background_image; }
192 if (value == background_image)
195 background_image = value;
196 OnBackgroundImageChanged (EventArgs.Empty);
201 [DefaultValue (BorderStyle.None)]
202 [DispIdAttribute (-504)]
203 public BorderStyle BorderStyle {
204 get { return InternalBorderStyle; }
205 set { InternalBorderStyle = value; }
208 ToolBarButtonCollection buttons;
210 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
212 [MergableProperty (false)]
213 public ToolBarButtonCollection Buttons {
214 get { return buttons; }
220 [RefreshProperties (RefreshProperties.All)]
221 public Size ButtonSize {
223 if (button_size.IsEmpty) {
224 if (buttons.Count == 0)
225 return new Size (39, 36);
227 return CalcButtonSize ();
232 size_specified = true;
233 if (button_size == value)
243 [DefaultValue (true)]
244 public bool Divider {
245 get { return divider; }
247 if (value == divider)
255 [DefaultValue (DockStyle.Top)]
257 public override DockStyle Dock {
258 get { return base.Dock; }
259 set { base.Dock = value; }
262 bool drop_down_arrows = false;
264 [DefaultValue (false)]
266 public bool DropDownArrows {
267 get { return drop_down_arrows; }
269 if (value == drop_down_arrows)
272 drop_down_arrows = value;
278 [EditorBrowsable (EditorBrowsableState.Never)]
279 public override Color ForeColor {
280 get { return foreground_color; }
282 if (value == foreground_color)
285 foreground_color = value;
286 OnForeColorChanged (EventArgs.Empty);
291 ImageList image_list;
293 [DefaultValue (null)]
294 public ImageList ImageList {
295 get { return image_list; }
296 set { image_list = value; }
300 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
301 [EditorBrowsable (EditorBrowsableState.Advanced)]
302 public Size ImageSize {
304 if (ImageList == null)
307 return ImageList.ImageSize;
314 [EditorBrowsable (EditorBrowsableState.Never)]
315 public new ImeMode ImeMode {
316 get { return ime_mode; }
318 if (value == ime_mode)
322 OnImeModeChanged (EventArgs.Empty);
327 [EditorBrowsable (EditorBrowsableState.Never)]
328 public override RightToLeft RightToLeft {
329 get { return base.RightToLeft; }
331 if (value == base.RightToLeft)
334 base.RightToLeft = value;
335 OnRightToLeftChanged (EventArgs.Empty);
339 bool show_tooltips = false;
341 [DefaultValue (false)]
343 public bool ShowToolTips {
344 get { return show_tooltips; }
345 set { show_tooltips = value; }
348 [DefaultValue (false)]
349 public new bool TabStop {
350 get { return base.TabStop; }
351 set { base.TabStop = value; }
356 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
357 [EditorBrowsable (EditorBrowsableState.Never)]
358 public override string Text {
366 OnTextChanged (EventArgs.Empty);
370 ToolBarTextAlign text_alignment = ToolBarTextAlign.Underneath;
372 [DefaultValue (ToolBarTextAlign.Underneath)]
374 public ToolBarTextAlign TextAlign {
375 get { return text_alignment; }
377 if (value == text_alignment)
380 text_alignment = value;
385 bool wrappable = true;
387 [DefaultValue (true)]
389 public bool Wrappable {
390 get { return wrappable; }
392 if (value == wrappable)
399 #endregion Public Properties
401 #region Public Methods
402 public override string ToString ()
404 int count = this.Buttons.Count;
407 return string.Format ("System.Windows.Forms.ToolBar, Button.Count: 0");
409 return string.Format ("System.Windows.Forms.ToolBar, Button.Count: {0}, Buttons[0]: {1}",
410 count, this.Buttons [0].ToString ());
412 #endregion Public Methods
414 #region Protected Methods
415 protected override void CreateHandle ()
417 base.CreateHandle ();
420 protected override void Dispose (bool disposing)
425 base.Dispose (disposing);
428 protected virtual void OnButtonClick (ToolBarButtonClickEventArgs e)
430 if (e.Button.Style == ToolBarButtonStyle.ToggleButton) {
431 if (! e.Button.Pushed)
432 e.Button.Pushed = true;
434 e.Button.Pushed = false;
436 e.Button.pressed = false;
438 Invalidate (e.Button.Rectangle);
441 if (ButtonClick != null)
442 ButtonClick (this, e);
445 protected virtual void OnButtonDropDown (ToolBarButtonClickEventArgs e)
447 if (ButtonDropDown != null)
448 ButtonDropDown (this, e);
450 if (e.Button.DropDownMenu == null)
453 Point loc = new Point (e.Button.Rectangle.X + 1, e.Button.Rectangle.Bottom + 1);
454 ((ContextMenu) e.Button.DropDownMenu).Show (this, loc);
456 e.Button.dd_pressed = false;
457 Invalidate (e.Button.Rectangle);
460 protected override void OnFontChanged (EventArgs e)
462 base.OnFontChanged (e);
466 protected override void OnHandleCreated (EventArgs e)
468 base.OnHandleCreated (e);
471 protected override void OnResize (EventArgs e)
475 if (Width <= 0 || Height <= 0 || !Visible)
481 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
483 base.SetBoundsCore (x, y, width, height, specified);
486 protected override void WndProc (ref Message m)
488 base.WndProc (ref m);
491 #endregion Protected Methods
493 #region Private Methods
494 private void ToolBar_MouseDown (object sender, MouseEventArgs me)
499 Point loc = new Point (me.X, me.Y);
501 // draw the pushed button
502 foreach (ToolBarButton button in buttons) {
503 if (button.Enabled && button.Rectangle.Contains (loc)) {
504 // Mark the DropDown rect as pressed.
505 // We don't redraw the dropdown rect.
506 if (button.Style == ToolBarButtonStyle.DropDownButton) {
507 Rectangle rect = button.Rectangle;
508 rect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
509 rect.X = button.Rectangle.Right - rect.Width;
510 if (rect.Contains (loc)) {
511 if (button.DropDownMenu != null) {
512 button.dd_pressed = true;
518 button.pressed = true;
519 button.inside = true;
520 Invalidate (button.Rectangle);
526 private void ToolBar_MouseUp (object sender, MouseEventArgs me)
531 Point loc = new Point (me.X, me.Y);
533 // draw the normal button
534 foreach (ToolBarButton button in buttons) {
535 if (button.Enabled && button.Rectangle.Contains (loc)) {
536 if (button.Style == ToolBarButtonStyle.DropDownButton) {
537 Rectangle ddRect = button.Rectangle;
538 ddRect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
539 ddRect.X = button.Rectangle.Right - ddRect.Width;
540 if (ddRect.Contains (loc)) {
541 if (button.dd_pressed)
542 OnButtonDropDown (new ToolBarButtonClickEventArgs (button));
546 // Fire a ButtonClick
548 OnButtonClick (new ToolBarButtonClickEventArgs (button));
549 } else if (button.pressed) {
550 button.pressed = false;
551 Invalidate (button.Rectangle);
556 private void ToolBar_MouseLeave (object sender, EventArgs e)
558 if (!Enabled || appearance != ToolBarAppearance.Flat || current_button == null)
561 if (current_button.Hilight) {
562 current_button.Hilight = false;
563 Invalidate (current_button.Rectangle);
566 current_button = null;
569 private void ToolBar_MouseMove (object sender, MouseEventArgs me)
574 Point loc = new Point (me.X, me.Y);
577 // If the button was pressed and we leave, release the
578 // button press and vice versa
579 foreach (ToolBarButton button in buttons) {
580 if (button.pressed &&
581 (button.inside != button.Rectangle.Contains (loc))) {
582 button.inside = button.Rectangle.Contains (loc);
583 button.Hilight = false;
584 Invalidate (button.Rectangle);
590 // following is only for flat style toolbar
591 else if (appearance == ToolBarAppearance.Flat) {
592 if (current_button != null && current_button.Rectangle.Contains (loc)) {
593 if (current_button.Hilight || current_button.Pushed)
595 current_button.Hilight = true;
596 Invalidate (current_button.Rectangle);
600 foreach (ToolBarButton button in buttons) {
601 if (button.Rectangle.Contains (loc) && button.Enabled) {
602 current_button = button;
603 if (current_button.Hilight || current_button.Pushed)
605 current_button.Hilight = true;
606 Invalidate (current_button.Rectangle);
609 else if (button.Hilight) {
610 button.Hilight = false;
611 Invalidate (button.Rectangle);
619 private void ToolBar_Paint (object sender, PaintEventArgs pevent)
621 ThemeEngine.Current.DrawToolBar (pevent.Graphics, pevent.ClipRectangle, this);
624 internal void Redraw (bool recalculate)
632 private Size CalcButtonSize ()
634 String longestText = buttons [0].Text;
635 for (int i = 1; i < buttons.Count; i++) {
636 if (buttons[i].Text.Length > longestText.Length)
637 longestText = buttons[i].Text;
640 SizeF sz = this.DeviceContext.MeasureString (longestText, this.Font);
641 Size size = new Size ((int) Math.Ceiling (sz.Width), (int) Math.Ceiling (sz.Height));
643 if (ImageList != null) {
644 // adjustment for the image grip
645 int imgWidth = this.ImageSize.Width + 2 * ThemeEngine.Current.ToolBarImageGripWidth;
646 int imgHeight = this.ImageSize.Height + 2 * ThemeEngine.Current.ToolBarImageGripWidth;
648 if (text_alignment == ToolBarTextAlign.Right) {
649 size.Width = imgWidth + size.Width;
650 size.Height = (size.Height > imgHeight) ? size.Height : imgHeight;
653 size.Height = imgHeight + size.Height;
654 size.Width = (size.Width > imgWidth) ? size.Width : imgWidth;
662 Theme theme = ThemeEngine.Current;
663 int ht = ButtonSize.Height + theme.ToolBarGripWidth;
664 int x = theme.ToolBarGripWidth;
665 int y = theme.ToolBarGripWidth;
668 int separator_index = -1;
670 for (int i = 0; i < buttons.Count; i++) {
671 ToolBarButton button = buttons [i];
677 button.Layout (ButtonSize);
681 bool is_separator = button.Style == ToolBarButtonStyle.Separator;
683 if (x + button.Rectangle.Width < Width || is_separator) {
684 button.Location = new Point (x, y);
685 x += button.Rectangle.Width;
688 } else if (separator_index > 0) {
690 separator_index = -1;
691 x = theme.ToolBarGripWidth;
694 x = theme.ToolBarGripWidth;
696 button.Location = new Point (x, y);
697 x += button.Rectangle.Width;
706 Height = DefaultSize.Height;
707 foreach (ToolBarButton button in buttons) {
709 button.Layout (ButtonSize);
712 button.Location = new Point (x, y);
713 x += button.Rectangle.Width;
717 #endregion Private Methods
720 public class ToolBarButtonCollection : IList, ICollection, IEnumerable
722 #region instance variables
723 private ArrayList list;
724 private ToolBar owner;
728 public ToolBarButtonCollection (ToolBar owner)
731 list = new ArrayList ();
737 public virtual int Count {
738 get { return list.Count; }
741 public virtual bool IsReadOnly {
742 get { return list.IsReadOnly; }
745 public virtual ToolBarButton this [int index] {
746 get { return (ToolBarButton) list [index]; }
748 value.SetParent (owner);
749 list [index] = value;
754 bool ICollection.IsSynchronized {
755 get { return list.IsSynchronized; }
758 object ICollection.SyncRoot {
759 get { return list.SyncRoot; }
762 bool IList.IsFixedSize {
763 get { return list.IsFixedSize; }
766 object IList.this [int index] {
767 get { return this [index]; }
769 if (! (value is ToolBarButton))
770 throw new ArgumentException("Not of type ToolBarButton", "value");
771 this [index] = (ToolBarButton) value;
777 public int Add (string text)
779 ToolBarButton button = new ToolBarButton (text);
780 return this.Add (button);
783 public int Add (ToolBarButton button)
786 button.SetParent (owner);
787 result = list.Add (button);
792 public void AddRange (ToolBarButton [] buttons)
794 foreach (ToolBarButton button in buttons)
798 public virtual void Clear ()
801 owner.Redraw (false);
804 public bool Contains (ToolBarButton button)
806 return list.Contains (button);
809 public virtual IEnumerator GetEnumerator ()
811 return list.GetEnumerator ();
814 void ICollection.CopyTo (Array dest, int index)
816 list.CopyTo (dest, index);
819 int IList.Add (object button)
821 if (! (button is ToolBarButton)) {
822 throw new ArgumentException("Not of type ToolBarButton", "button");
825 return this.Add ((ToolBarButton) button);
828 bool IList.Contains (object button)
830 if (! (button is ToolBarButton)) {
831 throw new ArgumentException("Not of type ToolBarButton", "button");
834 return this.Contains ((ToolBarButton) button);
837 int IList.IndexOf (object button)
839 if (! (button is ToolBarButton)) {
840 throw new ArgumentException("Not of type ToolBarButton", "button");
843 return this.IndexOf ((ToolBarButton) button);
846 void IList.Insert (int index, object button)
848 if (! (button is ToolBarButton)) {
849 throw new ArgumentException("Not of type ToolBarButton", "button");
852 this.Insert (index, (ToolBarButton) button);
855 void IList.Remove (object button)
857 if (! (button is ToolBarButton)) {
858 throw new ArgumentException("Not of type ToolBarButton", "button");
861 this.Remove ((ToolBarButton) button);
864 public int IndexOf (ToolBarButton button)
866 return list.IndexOf (button);
869 public void Insert (int index, ToolBarButton button)
871 list.Insert (index, button);
875 public void Remove (ToolBarButton button)
877 list.Remove (button);
881 public virtual void RemoveAt (int index)
883 list.RemoveAt (index);