[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mcs / class / System.Windows.Forms / System.Windows.Forms / ToolBar.cs
bloba56248de7cdca358c6a4d22555ede5137510b48b
1 // System.Windows.Forms.ToolBar.cs
2 //
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.
22 // Author:
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;
33 using System.Drawing;
34 using System.Drawing.Text;
35 using System.Drawing.Imaging;
36 using System.Runtime.InteropServices;
38 namespace System.Windows.Forms
40 [ComVisible (true)]
41 [ClassInterface (ClassInterfaceType.AutoDispatch)]
42 [DefaultEvent ("ButtonClick")]
43 [DefaultProperty ("Buttons")]
44 [Designer ("System.Windows.Forms.Design.ToolBarDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
45 public class ToolBar : Control
47 #region Instance Variables
48 private bool size_specified = false;
49 private ToolBarItem current_item;
50 internal ToolBarItem[] items;
51 internal Size default_size;
52 #endregion Instance Variables
54 #region Events
55 static object ButtonClickEvent = new object ();
56 static object ButtonDropDownEvent = new object ();
58 [Browsable (true)]
59 [EditorBrowsable (EditorBrowsableState.Always)]
60 public new event EventHandler AutoSizeChanged {
61 add { base.AutoSizeChanged += value; }
62 remove { base.AutoSizeChanged -= value; }
65 [Browsable (false)]
66 [EditorBrowsable (EditorBrowsableState.Never)]
67 public new event EventHandler BackColorChanged {
68 add { base.BackColorChanged += value; }
69 remove { base.BackColorChanged -= value; }
72 [Browsable (false)]
73 [EditorBrowsable (EditorBrowsableState.Never)]
74 public new event EventHandler BackgroundImageChanged {
75 add { base.BackgroundImageChanged += value; }
76 remove { base.BackgroundImageChanged -= value; }
79 [Browsable (false)]
80 [EditorBrowsable (EditorBrowsableState.Never)]
81 public new event EventHandler BackgroundImageLayoutChanged {
82 add { base.BackgroundImageLayoutChanged += value; }
83 remove { base.BackgroundImageLayoutChanged -= value; }
86 public event ToolBarButtonClickEventHandler ButtonClick {
87 add { Events.AddHandler (ButtonClickEvent, value); }
88 remove {Events.RemoveHandler (ButtonClickEvent, value); }
91 public event ToolBarButtonClickEventHandler ButtonDropDown {
92 add { Events.AddHandler (ButtonDropDownEvent, value); }
93 remove {Events.RemoveHandler (ButtonDropDownEvent, value); }
96 [Browsable (false)]
97 [EditorBrowsable (EditorBrowsableState.Never)]
98 public new event EventHandler ForeColorChanged {
99 add { base.ForeColorChanged += value; }
100 remove { base.ForeColorChanged -= value; }
103 [Browsable (false)]
104 [EditorBrowsable (EditorBrowsableState.Never)]
105 public new event EventHandler ImeModeChanged {
106 add { base.ImeModeChanged += value; }
107 remove { base.ImeModeChanged -= value; }
110 [Browsable (false)]
111 [EditorBrowsable (EditorBrowsableState.Never)]
112 public new event PaintEventHandler Paint {
113 add { base.Paint += value; }
114 remove { base.Paint -= value; }
117 [Browsable (false)]
118 [EditorBrowsable (EditorBrowsableState.Never)]
119 public new event EventHandler RightToLeftChanged {
120 add { base.RightToLeftChanged += value; }
121 remove { base.RightToLeftChanged -= value; }
124 [Browsable (false)]
125 [EditorBrowsable (EditorBrowsableState.Never)]
126 public new event EventHandler TextChanged {
127 add { base.TextChanged += value; }
128 remove { base.TextChanged -= value; }
130 #endregion Events
132 #region Constructor
133 public ToolBar ()
135 background_color = ThemeEngine.Current.DefaultControlBackColor;
136 foreground_color = ThemeEngine.Current.DefaultControlForeColor;
137 buttons = new ToolBarButtonCollection (this);
138 Dock = DockStyle.Top;
140 GotFocus += new EventHandler (FocusChanged);
141 LostFocus += new EventHandler (FocusChanged);
142 MouseDown += new MouseEventHandler (ToolBar_MouseDown);
143 MouseHover += new EventHandler (ToolBar_MouseHover);
144 MouseLeave += new EventHandler (ToolBar_MouseLeave);
145 MouseMove += new MouseEventHandler (ToolBar_MouseMove);
146 MouseUp += new MouseEventHandler (ToolBar_MouseUp);
147 BackgroundImageChanged += new EventHandler (ToolBar_BackgroundImageChanged);
149 TabStop = false;
151 SetStyle (ControlStyles.UserPaint, false);
152 SetStyle (ControlStyles.FixedHeight, true);
153 SetStyle (ControlStyles.FixedWidth, false);
155 #endregion Constructor
157 #region protected Properties
158 protected override CreateParams CreateParams {
159 get {
160 CreateParams create_params = base.CreateParams;
162 if (appearance == ToolBarAppearance.Flat) {
163 create_params.Style |= (int) ToolBarStyles.TBSTYLE_FLAT;
166 return create_params;
170 protected override ImeMode DefaultImeMode {
171 get { return ImeMode.Disable; }
174 protected override Size DefaultSize {
175 get { return ThemeEngine.Current.ToolBarDefaultSize; }
178 [EditorBrowsable (EditorBrowsableState.Never)]
179 protected override bool DoubleBuffered {
180 get { return base.DoubleBuffered; }
181 set { base.DoubleBuffered = value; }
183 #endregion
185 ToolBarAppearance appearance = ToolBarAppearance.Normal;
187 #region Public Properties
188 [DefaultValue (ToolBarAppearance.Normal)]
189 [Localizable (true)]
190 public ToolBarAppearance Appearance {
191 get { return appearance; }
192 set {
193 if (value == appearance)
194 return;
196 appearance = value;
197 Redraw (true);
201 bool autosize = true;
203 [Browsable (true)]
204 [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
205 [EditorBrowsable (EditorBrowsableState.Always)]
206 [DefaultValue (true)]
207 [Localizable (true)]
208 public override bool AutoSize {
209 get { return autosize; }
210 set {
211 if (value == autosize)
212 return;
214 autosize = value;
216 if (IsHandleCreated)
217 Redraw (true);
221 [Browsable (false)]
222 [EditorBrowsable (EditorBrowsableState.Never)]
223 public override Color BackColor {
224 get { return background_color; }
225 set {
226 if (value == background_color)
227 return;
229 background_color = value;
230 OnBackColorChanged (EventArgs.Empty);
231 Redraw (false);
235 [Browsable (false)]
236 [EditorBrowsable (EditorBrowsableState.Never)]
237 public override Image BackgroundImage {
238 get { return base.BackgroundImage; }
239 set { base.BackgroundImage = value; }
242 [Browsable (false)]
243 [EditorBrowsable (EditorBrowsableState.Never)]
244 public override ImageLayout BackgroundImageLayout {
245 get { return base.BackgroundImageLayout; }
246 set { base.BackgroundImageLayout = value; }
249 [DefaultValue (BorderStyle.None)]
250 [DispIdAttribute (-504)]
251 public BorderStyle BorderStyle {
252 get { return InternalBorderStyle; }
253 set { InternalBorderStyle = value; }
256 ToolBarButtonCollection buttons;
258 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
259 [Localizable (true)]
260 [MergableProperty (false)]
261 public ToolBarButtonCollection Buttons {
262 get { return buttons; }
265 Size button_size;
267 [Localizable (true)]
268 [RefreshProperties (RefreshProperties.All)]
269 public Size ButtonSize {
270 get {
271 if (!button_size.IsEmpty)
272 return button_size;
274 if (buttons.Count == 0)
275 return new Size (39, 36);
277 Size result = CalcButtonSize ();
278 if (result.IsEmpty)
279 return new Size (24, 22);
280 else
281 return result;
283 set {
284 size_specified = value != Size.Empty;
285 if (button_size == value)
286 return;
288 button_size = value;
289 Redraw (true);
293 bool divider = true;
295 [DefaultValue (true)]
296 public bool Divider {
297 get { return divider; }
298 set {
299 if (value == divider)
300 return;
302 divider = value;
303 Redraw (false);
307 [DefaultValue (DockStyle.Top)]
308 [Localizable (true)]
309 public override DockStyle Dock {
310 get { return base.Dock; }
311 set {
312 if (base.Dock == value) {
313 // Call base anyways so layout_type gets set correctly
314 if (value != DockStyle.None)
315 base.Dock = value;
316 return;
319 if (Vertical) {
320 SetStyle (ControlStyles.FixedWidth, AutoSize);
321 SetStyle (ControlStyles.FixedHeight, false);
322 } else {
323 SetStyle (ControlStyles.FixedHeight, AutoSize);
324 SetStyle (ControlStyles.FixedWidth, false);
327 LayoutToolBar ();
329 base.Dock = value;
333 bool drop_down_arrows = true;
335 [DefaultValue (false)]
336 [Localizable (true)]
337 public bool DropDownArrows {
338 get { return drop_down_arrows; }
339 set {
340 if (value == drop_down_arrows)
341 return;
343 drop_down_arrows = value;
344 Redraw (true);
348 [Browsable (false)]
349 [EditorBrowsable (EditorBrowsableState.Never)]
350 public override Color ForeColor {
351 get { return foreground_color; }
352 set {
353 if (value == foreground_color)
354 return;
356 foreground_color = value;
357 OnForeColorChanged (EventArgs.Empty);
358 Redraw (false);
362 ImageList image_list;
364 [DefaultValue (null)]
365 public ImageList ImageList {
366 get { return image_list; }
367 set {
368 if (image_list == value)
369 return;
370 image_list = value;
371 Redraw (true);
375 [Browsable (false)]
376 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
377 [EditorBrowsable (EditorBrowsableState.Advanced)]
378 public Size ImageSize {
379 get {
380 if (ImageList == null)
381 return Size.Empty;
383 return ImageList.ImageSize;
387 // XXX this should probably go away and it should call
388 // into Control.ImeMode instead.
389 ImeMode ime_mode = ImeMode.Disable;
391 [Browsable (false)]
392 [EditorBrowsable (EditorBrowsableState.Never)]
393 public new ImeMode ImeMode {
394 get { return ime_mode; }
395 set {
396 if (value == ime_mode)
397 return;
399 ime_mode = value;
400 OnImeModeChanged (EventArgs.Empty);
404 [Browsable (false)]
405 [EditorBrowsable (EditorBrowsableState.Never)]
406 public override RightToLeft RightToLeft {
407 get { return base.RightToLeft; }
408 set {
409 if (value == base.RightToLeft)
410 return;
412 base.RightToLeft = value;
413 OnRightToLeftChanged (EventArgs.Empty);
417 // Default value is "false" but after make a test in .NET we get "true" result as default.
418 bool show_tooltips = true;
420 [DefaultValue (false)]
421 [Localizable (true)]
422 public bool ShowToolTips {
423 get { return show_tooltips; }
424 set { show_tooltips = value; }
427 [DefaultValue (false)]
428 public new bool TabStop {
429 get { return base.TabStop; }
430 set { base.TabStop = value; }
433 [Bindable (false)]
434 [Browsable (false)]
435 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
436 [EditorBrowsable (EditorBrowsableState.Never)]
437 public override string Text {
438 get { return base.Text; }
439 set {
440 if (value == base.Text)
441 return;
443 base.Text = value;
444 Redraw (true);
448 ToolBarTextAlign text_alignment = ToolBarTextAlign.Underneath;
450 [DefaultValue (ToolBarTextAlign.Underneath)]
451 [Localizable (true)]
452 public ToolBarTextAlign TextAlign {
453 get { return text_alignment; }
454 set {
455 if (value == text_alignment)
456 return;
458 text_alignment = value;
459 Redraw (true);
463 bool wrappable = true;
465 [DefaultValue (true)]
466 [Localizable (true)]
467 public bool Wrappable {
468 get { return wrappable; }
469 set {
470 if (value == wrappable)
471 return;
473 wrappable = value;
474 Redraw (true);
477 #endregion Public Properties
479 #region Public Methods
480 public override string ToString ()
482 int count = this.Buttons.Count;
484 if (count == 0)
485 return string.Format ("System.Windows.Forms.ToolBar, Buttons.Count: 0");
486 else
487 return string.Format ("System.Windows.Forms.ToolBar, Buttons.Count: {0}, Buttons[0]: {1}",
488 count, this.Buttons [0].ToString ());
490 #endregion Public Methods
492 #region Protected Methods
493 protected override void CreateHandle ()
495 base.CreateHandle ();
496 default_size = CalcButtonSize ();
498 // In win32 the recalculate size only happens for not flat style
499 if (appearance != ToolBarAppearance.Flat)
500 Redraw (true);
503 protected override void Dispose (bool disposing)
505 if (disposing)
507 ImageList = null;
509 if (tipdown_timer != null)
510 tipdown_timer.Dispose();
512 if (tip_window != null)
513 tip_window.Dispose();
516 base.Dispose (disposing);
519 private ToolBarButton button_for_focus = null;
521 internal void UIAPerformClick (ToolBarButton button)
523 ToolBarItem previous_item = current_item;
524 current_item = null;
526 foreach (ToolBarItem item in items)
527 if (item.Button == button) {
528 current_item = item;
529 break;
532 try {
533 if (current_item == null)
534 throw new ArgumentException ("button", "The button specified is not part of this toolbar");
535 PerformButtonClick (new ToolBarButtonClickEventArgs (button));
536 } finally {
537 current_item = previous_item;
541 void PerformButtonClick (ToolBarButtonClickEventArgs e)
543 // Only change pushed for ToogleButton
544 if (e.Button.Style == ToolBarButtonStyle.ToggleButton) {
545 if (! e.Button.Pushed)
546 e.Button.Pushed = true;
547 else
548 e.Button.Pushed = false;
551 current_item.Pressed = false;
552 current_item.Invalidate ();
554 button_for_focus = current_item.Button;
555 button_for_focus.UIAHasFocus = true;
557 OnButtonClick (e);
560 protected virtual void OnButtonClick (ToolBarButtonClickEventArgs e)
562 ToolBarButtonClickEventHandler eh = (ToolBarButtonClickEventHandler)(Events [ButtonClickEvent]);
563 if (eh != null)
564 eh (this, e);
567 protected virtual void OnButtonDropDown (ToolBarButtonClickEventArgs e)
569 ToolBarButtonClickEventHandler eh = (ToolBarButtonClickEventHandler)(Events [ButtonDropDownEvent]);
570 if (eh != null)
571 eh (this, e);
573 if (e.Button.DropDownMenu == null)
574 return;
576 ShowDropDownMenu (current_item);
579 internal void ShowDropDownMenu (ToolBarItem item)
581 Point loc = new Point (item.Rectangle.X + 1, item.Rectangle.Bottom + 1);
582 ((ContextMenu) item.Button.DropDownMenu).Show (this, loc);
584 item.DDPressed = false;
585 item.Hilight = false;
586 item.Invalidate ();
589 protected override void OnFontChanged (EventArgs e)
591 base.OnFontChanged (e);
592 Redraw (true);
595 protected override void OnHandleCreated (EventArgs e)
597 base.OnHandleCreated (e);
600 protected override void OnResize (EventArgs e)
602 base.OnResize (e);
603 LayoutToolBar ();
606 protected override void ScaleControl (SizeF factor, BoundsSpecified specified)
608 specified &= ~BoundsSpecified.Height;
610 base.ScaleControl (factor, specified);
613 [EditorBrowsable (EditorBrowsableState.Never)]
614 protected override void ScaleCore (float dx, float dy)
616 dy = 1.0f;
618 base.ScaleCore (dx, dy);
621 private int requested_size = -1;
623 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
625 if (Vertical) {
626 if (!AutoSize && (requested_size != width) && ((specified & BoundsSpecified.Width) != BoundsSpecified.None))
627 requested_size = width;
628 } else {
629 if (!AutoSize && (requested_size != height) && ((specified & BoundsSpecified.Height) != BoundsSpecified.None))
630 requested_size = height;
633 base.SetBoundsCore (x, y, width, height, specified);
636 protected override void WndProc (ref Message m)
638 base.WndProc (ref m);
641 internal override bool InternalPreProcessMessage (ref Message msg)
643 if (msg.Msg == (int)Msg.WM_KEYDOWN) {
644 Keys key_data = (Keys)msg.WParam.ToInt32();
645 if (HandleKeyDown (ref msg, key_data))
646 return true;
648 return base.InternalPreProcessMessage (ref msg);
651 #endregion Protected Methods
653 #region Private Methods
654 internal int CurrentItem {
655 get {
656 return Array.IndexOf (items, current_item);
658 set {
659 if (current_item != null)
660 current_item.Hilight = false;
662 current_item = value == -1 ? null : items [value];
664 if (current_item != null)
665 current_item.Hilight = true;
670 private void FocusChanged (object sender, EventArgs args)
672 if (!Focused && button_for_focus != null)
673 button_for_focus.UIAHasFocus = false;
674 button_for_focus = null;
676 if (Appearance != ToolBarAppearance.Flat || Buttons.Count == 0)
677 return;
679 ToolBarItem prelit = null;
680 foreach (ToolBarItem item in items) {
681 if (item.Hilight) {
682 prelit = item;
683 break;
687 if (Focused && prelit == null) {
688 foreach (ToolBarItem item in items) {
689 if (item.Button.Enabled) {
690 item.Hilight = true;
691 break;
694 } else if (prelit != null) {
695 prelit.Hilight = false;
699 private bool HandleKeyDown (ref Message msg, Keys key_data)
701 if (Appearance != ToolBarAppearance.Flat || Buttons.Count == 0)
702 return false;
704 // Handle the key as needed if the current item is a dropdownbutton.
705 if (HandleKeyOnDropDown (ref msg, key_data))
706 return true;
708 switch (key_data) {
709 case Keys.Left:
710 case Keys.Up:
711 HighlightButton (-1);
712 return true;
713 case Keys.Right:
714 case Keys.Down:
715 HighlightButton (1);
716 return true;
717 case Keys.Enter:
718 case Keys.Space:
719 if (current_item != null) {
720 OnButtonClick (new ToolBarButtonClickEventArgs (current_item.Button));
721 return true;
723 break;
726 return false;
729 bool HandleKeyOnDropDown (ref Message msg, Keys key_data)
731 if (current_item == null || current_item.Button.Style != ToolBarButtonStyle.DropDownButton ||
732 current_item.Button.DropDownMenu == null)
733 return false;
735 Menu dropdown_menu = current_item.Button.DropDownMenu;
737 if (dropdown_menu.Tracker.active) {
738 dropdown_menu.ProcessCmdKey (ref msg, key_data);
739 return true; // always true if the menu is active
742 if (key_data == Keys.Up || key_data == Keys.Down) {
743 current_item.DDPressed = true;
744 current_item.Invalidate ();
745 OnButtonDropDown (new ToolBarButtonClickEventArgs (current_item.Button));
746 return true;
749 return false;
752 void HighlightButton (int offset)
754 ArrayList enabled = new ArrayList ();
755 int count = 0;
756 int start = -1;
757 ToolBarItem curr_item = null;
758 foreach (ToolBarItem item in items) {
759 if (item.Hilight) {
760 start = count;
761 curr_item = item;
764 if (item.Button.Enabled) {
765 enabled.Add (item);
766 count++;
770 int next = (start + offset) % count;
771 if (next < 0)
772 next = count - 1;
774 if (next == start)
775 return;
777 if (curr_item != null)
778 curr_item.Hilight = false;
780 current_item = enabled [next] as ToolBarItem;
781 current_item.Hilight = true;
784 private void ToolBar_BackgroundImageChanged (object sender, EventArgs args)
786 Redraw (false, true);
789 private void ToolBar_MouseDown (object sender, MouseEventArgs me)
791 if ((!Enabled) || ((me.Button & MouseButtons.Left) == 0))
792 return;
794 Point loc = new Point (me.X, me.Y);
796 if (ItemAtPoint (loc) == null)
797 return;
799 // Hide tooltip when left mouse button
800 if ((tip_window != null) && (tip_window.Visible) && ((me.Button & MouseButtons.Left) == MouseButtons.Left)) {
801 TipDownTimer.Stop ();
802 tip_window.Hide (this);
805 // draw the pushed button
806 foreach (ToolBarItem item in items) {
807 if (item.Button.Enabled && item.Rectangle.Contains (loc)) {
808 // Mark the DropDown rect as pressed.
809 // We don't redraw the dropdown rect.
810 if (item.Button.Style == ToolBarButtonStyle.DropDownButton) {
811 Rectangle rect = item.Rectangle;
812 if (DropDownArrows) {
813 rect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
814 rect.X = item.Rectangle.Right - rect.Width;
817 if (rect.Contains (loc)) {
818 if (item.Button.DropDownMenu != null) {
819 item.DDPressed = true;
820 Invalidate (rect);
822 break;
825 item.Pressed = true;
826 item.Inside = true;
827 item.Invalidate ();
828 break;
833 private void ToolBar_MouseUp (object sender, MouseEventArgs me)
835 if ((!Enabled) || ((me.Button & MouseButtons.Left) == 0))
836 return;
838 Point loc = new Point (me.X, me.Y);
840 // draw the normal button
841 // Make a copy in case the list is modified during enumeration
842 ArrayList items = new ArrayList (this.items);
843 foreach (ToolBarItem item in items) {
844 if (item.Button.Enabled && item.Rectangle.Contains (loc)) {
845 if (item.Button.Style == ToolBarButtonStyle.DropDownButton) {
846 Rectangle ddRect = item.Rectangle;
847 ddRect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
848 ddRect.X = item.Rectangle.Right - ddRect.Width;
849 if (ddRect.Contains (loc)) {
850 current_item = item;
851 if (item.DDPressed)
852 OnButtonDropDown (new ToolBarButtonClickEventArgs (item.Button));
853 continue;
856 // Fire a ButtonClick
857 current_item = item;
858 if ((item.Pressed) && ((me.Button & MouseButtons.Left) == MouseButtons.Left))
859 PerformButtonClick (new ToolBarButtonClickEventArgs (item.Button));
860 } else if (item.Pressed) {
861 item.Pressed = false;
862 item.Invalidate ();
867 private ToolBarItem ItemAtPoint (Point pt)
869 foreach (ToolBarItem item in items)
870 if (item.Rectangle.Contains (pt))
871 return item;
873 return null;
876 ToolTip tip_window = null;
877 Timer tipdown_timer = null;
879 private void PopDownTip (object o, EventArgs args)
881 tip_window.Hide (this);
884 private Timer TipDownTimer {
885 get {
886 if (tipdown_timer == null) {
887 tipdown_timer = new Timer ();
888 tipdown_timer.Enabled = false;
889 tipdown_timer.Interval = 5000;
890 tipdown_timer.Tick += new EventHandler (PopDownTip);
892 return tipdown_timer;
896 private void ToolBar_MouseHover (object sender, EventArgs e)
898 if (Capture)
899 return;
901 if (tip_window == null)
902 tip_window = new ToolTip ();
904 ToolBarItem item = ItemAtPoint (PointToClient (Control.MousePosition));
905 current_item = item;
907 if (item == null || item.Button.ToolTipText.Length == 0)
908 return;
910 tip_window.Present (this, item.Button.ToolTipText);
911 TipDownTimer.Start ();
914 private void ToolBar_MouseLeave (object sender, EventArgs e)
916 if (tipdown_timer != null)
917 tipdown_timer.Dispose ();
918 tipdown_timer = null;
919 if (tip_window != null)
920 tip_window.Dispose ();
921 tip_window = null;
923 if (!Enabled || current_item == null)
924 return;
926 current_item.Hilight = false;
927 current_item = null;
930 private void ToolBar_MouseMove (object sender, MouseEventArgs me)
932 if (!Enabled)
933 return;
935 if (tip_window != null && tip_window.Visible) {
936 TipDownTimer.Stop ();
937 TipDownTimer.Start ();
940 Point loc = new Point (me.X, me.Y);
942 if (Capture) {
943 // If the button was pressed and we leave, release the
944 // button press and vice versa
945 foreach (ToolBarItem item in items) {
946 if (item.Pressed &&
947 (item.Inside != item.Rectangle.Contains (loc))) {
948 item.Inside = item.Rectangle.Contains (loc);
949 item.Hilight = false;
950 break;
953 return;
956 if (current_item != null && current_item.Rectangle.Contains (loc)) {
957 if (ThemeEngine.Current.ToolBarHasHotElementStyles (this)) {
958 if (current_item.Hilight || (!ThemeEngine.Current.ToolBarHasHotCheckedElementStyles && current_item.Button.Pushed) || !current_item.Button.Enabled)
959 return;
960 current_item.Hilight = true;
962 } else {
963 if (tip_window != null) {
964 if (tip_window.Visible) {
965 tip_window.Hide (this);
966 TipDownTimer.Stop ();
968 current_item = ItemAtPoint (loc);
969 if (current_item != null && current_item.Button.ToolTipText.Length > 0) {
970 tip_window.Present (this, current_item.Button.ToolTipText);
971 TipDownTimer.Start ();
975 if (ThemeEngine.Current.ToolBarHasHotElementStyles (this)) {
976 foreach (ToolBarItem item in items) {
977 if (item.Rectangle.Contains (loc) && item.Button.Enabled) {
978 current_item = item;
979 if (current_item.Hilight || (!ThemeEngine.Current.ToolBarHasHotCheckedElementStyles && current_item.Button.Pushed))
980 continue;
981 current_item.Hilight = true;
983 else if (item.Hilight) {
984 item.Hilight = false;
991 internal override void OnPaintInternal (PaintEventArgs pevent)
993 if (GetStyle (ControlStyles.UserPaint))
994 return;
996 ThemeEngine.Current.DrawToolBar (pevent.Graphics, pevent.ClipRectangle, this);
998 // Toolbars do not raise OnPaint unless UserPaint is set
999 pevent.Handled = true;
1002 internal void Redraw (bool recalculate)
1004 Redraw (recalculate, true);
1007 internal void Redraw (bool recalculate, bool force)
1009 bool invalidate = true;
1011 if (recalculate)
1012 invalidate = LayoutToolBar ();
1014 if (force || invalidate)
1015 Invalidate ();
1018 internal bool SizeSpecified {
1019 get { return size_specified; }
1022 internal bool Vertical {
1023 get { return (Dock == DockStyle.Left) || (Dock == DockStyle.Right); }
1026 internal const int text_padding = 3;
1028 private Size CalcButtonSize ()
1030 if (Buttons.Count == 0)
1031 return Size.Empty;
1033 string longest_text = Buttons [0].Text;
1034 for (int i = 1; i < Buttons.Count; i++) {
1035 if (Buttons[i].Text.Length > longest_text.Length)
1036 longest_text = Buttons[i].Text;
1039 Size size = Size.Empty;
1040 if (longest_text != null && longest_text.Length > 0) {
1041 SizeF sz = TextRenderer.MeasureString (longest_text, Font);
1042 if (sz != SizeF.Empty)
1043 size = new Size ((int) Math.Ceiling (sz.Width) + 2 * text_padding, (int) Math.Ceiling (sz.Height));
1046 Size img_size = ImageList == null ? new Size (16, 16) : ImageSize;
1048 Theme theme = ThemeEngine.Current;
1049 int imgWidth = img_size.Width + 2 * theme.ToolBarImageGripWidth;
1050 int imgHeight = img_size.Height + 2 * theme.ToolBarImageGripWidth;
1052 if (text_alignment == ToolBarTextAlign.Right) {
1053 size.Width = imgWidth + size.Width;
1054 size.Height = (size.Height > imgHeight) ? size.Height : imgHeight;
1055 } else {
1056 size.Height = imgHeight + size.Height;
1057 size.Width = (size.Width > imgWidth) ? size.Width : imgWidth;
1060 size.Width += theme.ToolBarImageGripWidth;
1061 size.Height += theme.ToolBarImageGripWidth;
1062 return size;
1065 // Flat toolbars disregard specified sizes. Normal toolbars grow the
1066 // button size to be at least large enough to show the image.
1067 private Size AdjustedButtonSize {
1068 get {
1069 Size size;
1071 if (default_size.IsEmpty || Appearance == ToolBarAppearance.Normal)
1072 size = ButtonSize;
1073 else
1074 size = default_size;
1076 if (size_specified) {
1077 if (Appearance == ToolBarAppearance.Flat)
1078 size = CalcButtonSize ();
1079 else {
1080 int grip = ThemeEngine.Current.ToolBarImageGripWidth;
1081 if (size.Width < ImageSize.Width + 2 * grip )
1082 size.Width = ImageSize.Width + 2 * grip;
1083 if (size.Height < ImageSize.Height + 2 * grip)
1084 size.Height = ImageSize.Height + 2 * grip;
1087 return size;
1091 private bool LayoutToolBar ()
1093 bool changed = false;
1094 Theme theme = ThemeEngine.Current;
1095 int x = theme.ToolBarGripWidth;
1096 int y = theme.ToolBarGripWidth;
1098 Size adjusted_size = AdjustedButtonSize;
1100 int calculated_size = (Vertical ? adjusted_size.Width : adjusted_size.Height) + theme.ToolBarGripWidth;
1102 int separator_index = -1;
1104 items = new ToolBarItem [buttons.Count];
1106 for (int i = 0; i < buttons.Count; i++) {
1107 ToolBarButton button = buttons [i];
1109 ToolBarItem item = new ToolBarItem (button);
1110 items [i] = item;
1112 if (!button.Visible)
1113 continue;
1115 if (size_specified && (button.Style != ToolBarButtonStyle.Separator))
1116 changed = item.Layout (adjusted_size);
1117 else
1118 changed = item.Layout (Vertical, calculated_size);
1120 bool is_separator = button.Style == ToolBarButtonStyle.Separator;
1122 if (Vertical) {
1123 if (y + item.Rectangle.Height < Height || is_separator || !Wrappable) {
1124 if (item.Location.X != x || item.Location.Y != y)
1125 changed = true;
1126 item.Location = new Point (x, y);
1127 y += item.Rectangle.Height;
1128 if (is_separator)
1129 separator_index = i;
1130 } else if (separator_index > 0) {
1131 i = separator_index;
1132 separator_index = -1;
1133 y = theme.ToolBarGripWidth;
1134 x += calculated_size;
1135 } else {
1136 y = theme.ToolBarGripWidth;
1137 x += calculated_size;
1138 if (item.Location.X != x || item.Location.Y != y)
1139 changed = true;
1140 item.Location = new Point (x, y);
1141 y += item.Rectangle.Height;
1143 } else {
1144 if (x + item.Rectangle.Width < Width || is_separator || !Wrappable) {
1145 if (item.Location.X != x || item.Location.Y != y)
1146 changed = true;
1147 item.Location = new Point (x, y);
1148 x += item.Rectangle.Width;
1149 if (is_separator)
1150 separator_index = i;
1151 } else if (separator_index > 0) {
1152 i = separator_index;
1153 separator_index = -1;
1154 x = theme.ToolBarGripWidth;
1155 y += calculated_size;
1156 } else {
1157 x = theme.ToolBarGripWidth;
1158 y += calculated_size;
1159 if (item.Location.X != x || item.Location.Y != y)
1160 changed = true;
1161 item.Location = new Point (x, y);
1162 x += item.Rectangle.Width;
1167 if (Parent == null)
1168 return changed;
1170 if (Wrappable)
1171 calculated_size += Vertical ? x : y;
1173 if (IsHandleCreated) {
1174 if (Vertical)
1175 Width = calculated_size;
1176 else
1177 Height = calculated_size;
1180 return changed;
1182 #endregion Private Methods
1184 #region subclass
1185 public class ToolBarButtonCollection : IList, ICollection, IEnumerable
1187 #region instance variables
1188 private ArrayList list; // ToolBarButton list
1189 private ToolBar owner; // ToolBar associated to Collection
1190 private bool redraw; // Flag if needs to redraw after add/remove operations
1191 #endregion
1193 #region UIA Framework Events
1194 static object UIACollectionChangedEvent = new object ();
1196 internal event CollectionChangeEventHandler UIACollectionChanged {
1197 add { owner.Events.AddHandler (UIACollectionChangedEvent, value); }
1198 remove { owner.Events.RemoveHandler (UIACollectionChangedEvent, value); }
1201 internal void OnUIACollectionChanged (CollectionChangeEventArgs e)
1203 CollectionChangeEventHandler eh
1204 = (CollectionChangeEventHandler) owner.Events [UIACollectionChangedEvent];
1205 if (eh != null)
1206 eh (owner, e);
1208 #endregion
1210 #region constructors
1211 public ToolBarButtonCollection (ToolBar owner)
1213 this.list = new ArrayList ();
1214 this.owner = owner;
1215 this.redraw = true;
1217 #endregion
1219 #region properties
1220 [Browsable (false)]
1221 public int Count {
1222 get { return list.Count; }
1225 public bool IsReadOnly {
1226 get { return list.IsReadOnly; }
1229 public virtual ToolBarButton this [int index] {
1230 get { return (ToolBarButton) list [index]; }
1231 set {
1232 // UIA Framework Event: Button Removed
1233 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
1235 value.SetParent (owner);
1236 list [index] = value;
1237 owner.Redraw (true);
1239 // UIA Framework Event: Button Added
1240 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
1244 public virtual ToolBarButton this[string key] {
1245 get {
1246 if (string.IsNullOrEmpty (key))
1247 return null;
1249 foreach (ToolBarButton b in list)
1250 if (string.Compare (b.Name, key, true) == 0)
1251 return b;
1253 return null;
1257 bool ICollection.IsSynchronized {
1258 get { return list.IsSynchronized; }
1261 object ICollection.SyncRoot {
1262 get { return list.SyncRoot; }
1265 bool IList.IsFixedSize {
1266 get { return list.IsFixedSize; }
1269 object IList.this [int index] {
1270 get { return this [index]; }
1271 set {
1272 if (! (value is ToolBarButton))
1273 throw new ArgumentException("Not of type ToolBarButton", "value");
1274 this [index] = (ToolBarButton) value;
1277 #endregion
1279 #region methods
1280 public int Add (string text)
1282 ToolBarButton button = new ToolBarButton (text);
1283 return this.Add (button);
1286 public int Add (ToolBarButton button)
1288 int result;
1289 button.SetParent (owner);
1290 result = list.Add (button);
1291 if (redraw)
1292 owner.Redraw (true);
1294 // UIA Framework Event: Button Added
1295 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, result));
1297 return result;
1300 public void AddRange (ToolBarButton [] buttons)
1302 try {
1303 redraw = false;
1304 foreach (ToolBarButton button in buttons)
1305 Add (button);
1307 finally {
1308 redraw = true;
1309 owner.Redraw (true);
1313 public void Clear ()
1315 list.Clear ();
1316 owner.Redraw (false);
1318 // UIA Framework Event: Button Cleared
1319 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, -1));
1322 public bool Contains (ToolBarButton button)
1324 return list.Contains (button);
1327 public virtual bool ContainsKey (string key)
1329 return !(this[key] == null);
1332 public IEnumerator GetEnumerator ()
1334 return list.GetEnumerator ();
1337 void ICollection.CopyTo (Array dest, int index)
1339 list.CopyTo (dest, index);
1342 int IList.Add (object button)
1344 if (! (button is ToolBarButton)) {
1345 throw new ArgumentException("Not of type ToolBarButton", "button");
1348 return this.Add ((ToolBarButton) button);
1351 bool IList.Contains (object button)
1353 if (! (button is ToolBarButton)) {
1354 throw new ArgumentException("Not of type ToolBarButton", "button");
1357 return this.Contains ((ToolBarButton) button);
1360 int IList.IndexOf (object button)
1362 if (! (button is ToolBarButton)) {
1363 throw new ArgumentException("Not of type ToolBarButton", "button");
1366 return this.IndexOf ((ToolBarButton) button);
1369 void IList.Insert (int index, object button)
1371 if (! (button is ToolBarButton)) {
1372 throw new ArgumentException("Not of type ToolBarButton", "button");
1375 this.Insert (index, (ToolBarButton) button);
1378 void IList.Remove (object button)
1380 if (! (button is ToolBarButton)) {
1381 throw new ArgumentException("Not of type ToolBarButton", "button");
1384 this.Remove ((ToolBarButton) button);
1387 public int IndexOf (ToolBarButton button)
1389 return list.IndexOf (button);
1392 public virtual int IndexOfKey (string key)
1394 return IndexOf (this[key]);
1397 public void Insert (int index, ToolBarButton button)
1399 list.Insert (index, button);
1400 owner.Redraw (true);
1402 // UIA Framework Event: Button Added
1403 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
1406 public void Remove (ToolBarButton button)
1408 list.Remove (button);
1409 owner.Redraw (true);
1412 public void RemoveAt (int index)
1414 list.RemoveAt (index);
1415 owner.Redraw (true);
1417 // UIA Framework Event: Button Removed
1418 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
1421 public virtual void RemoveByKey (string key)
1423 Remove (this[key]);
1425 #endregion methods
1428 #endregion subclass
1432 // Because same button can be added to toolbar multiple times, we need to maintain
1433 // a list of button information for each positions.
1434 internal class ToolBarItem : Component
1436 #region Instance variables
1438 private ToolBar toolbar; // Parent toolbar
1439 private ToolBarButton button; // Associated toolBar button
1440 private Rectangle bounds; // Toolbar button bounds
1441 private Rectangle image_rect; // Image button bounds
1442 private Rectangle text_rect; // Text button bounds
1444 private bool dd_pressed = false; // to check for a mouse down on dropdown rect
1445 private bool inside = false; // to handle the mouse move event with mouse pressed
1446 private bool hilight = false; // to hilight buttons in flat style
1447 private bool pressed = false; // this is to check for mouse down on a button
1449 #endregion
1451 #region Constructors
1453 public ToolBarItem (ToolBarButton button)
1455 this.toolbar = button.Parent;
1456 this.button = button;
1459 #endregion Constructors
1461 #region Properties
1463 public ToolBarButton Button {
1464 get { return this.button; }
1467 public Rectangle Rectangle {
1468 get {
1469 if (!button.Visible || toolbar == null)
1470 return Rectangle.Empty;
1472 if (button.Style == ToolBarButtonStyle.DropDownButton && toolbar.DropDownArrows) {
1473 Rectangle result = bounds;
1474 result.Width += ThemeEngine.Current.ToolBarDropDownWidth;
1475 return result;
1478 return bounds;
1480 set { this.bounds = value; }
1483 public Point Location {
1484 get { return bounds.Location; }
1485 set { bounds.Location = value; }
1488 public Rectangle ImageRectangle {
1489 get {
1490 Rectangle result = image_rect;
1491 result.X += bounds.X;
1492 result.Y += bounds.Y;
1493 return result;
1497 public Rectangle TextRectangle {
1498 get {
1499 Rectangle result = text_rect;
1500 result.X += bounds.X;
1501 result.Y += bounds.Y;
1502 return result;
1506 private Size TextSize {
1507 get {
1508 StringFormat text_format = new StringFormat ();
1509 text_format.HotkeyPrefix = HotkeyPrefix.Hide;
1511 SizeF sz = TextRenderer.MeasureString (button.Text, toolbar.Font, SizeF.Empty, text_format);
1512 if (sz == SizeF.Empty)
1513 return Size.Empty;
1514 return new Size ((int) Math.Ceiling (sz.Width) + 2 * ToolBar.text_padding, (int) Math.Ceiling (sz.Height));
1518 public bool Pressed {
1519 get { return (pressed && inside); }
1520 set { pressed = value; }
1523 public bool DDPressed {
1524 get { return dd_pressed; }
1525 set { dd_pressed = value; }
1528 public bool Inside {
1529 get { return inside; }
1530 set { inside = value; }
1533 public bool Hilight {
1534 get { return hilight; }
1535 set {
1536 if (hilight == value)
1537 return;
1539 hilight = value;
1540 Invalidate ();
1544 #endregion Properties
1546 #region Methods
1548 public Size CalculateSize ()
1550 Theme theme = ThemeEngine.Current;
1552 int ht = toolbar.ButtonSize.Height + 2 * theme.ToolBarGripWidth;
1554 if (button.Style == ToolBarButtonStyle.Separator)
1555 return new Size (theme.ToolBarSeparatorWidth, ht);
1557 Size size;
1558 if (TextSize.IsEmpty && (button.Image == null))
1559 size = toolbar.default_size;
1560 else
1561 size = TextSize;
1563 Size image_size = (toolbar.ImageSize == Size.Empty) ? new Size (16, 16) : toolbar.ImageSize;
1565 int image_width = image_size.Width + 2 * theme.ToolBarImageGripWidth;
1566 int image_height = image_size.Height + 2 * theme.ToolBarImageGripWidth;
1568 if (toolbar.TextAlign == ToolBarTextAlign.Right) {
1569 size.Width = image_width + size.Width;
1570 size.Height = (size.Height > image_height) ? size.Height : image_height;
1571 } else {
1572 size.Height = image_height + size.Height;
1573 size.Width = (size.Width > image_width) ? size.Width : image_width;
1576 size.Width += theme.ToolBarGripWidth;
1577 size.Height += theme.ToolBarGripWidth;
1578 return size;
1582 public bool Layout (bool vertical, int calculated_size)
1584 if (toolbar == null || !button.Visible)
1585 return false;
1587 Size psize = toolbar.ButtonSize;
1588 Size size = psize;
1589 if ((!toolbar.SizeSpecified) || (button.Style == ToolBarButtonStyle.Separator)) {
1590 size = CalculateSize ();
1592 if (size.Width == 0 || size.Height == 0)
1593 size = psize;
1595 if (vertical)
1596 size.Width = calculated_size;
1597 else
1598 size.Height = calculated_size;
1600 return Layout (size);
1603 public bool Layout (Size size)
1605 if (toolbar == null || !button.Visible)
1606 return false;
1608 bounds.Size = size;
1610 Size image_size = (toolbar.ImageSize == Size.Empty) ? new Size (16, 16) : toolbar.ImageSize;
1611 int grip = ThemeEngine.Current.ToolBarImageGripWidth;
1613 Rectangle new_image_rect, new_text_rect;
1615 if (toolbar.TextAlign == ToolBarTextAlign.Underneath) {
1616 new_image_rect = new Rectangle ((bounds.Size.Width - image_size.Width) / 2 - grip, 0, image_size.Width + 2 + grip, image_size.Height + 2 * grip);
1617 new_text_rect = new Rectangle (0, new_image_rect.Height, bounds.Size.Width, bounds.Size.Height - new_image_rect.Height - 2 * grip);
1618 } else {
1619 new_image_rect = new Rectangle (0, 0, image_size.Width + 2 * grip, image_size.Height + 2 * grip);
1620 new_text_rect = new Rectangle (new_image_rect.Width, 0, bounds.Size.Width - new_image_rect.Width, bounds.Size.Height - 2 * grip);
1623 bool changed = false;
1625 if (new_image_rect != image_rect || new_text_rect != text_rect)
1626 changed = true;
1628 image_rect = new_image_rect;
1629 text_rect = new_text_rect;
1631 return changed;
1634 public void Invalidate ()
1636 if (toolbar != null)
1637 toolbar.Invalidate (Rectangle);
1640 #endregion Methods