Merge branch 'sgen-android'
[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 //      Everaldo Canuto <ecanuto@novell.com>
26 //
27 // Copyright (C) 2004-2006  Novell, Inc. (http://www.novell.com)
28 //
29
30 using System.Collections;
31 using System.ComponentModel;
32 using System.ComponentModel.Design;
33 using System.Drawing;
34 using System.Drawing.Text;
35 using System.Drawing.Imaging;
36 using System.Runtime.InteropServices;
37
38 namespace System.Windows.Forms
39 {
40         [ComVisible (true)]
41         [ClassInterface (ClassInterfaceType.AutoDispatch)]
42         [DefaultEvent ("ButtonClick")]
43         [DefaultProperty ("Buttons")]
44         [Designer ("System.Windows.Forms.Design.ToolBarDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
45         public class ToolBar : Control
46         {
47                 #region Instance Variables
48                 private bool size_specified = false;
49                 private ToolBarItem current_item;
50                 internal ToolBarItem[] items;
51                 internal Size default_size;
52                 #endregion Instance Variables
53
54                 #region Events
55                 static object ButtonClickEvent = new object ();
56                 static object ButtonDropDownEvent = new object ();
57
58                 [Browsable (true)]
59                 [EditorBrowsable (EditorBrowsableState.Always)]
60                 public new event EventHandler AutoSizeChanged {
61                         add { base.AutoSizeChanged += value; }
62                         remove { base.AutoSizeChanged -= value; }
63                 }
64
65                 [Browsable (false)]
66                 [EditorBrowsable (EditorBrowsableState.Never)]
67                 public new event EventHandler BackColorChanged {
68                         add { base.BackColorChanged += value; }
69                         remove { base.BackColorChanged -= value; }
70                 }
71
72                 [Browsable (false)]
73                 [EditorBrowsable (EditorBrowsableState.Never)]
74                 public new event EventHandler BackgroundImageChanged {
75                         add { base.BackgroundImageChanged += value; }
76                         remove { base.BackgroundImageChanged -= value; }
77                 }
78
79                 [Browsable (false)]
80                 [EditorBrowsable (EditorBrowsableState.Never)]
81                 public new event EventHandler BackgroundImageLayoutChanged {
82                         add { base.BackgroundImageLayoutChanged += value; }
83                         remove { base.BackgroundImageLayoutChanged -= value; }
84                 }
85
86                 public event ToolBarButtonClickEventHandler ButtonClick {
87                         add { Events.AddHandler (ButtonClickEvent, value); }
88                         remove {Events.RemoveHandler (ButtonClickEvent, value); }
89                 }
90
91                 public event ToolBarButtonClickEventHandler ButtonDropDown {
92                         add { Events.AddHandler (ButtonDropDownEvent, value); }
93                         remove {Events.RemoveHandler (ButtonDropDownEvent, value); }
94                 }
95
96                 [Browsable (false)]
97                 [EditorBrowsable (EditorBrowsableState.Never)]
98                 public new event EventHandler ForeColorChanged {
99                         add { base.ForeColorChanged += value; }
100                         remove { base.ForeColorChanged -= value; }
101                 }
102
103                 [Browsable (false)]
104                 [EditorBrowsable (EditorBrowsableState.Never)]
105                 public new event EventHandler ImeModeChanged {
106                         add { base.ImeModeChanged += value; }
107                         remove { base.ImeModeChanged -= value; }
108                 }
109
110                 [Browsable (false)]
111                 [EditorBrowsable (EditorBrowsableState.Never)]
112                 public new event PaintEventHandler Paint {
113                         add { base.Paint += value; }
114                         remove { base.Paint -= value; }
115                 }
116
117                 [Browsable (false)]
118                 [EditorBrowsable (EditorBrowsableState.Never)]
119                 public new event EventHandler RightToLeftChanged {
120                         add { base.RightToLeftChanged += value; }
121                         remove { base.RightToLeftChanged -= value; }
122                 }
123
124                 [Browsable (false)]
125                 [EditorBrowsable (EditorBrowsableState.Never)]
126                 public new event EventHandler TextChanged {
127                         add { base.TextChanged += value; }
128                         remove { base.TextChanged -= value; }
129                 }
130                 #endregion Events
131
132                 #region Constructor
133                 public ToolBar ()
134                 {
135                         background_color = ThemeEngine.Current.DefaultControlBackColor;
136                         foreground_color = ThemeEngine.Current.DefaultControlForeColor;
137                         buttons = new ToolBarButtonCollection (this);
138                         Dock = DockStyle.Top;
139                         
140                         GotFocus += new EventHandler (FocusChanged);
141                         LostFocus += new EventHandler (FocusChanged);
142                         MouseDown += new MouseEventHandler (ToolBar_MouseDown);
143                         MouseHover += new EventHandler (ToolBar_MouseHover);
144                         MouseLeave += new EventHandler (ToolBar_MouseLeave);
145                         MouseMove += new MouseEventHandler (ToolBar_MouseMove);
146                         MouseUp += new MouseEventHandler (ToolBar_MouseUp);
147                         BackgroundImageChanged += new EventHandler (ToolBar_BackgroundImageChanged);
148
149                         TabStop = false;
150                         
151                         SetStyle (ControlStyles.UserPaint, false);
152                         SetStyle (ControlStyles.FixedHeight, true);
153                         SetStyle (ControlStyles.FixedWidth, false);
154                 }
155                 #endregion Constructor
156
157                 #region protected Properties
158                 protected override CreateParams CreateParams {
159                         get { 
160                                 CreateParams create_params = base.CreateParams;
161                                 
162                                 if (appearance == ToolBarAppearance.Flat) {
163                                         create_params.Style |= (int) ToolBarStyles.TBSTYLE_FLAT;
164                                 }
165                                 
166                                 return create_params;
167                         }
168                 }
169
170                 protected override ImeMode DefaultImeMode {
171                         get { return ImeMode.Disable; }
172                 }
173
174                 protected override Size DefaultSize {
175                         get { return ThemeEngine.Current.ToolBarDefaultSize; }
176                 }
177
178                 [EditorBrowsable (EditorBrowsableState.Never)]
179                 protected override bool DoubleBuffered {
180                         get { return base.DoubleBuffered; }
181                         set { base.DoubleBuffered = value; }
182                 }
183                 #endregion
184
185                 ToolBarAppearance appearance = ToolBarAppearance.Normal;
186
187                 #region Public Properties
188                 [DefaultValue (ToolBarAppearance.Normal)]
189                 [Localizable (true)]
190                 public ToolBarAppearance Appearance {
191                         get { return appearance; }
192                         set {
193                                 if (value == appearance)
194                                         return;
195
196                                 appearance = value;
197                                 Redraw (true);
198                         }
199                 }
200
201                 bool autosize = true;
202
203                 [Browsable (true)]
204                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
205                 [EditorBrowsable (EditorBrowsableState.Always)]
206                 [DefaultValue (true)]
207                 [Localizable (true)]
208                 public override bool AutoSize {
209                         get { return autosize; }
210                         set {
211                                 if (value == autosize)
212                                         return;
213
214                                 autosize = value;
215                                 
216                                 if (IsHandleCreated)
217                                         Redraw (true);
218                         }
219                 }
220
221                 [Browsable (false)]
222                 [EditorBrowsable (EditorBrowsableState.Never)]
223                 public override Color BackColor {
224                         get { return background_color; }
225                         set {
226                                 if (value == background_color)
227                                         return;
228
229                                 background_color = value;
230                                 OnBackColorChanged (EventArgs.Empty);
231                                 Redraw (false);
232                         }
233                 }
234
235                 [Browsable (false)]
236                 [EditorBrowsable (EditorBrowsableState.Never)]
237                 public override Image BackgroundImage {
238                         get { return base.BackgroundImage; }
239                         set { base.BackgroundImage = value; }
240                 }
241
242                 [Browsable (false)]
243                 [EditorBrowsable (EditorBrowsableState.Never)]
244                 public override ImageLayout BackgroundImageLayout {
245                         get { return base.BackgroundImageLayout; }
246                         set { base.BackgroundImageLayout = value; }
247                 }
248
249                 [DefaultValue (BorderStyle.None)]
250                 [DispIdAttribute (-504)]
251                 public BorderStyle BorderStyle {
252                         get { return InternalBorderStyle; }
253                         set { InternalBorderStyle = value; }
254                 }
255
256                 ToolBarButtonCollection buttons;
257
258                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
259                 [Localizable (true)]
260                 [MergableProperty (false)]
261                 public ToolBarButtonCollection Buttons {
262                         get { return buttons; }
263                 }
264
265                 Size button_size;
266
267                 [Localizable (true)]
268                 [RefreshProperties (RefreshProperties.All)]
269                 public Size ButtonSize {
270                         get {
271                                 if (!button_size.IsEmpty)
272                                         return button_size; 
273                                 
274                                 if (buttons.Count == 0)
275                                         return new Size (39, 36);
276                                         
277                                 Size result = CalcButtonSize ();
278                                 if (result.IsEmpty)
279                                         return new Size (24, 22);
280                                 else
281                                         return result;
282                         }
283                         set {
284                                 size_specified = value != Size.Empty;
285                                 if (button_size == value)
286                                         return;
287
288                                 button_size = value;
289                                 Redraw (true);
290                         }
291                 }
292
293                 bool divider = true;
294
295                 [DefaultValue (true)]
296                 public bool Divider {
297                         get { return divider; }
298                         set {
299                                 if (value == divider)
300                                         return;
301
302                                 divider = value;
303                                 Redraw (false);
304                         }
305                 }
306
307                 [DefaultValue (DockStyle.Top)]
308                 [Localizable (true)]
309                 public override DockStyle Dock {
310                         get { return base.Dock; }
311                         set {
312                                 if (base.Dock == value) {
313                                         // Call base anyways so layout_type gets set correctly
314                                         if (value != DockStyle.None)
315                                                 base.Dock = value;
316                                         return;
317                                 }
318                                         
319                                 if (Vertical) {
320                                         SetStyle (ControlStyles.FixedWidth, AutoSize);
321                                         SetStyle (ControlStyles.FixedHeight, false);
322                                 } else {
323                                         SetStyle (ControlStyles.FixedHeight, AutoSize);
324                                         SetStyle (ControlStyles.FixedWidth, false);
325                                 }
326                                 
327                                 LayoutToolBar ();
328                                 
329                                 base.Dock = value;
330                         }
331                 }
332
333                 bool drop_down_arrows = true;
334
335                 [DefaultValue (false)]
336                 [Localizable (true)]
337                 public bool DropDownArrows {
338                         get { return drop_down_arrows; }
339                         set {
340                                 if (value == drop_down_arrows)
341                                         return;
342
343                                 drop_down_arrows = value;
344                                 Redraw (true);
345                         }
346                 }
347
348                 [Browsable (false)]
349                 [EditorBrowsable (EditorBrowsableState.Never)]
350                 public override Color ForeColor {
351                         get { return foreground_color; }
352                         set {
353                                 if (value == foreground_color)
354                                         return;
355
356                                 foreground_color = value;
357                                 OnForeColorChanged (EventArgs.Empty);
358                                 Redraw (false);
359                         }
360                 }
361
362                 ImageList image_list;
363
364                 [DefaultValue (null)]
365                 public ImageList ImageList {
366                         get { return image_list; }
367                         set { 
368                                 if (image_list == value)
369                                         return;
370                                 image_list = value;
371                                 Redraw (true);
372                         }
373                 }
374
375                 [Browsable (false)]
376                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
377                 [EditorBrowsable (EditorBrowsableState.Advanced)]
378                 public Size ImageSize {
379                         get {
380                                 if (ImageList == null)
381                                         return Size.Empty;
382
383                                 return ImageList.ImageSize;
384                         }
385                 }
386
387                 // XXX this should probably go away and it should call
388                 // into Control.ImeMode instead.
389                 ImeMode ime_mode = ImeMode.Disable;
390
391                 [Browsable (false)]
392                 [EditorBrowsable (EditorBrowsableState.Never)]
393                 public new ImeMode ImeMode {
394                         get { return ime_mode; }
395                         set {
396                                 if (value == ime_mode)
397                                         return;
398
399                                 ime_mode = value;
400                                 OnImeModeChanged (EventArgs.Empty);
401                         }
402                 }
403
404                 [Browsable (false)]
405                 [EditorBrowsable (EditorBrowsableState.Never)]
406                 public override RightToLeft RightToLeft {
407                         get { return base.RightToLeft; }
408                         set {
409                                 if (value == base.RightToLeft)
410                                         return;
411
412                                 base.RightToLeft = value;
413                                 OnRightToLeftChanged (EventArgs.Empty);
414                         }
415                 }
416
417                 // Default value is "false" but after make a test in .NET we get "true" result as default.  
418                 bool show_tooltips = true;
419
420                 [DefaultValue (false)]
421                 [Localizable (true)]
422                 public bool ShowToolTips {
423                         get { return show_tooltips; }
424                         set { show_tooltips = value; }
425                 }
426
427                 [DefaultValue (false)]
428                 public new bool TabStop {
429                         get { return base.TabStop; }
430                         set { base.TabStop = value; }
431                 }
432
433                 [Bindable (false)]
434                 [Browsable (false)]
435                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
436                 [EditorBrowsable (EditorBrowsableState.Never)]
437                 public override string Text {
438                         get { return base.Text; } 
439                         set {
440                                 if (value == base.Text)
441                                         return;
442
443                                 base.Text = value;
444                                 Redraw (true);
445                         }
446                 }
447
448                 ToolBarTextAlign text_alignment = ToolBarTextAlign.Underneath;
449
450                 [DefaultValue (ToolBarTextAlign.Underneath)]
451                 [Localizable (true)]
452                 public ToolBarTextAlign TextAlign {
453                         get { return text_alignment; }
454                         set {
455                                 if (value == text_alignment)
456                                         return;
457
458                                 text_alignment = value;
459                                 Redraw (true);
460                         }
461                 }
462
463                 bool wrappable = true;
464
465                 [DefaultValue (true)]
466                 [Localizable (true)]
467                 public bool Wrappable {
468                         get { return wrappable; }
469                         set {
470                                 if (value == wrappable)
471                                         return;
472
473                                 wrappable = value;
474                                 Redraw (true);
475                         }
476                 }
477                 #endregion Public Properties
478
479                 #region Public Methods
480                 public override string ToString ()
481                 {
482                         int count = this.Buttons.Count;
483
484                         if (count == 0)
485                                 return string.Format ("System.Windows.Forms.ToolBar, Buttons.Count: 0");
486                         else
487                                 return string.Format ("System.Windows.Forms.ToolBar, Buttons.Count: {0}, Buttons[0]: {1}",
488                                                       count, this.Buttons [0].ToString ());
489                 }
490                 #endregion Public Methods
491
492                 #region Protected Methods
493                 protected override void CreateHandle ()
494                 {
495                         base.CreateHandle ();
496                         default_size = CalcButtonSize ();
497                         
498                         // In win32 the recalculate size only happens for not flat style
499                         if (appearance != ToolBarAppearance.Flat)
500                                 Redraw (true);
501                 }
502
503                 protected override void Dispose (bool disposing)
504                 {
505                         if (disposing)
506                                 ImageList = null;
507
508                         base.Dispose (disposing);
509                 }
510
511                 private ToolBarButton button_for_focus = null;
512                 
513                 internal void UIAPerformClick (ToolBarButton button)
514                 {
515                         ToolBarItem previous_item = current_item;
516                         current_item = null;
517                         
518                         foreach (ToolBarItem item in items)
519                                 if (item.Button == button) {
520                                         current_item = item;
521                                         break;
522                                 }
523
524                         try {
525                                 if (current_item == null)
526                                         throw new ArgumentException ("button", "The button specified is not part of this toolbar");
527                                 PerformButtonClick (new ToolBarButtonClickEventArgs (button));
528                         } finally {
529                                 current_item = previous_item;
530                         }
531                 }
532                 
533                 void PerformButtonClick (ToolBarButtonClickEventArgs e)
534                 {
535                         // Only change pushed for ToogleButton
536                         if (e.Button.Style == ToolBarButtonStyle.ToggleButton) {
537                                 if (! e.Button.Pushed)
538                                         e.Button.Pushed = true;
539                                 else
540                                         e.Button.Pushed = false;
541                         }
542                         
543                         current_item.Pressed = false;
544                         current_item.Invalidate ();
545                         
546                         button_for_focus = current_item.Button;
547                         button_for_focus.UIAHasFocus = true;
548
549                         OnButtonClick (e);
550                 }
551
552                 protected virtual void OnButtonClick (ToolBarButtonClickEventArgs e)
553                 {                       
554                         ToolBarButtonClickEventHandler eh = (ToolBarButtonClickEventHandler)(Events [ButtonClickEvent]);
555                         if (eh != null)
556                                 eh (this, e);
557                 }
558
559                 protected virtual void OnButtonDropDown (ToolBarButtonClickEventArgs e) 
560                 {
561                         ToolBarButtonClickEventHandler eh = (ToolBarButtonClickEventHandler)(Events [ButtonDropDownEvent]);
562                         if (eh != null)
563                                 eh (this, e);
564
565                         if (e.Button.DropDownMenu == null)
566                                 return;
567
568                         ShowDropDownMenu (current_item);
569                 }
570
571                 internal void ShowDropDownMenu (ToolBarItem item)
572                 {
573                         Point loc = new Point (item.Rectangle.X + 1, item.Rectangle.Bottom + 1);
574                         ((ContextMenu) item.Button.DropDownMenu).Show (this, loc);
575
576                         item.DDPressed = false;
577                         item.Hilight = false;
578                         item.Invalidate ();
579                 }
580
581                 protected override void OnFontChanged (EventArgs e)
582                 {
583                         base.OnFontChanged (e);
584                         Redraw (true);
585                 }
586
587                 protected override void OnHandleCreated (EventArgs e)
588                 {
589                         base.OnHandleCreated (e);
590                 }
591
592                 protected override void OnResize (EventArgs e)
593                 {
594                         base.OnResize (e);
595                         LayoutToolBar ();
596                 }
597
598                 protected override void ScaleControl (SizeF factor, BoundsSpecified specified)
599                 {
600                         specified &= ~BoundsSpecified.Height;
601                         
602                         base.ScaleControl (factor, specified);
603                 }
604
605                 [EditorBrowsable (EditorBrowsableState.Never)]
606                 protected override void ScaleCore (float dx, float dy)
607                 {
608                         dy = 1.0f;
609                         
610                         base.ScaleCore (dx, dy);
611                 }
612
613                 private int requested_size = -1;
614
615                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
616                 {
617                         if (Vertical) {
618                                 if (!AutoSize && (requested_size != width) && ((specified & BoundsSpecified.Width) != BoundsSpecified.None)) 
619                                         requested_size = width;
620                         } else {
621                                 if (!AutoSize && (requested_size != height) && ((specified & BoundsSpecified.Height) != BoundsSpecified.None)) 
622                                         requested_size = height;
623                         }
624                         
625                         base.SetBoundsCore (x, y, width, height, specified);
626                 }
627
628                 protected override void WndProc (ref Message m)
629                 {
630                         base.WndProc (ref m);
631                 }
632
633                 internal override bool InternalPreProcessMessage (ref Message msg)
634                 {
635                         if (msg.Msg == (int)Msg.WM_KEYDOWN) {
636                                 Keys key_data = (Keys)msg.WParam.ToInt32();
637                                 if (HandleKeyDown (ref msg, key_data))
638                                         return true;
639                         } 
640                         return base.InternalPreProcessMessage (ref msg);
641                 }
642                         
643                 #endregion Protected Methods
644
645                 #region Private Methods
646                 internal int CurrentItem {
647                         get {
648                                 return Array.IndexOf (items, current_item);
649                         }
650                         set {
651                                 if (current_item != null)
652                                         current_item.Hilight = false;
653
654                                 current_item = value == -1 ? null : items [value];
655
656                                 if (current_item != null)
657                                         current_item.Hilight = true;
658                         }
659
660                 }
661
662                 private void FocusChanged (object sender, EventArgs args)
663                 {
664                         if (!Focused && button_for_focus != null)
665                                 button_for_focus.UIAHasFocus = false;
666                         button_for_focus = null;
667                         
668                         if (Appearance != ToolBarAppearance.Flat || Buttons.Count == 0)
669                                 return;
670
671                         ToolBarItem prelit = null;
672                         foreach (ToolBarItem item in items) {
673                                 if (item.Hilight) {
674                                         prelit = item;
675                                         break;
676                                 }
677                         }
678
679                         if (Focused && prelit == null) {
680                                 foreach (ToolBarItem item in items) {
681                                         if (item.Button.Enabled) {
682                                                 item.Hilight = true;
683                                                 break;
684                                         }
685                                 }
686                         } else if (prelit != null) {
687                                 prelit.Hilight = false;
688                         }
689                 }
690
691                 private bool HandleKeyDown (ref Message msg, Keys key_data)
692                 {
693                         if (Appearance != ToolBarAppearance.Flat || Buttons.Count == 0)
694                                 return false;
695
696                         // Handle the key as needed if the current item is a dropdownbutton.
697                         if (HandleKeyOnDropDown (ref msg, key_data))
698                                 return true;
699
700                         switch (key_data) {
701                                 case Keys.Left:
702                                 case Keys.Up:
703                                         HighlightButton (-1);
704                                         return true;
705                                 case Keys.Right:
706                                 case Keys.Down:
707                                         HighlightButton (1);
708                                         return true;
709                                 case Keys.Enter:
710                                 case Keys.Space:
711                                         if (current_item != null) {
712                                                 OnButtonClick (new ToolBarButtonClickEventArgs (current_item.Button));
713                                                 return true;
714                                         }
715                                         break;
716                         }
717
718                         return false;
719                 }
720
721                 bool HandleKeyOnDropDown (ref Message msg, Keys key_data)
722                 {
723                         if (current_item == null || current_item.Button.Style != ToolBarButtonStyle.DropDownButton ||
724                                         current_item.Button.DropDownMenu == null)
725                                 return false;
726
727                         Menu dropdown_menu = current_item.Button.DropDownMenu;
728
729                         if (dropdown_menu.Tracker.active) {
730                                 dropdown_menu.ProcessCmdKey (ref msg, key_data);
731                                 return true; // always true if the menu is active
732                         }
733
734                         if (key_data == Keys.Up || key_data == Keys.Down) {
735                                 current_item.DDPressed = true;
736                                 current_item.Invalidate ();
737                                 OnButtonDropDown (new ToolBarButtonClickEventArgs (current_item.Button));
738                                 return true;
739                         }
740
741                         return false;
742                 }
743
744                 void HighlightButton (int offset)
745                 {
746                         ArrayList enabled = new ArrayList ();
747                         int count = 0;
748                         int start = -1;
749                         ToolBarItem curr_item = null;
750                         foreach (ToolBarItem item in items) {
751                                 if (item.Hilight) {
752                                         start = count;
753                                         curr_item = item;
754                                 }
755
756                                 if (item.Button.Enabled) {
757                                         enabled.Add (item);
758                                         count++;
759                                 }
760                         }
761
762                         int next = (start + offset) % count;
763                         if (next < 0)
764                                 next = count - 1;
765
766                         if (next == start)
767                                 return;
768
769                         if (curr_item != null)
770                                 curr_item.Hilight = false;
771
772                         current_item = enabled [next] as ToolBarItem;
773                         current_item.Hilight = true;
774                 }
775
776                 private void ToolBar_BackgroundImageChanged (object sender, EventArgs args)
777                 {
778                         Redraw (false, true);
779                 }
780
781                 private void ToolBar_MouseDown (object sender, MouseEventArgs me)
782                 {
783                         if ((!Enabled) || ((me.Button & MouseButtons.Left) == 0))
784                                 return;
785
786                         Point loc = new Point (me.X, me.Y);
787
788                         if (ItemAtPoint (loc) == null)
789                                 return;
790                         
791                         // Hide tooltip when left mouse button 
792                         if ((tip_window != null) && (tip_window.Visible) && ((me.Button & MouseButtons.Left) == MouseButtons.Left)) {
793                                 TipDownTimer.Stop ();
794                                 tip_window.Hide (this);
795                         }
796                         
797                         // draw the pushed button
798                         foreach (ToolBarItem item in items) {
799                                 if (item.Button.Enabled && item.Rectangle.Contains (loc)) {
800                                         // Mark the DropDown rect as pressed.
801                                         // We don't redraw the dropdown rect.
802                                         if (item.Button.Style == ToolBarButtonStyle.DropDownButton) {
803                                                 Rectangle rect = item.Rectangle;
804                                                 if (DropDownArrows) {
805                                                         rect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
806                                                         rect.X = item.Rectangle.Right - rect.Width;
807                                                 }
808                                                 
809                                                 if (rect.Contains (loc)) {
810                                                         if (item.Button.DropDownMenu != null) {
811                                                                 item.DDPressed = true;
812                                                                 Invalidate (rect);
813                                                         }
814                                                         break;
815                                                 }
816                                         }
817                                         item.Pressed = true;
818                                         item.Inside = true;
819                                         item.Invalidate ();
820                                         break;
821                                 }
822                         }
823                 }
824
825                 private void ToolBar_MouseUp (object sender, MouseEventArgs me)
826                 {
827                         if ((!Enabled) || ((me.Button & MouseButtons.Left) == 0))
828                                 return;
829
830                         Point loc = new Point (me.X, me.Y);
831
832                         // draw the normal button
833                         // Make a copy in case the list is modified during enumeration
834                         ArrayList items = new ArrayList (this.items);
835                         foreach (ToolBarItem item in items) {
836                                 if (item.Button.Enabled && item.Rectangle.Contains (loc)) {
837                                         if (item.Button.Style == ToolBarButtonStyle.DropDownButton) {
838                                                 Rectangle ddRect = item.Rectangle;
839                                                 ddRect.Width = ThemeEngine.Current.ToolBarDropDownWidth;
840                                                 ddRect.X = item.Rectangle.Right - ddRect.Width;
841                                                 if (ddRect.Contains (loc)) {
842                                                         current_item = item;
843                                                         if (item.DDPressed)
844                                                                 OnButtonDropDown (new ToolBarButtonClickEventArgs (item.Button));
845                                                         continue;
846                                                 }
847                                         }
848                                         // Fire a ButtonClick
849                                         current_item = item;
850                                         if ((item.Pressed) && ((me.Button & MouseButtons.Left) == MouseButtons.Left))
851                                                 PerformButtonClick (new ToolBarButtonClickEventArgs (item.Button));
852                                 } else if (item.Pressed) {
853                                         item.Pressed = false;
854                                         item.Invalidate ();
855                                 }
856                         }
857                 }
858
859                 private ToolBarItem ItemAtPoint (Point pt)
860                 {
861                         foreach (ToolBarItem item in items)
862                                 if (item.Rectangle.Contains (pt)) 
863                                         return item;
864
865                         return null;
866                 }
867
868                 ToolTip tip_window = null;
869                 Timer tipdown_timer = null;
870
871                 private void PopDownTip (object o, EventArgs args)
872                 {
873                         tip_window.Hide (this);
874                 }
875
876                 private Timer TipDownTimer {
877                         get {
878                                 if (tipdown_timer == null) {
879                                         tipdown_timer = new Timer ();
880                                         tipdown_timer.Enabled = false;
881                                         tipdown_timer.Interval = 5000;
882                                         tipdown_timer.Tick += new EventHandler (PopDownTip);
883                                 }
884                                 return tipdown_timer;
885                         }
886                 }
887
888                 private void ToolBar_MouseHover (object sender, EventArgs e)
889                 {
890                         if (Capture)
891                                 return;
892
893                         if (tip_window == null)
894                                 tip_window = new ToolTip ();
895
896                         ToolBarItem item = ItemAtPoint (PointToClient (Control.MousePosition));
897                         current_item = item;
898
899                         if (item == null || item.Button.ToolTipText.Length == 0)
900                                 return;
901
902                         tip_window.Present (this, item.Button.ToolTipText);
903                         TipDownTimer.Start ();
904                 }
905
906                 private void ToolBar_MouseLeave (object sender, EventArgs e)
907                 {
908                         if (tipdown_timer != null)
909                                 tipdown_timer.Dispose ();
910                         tipdown_timer = null;
911                         if (tip_window != null)
912                                 tip_window.Dispose ();
913                         tip_window = null;
914
915                         if (!Enabled || current_item == null) 
916                                 return;
917
918                         current_item.Hilight = false;
919                         current_item = null;
920                 }
921
922                 private void ToolBar_MouseMove (object sender, MouseEventArgs me)
923                 {
924                         if (!Enabled) 
925                                 return;
926
927                         if (tip_window != null && tip_window.Visible) {
928                                 TipDownTimer.Stop ();
929                                 TipDownTimer.Start ();
930                         }
931
932                         Point loc = new Point (me.X, me.Y);
933
934                         if (Capture) {
935                                 // If the button was pressed and we leave, release the 
936                                 // button press and vice versa
937                                 foreach (ToolBarItem item in items) {
938                                         if (item.Pressed &&
939                                             (item.Inside != item.Rectangle.Contains (loc))) {
940                                                 item.Inside = item.Rectangle.Contains (loc);
941                                                 item.Hilight = false;
942                                                 break;
943                                         }
944                                 }
945                                 return;
946                         } 
947
948                         if (current_item != null && current_item.Rectangle.Contains (loc)) {
949                                 if (ThemeEngine.Current.ToolBarHasHotElementStyles (this)) {
950                                         if (current_item.Hilight || (!ThemeEngine.Current.ToolBarHasHotCheckedElementStyles && current_item.Button.Pushed) || !current_item.Button.Enabled)
951                                                 return;
952                                         current_item.Hilight = true;
953                                 }
954                         } else {
955                                 if (tip_window != null) {
956                                         if (tip_window.Visible) {
957                                                 tip_window.Hide (this);
958                                                 TipDownTimer.Stop ();
959                                         }
960                                         current_item = ItemAtPoint (loc);
961                                         if (current_item != null && current_item.Button.ToolTipText.Length > 0) {
962                                                 tip_window.Present (this, current_item.Button.ToolTipText);
963                                                 TipDownTimer.Start ();
964                                         }
965                                 }
966
967                                 if (ThemeEngine.Current.ToolBarHasHotElementStyles (this)) {
968                                         foreach (ToolBarItem item in items) {
969                                                 if (item.Rectangle.Contains (loc) && item.Button.Enabled) {
970                                                         current_item = item;
971                                                         if (current_item.Hilight || (!ThemeEngine.Current.ToolBarHasHotCheckedElementStyles && current_item.Button.Pushed))
972                                                                 continue;
973                                                         current_item.Hilight = true;
974                                                 }
975                                                 else if (item.Hilight) {
976                                                         item.Hilight = false;
977                                                 }
978                                         }
979                                 }
980                         }
981                 }
982
983                 internal override void OnPaintInternal (PaintEventArgs pevent)
984                 {
985                         if (GetStyle (ControlStyles.UserPaint))
986                                 return;
987                                 
988                         ThemeEngine.Current.DrawToolBar (pevent.Graphics, pevent.ClipRectangle, this);
989                         
990                         // Toolbars do not raise OnPaint unless UserPaint is set
991                         pevent.Handled = true;
992                 }
993
994                 internal void Redraw (bool recalculate)
995                 {
996                         Redraw (recalculate, true);
997                 }
998
999                 internal void Redraw (bool recalculate, bool force)
1000                 {
1001                         bool invalidate = true;
1002                         
1003                         if (recalculate)
1004                                 invalidate = LayoutToolBar ();
1005
1006                         if (force || invalidate)
1007                                 Invalidate ();
1008                 }
1009
1010                 internal bool SizeSpecified {
1011                         get { return size_specified; }
1012                 }
1013                 
1014                 internal bool Vertical {
1015                         get { return (Dock == DockStyle.Left) || (Dock == DockStyle.Right); }
1016                 }
1017
1018                 internal const int text_padding = 3;
1019
1020                 private Size CalcButtonSize ()
1021                 {
1022                         if (Buttons.Count == 0)
1023                                 return Size.Empty;
1024
1025                         string longest_text = Buttons [0].Text;
1026                         for (int i = 1; i < Buttons.Count; i++) {
1027                                 if (Buttons[i].Text.Length > longest_text.Length)
1028                                         longest_text = Buttons[i].Text;
1029                         }
1030
1031                         Size size = Size.Empty;
1032                         if (longest_text != null && longest_text.Length > 0) {
1033                                 SizeF sz = TextRenderer.MeasureString (longest_text, Font);
1034                                 if (sz != SizeF.Empty)
1035                                         size = new Size ((int) Math.Ceiling (sz.Width) + 2 * text_padding, (int) Math.Ceiling (sz.Height));
1036                         }
1037
1038                         Size img_size = ImageList == null ? new Size (16, 16) : ImageSize;
1039
1040                         Theme theme = ThemeEngine.Current;
1041                         int imgWidth = img_size.Width + 2 * theme.ToolBarImageGripWidth; 
1042                         int imgHeight = img_size.Height + 2 * theme.ToolBarImageGripWidth;
1043
1044                         if (text_alignment == ToolBarTextAlign.Right) {
1045                                 size.Width = imgWidth + size.Width;
1046                                 size.Height = (size.Height > imgHeight) ? size.Height : imgHeight;
1047                         } else {
1048                                 size.Height = imgHeight + size.Height;
1049                                 size.Width = (size.Width > imgWidth) ? size.Width : imgWidth;
1050                         }
1051
1052                         size.Width += theme.ToolBarImageGripWidth;
1053                         size.Height += theme.ToolBarImageGripWidth;
1054                         return size;
1055                 }
1056
1057                 // Flat toolbars disregard specified sizes.  Normal toolbars grow the
1058                 // button size to be at least large enough to show the image.
1059                 private Size AdjustedButtonSize {
1060                         get {
1061                                 Size size;
1062
1063                                 if (default_size.IsEmpty || Appearance == ToolBarAppearance.Normal) 
1064                                         size = ButtonSize;
1065                                 else
1066                                         size = default_size;
1067                                 
1068                                 if (size_specified) {
1069                                         if (Appearance == ToolBarAppearance.Flat)
1070                                                 size = CalcButtonSize ();
1071                                         else {
1072                                                 int grip = ThemeEngine.Current.ToolBarImageGripWidth;
1073                                                 if (size.Width < ImageSize.Width + 2 * grip )
1074                                                         size.Width = ImageSize.Width + 2 * grip;
1075                                                 if (size.Height < ImageSize.Height + 2 * grip)
1076                                                         size.Height = ImageSize.Height + 2 * grip;
1077                                         }
1078                                 }
1079                                 return size;
1080                         }
1081                 }
1082
1083                 private bool LayoutToolBar ()
1084                 {
1085                         bool changed = false;
1086                         Theme theme = ThemeEngine.Current;
1087                         int x = theme.ToolBarGripWidth;
1088                         int y = theme.ToolBarGripWidth;
1089
1090                         Size adjusted_size = AdjustedButtonSize;
1091                         
1092                         int calculated_size = (Vertical ? adjusted_size.Width : adjusted_size.Height) + theme.ToolBarGripWidth;
1093                         
1094                         int separator_index = -1;
1095
1096                         items = new ToolBarItem [buttons.Count];
1097                         
1098                         for (int i = 0; i < buttons.Count; i++) {
1099                                 ToolBarButton button = buttons [i];
1100                                 
1101                                 ToolBarItem item = new ToolBarItem (button);
1102                                 items [i] = item;
1103
1104                                 if (!button.Visible)
1105                                         continue;
1106
1107                                 if (size_specified && (button.Style != ToolBarButtonStyle.Separator))
1108                                         changed = item.Layout (adjusted_size);
1109                                 else
1110                                         changed = item.Layout (Vertical, calculated_size);
1111                                 
1112                                 bool is_separator = button.Style == ToolBarButtonStyle.Separator;
1113                                 
1114                                 if (Vertical) {
1115                                         if (y + item.Rectangle.Height < Height || is_separator || !Wrappable) {
1116                                                 if (item.Location.X != x || item.Location.Y != y)
1117                                                         changed = true;
1118                                                 item.Location = new Point (x, y);
1119                                                 y += item.Rectangle.Height;
1120                                                 if (is_separator)
1121                                                         separator_index = i;
1122                                         } else if (separator_index > 0) {
1123                                                 i = separator_index;
1124                                                 separator_index = -1;
1125                                                 y = theme.ToolBarGripWidth;
1126                                                 x += calculated_size; 
1127                                         } else {
1128                                                 y = theme.ToolBarGripWidth;
1129                                                 x += calculated_size; 
1130                                                 if (item.Location.X != x || item.Location.Y != y)
1131                                                         changed = true;
1132                                                 item.Location = new Point (x, y);
1133                                                 y += item.Rectangle.Height;
1134                                         }
1135                                 } else {
1136                                         if (x + item.Rectangle.Width < Width || is_separator || !Wrappable) {
1137                                                 if (item.Location.X != x || item.Location.Y != y)
1138                                                         changed = true;
1139                                                 item.Location = new Point (x, y);
1140                                                 x += item.Rectangle.Width;
1141                                                 if (is_separator)
1142                                                         separator_index = i;
1143                                         } else if (separator_index > 0) {
1144                                                 i = separator_index;
1145                                                 separator_index = -1;
1146                                                 x = theme.ToolBarGripWidth;
1147                                                 y += calculated_size; 
1148                                         } else {
1149                                                 x = theme.ToolBarGripWidth;
1150                                                 y += calculated_size; 
1151                                                 if (item.Location.X != x || item.Location.Y != y)
1152                                                         changed = true;
1153                                                 item.Location = new Point (x, y);
1154                                                 x += item.Rectangle.Width;
1155                                         }
1156                                 }
1157                         }
1158                         
1159                         if (Parent == null)
1160                                 return changed;
1161                         
1162                         if (Wrappable)
1163                                 calculated_size += Vertical ? x : y;
1164                         
1165                         if (IsHandleCreated) {
1166                                 if (Vertical)
1167                                         Width = calculated_size;
1168                                 else
1169                                         Height = calculated_size; 
1170                         }
1171                         
1172                         return changed;
1173                 }
1174                 #endregion Private Methods
1175
1176                 #region subclass
1177                 public class ToolBarButtonCollection : IList, ICollection, IEnumerable
1178                 {
1179                         #region instance variables
1180                         private ArrayList list; // ToolBarButton list
1181                         private ToolBar owner;  // ToolBar associated to Collection
1182                         private bool redraw;    // Flag if needs to redraw after add/remove operations
1183                         #endregion
1184
1185                         #region UIA Framework Events
1186                         static object UIACollectionChangedEvent = new object ();
1187                         
1188                         internal event CollectionChangeEventHandler UIACollectionChanged {
1189                                 add { owner.Events.AddHandler (UIACollectionChangedEvent, value); }
1190                                 remove { owner.Events.RemoveHandler (UIACollectionChangedEvent, value); }
1191                         }
1192
1193                         internal void OnUIACollectionChanged (CollectionChangeEventArgs e)
1194                         {
1195                                 CollectionChangeEventHandler eh
1196                                         = (CollectionChangeEventHandler) owner.Events [UIACollectionChangedEvent];
1197                                 if (eh != null)
1198                                         eh (owner, e);
1199                         }
1200                         #endregion
1201
1202                         #region constructors
1203                         public ToolBarButtonCollection (ToolBar owner)
1204                         {
1205                                 this.list   = new ArrayList ();
1206                                 this.owner  = owner;
1207                                 this.redraw = true;
1208                         }
1209                         #endregion
1210
1211                         #region properties
1212                         [Browsable (false)]
1213                         public int Count {
1214                                 get { return list.Count; }
1215                         }
1216
1217                         public bool IsReadOnly {
1218                                 get { return list.IsReadOnly; }
1219                         }
1220
1221                         public virtual ToolBarButton this [int index] {
1222                                 get { return (ToolBarButton) list [index]; }
1223                                 set {
1224                                         // UIA Framework Event: Button Removed
1225                                         OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
1226
1227                                         value.SetParent (owner);
1228                                         list [index] = value;
1229                                         owner.Redraw (true);
1230
1231                                 // UIA Framework Event: Button Added
1232                                 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
1233                                 }
1234                         }
1235
1236                         public virtual ToolBarButton this[string key] {
1237                                 get {
1238                                         if (string.IsNullOrEmpty (key))
1239                                                 return null;
1240                                                 
1241                                         foreach (ToolBarButton b in list)
1242                                                 if (string.Compare (b.Name, key, true) == 0)
1243                                                         return b;
1244                                                         
1245                                         return null;
1246                                 }
1247                         }
1248
1249                         bool ICollection.IsSynchronized {
1250                                 get { return list.IsSynchronized; }
1251                         }
1252
1253                         object ICollection.SyncRoot {
1254                                 get { return list.SyncRoot; }
1255                         }
1256
1257                         bool IList.IsFixedSize {
1258                                 get { return list.IsFixedSize; }
1259                         }
1260
1261                         object IList.this [int index] {
1262                                 get { return this [index]; }
1263                                 set {
1264                                         if (! (value is ToolBarButton))
1265                                                 throw new ArgumentException("Not of type ToolBarButton", "value");
1266                                         this [index] = (ToolBarButton) value;
1267                                 }
1268                         }
1269                         #endregion
1270
1271                         #region methods
1272                         public int Add (string text)
1273                         {
1274                                 ToolBarButton button = new ToolBarButton (text);
1275                                 return this.Add (button);
1276                         }
1277
1278                         public int Add (ToolBarButton button)
1279                         {
1280                                 int result;
1281                                 button.SetParent (owner);
1282                                 result = list.Add (button);
1283                                 if (redraw)
1284                                         owner.Redraw (true);
1285
1286                                 // UIA Framework Event: Button Added
1287                                 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, result));
1288
1289                                 return result;
1290                         }
1291
1292                         public void AddRange (ToolBarButton [] buttons)
1293                         {
1294                                 try {
1295                                         redraw = false;
1296                                         foreach (ToolBarButton button in buttons)
1297                                                 Add (button);
1298                                 }
1299                                 finally {
1300                                         redraw = true;
1301                                         owner.Redraw (true);
1302                                 }
1303                         }
1304
1305                         public void Clear ()
1306                         {
1307                                 list.Clear ();
1308                                 owner.Redraw (false);
1309
1310                                 // UIA Framework Event: Button Cleared
1311                                 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, -1));
1312                         }
1313
1314                         public bool Contains (ToolBarButton button)
1315                         {
1316                                 return list.Contains (button);
1317                         }
1318
1319                         public virtual bool ContainsKey (string key)
1320                         {
1321                                 return !(this[key] == null);
1322                         }
1323
1324                         public IEnumerator GetEnumerator ()
1325                         {
1326                                 return list.GetEnumerator ();
1327                         }
1328
1329                         void ICollection.CopyTo (Array dest, int index)
1330                         {
1331                                 list.CopyTo (dest, index);
1332                         }
1333
1334                         int IList.Add (object button)
1335                         {
1336                                 if (! (button is ToolBarButton)) {
1337                                         throw new ArgumentException("Not of type ToolBarButton", "button");
1338                                 }
1339
1340                                 return this.Add ((ToolBarButton) button);
1341                         }
1342
1343                         bool IList.Contains (object button)
1344                         {
1345                                 if (! (button is ToolBarButton)) {
1346                                         throw new ArgumentException("Not of type ToolBarButton", "button");
1347                                 }
1348
1349                                 return this.Contains ((ToolBarButton) button);
1350                         }
1351
1352                         int IList.IndexOf (object button)
1353                         {
1354                                 if (! (button is ToolBarButton)) {
1355                                         throw new ArgumentException("Not of type ToolBarButton", "button");
1356                                 }
1357
1358                                 return this.IndexOf ((ToolBarButton) button);
1359                         }
1360
1361                         void IList.Insert (int index, object button)
1362                         {
1363                                 if (! (button is ToolBarButton)) {
1364                                         throw new ArgumentException("Not of type ToolBarButton", "button");
1365                                 }
1366
1367                                 this.Insert (index, (ToolBarButton) button);
1368                         }
1369
1370                         void IList.Remove (object button)
1371                         {
1372                                 if (! (button is ToolBarButton)) {
1373                                         throw new ArgumentException("Not of type ToolBarButton", "button");
1374                                 }
1375
1376                                 this.Remove ((ToolBarButton) button);
1377                         }
1378
1379                         public int IndexOf (ToolBarButton button)
1380                         {
1381                                 return list.IndexOf (button);
1382                         }
1383
1384                         public virtual int IndexOfKey (string key)
1385                         {
1386                                 return IndexOf (this[key]);
1387                         }
1388
1389                         public void Insert (int index, ToolBarButton button)
1390                         {
1391                                 list.Insert (index, button);
1392                                 owner.Redraw (true);
1393
1394                                 // UIA Framework Event: Button Added
1395                                 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
1396                         }
1397
1398                         public void Remove (ToolBarButton button)
1399                         {
1400                                 list.Remove (button);
1401                                 owner.Redraw (true);
1402                         }
1403
1404                         public void RemoveAt (int index)
1405                         {
1406                                 list.RemoveAt (index);
1407                                 owner.Redraw (true);
1408
1409                                 // UIA Framework Event: Button Removed
1410                                 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
1411                         }
1412
1413                         public virtual void RemoveByKey (string key)
1414                         {
1415                                 Remove (this[key]);
1416                         }
1417                         #endregion methods
1418                 }
1419                 
1420                 #endregion subclass
1421         }
1422         
1423         
1424         // Because same button can be added to toolbar multiple times, we need to maintain
1425         // a list of button information for each positions. 
1426         internal class ToolBarItem : Component
1427         {
1428                 #region Instance variables
1429                 
1430                 private ToolBar       toolbar;    // Parent toolbar
1431                 private ToolBarButton button;     // Associated toolBar button 
1432                 private Rectangle     bounds;     // Toolbar button bounds
1433                 private Rectangle     image_rect; // Image button bounds
1434                 private Rectangle     text_rect;  // Text button bounds
1435
1436                 private bool dd_pressed = false;  // to check for a mouse down on dropdown rect
1437                 private bool inside     = false;  // to handle the mouse move event with mouse pressed
1438                 private bool hilight    = false;  // to hilight buttons in flat style
1439                 private bool pressed    = false;  // this is to check for mouse down on a button
1440                 
1441                 #endregion
1442                 
1443                 #region Constructors
1444                 
1445                 public ToolBarItem (ToolBarButton button)
1446                 {
1447                         this.toolbar = button.Parent;
1448                         this.button  = button;
1449                 }
1450                 
1451                 #endregion Constructors
1452         
1453                 #region Properties
1454
1455                 public ToolBarButton Button {
1456                         get { return this.button; }
1457                 }
1458                 
1459                 public Rectangle Rectangle {
1460                         get { 
1461                                 if (!button.Visible || toolbar == null)
1462                                         return Rectangle.Empty;
1463
1464                                 if (button.Style == ToolBarButtonStyle.DropDownButton && toolbar.DropDownArrows) {
1465                                         Rectangle result = bounds;
1466                                         result.Width += ThemeEngine.Current.ToolBarDropDownWidth;
1467                                         return result;
1468                                 }
1469                                  
1470                                 return bounds;
1471                         }
1472                         set { this.bounds = value; }
1473                 }
1474
1475                 public Point Location {
1476                         get { return bounds.Location; }
1477                         set { bounds.Location = value; }
1478                 }
1479
1480                 public Rectangle ImageRectangle {
1481                         get {
1482                                 Rectangle result = image_rect;
1483                                 result.X += bounds.X;
1484                                 result.Y += bounds.Y;
1485                                 return result; 
1486                         }
1487                 }
1488                 
1489                 public Rectangle TextRectangle {
1490                         get { 
1491                                 Rectangle result = text_rect;
1492                                 result.X += bounds.X;
1493                                 result.Y += bounds.Y;
1494                                 return result; 
1495                         }
1496                 }
1497
1498                 private Size TextSize {
1499                         get {
1500                                 StringFormat text_format = new StringFormat ();
1501                                 text_format.HotkeyPrefix = HotkeyPrefix.Hide;
1502
1503                                 SizeF sz = TextRenderer.MeasureString (button.Text, toolbar.Font, SizeF.Empty, text_format);
1504                                 if (sz == SizeF.Empty)
1505                                         return Size.Empty;
1506                                 return new Size ((int) Math.Ceiling (sz.Width) + 2 * ToolBar.text_padding, (int) Math.Ceiling (sz.Height));
1507                         }
1508                 }
1509                 
1510                 public bool Pressed {
1511                         get { return (pressed && inside); }
1512                         set { pressed = value; }
1513                 }
1514
1515                 public bool DDPressed {
1516                         get { return dd_pressed; }
1517                         set { dd_pressed = value; }
1518                 }
1519
1520                 public bool Inside {
1521                         get { return inside; }
1522                         set { inside = value; }
1523                 }
1524
1525                 public bool Hilight {
1526                         get { return hilight; }
1527                         set {
1528                                 if (hilight == value)
1529                                         return;
1530
1531                                 hilight = value;
1532                                 Invalidate ();
1533                         }
1534                 }       
1535                 
1536                 #endregion Properties
1537
1538                 #region Methods
1539                 
1540                 public Size CalculateSize ()
1541                 {
1542                         Theme theme = ThemeEngine.Current;
1543
1544                         int ht = toolbar.ButtonSize.Height + 2 * theme.ToolBarGripWidth;
1545
1546                         if (button.Style == ToolBarButtonStyle.Separator)
1547                                 return new Size (theme.ToolBarSeparatorWidth, ht);
1548
1549                         Size size;
1550                         if (TextSize.IsEmpty && (button.Image == null))
1551                                 size = toolbar.default_size;
1552                         else
1553                                 size = TextSize;
1554                         
1555                         Size image_size = (toolbar.ImageSize == Size.Empty) ? new Size (16, 16) : toolbar.ImageSize;
1556
1557                         int image_width = image_size.Width + 2 * theme.ToolBarImageGripWidth; 
1558                         int image_height = image_size.Height + 2 * theme.ToolBarImageGripWidth; 
1559
1560                         if (toolbar.TextAlign == ToolBarTextAlign.Right) {
1561                                 size.Width =  image_width + size.Width;
1562                                 size.Height = (size.Height > image_height) ? size.Height : image_height;
1563                         } else {
1564                                 size.Height = image_height + size.Height;
1565                                 size.Width = (size.Width > image_width) ? size.Width : image_width;
1566                         }
1567
1568                         size.Width += theme.ToolBarGripWidth;
1569                         size.Height += theme.ToolBarGripWidth;
1570                         return size;
1571                 }
1572
1573                 
1574                 public bool Layout (bool vertical, int calculated_size)
1575                 {
1576                         if (toolbar == null || !button.Visible)
1577                                 return false;
1578
1579                         Size psize = toolbar.ButtonSize;
1580                         Size size = psize;
1581                         if ((!toolbar.SizeSpecified) || (button.Style == ToolBarButtonStyle.Separator)) {
1582                                 size = CalculateSize ();
1583
1584                                 if (size.Width == 0 || size.Height == 0)
1585                                         size = psize;
1586
1587                                 if (vertical)
1588                                         size.Width = calculated_size;
1589                                 else
1590                                         size.Height = calculated_size;
1591                         }
1592                         return Layout (size);
1593                 }
1594
1595                 public bool Layout (Size size)
1596                 {
1597                         if (toolbar == null || !button.Visible)
1598                                 return false;
1599
1600                         bounds.Size = size;
1601
1602                         Size image_size = (toolbar.ImageSize == Size.Empty) ? new Size (16, 16) : toolbar.ImageSize;
1603                         int grip = ThemeEngine.Current.ToolBarImageGripWidth;
1604
1605                         Rectangle new_image_rect, new_text_rect;
1606                         
1607                         if (toolbar.TextAlign == ToolBarTextAlign.Underneath) {
1608                                 new_image_rect = new Rectangle ((bounds.Size.Width - image_size.Width) / 2 - grip, 0, image_size.Width + 2 + grip, image_size.Height + 2 * grip);
1609                                 new_text_rect = new Rectangle (0, new_image_rect.Height, bounds.Size.Width, bounds.Size.Height - new_image_rect.Height - 2 * grip);
1610                         } else {
1611                                 new_image_rect = new Rectangle (0, 0, image_size.Width + 2 * grip, image_size.Height + 2 * grip);
1612                                 new_text_rect = new Rectangle (new_image_rect.Width, 0, bounds.Size.Width - new_image_rect.Width, bounds.Size.Height - 2 * grip);
1613                         }
1614
1615                         bool changed = false;
1616
1617                         if (new_image_rect != image_rect || new_text_rect != text_rect)
1618                                 changed = true;
1619
1620                         image_rect = new_image_rect;
1621                         text_rect = new_text_rect;
1622                         
1623                         return changed;
1624                 }
1625                 
1626                 public void Invalidate ()
1627                 {
1628                         if (toolbar != null)
1629                                 toolbar.Invalidate (Rectangle);
1630                 }
1631
1632                 #endregion Methods
1633         }
1634 }