* ToolBar.cs: Added support for displaying ContextMenu
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ToolBar.cs
1 //
2 // System.Windows.Forms.ToolBar.cs
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //
23 // Author:
24 //      Ravindra (rkumar@novell.com)
25 //
26 // TODO:
27 //   - Tooltip
28 //
29 // Copyright (C) Novell, Inc. 2004 (http://www.novell.com)
30 //
31 //
32 // $Revision: 1.17 $
33 // $Modtime: $
34 // $Log: ToolBar.cs,v $
35 // Revision 1.17  2004/10/26 09:33:42  ravindra
36 // ToolBar should use the user specified button size, if there is any. Added a size_specified flag for the same.
37 //
38 // Revision 1.16  2004/10/14 11:14:05  ravindra
39 //      - Changed Redraw () to do a Refresh () always.
40 //      - Fixed the MouseMove event handling when mouse is pressed,
41 //      ie drag event handling.
42 //      - Replaced the usage of ToolBarButton.Pressed property to
43 //      ToolBarButton.pressed internal variable.
44 //
45 // Revision 1.15  2004/10/06 09:59:05  jordi
46 // removes warnings from compilation
47 //
48 // Revision 1.14  2004/10/05 09:07:07  ravindra
49 //      - Removed a private method, Draw ().
50 //      - Fixed the ButtonDropDown event handling.
51 //      - Fixed MouseMove event handling.
52 //
53 // Revision 1.13  2004/10/05 04:56:12  jackson
54 // Let the base Control handle the buffers, derived classes should not have to CreateBuffers themselves.
55 //
56 // Revision 1.12  2004/09/28 18:44:25  pbartok
57 // - Streamlined Theme interfaces:
58 //   * Each DrawXXX method for a control now is passed the object for the
59 //     control to be drawn in order to allow accessing any state the theme
60 //     might require
61 //
62 //   * ControlPaint methods for the theme now have a CP prefix to avoid
63 //     name clashes with the Draw methods for controls
64 //
65 //   * Every control now retrieves it's DefaultSize from the current theme
66 //
67 // Revision 1.11  2004/09/16 13:00:19  ravindra
68 // Invalidate should be done before redrawing.
69 //
70 // Revision 1.10  2004/09/09 11:25:03  ravindra
71 // Make redraw accessible from ToolBarButton.
72 //
73 // Revision 1.9  2004/08/25 20:04:40  ravindra
74 // Added the missing divider code and grip for ToolBar Control.
75 //
76 // Revision 1.8  2004/08/25 00:43:13  ravindra
77 // Fixed wrapping related issues in ToolBar control.
78 //
79 // Revision 1.7  2004/08/22 01:20:14  ravindra
80 // Correcting the formatting mess of VS.NET.
81 //
82 // Revision 1.6  2004/08/22 00:49:37  ravindra
83 // Probably this completes the missing attributes in toolbar control.
84 //
85 // Revision 1.5  2004/08/22 00:03:20  ravindra
86 // Fixed toolbar control signatures.
87 //
88 // Revision 1.4  2004/08/21 01:52:08  ravindra
89 // Improvments in mouse event handling in the ToolBar control.
90 //
91 // Revision 1.3  2004/08/17 02:00:54  ravindra
92 // Added attributes.
93 //
94 // Revision 1.2  2004/08/17 00:48:50  ravindra
95 // Added attributes.
96 //
97 // Revision 1.1  2004/08/15 23:13:15  ravindra
98 // First Implementation of ToolBar control.
99 //
100 //
101
102 // NOT COMPLETE
103
104 using System.Collections;
105 using System.ComponentModel;
106 using System.ComponentModel.Design;
107 using System.Drawing;
108 using System.Drawing.Imaging;
109 using System.Runtime.InteropServices;
110
111 namespace System.Windows.Forms
112 {       
113         [DefaultEvent ("ButtonClick")]
114         [DefaultProperty ("Buttons")]
115         [Designer ("System.Windows.Forms.Design.ToolBarDesigner, " + Consts.AssemblySystem_Design, typeof (IDesigner))]
116         public class ToolBar : Control
117         {
118                 #region Instance Variables
119                 internal ToolBarAppearance      appearance;
120                 internal bool                   autosize;
121                 internal BorderStyle            borderStyle;
122                 internal ToolBarButtonCollection buttons;
123                 internal Size                   buttonSize;
124                 internal bool                   divider;
125                 internal bool                   dropDownArrows;
126                 internal ImageList              imageList;
127                 internal ImeMode                imeMode;
128                 internal bool                   showToolTips;
129                 internal ToolBarTextAlign       textAlignment;
130                 internal bool                   wrappable;        // flag to make the toolbar wrappable
131                 internal bool                   redraw;           // flag to force redrawing the control
132                 private bool                    size_specified;   // flag to know if button size is fixed.
133                 internal ToolBarButton          currentButton; // the highlighted button
134                 #endregion Instance Variables
135
136                 #region Events
137                 [Browsable (false)]
138                 [EditorBrowsable (EditorBrowsableState.Never)]
139                 public new event EventHandler BackColorChanged;
140
141                 [Browsable (false)]
142                 [EditorBrowsable (EditorBrowsableState.Never)]
143                 public new event EventHandler BackgroundImageChanged;
144
145                 public event ToolBarButtonClickEventHandler ButtonClick;
146                 public event ToolBarButtonClickEventHandler ButtonDropDown;
147
148                 [Browsable (false)]
149                 [EditorBrowsable (EditorBrowsableState.Never)]
150                 public new event EventHandler ForeColorChanged;
151
152                 [Browsable (false)]
153                 [EditorBrowsable (EditorBrowsableState.Never)]
154                 public new event EventHandler ImeModeChanged;
155
156                 [Browsable (false)]
157                 [EditorBrowsable (EditorBrowsableState.Never)]
158                 public new event PaintEventHandler Paint;
159
160                 [Browsable (false)]
161                 [EditorBrowsable (EditorBrowsableState.Never)]
162                 public new event EventHandler RightToLeftChanged;
163
164                 [Browsable (false)]
165                 [EditorBrowsable (EditorBrowsableState.Never)]
166                 public new event EventHandler TextChanged;
167                 #endregion Events
168
169                 #region Constructor
170                 public ToolBar ()
171                 {
172                         appearance = ToolBarAppearance.Normal;
173                         autosize = true;
174                         background_color = ThemeEngine.Current.DefaultControlBackColor;
175                         borderStyle = BorderStyle.None;
176                         buttons = new ToolBarButtonCollection (this);
177                         buttonSize = Size.Empty;
178                         divider = true;
179                         dropDownArrows = false;
180                         foreground_color = ThemeEngine.Current.DefaultControlForeColor;
181                         showToolTips = false;
182                         textAlignment = ToolBarTextAlign.Underneath;
183                         wrappable = true;
184                         dock_style = DockStyle.Top;
185                         redraw = true;
186                         size_specified = false;
187                         
188                         // event handlers
189                         this.MouseDown += new MouseEventHandler (ToolBar_MouseDown);
190                         this.MouseLeave += new EventHandler (ToolBar_MouseLeave);
191                         this.MouseMove += new MouseEventHandler (ToolBar_MouseMove);
192                         this.MouseUp += new MouseEventHandler (ToolBar_MouseUp);
193                         base.Paint += new PaintEventHandler (ToolBar_Paint);
194                 }
195                 #endregion Constructor
196
197                 #region protected Properties
198                 protected override CreateParams CreateParams 
199                 {
200                         get { return base.CreateParams; }
201                 }
202
203                 protected override ImeMode DefaultImeMode {
204                         get { return ImeMode.Disable; }
205                 }
206
207                 protected override Size DefaultSize {
208                         get { return ThemeEngine.Current.ToolBarDefaultSize; }
209                 }
210                 #endregion
211
212                 #region Public Properties
213                 [DefaultValue (ToolBarAppearance.Normal)]
214                 [Localizable (true)]
215                 public ToolBarAppearance Appearance {
216                         get { return appearance; }
217                         set {
218                                 if (value == appearance)
219                                         return;
220
221                                 appearance = value;
222                                 Redraw (false);
223                         }
224                 }
225
226                 [DefaultValue (true)]
227                 [Localizable (true)]
228                 public bool AutoSize {
229                         get { return autosize; }
230                         set {
231                                 if (value == autosize)
232                                         return;
233
234                                 autosize = value;
235                                 Redraw (true);
236                         }
237                 }
238
239                 [Browsable (false)]
240                 [EditorBrowsable (EditorBrowsableState.Never)]
241                 public override Color BackColor {
242                         get { return background_color; }
243                         set {
244                                 if (value == background_color)
245                                         return;
246
247                                 background_color = value;
248                                 if (BackColorChanged != null)
249                                         BackColorChanged (this, new EventArgs ());
250                                 Redraw (false);
251                         }
252                 }
253
254                 [Browsable (false)]
255                 [EditorBrowsable (EditorBrowsableState.Never)]
256                 public override Image BackgroundImage {
257                         get { return background_image; }
258                         set {
259                                 if (value == background_image)
260                                         return;
261
262                                 background_image = value;
263                                 if (BackgroundImageChanged != null)
264                                         BackgroundImageChanged (this, new EventArgs ());
265                                 Redraw (false);
266                         }
267                 }
268
269                 [DefaultValue (BorderStyle.None)]
270                 [DispIdAttribute (-504)]
271                 public BorderStyle BorderStyle {
272                         get { return borderStyle; }
273                         set {
274                                 if (value == borderStyle)
275                                         return;
276
277                                 borderStyle = value;
278                                 Redraw (false);
279                         }
280                 }
281
282                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
283                 [Localizable (true)]
284                 [MergableProperty (false)]
285                 public ToolBarButtonCollection Buttons {
286                         get { return buttons; }
287                 }
288
289                 [Localizable (true)]
290                 [RefreshProperties (RefreshProperties.All)]
291                 public Size ButtonSize {
292                         get {
293                                 if (buttonSize.IsEmpty) {
294                                         if (buttons.Count == 0)
295                                                 return new Size (39, 36);
296                                         else
297                                                 return CalcButtonSize ();
298                                 }
299                                 return buttonSize;
300                         }
301                         set {
302                                 if (buttonSize.Width == value.Width && buttonSize.Height == value.Height)
303                                         return;
304
305                                         buttonSize = value;
306                                         size_specified = true;
307                                         Redraw (true);
308                         }
309                 }
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 { base.Dock = value; } 
328                 }
329
330                 [DefaultValue (false)]
331                 [Localizable (true)]
332                 public bool DropDownArrows {
333                         get { return dropDownArrows; }
334                         set {
335                                 if (value == dropDownArrows)
336                                         return;
337
338                                 dropDownArrows = value;
339                                 Redraw (true);
340                         }
341                 }
342
343                 [Browsable (false)]
344                 [EditorBrowsable (EditorBrowsableState.Never)]
345                 public override Color ForeColor {
346                         get { return foreground_color; }
347                         set {
348                                 if (value == foreground_color)
349                                         return;
350
351                                 foreground_color = value;
352                                 if (ForeColorChanged != null)
353                                         ForeColorChanged (this, new EventArgs ());
354                                 Redraw (false);
355                         }
356                 }
357
358                 [DefaultValue (null)]
359                 public ImageList ImageList {
360                         get { return imageList; }
361                         set { imageList = value; }
362                 }
363
364                 [Browsable (false)]
365                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
366                 [EditorBrowsable (EditorBrowsableState.Advanced)]
367                 public Size ImageSize {
368                         get {
369                                 if (imageList == null)
370                                         return Size.Empty;
371
372                                 return imageList.ImageSize;
373                         }
374                 }
375
376                 [Browsable (false)]
377                 [EditorBrowsable (EditorBrowsableState.Never)]
378                 public new ImeMode ImeMode {
379                         get { return imeMode; }
380                         set {
381                                 if (value == imeMode)
382                                         return;
383
384                                 imeMode = value;
385                                 if (ImeModeChanged != null)
386                                         ImeModeChanged (this, new EventArgs ());
387                         }
388                 }
389
390                 [Browsable (false)]
391                 [EditorBrowsable (EditorBrowsableState.Never)]
392                 public override RightToLeft RightToLeft {
393                         get { return base.RightToLeft; }
394                         set {
395                                 if (value == base.RightToLeft)
396                                         return;
397
398                                 base.RightToLeft = value;
399                                 if (RightToLeftChanged != null)
400                                         RightToLeftChanged (this, new EventArgs ());
401                         }
402                 }
403
404                 [DefaultValue (false)]
405                 [Localizable (true)]
406                 public bool ShowToolTips {
407                         get { return showToolTips; }
408                         set { showToolTips = value; }
409                 }
410
411                 [DefaultValue (false)]
412                 public new bool TabStop {
413                         get { return base.TabStop; }
414                         set { base.TabStop = value; }
415                 }
416
417                 [Bindable (false)]
418                 [Browsable (false)]
419                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
420                 [EditorBrowsable (EditorBrowsableState.Never)]
421                 public override string Text {
422                         get { return text; } 
423                         set {
424                                 if (value == text)
425                                         return;
426
427                                 text = value;
428                                 Redraw (true);
429                                 if (TextChanged != null)
430                                         TextChanged (this, new EventArgs ());
431                         }
432                 }
433
434                 [DefaultValue (ToolBarTextAlign.Underneath)]
435                 [Localizable (true)]
436                 public ToolBarTextAlign TextAlign {
437                         get { return textAlignment; }
438                         set {
439                                 if (value == textAlignment)
440                                         return;
441
442                                 textAlignment = value;
443                                 Redraw (true);
444                         }
445                 }
446
447                 [DefaultValue (true)]
448                 [Localizable (true)]
449                 public bool Wrappable {
450                         get { return wrappable; }
451                         set {
452                                 if (value == wrappable)
453                                         return;
454
455                                 wrappable = value;
456                                 Redraw (true);
457                         }
458                 }
459                 #endregion Public Properties
460
461                 #region Public Methods
462                 public override string ToString ()
463                 {
464                         int count = this.Buttons.Count;
465
466                         if (count == 0)
467                                 return string.Format ("System.Windows.Forms.ToolBar, Button.Count: 0");
468                         else
469                                 return string.Format ("System.Windows.Forms.ToolBar, Button.Count: {0}, Buttons[0]: {1}",
470                                                       count, this.Buttons [0].ToString ());
471                 }
472                 #endregion Public Methods
473
474                 #region Internal Methods
475                 internal Rectangle GetChildBounds (ToolBarButton button)
476                 {
477                         if (button.Style == ToolBarButtonStyle.Separator)
478                                 return new Rectangle (button.Location.X, button.Location.Y, 
479                                                       ThemeEngine.Current.ToolBarSeparatorWidth, this.ButtonSize.Height);
480
481                         if (size_specified)
482                                 return new Rectangle (button.Location, this.ButtonSize);
483
484                         SizeF sz = this.DeviceContext.MeasureString (button.Text, this.Font);
485                         Size size = new Size ((int) Math.Ceiling (sz.Width), (int) Math.Ceiling (sz.Height));
486
487                         if (imageList != null) {
488                                 // adjustment for the image grip 
489                                 int imgWidth = this.ImageSize.Width + 2 * ThemeEngine.Current.ToolBarImageGripWidth; 
490                                 int imgHeight = this.ImageSize.Height + 2 * ThemeEngine.Current.ToolBarImageGripWidth; 
491
492                                 if (textAlignment == ToolBarTextAlign.Right) {
493                                         size.Width =  imgWidth + size.Width;
494                                         size.Height = (size.Height > imgHeight) ? size.Height : imgHeight;
495                                 }
496                                 else {
497                                         size.Height = imgHeight + size.Height;
498                                         size.Width = (size.Width > imgWidth) ? size.Width : imgWidth;
499                                 }
500                         }
501                         if (button.Style == ToolBarButtonStyle.DropDownButton && this.dropDownArrows)
502                                 size.Width += ThemeEngine.Current.ToolBarDropDownWidth;
503
504                         return new Rectangle (button.Location, size);
505                 }
506                 #endregion Internal Methods
507
508                 #region Protected Methods
509                 protected override void CreateHandle ()
510                 {
511                         base.CreateHandle ();
512                 }
513
514                 protected override void Dispose (bool disposing)
515                 {
516                         if (disposing) {
517                                 if (imageList != null)
518                                         imageList.Dispose ();
519                         }
520
521                         base.Dispose (disposing);
522                 }
523
524                 protected virtual void OnButtonClick (ToolBarButtonClickEventArgs e)
525                 {
526                         if (e.Button.Style == ToolBarButtonStyle.ToggleButton) {
527                                 if (! e.Button.Pushed)
528                                         e.Button.Pushed = true;
529                                 else
530                                         e.Button.Pushed = false;
531                         }
532                         e.Button.pressed = false;
533
534                         Invalidate (e.Button.Rectangle);
535                         Redraw (false);
536
537                         if (ButtonClick != null)
538                                 ButtonClick (this, e);
539                         else
540                                 return;
541                 }
542
543                 protected virtual void OnButtonDropDown (ToolBarButtonClickEventArgs e) 
544                 {
545                         // Reset the flag set on DropDown
546                         e.Button.dd_pressed = false;
547
548                         if (ButtonDropDown != null)
549                                 ButtonDropDown (this, e);
550
551                         if (e.Button.DropDownMenu == null)
552                                 return;
553
554                         Point loc = new Point (e.Button.Location.X + 1,
555                                                e.Button.Rectangle.Bottom + 2);
556                         ((ContextMenu) e.Button.DropDownMenu).Show (this, loc);
557                 }
558
559                 protected override void OnFontChanged (EventArgs e)
560                 {
561                         base.OnFontChanged (e);
562                         Redraw (true);
563                 }
564
565                 protected override void OnHandleCreated (EventArgs e)
566                 {
567                         base.OnHandleCreated (e);
568                 }
569
570                 protected override void OnResize (EventArgs e)
571                 {
572                         base.OnResize (e);
573
574                         if (this.Width <= 0 || this.Height <= 0 || this.Visible == false)
575                                 return;
576
577                         Redraw (true);
578                 }
579
580                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
581                 {
582                         base.SetBoundsCore (x, y, width, height, specified);
583                 }
584
585                 protected override void WndProc (ref Message m)
586                 {
587                         base.WndProc (ref m);
588                 }
589
590                 #endregion Protected Methods
591
592                 #region Private Methods
593                 private void ToolBar_MouseDown (object sender, MouseEventArgs me)
594                 {
595                         if (! this.Enabled) return;
596
597                         Point hit = new Point (me.X, me.Y);
598                         this.Capture = true;
599
600                         // draw the pushed button
601                         foreach (ToolBarButton button in buttons) {
602                                 if (button.Enabled && button.Rectangle.Contains (hit)) {
603                                         // Mark the DropDown rect as pressed.
604                                         // We don't redraw the dropdown rect.
605                                         if (button.Style == ToolBarButtonStyle.DropDownButton) {
606                                                 Rectangle ddRect = Rectangle.Empty;
607                                                 Rectangle rect = button.Rectangle;
608                                                 ddRect.Height = rect.Height;
609                                                 ddRect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
610                                                 ddRect.X = rect.X + rect.Width - ddRect.Width;
611                                                 ddRect.Y = rect.Y;
612                                                 if (ddRect.Contains (hit)) {
613                                                         button.dd_pressed = true;
614                                                         break;
615                                                 }
616                                         }
617                                         // If it is not dropdown then we treat it as a normal
618                                         // button press.
619                                         button.pressed = true;
620                                         button.inside = true;
621                                         Invalidate (button.Rectangle);
622                                         Redraw (false);
623                                         break;
624                                 }
625                         }
626                 }
627
628                 private void ToolBar_MouseUp (object sender, MouseEventArgs me)
629                 {
630                         if (! this.Enabled) return;
631
632                         Point hit = new Point (me.X, me.Y);
633                         this.Capture = false;
634
635                         // draw the normal button
636                         foreach (ToolBarButton button in buttons) {
637                                 if (button.Enabled && button.Rectangle.Contains (hit)) {
638                                         if (button.Style == ToolBarButtonStyle.DropDownButton) {
639                                                 Rectangle ddRect = Rectangle.Empty;
640                                                 Rectangle rect = button.Rectangle;
641                                                 ddRect.Height = rect.Height;
642                                                 ddRect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
643                                                 ddRect.X = rect.X + rect.Width - ddRect.Width;
644                                                 ddRect.Y = rect.Y;
645                                                 // Fire a ButtonDropDown event
646                                                 if (ddRect.Contains (hit)) {
647                                                         if (button.dd_pressed)
648                                                                 this.OnButtonDropDown (new ToolBarButtonClickEventArgs (button));
649                                                         continue;
650                                                 }
651                                         }
652                                         // Fire a ButtonClick
653                                         if (button.pressed)
654                                                 this.OnButtonClick (new ToolBarButtonClickEventArgs (button));
655                                 }
656                                 // Clear the button press flags, if any
657                                 else if (button.pressed) {
658                                         button.pressed = false;
659                                         Invalidate (button.Rectangle);
660                                         Redraw (false);
661                                 }
662                         }
663                 }
664
665                 private void ToolBar_MouseLeave (object sender, EventArgs e)
666                 {
667                         if (! this.Enabled || appearance != ToolBarAppearance.Flat) return;
668
669                         if (currentButton != null && currentButton.Hilight) {
670                                 currentButton.Hilight = false;
671                                 Invalidate (currentButton.Rectangle);
672                                 Redraw (false);
673                         }
674                         currentButton = null;
675                 }
676
677                 private void ToolBar_MouseMove (object sender, MouseEventArgs me)
678                 {
679                         if (! this.Enabled) return;
680
681                         Point hit = new Point (me.X, me.Y);
682
683                         if (this.Capture) {
684                                 // If the button was pressed and we leave, release the 
685                                 // button press and vice versa
686                                 foreach (ToolBarButton button in buttons) {
687                                         if (button.pressed &&
688                                             (button.inside != button.Rectangle.Contains (hit))) {
689                                                 button.inside = button.Rectangle.Contains (hit);
690                                                 button.Hilight = false;
691                                                 Invalidate (button.Rectangle);
692                                                 Redraw (false);
693                                                 break;
694                                         }
695                                 }
696                         }
697                         // following is only for flat style toolbar
698                         else if (appearance == ToolBarAppearance.Flat) {
699                                 if (currentButton != null && currentButton.Rectangle.Contains (hit)) {
700                                         if (currentButton.Hilight || currentButton.Pushed)
701                                                 return;
702                                         currentButton.Hilight = true;
703                                         Invalidate (currentButton.Rectangle);
704                                         Redraw (false);
705                                 }
706                                 else {
707                                         foreach (ToolBarButton button in buttons) {
708                                                 if (button.Rectangle.Contains (hit) && button.Enabled) {
709                                                         currentButton = button;
710                                                         if (currentButton.Hilight || currentButton.Pushed)
711                                                                 continue;
712                                                         currentButton.Hilight = true;
713                                                         Invalidate (currentButton.Rectangle);
714                                                         Redraw (false);
715                                                 }
716                                                 else if (button.Hilight) {
717                                                         button.Hilight = false;
718                                                         Invalidate (button.Rectangle);
719                                                         Redraw (false);
720                                                 }
721                                         }
722                                 }
723                         }
724                 }
725
726                 private void ToolBar_Paint (object sender, PaintEventArgs pe)
727                 {
728                         if (this.Width <= 0 || this.Height <=  0 || this.Visible == false)
729                                 return;
730
731                         if (redraw) {
732                                 ThemeEngine.Current.DrawToolBar (this.DeviceContext, pe.ClipRectangle, this);
733                                 redraw = false;
734                         }
735
736                         // paint on the screen
737                         pe.Graphics.DrawImage (this.ImageBuffer, pe.ClipRectangle, pe.ClipRectangle, GraphicsUnit.Pixel);
738
739                         if (Paint != null)
740                                 Paint (this, pe);
741                 }
742
743                 internal void Redraw (bool recalculate)
744                 {
745                         if (recalculate)
746                                 CalcToolBar ();
747
748                         redraw = true;
749                         Refresh ();
750                 }
751
752                 private Size CalcButtonSize ()
753                 {
754                         String longestText = buttons [0].Text;
755                         for (int i = 1; i < buttons.Count; i++) {
756                                 if (buttons[i].Text.Length > longestText.Length)
757                                         longestText = buttons[i].Text;
758                         }
759
760                         SizeF sz = this.DeviceContext.MeasureString (longestText, this.Font);
761                         Size size = new Size ((int) Math.Ceiling (sz.Width), (int) Math.Ceiling (sz.Height));
762
763                         if (imageList != null) {
764                                 // adjustment for the image grip 
765                                 int imgWidth = this.ImageSize.Width + 2 * ThemeEngine.Current.ToolBarImageGripWidth; 
766                                 int imgHeight = this.ImageSize.Height + 2 * ThemeEngine.Current.ToolBarImageGripWidth;
767
768                                 if (textAlignment == ToolBarTextAlign.Right) {
769                                         size.Width = imgWidth + size.Width;
770                                         size.Height = (size.Height > imgHeight) ? size.Height : imgHeight;
771                                 }
772                                 else {
773                                         size.Height = imgHeight + size.Height;
774                                         size.Width = (size.Width > imgWidth) ? size.Width : imgWidth;
775                                 }
776                         }
777                         return size;
778                 }
779
780                 /* Checks for the separators and sets the location of a button and its wrapper flag */
781                 private void CalcToolBar ()
782                 {
783                         int wd = this.Width;             // the amount of space we have for rest of the buttons
784                         int ht = this.ButtonSize.Height; // all buttons are displayed with the same height
785                         Point loc;                       // the location to place the next button, leave the space for border
786                         loc = new Point (ThemeEngine.Current.ToolBarGripWidth, ThemeEngine.Current.ToolBarGripWidth);
787
788                         // clear all the wrappers if toolbar is not wrappable
789                         if (! wrappable && ! autosize) {
790                                 if (this.Height != this.DefaultSize.Height)
791                                         this.Height = this.DefaultSize.Height;
792                                 foreach (ToolBarButton button in buttons) {
793                                         button.Location = loc;
794                                         button.Wrapper = false;
795                                         loc.X = loc.X + button.Rectangle.Width;
796                                 }
797                         }
798                         else if (! wrappable) { // autosizeable
799                                 if (ht != this.Height)
800                                         this.Height = ht;
801                                 foreach (ToolBarButton button in buttons) {
802                                         button.Location = loc;
803                                         button.Wrapper = false;
804                                         loc.X = loc.X + button.Rectangle.Width;
805                                 }
806                         }
807                         else { // wrappable
808                                 bool seenSeparator = false;
809                                 int separatorIndex = -1;
810                                 ToolBarButton button;
811
812                                 for (int i = 0; i < buttons.Count; i++) {
813                                         button = buttons [i];
814                                         if (button.Visible) {
815                                                 if (button.Style == ToolBarButtonStyle.Separator) {
816                                                         wd -= ThemeEngine.Current.ToolBarSeparatorWidth;
817                                                         if (wd > 0) {
818                                                                 button.Wrapper = false; // clear the old flag in case it was set
819                                                                 button.Location = loc;
820                                                                 loc.X = loc.X + ThemeEngine.Current.ToolBarSeparatorWidth;
821                                                         }
822                                                         else {
823                                                                 button.Wrapper = true;
824                                                                 button.Location = loc;
825                                                                 loc.X = ThemeEngine.Current.ToolBarGripWidth;
826                                                                 wd = this.Width;
827                                                                 // we need space to draw horizontal separator
828                                                                 loc.Y = loc.Y + ThemeEngine.Current.ToolBarSeparatorWidth + ht; 
829                                                         }
830                                                         seenSeparator = true;
831                                                         separatorIndex = i;
832                                                 }
833                                                 else {
834                                                         Rectangle rect = button.Rectangle;
835                                                         wd -= rect.Width;
836                                                         if (wd > 0) {
837                                                                 button.Wrapper = false;
838                                                                 button.Location = loc;
839                                                                 loc.X = loc.X + rect.Width;
840                                                         }
841                                                         else if (seenSeparator) { 
842                                                                 // wrap at the separator and reassign the locations
843                                                                 i = separatorIndex; // for loop is going to increment it
844                                                                 buttons [separatorIndex].Wrapper = true;
845                                                                 seenSeparator = false;
846                                                                 separatorIndex = -1;
847                                                                 loc.X = ThemeEngine.Current.ToolBarGripWidth;
848                                                                 // we need space to draw horizontal separator
849                                                                 loc.Y = loc.Y + ht + ThemeEngine.Current.ToolBarSeparatorWidth; 
850                                                                 wd = this.Width;
851                                                                 continue;
852                                                         }
853                                                         else {
854                                                                 button.Wrapper = true;
855                                                                 wd = this.Width;
856                                                                 loc.X = 0;
857                                                                 loc.Y += ht;
858                                                                 button.Location = loc;
859                                                                 loc.X = loc.X + rect.Width;
860                                                         }
861                                                 }
862                                         }
863                                         else // don't consider invisible buttons
864                                                 continue;
865                                 }
866                                 /* adjust the control height, if we are autosizeable */
867                                 if (autosize) // wrappable
868                                         if (this.Height != (loc.Y + ht + ThemeEngine.Current.ToolBarGripWidth))
869                                                 this.Height = loc.Y + ht + ThemeEngine.Current.ToolBarGripWidth;
870                         }
871                 }
872
873                 private void DumpToolBar (string msg)
874                 {
875                         Console.WriteLine (msg);
876                         Console.WriteLine ("ToolBar: name: " + this.Text);
877                         Console.WriteLine ("ToolBar: wd, ht: " + this.Size);
878                         Console.WriteLine ("ToolBar: img size: " + this.ImageSize);
879                         Console.WriteLine ("ToolBar: button sz: " + this.buttonSize);
880                         Console.WriteLine ("ToolBar: textalignment: "+ this.TextAlign);
881                         Console.WriteLine ("ToolBar: appearance: "+ this.Appearance);
882                         Console.WriteLine ("ToolBar: wrappable: "+ this.Wrappable);
883                         Console.WriteLine ("ToolBar: buttons count: " + this.Buttons.Count);
884
885                         int i= 0;       
886                         foreach (ToolBarButton b in buttons) {
887                                 Console.WriteLine ("ToolBar: button [{0}]:",i++);
888                                 b.Dump ();
889                         }
890                 }
891                 #endregion Private Methods
892
893                 #region subclass
894                 public class ToolBarButtonCollection : IList, ICollection, IEnumerable
895                 {
896                         #region instance variables
897                         private ArrayList buttonsList;
898                         private ToolBar owner;
899                         #endregion
900
901                         #region constructors
902                         public ToolBarButtonCollection (ToolBar owner)
903                         {
904                                 this.owner = owner;
905                                 this.buttonsList = new ArrayList ();
906                         }
907                         #endregion
908
909                         #region properties
910                         [Browsable (false)]
911                         public virtual int Count {
912                                 get { return buttonsList.Count; }
913                         }
914
915                         public virtual bool IsReadOnly {
916                                 get { return buttonsList.IsReadOnly; }
917                         }
918
919                         public virtual ToolBarButton this [int index] {
920                                 get { return (ToolBarButton) buttonsList [index]; }
921                                 set {
922                                         value.SetParent (owner);
923                                         buttonsList [index] = value;
924                                         owner.Redraw (true);
925                                 }
926                         }
927
928                         bool ICollection.IsSynchronized {
929                                 get { return buttonsList.IsSynchronized; }
930                         }
931
932                         object ICollection.SyncRoot {
933                                 get { return buttonsList.SyncRoot; }
934                         }
935
936                         bool IList.IsFixedSize {
937                                 get { return buttonsList.IsFixedSize; }
938                         }
939
940                         object IList.this [int index] {
941                                 get { return this [index]; }
942                                 set {
943                                         if (! (value is ToolBarButton))
944                                                 throw new ArgumentException("Not of type ToolBarButton", "value");
945                                         this [index] = (ToolBarButton) value;
946                                 }
947                         }
948                         #endregion
949
950                         #region methods
951                         public int Add (string text)
952                         {
953                                 ToolBarButton button = new ToolBarButton (text);
954                                 return this.Add (button);
955                         }
956
957                         public int Add (ToolBarButton button)
958                         {
959                                 int result;
960                                 button.SetParent (owner);
961                                 result = buttonsList.Add (button);
962                                 owner.Redraw (true);
963                                 return result;
964                         }
965
966                         public void AddRange (ToolBarButton [] buttons)
967                         {
968                                 foreach (ToolBarButton button in buttons)
969                                         Add (button);
970                         }
971
972                         public virtual void Clear ()
973                         {
974                                 buttonsList.Clear ();
975                                 owner.Redraw (false);
976                         }
977
978                         public bool Contains (ToolBarButton button)
979                         {
980                                 return buttonsList.Contains (button);
981                         }
982
983                         public virtual IEnumerator GetEnumerator ()
984                         {
985                                 return buttonsList.GetEnumerator ();
986                         }
987
988                         void ICollection.CopyTo (Array dest, int index)
989                         {
990                                 buttonsList.CopyTo (dest, index);
991                         }
992
993                         int IList.Add (object button)
994                         {
995                                 if (! (button is ToolBarButton)) {
996                                         throw new ArgumentException("Not of type ToolBarButton", "button");
997                                 }
998
999                                 return this.Add ((ToolBarButton) button);
1000                         }
1001
1002                         bool IList.Contains (object button)
1003                         {
1004                                 if (! (button is ToolBarButton)) {
1005                                         throw new ArgumentException("Not of type ToolBarButton", "button");
1006                                 }
1007
1008                                 return this.Contains ((ToolBarButton) button);
1009                         }
1010
1011                         int IList.IndexOf (object button)
1012                         {
1013                                 if (! (button is ToolBarButton)) {
1014                                         throw new ArgumentException("Not of type ToolBarButton", "button");
1015                                 }
1016
1017                                 return this.IndexOf ((ToolBarButton) button);
1018                         }
1019
1020                         void IList.Insert (int index, object button)
1021                         {
1022                                 if (! (button is ToolBarButton)) {
1023                                         throw new ArgumentException("Not of type ToolBarButton", "button");
1024                                 }
1025
1026                                 this.Insert (index, (ToolBarButton) button);
1027                         }
1028
1029                         void IList.Remove (object button)
1030                         {
1031                                 if (! (button is ToolBarButton)) {
1032                                         throw new ArgumentException("Not of type ToolBarButton", "button");
1033                                 }
1034
1035                                 this.Remove ((ToolBarButton) button);
1036                         }
1037
1038                         public int IndexOf (ToolBarButton button)
1039                         {
1040                                 return buttonsList.IndexOf (button);
1041                         }
1042
1043                         public void Insert (int index, ToolBarButton button)
1044                         {
1045                                 buttonsList.Insert (index, button);
1046                                 owner.Redraw (true);
1047                         }
1048
1049                         public void Remove (ToolBarButton button)
1050                         {
1051                                 buttonsList.Remove (button);
1052                                 owner.Redraw (true);
1053                         }
1054
1055                         public virtual void RemoveAt (int index)
1056                         {
1057                                 buttonsList.RemoveAt (index);
1058                                 owner.Redraw (true);
1059                         }
1060                         #endregion methods
1061                 }
1062                 #endregion subclass
1063         }
1064 }