2006-12-05 Chris Toshok <toshok@ximian.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ToolStripItem.cs
1 //
2 // ToolStripItem.cs
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //
23 // Copyright (c) 2006 Jonathan Pobst
24 //
25 // Authors:
26 //      Jonathan Pobst (monkey@jpobst.com)
27 //
28 #if NET_2_0
29
30 using System;
31 using System.Drawing;
32 using System.ComponentModel;
33
34 namespace System.Windows.Forms
35 {
36         [DefaultEvent ("Click")]
37         [DefaultProperty ("Text")]
38         [DesignTimeVisible (false)]
39         [ToolboxItem (false)]
40         public abstract class ToolStripItem : Component, IDropTarget, IComponent, IDisposable
41         {
42                 #region Private Variables
43                 private AccessibleObject accessibility_object;
44                 private string accessible_default_action_description;
45                 private ToolStripItemAlignment alignment;
46                 private bool auto_size;
47                 private bool auto_tool_tip;
48                 private Color back_color;
49                 private Rectangle bounds;
50                 private bool can_select;
51                 private ToolStripItemDisplayStyle display_style;
52                 private DockStyle dock;
53                 private bool double_click_enabled;
54                 private bool enabled;
55                 private Font font;
56                 private Color fore_color;
57                 private Image image;
58                 private ContentAlignment image_align;
59                 private int image_index;
60                 private ToolStripItemImageScaling image_scaling;
61                 internal bool is_pressed;
62                 private bool is_selected;
63                 private Padding margin;
64                 private string name;
65                 private ToolStrip owner;
66                 internal ToolStripItem owner_item;
67                 private Padding padding;
68                 private Object tag;
69                 private string text;
70                 private ContentAlignment text_align;
71                 private TextImageRelation text_image_relation;
72                 private string tool_tip_text;
73                 private bool visible;
74
75                 private ToolStrip parent;
76                 private Size text_size;
77                 #endregion
78
79                 #region Public Constructors
80                 protected ToolStripItem ()
81                         : this (String.Empty, null, null, String.Empty)
82                 {
83                 }
84
85                 protected ToolStripItem (string text, Image image, EventHandler onClick)
86                         : this (text, image, onClick, String.Empty)
87                 {
88                 }
89
90                 protected ToolStripItem (string text, Image image, EventHandler onClick, string name)
91                 {
92                         this.alignment = ToolStripItemAlignment.Left;
93                         this.auto_size = true;
94                         this.auto_tool_tip = this.DefaultAutoToolTip;
95                         this.back_color = Control.DefaultBackColor;
96                         this.display_style = this.DefaultDisplayStyle;
97                         this.dock = DockStyle.None;
98                         this.enabled = true;
99                         this.font = new Font ("Tahoma", 8.25f);
100                         this.fore_color = Control.DefaultForeColor;
101                         this.image = image;
102                         this.image_align = ContentAlignment.MiddleCenter;
103                         this.image_index = -1;
104                         this.image_scaling = ToolStripItemImageScaling.SizeToFit;
105                         this.margin = this.DefaultMargin;
106                         this.name = name;
107                         this.padding = this.DefaultPadding;
108                         this.bounds.Size = this.DefaultSize;
109                         this.text = text;
110                         this.text_align = ContentAlignment.MiddleCenter;
111                         this.text_image_relation = TextImageRelation.ImageBeforeText;
112                         this.visible = true;
113
114                         this.Click += onClick;
115                         this.can_select = this is ToolStripMenuItem || this is ToolStripDropDownButton || this is ToolStripSplitButton ? true : false;
116                         OnLayout (new LayoutEventArgs (null, string.Empty));
117                 }
118                 #endregion
119
120                 #region Public Properties
121                 public AccessibleObject AccessibilityObject {
122                         get { 
123                                 if (this.accessibility_object == null)
124                                         this.accessibility_object = CreateAccessibilityInstance ();
125                                         
126                                 return this.accessibility_object;
127                         }
128                 }
129                 
130                 public string AccessibleDefaultActionDescription {
131                         get {
132                                 if (this.accessibility_object == null)
133                                         return null;
134                                 
135                                 return this.accessible_default_action_description;
136                         }
137                         set { this.accessible_default_action_description = value; }
138                 }
139
140                 [Localizable (true)]
141                 public string AccessibleDescription {
142                         get {
143                                 if (this.accessibility_object == null)
144                                         return null;
145                                 
146                                 return this.AccessibilityObject.Description;
147                         }
148                         set { this.AccessibilityObject.description = value; }
149                 }
150
151                 [Localizable (true)]
152                 public string AccessibleName {
153                         get { 
154                                 if (this.accessibility_object == null)
155                                         return null;
156                                         
157                                 return this.AccessibilityObject.Name; 
158                         }
159                         set { this.AccessibilityObject.Name = value; }
160                 }
161                 
162                 public AccessibleRole AccessibleRole {
163                         get
164                         {
165                                 if (this.accessibility_object == null)
166                                         return AccessibleRole.Default;
167                                 
168                                 return this.AccessibilityObject.Role;
169                         }
170                         set { this.AccessibilityObject.role = value; }
171                 }
172                 
173                 [MonoTODO]
174                 [DefaultValue (ToolStripItemAlignment.Left)]
175                 public ToolStripItemAlignment Alignment {
176                         get { return this.alignment; }
177                         set {
178                                 if (!Enum.IsDefined (typeof (ToolStripItemAlignment), value))
179                                         throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripItemAlignment", value));
180
181                                 this.alignment = value;
182                         }
183                 }
184
185                 [Localizable (true)]
186                 [DefaultValue (true)]
187                 public bool AutoSize {
188                         get { return this.auto_size; }
189                         set { 
190                                 this.auto_size = value; 
191                                 this.CalculateAutoSize (); 
192                         }
193                 }
194
195                 [MonoTODO ("Need 2.0 ToolTip to implement tool tips.")]
196                 [DefaultValue (false)]
197                 public bool AutoToolTip {
198                         get { return this.auto_tool_tip; }
199                         set { this.auto_tool_tip = value; }
200                 }
201
202                 [Browsable (false)]
203                 public bool Available {
204                         get { return this.visible; }
205                         set {
206                                 if (this.visible != value) {
207                                         visible = value; 
208                                         
209                                         if (this.owner != null) 
210                                                 owner.PerformLayout (); 
211                                                 
212                                         OnAvailableChanged (EventArgs.Empty); 
213                                 }
214                         }
215                 }
216
217                 public virtual Color BackColor {
218                         get { return this.back_color; }
219                         set {
220                                 if (this.back_color != value) {
221                                         back_color = value;
222                                         OnBackColorChanged (EventArgs.Empty);
223                                         this.Invalidate ();
224                                 }
225                         }
226                 }
227
228                 [Browsable (false)]
229                 public virtual Rectangle Bounds {
230                         get { return this.bounds; }
231                 }
232
233                 [Browsable (false)]
234                 public virtual bool CanSelect {
235                         get { return this.can_select; }
236                 }
237
238                 [Browsable (false)]
239                 public Rectangle ContentRectangle {
240                         get {
241                                 // ToolStripLabels don't have a border
242                                 if (this is ToolStripLabel)
243                                         return new Rectangle (0, 0, this.bounds.Width, this.bounds.Height);
244
245                                 if (this is ToolStripDropDownButton && (this as ToolStripDropDownButton).ShowDropDownArrow)
246                                         return new Rectangle (2, 2, this.bounds.Width - 13, this.bounds.Height - 4);
247
248                                 return new Rectangle (2, 2, this.bounds.Width - 4, this.bounds.Height - 4);
249                         }
250                 }
251
252                 public virtual ToolStripItemDisplayStyle DisplayStyle {
253                         get { return this.display_style; }
254                         set {
255                                 if (this.display_style != value) {
256                                         this.display_style = value; 
257                                         this.CalculateAutoSize (); 
258                                         OnDisplayStyleChanged (EventArgs.Empty); 
259                                         this.Invalidate ();
260                                 }
261                         }
262                 }
263
264                 [Browsable (false)]
265                 [DefaultValue (DockStyle.None)]
266                 public DockStyle Dock {
267                         get { return this.dock; }
268                         set {
269                                 if (this.dock != value) {
270                                         if (!Enum.IsDefined (typeof (DockStyle), value))
271                                                 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for DockStyle", value));
272
273                                         this.dock = value;
274                                         this.CalculateAutoSize ();
275                                 }
276                         }
277                 }
278
279                 [DefaultValue (false)]
280                 public bool DoubleClickEnabled {
281                         get { return this.double_click_enabled; }
282                         set { this.double_click_enabled = value; }
283                 }
284
285                 [Localizable (true)]
286                 [DefaultValue (true)]
287                 public virtual bool Enabled {
288                         get { return enabled; }
289                         set { 
290                                 if (this.enabled != value) {
291                                         this.enabled = value; 
292                                         OnEnabledChanged (EventArgs.Empty); 
293                                         this.Invalidate ();
294                                 }
295                         }
296                 }
297
298                 [Localizable (true)]
299                 public virtual Font Font
300                 {
301                         get { return this.font; }
302                         set { 
303                                 if (this.font != value) {
304                                         this.font = value; 
305                                         this.CalculateAutoSize (); 
306                                         this.OnFontChanged (EventArgs.Empty); 
307                                         this.Invalidate ();
308                                 }
309                         }
310                 }
311
312                 public virtual Color ForeColor {
313                         get { return this.fore_color; }
314                         set { 
315                                 if (this.fore_color != value) {
316                                         this.fore_color = value; 
317                                         this.OnForeColorChanged (EventArgs.Empty); 
318                                         this.Invalidate ();
319                                 }
320                         }
321                 }
322
323                 [Browsable (false)]
324                 public int Height {
325                         get { return this.bounds.Height; }
326                         set { 
327                                 this.bounds.Height = value; 
328                                 this.CalculateAutoSize ();
329                                 this.OnBoundsChanged ();
330                                 this.Invalidate (); 
331                         }
332                 }
333
334                 [Localizable (true)]
335                 public virtual Image Image {
336                         get { return this.image; }
337                         set {
338                                 this.image = value; 
339                                 this.CalculateAutoSize (); 
340                                 this.Invalidate ();
341                         }
342                 }
343
344                 [Localizable (true)]
345                 [DefaultValue (ContentAlignment.MiddleCenter)]
346                 public ContentAlignment ImageAlign {
347                         get { return this.image_align; }
348                         set {
349                                 if (!Enum.IsDefined (typeof (ContentAlignment), value))
350                                         throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ContentAlignment", value));
351
352                                 this.image_align = value;
353                                 this.Invalidate ();
354                         }
355                 }
356
357                 [Localizable (true)]
358                 public int ImageIndex {
359                         get { return this.image_index; }
360                         set {
361                                 if (value < -1)
362                                         throw new ArgumentException ("ImageIndex cannot be less than -1");
363
364                                 this.image_index = value;
365                                 this.CalculateAutoSize ();
366                                 this.Invalidate ();
367                         }
368                 }
369
370                 [Localizable (true)]
371                 [DefaultValue (ToolStripItemImageScaling.SizeToFit)]
372                 public ToolStripItemImageScaling ImageScaling {
373                         get { return this.image_scaling; }
374                         set { 
375                                 this.image_scaling = value; 
376                                 this.CalculateAutoSize (); 
377                                 this.Invalidate (); 
378                         }
379                 }
380
381                 [Localizable (true)]
382                 [MonoTODO ("Stub, doesn't actually do anything yet.")]
383                 public Color ImageTransparentColor {
384                         get { return Color.Transparent; }
385                         set { }
386                 }
387                 
388                 [Browsable (false)]
389                 public bool IsOnDropDown {
390                         get {
391                                 if (this.owner != null && this.owner is ToolStripDropDown)
392                                         return true;
393
394                                 return false;
395                         }
396                 }
397
398                 public Padding Margin {
399                         get { return this.margin; }
400                         set {
401                                 this.margin = value; 
402                                 this.CalculateAutoSize ();
403                         }
404                 }
405
406                 [DefaultValue (null)]
407                 public string Name {
408                         get { return this.name; }
409                         set { this.name = value; }
410                 }
411
412                 [Browsable (false)]
413                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
414                 public ToolStrip Owner {
415                         get { return this.owner; }
416                         set { 
417                                 if (this.owner != value) {
418                                         this.owner = value; 
419                                         this.CalculateAutoSize (); 
420                                         OnOwnerChanged (EventArgs.Empty);
421                                 }
422                         }
423                 }
424
425                 [Browsable (false)]
426                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
427                 public ToolStripItem OwnerItem {
428                         get { return this.owner_item; }
429                 }
430
431                 public virtual Padding Padding {
432                         get { return this.padding; }
433                         set { 
434                                 this.padding = value; 
435                                 this.CalculateAutoSize (); 
436                                 this.Invalidate (); 
437                         }
438                 }
439
440                 [Browsable (false)]
441                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
442                 public virtual bool Pressed { get { return this.is_pressed; } }
443
444                 [Browsable (false)]
445                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
446                 public virtual bool Selected { get { return this.is_selected; } }
447
448                 [Localizable (true)]
449                 public virtual Size Size {
450                         get { return this.bounds.Size; }
451                         set { 
452                                 this.bounds.Size = value; 
453                                 this.CalculateAutoSize ();
454                                 OnBoundsChanged ();
455                         }
456                 }
457
458                 [Localizable (false)]
459                 [Bindable (true)]
460                 [DefaultValue (null)]
461                 public Object Tag {
462                         get { return this.tag; }
463                         set { this.tag = value; }
464                 }
465
466                 [Localizable (true)]
467                 [DefaultValue ("")]
468                 public virtual string Text
469                 {
470                         get { return this.text; }
471                         set { 
472                                 if (this.text != value) { 
473                                         this.text = value; 
474                                         this.CalculateAutoSize (); 
475                                         this.OnTextChanged (EventArgs.Empty); 
476                                         this.Invalidate (); 
477                                 } 
478                         }
479                 }
480
481                 [Localizable (true)]
482                 [DefaultValue (ContentAlignment.MiddleCenter)]
483                 public virtual ContentAlignment TextAlign {
484                         get { return this.text_align; }
485                         set {
486                                 if (!Enum.IsDefined (typeof (ContentAlignment), value))
487                                         throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ContentAlignment", value));
488                                 this.text_align = value;
489                                 this.Invalidate ();
490                         }
491                 }
492
493                 [Localizable (true)]
494                 [DefaultValue (TextImageRelation.ImageBeforeText)]
495                 public TextImageRelation TextImageRelation {
496                         get { return this.text_image_relation; }
497                         set { 
498                                 this.text_image_relation = value; 
499                                 this.CalculateAutoSize (); 
500                                 this.Invalidate (); 
501                         }
502                 }
503
504                 [Localizable (true)]
505                 public string ToolTipText {
506                         get { return this.tool_tip_text; }
507                         set { this.tool_tip_text = value; }
508                 }
509
510                 [Localizable (true)]
511                 public bool Visible {
512                         get { 
513                                 if (this.parent == null)
514                                         return false;
515                         
516                                 return this.visible && this.parent.Visible; 
517                         }
518                         set { 
519                                 if (this.visible != value) {
520                                         this.visible = value; 
521                                         this.OnVisibleChanged (EventArgs.Empty); 
522                                         this.Invalidate ();
523                                 }
524                         }
525                 }
526
527                 [Browsable (false)]
528                 public int Width {
529                         get { return this.bounds.Width; }
530                         set { 
531                                 this.bounds.Width = value; 
532                                 this.CalculateAutoSize (); 
533                                 this.OnBoundsChanged();
534                         }
535                 }
536                 #endregion
537
538                 #region Protected Properties
539                 protected virtual bool DefaultAutoToolTip { get { return false; } }
540                 protected virtual ToolStripItemDisplayStyle DefaultDisplayStyle { get { return ToolStripItemDisplayStyle.ImageAndText; } }
541                 protected internal virtual Padding DefaultMargin { get { return new Padding (0, 1, 0, 2); } }
542                 protected virtual Padding DefaultPadding { get { return new Padding (); } }
543                 protected virtual Size DefaultSize { get { return new Size (23, 23); } }
544                 protected internal virtual bool DismissWhenClicked { get { return false; } }
545                 [Browsable (false)]
546                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
547                 protected internal ToolStrip Parent {
548                         get { return this.parent; }
549                         set { 
550                                 ToolStrip old_parent = this.parent;
551                                 this.parent = value; 
552                                 OnParentChanged(old_parent, this.parent);
553                         }
554                 }
555                 protected internal virtual bool ShowKeyboardCues { get { return true; } }
556                 #endregion
557
558                 #region Public Methods
559                 public ToolStrip GetCurrentParent ()
560                 { 
561                         return this.parent; 
562                 }
563
564                 public virtual Size GetPreferredSize (Size constrainingSize)
565                 {
566                         return this.CalculatePreferredSize (constrainingSize);
567                 }
568
569                 public void Invalidate ()
570                 {
571                         if (owner != null)
572                                 owner.Invalidate (this.bounds);
573                 }
574
575                 public void Invalidate (Rectangle r)
576                 {
577                         if (owner != null)
578                                 owner.Invalidate (r);
579                 }
580
581                 public void PerformClick ()
582                 { 
583                         this.OnClick (EventArgs.Empty); 
584                 }
585
586                 [EditorBrowsable (EditorBrowsableState.Never)]
587                 public virtual void ResetBackColor () { this.BackColor = Control.DefaultBackColor; }
588
589                 [EditorBrowsable (EditorBrowsableState.Never)]
590                 public virtual void ResetDisplayStyle () { this.display_style = this.DefaultDisplayStyle; }
591
592                 [EditorBrowsable (EditorBrowsableState.Never)]
593                 public virtual void ResetFont () { this.font = new Font ("Tahoma", 8.25f); }
594
595                 [EditorBrowsable (EditorBrowsableState.Never)]
596                 public virtual void ResetForeColor () { this.ForeColor = Control.DefaultForeColor; }
597
598                 [EditorBrowsable (EditorBrowsableState.Never)]
599                 public virtual void ResetImage () { this.image = null; }
600
601                 [EditorBrowsable (EditorBrowsableState.Never)]
602                 public void ResetMargin () { this.margin = this.DefaultMargin; }
603
604                 [EditorBrowsable (EditorBrowsableState.Never)]
605                 public void ResetPadding () { this.padding = this.DefaultPadding; }
606
607                 public void Select ()
608                 {
609                         if (this.CanSelect) {
610                                 this.is_selected = true;
611                                 this.Invalidate ();
612                         }
613                 }
614
615                 public override string ToString ()
616                 {
617                         return this.text;
618                 }
619                 #endregion
620
621                 #region Protected Methods
622                 protected virtual AccessibleObject CreateAccessibilityInstance ()
623                 {
624                         return new ToolStripItemAccessibleObject (this);
625                 }
626
627                 protected override void Dispose (bool disposing)
628                 {
629                         base.Dispose (disposing);
630                 }
631                 
632                 protected virtual void OnAvailableChanged (EventArgs e)
633                 {
634                         EventHandler eh = (EventHandler)(Events [AvailableChangedEvent]);
635                         if (eh != null)
636                                 eh (this, e);
637                 }
638
639                 protected virtual void OnBackColorChanged (EventArgs e)
640                 {
641                         EventHandler eh = (EventHandler)(Events [BackColorChangedEvent]);
642                         if (eh != null)
643                                 eh (this, e);
644                 }
645
646                 protected virtual void OnBoundsChanged ()
647                 {
648                         OnLayout (new LayoutEventArgs(null, ""));
649                 }
650
651                 protected virtual void OnClick (EventArgs e)
652                 {
653                         EventHandler eh = (EventHandler)(Events [ClickEvent]);
654                         if (eh != null)
655                                 eh (this, e);
656                 }
657
658                 protected virtual void OnDisplayStyleChanged (EventArgs e)
659                 {
660                         EventHandler eh = (EventHandler)(Events [DisplayStyleChangedEvent]);
661                         if (eh != null)
662                                 eh (this, e);
663                 }
664
665                 protected virtual void OnDoubleClick (EventArgs e)
666                 {
667                         EventHandler eh = (EventHandler)(Events [DoubleClickEvent]);
668                         if (eh != null)
669                                 eh (this, e);
670
671                         if (!double_click_enabled)
672                                 OnClick (e);
673                 }
674
675                 protected virtual void OnEnabledChanged (EventArgs e)
676                 {
677                         EventHandler eh = (EventHandler)(Events [EnabledChangedEvent]);
678                         if (eh != null)
679                                 eh (this, e);
680                 }
681
682                 protected virtual void OnFontChanged (EventArgs e)
683                 {
684                 }
685
686                 protected virtual void OnForeColorChanged (EventArgs e)
687                 {
688                         EventHandler eh = (EventHandler)(Events [ForeColorChangedEvent]);
689                         if (eh != null)
690                                 eh (this, e);
691                 }
692
693                 protected virtual void OnLayout (LayoutEventArgs e)
694                 {
695                 }
696
697                 protected virtual void OnLocationChanged (EventArgs e)
698                 {
699                         EventHandler eh = (EventHandler)(Events [LocationChangedEvent]);
700                         if (eh != null)
701                                 eh (this, e);
702                 }
703
704                 protected virtual void OnMouseDown (MouseEventArgs e)
705                 {
706                         if (this.Enabled) {
707                                 this.is_pressed = true;
708                                 this.Invalidate ();
709
710                                 MouseEventHandler eh = (MouseEventHandler)(Events [MouseDownEvent]);
711                                 if (eh != null)
712                                         eh (this, e);
713                         }
714                 }
715
716                 protected virtual void OnMouseEnter (EventArgs e)
717                 {
718                         if (this.CanSelect) {
719                                 this.is_selected = true;
720                                 this.Invalidate ();
721                         }
722
723                         EventHandler eh = (EventHandler)(Events [MouseEnterEvent]);
724                         if (eh != null)
725                                 eh (this, e);
726                 }
727
728                 protected virtual void OnMouseHover (EventArgs e)
729                 {
730                         if (this.Enabled) {
731                                 EventHandler eh = (EventHandler)(Events [MouseHoverEvent]);
732                                 if (eh != null)
733                                         eh (this, e);
734                         }
735                 }
736
737                 protected virtual void OnMouseLeave (EventArgs e)
738                 {
739                         if (this.CanSelect) {
740                                 this.is_selected = false;
741                                 this.is_pressed = false;
742                                 this.Invalidate ();
743                         }
744
745                         EventHandler eh = (EventHandler)(Events [MouseLeaveEvent]);
746                         if (eh != null)
747                                 eh (this, e);
748                 }
749
750                 protected virtual void OnMouseMove (MouseEventArgs e)
751                 {
752                         if (this.Enabled) {
753                                 MouseEventHandler eh = (MouseEventHandler)(Events [MouseMoveEvent]);
754                                 if (eh != null)
755                                         eh (this, e);
756                         }
757                 }
758
759                 protected virtual void OnMouseUp (MouseEventArgs e)
760                 {
761                         if (this.Enabled) {
762                                 this.is_pressed = false;
763                                 this.Invalidate ();
764
765                                 MouseEventHandler eh = (MouseEventHandler)(Events [MouseUpEvent]);
766                                 if (eh != null)
767                                         eh (this, e);
768                         }
769                 }
770
771                 protected virtual void OnOwnerChanged (EventArgs e)
772                 {
773                         EventHandler eh = (EventHandler)(Events [OwnerChangedEvent]);
774                         if (eh != null)
775                                 eh (this, e);
776                 }
777
778                 protected virtual void OnPaint (PaintEventArgs e)
779                 {
780                         PaintEventHandler eh = (PaintEventHandler)(Events [PaintEvent]);
781                         if (eh != null)
782                                 eh (this, e);
783                 }
784
785                 protected virtual void OnParentChanged (ToolStrip oldParent, ToolStrip newParent)
786                 {
787                 }
788                 
789                 protected virtual void OnTextChanged (EventArgs e)
790                 {
791                         EventHandler eh = (EventHandler)(Events [TextChangedEvent]);
792                         if (eh != null)
793                                 eh (this, e);
794                 }
795
796                 protected virtual void OnVisibleChanged (EventArgs e)
797                 {
798                         EventHandler eh = (EventHandler)(Events [VisibleChangedEvent]);
799                         if (eh != null)
800                                 eh (this, e);
801                 }
802
803                 protected internal virtual void SetBounds (Rectangle bounds)
804                 {
805                         if (this.bounds != bounds) {
806                                 this.bounds = bounds;
807                                 OnBoundsChanged ();
808                         }
809                 }
810                 #endregion
811
812                 #region Public Events
813                 static object AvailableChangedEvent = new object ();
814                 static object BackColorChangedEvent = new object ();
815                 static object ClickEvent = new object ();
816                 static object DisplayStyleChangedEvent = new object ();
817                 static object DoubleClickEvent = new object ();
818                 static object EnabledChangedEvent = new object ();
819                 static object ForeColorChangedEvent = new object ();
820                 static object LocationChangedEvent = new object ();
821                 static object MouseDownEvent = new object ();
822                 static object MouseEnterEvent = new object ();
823                 static object MouseHoverEvent = new object ();
824                 static object MouseLeaveEvent = new object ();
825                 static object MouseMoveEvent = new object ();
826                 static object MouseUpEvent = new object ();
827                 static object OwnerChangedEvent = new object ();
828                 static object PaintEvent = new object ();
829                 static object TextChangedEvent = new object ();
830                 static object VisibleChangedEvent = new object ();
831
832                 [Browsable (false)]
833                 public event EventHandler AvailableChanged {
834                         add { Events.AddHandler (AvailableChangedEvent, value); }
835                         remove {Events.RemoveHandler (AvailableChangedEvent, value); }
836                 }
837
838                 public event EventHandler BackColorChanged {
839                         add { Events.AddHandler (BackColorChangedEvent, value); }
840                         remove {Events.RemoveHandler (BackColorChangedEvent, value); }
841                 }
842
843                 public event EventHandler Click {
844                         add { Events.AddHandler (ClickEvent, value); }
845                         remove {Events.RemoveHandler (ClickEvent, value); }
846                 }
847
848                 public event EventHandler DisplayStyleChanged {
849                         add { Events.AddHandler (DisplayStyleChangedEvent, value); }
850                         remove {Events.RemoveHandler (DisplayStyleChangedEvent, value); }
851                 }
852
853                 public event EventHandler DoubleClick {
854                         add { Events.AddHandler (DoubleClickEvent, value); }
855                         remove {Events.RemoveHandler (DoubleClickEvent, value); }
856                 }
857
858                 public event EventHandler EnabledChanged {
859                         add { Events.AddHandler (EnabledChangedEvent, value); }
860                         remove {Events.RemoveHandler (EnabledChangedEvent, value); }
861                 }
862
863                 public event EventHandler ForeColorChanged {
864                         add { Events.AddHandler (ForeColorChangedEvent, value); }
865                         remove {Events.RemoveHandler (ForeColorChangedEvent, value); }
866                 }
867
868                 public event EventHandler LocationChanged {
869                         add { Events.AddHandler (LocationChangedEvent, value); }
870                         remove {Events.RemoveHandler (LocationChangedEvent, value); }
871                 }
872
873                 public event MouseEventHandler MouseDown {
874                         add { Events.AddHandler (MouseDownEvent, value); }
875                         remove {Events.RemoveHandler (MouseDownEvent, value); }
876                 }
877
878                 public event EventHandler MouseEnter {
879                         add { Events.AddHandler (MouseEnterEvent, value); }
880                         remove {Events.RemoveHandler (MouseEnterEvent, value); }
881                 }
882
883                 public event EventHandler MouseHover {
884                         add { Events.AddHandler (MouseHoverEvent, value); }
885                         remove {Events.RemoveHandler (MouseHoverEvent, value); }
886                 }
887
888                 public event EventHandler MouseLeave {
889                         add { Events.AddHandler (MouseLeaveEvent, value); }
890                         remove {Events.RemoveHandler (MouseLeaveEvent, value); }
891                 }
892
893                 public event MouseEventHandler MouseMove {
894                         add { Events.AddHandler (MouseMoveEvent, value); }
895                         remove {Events.RemoveHandler (MouseMoveEvent, value); }
896                 }
897
898                 public event MouseEventHandler MouseUp {
899                         add { Events.AddHandler (MouseUpEvent, value); }
900                         remove {Events.RemoveHandler (MouseUpEvent, value); }
901                 }
902
903                 public event EventHandler OwnerChanged {
904                         add { Events.AddHandler (OwnerChangedEvent, value); }
905                         remove {Events.RemoveHandler (OwnerChangedEvent, value); }
906                 }
907
908                 public event PaintEventHandler Paint {
909                         add { Events.AddHandler (PaintEvent, value); }
910                         remove {Events.RemoveHandler (PaintEvent, value); }
911                 }
912
913                 public event EventHandler TextChanged {
914                         add { Events.AddHandler (TextChangedEvent, value); }
915                         remove {Events.RemoveHandler (TextChangedEvent, value); }
916                 }
917
918                 public event EventHandler VisibleChanged {
919                         add { Events.AddHandler (VisibleChangedEvent, value); }
920                         remove {Events.RemoveHandler (VisibleChangedEvent, value); }
921                 }
922                 #endregion
923
924                 #region Internal Methods
925                 internal Rectangle AlignInRectangle (Rectangle outer, Size inner, ContentAlignment align)
926                 {
927                         int x = 0;
928                         int y = 0;
929
930                         if (align == ContentAlignment.BottomLeft || align == ContentAlignment.MiddleLeft || align == ContentAlignment.TopLeft)
931                                 x = outer.X;
932                         else if (align == ContentAlignment.BottomCenter || align == ContentAlignment.MiddleCenter || align == ContentAlignment.TopCenter)
933                                 x = Math.Max (outer.X + ((outer.Width - inner.Width) / 2), outer.Left);
934                         else if (align == ContentAlignment.BottomRight || align == ContentAlignment.MiddleRight || align == ContentAlignment.TopRight)
935                                 x = outer.Right - inner.Width;
936                         if (align == ContentAlignment.TopCenter || align == ContentAlignment.TopLeft || align == ContentAlignment.TopRight)
937                                 y = outer.Y;
938                         else if (align == ContentAlignment.MiddleCenter || align == ContentAlignment.MiddleLeft || align == ContentAlignment.MiddleRight)
939                                 y = outer.Y + (outer.Height - inner.Height) / 2;
940                         else if (align == ContentAlignment.BottomCenter || align == ContentAlignment.BottomRight || align == ContentAlignment.BottomLeft)
941                                 y = outer.Bottom - inner.Height;
942
943                         return new Rectangle (x, y, Math.Min (inner.Width, outer.Width), Math.Min (inner.Height, outer.Height));
944                 }
945
946                 internal void CalculateAutoSize ()
947                 {
948                         if (!this.auto_size || this is ToolStripControlHost)
949                                 return;
950
951                         this.text_size = TextRenderer.MeasureText (this.Text, this.Font, Size.Empty, TextFormatFlags.HidePrefix);
952                         //this.text_size.Width += 6;
953
954                         Size final_size = this.CalculatePreferredSize (Size.Empty);
955
956                         if (final_size != this.Size) {
957                                 this.bounds.Size = final_size;
958                                 if (this.owner != null) 
959                                         this.owner.PerformLayout ();
960                         }
961                 }
962
963                 internal Size CalculatePreferredSize (Size constrainingSize)
964                 {
965                         Size preferred_size = this.DefaultSize;
966
967                         switch (this.display_style) {
968                                 case ToolStripItemDisplayStyle.Text:
969                                         int width = text_size.Width + this.padding.Horizontal;
970                                         int height = text_size.Height + this.padding.Vertical;
971                                         preferred_size = new Size (width, height);
972                                         break;
973                                 case ToolStripItemDisplayStyle.Image:
974                                         if (this.image == null)
975                                                 preferred_size = this.DefaultSize;
976                                         else {
977                                                 switch (this.image_scaling) {
978                                                         case ToolStripItemImageScaling.None:
979                                                                 preferred_size = this.image.Size;
980                                                                 break;
981                                                         case ToolStripItemImageScaling.SizeToFit:
982                                                                 if (this.owner == null)
983                                                                         preferred_size = this.image.Size;
984                                                                 else
985                                                                         preferred_size = this.owner.ImageScalingSize;
986                                                                 break;
987                                                 }
988                                         }
989                                         break;
990                                 case ToolStripItemDisplayStyle.ImageAndText:
991                                         int width2 = text_size.Width + this.padding.Horizontal;
992                                         int height2 = text_size.Height + this.padding.Vertical;
993
994                                         if (this.image != null) {
995                                                 switch (this.text_image_relation) {
996                                                         case TextImageRelation.Overlay:
997                                                                 width2 = Math.Max (width2, this.image.Width);
998                                                                 height2 = Math.Max (height2, this.image.Height);
999                                                                 break;
1000                                                         case TextImageRelation.ImageAboveText:
1001                                                         case TextImageRelation.TextAboveImage:
1002                                                                 width2 = Math.Max (width2, this.image.Width);
1003                                                                 height2 += this.image.Height;
1004                                                                 break;
1005                                                         case TextImageRelation.ImageBeforeText:
1006                                                         case TextImageRelation.TextBeforeImage:
1007                                                                 height2 = Math.Max (height2, this.image.Height);
1008                                                                 width2 += this.image.Width;
1009                                                                 break;
1010                                                 }
1011                                         }
1012
1013                                         preferred_size = new Size (width2, height2);
1014                                         break;
1015                         }
1016
1017                         if (!(this is ToolStripLabel)) {                // Everything but labels have a border
1018                                 preferred_size.Height += 4;
1019                                 preferred_size.Width += 4;
1020                         }
1021                         
1022                         // Account for ToolStripDropDownButton's drop down arrow
1023                         if (this is ToolStripDropDownButton && (this as ToolStripDropDownButton).ShowDropDownArrow)
1024                                 preferred_size.Width += 9;
1025                                 
1026                         if (preferred_size.Width < 23)
1027                                 preferred_size.Width = 23;              // There seems to be a minimum width of 23
1028
1029                         return preferred_size;
1030                 }
1031
1032                 internal void CalculateTextAndImageRectangles (out Rectangle text_rect, out Rectangle image_rect)
1033                 {
1034                         this.CalculateTextAndImageRectangles (this.ContentRectangle, out text_rect, out image_rect);
1035                 }
1036                 
1037                 internal void CalculateTextAndImageRectangles (Rectangle contentRectangle, out Rectangle text_rect, out Rectangle image_rect)
1038                 {
1039                         text_rect = Rectangle.Empty;
1040                         image_rect = Rectangle.Empty;
1041
1042                         switch (this.display_style) {
1043                                 case ToolStripItemDisplayStyle.None:
1044                                         break;
1045                                 case ToolStripItemDisplayStyle.Text:
1046                                         if (this.text != string.Empty)
1047                                                 text_rect = AlignInRectangle (contentRectangle, this.text_size, this.text_align);
1048                                         break;
1049                                 case ToolStripItemDisplayStyle.Image:
1050                                         if (this.image != null)
1051                                                 image_rect = AlignInRectangle (contentRectangle, this.image.Size, this.image_align);
1052                                         break;
1053                                 case ToolStripItemDisplayStyle.ImageAndText:
1054                                         if (this.text != string.Empty && this.image == null)
1055                                                 text_rect = AlignInRectangle (contentRectangle, this.text_size, this.text_align);
1056                                         else if (this.text == string.Empty && this.image != null)
1057                                                 image_rect = AlignInRectangle (contentRectangle, this.image.Size, this.image_align);
1058                                         else if (this.text == string.Empty && this.image == null)
1059                                                 break;
1060                                         else {
1061                                                 Rectangle text_area;
1062                                                 Rectangle image_area;
1063
1064                                                 switch (this.text_image_relation) {
1065                                                         case TextImageRelation.Overlay:
1066                                                                 text_rect = AlignInRectangle (contentRectangle, this.text_size, this.text_align);
1067                                                                 image_rect = AlignInRectangle (contentRectangle, this.image.Size, this.image_align);
1068                                                                 break;
1069                                                         case TextImageRelation.ImageAboveText:
1070                                                                 text_area = new Rectangle (contentRectangle.Left, contentRectangle.Bottom - (text_size.Height - 4), contentRectangle.Width, text_size.Height - 4);
1071                                                                 image_area = new Rectangle (contentRectangle.Left, contentRectangle.Top, contentRectangle.Width, contentRectangle.Height - text_area.Height);
1072
1073                                                                 text_rect = AlignInRectangle (text_area, this.text_size, this.text_align);
1074                                                                 image_rect = AlignInRectangle (image_area, this.image.Size, this.image_align);
1075                                                                 break;
1076                                                         case TextImageRelation.TextAboveImage:
1077                                                                 text_area = new Rectangle (contentRectangle.Left, contentRectangle.Top, contentRectangle.Width, text_size.Height - 4);
1078                                                                 image_area = new Rectangle (contentRectangle.Left, text_area.Bottom, contentRectangle.Width, contentRectangle.Height - text_area.Height);
1079
1080                                                                 text_rect = AlignInRectangle (text_area, this.text_size, this.text_align);
1081                                                                 image_rect = AlignInRectangle (image_area, this.image.Size, this.image_align);
1082                                                                 break;
1083                                                         case TextImageRelation.ImageBeforeText:
1084                                                                 text_area = new Rectangle (contentRectangle.Right - this.text_size.Width, contentRectangle.Top, this.text_size.Width, contentRectangle.Height);
1085                                                                 image_area = new Rectangle (contentRectangle.Left, contentRectangle.Top, text_area.Left - contentRectangle.Left, contentRectangle.Height);
1086
1087                                                                 text_rect = AlignInRectangle (text_area, this.text_size, this.text_align);
1088                                                                 image_rect = AlignInRectangle (image_area, this.image.Size, this.image_align);
1089                                                                 break;
1090                                                         case TextImageRelation.TextBeforeImage:
1091                                                                 text_area = new Rectangle (contentRectangle.Left, contentRectangle.Top, this.text_size.Width, contentRectangle.Height);
1092                                                                 image_area = new Rectangle (text_area.Right, contentRectangle.Top, contentRectangle.Width - text_area.Width, contentRectangle.Height);
1093
1094                                                                 text_rect = AlignInRectangle (text_area, this.text_size, this.text_align);
1095                                                                 image_rect = AlignInRectangle (image_area, this.image.Size, this.image_align);
1096                                                                 break;
1097                                                 }
1098                                         }
1099                                         break;
1100                         }
1101                 }
1102
1103                 internal void FireEvent (EventArgs e, ToolStripItemEventType met)
1104                 {
1105                         switch (met) {
1106                                 case ToolStripItemEventType.MouseUp:
1107                                         this.OnMouseUp ((MouseEventArgs)e);
1108                                         this.OnClick ((MouseEventArgs)e);
1109                                         break;
1110                                 case ToolStripItemEventType.MouseDown:
1111                                         this.OnMouseDown ((MouseEventArgs)e);
1112                                         break;
1113                                 case ToolStripItemEventType.MouseEnter:
1114                                         this.OnMouseEnter (e);
1115                                         break;
1116                                 case ToolStripItemEventType.MouseHover:
1117                                         this.OnMouseHover (e);
1118                                         break;
1119                                 case ToolStripItemEventType.MouseLeave:
1120                                         this.OnMouseLeave (e);
1121                                         break;
1122                                 case ToolStripItemEventType.MouseMove:
1123                                         this.OnMouseMove ((MouseEventArgs)e);
1124                                         break;
1125                                 case ToolStripItemEventType.Paint:
1126                                         this.OnPaint ((PaintEventArgs)e);
1127                                         break;
1128                         }
1129                 }
1130                 #endregion
1131                 
1132                 public class ToolStripItemAccessibleObject : AccessibleObject
1133                 {
1134                         private ToolStripItem owner;
1135                         
1136                         public ToolStripItemAccessibleObject (ToolStripItem ownerItem)
1137                         {
1138                                 if (ownerItem == null)
1139                                         throw new ArgumentNullException ("ownerItem");
1140                                         
1141                                 this.owner = ownerItem;
1142                                 base.default_action = string.Empty;
1143                                 base.keyboard_shortcut = string.Empty;
1144                                 base.name = string.Empty;
1145                                 base.value = string.Empty;
1146                         }
1147
1148                         #region Public Properties
1149                         public override Rectangle Bounds {
1150                                 get {
1151                                         return owner.Visible ? owner.Bounds : Rectangle.Empty;
1152                                 }
1153                         }
1154
1155                         public override string DefaultAction {
1156                                 get { return base.DefaultAction; }
1157                         }
1158
1159                         public override string Description {
1160                                 get { return base.Description; }
1161                         }
1162
1163                         public override string Help {
1164                                 get { return base.Help; }
1165                         }
1166
1167                         public override string KeyboardShortcut {
1168                                 get { return base.KeyboardShortcut; }
1169                         }
1170
1171                         public override string Name {
1172                                 get {
1173                                         if (base.name == string.Empty)
1174                                                 return owner.Text;
1175                                                 
1176                                         return base.Name;
1177                                 }
1178                                 set { base.Name = value; }
1179                         }
1180
1181                         public override AccessibleObject Parent {
1182                                 get { return base.Parent; }
1183                         }
1184
1185                         public override AccessibleRole Role {
1186                                 get { return base.Role; }
1187                         }
1188
1189                         public override AccessibleStates State {
1190                                 get { return base.State; }
1191                         }
1192                         #endregion
1193
1194                         #region Public Methods
1195                         public void AddState (AccessibleStates state)
1196                         {
1197                                 base.state = state;
1198                         }
1199
1200                         public override void DoDefaultAction ()
1201                         {
1202                                 base.DoDefaultAction ();
1203                         }
1204
1205                         public override int GetHelpTopic (out string FileName)
1206                         {
1207                                 return base.GetHelpTopic (out FileName);
1208                         }
1209
1210                         public override AccessibleObject Navigate (AccessibleNavigation navdir)
1211                         {
1212                                 return base.Navigate (navdir);
1213                         }
1214
1215                         public override string ToString ()
1216                         {
1217                                 return string.Format ("ToolStripItemAccessibleObject: Owner = {0}", owner.ToString());
1218                         }
1219                         #endregion
1220                 }
1221         }
1222 }
1223 #endif