* TabControl.cs: Show the tooltip depending on the value
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ToolBar.cs
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:
10 //
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 //
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.
21 //
22 // Author:
23 //      Ravindra (rkumar@novell.com)
24 //      Mike Kestner <mkestner@novell.com>
25 //      Everaldo Canuto <ecanuto@novell.com>
26 //
27 // Copyright (C) 2004-2006  Novell, Inc. (http://www.novell.com)
28 //
29
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;
37
38 namespace System.Windows.Forms
39 {
40 #if NET_2_0
41         [ComVisible (true)]
42         [ClassInterface (ClassInterfaceType.AutoDispatch)]
43 #endif
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
48         {
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
55
56                 #region Events
57                 static object ButtonClickEvent = new object ();
58                 static object ButtonDropDownEvent = new object ();
59
60 #if NET_2_0
61                 [Browsable (true)]
62                 [EditorBrowsable (EditorBrowsableState.Always)]
63                 public new event EventHandler AutoSizeChanged {
64                         add { base.AutoSizeChanged += value; }
65                         remove { base.AutoSizeChanged -= value; }
66                 }
67 #endif
68
69                 [Browsable (false)]
70                 [EditorBrowsable (EditorBrowsableState.Never)]
71                 public new event EventHandler BackColorChanged {
72                         add { base.BackColorChanged += value; }
73                         remove { base.BackColorChanged -= value; }
74                 }
75
76                 [Browsable (false)]
77                 [EditorBrowsable (EditorBrowsableState.Never)]
78                 public new event EventHandler BackgroundImageChanged {
79                         add { base.BackgroundImageChanged += value; }
80                         remove { base.BackgroundImageChanged -= value; }
81                 }
82
83 #if NET_2_0
84                 [Browsable (false)]
85                 [EditorBrowsable (EditorBrowsableState.Never)]
86                 public new event EventHandler BackgroundImageLayoutChanged {
87                         add { base.BackgroundImageLayoutChanged += value; }
88                         remove { base.BackgroundImageLayoutChanged -= value; }
89                 }
90 #endif
91
92                 public event ToolBarButtonClickEventHandler ButtonClick {
93                         add { Events.AddHandler (ButtonClickEvent, value); }
94                         remove {Events.RemoveHandler (ButtonClickEvent, value); }
95                 }
96
97                 public event ToolBarButtonClickEventHandler ButtonDropDown {
98                         add { Events.AddHandler (ButtonDropDownEvent, value); }
99                         remove {Events.RemoveHandler (ButtonDropDownEvent, value); }
100                 }
101
102                 [Browsable (false)]
103                 [EditorBrowsable (EditorBrowsableState.Never)]
104                 public new event EventHandler ForeColorChanged {
105                         add { base.ForeColorChanged += value; }
106                         remove { base.ForeColorChanged -= value; }
107                 }
108
109                 [Browsable (false)]
110                 [EditorBrowsable (EditorBrowsableState.Never)]
111                 public new event EventHandler ImeModeChanged {
112                         add { base.ImeModeChanged += value; }
113                         remove { base.ImeModeChanged -= value; }
114                 }
115
116                 [Browsable (false)]
117                 [EditorBrowsable (EditorBrowsableState.Never)]
118                 public new event PaintEventHandler Paint {
119                         add { base.Paint += value; }
120                         remove { base.Paint -= value; }
121                 }
122
123                 [Browsable (false)]
124                 [EditorBrowsable (EditorBrowsableState.Never)]
125                 public new event EventHandler RightToLeftChanged {
126                         add { base.RightToLeftChanged += value; }
127                         remove { base.RightToLeftChanged -= value; }
128                 }
129
130                 [Browsable (false)]
131                 [EditorBrowsable (EditorBrowsableState.Never)]
132                 public new event EventHandler TextChanged {
133                         add { base.TextChanged += value; }
134                         remove { base.TextChanged -= value; }
135                 }
136                 #endregion Events
137
138                 #region Constructor
139                 public ToolBar ()
140                 {
141                         background_color = ThemeEngine.Current.DefaultControlBackColor;
142                         foreground_color = ThemeEngine.Current.DefaultControlForeColor;
143                         buttons = new ToolBarButtonCollection (this);
144                         Dock = DockStyle.Top;
145                         
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);
154
155                         TabStop = false;
156                         
157                         SetStyle (ControlStyles.UserPaint, false);
158                         SetStyle (ControlStyles.FixedHeight, true);
159                         SetStyle (ControlStyles.FixedWidth, false);
160                 }
161                 #endregion Constructor
162
163                 #region protected Properties
164                 protected override CreateParams CreateParams {
165                         get { 
166                                 CreateParams create_params = base.CreateParams;
167                                 
168                                 if (appearance == ToolBarAppearance.Flat) {
169                                         create_params.Style |= (int) ToolBarStyles.TBSTYLE_FLAT;
170                                 }
171                                 
172                                 return create_params;
173                         }
174                 }
175
176                 protected override ImeMode DefaultImeMode {
177                         get { return ImeMode.Disable; }
178                 }
179
180                 protected override Size DefaultSize {
181                         get { return ThemeEngine.Current.ToolBarDefaultSize; }
182                 }
183
184 #if NET_2_0
185                 [EditorBrowsable (EditorBrowsableState.Never)]
186                 protected override bool DoubleBuffered {
187                         get { return base.DoubleBuffered; }
188                         set { base.DoubleBuffered = value; }
189                 }
190 #endif
191                 #endregion
192
193                 ToolBarAppearance appearance = ToolBarAppearance.Normal;
194
195                 #region Public Properties
196                 [DefaultValue (ToolBarAppearance.Normal)]
197                 [Localizable (true)]
198                 public ToolBarAppearance Appearance {
199                         get { return appearance; }
200                         set {
201                                 if (value == appearance)
202                                         return;
203
204                                 appearance = value;
205                                 Redraw (true);
206                         }
207                 }
208
209                 bool autosize = true;
210
211 #if NET_2_0
212                 [Browsable (true)]
213                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
214                 [EditorBrowsable (EditorBrowsableState.Always)]
215 #endif
216                 [DefaultValue (true)]
217                 [Localizable (true)]
218                 public 
219 #if NET_2_0
220                 override
221 #endif
222                 bool AutoSize {
223                         get { return autosize; }
224                         set {
225                                 if (value == autosize)
226                                         return;
227
228                                 autosize = value;
229                                 
230                                 if (IsHandleCreated)
231                                         Redraw (true);
232                         }
233                 }
234
235                 [Browsable (false)]
236                 [EditorBrowsable (EditorBrowsableState.Never)]
237                 public override Color BackColor {
238                         get { return background_color; }
239                         set {
240                                 if (value == background_color)
241                                         return;
242
243                                 background_color = value;
244                                 OnBackColorChanged (EventArgs.Empty);
245                                 Redraw (false);
246                         }
247                 }
248
249                 [Browsable (false)]
250                 [EditorBrowsable (EditorBrowsableState.Never)]
251                 public override Image BackgroundImage {
252                         get { return base.BackgroundImage; }
253                         set { base.BackgroundImage = value; }
254                 }
255
256 #if NET_2_0
257                 [Browsable (false)]
258                 [EditorBrowsable (EditorBrowsableState.Never)]
259                 public override ImageLayout BackgroundImageLayout {
260                         get { return base.BackgroundImageLayout; }
261                         set { base.BackgroundImageLayout = value; }
262                 }
263 #endif
264
265                 [DefaultValue (BorderStyle.None)]
266                 [DispIdAttribute (-504)]
267                 public BorderStyle BorderStyle {
268                         get { return InternalBorderStyle; }
269                         set { InternalBorderStyle = value; }
270                 }
271
272                 ToolBarButtonCollection buttons;
273
274                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
275                 [Localizable (true)]
276                 [MergableProperty (false)]
277                 public ToolBarButtonCollection Buttons {
278                         get { return buttons; }
279                 }
280
281                 Size button_size;
282
283                 [Localizable (true)]
284                 [RefreshProperties (RefreshProperties.All)]
285                 public Size ButtonSize {
286                         get {
287                                 if (!button_size.IsEmpty)
288                                         return button_size; 
289                                 
290                                 if (buttons.Count == 0)
291                                         return new Size (39, 36);
292                                         
293                                 Size result = CalcButtonSize ();
294                                 if (result.IsEmpty)
295                                         return new Size (24, 22);
296                                 else
297                                         return result;
298                         }
299                         set {
300                                 size_specified = value != Size.Empty;
301                                 if (button_size == value)
302                                         return;
303
304                                 button_size = value;
305                                 Redraw (true);
306                         }
307                 }
308
309                 bool divider = true;
310
311                 [DefaultValue (true)]
312                 public bool Divider {
313                         get { return divider; }
314                         set {
315                                 if (value == divider)
316                                         return;
317
318                                 divider = value;
319                                 Redraw (false);
320                         }
321                 }
322
323                 [DefaultValue (DockStyle.Top)]
324                 [Localizable (true)]
325                 public override DockStyle Dock {
326                         get { return base.Dock; }
327                         set {
328                                 if (base.Dock == value) {
329                                         // Call base anyways so layout_type gets set correctly
330                                         if (value != DockStyle.None)
331                                                 base.Dock = value;
332                                         return;
333                                 }
334                                         
335                                 if (Vertical) {
336                                         SetStyle (ControlStyles.FixedWidth, AutoSize);
337                                         SetStyle (ControlStyles.FixedHeight, false);
338                                 } else {
339                                         SetStyle (ControlStyles.FixedHeight, AutoSize);
340                                         SetStyle (ControlStyles.FixedWidth, false);
341                                 }
342                                 
343                                 LayoutToolBar ();
344                                 
345                                 base.Dock = value;
346                         }
347                 }
348
349                 bool drop_down_arrows = true;
350
351                 [DefaultValue (false)]
352                 [Localizable (true)]
353                 public bool DropDownArrows {
354                         get { return drop_down_arrows; }
355                         set {
356                                 if (value == drop_down_arrows)
357                                         return;
358
359                                 drop_down_arrows = value;
360                                 Redraw (true);
361                         }
362                 }
363
364                 [Browsable (false)]
365                 [EditorBrowsable (EditorBrowsableState.Never)]
366                 public override Color ForeColor {
367                         get { return foreground_color; }
368                         set {
369                                 if (value == foreground_color)
370                                         return;
371
372                                 foreground_color = value;
373                                 OnForeColorChanged (EventArgs.Empty);
374                                 Redraw (false);
375                         }
376                 }
377
378                 ImageList image_list;
379
380                 [DefaultValue (null)]
381                 public ImageList ImageList {
382                         get { return image_list; }
383                         set { 
384                                 if (image_list == value)
385                                         return;
386                                 image_list = value;
387                                 Redraw (true);
388                         }
389                 }
390
391                 [Browsable (false)]
392                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
393                 [EditorBrowsable (EditorBrowsableState.Advanced)]
394                 public Size ImageSize {
395                         get {
396                                 if (ImageList == null)
397                                         return Size.Empty;
398
399                                 return ImageList.ImageSize;
400                         }
401                 }
402
403                 // XXX this should probably go away and it should call
404                 // into Control.ImeMode instead.
405                 ImeMode ime_mode = ImeMode.Disable;
406
407                 [Browsable (false)]
408                 [EditorBrowsable (EditorBrowsableState.Never)]
409                 public new ImeMode ImeMode {
410                         get { return ime_mode; }
411                         set {
412                                 if (value == ime_mode)
413                                         return;
414
415                                 ime_mode = value;
416                                 OnImeModeChanged (EventArgs.Empty);
417                         }
418                 }
419
420                 [Browsable (false)]
421                 [EditorBrowsable (EditorBrowsableState.Never)]
422                 public override RightToLeft RightToLeft {
423                         get { return base.RightToLeft; }
424                         set {
425                                 if (value == base.RightToLeft)
426                                         return;
427
428                                 base.RightToLeft = value;
429                                 OnRightToLeftChanged (EventArgs.Empty);
430                         }
431                 }
432
433                 // Default value is "false" but after make a test in .NET we get "true" result as default.  
434                 bool show_tooltips = true;
435
436                 [DefaultValue (false)]
437                 [Localizable (true)]
438                 public bool ShowToolTips {
439                         get { return show_tooltips; }
440                         set { show_tooltips = value; }
441                 }
442
443                 [DefaultValue (false)]
444                 public new bool TabStop {
445                         get { return base.TabStop; }
446                         set { base.TabStop = value; }
447                 }
448
449                 [Bindable (false)]
450                 [Browsable (false)]
451                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
452                 [EditorBrowsable (EditorBrowsableState.Never)]
453                 public override string Text {
454                         get { return base.Text; } 
455                         set {
456                                 if (value == base.Text)
457                                         return;
458
459                                 base.Text = value;
460                                 Redraw (true);
461                         }
462                 }
463
464                 ToolBarTextAlign text_alignment = ToolBarTextAlign.Underneath;
465
466                 [DefaultValue (ToolBarTextAlign.Underneath)]
467                 [Localizable (true)]
468                 public ToolBarTextAlign TextAlign {
469                         get { return text_alignment; }
470                         set {
471                                 if (value == text_alignment)
472                                         return;
473
474                                 text_alignment = value;
475                                 Redraw (true);
476                         }
477                 }
478
479                 bool wrappable = true;
480
481                 [DefaultValue (true)]
482                 [Localizable (true)]
483                 public bool Wrappable {
484                         get { return wrappable; }
485                         set {
486                                 if (value == wrappable)
487                                         return;
488
489                                 wrappable = value;
490                                 Redraw (true);
491                         }
492                 }
493                 #endregion Public Properties
494
495                 #region Public Methods
496                 public override string ToString ()
497                 {
498                         int count = this.Buttons.Count;
499
500                         if (count == 0)
501                                 return string.Format ("System.Windows.Forms.ToolBar, Buttons.Count: 0");
502                         else
503                                 return string.Format ("System.Windows.Forms.ToolBar, Buttons.Count: {0}, Buttons[0]: {1}",
504                                                       count, this.Buttons [0].ToString ());
505                 }
506                 #endregion Public Methods
507
508                 #region Protected Methods
509                 protected override void CreateHandle ()
510                 {
511                         base.CreateHandle ();
512                         default_size = CalcButtonSize ();
513                         
514                         // In win32 the recalculate size only happens for not flat style
515                         if (appearance != ToolBarAppearance.Flat)
516                                 Redraw (true);
517                 }
518
519                 protected override void Dispose (bool disposing)
520                 {
521                         if (disposing)
522                                 ImageList = null;
523
524                         base.Dispose (disposing);
525                 }
526
527 #if NET_2_0
528                 private ToolBarButton button_for_focus = null;
529                 
530                 internal void UIAPerformClick (ToolBarButton button)
531                 {
532                         ToolBarItem previous_item = current_item;
533                         current_item = null;
534                         
535                         foreach (ToolBarItem item in items)
536                                 if (item.Button == button) {
537                                         current_item = item;
538                                         break;
539                                 }
540
541                         try {
542                                 if (current_item == null)
543                                         throw new ArgumentException ("button", "The button specified is not part of this toolbar");
544                                 PerformButtonClick (new ToolBarButtonClickEventArgs (button));
545                         } finally {
546                                 current_item = previous_item;
547                         }
548                 }
549 #endif
550                 
551                 void PerformButtonClick (ToolBarButtonClickEventArgs e)
552                 {
553                         // Only change pushed for ToogleButton
554                         if (e.Button.Style == ToolBarButtonStyle.ToggleButton) {
555                                 if (! e.Button.Pushed)
556                                         e.Button.Pushed = true;
557                                 else
558                                         e.Button.Pushed = false;
559                         }
560                         
561                         current_item.Pressed = false;
562                         current_item.Invalidate ();
563                         
564 #if NET_2_0
565                         button_for_focus = current_item.Button;
566                         button_for_focus.UIAHasFocus = true;
567 #endif
568                         OnButtonClick (e);
569                 }
570
571                 protected virtual void OnButtonClick (ToolBarButtonClickEventArgs e)
572                 {                       
573                         ToolBarButtonClickEventHandler eh = (ToolBarButtonClickEventHandler)(Events [ButtonClickEvent]);
574                         if (eh != null)
575                                 eh (this, e);
576                 }
577
578                 protected virtual void OnButtonDropDown (ToolBarButtonClickEventArgs e) 
579                 {
580                         ToolBarButtonClickEventHandler eh = (ToolBarButtonClickEventHandler)(Events [ButtonDropDownEvent]);
581                         if (eh != null)
582                                 eh (this, e);
583
584                         if (e.Button.DropDownMenu == null)
585                                 return;
586
587                         ShowDropDownMenu (current_item);
588                 }
589
590                 internal void ShowDropDownMenu (ToolBarItem item)
591                 {
592                         Point loc = new Point (item.Rectangle.X + 1, item.Rectangle.Bottom + 1);
593                         ((ContextMenu) item.Button.DropDownMenu).Show (this, loc);
594
595                         item.DDPressed = false;
596                         item.Hilight = false;
597                         item.Invalidate ();
598                 }
599
600                 protected override void OnFontChanged (EventArgs e)
601                 {
602                         base.OnFontChanged (e);
603                         Redraw (true);
604                 }
605
606                 protected override void OnHandleCreated (EventArgs e)
607                 {
608                         base.OnHandleCreated (e);
609                 }
610
611                 protected override void OnResize (EventArgs e)
612                 {
613                         base.OnResize (e);
614                         LayoutToolBar ();
615                 }
616
617 #if NET_2_0
618                 protected override void ScaleControl (SizeF factor, BoundsSpecified specified)
619                 {
620                         specified &= ~BoundsSpecified.Height;
621                         
622                         base.ScaleControl (factor, specified);
623                 }
624
625                 [EditorBrowsable (EditorBrowsableState.Never)]
626                 protected override void ScaleCore (float dx, float dy)
627                 {
628                         dy = 1.0f;
629                         
630                         base.ScaleCore (dx, dy);
631                 }
632 #endif
633
634                 private int requested_size = -1;
635
636                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
637                 {
638                         if (Vertical) {
639                                 if (!AutoSize && (requested_size != width) && ((specified & BoundsSpecified.Width) != BoundsSpecified.None)) 
640                                         requested_size = width;
641                         } else {
642                                 if (!AutoSize && (requested_size != height) && ((specified & BoundsSpecified.Height) != BoundsSpecified.None)) 
643                                         requested_size = height;
644                         }
645                         
646                         base.SetBoundsCore (x, y, width, height, specified);
647                 }
648
649                 protected override void WndProc (ref Message m)
650                 {
651                         base.WndProc (ref m);
652                 }
653
654                 internal override bool InternalPreProcessMessage (ref Message msg)
655                 {
656                         if (msg.Msg == (int)Msg.WM_KEYDOWN) {
657                                 Keys key_data = (Keys)msg.WParam.ToInt32();
658                                 if (HandleKeyDown (ref msg, key_data))
659                                         return true;
660                         } 
661                         return base.InternalPreProcessMessage (ref msg);
662                 }
663                         
664                 #endregion Protected Methods
665
666                 #region Private Methods
667                 internal int CurrentItem {
668                         get {
669                                 return Array.IndexOf (items, current_item);
670                         }
671                         set {
672                                 if (current_item != null)
673                                         current_item.Hilight = false;
674
675                                 current_item = value == -1 ? null : items [value];
676
677                                 if (current_item != null)
678                                         current_item.Hilight = true;
679                         }
680
681                 }
682
683                 private void FocusChanged (object sender, EventArgs args)
684                 {
685 #if NET_2_0
686                         if (!Focused && button_for_focus != null)
687                                 button_for_focus.UIAHasFocus = false;
688                         button_for_focus = null;
689 #endif
690                         
691                         if (Appearance != ToolBarAppearance.Flat || Buttons.Count == 0)
692                                 return;
693
694                         ToolBarItem prelit = null;
695                         foreach (ToolBarItem item in items) {
696                                 if (item.Hilight) {
697                                         prelit = item;
698                                         break;
699                                 }
700                         }
701
702                         if (Focused && prelit == null) {
703                                 foreach (ToolBarItem item in items) {
704                                         if (item.Button.Enabled) {
705                                                 item.Hilight = true;
706                                                 break;
707                                         }
708                                 }
709                         } else if (prelit != null) {
710                                 prelit.Hilight = false;
711                         }
712                 }
713
714                 private bool HandleKeyDown (ref Message msg, Keys key_data)
715                 {
716                         if (Appearance != ToolBarAppearance.Flat || Buttons.Count == 0)
717                                 return false;
718
719                         // Handle the key as needed if the current item is a dropdownbutton.
720                         if (HandleKeyOnDropDown (ref msg, key_data))
721                                 return true;
722
723                         switch (key_data) {
724                                 case Keys.Left:
725                                 case Keys.Up:
726                                         HighlightButton (-1);
727                                         return true;
728                                 case Keys.Right:
729                                 case Keys.Down:
730                                         HighlightButton (1);
731                                         return true;
732                                 case Keys.Enter:
733                                 case Keys.Space:
734                                         if (current_item != null) {
735                                                 OnButtonClick (new ToolBarButtonClickEventArgs (current_item.Button));
736                                                 return true;
737                                         }
738                                         break;
739                         }
740
741                         return false;
742                 }
743
744                 bool HandleKeyOnDropDown (ref Message msg, Keys key_data)
745                 {
746                         if (current_item == null || current_item.Button.Style != ToolBarButtonStyle.DropDownButton ||
747                                         current_item.Button.DropDownMenu == null)
748                                 return false;
749
750                         Menu dropdown_menu = current_item.Button.DropDownMenu;
751
752                         if (dropdown_menu.Tracker.active) {
753                                 dropdown_menu.ProcessCmdKey (ref msg, key_data);
754                                 return true; // always true if the menu is active
755                         }
756
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));
761                                 return true;
762                         }
763
764                         return false;
765                 }
766
767                 void HighlightButton (int offset)
768                 {
769                         ArrayList enabled = new ArrayList ();
770                         int count = 0;
771                         int start = -1;
772                         ToolBarItem curr_item = null;
773                         foreach (ToolBarItem item in items) {
774                                 if (item.Hilight) {
775                                         start = count;
776                                         curr_item = item;
777                                 }
778
779                                 if (item.Button.Enabled) {
780                                         enabled.Add (item);
781                                         count++;
782                                 }
783                         }
784
785                         int next = (start + offset) % count;
786                         if (next < 0)
787                                 next = count - 1;
788
789                         if (next == start)
790                                 return;
791
792                         if (curr_item != null)
793                                 curr_item.Hilight = false;
794
795                         current_item = enabled [next] as ToolBarItem;
796                         current_item.Hilight = true;
797                 }
798
799                 private void ToolBar_BackgroundImageChanged (object sender, EventArgs args)
800                 {
801                         Redraw (false, true);
802                 }
803
804                 private void ToolBar_MouseDown (object sender, MouseEventArgs me)
805                 {
806                         if ((!Enabled) || ((me.Button & MouseButtons.Left) == 0))
807                                 return;
808
809                         Point loc = new Point (me.X, me.Y);
810
811                         if (ItemAtPoint (loc) == null)
812                                 return;
813                         
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);
818                         }
819                         
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;
830                                                 }
831                                                 
832                                                 if (rect.Contains (loc)) {
833                                                         if (item.Button.DropDownMenu != null) {
834                                                                 item.DDPressed = true;
835                                                                 Invalidate (rect);
836                                                         }
837                                                         break;
838                                                 }
839                                         }
840                                         item.Pressed = true;
841                                         item.Inside = true;
842                                         item.Invalidate ();
843                                         break;
844                                 }
845                         }
846                 }
847
848                 private void ToolBar_MouseUp (object sender, MouseEventArgs me)
849                 {
850                         if ((!Enabled) || ((me.Button & MouseButtons.Left) == 0))
851                                 return;
852
853                         Point loc = new Point (me.X, me.Y);
854
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)) {
865                                                         current_item = item;
866                                                         if (item.DDPressed)
867                                                                 OnButtonDropDown (new ToolBarButtonClickEventArgs (item.Button));
868                                                         continue;
869                                                 }
870                                         }
871                                         // Fire a ButtonClick
872                                         current_item = item;
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;
877                                         item.Invalidate ();
878                                 }
879                         }
880                 }
881
882                 private ToolBarItem ItemAtPoint (Point pt)
883                 {
884                         foreach (ToolBarItem item in items)
885                                 if (item.Rectangle.Contains (pt)) 
886                                         return item;
887
888                         return null;
889                 }
890
891                 ToolTip tip_window = null;
892                 Timer tipdown_timer = null;
893
894                 private void PopDownTip (object o, EventArgs args)
895                 {
896                         tip_window.Hide (this);
897                 }
898
899                 private Timer TipDownTimer {
900                         get {
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);
906                                 }
907                                 return tipdown_timer;
908                         }
909                 }
910
911                 private void ToolBar_MouseHover (object sender, EventArgs e)
912                 {
913                         if (Capture)
914                                 return;
915
916                         if (tip_window == null)
917                                 tip_window = new ToolTip ();
918
919                         ToolBarItem item = ItemAtPoint (PointToClient (Control.MousePosition));
920                         current_item = item;
921
922                         if (item == null || item.Button.ToolTipText.Length == 0)
923                                 return;
924
925                         tip_window.Present (this, item.Button.ToolTipText);
926                         TipDownTimer.Start ();
927                 }
928
929                 private void ToolBar_MouseLeave (object sender, EventArgs e)
930                 {
931                         if (tipdown_timer != null)
932                                 tipdown_timer.Dispose ();
933                         tipdown_timer = null;
934                         if (tip_window != null)
935                                 tip_window.Dispose ();
936                         tip_window = null;
937
938                         if (!Enabled || current_item == null) 
939                                 return;
940
941                         current_item.Hilight = false;
942                         current_item = null;
943                 }
944
945                 private void ToolBar_MouseMove (object sender, MouseEventArgs me)
946                 {
947                         if (!Enabled) 
948                                 return;
949
950                         if (tip_window != null && tip_window.Visible) {
951                                 TipDownTimer.Stop ();
952                                 TipDownTimer.Start ();
953                         }
954
955                         Point loc = new Point (me.X, me.Y);
956
957                         if (Capture) {
958                                 // If the button was pressed and we leave, release the 
959                                 // button press and vice versa
960                                 foreach (ToolBarItem item in items) {
961                                         if (item.Pressed &&
962                                             (item.Inside != item.Rectangle.Contains (loc))) {
963                                                 item.Inside = item.Rectangle.Contains (loc);
964                                                 item.Hilight = false;
965                                                 break;
966                                         }
967                                 }
968                                 return;
969                         } 
970
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)
974                                                 return;
975                                         current_item.Hilight = true;
976                                 }
977                         } else {
978                                 if (tip_window != null) {
979                                         if (tip_window.Visible) {
980                                                 tip_window.Hide (this);
981                                                 TipDownTimer.Stop ();
982                                         }
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 ();
987                                         }
988                                 }
989
990                                 if (ThemeEngine.Current.ToolBarHasHotElementStyles (this)) {
991                                         foreach (ToolBarItem item in items) {
992                                                 if (item.Rectangle.Contains (loc) && item.Button.Enabled) {
993                                                         current_item = item;
994                                                         if (current_item.Hilight || (!ThemeEngine.Current.ToolBarHasHotCheckedElementStyles && current_item.Button.Pushed))
995                                                                 continue;
996                                                         current_item.Hilight = true;
997                                                 }
998                                                 else if (item.Hilight) {
999                                                         item.Hilight = false;
1000                                                 }
1001                                         }
1002                                 }
1003                         }
1004                 }
1005
1006                 internal override void OnPaintInternal (PaintEventArgs pevent)
1007                 {
1008                         if (GetStyle (ControlStyles.UserPaint))
1009                                 return;
1010                                 
1011                         ThemeEngine.Current.DrawToolBar (pevent.Graphics, pevent.ClipRectangle, this);
1012                         
1013                         // Toolbars do not raise OnPaint unless UserPaint is set
1014                         pevent.Handled = true;
1015                 }
1016
1017                 internal void Redraw (bool recalculate)
1018                 {
1019                         Redraw (recalculate, true);
1020                 }
1021
1022                 internal void Redraw (bool recalculate, bool force)
1023                 {
1024                         bool invalidate = true;
1025                         
1026                         if (recalculate)
1027                                 invalidate = LayoutToolBar ();
1028
1029                         if (force || invalidate)
1030                                 Invalidate ();
1031                 }
1032
1033                 internal bool SizeSpecified {
1034                         get { return size_specified; }
1035                 }
1036                 
1037                 internal bool Vertical {
1038                         get { return (Dock == DockStyle.Left) || (Dock == DockStyle.Right); }
1039                 }
1040
1041                 internal const int text_padding = 3;
1042
1043                 private Size CalcButtonSize ()
1044                 {
1045                         if (Buttons.Count == 0)
1046                                 return Size.Empty;
1047
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;
1052                         }
1053
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));
1059                         }
1060
1061                         Size img_size = ImageList == null ? new Size (16, 16) : ImageSize;
1062
1063                         Theme theme = ThemeEngine.Current;
1064                         int imgWidth = img_size.Width + 2 * theme.ToolBarImageGripWidth; 
1065                         int imgHeight = img_size.Height + 2 * theme.ToolBarImageGripWidth;
1066
1067                         if (text_alignment == ToolBarTextAlign.Right) {
1068                                 size.Width = imgWidth + size.Width;
1069                                 size.Height = (size.Height > imgHeight) ? size.Height : imgHeight;
1070                         } else {
1071                                 size.Height = imgHeight + size.Height;
1072                                 size.Width = (size.Width > imgWidth) ? size.Width : imgWidth;
1073                         }
1074
1075                         size.Width += theme.ToolBarImageGripWidth;
1076                         size.Height += theme.ToolBarImageGripWidth;
1077                         return size;
1078                 }
1079
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 {
1083                         get {
1084                                 Size size;
1085
1086                                 if (default_size.IsEmpty || Appearance == ToolBarAppearance.Normal) 
1087                                         size = ButtonSize;
1088                                 else
1089                                         size = default_size;
1090                                 
1091                                 if (size_specified) {
1092                                         if (Appearance == ToolBarAppearance.Flat)
1093                                                 size = CalcButtonSize ();
1094                                         else {
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;
1100                                         }
1101                                 }
1102                                 return size;
1103                         }
1104                 }
1105
1106                 private bool LayoutToolBar ()
1107                 {
1108                         bool changed = false;
1109                         Theme theme = ThemeEngine.Current;
1110                         int x = theme.ToolBarGripWidth;
1111                         int y = theme.ToolBarGripWidth;
1112
1113                         Size adjusted_size = AdjustedButtonSize;
1114                         
1115                         int calculated_size = (Vertical ? adjusted_size.Width : adjusted_size.Height) + theme.ToolBarGripWidth;
1116                         
1117                         int separator_index = -1;
1118
1119                         items = new ToolBarItem [buttons.Count];
1120                         
1121                         for (int i = 0; i < buttons.Count; i++) {
1122                                 ToolBarButton button = buttons [i];
1123                                 
1124                                 ToolBarItem item = new ToolBarItem (button);
1125                                 items [i] = item;
1126
1127                                 if (!button.Visible)
1128                                         continue;
1129
1130                                 if (size_specified && (button.Style != ToolBarButtonStyle.Separator))
1131                                         changed = item.Layout (adjusted_size);
1132                                 else
1133                                         changed = item.Layout (Vertical, calculated_size);
1134                                 
1135                                 bool is_separator = button.Style == ToolBarButtonStyle.Separator;
1136                                 
1137                                 if (Vertical) {
1138                                         if (y + item.Rectangle.Height < Height || is_separator || !Wrappable) {
1139                                                 if (item.Location.X != x || item.Location.Y != y)
1140                                                         changed = true;
1141                                                 item.Location = new Point (x, y);
1142                                                 y += item.Rectangle.Height;
1143                                                 if (is_separator)
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; 
1150                                         } else {
1151                                                 y = theme.ToolBarGripWidth;
1152                                                 x += calculated_size; 
1153                                                 if (item.Location.X != x || item.Location.Y != y)
1154                                                         changed = true;
1155                                                 item.Location = new Point (x, y);
1156                                                 y += item.Rectangle.Height;
1157                                         }
1158                                 } else {
1159                                         if (x + item.Rectangle.Width < Width || is_separator || !Wrappable) {
1160                                                 if (item.Location.X != x || item.Location.Y != y)
1161                                                         changed = true;
1162                                                 item.Location = new Point (x, y);
1163                                                 x += item.Rectangle.Width;
1164                                                 if (is_separator)
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; 
1171                                         } else {
1172                                                 x = theme.ToolBarGripWidth;
1173                                                 y += calculated_size; 
1174                                                 if (item.Location.X != x || item.Location.Y != y)
1175                                                         changed = true;
1176                                                 item.Location = new Point (x, y);
1177                                                 x += item.Rectangle.Width;
1178                                         }
1179                                 }
1180                         }
1181                         
1182                         if (Parent == null)
1183                                 return changed;
1184                         
1185                         if (Wrappable)
1186                                 calculated_size += Vertical ? x : y;
1187                         
1188                         if (IsHandleCreated) {
1189                                 if (Vertical)
1190                                         Width = calculated_size;
1191                                 else
1192                                         Height = calculated_size; 
1193                         }
1194                         
1195                         return changed;
1196                 }
1197                 #endregion Private Methods
1198
1199                 #region subclass
1200                 public class ToolBarButtonCollection : IList, ICollection, IEnumerable
1201                 {
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
1206                         #endregion
1207
1208                         #region UIA Framework Events
1209 #if NET_2_0
1210                         static object UIACollectionChangedEvent = new object ();
1211                         
1212                         internal event CollectionChangeEventHandler UIACollectionChanged {
1213                                 add { owner.Events.AddHandler (UIACollectionChangedEvent, value); }
1214                                 remove { owner.Events.RemoveHandler (UIACollectionChangedEvent, value); }
1215                         }
1216
1217                         internal void OnUIACollectionChanged (CollectionChangeEventArgs e)
1218                         {
1219                                 CollectionChangeEventHandler eh
1220                                         = (CollectionChangeEventHandler) owner.Events [UIACollectionChangedEvent];
1221                                 if (eh != null)
1222                                         eh (owner, e);
1223                         }
1224 #endif
1225                         #endregion
1226
1227                         #region constructors
1228                         public ToolBarButtonCollection (ToolBar owner)
1229                         {
1230                                 this.list   = new ArrayList ();
1231                                 this.owner  = owner;
1232                                 this.redraw = true;
1233                         }
1234                         #endregion
1235
1236                         #region properties
1237                         [Browsable (false)]
1238                         public int Count {
1239                                 get { return list.Count; }
1240                         }
1241
1242                         public bool IsReadOnly {
1243                                 get { return list.IsReadOnly; }
1244                         }
1245
1246                         public virtual ToolBarButton this [int index] {
1247                                 get { return (ToolBarButton) list [index]; }
1248                                 set {
1249 #if NET_2_0
1250                                         // UIA Framework Event: Button Removed
1251                                         OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
1252 #endif
1253
1254                                         value.SetParent (owner);
1255                                         list [index] = value;
1256                                         owner.Redraw (true);
1257
1258 #if NET_2_0
1259
1260                                 // UIA Framework Event: Button Added
1261                                 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
1262 #endif
1263                                 }
1264                         }
1265
1266 #if NET_2_0
1267                         public virtual ToolBarButton this[string key] {
1268                                 get {
1269                                         if (string.IsNullOrEmpty (key))
1270                                                 return null;
1271                                                 
1272                                         foreach (ToolBarButton b in list)
1273                                                 if (string.Compare (b.Name, key, true) == 0)
1274                                                         return b;
1275                                                         
1276                                         return null;
1277                                 }
1278                         }
1279 #endif
1280
1281                         bool ICollection.IsSynchronized {
1282                                 get { return list.IsSynchronized; }
1283                         }
1284
1285                         object ICollection.SyncRoot {
1286                                 get { return list.SyncRoot; }
1287                         }
1288
1289                         bool IList.IsFixedSize {
1290                                 get { return list.IsFixedSize; }
1291                         }
1292
1293                         object IList.this [int index] {
1294                                 get { return this [index]; }
1295                                 set {
1296                                         if (! (value is ToolBarButton))
1297                                                 throw new ArgumentException("Not of type ToolBarButton", "value");
1298                                         this [index] = (ToolBarButton) value;
1299                                 }
1300                         }
1301                         #endregion
1302
1303                         #region methods
1304                         public int Add (string text)
1305                         {
1306                                 ToolBarButton button = new ToolBarButton (text);
1307                                 return this.Add (button);
1308                         }
1309
1310                         public int Add (ToolBarButton button)
1311                         {
1312                                 int result;
1313                                 button.SetParent (owner);
1314                                 result = list.Add (button);
1315                                 if (redraw)
1316                                         owner.Redraw (true);
1317
1318 #if NET_2_0
1319                                 // UIA Framework Event: Button Added
1320                                 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, result));
1321 #endif
1322
1323                                 return result;
1324                         }
1325
1326                         public void AddRange (ToolBarButton [] buttons)
1327                         {
1328                                 try {
1329                                         redraw = false;
1330                                         foreach (ToolBarButton button in buttons)
1331                                                 Add (button);
1332                                 }
1333                                 finally {
1334                                         redraw = true;
1335                                         owner.Redraw (true);
1336                                 }
1337                         }
1338
1339                         public void Clear ()
1340                         {
1341                                 list.Clear ();
1342                                 owner.Redraw (false);
1343
1344 #if NET_2_0
1345                                 // UIA Framework Event: Button Cleared
1346                                 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, -1));
1347 #endif
1348                         }
1349
1350                         public bool Contains (ToolBarButton button)
1351                         {
1352                                 return list.Contains (button);
1353                         }
1354
1355 #if NET_2_0
1356                         public virtual bool ContainsKey (string key)
1357                         {
1358                                 return !(this[key] == null);
1359                         }
1360 #endif
1361
1362                         public IEnumerator GetEnumerator ()
1363                         {
1364                                 return list.GetEnumerator ();
1365                         }
1366
1367                         void ICollection.CopyTo (Array dest, int index)
1368                         {
1369                                 list.CopyTo (dest, index);
1370                         }
1371
1372                         int IList.Add (object button)
1373                         {
1374                                 if (! (button is ToolBarButton)) {
1375                                         throw new ArgumentException("Not of type ToolBarButton", "button");
1376                                 }
1377
1378                                 return this.Add ((ToolBarButton) button);
1379                         }
1380
1381                         bool IList.Contains (object button)
1382                         {
1383                                 if (! (button is ToolBarButton)) {
1384                                         throw new ArgumentException("Not of type ToolBarButton", "button");
1385                                 }
1386
1387                                 return this.Contains ((ToolBarButton) button);
1388                         }
1389
1390                         int IList.IndexOf (object button)
1391                         {
1392                                 if (! (button is ToolBarButton)) {
1393                                         throw new ArgumentException("Not of type ToolBarButton", "button");
1394                                 }
1395
1396                                 return this.IndexOf ((ToolBarButton) button);
1397                         }
1398
1399                         void IList.Insert (int index, object button)
1400                         {
1401                                 if (! (button is ToolBarButton)) {
1402                                         throw new ArgumentException("Not of type ToolBarButton", "button");
1403                                 }
1404
1405                                 this.Insert (index, (ToolBarButton) button);
1406                         }
1407
1408                         void IList.Remove (object button)
1409                         {
1410                                 if (! (button is ToolBarButton)) {
1411                                         throw new ArgumentException("Not of type ToolBarButton", "button");
1412                                 }
1413
1414                                 this.Remove ((ToolBarButton) button);
1415                         }
1416
1417                         public int IndexOf (ToolBarButton button)
1418                         {
1419                                 return list.IndexOf (button);
1420                         }
1421
1422 #if NET_2_0
1423                         public virtual int IndexOfKey (string key)
1424                         {
1425                                 return IndexOf (this[key]);
1426                         }
1427 #endif
1428
1429                         public void Insert (int index, ToolBarButton button)
1430                         {
1431                                 list.Insert (index, button);
1432                                 owner.Redraw (true);
1433
1434 #if NET_2_0
1435                                 // UIA Framework Event: Button Added
1436                                 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
1437 #endif
1438                         }
1439
1440                         public void Remove (ToolBarButton button)
1441                         {
1442                                 list.Remove (button);
1443                                 owner.Redraw (true);
1444                         }
1445
1446                         public void RemoveAt (int index)
1447                         {
1448                                 list.RemoveAt (index);
1449                                 owner.Redraw (true);
1450
1451 #if NET_2_0
1452                                 // UIA Framework Event: Button Removed
1453                                 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
1454 #endif
1455                         }
1456
1457 #if NET_2_0
1458                         public virtual void RemoveByKey (string key)
1459                         {
1460                                 Remove (this[key]);
1461                         }
1462 #endif
1463                         #endregion methods
1464                 }
1465                 
1466                 #endregion subclass
1467         }
1468         
1469         
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
1473         {
1474                 #region Instance variables
1475                 
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
1481
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
1486                 
1487                 #endregion
1488                 
1489                 #region Constructors
1490                 
1491                 public ToolBarItem (ToolBarButton button)
1492                 {
1493                         this.toolbar = button.Parent;
1494                         this.button  = button;
1495                 }
1496                 
1497                 #endregion Constructors
1498         
1499                 #region Properties
1500
1501                 public ToolBarButton Button {
1502                         get { return this.button; }
1503                 }
1504                 
1505                 public Rectangle Rectangle {
1506                         get { 
1507                                 if (!button.Visible || toolbar == null)
1508                                         return Rectangle.Empty;
1509
1510                                 if (button.Style == ToolBarButtonStyle.DropDownButton && toolbar.DropDownArrows) {
1511                                         Rectangle result = bounds;
1512                                         result.Width += ThemeEngine.Current.ToolBarDropDownWidth;
1513                                         return result;
1514                                 }
1515                                  
1516                                 return bounds;
1517                         }
1518                         set { this.bounds = value; }
1519                 }
1520
1521                 public Point Location {
1522                         get { return bounds.Location; }
1523                         set { bounds.Location = value; }
1524                 }
1525
1526                 public Rectangle ImageRectangle {
1527                         get {
1528                                 Rectangle result = image_rect;
1529                                 result.X += bounds.X;
1530                                 result.Y += bounds.Y;
1531                                 return result; 
1532                         }
1533                 }
1534                 
1535                 public Rectangle TextRectangle {
1536                         get { 
1537                                 Rectangle result = text_rect;
1538                                 result.X += bounds.X;
1539                                 result.Y += bounds.Y;
1540                                 return result; 
1541                         }
1542                 }
1543
1544                 private Size TextSize {
1545                         get {
1546                                 StringFormat text_format = new StringFormat ();
1547                                 text_format.HotkeyPrefix = HotkeyPrefix.Hide;
1548
1549                                 SizeF sz = TextRenderer.MeasureString (button.Text, toolbar.Font, SizeF.Empty, text_format);
1550                                 if (sz == SizeF.Empty)
1551                                         return Size.Empty;
1552                                 return new Size ((int) Math.Ceiling (sz.Width) + 2 * ToolBar.text_padding, (int) Math.Ceiling (sz.Height));
1553                         }
1554                 }
1555                 
1556                 public bool Pressed {
1557                         get { return (pressed && inside); }
1558                         set { pressed = value; }
1559                 }
1560
1561                 public bool DDPressed {
1562                         get { return dd_pressed; }
1563                         set { dd_pressed = value; }
1564                 }
1565
1566                 public bool Inside {
1567                         get { return inside; }
1568                         set { inside = value; }
1569                 }
1570
1571                 public bool Hilight {
1572                         get { return hilight; }
1573                         set {
1574                                 if (hilight == value)
1575                                         return;
1576
1577                                 hilight = value;
1578                                 Invalidate ();
1579                         }
1580                 }       
1581                 
1582                 #endregion Properties
1583
1584                 #region Methods
1585                 
1586                 public Size CalculateSize ()
1587                 {
1588                         Theme theme = ThemeEngine.Current;
1589
1590                         int ht = toolbar.ButtonSize.Height + 2 * theme.ToolBarGripWidth;
1591
1592                         if (button.Style == ToolBarButtonStyle.Separator)
1593                                 return new Size (theme.ToolBarSeparatorWidth, ht);
1594
1595                         Size size;
1596                         if (TextSize.IsEmpty && (button.Image == null))
1597                                 size = toolbar.default_size;
1598                         else
1599                                 size = TextSize;
1600                         
1601                         Size image_size = (toolbar.ImageSize == Size.Empty) ? new Size (16, 16) : toolbar.ImageSize;
1602
1603                         int image_width = image_size.Width + 2 * theme.ToolBarImageGripWidth; 
1604                         int image_height = image_size.Height + 2 * theme.ToolBarImageGripWidth; 
1605
1606                         if (toolbar.TextAlign == ToolBarTextAlign.Right) {
1607                                 size.Width =  image_width + size.Width;
1608                                 size.Height = (size.Height > image_height) ? size.Height : image_height;
1609                         } else {
1610                                 size.Height = image_height + size.Height;
1611                                 size.Width = (size.Width > image_width) ? size.Width : image_width;
1612                         }
1613
1614                         size.Width += theme.ToolBarGripWidth;
1615                         size.Height += theme.ToolBarGripWidth;
1616                         return size;
1617                 }
1618
1619                 
1620                 public bool Layout (bool vertical, int calculated_size)
1621                 {
1622                         if (toolbar == null || !button.Visible)
1623                                 return false;
1624
1625                         Size psize = toolbar.ButtonSize;
1626                         Size size = psize;
1627                         if ((!toolbar.SizeSpecified) || (button.Style == ToolBarButtonStyle.Separator)) {
1628                                 size = CalculateSize ();
1629
1630                                 if (size.Width == 0 || size.Height == 0)
1631                                         size = psize;
1632
1633                                 if (vertical)
1634                                         size.Width = calculated_size;
1635                                 else
1636                                         size.Height = calculated_size;
1637                         }
1638                         return Layout (size);
1639                 }
1640
1641                 public bool Layout (Size size)
1642                 {
1643                         if (toolbar == null || !button.Visible)
1644                                 return false;
1645
1646                         bounds.Size = size;
1647
1648                         Size image_size = (toolbar.ImageSize == Size.Empty) ? new Size (16, 16) : toolbar.ImageSize;
1649                         int grip = ThemeEngine.Current.ToolBarImageGripWidth;
1650
1651                         Rectangle new_image_rect, new_text_rect;
1652                         
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);
1656                         } else {
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);
1659                         }
1660
1661                         bool changed = false;
1662
1663                         if (new_image_rect != image_rect || new_text_rect != text_rect)
1664                                 changed = true;
1665
1666                         image_rect = new_image_rect;
1667                         text_rect = new_text_rect;
1668                         
1669                         return changed;
1670                 }
1671                 
1672                 public void Invalidate ()
1673                 {
1674                         if (toolbar != null)
1675                                 toolbar.Invalidate (Rectangle);
1676                 }
1677
1678                 #endregion Methods
1679         }
1680 }