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