* TreeView.cs: Don't draw the selected node when we lose
[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
33 // NOT COMPLETE
34
35 using System.Collections;
36 using System.ComponentModel;
37 using System.ComponentModel.Design;
38 using System.Drawing;
39 using System.Drawing.Imaging;
40 using System.Runtime.InteropServices;
41
42 namespace System.Windows.Forms
43 {       
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                 internal ToolBarAppearance      appearance;
51                 internal bool                   autosize;
52                 internal ToolBarButtonCollection buttons;
53                 internal Size                   buttonSize;
54                 internal bool                   divider;
55                 internal bool                   dropDownArrows;
56                 internal ImageList              imageList;
57                 internal ImeMode                imeMode;
58                 internal bool                   showToolTips;
59                 internal ToolBarTextAlign       textAlignment;
60                 internal bool                   wrappable;        // flag to make the toolbar wrappable
61                 internal bool                   redraw;           // flag to force redrawing the control
62                 private bool                    size_specified;   // flag to know if button size is fixed.
63                 internal ToolBarButton          currentButton; // the highlighted button
64                 #endregion Instance Variables
65
66                 #region Events
67                 [Browsable (false)]
68                 [EditorBrowsable (EditorBrowsableState.Never)]
69                 public new event EventHandler BackColorChanged;
70
71                 [Browsable (false)]
72                 [EditorBrowsable (EditorBrowsableState.Never)]
73                 public new event EventHandler BackgroundImageChanged;
74
75                 public event ToolBarButtonClickEventHandler ButtonClick;
76                 public event ToolBarButtonClickEventHandler ButtonDropDown;
77
78                 [Browsable (false)]
79                 [EditorBrowsable (EditorBrowsableState.Never)]
80                 public new event EventHandler ForeColorChanged;
81
82                 [Browsable (false)]
83                 [EditorBrowsable (EditorBrowsableState.Never)]
84                 public new event EventHandler ImeModeChanged;
85
86                 [Browsable (false)]
87                 [EditorBrowsable (EditorBrowsableState.Never)]
88                 public new event PaintEventHandler Paint;
89
90                 [Browsable (false)]
91                 [EditorBrowsable (EditorBrowsableState.Never)]
92                 public new event EventHandler RightToLeftChanged;
93
94                 [Browsable (false)]
95                 [EditorBrowsable (EditorBrowsableState.Never)]
96                 public new event EventHandler TextChanged;
97                 #endregion Events
98
99                 #region Constructor
100                 public ToolBar ()
101                 {
102                         appearance = ToolBarAppearance.Normal;
103                         autosize = true;
104                         background_color = ThemeEngine.Current.DefaultControlBackColor;
105                         border_style = BorderStyle.None;
106                         buttons = new ToolBarButtonCollection (this);
107                         buttonSize = Size.Empty;
108                         divider = true;
109                         dropDownArrows = false;
110                         foreground_color = ThemeEngine.Current.DefaultControlForeColor;
111                         showToolTips = false;
112                         textAlignment = ToolBarTextAlign.Underneath;
113                         wrappable = true;
114                         dock_style = DockStyle.Top;
115                         redraw = true;
116                         size_specified = false;
117                         
118                         // event handlers
119                         this.MouseDown += new MouseEventHandler (ToolBar_MouseDown);
120                         this.MouseLeave += new EventHandler (ToolBar_MouseLeave);
121                         this.MouseMove += new MouseEventHandler (ToolBar_MouseMove);
122                         this.MouseUp += new MouseEventHandler (ToolBar_MouseUp);
123                         base.Paint += new PaintEventHandler (ToolBar_Paint);
124
125                         SetStyle (ControlStyles.UserPaint, false);
126                         SetStyle (ControlStyles.FixedHeight, true);
127                 }
128                 #endregion Constructor
129
130                 #region protected Properties
131                 protected override CreateParams CreateParams 
132                 {
133                         get { return base.CreateParams; }
134                 }
135
136                 protected override ImeMode DefaultImeMode {
137                         get { return ImeMode.Disable; }
138                 }
139
140                 protected override Size DefaultSize {
141                         get { return ThemeEngine.Current.ToolBarDefaultSize; }
142                 }
143                 #endregion
144
145                 #region Public Properties
146                 [DefaultValue (ToolBarAppearance.Normal)]
147                 [Localizable (true)]
148                 public ToolBarAppearance Appearance {
149                         get { return appearance; }
150                         set {
151                                 if (value == appearance)
152                                         return;
153
154                                 appearance = value;
155                                 Redraw (false);
156                         }
157                 }
158
159                 [DefaultValue (true)]
160                 [Localizable (true)]
161                 public bool AutoSize {
162                         get { return autosize; }
163                         set {
164                                 if (value == autosize)
165                                         return;
166
167                                 autosize = value;
168                                 Redraw (true);
169                         }
170                 }
171
172                 [Browsable (false)]
173                 [EditorBrowsable (EditorBrowsableState.Never)]
174                 public override Color BackColor {
175                         get { return background_color; }
176                         set {
177                                 if (value == background_color)
178                                         return;
179
180                                 background_color = value;
181                                 if (BackColorChanged != null)
182                                         BackColorChanged (this, new EventArgs ());
183                                 Redraw (false);
184                         }
185                 }
186
187                 [Browsable (false)]
188                 [EditorBrowsable (EditorBrowsableState.Never)]
189                 public override Image BackgroundImage {
190                         get { return background_image; }
191                         set {
192                                 if (value == background_image)
193                                         return;
194
195                                 background_image = value;
196                                 if (BackgroundImageChanged != null)
197                                         BackgroundImageChanged (this, new EventArgs ());
198                                 Redraw (false);
199                         }
200                 }
201
202                 [DefaultValue (BorderStyle.None)]
203                 [DispIdAttribute (-504)]
204                 public BorderStyle BorderStyle {
205                         get { return InternalBorderStyle; }
206                         set { InternalBorderStyle = value; }
207                 }
208
209                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
210                 [Localizable (true)]
211                 [MergableProperty (false)]
212                 public ToolBarButtonCollection Buttons {
213                         get { return buttons; }
214                 }
215
216                 [Localizable (true)]
217                 [RefreshProperties (RefreshProperties.All)]
218                 public Size ButtonSize {
219                         get {
220                                 if (buttonSize.IsEmpty) {
221                                         if (buttons.Count == 0)
222                                                 return new Size (39, 36);
223                                         else
224                                                 return CalcButtonSize ();
225                                 }
226                                 return buttonSize;
227                         }
228                         set {
229                                 if (buttonSize.Width == value.Width && buttonSize.Height == value.Height)
230                                         return;
231
232                                         buttonSize = value;
233                                         size_specified = true;
234                                         Redraw (true);
235                         }
236                 }
237
238                 [DefaultValue (true)]
239                 public bool Divider {
240                         get { return divider; }
241                         set {
242                                 if (value == divider)
243                                         return;
244
245                                 divider = value;
246                                 Redraw (false);
247                         }
248                 }
249
250                 [DefaultValue (DockStyle.Top)]
251                 [Localizable (true)]
252                 public override DockStyle Dock {
253                         get { return base.Dock; }
254                         set { base.Dock = value; } 
255                 }
256
257                 [DefaultValue (false)]
258                 [Localizable (true)]
259                 public bool DropDownArrows {
260                         get { return dropDownArrows; }
261                         set {
262                                 if (value == dropDownArrows)
263                                         return;
264
265                                 dropDownArrows = value;
266                                 Redraw (true);
267                         }
268                 }
269
270                 [Browsable (false)]
271                 [EditorBrowsable (EditorBrowsableState.Never)]
272                 public override Color ForeColor {
273                         get { return foreground_color; }
274                         set {
275                                 if (value == foreground_color)
276                                         return;
277
278                                 foreground_color = value;
279                                 if (ForeColorChanged != null)
280                                         ForeColorChanged (this, new EventArgs ());
281                                 Redraw (false);
282                         }
283                 }
284
285                 [DefaultValue (null)]
286                 public ImageList ImageList {
287                         get { return imageList; }
288                         set { imageList = value; }
289                 }
290
291                 [Browsable (false)]
292                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
293                 [EditorBrowsable (EditorBrowsableState.Advanced)]
294                 public Size ImageSize {
295                         get {
296                                 if (imageList == null)
297                                         return Size.Empty;
298
299                                 return imageList.ImageSize;
300                         }
301                 }
302
303                 [Browsable (false)]
304                 [EditorBrowsable (EditorBrowsableState.Never)]
305                 public new ImeMode ImeMode {
306                         get { return imeMode; }
307                         set {
308                                 if (value == imeMode)
309                                         return;
310
311                                 imeMode = value;
312                                 if (ImeModeChanged != null)
313                                         ImeModeChanged (this, new EventArgs ());
314                         }
315                 }
316
317                 [Browsable (false)]
318                 [EditorBrowsable (EditorBrowsableState.Never)]
319                 public override RightToLeft RightToLeft {
320                         get { return base.RightToLeft; }
321                         set {
322                                 if (value == base.RightToLeft)
323                                         return;
324
325                                 base.RightToLeft = value;
326                                 if (RightToLeftChanged != null)
327                                         RightToLeftChanged (this, new EventArgs ());
328                         }
329                 }
330
331                 [DefaultValue (false)]
332                 [Localizable (true)]
333                 public bool ShowToolTips {
334                         get { return showToolTips; }
335                         set { showToolTips = value; }
336                 }
337
338                 [DefaultValue (false)]
339                 public new bool TabStop {
340                         get { return base.TabStop; }
341                         set { base.TabStop = value; }
342                 }
343
344                 [Bindable (false)]
345                 [Browsable (false)]
346                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
347                 [EditorBrowsable (EditorBrowsableState.Never)]
348                 public override string Text {
349                         get { return text; } 
350                         set {
351                                 if (value == text)
352                                         return;
353
354                                 text = value;
355                                 Redraw (true);
356                                 if (TextChanged != null)
357                                         TextChanged (this, new EventArgs ());
358                         }
359                 }
360
361                 [DefaultValue (ToolBarTextAlign.Underneath)]
362                 [Localizable (true)]
363                 public ToolBarTextAlign TextAlign {
364                         get { return textAlignment; }
365                         set {
366                                 if (value == textAlignment)
367                                         return;
368
369                                 textAlignment = value;
370                                 Redraw (true);
371                         }
372                 }
373
374                 [DefaultValue (true)]
375                 [Localizable (true)]
376                 public bool Wrappable {
377                         get { return wrappable; }
378                         set {
379                                 if (value == wrappable)
380                                         return;
381
382                                 wrappable = value;
383                                 Redraw (true);
384                         }
385                 }
386                 #endregion Public Properties
387
388                 #region Public Methods
389                 public override string ToString ()
390                 {
391                         int count = this.Buttons.Count;
392
393                         if (count == 0)
394                                 return string.Format ("System.Windows.Forms.ToolBar, Button.Count: 0");
395                         else
396                                 return string.Format ("System.Windows.Forms.ToolBar, Button.Count: {0}, Buttons[0]: {1}",
397                                                       count, this.Buttons [0].ToString ());
398                 }
399                 #endregion Public Methods
400
401                 #region Internal Methods
402                 internal Rectangle GetChildBounds (ToolBarButton button)
403                 {
404                         if (button.Style == ToolBarButtonStyle.Separator)
405                                 return new Rectangle (button.Location.X, button.Location.Y, 
406                                                       ThemeEngine.Current.ToolBarSeparatorWidth, this.ButtonSize.Height);
407
408                         if (size_specified)
409                                 return new Rectangle (button.Location, this.ButtonSize);
410
411                         SizeF sz = this.DeviceContext.MeasureString (button.Text, this.Font);
412                         Size size = new Size ((int) Math.Ceiling (sz.Width), (int) Math.Ceiling (sz.Height));
413
414                         if (imageList != null) {
415                                 // adjustment for the image grip 
416                                 int imgWidth = this.ImageSize.Width + 2 * ThemeEngine.Current.ToolBarImageGripWidth; 
417                                 int imgHeight = this.ImageSize.Height + 2 * ThemeEngine.Current.ToolBarImageGripWidth; 
418
419                                 if (textAlignment == ToolBarTextAlign.Right) {
420                                         size.Width =  imgWidth + size.Width;
421                                         size.Height = (size.Height > imgHeight) ? size.Height : imgHeight;
422                                 }
423                                 else {
424                                         size.Height = imgHeight + size.Height;
425                                         size.Width = (size.Width > imgWidth) ? size.Width : imgWidth;
426                                 }
427                         }
428                         if (button.Style == ToolBarButtonStyle.DropDownButton && this.dropDownArrows)
429                                 size.Width += ThemeEngine.Current.ToolBarDropDownWidth;
430
431                         return new Rectangle (button.Location, size);
432                 }
433                 #endregion Internal Methods
434
435                 #region Protected Methods
436                 protected override void CreateHandle ()
437                 {
438                         base.CreateHandle ();
439                 }
440
441                 protected override void Dispose (bool disposing)
442                 {
443                         if (disposing)
444                                 imageList = null;
445
446                         base.Dispose (disposing);
447                 }
448
449                 protected virtual void OnButtonClick (ToolBarButtonClickEventArgs e)
450                 {
451                         if (e.Button.Style == ToolBarButtonStyle.ToggleButton) {
452                                 if (! e.Button.Pushed)
453                                         e.Button.Pushed = true;
454                                 else
455                                         e.Button.Pushed = false;
456                         }
457                         e.Button.pressed = false;
458
459                         Invalidate (e.Button.Rectangle);
460                         Redraw (false);
461
462                         if (ButtonClick != null)
463                                 ButtonClick (this, e);
464                         else
465                                 return;
466                 }
467
468                 protected virtual void OnButtonDropDown (ToolBarButtonClickEventArgs e) 
469                 {
470                         // Reset the flag set on DropDown
471                         e.Button.dd_pressed = false;
472
473                         if (ButtonDropDown != null)
474                                 ButtonDropDown (this, e);
475
476                         if (e.Button.DropDownMenu == null)
477                                 return;
478
479                         Point loc = new Point (e.Button.Location.X + 1,
480                                                e.Button.Rectangle.Bottom + 2);
481                         ((ContextMenu) e.Button.DropDownMenu).Show (this, loc);
482                 }
483
484                 protected override void OnFontChanged (EventArgs e)
485                 {
486                         base.OnFontChanged (e);
487                         Redraw (true);
488                 }
489
490                 protected override void OnHandleCreated (EventArgs e)
491                 {
492                         base.OnHandleCreated (e);
493                 }
494
495                 protected override void OnResize (EventArgs e)
496                 {
497                         base.OnResize (e);
498
499                         if (this.Width <= 0 || this.Height <= 0 || this.Visible == false)
500                                 return;
501
502                         Redraw (true);
503                 }
504
505                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
506                 {
507                         base.SetBoundsCore (x, y, width, height, specified);
508                 }
509
510                 protected override void WndProc (ref Message m)
511                 {
512                         base.WndProc (ref m);
513                 }
514
515                 #endregion Protected Methods
516
517                 #region Private Methods
518                 private void ToolBar_MouseDown (object sender, MouseEventArgs me)
519                 {
520                         if (! this.Enabled) return;
521
522                         Point hit = new Point (me.X, me.Y);
523                         this.Capture = true;
524
525                         // draw the pushed button
526                         foreach (ToolBarButton button in buttons) {
527                                 if (button.Enabled && button.Rectangle.Contains (hit)) {
528                                         // Mark the DropDown rect as pressed.
529                                         // We don't redraw the dropdown rect.
530                                         if (button.Style == ToolBarButtonStyle.DropDownButton) {
531                                                 Rectangle ddRect = Rectangle.Empty;
532                                                 Rectangle rect = button.Rectangle;
533                                                 ddRect.Height = rect.Height;
534                                                 ddRect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
535                                                 ddRect.X = rect.X + rect.Width - ddRect.Width;
536                                                 ddRect.Y = rect.Y;
537                                                 if (ddRect.Contains (hit)) {
538                                                         button.dd_pressed = true;
539                                                         break;
540                                                 }
541                                         }
542                                         // If it is not dropdown then we treat it as a normal
543                                         // button press.
544                                         button.pressed = true;
545                                         button.inside = true;
546                                         Invalidate (button.Rectangle);
547                                         Redraw (false);
548                                         break;
549                                 }
550                         }
551                 }
552
553                 private void ToolBar_MouseUp (object sender, MouseEventArgs me)
554                 {
555                         if (! this.Enabled) return;
556
557                         Point hit = new Point (me.X, me.Y);
558                         this.Capture = false;
559
560                         // draw the normal button
561                         foreach (ToolBarButton button in buttons) {
562                                 if (button.Enabled && button.Rectangle.Contains (hit)) {
563                                         if (button.Style == ToolBarButtonStyle.DropDownButton) {
564                                                 Rectangle ddRect = Rectangle.Empty;
565                                                 Rectangle rect = button.Rectangle;
566                                                 ddRect.Height = rect.Height;
567                                                 ddRect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
568                                                 ddRect.X = rect.X + rect.Width - ddRect.Width;
569                                                 ddRect.Y = rect.Y;
570                                                 // Fire a ButtonDropDown event
571                                                 if (ddRect.Contains (hit)) {
572                                                         if (button.dd_pressed)
573                                                                 this.OnButtonDropDown (new ToolBarButtonClickEventArgs (button));
574                                                         continue;
575                                                 }
576                                         }
577                                         // Fire a ButtonClick
578                                         if (button.pressed)
579                                                 this.OnButtonClick (new ToolBarButtonClickEventArgs (button));
580                                 }
581                                 // Clear the button press flags, if any
582                                 else if (button.pressed) {
583                                         button.pressed = false;
584                                         Invalidate (button.Rectangle);
585                                         Redraw (false);
586                                 }
587                         }
588                 }
589
590                 private void ToolBar_MouseLeave (object sender, EventArgs e)
591                 {
592                         if (! this.Enabled || appearance != ToolBarAppearance.Flat) return;
593
594                         if (currentButton != null && currentButton.Hilight) {
595                                 currentButton.Hilight = false;
596                                 Invalidate (currentButton.Rectangle);
597                                 Redraw (false);
598                         }
599                         currentButton = null;
600                 }
601
602                 private void ToolBar_MouseMove (object sender, MouseEventArgs me)
603                 {
604                         if (! this.Enabled) return;
605
606                         Point hit = new Point (me.X, me.Y);
607
608                         if (this.Capture) {
609                                 // If the button was pressed and we leave, release the 
610                                 // button press and vice versa
611                                 foreach (ToolBarButton button in buttons) {
612                                         if (button.pressed &&
613                                             (button.inside != button.Rectangle.Contains (hit))) {
614                                                 button.inside = button.Rectangle.Contains (hit);
615                                                 button.Hilight = false;
616                                                 Invalidate (button.Rectangle);
617                                                 Redraw (false);
618                                                 break;
619                                         }
620                                 }
621                         }
622                         // following is only for flat style toolbar
623                         else if (appearance == ToolBarAppearance.Flat) {
624                                 if (currentButton != null && currentButton.Rectangle.Contains (hit)) {
625                                         if (currentButton.Hilight || currentButton.Pushed)
626                                                 return;
627                                         currentButton.Hilight = true;
628                                         Invalidate (currentButton.Rectangle);
629                                         Redraw (false);
630                                 }
631                                 else {
632                                         foreach (ToolBarButton button in buttons) {
633                                                 if (button.Rectangle.Contains (hit) && button.Enabled) {
634                                                         currentButton = button;
635                                                         if (currentButton.Hilight || currentButton.Pushed)
636                                                                 continue;
637                                                         currentButton.Hilight = true;
638                                                         Invalidate (currentButton.Rectangle);
639                                                         Redraw (false);
640                                                 }
641                                                 else if (button.Hilight) {
642                                                         button.Hilight = false;
643                                                         Invalidate (button.Rectangle);
644                                                         Redraw (false);
645                                                 }
646                                         }
647                                 }
648                         }
649                 }
650
651                 private void ToolBar_Paint (object sender, PaintEventArgs pevent)
652                 {
653                         if (this.Width <= 0 || this.Height <=  0 || this.Visible == false)
654                                 return;
655
656                         if (redraw) {
657                                 ThemeEngine.Current.DrawToolBar (pevent.Graphics, pevent.ClipRectangle, this);
658                                 redraw = false;
659                         }
660
661                         if (Paint != null) {
662                                 Paint (this, pevent);
663                         }
664                 }
665
666                 internal void Redraw (bool recalculate)
667                 {
668                         if (recalculate) {
669                                 CalcToolBar ();
670                         }
671
672                         redraw = true;
673                         Refresh ();
674                 }
675
676                 private Size CalcButtonSize ()
677                 {
678                         String longestText = buttons [0].Text;
679                         for (int i = 1; i < buttons.Count; i++) {
680                                 if (buttons[i].Text.Length > longestText.Length)
681                                         longestText = buttons[i].Text;
682                         }
683
684                         SizeF sz = this.DeviceContext.MeasureString (longestText, this.Font);
685                         Size size = new Size ((int) Math.Ceiling (sz.Width), (int) Math.Ceiling (sz.Height));
686
687                         if (imageList != null) {
688                                 // adjustment for the image grip 
689                                 int imgWidth = this.ImageSize.Width + 2 * ThemeEngine.Current.ToolBarImageGripWidth; 
690                                 int imgHeight = this.ImageSize.Height + 2 * ThemeEngine.Current.ToolBarImageGripWidth;
691
692                                 if (textAlignment == ToolBarTextAlign.Right) {
693                                         size.Width = imgWidth + size.Width;
694                                         size.Height = (size.Height > imgHeight) ? size.Height : imgHeight;
695                                 }
696                                 else {
697                                         size.Height = imgHeight + size.Height;
698                                         size.Width = (size.Width > imgWidth) ? size.Width : imgWidth;
699                                 }
700                         }
701                         return size;
702                 }
703
704                 /* Checks for the separators and sets the location of a button and its wrapper flag */
705                 private void CalcToolBar ()
706                 {
707                         int wd = this.Width;             // the amount of space we have for rest of the buttons
708                         int ht = this.ButtonSize.Height; // all buttons are displayed with the same height
709                         Point loc;                       // the location to place the next button, leave the space for border
710                         loc = new Point (ThemeEngine.Current.ToolBarGripWidth, ThemeEngine.Current.ToolBarGripWidth);
711
712                         // clear all the wrappers if toolbar is not wrappable
713                         if (! wrappable && ! autosize) {
714                                 if (this.Height != this.DefaultSize.Height)
715                                         this.Height = this.DefaultSize.Height;
716                                 foreach (ToolBarButton button in buttons) {
717                                         button.Location = loc;
718                                         button.Wrapper = false;
719                                         loc.X = loc.X + button.Rectangle.Width;
720                                 }
721                         }
722                         else if (! wrappable) { // autosizeable
723                                 if (ht != this.Height)
724                                         this.Height = ht;
725                                 foreach (ToolBarButton button in buttons) {
726                                         button.Location = loc;
727                                         button.Wrapper = false;
728                                         loc.X = loc.X + button.Rectangle.Width;
729                                 }
730                         }
731                         else { // wrappable
732                                 bool seenSeparator = false;
733                                 int separatorIndex = -1;
734                                 ToolBarButton button;
735
736                                 for (int i = 0; i < buttons.Count; i++) {
737                                         button = buttons [i];
738                                         if (button.Visible) {
739                                                 if (button.Style == ToolBarButtonStyle.Separator) {
740                                                         wd -= ThemeEngine.Current.ToolBarSeparatorWidth;
741                                                         if (wd > 0) {
742                                                                 button.Wrapper = false; // clear the old flag in case it was set
743                                                                 button.Location = loc;
744                                                                 loc.X = loc.X + ThemeEngine.Current.ToolBarSeparatorWidth;
745                                                         }
746                                                         else {
747                                                                 button.Wrapper = true;
748                                                                 button.Location = loc;
749                                                                 loc.X = ThemeEngine.Current.ToolBarGripWidth;
750                                                                 wd = this.Width;
751                                                                 // we need space to draw horizontal separator
752                                                                 loc.Y = loc.Y + ThemeEngine.Current.ToolBarSeparatorWidth + ht; 
753                                                         }
754                                                         seenSeparator = true;
755                                                         separatorIndex = i;
756                                                 }
757                                                 else {
758                                                         Rectangle rect = button.Rectangle;
759                                                         wd -= rect.Width;
760                                                         if (wd > 0) {
761                                                                 button.Wrapper = false;
762                                                                 button.Location = loc;
763                                                                 loc.X = loc.X + rect.Width;
764                                                         }
765                                                         else if (seenSeparator) { 
766                                                                 // wrap at the separator and reassign the locations
767                                                                 i = separatorIndex; // for loop is going to increment it
768                                                                 buttons [separatorIndex].Wrapper = true;
769                                                                 seenSeparator = false;
770                                                                 separatorIndex = -1;
771                                                                 loc.X = ThemeEngine.Current.ToolBarGripWidth;
772                                                                 // we need space to draw horizontal separator
773                                                                 loc.Y = loc.Y + ht + ThemeEngine.Current.ToolBarSeparatorWidth; 
774                                                                 wd = this.Width;
775                                                                 continue;
776                                                         }
777                                                         else {
778                                                                 button.Wrapper = true;
779                                                                 wd = this.Width;
780                                                                 loc.X = 0;
781                                                                 loc.Y += ht;
782                                                                 button.Location = loc;
783                                                                 loc.X = loc.X + rect.Width;
784                                                         }
785                                                 }
786                                         }
787                                         else // don't consider invisible buttons
788                                                 continue;
789                                 }
790                                 /* adjust the control height, if we are autosizeable */
791                                 if (autosize) // wrappable
792                                         if (this.Height != (loc.Y + ht + ThemeEngine.Current.ToolBarGripWidth))
793                                                 this.Height = loc.Y + ht + ThemeEngine.Current.ToolBarGripWidth;
794                         }
795                 }
796
797                 private void DumpToolBar (string msg)
798                 {
799                         Console.WriteLine (msg);
800                         Console.WriteLine ("ToolBar: name: " + this.Text);
801                         Console.WriteLine ("ToolBar: wd, ht: " + this.Size);
802                         Console.WriteLine ("ToolBar: img size: " + this.ImageSize);
803                         Console.WriteLine ("ToolBar: button sz: " + this.buttonSize);
804                         Console.WriteLine ("ToolBar: textalignment: "+ this.TextAlign);
805                         Console.WriteLine ("ToolBar: appearance: "+ this.Appearance);
806                         Console.WriteLine ("ToolBar: wrappable: "+ this.Wrappable);
807                         Console.WriteLine ("ToolBar: buttons count: " + this.Buttons.Count);
808
809                         int i= 0;       
810                         foreach (ToolBarButton b in buttons) {
811                                 Console.WriteLine ("ToolBar: button [{0}]:",i++);
812                                 b.Dump ();
813                         }
814                 }
815                 #endregion Private Methods
816
817                 #region subclass
818                 public class ToolBarButtonCollection : IList, ICollection, IEnumerable
819                 {
820                         #region instance variables
821                         private ArrayList buttonsList;
822                         private ToolBar owner;
823                         #endregion
824
825                         #region constructors
826                         public ToolBarButtonCollection (ToolBar owner)
827                         {
828                                 this.owner = owner;
829                                 this.buttonsList = new ArrayList ();
830                         }
831                         #endregion
832
833                         #region properties
834                         [Browsable (false)]
835                         public virtual int Count {
836                                 get { return buttonsList.Count; }
837                         }
838
839                         public virtual bool IsReadOnly {
840                                 get { return buttonsList.IsReadOnly; }
841                         }
842
843                         public virtual ToolBarButton this [int index] {
844                                 get { return (ToolBarButton) buttonsList [index]; }
845                                 set {
846                                         value.SetParent (owner);
847                                         buttonsList [index] = value;
848                                         owner.Redraw (true);
849                                 }
850                         }
851
852                         bool ICollection.IsSynchronized {
853                                 get { return buttonsList.IsSynchronized; }
854                         }
855
856                         object ICollection.SyncRoot {
857                                 get { return buttonsList.SyncRoot; }
858                         }
859
860                         bool IList.IsFixedSize {
861                                 get { return buttonsList.IsFixedSize; }
862                         }
863
864                         object IList.this [int index] {
865                                 get { return this [index]; }
866                                 set {
867                                         if (! (value is ToolBarButton))
868                                                 throw new ArgumentException("Not of type ToolBarButton", "value");
869                                         this [index] = (ToolBarButton) value;
870                                 }
871                         }
872                         #endregion
873
874                         #region methods
875                         public int Add (string text)
876                         {
877                                 ToolBarButton button = new ToolBarButton (text);
878                                 return this.Add (button);
879                         }
880
881                         public int Add (ToolBarButton button)
882                         {
883                                 int result;
884                                 button.SetParent (owner);
885                                 result = buttonsList.Add (button);
886                                 owner.Redraw (true);
887                                 return result;
888                         }
889
890                         public void AddRange (ToolBarButton [] buttons)
891                         {
892                                 foreach (ToolBarButton button in buttons)
893                                         Add (button);
894                         }
895
896                         public virtual void Clear ()
897                         {
898                                 buttonsList.Clear ();
899                                 owner.Redraw (false);
900                         }
901
902                         public bool Contains (ToolBarButton button)
903                         {
904                                 return buttonsList.Contains (button);
905                         }
906
907                         public virtual IEnumerator GetEnumerator ()
908                         {
909                                 return buttonsList.GetEnumerator ();
910                         }
911
912                         void ICollection.CopyTo (Array dest, int index)
913                         {
914                                 buttonsList.CopyTo (dest, index);
915                         }
916
917                         int IList.Add (object button)
918                         {
919                                 if (! (button is ToolBarButton)) {
920                                         throw new ArgumentException("Not of type ToolBarButton", "button");
921                                 }
922
923                                 return this.Add ((ToolBarButton) button);
924                         }
925
926                         bool IList.Contains (object button)
927                         {
928                                 if (! (button is ToolBarButton)) {
929                                         throw new ArgumentException("Not of type ToolBarButton", "button");
930                                 }
931
932                                 return this.Contains ((ToolBarButton) button);
933                         }
934
935                         int IList.IndexOf (object button)
936                         {
937                                 if (! (button is ToolBarButton)) {
938                                         throw new ArgumentException("Not of type ToolBarButton", "button");
939                                 }
940
941                                 return this.IndexOf ((ToolBarButton) button);
942                         }
943
944                         void IList.Insert (int index, object button)
945                         {
946                                 if (! (button is ToolBarButton)) {
947                                         throw new ArgumentException("Not of type ToolBarButton", "button");
948                                 }
949
950                                 this.Insert (index, (ToolBarButton) button);
951                         }
952
953                         void IList.Remove (object button)
954                         {
955                                 if (! (button is ToolBarButton)) {
956                                         throw new ArgumentException("Not of type ToolBarButton", "button");
957                                 }
958
959                                 this.Remove ((ToolBarButton) button);
960                         }
961
962                         public int IndexOf (ToolBarButton button)
963                         {
964                                 return buttonsList.IndexOf (button);
965                         }
966
967                         public void Insert (int index, ToolBarButton button)
968                         {
969                                 buttonsList.Insert (index, button);
970                                 owner.Redraw (true);
971                         }
972
973                         public void Remove (ToolBarButton button)
974                         {
975                                 buttonsList.Remove (button);
976                                 owner.Redraw (true);
977                         }
978
979                         public virtual void RemoveAt (int index)
980                         {
981                                 buttonsList.RemoveAt (index);
982                                 owner.Redraw (true);
983                         }
984                         #endregion methods
985                 }
986                 #endregion subclass
987         }
988 }