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>
25 // Everaldo Canuto <ecanuto@novell.com>
27 // Copyright (C) 2004-2006 Novell, Inc. (http://www.novell.com)
30 using System.Collections;
31 using System.ComponentModel;
32 using System.ComponentModel.Design;
34 using System.Drawing.Text;
35 using System.Drawing.Imaging;
36 using System.Runtime.InteropServices;
38 namespace System.Windows.Forms
42 [ClassInterface (ClassInterfaceType.AutoDispatch)]
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 private bool size_specified = false;
51 private ToolBarItem current_item;
52 internal ToolBarItem[] items;
53 internal Size default_size;
54 #endregion Instance Variables
57 static object ButtonClickEvent = new object ();
58 static object ButtonDropDownEvent = new object ();
62 [EditorBrowsable (EditorBrowsableState.Always)]
63 public new event EventHandler AutoSizeChanged {
64 add { base.AutoSizeChanged += value; }
65 remove { base.AutoSizeChanged -= value; }
70 [EditorBrowsable (EditorBrowsableState.Never)]
71 public new event EventHandler BackColorChanged {
72 add { base.BackColorChanged += value; }
73 remove { base.BackColorChanged -= value; }
77 [EditorBrowsable (EditorBrowsableState.Never)]
78 public new event EventHandler BackgroundImageChanged {
79 add { base.BackgroundImageChanged += value; }
80 remove { base.BackgroundImageChanged -= value; }
85 [EditorBrowsable (EditorBrowsableState.Never)]
86 public new event EventHandler BackgroundImageLayoutChanged {
87 add { base.BackgroundImageLayoutChanged += value; }
88 remove { base.BackgroundImageLayoutChanged -= value; }
92 public event ToolBarButtonClickEventHandler ButtonClick {
93 add { Events.AddHandler (ButtonClickEvent, value); }
94 remove {Events.RemoveHandler (ButtonClickEvent, value); }
97 public event ToolBarButtonClickEventHandler ButtonDropDown {
98 add { Events.AddHandler (ButtonDropDownEvent, value); }
99 remove {Events.RemoveHandler (ButtonDropDownEvent, value); }
103 [EditorBrowsable (EditorBrowsableState.Never)]
104 public new event EventHandler ForeColorChanged {
105 add { base.ForeColorChanged += value; }
106 remove { base.ForeColorChanged -= value; }
110 [EditorBrowsable (EditorBrowsableState.Never)]
111 public new event EventHandler ImeModeChanged {
112 add { base.ImeModeChanged += value; }
113 remove { base.ImeModeChanged -= value; }
117 [EditorBrowsable (EditorBrowsableState.Never)]
118 public new event PaintEventHandler Paint {
119 add { base.Paint += value; }
120 remove { base.Paint -= value; }
124 [EditorBrowsable (EditorBrowsableState.Never)]
125 public new event EventHandler RightToLeftChanged {
126 add { base.RightToLeftChanged += value; }
127 remove { base.RightToLeftChanged -= value; }
131 [EditorBrowsable (EditorBrowsableState.Never)]
132 public new event EventHandler TextChanged {
133 add { base.TextChanged += value; }
134 remove { base.TextChanged -= value; }
141 background_color = ThemeEngine.Current.DefaultControlBackColor;
142 foreground_color = ThemeEngine.Current.DefaultControlForeColor;
143 buttons = new ToolBarButtonCollection (this);
144 Dock = DockStyle.Top;
146 GotFocus += new EventHandler (FocusChanged);
147 LostFocus += new EventHandler (FocusChanged);
148 MouseDown += new MouseEventHandler (ToolBar_MouseDown);
149 MouseHover += new EventHandler (ToolBar_MouseHover);
150 MouseLeave += new EventHandler (ToolBar_MouseLeave);
151 MouseMove += new MouseEventHandler (ToolBar_MouseMove);
152 MouseUp += new MouseEventHandler (ToolBar_MouseUp);
153 BackgroundImageChanged += new EventHandler (ToolBar_BackgroundImageChanged);
157 SetStyle (ControlStyles.UserPaint, false);
158 SetStyle (ControlStyles.FixedHeight, true);
159 SetStyle (ControlStyles.FixedWidth, false);
161 #endregion Constructor
163 #region protected Properties
164 protected override CreateParams CreateParams {
166 CreateParams create_params = base.CreateParams;
168 if (appearance == ToolBarAppearance.Flat) {
169 create_params.Style |= (int) ToolBarStyles.TBSTYLE_FLAT;
172 return create_params;
176 protected override ImeMode DefaultImeMode {
177 get { return ImeMode.Disable; }
180 protected override Size DefaultSize {
181 get { return ThemeEngine.Current.ToolBarDefaultSize; }
185 [EditorBrowsable (EditorBrowsableState.Never)]
186 protected override bool DoubleBuffered {
187 get { return base.DoubleBuffered; }
188 set { base.DoubleBuffered = value; }
193 ToolBarAppearance appearance = ToolBarAppearance.Normal;
195 #region Public Properties
196 [DefaultValue (ToolBarAppearance.Normal)]
198 public ToolBarAppearance Appearance {
199 get { return appearance; }
201 if (value == appearance)
209 bool autosize = true;
213 [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
214 [EditorBrowsable (EditorBrowsableState.Always)]
216 [DefaultValue (true)]
223 get { return autosize; }
225 if (value == autosize)
236 [EditorBrowsable (EditorBrowsableState.Never)]
237 public override Color BackColor {
238 get { return background_color; }
240 if (value == background_color)
243 background_color = value;
244 OnBackColorChanged (EventArgs.Empty);
250 [EditorBrowsable (EditorBrowsableState.Never)]
251 public override Image BackgroundImage {
252 get { return base.BackgroundImage; }
253 set { base.BackgroundImage = value; }
258 [EditorBrowsable (EditorBrowsableState.Never)]
259 public override ImageLayout BackgroundImageLayout {
260 get { return base.BackgroundImageLayout; }
261 set { base.BackgroundImageLayout = value; }
265 [DefaultValue (BorderStyle.None)]
266 [DispIdAttribute (-504)]
267 public BorderStyle BorderStyle {
268 get { return InternalBorderStyle; }
269 set { InternalBorderStyle = value; }
272 ToolBarButtonCollection buttons;
274 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
276 [MergableProperty (false)]
277 public ToolBarButtonCollection Buttons {
278 get { return buttons; }
284 [RefreshProperties (RefreshProperties.All)]
285 public Size ButtonSize {
287 if (!button_size.IsEmpty)
290 if (buttons.Count == 0)
291 return new Size (39, 36);
293 Size result = CalcButtonSize ();
295 return new Size (24, 22);
300 size_specified = value != Size.Empty;
301 if (button_size == value)
311 [DefaultValue (true)]
312 public bool Divider {
313 get { return divider; }
315 if (value == divider)
323 [DefaultValue (DockStyle.Top)]
325 public override DockStyle Dock {
326 get { return base.Dock; }
328 if (base.Dock == value) {
329 // Call base anyways so layout_type gets set correctly
330 if (value != DockStyle.None)
336 SetStyle (ControlStyles.FixedWidth, AutoSize);
337 SetStyle (ControlStyles.FixedHeight, false);
339 SetStyle (ControlStyles.FixedHeight, AutoSize);
340 SetStyle (ControlStyles.FixedWidth, false);
349 bool drop_down_arrows = true;
351 [DefaultValue (false)]
353 public bool DropDownArrows {
354 get { return drop_down_arrows; }
356 if (value == drop_down_arrows)
359 drop_down_arrows = value;
365 [EditorBrowsable (EditorBrowsableState.Never)]
366 public override Color ForeColor {
367 get { return foreground_color; }
369 if (value == foreground_color)
372 foreground_color = value;
373 OnForeColorChanged (EventArgs.Empty);
378 ImageList image_list;
380 [DefaultValue (null)]
381 public ImageList ImageList {
382 get { return image_list; }
384 if (image_list == value)
392 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
393 [EditorBrowsable (EditorBrowsableState.Advanced)]
394 public Size ImageSize {
396 if (ImageList == null)
399 return ImageList.ImageSize;
403 // XXX this should probably go away and it should call
404 // into Control.ImeMode instead.
405 ImeMode ime_mode = ImeMode.Disable;
408 [EditorBrowsable (EditorBrowsableState.Never)]
409 public new ImeMode ImeMode {
410 get { return ime_mode; }
412 if (value == ime_mode)
416 OnImeModeChanged (EventArgs.Empty);
421 [EditorBrowsable (EditorBrowsableState.Never)]
422 public override RightToLeft RightToLeft {
423 get { return base.RightToLeft; }
425 if (value == base.RightToLeft)
428 base.RightToLeft = value;
429 OnRightToLeftChanged (EventArgs.Empty);
433 // Default value is "false" but after make a test in .NET we get "true" result as default.
434 bool show_tooltips = true;
436 [DefaultValue (false)]
438 public bool ShowToolTips {
439 get { return show_tooltips; }
440 set { show_tooltips = value; }
443 [DefaultValue (false)]
444 public new bool TabStop {
445 get { return base.TabStop; }
446 set { base.TabStop = value; }
451 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
452 [EditorBrowsable (EditorBrowsableState.Never)]
453 public override string Text {
454 get { return base.Text; }
456 if (value == base.Text)
464 ToolBarTextAlign text_alignment = ToolBarTextAlign.Underneath;
466 [DefaultValue (ToolBarTextAlign.Underneath)]
468 public ToolBarTextAlign TextAlign {
469 get { return text_alignment; }
471 if (value == text_alignment)
474 text_alignment = value;
479 bool wrappable = true;
481 [DefaultValue (true)]
483 public bool Wrappable {
484 get { return wrappable; }
486 if (value == wrappable)
493 #endregion Public Properties
495 #region Public Methods
496 public override string ToString ()
498 int count = this.Buttons.Count;
501 return string.Format ("System.Windows.Forms.ToolBar, Buttons.Count: 0");
503 return string.Format ("System.Windows.Forms.ToolBar, Buttons.Count: {0}, Buttons[0]: {1}",
504 count, this.Buttons [0].ToString ());
506 #endregion Public Methods
508 #region Protected Methods
509 protected override void CreateHandle ()
511 base.CreateHandle ();
512 default_size = CalcButtonSize ();
514 // In win32 the recalculate size only happens for not flat style
515 if (appearance != ToolBarAppearance.Flat)
519 protected override void Dispose (bool disposing)
524 base.Dispose (disposing);
528 private ToolBarButton button_for_focus = null;
530 internal void UIAPerformClick (ToolBarButton button)
532 ToolBarItem previous_item = current_item;
535 foreach (ToolBarItem item in items)
536 if (item.Button == button) {
542 if (current_item == null)
543 throw new ArgumentException ("button", "The button specified is not part of this toolbar");
544 PerformButtonClick (new ToolBarButtonClickEventArgs (button));
546 current_item = previous_item;
551 void PerformButtonClick (ToolBarButtonClickEventArgs e)
553 // Only change pushed for ToogleButton
554 if (e.Button.Style == ToolBarButtonStyle.ToggleButton) {
555 if (! e.Button.Pushed)
556 e.Button.Pushed = true;
558 e.Button.Pushed = false;
561 current_item.Pressed = false;
562 current_item.Invalidate ();
565 button_for_focus = current_item.Button;
566 button_for_focus.UIAHasFocus = true;
571 protected virtual void OnButtonClick (ToolBarButtonClickEventArgs e)
573 ToolBarButtonClickEventHandler eh = (ToolBarButtonClickEventHandler)(Events [ButtonClickEvent]);
578 protected virtual void OnButtonDropDown (ToolBarButtonClickEventArgs e)
580 ToolBarButtonClickEventHandler eh = (ToolBarButtonClickEventHandler)(Events [ButtonDropDownEvent]);
584 if (e.Button.DropDownMenu == null)
587 ShowDropDownMenu (current_item);
590 internal void ShowDropDownMenu (ToolBarItem item)
592 Point loc = new Point (item.Rectangle.X + 1, item.Rectangle.Bottom + 1);
593 ((ContextMenu) item.Button.DropDownMenu).Show (this, loc);
595 item.DDPressed = false;
596 item.Hilight = false;
600 protected override void OnFontChanged (EventArgs e)
602 base.OnFontChanged (e);
606 protected override void OnHandleCreated (EventArgs e)
608 base.OnHandleCreated (e);
611 protected override void OnResize (EventArgs e)
618 protected override void ScaleControl (SizeF factor, BoundsSpecified specified)
620 specified &= ~BoundsSpecified.Height;
622 base.ScaleControl (factor, specified);
625 [EditorBrowsable (EditorBrowsableState.Never)]
626 protected override void ScaleCore (float dx, float dy)
630 base.ScaleCore (dx, dy);
634 private int requested_size = -1;
636 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
639 if (!AutoSize && (requested_size != width) && ((specified & BoundsSpecified.Width) != BoundsSpecified.None))
640 requested_size = width;
642 if (!AutoSize && (requested_size != height) && ((specified & BoundsSpecified.Height) != BoundsSpecified.None))
643 requested_size = height;
646 base.SetBoundsCore (x, y, width, height, specified);
649 protected override void WndProc (ref Message m)
651 base.WndProc (ref m);
654 internal override bool InternalPreProcessMessage (ref Message msg)
656 if (msg.Msg == (int)Msg.WM_KEYDOWN) {
657 Keys key_data = (Keys)msg.WParam.ToInt32();
658 if (HandleKeyDown (ref msg, key_data))
661 return base.InternalPreProcessMessage (ref msg);
664 #endregion Protected Methods
666 #region Private Methods
667 internal int CurrentItem {
669 return Array.IndexOf (items, current_item);
672 if (current_item != null)
673 current_item.Hilight = false;
675 current_item = value == -1 ? null : items [value];
677 if (current_item != null)
678 current_item.Hilight = true;
683 private void FocusChanged (object sender, EventArgs args)
686 if (!Focused && button_for_focus != null)
687 button_for_focus.UIAHasFocus = false;
688 button_for_focus = null;
691 if (Appearance != ToolBarAppearance.Flat || Buttons.Count == 0)
694 ToolBarItem prelit = null;
695 foreach (ToolBarItem item in items) {
702 if (Focused && prelit == null) {
703 foreach (ToolBarItem item in items) {
704 if (item.Button.Enabled) {
709 } else if (prelit != null) {
710 prelit.Hilight = false;
714 private bool HandleKeyDown (ref Message msg, Keys key_data)
716 if (Appearance != ToolBarAppearance.Flat || Buttons.Count == 0)
719 // Handle the key as needed if the current item is a dropdownbutton.
720 if (HandleKeyOnDropDown (ref msg, key_data))
726 HighlightButton (-1);
734 if (current_item != null) {
735 OnButtonClick (new ToolBarButtonClickEventArgs (current_item.Button));
744 bool HandleKeyOnDropDown (ref Message msg, Keys key_data)
746 if (current_item == null || current_item.Button.Style != ToolBarButtonStyle.DropDownButton ||
747 current_item.Button.DropDownMenu == null)
750 Menu dropdown_menu = current_item.Button.DropDownMenu;
752 if (dropdown_menu.Tracker.active) {
753 dropdown_menu.ProcessCmdKey (ref msg, key_data);
754 return true; // always true if the menu is active
757 if (key_data == Keys.Up || key_data == Keys.Down) {
758 current_item.DDPressed = true;
759 current_item.Invalidate ();
760 OnButtonDropDown (new ToolBarButtonClickEventArgs (current_item.Button));
767 void HighlightButton (int offset)
769 ArrayList enabled = new ArrayList ();
772 ToolBarItem curr_item = null;
773 foreach (ToolBarItem item in items) {
779 if (item.Button.Enabled) {
785 int next = (start + offset) % count;
792 if (curr_item != null)
793 curr_item.Hilight = false;
795 current_item = enabled [next] as ToolBarItem;
796 current_item.Hilight = true;
799 private void ToolBar_BackgroundImageChanged (object sender, EventArgs args)
801 Redraw (false, true);
804 private void ToolBar_MouseDown (object sender, MouseEventArgs me)
806 if ((!Enabled) || ((me.Button & MouseButtons.Left) == 0))
809 Point loc = new Point (me.X, me.Y);
811 if (ItemAtPoint (loc) == null)
814 // Hide tooltip when left mouse button
815 if ((tip_window != null) && (tip_window.Visible) && ((me.Button & MouseButtons.Left) == MouseButtons.Left)) {
816 TipDownTimer.Stop ();
817 tip_window.Hide (this);
820 // draw the pushed button
821 foreach (ToolBarItem item in items) {
822 if (item.Button.Enabled && item.Rectangle.Contains (loc)) {
823 // Mark the DropDown rect as pressed.
824 // We don't redraw the dropdown rect.
825 if (item.Button.Style == ToolBarButtonStyle.DropDownButton) {
826 Rectangle rect = item.Rectangle;
827 if (DropDownArrows) {
828 rect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
829 rect.X = item.Rectangle.Right - rect.Width;
832 if (rect.Contains (loc)) {
833 if (item.Button.DropDownMenu != null) {
834 item.DDPressed = true;
848 private void ToolBar_MouseUp (object sender, MouseEventArgs me)
850 if ((!Enabled) || ((me.Button & MouseButtons.Left) == 0))
853 Point loc = new Point (me.X, me.Y);
855 // draw the normal button
856 // Make a copy in case the list is modified during enumeration
857 ArrayList items = new ArrayList (this.items);
858 foreach (ToolBarItem item in items) {
859 if (item.Button.Enabled && item.Rectangle.Contains (loc)) {
860 if (item.Button.Style == ToolBarButtonStyle.DropDownButton) {
861 Rectangle ddRect = item.Rectangle;
862 ddRect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
863 ddRect.X = item.Rectangle.Right - ddRect.Width;
864 if (ddRect.Contains (loc)) {
867 OnButtonDropDown (new ToolBarButtonClickEventArgs (item.Button));
871 // Fire a ButtonClick
873 if ((item.Pressed) && ((me.Button & MouseButtons.Left) == MouseButtons.Left))
874 PerformButtonClick (new ToolBarButtonClickEventArgs (item.Button));
875 } else if (item.Pressed) {
876 item.Pressed = false;
882 private ToolBarItem ItemAtPoint (Point pt)
884 foreach (ToolBarItem item in items)
885 if (item.Rectangle.Contains (pt))
891 ToolTip tip_window = null;
892 Timer tipdown_timer = null;
894 private void PopDownTip (object o, EventArgs args)
896 tip_window.Hide (this);
899 private Timer TipDownTimer {
901 if (tipdown_timer == null) {
902 tipdown_timer = new Timer ();
903 tipdown_timer.Enabled = false;
904 tipdown_timer.Interval = 5000;
905 tipdown_timer.Tick += new EventHandler (PopDownTip);
907 return tipdown_timer;
911 private void ToolBar_MouseHover (object sender, EventArgs e)
916 if (tip_window == null)
917 tip_window = new ToolTip ();
919 ToolBarItem item = ItemAtPoint (PointToClient (Control.MousePosition));
922 if (item == null || item.Button.ToolTipText.Length == 0)
925 tip_window.Present (this, item.Button.ToolTipText);
926 TipDownTimer.Start ();
929 private void ToolBar_MouseLeave (object sender, EventArgs e)
931 if (tipdown_timer != null)
932 tipdown_timer.Dispose ();
933 tipdown_timer = null;
934 if (tip_window != null)
935 tip_window.Dispose ();
938 if (!Enabled || current_item == null)
941 current_item.Hilight = false;
945 private void ToolBar_MouseMove (object sender, MouseEventArgs me)
950 if (tip_window != null && tip_window.Visible) {
951 TipDownTimer.Stop ();
952 TipDownTimer.Start ();
955 Point loc = new Point (me.X, me.Y);
958 // If the button was pressed and we leave, release the
959 // button press and vice versa
960 foreach (ToolBarItem item in items) {
962 (item.Inside != item.Rectangle.Contains (loc))) {
963 item.Inside = item.Rectangle.Contains (loc);
964 item.Hilight = false;
971 if (current_item != null && current_item.Rectangle.Contains (loc)) {
972 if (ThemeEngine.Current.ToolBarHasHotElementStyles (this)) {
973 if (current_item.Hilight || (!ThemeEngine.Current.ToolBarHasHotCheckedElementStyles && current_item.Button.Pushed) || !current_item.Button.Enabled)
975 current_item.Hilight = true;
978 if (tip_window != null) {
979 if (tip_window.Visible) {
980 tip_window.Hide (this);
981 TipDownTimer.Stop ();
983 current_item = ItemAtPoint (loc);
984 if (current_item != null && current_item.Button.ToolTipText.Length > 0) {
985 tip_window.Present (this, current_item.Button.ToolTipText);
986 TipDownTimer.Start ();
990 if (ThemeEngine.Current.ToolBarHasHotElementStyles (this)) {
991 foreach (ToolBarItem item in items) {
992 if (item.Rectangle.Contains (loc) && item.Button.Enabled) {
994 if (current_item.Hilight || (!ThemeEngine.Current.ToolBarHasHotCheckedElementStyles && current_item.Button.Pushed))
996 current_item.Hilight = true;
998 else if (item.Hilight) {
999 item.Hilight = false;
1006 internal override void OnPaintInternal (PaintEventArgs pevent)
1008 if (GetStyle (ControlStyles.UserPaint))
1011 ThemeEngine.Current.DrawToolBar (pevent.Graphics, pevent.ClipRectangle, this);
1013 // Toolbars do not raise OnPaint unless UserPaint is set
1014 pevent.Handled = true;
1017 internal void Redraw (bool recalculate)
1019 Redraw (recalculate, true);
1022 internal void Redraw (bool recalculate, bool force)
1024 bool invalidate = true;
1027 invalidate = LayoutToolBar ();
1029 if (force || invalidate)
1033 internal bool SizeSpecified {
1034 get { return size_specified; }
1037 internal bool Vertical {
1038 get { return (Dock == DockStyle.Left) || (Dock == DockStyle.Right); }
1041 internal const int text_padding = 3;
1043 private Size CalcButtonSize ()
1045 if (Buttons.Count == 0)
1048 string longest_text = Buttons [0].Text;
1049 for (int i = 1; i < Buttons.Count; i++) {
1050 if (Buttons[i].Text.Length > longest_text.Length)
1051 longest_text = Buttons[i].Text;
1054 Size size = Size.Empty;
1055 if (longest_text != null && longest_text.Length > 0) {
1056 SizeF sz = TextRenderer.MeasureString (longest_text, Font);
1057 if (sz != SizeF.Empty)
1058 size = new Size ((int) Math.Ceiling (sz.Width) + 2 * text_padding, (int) Math.Ceiling (sz.Height));
1061 Size img_size = ImageList == null ? new Size (16, 16) : ImageSize;
1063 Theme theme = ThemeEngine.Current;
1064 int imgWidth = img_size.Width + 2 * theme.ToolBarImageGripWidth;
1065 int imgHeight = img_size.Height + 2 * theme.ToolBarImageGripWidth;
1067 if (text_alignment == ToolBarTextAlign.Right) {
1068 size.Width = imgWidth + size.Width;
1069 size.Height = (size.Height > imgHeight) ? size.Height : imgHeight;
1071 size.Height = imgHeight + size.Height;
1072 size.Width = (size.Width > imgWidth) ? size.Width : imgWidth;
1075 size.Width += theme.ToolBarImageGripWidth;
1076 size.Height += theme.ToolBarImageGripWidth;
1080 // Flat toolbars disregard specified sizes. Normal toolbars grow the
1081 // button size to be at least large enough to show the image.
1082 private Size AdjustedButtonSize {
1086 if (default_size.IsEmpty || Appearance == ToolBarAppearance.Normal)
1089 size = default_size;
1091 if (size_specified) {
1092 if (Appearance == ToolBarAppearance.Flat)
1093 size = CalcButtonSize ();
1095 int grip = ThemeEngine.Current.ToolBarImageGripWidth;
1096 if (size.Width < ImageSize.Width + 2 * grip )
1097 size.Width = ImageSize.Width + 2 * grip;
1098 if (size.Height < ImageSize.Height + 2 * grip)
1099 size.Height = ImageSize.Height + 2 * grip;
1106 private bool LayoutToolBar ()
1108 bool changed = false;
1109 Theme theme = ThemeEngine.Current;
1110 int x = theme.ToolBarGripWidth;
1111 int y = theme.ToolBarGripWidth;
1113 Size adjusted_size = AdjustedButtonSize;
1115 int calculated_size = (Vertical ? adjusted_size.Width : adjusted_size.Height) + theme.ToolBarGripWidth;
1117 int separator_index = -1;
1119 items = new ToolBarItem [buttons.Count];
1121 for (int i = 0; i < buttons.Count; i++) {
1122 ToolBarButton button = buttons [i];
1124 ToolBarItem item = new ToolBarItem (button);
1127 if (!button.Visible)
1130 if (size_specified && (button.Style != ToolBarButtonStyle.Separator))
1131 changed = item.Layout (adjusted_size);
1133 changed = item.Layout (Vertical, calculated_size);
1135 bool is_separator = button.Style == ToolBarButtonStyle.Separator;
1138 if (y + item.Rectangle.Height < Height || is_separator || !Wrappable) {
1139 if (item.Location.X != x || item.Location.Y != y)
1141 item.Location = new Point (x, y);
1142 y += item.Rectangle.Height;
1144 separator_index = i;
1145 } else if (separator_index > 0) {
1146 i = separator_index;
1147 separator_index = -1;
1148 y = theme.ToolBarGripWidth;
1149 x += calculated_size;
1151 y = theme.ToolBarGripWidth;
1152 x += calculated_size;
1153 if (item.Location.X != x || item.Location.Y != y)
1155 item.Location = new Point (x, y);
1156 y += item.Rectangle.Height;
1159 if (x + item.Rectangle.Width < Width || is_separator || !Wrappable) {
1160 if (item.Location.X != x || item.Location.Y != y)
1162 item.Location = new Point (x, y);
1163 x += item.Rectangle.Width;
1165 separator_index = i;
1166 } else if (separator_index > 0) {
1167 i = separator_index;
1168 separator_index = -1;
1169 x = theme.ToolBarGripWidth;
1170 y += calculated_size;
1172 x = theme.ToolBarGripWidth;
1173 y += calculated_size;
1174 if (item.Location.X != x || item.Location.Y != y)
1176 item.Location = new Point (x, y);
1177 x += item.Rectangle.Width;
1186 calculated_size += Vertical ? x : y;
1188 if (IsHandleCreated) {
1190 Width = calculated_size;
1192 Height = calculated_size;
1197 #endregion Private Methods
1200 public class ToolBarButtonCollection : IList, ICollection, IEnumerable
1202 #region instance variables
1203 private ArrayList list; // ToolBarButton list
1204 private ToolBar owner; // ToolBar associated to Collection
1205 private bool redraw; // Flag if needs to redraw after add/remove operations
1208 #region UIA Framework Events
1210 static object UIACollectionChangedEvent = new object ();
1212 internal event CollectionChangeEventHandler UIACollectionChanged {
1213 add { owner.Events.AddHandler (UIACollectionChangedEvent, value); }
1214 remove { owner.Events.RemoveHandler (UIACollectionChangedEvent, value); }
1217 internal void OnUIACollectionChanged (CollectionChangeEventArgs e)
1219 CollectionChangeEventHandler eh
1220 = (CollectionChangeEventHandler) owner.Events [UIACollectionChangedEvent];
1227 #region constructors
1228 public ToolBarButtonCollection (ToolBar owner)
1230 this.list = new ArrayList ();
1239 get { return list.Count; }
1242 public bool IsReadOnly {
1243 get { return list.IsReadOnly; }
1246 public virtual ToolBarButton this [int index] {
1247 get { return (ToolBarButton) list [index]; }
1250 // UIA Framework Event: Button Removed
1251 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
1254 value.SetParent (owner);
1255 list [index] = value;
1256 owner.Redraw (true);
1260 // UIA Framework Event: Button Added
1261 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
1267 public virtual ToolBarButton this[string key] {
1269 if (string.IsNullOrEmpty (key))
1272 foreach (ToolBarButton b in list)
1273 if (string.Compare (b.Name, key, true) == 0)
1281 bool ICollection.IsSynchronized {
1282 get { return list.IsSynchronized; }
1285 object ICollection.SyncRoot {
1286 get { return list.SyncRoot; }
1289 bool IList.IsFixedSize {
1290 get { return list.IsFixedSize; }
1293 object IList.this [int index] {
1294 get { return this [index]; }
1296 if (! (value is ToolBarButton))
1297 throw new ArgumentException("Not of type ToolBarButton", "value");
1298 this [index] = (ToolBarButton) value;
1304 public int Add (string text)
1306 ToolBarButton button = new ToolBarButton (text);
1307 return this.Add (button);
1310 public int Add (ToolBarButton button)
1313 button.SetParent (owner);
1314 result = list.Add (button);
1316 owner.Redraw (true);
1319 // UIA Framework Event: Button Added
1320 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, result));
1326 public void AddRange (ToolBarButton [] buttons)
1330 foreach (ToolBarButton button in buttons)
1335 owner.Redraw (true);
1339 public void Clear ()
1342 owner.Redraw (false);
1345 // UIA Framework Event: Button Cleared
1346 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, -1));
1350 public bool Contains (ToolBarButton button)
1352 return list.Contains (button);
1356 public virtual bool ContainsKey (string key)
1358 return !(this[key] == null);
1362 public IEnumerator GetEnumerator ()
1364 return list.GetEnumerator ();
1367 void ICollection.CopyTo (Array dest, int index)
1369 list.CopyTo (dest, index);
1372 int IList.Add (object button)
1374 if (! (button is ToolBarButton)) {
1375 throw new ArgumentException("Not of type ToolBarButton", "button");
1378 return this.Add ((ToolBarButton) button);
1381 bool IList.Contains (object button)
1383 if (! (button is ToolBarButton)) {
1384 throw new ArgumentException("Not of type ToolBarButton", "button");
1387 return this.Contains ((ToolBarButton) button);
1390 int IList.IndexOf (object button)
1392 if (! (button is ToolBarButton)) {
1393 throw new ArgumentException("Not of type ToolBarButton", "button");
1396 return this.IndexOf ((ToolBarButton) button);
1399 void IList.Insert (int index, object button)
1401 if (! (button is ToolBarButton)) {
1402 throw new ArgumentException("Not of type ToolBarButton", "button");
1405 this.Insert (index, (ToolBarButton) button);
1408 void IList.Remove (object button)
1410 if (! (button is ToolBarButton)) {
1411 throw new ArgumentException("Not of type ToolBarButton", "button");
1414 this.Remove ((ToolBarButton) button);
1417 public int IndexOf (ToolBarButton button)
1419 return list.IndexOf (button);
1423 public virtual int IndexOfKey (string key)
1425 return IndexOf (this[key]);
1429 public void Insert (int index, ToolBarButton button)
1431 list.Insert (index, button);
1432 owner.Redraw (true);
1435 // UIA Framework Event: Button Added
1436 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
1440 public void Remove (ToolBarButton button)
1442 list.Remove (button);
1443 owner.Redraw (true);
1446 public void RemoveAt (int index)
1448 list.RemoveAt (index);
1449 owner.Redraw (true);
1452 // UIA Framework Event: Button Removed
1453 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
1458 public virtual void RemoveByKey (string key)
1470 // Because same button can be added to toolbar multiple times, we need to maintain
1471 // a list of button information for each positions.
1472 internal class ToolBarItem : Component
1474 #region Instance variables
1476 private ToolBar toolbar; // Parent toolbar
1477 private ToolBarButton button; // Associated toolBar button
1478 private Rectangle bounds; // Toolbar button bounds
1479 private Rectangle image_rect; // Image button bounds
1480 private Rectangle text_rect; // Text button bounds
1482 private bool dd_pressed = false; // to check for a mouse down on dropdown rect
1483 private bool inside = false; // to handle the mouse move event with mouse pressed
1484 private bool hilight = false; // to hilight buttons in flat style
1485 private bool pressed = false; // this is to check for mouse down on a button
1489 #region Constructors
1491 public ToolBarItem (ToolBarButton button)
1493 this.toolbar = button.Parent;
1494 this.button = button;
1497 #endregion Constructors
1501 public ToolBarButton Button {
1502 get { return this.button; }
1505 public Rectangle Rectangle {
1507 if (!button.Visible || toolbar == null)
1508 return Rectangle.Empty;
1510 if (button.Style == ToolBarButtonStyle.DropDownButton && toolbar.DropDownArrows) {
1511 Rectangle result = bounds;
1512 result.Width += ThemeEngine.Current.ToolBarDropDownWidth;
1518 set { this.bounds = value; }
1521 public Point Location {
1522 get { return bounds.Location; }
1523 set { bounds.Location = value; }
1526 public Rectangle ImageRectangle {
1528 Rectangle result = image_rect;
1529 result.X += bounds.X;
1530 result.Y += bounds.Y;
1535 public Rectangle TextRectangle {
1537 Rectangle result = text_rect;
1538 result.X += bounds.X;
1539 result.Y += bounds.Y;
1544 private Size TextSize {
1546 StringFormat text_format = new StringFormat ();
1547 text_format.HotkeyPrefix = HotkeyPrefix.Hide;
1549 SizeF sz = TextRenderer.MeasureString (button.Text, toolbar.Font, SizeF.Empty, text_format);
1550 if (sz == SizeF.Empty)
1552 return new Size ((int) Math.Ceiling (sz.Width) + 2 * ToolBar.text_padding, (int) Math.Ceiling (sz.Height));
1556 public bool Pressed {
1557 get { return (pressed && inside); }
1558 set { pressed = value; }
1561 public bool DDPressed {
1562 get { return dd_pressed; }
1563 set { dd_pressed = value; }
1566 public bool Inside {
1567 get { return inside; }
1568 set { inside = value; }
1571 public bool Hilight {
1572 get { return hilight; }
1574 if (hilight == value)
1582 #endregion Properties
1586 public Size CalculateSize ()
1588 Theme theme = ThemeEngine.Current;
1590 int ht = toolbar.ButtonSize.Height + 2 * theme.ToolBarGripWidth;
1592 if (button.Style == ToolBarButtonStyle.Separator)
1593 return new Size (theme.ToolBarSeparatorWidth, ht);
1596 if (TextSize.IsEmpty && (button.Image == null))
1597 size = toolbar.default_size;
1601 Size image_size = (toolbar.ImageSize == Size.Empty) ? new Size (16, 16) : toolbar.ImageSize;
1603 int image_width = image_size.Width + 2 * theme.ToolBarImageGripWidth;
1604 int image_height = image_size.Height + 2 * theme.ToolBarImageGripWidth;
1606 if (toolbar.TextAlign == ToolBarTextAlign.Right) {
1607 size.Width = image_width + size.Width;
1608 size.Height = (size.Height > image_height) ? size.Height : image_height;
1610 size.Height = image_height + size.Height;
1611 size.Width = (size.Width > image_width) ? size.Width : image_width;
1614 size.Width += theme.ToolBarGripWidth;
1615 size.Height += theme.ToolBarGripWidth;
1620 public bool Layout (bool vertical, int calculated_size)
1622 if (toolbar == null || !button.Visible)
1625 Size psize = toolbar.ButtonSize;
1627 if ((!toolbar.SizeSpecified) || (button.Style == ToolBarButtonStyle.Separator)) {
1628 size = CalculateSize ();
1630 if (size.Width == 0 || size.Height == 0)
1634 size.Width = calculated_size;
1636 size.Height = calculated_size;
1638 return Layout (size);
1641 public bool Layout (Size size)
1643 if (toolbar == null || !button.Visible)
1648 Size image_size = (toolbar.ImageSize == Size.Empty) ? new Size (16, 16) : toolbar.ImageSize;
1649 int grip = ThemeEngine.Current.ToolBarImageGripWidth;
1651 Rectangle new_image_rect, new_text_rect;
1653 if (toolbar.TextAlign == ToolBarTextAlign.Underneath) {
1654 new_image_rect = new Rectangle ((bounds.Size.Width - image_size.Width) / 2 - grip, 0, image_size.Width + 2 + grip, image_size.Height + 2 * grip);
1655 new_text_rect = new Rectangle (0, new_image_rect.Height, bounds.Size.Width, bounds.Size.Height - new_image_rect.Height - 2 * grip);
1657 new_image_rect = new Rectangle (0, 0, image_size.Width + 2 * grip, image_size.Height + 2 * grip);
1658 new_text_rect = new Rectangle (new_image_rect.Width, 0, bounds.Size.Width - new_image_rect.Width, bounds.Size.Height - 2 * grip);
1661 bool changed = false;
1663 if (new_image_rect != image_rect || new_text_rect != text_rect)
1666 image_rect = new_image_rect;
1667 text_rect = new_text_rect;
1672 public void Invalidate ()
1674 if (toolbar != null)
1675 toolbar.Invalidate (Rectangle);