* roottypes.cs: Rename from tree.cs.
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ToolBar.cs
1 // System.Windows.Forms.ToolBar.cs
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining
4 // a copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to
9 // the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 // Author:
23 //      Ravindra (rkumar@novell.com)
24 //      Mike Kestner <mkestner@novell.com>
25 //
26 // TODO:
27 //   - Tooltip
28 //
29 // Copyright (C) 2004-2006  Novell, Inc. (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                 bool size_specified = false;
51                 ToolBarButton current_button;
52                 #endregion Instance Variables
53
54                 #region Events
55                 [Browsable (false)]
56                 [EditorBrowsable (EditorBrowsableState.Never)]
57                 public new event EventHandler BackColorChanged {
58                         add { base.BackColorChanged += value; }
59                         remove { base.BackColorChanged -= value; }
60                 }
61
62                 [Browsable (false)]
63                 [EditorBrowsable (EditorBrowsableState.Never)]
64                 public new event EventHandler BackgroundImageChanged {
65                         add { base.BackgroundImageChanged += value; }
66                         remove { base.BackgroundImageChanged -= value; }
67                 }
68
69                 public event ToolBarButtonClickEventHandler ButtonClick;
70                 public event ToolBarButtonClickEventHandler ButtonDropDown;
71
72                 [Browsable (false)]
73                 [EditorBrowsable (EditorBrowsableState.Never)]
74                 public new event EventHandler ForeColorChanged {
75                         add { base.ForeColorChanged += value; }
76                         remove { base.ForeColorChanged -= value; }
77                 }
78
79                 [Browsable (false)]
80                 [EditorBrowsable (EditorBrowsableState.Never)]
81                 public new event EventHandler ImeModeChanged {
82                         add { base.ImeModeChanged += value; }
83                         remove { base.ImeModeChanged -= value; }
84                 }
85
86                 [Browsable (false)]
87                 [EditorBrowsable (EditorBrowsableState.Never)]
88                 public new event PaintEventHandler Paint {
89                         add { base.Paint += value; }
90                         remove { base.Paint -= value; }
91                 }
92
93                 [Browsable (false)]
94                 [EditorBrowsable (EditorBrowsableState.Never)]
95                 public new event EventHandler RightToLeftChanged {
96                         add { base.RightToLeftChanged += value; }
97                         remove { base.RightToLeftChanged -= value; }
98                 }
99
100                 [Browsable (false)]
101                 [EditorBrowsable (EditorBrowsableState.Never)]
102                 public new event EventHandler TextChanged {
103                         add { base.TextChanged += value; }
104                         remove { base.TextChanged -= value; }
105                 }
106                 #endregion Events
107
108                 #region Constructor
109                 public ToolBar ()
110                 {
111                         background_color = ThemeEngine.Current.DefaultControlBackColor;
112                         foreground_color = ThemeEngine.Current.DefaultControlForeColor;
113                         buttons = new ToolBarButtonCollection (this);
114                         dock_style = DockStyle.Top;
115                         
116                         GotFocus += new EventHandler (FocusChanged);
117                         LostFocus += new EventHandler (FocusChanged);
118                         MouseDown += new MouseEventHandler (ToolBar_MouseDown);
119                         MouseLeave += new EventHandler (ToolBar_MouseLeave);
120                         MouseMove += new MouseEventHandler (ToolBar_MouseMove);
121                         MouseUp += new MouseEventHandler (ToolBar_MouseUp);
122
123                         SetStyle (ControlStyles.UserPaint, false);
124                         SetStyle (ControlStyles.FixedHeight, true);
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                 ToolBarAppearance appearance = ToolBarAppearance.Normal;
144
145                 #region Public Properties
146                 [DefaultValue (ToolBarAppearance.Normal)]
147                 [Localizable (true)]
148                 public ToolBarAppearance Appearance {
149                         get { return appearance; }
150                         set {
151                                 if (value == appearance)
152                                         return;
153
154                                 appearance = value;
155                                 Redraw (true);
156                         }
157                 }
158
159                 bool autosize = true;
160
161                 [DefaultValue (true)]
162                 [Localizable (true)]
163                 public bool AutoSize {
164                         get { return autosize; }
165                         set {
166                                 if (value == autosize)
167                                         return;
168
169                                 autosize = value;
170                                 Redraw (true);
171                         }
172                 }
173
174                 [Browsable (false)]
175                 [EditorBrowsable (EditorBrowsableState.Never)]
176                 public override Color BackColor {
177                         get { return background_color; }
178                         set {
179                                 if (value == background_color)
180                                         return;
181
182                                 background_color = value;
183                                 OnBackColorChanged (EventArgs.Empty);
184                                 Redraw (false);
185                         }
186                 }
187
188                 [Browsable (false)]
189                 [EditorBrowsable (EditorBrowsableState.Never)]
190                 public override Image BackgroundImage {
191                         get { return background_image; }
192                         set {
193                                 if (value == background_image)
194                                         return;
195
196                                 background_image = value;
197                                 OnBackgroundImageChanged (EventArgs.Empty);
198                                 Redraw (false);
199                         }
200                 }
201
202                 [DefaultValue (BorderStyle.None)]
203                 [DispIdAttribute (-504)]
204                 public BorderStyle BorderStyle {
205                         get { return InternalBorderStyle; }
206                         set { InternalBorderStyle = value; }
207                 }
208
209                 ToolBarButtonCollection buttons;
210
211                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
212                 [Localizable (true)]
213                 [MergableProperty (false)]
214                 public ToolBarButtonCollection Buttons {
215                         get { return buttons; }
216                 }
217
218                 Size button_size;
219
220                 [Localizable (true)]
221                 [RefreshProperties (RefreshProperties.All)]
222                 public Size ButtonSize {
223                         get {
224                                 if (button_size.IsEmpty) {
225                                         if (buttons.Count == 0)
226                                                 return new Size (24, 22);
227                                         Size result = CalcButtonSize ();
228                                         if (result.IsEmpty)
229                                                 return new Size (24, 22);
230                                         else
231                                                 return result;
232                                 }
233                                 return button_size;
234                         }
235                         set {
236                                 size_specified = value != Size.Empty;
237                                 if (button_size == value)
238                                         return;
239
240                                 button_size = value;
241                                 Redraw (true);
242                         }
243                 }
244
245                 bool divider = true;
246
247                 [DefaultValue (true)]
248                 public bool Divider {
249                         get { return divider; }
250                         set {
251                                 if (value == divider)
252                                         return;
253
254                                 divider = value;
255                                 Redraw (false);
256                         }
257                 }
258
259                 [DefaultValue (DockStyle.Top)]
260                 [Localizable (true)]
261                 public override DockStyle Dock {
262                         get { return base.Dock; }
263                         set { base.Dock = value; } 
264                 }
265
266                 bool drop_down_arrows = false;
267
268                 [DefaultValue (false)]
269                 [Localizable (true)]
270                 public bool DropDownArrows {
271                         get { return drop_down_arrows; }
272                         set {
273                                 if (value == drop_down_arrows)
274                                         return;
275
276                                 drop_down_arrows = value;
277                                 Redraw (true);
278                         }
279                 }
280
281                 [Browsable (false)]
282                 [EditorBrowsable (EditorBrowsableState.Never)]
283                 public override Color ForeColor {
284                         get { return foreground_color; }
285                         set {
286                                 if (value == foreground_color)
287                                         return;
288
289                                 foreground_color = value;
290                                 OnForeColorChanged (EventArgs.Empty);
291                                 Redraw (false);
292                         }
293                 }
294
295                 ImageList image_list;
296
297                 [DefaultValue (null)]
298                 public ImageList ImageList {
299                         get { return image_list; }
300                         set { 
301                                 if (image_list == value)
302                                         return;
303                                 image_list = value;
304                                 Redraw (true);
305                         }
306                 }
307
308                 [Browsable (false)]
309                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
310                 [EditorBrowsable (EditorBrowsableState.Advanced)]
311                 public Size ImageSize {
312                         get {
313                                 if (ImageList == null)
314                                         return Size.Empty;
315
316                                 return ImageList.ImageSize;
317                         }
318                 }
319
320                 ImeMode ime_mode;
321
322                 [Browsable (false)]
323                 [EditorBrowsable (EditorBrowsableState.Never)]
324                 public new ImeMode ImeMode {
325                         get { return ime_mode; }
326                         set {
327                                 if (value == ime_mode)
328                                         return;
329
330                                 ime_mode = value;
331                                 OnImeModeChanged (EventArgs.Empty);
332                         }
333                 }
334
335                 [Browsable (false)]
336                 [EditorBrowsable (EditorBrowsableState.Never)]
337                 public override RightToLeft RightToLeft {
338                         get { return base.RightToLeft; }
339                         set {
340                                 if (value == base.RightToLeft)
341                                         return;
342
343                                 base.RightToLeft = value;
344                                 OnRightToLeftChanged (EventArgs.Empty);
345                         }
346                 }
347
348                 bool show_tooltips = false;
349
350                 [DefaultValue (false)]
351                 [Localizable (true)]
352                 public bool ShowToolTips {
353                         get { return show_tooltips; }
354                         set { show_tooltips = value; }
355                 }
356
357                 [DefaultValue (false)]
358                 public new bool TabStop {
359                         get { return base.TabStop; }
360                         set { base.TabStop = value; }
361                 }
362
363                 [Bindable (false)]
364                 [Browsable (false)]
365                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
366                 [EditorBrowsable (EditorBrowsableState.Never)]
367                 public override string Text {
368                         get { return text; } 
369                         set {
370                                 if (value == text)
371                                         return;
372
373                                 text = value;
374                                 Redraw (true);
375                                 OnTextChanged (EventArgs.Empty);
376                         }
377                 }
378
379                 ToolBarTextAlign text_alignment = ToolBarTextAlign.Underneath;
380
381                 [DefaultValue (ToolBarTextAlign.Underneath)]
382                 [Localizable (true)]
383                 public ToolBarTextAlign TextAlign {
384                         get { return text_alignment; }
385                         set {
386                                 if (value == text_alignment)
387                                         return;
388
389                                 text_alignment = value;
390                                 Redraw (true);
391                         }
392                 }
393
394                 bool wrappable = true;
395
396                 [DefaultValue (true)]
397                 [Localizable (true)]
398                 public bool Wrappable {
399                         get { return wrappable; }
400                         set {
401                                 if (value == wrappable)
402                                         return;
403
404                                 wrappable = value;
405                                 Redraw (true);
406                         }
407                 }
408                 #endregion Public Properties
409
410                 #region Public Methods
411                 public override string ToString ()
412                 {
413                         int count = this.Buttons.Count;
414
415                         if (count == 0)
416                                 return string.Format ("System.Windows.Forms.ToolBar, Button.Count: 0");
417                         else
418                                 return string.Format ("System.Windows.Forms.ToolBar, Button.Count: {0}, Buttons[0]: {1}",
419                                                       count, this.Buttons [0].ToString ());
420                 }
421                 #endregion Public Methods
422
423                 #region Protected Methods
424                 protected override void CreateHandle ()
425                 {
426                         base.CreateHandle ();
427                 }
428
429                 protected override void Dispose (bool disposing)
430                 {
431                         if (disposing)
432                                 ImageList = null;
433
434                         base.Dispose (disposing);
435                 }
436
437                 protected virtual void OnButtonClick (ToolBarButtonClickEventArgs e)
438                 {
439                         if (e.Button.Style == ToolBarButtonStyle.ToggleButton) {
440                                 if (! e.Button.Pushed)
441                                         e.Button.Pushed = true;
442                                 else
443                                         e.Button.Pushed = false;
444                         }
445                         e.Button.pressed = false;
446
447                         Invalidate (e.Button.Rectangle);
448
449                         if (ButtonClick != null)
450                                 ButtonClick (this, e);
451                 }
452
453                 protected virtual void OnButtonDropDown (ToolBarButtonClickEventArgs e) 
454                 {
455                         if (ButtonDropDown != null)
456                                 ButtonDropDown (this, e);
457
458                         if (e.Button.DropDownMenu == null)
459                                 return;
460
461                         Point loc = new Point (e.Button.Rectangle.X + 1, e.Button.Rectangle.Bottom + 1);
462                         ((ContextMenu) e.Button.DropDownMenu).Show (this, loc);
463
464                         e.Button.dd_pressed = false;
465                         Invalidate (e.Button.Rectangle);
466                 }
467
468                 protected override void OnFontChanged (EventArgs e)
469                 {
470                         base.OnFontChanged (e);
471                         Redraw (true);
472                 }
473
474                 protected override void OnHandleCreated (EventArgs e)
475                 {
476                         base.OnHandleCreated (e);
477                 }
478
479                 protected override void OnResize (EventArgs e)
480                 {
481                         base.OnResize (e);
482
483                         if (Width <= 0 || Height <= 0 || !Visible)
484                                 return;
485
486                         Redraw (true);
487                 }
488
489                 bool height_specified = false;
490                 int requested_height = -1;
491
492                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
493                 {
494                         if ((specified & BoundsSpecified.Height) != 0) {
495                                 requested_height = height;
496                                 height_specified = true;
497                         }
498                         base.SetBoundsCore (x, y, width, height, specified);
499                 }
500
501                 protected override void WndProc (ref Message m)
502                 {
503                         base.WndProc (ref m);
504                 }
505
506                 internal override bool InternalPreProcessMessage (ref Message msg)
507                 {
508                         if (msg.Msg == (int)Msg.WM_KEYDOWN) {
509                                 Keys key_data = (Keys)msg.WParam.ToInt32();
510                                 if (HandleKeyDown (key_data))
511                                         return true;
512                         } 
513                         return base.InternalPreProcessMessage (ref msg);
514                 }
515                         
516                 #endregion Protected Methods
517
518                 #region Private Methods
519                 private void FocusChanged (object sender, EventArgs args)
520                 {
521                         if (Appearance != ToolBarAppearance.Flat || Buttons.Count == 0)
522                                 return;
523
524                         ToolBarButton prelit = null;
525                         foreach (ToolBarButton b in Buttons)
526                                 if (b.Hilight) {
527                                         prelit = b;
528                                         break;
529                                 }
530
531                         if (Focused && prelit == null)
532                                 foreach (ToolBarButton btn in Buttons) {
533                                         if (btn.Enabled) {
534                                                 btn.Hilight = true;
535                                                 break;
536                                         }
537                                 }
538                         else if (prelit != null)
539                                 prelit.Hilight = false;
540                 }
541
542                 private bool HandleKeyDown (Keys key_data)
543                 {
544                         if (Appearance != ToolBarAppearance.Flat || Buttons.Count == 0)
545                                 return false;
546
547                         switch (key_data) {
548                         case Keys.Left:
549                         case Keys.Up:
550                                 HighlightButton (-1);
551                                 return true;
552                         case Keys.Right:
553                         case Keys.Down:
554                                 HighlightButton (1);
555                                 return true;
556                         default:
557                                 return false;
558                         }
559                 }
560
561                 void HighlightButton (int offset)
562                 {
563                         ArrayList enabled = new ArrayList ();
564                         int count = 0;
565                         int start = -1;
566                         ToolBarButton curr_button = null;
567                         foreach (ToolBarButton btn in Buttons) {
568                                 if (btn.Hilight) {
569                                         start = count;
570                                         curr_button = btn;
571                                 }
572
573                                 if (btn.Enabled) {
574                                         enabled.Add (btn);
575                                         count++;
576                                 }
577                         }
578
579                         int next = (start + offset) % count;
580                         if (next < 0)
581                                 next = count - 1;
582
583                         if (next == start)
584                                 return;
585
586                         if (curr_button != null)
587                                 curr_button.Hilight = false;
588                         (enabled [next] as ToolBarButton).Hilight = true;
589                 }
590
591                 private void ToolBar_MouseDown (object sender, MouseEventArgs me)
592                 {
593                         if (!Enabled) 
594                                 return;
595
596                         Point loc = new Point (me.X, me.Y);
597
598                         // draw the pushed button
599                         foreach (ToolBarButton button in buttons) {
600                                 if (button.Enabled && button.Rectangle.Contains (loc)) {
601                                         // Mark the DropDown rect as pressed.
602                                         // We don't redraw the dropdown rect.
603                                         if (button.Style == ToolBarButtonStyle.DropDownButton) {
604                                                 Rectangle rect = button.Rectangle;
605                                                 rect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
606                                                 rect.X = button.Rectangle.Right - rect.Width;
607                                                 if (rect.Contains (loc)) {
608                                                         if (button.DropDownMenu != null) {
609                                                                 button.dd_pressed = true;
610                                                                 Invalidate (rect);
611                                                         }
612                                                         break;
613                                                 }
614                                         }
615                                         button.pressed = true;
616                                         button.inside = true;
617                                         Invalidate (button.Rectangle);
618                                         break;
619                                 }
620                         }
621                 }
622
623                 private void ToolBar_MouseUp (object sender, MouseEventArgs me)
624                 {
625                         if (!Enabled) 
626                                 return;
627
628                         Point loc = new Point (me.X, me.Y);
629
630                         // draw the normal button
631                         // Make a copy in case the list is modified during enumeration
632                         ArrayList buttons = new ArrayList (this.buttons);
633                         foreach (ToolBarButton button in buttons) {
634                                 if (button.Enabled && button.Rectangle.Contains (loc)) {
635                                         if (button.Style == ToolBarButtonStyle.DropDownButton) {
636                                                 Rectangle ddRect = button.Rectangle;
637                                                 ddRect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
638                                                 ddRect.X = button.Rectangle.Right - ddRect.Width;
639                                                 if (ddRect.Contains (loc)) {
640                                                         if (button.dd_pressed)
641                                                                 OnButtonDropDown (new ToolBarButtonClickEventArgs (button));
642                                                         continue;
643                                                 }
644                                         }
645                                         // Fire a ButtonClick
646                                         if (button.pressed)
647                                                 OnButtonClick (new ToolBarButtonClickEventArgs (button));
648                                 } else if (button.pressed) {
649                                         button.pressed = false;
650                                         Invalidate (button.Rectangle);
651                                 }
652                         }
653                 }
654
655                 private void ToolBar_MouseLeave (object sender, EventArgs e)
656                 {
657                         if (!Enabled || appearance != ToolBarAppearance.Flat || current_button == null) 
658                                 return;
659
660                         if (current_button.Hilight) {
661                                 current_button.Hilight = false;
662                                 Invalidate (current_button.Rectangle);
663                         }
664                         current_button = null;
665                 }
666
667                 private void ToolBar_MouseMove (object sender, MouseEventArgs me)
668                 {
669                         if (!Enabled) 
670                                 return;
671
672                         Point loc = new Point (me.X, me.Y);
673
674                         if (this.Capture) {
675                                 // If the button was pressed and we leave, release the 
676                                 // button press and vice versa
677                                 foreach (ToolBarButton button in buttons) {
678                                         if (button.pressed &&
679                                             (button.inside != button.Rectangle.Contains (loc))) {
680                                                 button.inside = button.Rectangle.Contains (loc);
681                                                 button.Hilight = false;
682                                                 Invalidate (button.Rectangle);
683                                                 break;
684                                         }
685                                 }
686                         }
687                         // following is only for flat style toolbar
688                         else if (appearance == ToolBarAppearance.Flat) {
689                                 if (current_button != null && current_button.Rectangle.Contains (loc)) {
690                                         if (current_button.Hilight || current_button.Pushed)
691                                                 return;
692                                         current_button.Hilight = true;
693                                         Invalidate (current_button.Rectangle);
694                                 }
695                                 else {
696                                         foreach (ToolBarButton button in buttons) {
697                                                 if (button.Rectangle.Contains (loc) && button.Enabled) {
698                                                         current_button = button;
699                                                         if (current_button.Hilight || current_button.Pushed)
700                                                                 continue;
701                                                         current_button.Hilight = true;
702                                                         Invalidate (current_button.Rectangle);
703                                                 }
704                                                 else if (button.Hilight) {
705                                                         button.Hilight = false;
706                                                         Invalidate (button.Rectangle);
707                                                 }
708                                         }
709                                 }
710                         }
711                 }
712
713                 internal override void OnPaintInternal (PaintEventArgs pevent)
714                 {
715                         ThemeEngine.Current.DrawToolBar (pevent.Graphics, pevent.ClipRectangle, this);
716                 }
717
718                 internal void Redraw (bool recalculate)
719                 {
720                         if (recalculate)
721                                 Layout ();
722
723                         Invalidate ();
724                 }
725
726                 internal bool SizeSpecified {
727                         get { return size_specified; }
728                 }
729
730                 const int text_padding = 3;
731
732                 private Size CalcButtonSize ()
733                 {
734                         if (Buttons.Count == 0)
735                                 return Size.Empty;
736
737                         string longest_text = Buttons [0].Text;
738                         for (int i = 1; i < Buttons.Count; i++) {
739                                 if (Buttons[i].Text.Length > longest_text.Length)
740                                         longest_text = Buttons[i].Text;
741                         }
742
743                         Size size = Size.Empty;
744                         if (longest_text != null && longest_text.Length > 0) {
745                                 SizeF sz = DeviceContext.MeasureString (longest_text, Font);
746                                 if (sz != SizeF.Empty)
747                                         size = new Size ((int) Math.Ceiling (sz.Width) + 2 * text_padding, (int) Math.Ceiling (sz.Height));
748                         }
749
750                         Size img_size = ImageList == null ? new Size (16, 16) : ImageSize;
751
752                         Theme theme = ThemeEngine.Current;
753                         int imgWidth = img_size.Width + 2 * theme.ToolBarImageGripWidth; 
754                         int imgHeight = img_size.Height + 2 * theme.ToolBarImageGripWidth;
755
756                         if (text_alignment == ToolBarTextAlign.Right) {
757                                 size.Width = imgWidth + size.Width;
758                                 size.Height = (size.Height > imgHeight) ? size.Height : imgHeight;
759                         } else {
760                                 size.Height = imgHeight + size.Height;
761                                 size.Width = (size.Width > imgWidth) ? size.Width : imgWidth;
762                         }
763
764                         size.Width += theme.ToolBarImageGripWidth;
765                         size.Height += theme.ToolBarImageGripWidth;
766                         return size;
767                 }
768
769                 // Flat toolbars disregard specified sizes.  Normal toolbars grow the
770                 // button size to be at least large enough to show the image.
771                 Size AdjustedButtonSize {
772                         get {
773                                 Size size = ButtonSize;
774                                 if (size_specified) {
775                                         if (Appearance == ToolBarAppearance.Flat)
776                                                 size = CalcButtonSize ();
777                                         else {
778                                                 int grip = ThemeEngine.Current.ToolBarImageGripWidth;
779                                                 if (size.Width < ImageSize.Width + 2 * grip )
780                                                         size.Width = ImageSize.Width + 2 * grip;
781                                                 if (size.Height < ImageSize.Height + 2 * grip)
782                                                         size.Height = ImageSize.Height + 2 * grip;
783                                         }
784                                 }
785                                 return size;
786                         }
787                 }
788
789                 void Layout ()
790                 {
791                         Theme theme = ThemeEngine.Current;
792                         int x = theme.ToolBarGripWidth;
793                         int y = theme.ToolBarGripWidth;
794
795                         Size button_size = AdjustedButtonSize;
796
797                         int ht = button_size.Height + theme.ToolBarGripWidth;
798
799                         if (Wrappable && Parent != null) {
800                                 int separator_index = -1;
801
802                                 for (int i = 0; i < buttons.Count; i++) {
803                                         ToolBarButton button = buttons [i];
804
805                                         if (!button.Visible)
806                                                 continue;
807
808                                         if (size_specified)
809                                                 button.Layout (button_size);
810                                         else
811                                                 button.Layout ();
812
813                                         bool is_separator = button.Style == ToolBarButtonStyle.Separator;
814
815                                         if (x + button.Rectangle.Width < Width || is_separator) {
816                                                 button.Location = new Point (x, y);
817                                                 x += button.Rectangle.Width;
818                                                 if (is_separator)
819                                                         separator_index = i;
820                                         } else if (separator_index > 0) { 
821                                                 i = separator_index;
822                                                 separator_index = -1;
823                                                 x = theme.ToolBarGripWidth;
824                                                 y += ht; 
825                                         } else {
826                                                 x = theme.ToolBarGripWidth;
827                                                 y += ht; 
828                                                 button.Location = new Point (x, y);
829                                                 x += button.Rectangle.Width;
830                                         }
831                                 }
832                                 if (AutoSize)
833                                         Height = y + ht;
834                         } else {
835                                 if (AutoSize)
836                                         Height = ht;
837                                 else if (!height_specified)
838                                         Height = DefaultSize.Height;
839                                 foreach (ToolBarButton button in buttons) {
840                                         if (size_specified)
841                                                 button.Layout (button_size);
842                                         else
843                                                 button.Layout ();
844                                         button.Location = new Point (x, y);
845                                         x += button.Rectangle.Width;
846                                 }
847                         }
848                 }
849                 #endregion Private Methods
850
851                 #region subclass
852                 public class ToolBarButtonCollection : IList, ICollection, IEnumerable
853                 {
854                         #region instance variables
855                         private ArrayList list;
856                         private ToolBar owner;
857                         #endregion
858
859                         #region constructors
860                         public ToolBarButtonCollection (ToolBar owner)
861                         {
862                                 this.owner = owner;
863                                 list = new ArrayList ();
864                         }
865                         #endregion
866
867                         #region properties
868                         [Browsable (false)]
869                         public int Count {
870                                 get { return list.Count; }
871                         }
872
873                         public bool IsReadOnly {
874                                 get { return list.IsReadOnly; }
875                         }
876
877                         public virtual ToolBarButton this [int index] {
878                                 get { return (ToolBarButton) list [index]; }
879                                 set {
880                                         value.SetParent (owner);
881                                         list [index] = value;
882                                         owner.Redraw (true);
883                                 }
884                         }
885
886                         bool ICollection.IsSynchronized {
887                                 get { return list.IsSynchronized; }
888                         }
889
890                         object ICollection.SyncRoot {
891                                 get { return list.SyncRoot; }
892                         }
893
894                         bool IList.IsFixedSize {
895                                 get { return list.IsFixedSize; }
896                         }
897
898                         object IList.this [int index] {
899                                 get { return this [index]; }
900                                 set {
901                                         if (! (value is ToolBarButton))
902                                                 throw new ArgumentException("Not of type ToolBarButton", "value");
903                                         this [index] = (ToolBarButton) value;
904                                 }
905                         }
906                         #endregion
907
908                         #region methods
909                         public int Add (string text)
910                         {
911                                 ToolBarButton button = new ToolBarButton (text);
912                                 return this.Add (button);
913                         }
914
915                         public int Add (ToolBarButton button)
916                         {
917                                 int result;
918                                 button.SetParent (owner);
919                                 result = list.Add (button);
920                                 owner.Redraw (true);
921                                 return result;
922                         }
923
924                         public void AddRange (ToolBarButton [] buttons)
925                         {
926                                 foreach (ToolBarButton button in buttons)
927                                         Add (button);
928                         }
929
930                         public void Clear ()
931                         {
932                                 list.Clear ();
933                                 owner.Redraw (false);
934                         }
935
936                         public bool Contains (ToolBarButton button)
937                         {
938                                 return list.Contains (button);
939                         }
940
941                         public IEnumerator GetEnumerator ()
942                         {
943                                 return list.GetEnumerator ();
944                         }
945
946                         void ICollection.CopyTo (Array dest, int index)
947                         {
948                                 list.CopyTo (dest, index);
949                         }
950
951                         int IList.Add (object button)
952                         {
953                                 if (! (button is ToolBarButton)) {
954                                         throw new ArgumentException("Not of type ToolBarButton", "button");
955                                 }
956
957                                 return this.Add ((ToolBarButton) button);
958                         }
959
960                         bool IList.Contains (object button)
961                         {
962                                 if (! (button is ToolBarButton)) {
963                                         throw new ArgumentException("Not of type ToolBarButton", "button");
964                                 }
965
966                                 return this.Contains ((ToolBarButton) button);
967                         }
968
969                         int IList.IndexOf (object button)
970                         {
971                                 if (! (button is ToolBarButton)) {
972                                         throw new ArgumentException("Not of type ToolBarButton", "button");
973                                 }
974
975                                 return this.IndexOf ((ToolBarButton) button);
976                         }
977
978                         void IList.Insert (int index, object button)
979                         {
980                                 if (! (button is ToolBarButton)) {
981                                         throw new ArgumentException("Not of type ToolBarButton", "button");
982                                 }
983
984                                 this.Insert (index, (ToolBarButton) button);
985                         }
986
987                         void IList.Remove (object button)
988                         {
989                                 if (! (button is ToolBarButton)) {
990                                         throw new ArgumentException("Not of type ToolBarButton", "button");
991                                 }
992
993                                 this.Remove ((ToolBarButton) button);
994                         }
995
996                         public int IndexOf (ToolBarButton button)
997                         {
998                                 return list.IndexOf (button);
999                         }
1000
1001                         public void Insert (int index, ToolBarButton button)
1002                         {
1003                                 list.Insert (index, button);
1004                                 owner.Redraw (true);
1005                         }
1006
1007                         public void Remove (ToolBarButton button)
1008                         {
1009                                 list.Remove (button);
1010                                 owner.Redraw (true);
1011                         }
1012
1013                         public void RemoveAt (int index)
1014                         {
1015                                 list.RemoveAt (index);
1016                                 owner.Redraw (true);
1017                         }
1018                         #endregion methods
1019                 }
1020                 #endregion subclass
1021         }
1022 }