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