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
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
55 static object ButtonClickEvent = new object ();
56 static object ButtonDropDownEvent = new object ();
59 [EditorBrowsable (EditorBrowsableState.Always)]
60 public new event EventHandler AutoSizeChanged {
61 add { base.AutoSizeChanged += value; }
62 remove { base.AutoSizeChanged -= value; }
66 [EditorBrowsable (EditorBrowsableState.Never)]
67 public new event EventHandler BackColorChanged {
68 add { base.BackColorChanged += value; }
69 remove { base.BackColorChanged -= value; }
73 [EditorBrowsable (EditorBrowsableState.Never)]
74 public new event EventHandler BackgroundImageChanged {
75 add { base.BackgroundImageChanged += value; }
76 remove { base.BackgroundImageChanged -= value; }
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); }
97 [EditorBrowsable (EditorBrowsableState.Never)]
98 public new event EventHandler ForeColorChanged {
99 add { base.ForeColorChanged += value; }
100 remove { base.ForeColorChanged -= value; }
104 [EditorBrowsable (EditorBrowsableState.Never)]
105 public new event EventHandler ImeModeChanged {
106 add { base.ImeModeChanged += value; }
107 remove { base.ImeModeChanged -= value; }
111 [EditorBrowsable (EditorBrowsableState.Never)]
112 public new event PaintEventHandler Paint {
113 add { base.Paint += value; }
114 remove { base.Paint -= value; }
118 [EditorBrowsable (EditorBrowsableState.Never)]
119 public new event EventHandler RightToLeftChanged {
120 add { base.RightToLeftChanged += value; }
121 remove { base.RightToLeftChanged -= value; }
125 [EditorBrowsable (EditorBrowsableState.Never)]
126 public new event EventHandler TextChanged {
127 add { base.TextChanged += value; }
128 remove { base.TextChanged -= value; }
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);
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 {
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; }
185 ToolBarAppearance appearance = ToolBarAppearance.Normal;
187 #region Public Properties
188 [DefaultValue (ToolBarAppearance.Normal)]
190 public ToolBarAppearance Appearance {
191 get { return appearance; }
193 if (value == appearance)
201 bool autosize = true;
204 [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
205 [EditorBrowsable (EditorBrowsableState.Always)]
206 [DefaultValue (true)]
208 public override bool AutoSize {
209 get { return autosize; }
211 if (value == autosize)
222 [EditorBrowsable (EditorBrowsableState.Never)]
223 public override Color BackColor {
224 get { return background_color; }
226 if (value == background_color)
229 background_color = value;
230 OnBackColorChanged (EventArgs.Empty);
236 [EditorBrowsable (EditorBrowsableState.Never)]
237 public override Image BackgroundImage {
238 get { return base.BackgroundImage; }
239 set { base.BackgroundImage = value; }
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)]
260 [MergableProperty (false)]
261 public ToolBarButtonCollection Buttons {
262 get { return buttons; }
268 [RefreshProperties (RefreshProperties.All)]
269 public Size ButtonSize {
271 if (!button_size.IsEmpty)
274 if (buttons.Count == 0)
275 return new Size (39, 36);
277 Size result = CalcButtonSize ();
279 return new Size (24, 22);
284 size_specified = value != Size.Empty;
285 if (button_size == value)
295 [DefaultValue (true)]
296 public bool Divider {
297 get { return divider; }
299 if (value == divider)
307 [DefaultValue (DockStyle.Top)]
309 public override DockStyle Dock {
310 get { return base.Dock; }
312 if (base.Dock == value) {
313 // Call base anyways so layout_type gets set correctly
314 if (value != DockStyle.None)
320 SetStyle (ControlStyles.FixedWidth, AutoSize);
321 SetStyle (ControlStyles.FixedHeight, false);
323 SetStyle (ControlStyles.FixedHeight, AutoSize);
324 SetStyle (ControlStyles.FixedWidth, false);
333 bool drop_down_arrows = true;
335 [DefaultValue (false)]
337 public bool DropDownArrows {
338 get { return drop_down_arrows; }
340 if (value == drop_down_arrows)
343 drop_down_arrows = value;
349 [EditorBrowsable (EditorBrowsableState.Never)]
350 public override Color ForeColor {
351 get { return foreground_color; }
353 if (value == foreground_color)
356 foreground_color = value;
357 OnForeColorChanged (EventArgs.Empty);
362 ImageList image_list;
364 [DefaultValue (null)]
365 public ImageList ImageList {
366 get { return image_list; }
368 if (image_list == value)
376 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
377 [EditorBrowsable (EditorBrowsableState.Advanced)]
378 public Size ImageSize {
380 if (ImageList == null)
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;
392 [EditorBrowsable (EditorBrowsableState.Never)]
393 public new ImeMode ImeMode {
394 get { return ime_mode; }
396 if (value == ime_mode)
400 OnImeModeChanged (EventArgs.Empty);
405 [EditorBrowsable (EditorBrowsableState.Never)]
406 public override RightToLeft RightToLeft {
407 get { return base.RightToLeft; }
409 if (value == base.RightToLeft)
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)]
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; }
435 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
436 [EditorBrowsable (EditorBrowsableState.Never)]
437 public override string Text {
438 get { return base.Text; }
440 if (value == base.Text)
448 ToolBarTextAlign text_alignment = ToolBarTextAlign.Underneath;
450 [DefaultValue (ToolBarTextAlign.Underneath)]
452 public ToolBarTextAlign TextAlign {
453 get { return text_alignment; }
455 if (value == text_alignment)
458 text_alignment = value;
463 bool wrappable = true;
465 [DefaultValue (true)]
467 public bool Wrappable {
468 get { return wrappable; }
470 if (value == wrappable)
477 #endregion Public Properties
479 #region Public Methods
480 public override string ToString ()
482 int count = this.Buttons.Count;
485 return string.Format ("System.Windows.Forms.ToolBar, Buttons.Count: 0");
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)
503 protected override void Dispose (bool disposing)
508 base.Dispose (disposing);
511 private ToolBarButton button_for_focus = null;
513 internal void UIAPerformClick (ToolBarButton button)
515 ToolBarItem previous_item = current_item;
518 foreach (ToolBarItem item in items)
519 if (item.Button == button) {
525 if (current_item == null)
526 throw new ArgumentException ("button", "The button specified is not part of this toolbar");
527 PerformButtonClick (new ToolBarButtonClickEventArgs (button));
529 current_item = previous_item;
533 void PerformButtonClick (ToolBarButtonClickEventArgs e)
535 // Only change pushed for ToogleButton
536 if (e.Button.Style == ToolBarButtonStyle.ToggleButton) {
537 if (! e.Button.Pushed)
538 e.Button.Pushed = true;
540 e.Button.Pushed = false;
543 current_item.Pressed = false;
544 current_item.Invalidate ();
546 button_for_focus = current_item.Button;
547 button_for_focus.UIAHasFocus = true;
552 protected virtual void OnButtonClick (ToolBarButtonClickEventArgs e)
554 ToolBarButtonClickEventHandler eh = (ToolBarButtonClickEventHandler)(Events [ButtonClickEvent]);
559 protected virtual void OnButtonDropDown (ToolBarButtonClickEventArgs e)
561 ToolBarButtonClickEventHandler eh = (ToolBarButtonClickEventHandler)(Events [ButtonDropDownEvent]);
565 if (e.Button.DropDownMenu == null)
568 ShowDropDownMenu (current_item);
571 internal void ShowDropDownMenu (ToolBarItem item)
573 Point loc = new Point (item.Rectangle.X + 1, item.Rectangle.Bottom + 1);
574 ((ContextMenu) item.Button.DropDownMenu).Show (this, loc);
576 item.DDPressed = false;
577 item.Hilight = false;
581 protected override void OnFontChanged (EventArgs e)
583 base.OnFontChanged (e);
587 protected override void OnHandleCreated (EventArgs e)
589 base.OnHandleCreated (e);
592 protected override void OnResize (EventArgs e)
598 protected override void ScaleControl (SizeF factor, BoundsSpecified specified)
600 specified &= ~BoundsSpecified.Height;
602 base.ScaleControl (factor, specified);
605 [EditorBrowsable (EditorBrowsableState.Never)]
606 protected override void ScaleCore (float dx, float dy)
610 base.ScaleCore (dx, dy);
613 private int requested_size = -1;
615 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
618 if (!AutoSize && (requested_size != width) && ((specified & BoundsSpecified.Width) != BoundsSpecified.None))
619 requested_size = width;
621 if (!AutoSize && (requested_size != height) && ((specified & BoundsSpecified.Height) != BoundsSpecified.None))
622 requested_size = height;
625 base.SetBoundsCore (x, y, width, height, specified);
628 protected override void WndProc (ref Message m)
630 base.WndProc (ref m);
633 internal override bool InternalPreProcessMessage (ref Message msg)
635 if (msg.Msg == (int)Msg.WM_KEYDOWN) {
636 Keys key_data = (Keys)msg.WParam.ToInt32();
637 if (HandleKeyDown (ref msg, key_data))
640 return base.InternalPreProcessMessage (ref msg);
643 #endregion Protected Methods
645 #region Private Methods
646 internal int CurrentItem {
648 return Array.IndexOf (items, current_item);
651 if (current_item != null)
652 current_item.Hilight = false;
654 current_item = value == -1 ? null : items [value];
656 if (current_item != null)
657 current_item.Hilight = true;
662 private void FocusChanged (object sender, EventArgs args)
664 if (!Focused && button_for_focus != null)
665 button_for_focus.UIAHasFocus = false;
666 button_for_focus = null;
668 if (Appearance != ToolBarAppearance.Flat || Buttons.Count == 0)
671 ToolBarItem prelit = null;
672 foreach (ToolBarItem item in items) {
679 if (Focused && prelit == null) {
680 foreach (ToolBarItem item in items) {
681 if (item.Button.Enabled) {
686 } else if (prelit != null) {
687 prelit.Hilight = false;
691 private bool HandleKeyDown (ref Message msg, Keys key_data)
693 if (Appearance != ToolBarAppearance.Flat || Buttons.Count == 0)
696 // Handle the key as needed if the current item is a dropdownbutton.
697 if (HandleKeyOnDropDown (ref msg, key_data))
703 HighlightButton (-1);
711 if (current_item != null) {
712 OnButtonClick (new ToolBarButtonClickEventArgs (current_item.Button));
721 bool HandleKeyOnDropDown (ref Message msg, Keys key_data)
723 if (current_item == null || current_item.Button.Style != ToolBarButtonStyle.DropDownButton ||
724 current_item.Button.DropDownMenu == null)
727 Menu dropdown_menu = current_item.Button.DropDownMenu;
729 if (dropdown_menu.Tracker.active) {
730 dropdown_menu.ProcessCmdKey (ref msg, key_data);
731 return true; // always true if the menu is active
734 if (key_data == Keys.Up || key_data == Keys.Down) {
735 current_item.DDPressed = true;
736 current_item.Invalidate ();
737 OnButtonDropDown (new ToolBarButtonClickEventArgs (current_item.Button));
744 void HighlightButton (int offset)
746 ArrayList enabled = new ArrayList ();
749 ToolBarItem curr_item = null;
750 foreach (ToolBarItem item in items) {
756 if (item.Button.Enabled) {
762 int next = (start + offset) % count;
769 if (curr_item != null)
770 curr_item.Hilight = false;
772 current_item = enabled [next] as ToolBarItem;
773 current_item.Hilight = true;
776 private void ToolBar_BackgroundImageChanged (object sender, EventArgs args)
778 Redraw (false, true);
781 private void ToolBar_MouseDown (object sender, MouseEventArgs me)
783 if ((!Enabled) || ((me.Button & MouseButtons.Left) == 0))
786 Point loc = new Point (me.X, me.Y);
788 if (ItemAtPoint (loc) == null)
791 // Hide tooltip when left mouse button
792 if ((tip_window != null) && (tip_window.Visible) && ((me.Button & MouseButtons.Left) == MouseButtons.Left)) {
793 TipDownTimer.Stop ();
794 tip_window.Hide (this);
797 // draw the pushed button
798 foreach (ToolBarItem item in items) {
799 if (item.Button.Enabled && item.Rectangle.Contains (loc)) {
800 // Mark the DropDown rect as pressed.
801 // We don't redraw the dropdown rect.
802 if (item.Button.Style == ToolBarButtonStyle.DropDownButton) {
803 Rectangle rect = item.Rectangle;
804 if (DropDownArrows) {
805 rect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
806 rect.X = item.Rectangle.Right - rect.Width;
809 if (rect.Contains (loc)) {
810 if (item.Button.DropDownMenu != null) {
811 item.DDPressed = true;
825 private void ToolBar_MouseUp (object sender, MouseEventArgs me)
827 if ((!Enabled) || ((me.Button & MouseButtons.Left) == 0))
830 Point loc = new Point (me.X, me.Y);
832 // draw the normal button
833 // Make a copy in case the list is modified during enumeration
834 ArrayList items = new ArrayList (this.items);
835 foreach (ToolBarItem item in items) {
836 if (item.Button.Enabled && item.Rectangle.Contains (loc)) {
837 if (item.Button.Style == ToolBarButtonStyle.DropDownButton) {
838 Rectangle ddRect = item.Rectangle;
839 ddRect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
840 ddRect.X = item.Rectangle.Right - ddRect.Width;
841 if (ddRect.Contains (loc)) {
844 OnButtonDropDown (new ToolBarButtonClickEventArgs (item.Button));
848 // Fire a ButtonClick
850 if ((item.Pressed) && ((me.Button & MouseButtons.Left) == MouseButtons.Left))
851 PerformButtonClick (new ToolBarButtonClickEventArgs (item.Button));
852 } else if (item.Pressed) {
853 item.Pressed = false;
859 private ToolBarItem ItemAtPoint (Point pt)
861 foreach (ToolBarItem item in items)
862 if (item.Rectangle.Contains (pt))
868 ToolTip tip_window = null;
869 Timer tipdown_timer = null;
871 private void PopDownTip (object o, EventArgs args)
873 tip_window.Hide (this);
876 private Timer TipDownTimer {
878 if (tipdown_timer == null) {
879 tipdown_timer = new Timer ();
880 tipdown_timer.Enabled = false;
881 tipdown_timer.Interval = 5000;
882 tipdown_timer.Tick += new EventHandler (PopDownTip);
884 return tipdown_timer;
888 private void ToolBar_MouseHover (object sender, EventArgs e)
893 if (tip_window == null)
894 tip_window = new ToolTip ();
896 ToolBarItem item = ItemAtPoint (PointToClient (Control.MousePosition));
899 if (item == null || item.Button.ToolTipText.Length == 0)
902 tip_window.Present (this, item.Button.ToolTipText);
903 TipDownTimer.Start ();
906 private void ToolBar_MouseLeave (object sender, EventArgs e)
908 if (tipdown_timer != null)
909 tipdown_timer.Dispose ();
910 tipdown_timer = null;
911 if (tip_window != null)
912 tip_window.Dispose ();
915 if (!Enabled || current_item == null)
918 current_item.Hilight = false;
922 private void ToolBar_MouseMove (object sender, MouseEventArgs me)
927 if (tip_window != null && tip_window.Visible) {
928 TipDownTimer.Stop ();
929 TipDownTimer.Start ();
932 Point loc = new Point (me.X, me.Y);
935 // If the button was pressed and we leave, release the
936 // button press and vice versa
937 foreach (ToolBarItem item in items) {
939 (item.Inside != item.Rectangle.Contains (loc))) {
940 item.Inside = item.Rectangle.Contains (loc);
941 item.Hilight = false;
948 if (current_item != null && current_item.Rectangle.Contains (loc)) {
949 if (ThemeEngine.Current.ToolBarHasHotElementStyles (this)) {
950 if (current_item.Hilight || (!ThemeEngine.Current.ToolBarHasHotCheckedElementStyles && current_item.Button.Pushed) || !current_item.Button.Enabled)
952 current_item.Hilight = true;
955 if (tip_window != null) {
956 if (tip_window.Visible) {
957 tip_window.Hide (this);
958 TipDownTimer.Stop ();
960 current_item = ItemAtPoint (loc);
961 if (current_item != null && current_item.Button.ToolTipText.Length > 0) {
962 tip_window.Present (this, current_item.Button.ToolTipText);
963 TipDownTimer.Start ();
967 if (ThemeEngine.Current.ToolBarHasHotElementStyles (this)) {
968 foreach (ToolBarItem item in items) {
969 if (item.Rectangle.Contains (loc) && item.Button.Enabled) {
971 if (current_item.Hilight || (!ThemeEngine.Current.ToolBarHasHotCheckedElementStyles && current_item.Button.Pushed))
973 current_item.Hilight = true;
975 else if (item.Hilight) {
976 item.Hilight = false;
983 internal override void OnPaintInternal (PaintEventArgs pevent)
985 if (GetStyle (ControlStyles.UserPaint))
988 ThemeEngine.Current.DrawToolBar (pevent.Graphics, pevent.ClipRectangle, this);
990 // Toolbars do not raise OnPaint unless UserPaint is set
991 pevent.Handled = true;
994 internal void Redraw (bool recalculate)
996 Redraw (recalculate, true);
999 internal void Redraw (bool recalculate, bool force)
1001 bool invalidate = true;
1004 invalidate = LayoutToolBar ();
1006 if (force || invalidate)
1010 internal bool SizeSpecified {
1011 get { return size_specified; }
1014 internal bool Vertical {
1015 get { return (Dock == DockStyle.Left) || (Dock == DockStyle.Right); }
1018 internal const int text_padding = 3;
1020 private Size CalcButtonSize ()
1022 if (Buttons.Count == 0)
1025 string longest_text = Buttons [0].Text;
1026 for (int i = 1; i < Buttons.Count; i++) {
1027 if (Buttons[i].Text.Length > longest_text.Length)
1028 longest_text = Buttons[i].Text;
1031 Size size = Size.Empty;
1032 if (longest_text != null && longest_text.Length > 0) {
1033 SizeF sz = TextRenderer.MeasureString (longest_text, Font);
1034 if (sz != SizeF.Empty)
1035 size = new Size ((int) Math.Ceiling (sz.Width) + 2 * text_padding, (int) Math.Ceiling (sz.Height));
1038 Size img_size = ImageList == null ? new Size (16, 16) : ImageSize;
1040 Theme theme = ThemeEngine.Current;
1041 int imgWidth = img_size.Width + 2 * theme.ToolBarImageGripWidth;
1042 int imgHeight = img_size.Height + 2 * theme.ToolBarImageGripWidth;
1044 if (text_alignment == ToolBarTextAlign.Right) {
1045 size.Width = imgWidth + size.Width;
1046 size.Height = (size.Height > imgHeight) ? size.Height : imgHeight;
1048 size.Height = imgHeight + size.Height;
1049 size.Width = (size.Width > imgWidth) ? size.Width : imgWidth;
1052 size.Width += theme.ToolBarImageGripWidth;
1053 size.Height += theme.ToolBarImageGripWidth;
1057 // Flat toolbars disregard specified sizes. Normal toolbars grow the
1058 // button size to be at least large enough to show the image.
1059 private Size AdjustedButtonSize {
1063 if (default_size.IsEmpty || Appearance == ToolBarAppearance.Normal)
1066 size = default_size;
1068 if (size_specified) {
1069 if (Appearance == ToolBarAppearance.Flat)
1070 size = CalcButtonSize ();
1072 int grip = ThemeEngine.Current.ToolBarImageGripWidth;
1073 if (size.Width < ImageSize.Width + 2 * grip )
1074 size.Width = ImageSize.Width + 2 * grip;
1075 if (size.Height < ImageSize.Height + 2 * grip)
1076 size.Height = ImageSize.Height + 2 * grip;
1083 private bool LayoutToolBar ()
1085 bool changed = false;
1086 Theme theme = ThemeEngine.Current;
1087 int x = theme.ToolBarGripWidth;
1088 int y = theme.ToolBarGripWidth;
1090 Size adjusted_size = AdjustedButtonSize;
1092 int calculated_size = (Vertical ? adjusted_size.Width : adjusted_size.Height) + theme.ToolBarGripWidth;
1094 int separator_index = -1;
1096 items = new ToolBarItem [buttons.Count];
1098 for (int i = 0; i < buttons.Count; i++) {
1099 ToolBarButton button = buttons [i];
1101 ToolBarItem item = new ToolBarItem (button);
1104 if (!button.Visible)
1107 if (size_specified && (button.Style != ToolBarButtonStyle.Separator))
1108 changed = item.Layout (adjusted_size);
1110 changed = item.Layout (Vertical, calculated_size);
1112 bool is_separator = button.Style == ToolBarButtonStyle.Separator;
1115 if (y + item.Rectangle.Height < Height || is_separator || !Wrappable) {
1116 if (item.Location.X != x || item.Location.Y != y)
1118 item.Location = new Point (x, y);
1119 y += item.Rectangle.Height;
1121 separator_index = i;
1122 } else if (separator_index > 0) {
1123 i = separator_index;
1124 separator_index = -1;
1125 y = theme.ToolBarGripWidth;
1126 x += calculated_size;
1128 y = theme.ToolBarGripWidth;
1129 x += calculated_size;
1130 if (item.Location.X != x || item.Location.Y != y)
1132 item.Location = new Point (x, y);
1133 y += item.Rectangle.Height;
1136 if (x + item.Rectangle.Width < Width || is_separator || !Wrappable) {
1137 if (item.Location.X != x || item.Location.Y != y)
1139 item.Location = new Point (x, y);
1140 x += item.Rectangle.Width;
1142 separator_index = i;
1143 } else if (separator_index > 0) {
1144 i = separator_index;
1145 separator_index = -1;
1146 x = theme.ToolBarGripWidth;
1147 y += calculated_size;
1149 x = theme.ToolBarGripWidth;
1150 y += calculated_size;
1151 if (item.Location.X != x || item.Location.Y != y)
1153 item.Location = new Point (x, y);
1154 x += item.Rectangle.Width;
1163 calculated_size += Vertical ? x : y;
1165 if (IsHandleCreated) {
1167 Width = calculated_size;
1169 Height = calculated_size;
1174 #endregion Private Methods
1177 public class ToolBarButtonCollection : IList, ICollection, IEnumerable
1179 #region instance variables
1180 private ArrayList list; // ToolBarButton list
1181 private ToolBar owner; // ToolBar associated to Collection
1182 private bool redraw; // Flag if needs to redraw after add/remove operations
1185 #region UIA Framework Events
1186 static object UIACollectionChangedEvent = new object ();
1188 internal event CollectionChangeEventHandler UIACollectionChanged {
1189 add { owner.Events.AddHandler (UIACollectionChangedEvent, value); }
1190 remove { owner.Events.RemoveHandler (UIACollectionChangedEvent, value); }
1193 internal void OnUIACollectionChanged (CollectionChangeEventArgs e)
1195 CollectionChangeEventHandler eh
1196 = (CollectionChangeEventHandler) owner.Events [UIACollectionChangedEvent];
1202 #region constructors
1203 public ToolBarButtonCollection (ToolBar owner)
1205 this.list = new ArrayList ();
1214 get { return list.Count; }
1217 public bool IsReadOnly {
1218 get { return list.IsReadOnly; }
1221 public virtual ToolBarButton this [int index] {
1222 get { return (ToolBarButton) list [index]; }
1224 // UIA Framework Event: Button Removed
1225 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
1227 value.SetParent (owner);
1228 list [index] = value;
1229 owner.Redraw (true);
1231 // UIA Framework Event: Button Added
1232 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
1236 public virtual ToolBarButton this[string key] {
1238 if (string.IsNullOrEmpty (key))
1241 foreach (ToolBarButton b in list)
1242 if (string.Compare (b.Name, key, true) == 0)
1249 bool ICollection.IsSynchronized {
1250 get { return list.IsSynchronized; }
1253 object ICollection.SyncRoot {
1254 get { return list.SyncRoot; }
1257 bool IList.IsFixedSize {
1258 get { return list.IsFixedSize; }
1261 object IList.this [int index] {
1262 get { return this [index]; }
1264 if (! (value is ToolBarButton))
1265 throw new ArgumentException("Not of type ToolBarButton", "value");
1266 this [index] = (ToolBarButton) value;
1272 public int Add (string text)
1274 ToolBarButton button = new ToolBarButton (text);
1275 return this.Add (button);
1278 public int Add (ToolBarButton button)
1281 button.SetParent (owner);
1282 result = list.Add (button);
1284 owner.Redraw (true);
1286 // UIA Framework Event: Button Added
1287 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, result));
1292 public void AddRange (ToolBarButton [] buttons)
1296 foreach (ToolBarButton button in buttons)
1301 owner.Redraw (true);
1305 public void Clear ()
1308 owner.Redraw (false);
1310 // UIA Framework Event: Button Cleared
1311 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, -1));
1314 public bool Contains (ToolBarButton button)
1316 return list.Contains (button);
1319 public virtual bool ContainsKey (string key)
1321 return !(this[key] == null);
1324 public IEnumerator GetEnumerator ()
1326 return list.GetEnumerator ();
1329 void ICollection.CopyTo (Array dest, int index)
1331 list.CopyTo (dest, index);
1334 int IList.Add (object button)
1336 if (! (button is ToolBarButton)) {
1337 throw new ArgumentException("Not of type ToolBarButton", "button");
1340 return this.Add ((ToolBarButton) button);
1343 bool IList.Contains (object button)
1345 if (! (button is ToolBarButton)) {
1346 throw new ArgumentException("Not of type ToolBarButton", "button");
1349 return this.Contains ((ToolBarButton) button);
1352 int IList.IndexOf (object button)
1354 if (! (button is ToolBarButton)) {
1355 throw new ArgumentException("Not of type ToolBarButton", "button");
1358 return this.IndexOf ((ToolBarButton) button);
1361 void IList.Insert (int index, object button)
1363 if (! (button is ToolBarButton)) {
1364 throw new ArgumentException("Not of type ToolBarButton", "button");
1367 this.Insert (index, (ToolBarButton) button);
1370 void IList.Remove (object button)
1372 if (! (button is ToolBarButton)) {
1373 throw new ArgumentException("Not of type ToolBarButton", "button");
1376 this.Remove ((ToolBarButton) button);
1379 public int IndexOf (ToolBarButton button)
1381 return list.IndexOf (button);
1384 public virtual int IndexOfKey (string key)
1386 return IndexOf (this[key]);
1389 public void Insert (int index, ToolBarButton button)
1391 list.Insert (index, button);
1392 owner.Redraw (true);
1394 // UIA Framework Event: Button Added
1395 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
1398 public void Remove (ToolBarButton button)
1400 list.Remove (button);
1401 owner.Redraw (true);
1404 public void RemoveAt (int index)
1406 list.RemoveAt (index);
1407 owner.Redraw (true);
1409 // UIA Framework Event: Button Removed
1410 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
1413 public virtual void RemoveByKey (string key)
1424 // Because same button can be added to toolbar multiple times, we need to maintain
1425 // a list of button information for each positions.
1426 internal class ToolBarItem : Component
1428 #region Instance variables
1430 private ToolBar toolbar; // Parent toolbar
1431 private ToolBarButton button; // Associated toolBar button
1432 private Rectangle bounds; // Toolbar button bounds
1433 private Rectangle image_rect; // Image button bounds
1434 private Rectangle text_rect; // Text button bounds
1436 private bool dd_pressed = false; // to check for a mouse down on dropdown rect
1437 private bool inside = false; // to handle the mouse move event with mouse pressed
1438 private bool hilight = false; // to hilight buttons in flat style
1439 private bool pressed = false; // this is to check for mouse down on a button
1443 #region Constructors
1445 public ToolBarItem (ToolBarButton button)
1447 this.toolbar = button.Parent;
1448 this.button = button;
1451 #endregion Constructors
1455 public ToolBarButton Button {
1456 get { return this.button; }
1459 public Rectangle Rectangle {
1461 if (!button.Visible || toolbar == null)
1462 return Rectangle.Empty;
1464 if (button.Style == ToolBarButtonStyle.DropDownButton && toolbar.DropDownArrows) {
1465 Rectangle result = bounds;
1466 result.Width += ThemeEngine.Current.ToolBarDropDownWidth;
1472 set { this.bounds = value; }
1475 public Point Location {
1476 get { return bounds.Location; }
1477 set { bounds.Location = value; }
1480 public Rectangle ImageRectangle {
1482 Rectangle result = image_rect;
1483 result.X += bounds.X;
1484 result.Y += bounds.Y;
1489 public Rectangle TextRectangle {
1491 Rectangle result = text_rect;
1492 result.X += bounds.X;
1493 result.Y += bounds.Y;
1498 private Size TextSize {
1500 StringFormat text_format = new StringFormat ();
1501 text_format.HotkeyPrefix = HotkeyPrefix.Hide;
1503 SizeF sz = TextRenderer.MeasureString (button.Text, toolbar.Font, SizeF.Empty, text_format);
1504 if (sz == SizeF.Empty)
1506 return new Size ((int) Math.Ceiling (sz.Width) + 2 * ToolBar.text_padding, (int) Math.Ceiling (sz.Height));
1510 public bool Pressed {
1511 get { return (pressed && inside); }
1512 set { pressed = value; }
1515 public bool DDPressed {
1516 get { return dd_pressed; }
1517 set { dd_pressed = value; }
1520 public bool Inside {
1521 get { return inside; }
1522 set { inside = value; }
1525 public bool Hilight {
1526 get { return hilight; }
1528 if (hilight == value)
1536 #endregion Properties
1540 public Size CalculateSize ()
1542 Theme theme = ThemeEngine.Current;
1544 int ht = toolbar.ButtonSize.Height + 2 * theme.ToolBarGripWidth;
1546 if (button.Style == ToolBarButtonStyle.Separator)
1547 return new Size (theme.ToolBarSeparatorWidth, ht);
1550 if (TextSize.IsEmpty && (button.Image == null))
1551 size = toolbar.default_size;
1555 Size image_size = (toolbar.ImageSize == Size.Empty) ? new Size (16, 16) : toolbar.ImageSize;
1557 int image_width = image_size.Width + 2 * theme.ToolBarImageGripWidth;
1558 int image_height = image_size.Height + 2 * theme.ToolBarImageGripWidth;
1560 if (toolbar.TextAlign == ToolBarTextAlign.Right) {
1561 size.Width = image_width + size.Width;
1562 size.Height = (size.Height > image_height) ? size.Height : image_height;
1564 size.Height = image_height + size.Height;
1565 size.Width = (size.Width > image_width) ? size.Width : image_width;
1568 size.Width += theme.ToolBarGripWidth;
1569 size.Height += theme.ToolBarGripWidth;
1574 public bool Layout (bool vertical, int calculated_size)
1576 if (toolbar == null || !button.Visible)
1579 Size psize = toolbar.ButtonSize;
1581 if ((!toolbar.SizeSpecified) || (button.Style == ToolBarButtonStyle.Separator)) {
1582 size = CalculateSize ();
1584 if (size.Width == 0 || size.Height == 0)
1588 size.Width = calculated_size;
1590 size.Height = calculated_size;
1592 return Layout (size);
1595 public bool Layout (Size size)
1597 if (toolbar == null || !button.Visible)
1602 Size image_size = (toolbar.ImageSize == Size.Empty) ? new Size (16, 16) : toolbar.ImageSize;
1603 int grip = ThemeEngine.Current.ToolBarImageGripWidth;
1605 Rectangle new_image_rect, new_text_rect;
1607 if (toolbar.TextAlign == ToolBarTextAlign.Underneath) {
1608 new_image_rect = new Rectangle ((bounds.Size.Width - image_size.Width) / 2 - grip, 0, image_size.Width + 2 + grip, image_size.Height + 2 * grip);
1609 new_text_rect = new Rectangle (0, new_image_rect.Height, bounds.Size.Width, bounds.Size.Height - new_image_rect.Height - 2 * grip);
1611 new_image_rect = new Rectangle (0, 0, image_size.Width + 2 * grip, image_size.Height + 2 * grip);
1612 new_text_rect = new Rectangle (new_image_rect.Width, 0, bounds.Size.Width - new_image_rect.Width, bounds.Size.Height - 2 * grip);
1615 bool changed = false;
1617 if (new_image_rect != image_rect || new_text_rect != text_rect)
1620 image_rect = new_image_rect;
1621 text_rect = new_text_rect;
1626 public void Invalidate ()
1628 if (toolbar != null)
1629 toolbar.Invalidate (Rectangle);