Merge branch 'master' into import-system-xml-linq
[mono.git] / mcs / class / System.Windows.Forms / System.Windows.Forms / ToolStripDropDown.cs
1 //
2 // ToolStripDropDown.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
29 using System.Drawing;
30 using System.Runtime.InteropServices;
31 using System.ComponentModel;
32
33 namespace System.Windows.Forms
34 {
35         [ClassInterface (ClassInterfaceType.AutoDispatch)]
36         [ComVisible (true)]
37         [Designer ("System.Windows.Forms.Design.ToolStripDropDownDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
38         public class ToolStripDropDown : ToolStrip
39         {
40                 private bool allow_transparency;
41                 private bool auto_close;
42                 private bool can_overflow;
43                 private bool drop_shadow_enabled = true;
44                 private double opacity = 1D;
45                 private ToolStripItem owner_item;
46
47                 #region Public Constructor
48                 public ToolStripDropDown () : base ()
49                 {
50                         SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
51                         SetStyle (ControlStyles.ResizeRedraw, true);
52
53                         this.auto_close = true;
54                         is_visible = false;
55                         this.DefaultDropDownDirection = ToolStripDropDownDirection.Right;
56                         this.GripStyle = ToolStripGripStyle.Hidden;
57                         this.is_toplevel = true;
58                 }
59                 #endregion
60
61                 #region Public Properties
62                 [Browsable (false)]
63                 [EditorBrowsable (EditorBrowsableState.Never)]
64                 public new bool AllowItemReorder {
65                         get { return base.AllowItemReorder; }
66                         set { base.AllowItemReorder = value; }
67                 }
68                 
69                 [Browsable (false)]
70                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
71                 public bool AllowTransparency {
72                         get { return allow_transparency; }
73                         set {
74                                 if (value == allow_transparency)
75                                         return;
76
77                                 if ((XplatUI.SupportsTransparency () & TransparencySupport.Set) != 0) {
78                                         allow_transparency = value;
79
80                                         if (this.IsHandleCreated) {
81                                                 if (value) 
82                                                         XplatUI.SetWindowTransparency (Handle, Opacity, Color.Empty);
83                                                 else
84                                                         UpdateStyles (); // Remove the WS_EX_LAYERED style
85                                         }
86                                 }
87                         }
88                 }
89
90                 [Browsable (false)]
91                 [EditorBrowsable (EditorBrowsableState.Never)]
92                 public override AnchorStyles Anchor {
93                         get { return base.Anchor; }
94                         set { base.Anchor = value; }
95                 }
96
97                 [DefaultValue (true)]
98                 public bool AutoClose
99                 {
100                         get { return this.auto_close; }
101                         set { this.auto_close = value; }
102                 }
103
104                 [DefaultValue (true)]
105                 public override bool AutoSize {
106                         get { return base.AutoSize; }
107                         set { base.AutoSize = value; }
108                 }
109
110                 [Browsable (false)]
111                 [DefaultValue (false)]
112                 [EditorBrowsable (EditorBrowsableState.Never)]
113                 public new bool CanOverflow {
114                         get { return this.can_overflow; }
115                         set { this.can_overflow = value; }
116                 }
117                 
118                 [Browsable (false)]
119                 [EditorBrowsable (EditorBrowsableState.Never)]
120                 public new ContextMenu ContextMenu {
121                         get { return null; }
122                         set { }
123                 }
124
125                 [Browsable (false)]
126                 [EditorBrowsable (EditorBrowsableState.Never)]
127                 public new ContextMenuStrip ContextMenuStrip {
128                         get { return null; }
129                         set { }
130                 }
131
132                 public override ToolStripDropDownDirection DefaultDropDownDirection {
133                         get { return base.DefaultDropDownDirection; }
134                         set { base.DefaultDropDownDirection = value; }
135                 }
136                 
137                 [Browsable (false)]
138                 [EditorBrowsable (EditorBrowsableState.Always)]
139                 [DefaultValue (DockStyle.None)]
140                 public override DockStyle Dock {
141                         get { return base.Dock; }
142                         set { base.Dock = value; }
143                 }
144                 
145                 public bool DropShadowEnabled {
146                         get { return this.drop_shadow_enabled; }
147                         set {
148                                 if (this.drop_shadow_enabled == value)
149                                         return;
150                                         
151                                 this.drop_shadow_enabled = value;
152                                 UpdateStyles ();        // Re-CreateParams
153                         }
154                 }
155
156                 public override Font Font {
157                         get { return base.Font; }
158                         set { base.Font = value; }
159                 }
160
161                 [Browsable (false)]
162                 [EditorBrowsable (EditorBrowsableState.Never)]
163                 public new ToolStripGripDisplayStyle GripDisplayStyle {
164                         get { return ToolStripGripDisplayStyle.Vertical; }
165                 }
166
167                 [Browsable (false)]
168                 [EditorBrowsable (EditorBrowsableState.Never)]
169                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
170                 public new Padding GripMargin {
171                         get { return Padding.Empty; }
172                         set { }
173                 }
174
175                 [Browsable (false)]
176                 [EditorBrowsable (EditorBrowsableState.Never)]
177                 public new Rectangle GripRectangle {
178                         get { return Rectangle.Empty; }
179                 }
180
181                 [Browsable (false)]
182                 [EditorBrowsable (EditorBrowsableState.Never)]
183                 [DefaultValue (ToolStripGripStyle.Hidden)]
184                 public new ToolStripGripStyle GripStyle {
185                         get { return base.GripStyle; }
186                         set { base.GripStyle = value; }
187                 }
188
189                 [Browsable (false)]
190                 public bool IsAutoGenerated {
191                         get { return this is ToolStripOverflow; }
192                 }
193                 
194                 [Browsable (false)]
195                 [EditorBrowsable (EditorBrowsableState.Never)]
196                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
197                 public new Point Location {
198                         get { return base.Location; }
199                         set { base.Location = value; }
200                 }
201
202                 [DefaultValue (1D)]
203                 [TypeConverter (typeof (OpacityConverter))]
204                 [Browsable (false)]
205                 [EditorBrowsable (EditorBrowsableState.Advanced)]
206                 public double Opacity {
207                         get { return this.opacity; }
208                         set {
209                                         if (this.opacity == value)
210                                                 return;
211                                                 
212                                         this.opacity = value;
213                                         this.allow_transparency = true;
214                                         
215                                         if (this.IsHandleCreated) {
216                                                 UpdateStyles ();
217                                                 XplatUI.SetWindowTransparency (Handle, opacity, Color.Empty);
218                                         }
219                         }
220                 }
221
222                 [Browsable (false)]
223                 [EditorBrowsable (EditorBrowsableState.Never)]
224                 public new ToolStripOverflowButton OverflowButton {
225                         get { return base.OverflowButton; }
226                 }
227
228                 [Browsable (false)]
229                 [DefaultValue (null)]
230                 public ToolStripItem OwnerItem {
231                         get { return this.owner_item; }
232                         set { this.owner_item = value; 
233                                 
234                                 if (this.owner_item != null) {
235                                         if (this.owner_item.Owner != null && this.owner_item.Owner.RenderMode != ToolStripRenderMode.ManagerRenderMode)
236                                                 this.Renderer = this.owner_item.Owner.Renderer;
237
238                                         Font = owner_item.Font;
239                                 }
240                         }
241                 }
242
243                 [Browsable (false)]
244                 [EditorBrowsable (EditorBrowsableState.Always)]
245                 public new Region Region {
246                         get { return base.Region; }
247                         set { base.Region = value; }
248                 }
249
250                 [Localizable (true)]
251                 [AmbientValue (RightToLeft.Inherit)]
252                 public override RightToLeft RightToLeft {
253                         get { return base.RightToLeft; }
254                         set { base.RightToLeft = value; }
255                 }
256
257                 [Browsable (false)]
258                 [EditorBrowsable (EditorBrowsableState.Never)]
259                 public new bool Stretch {
260                         get { return false; }
261                         set { }
262                 }
263
264                 [Browsable (false)]
265                 [EditorBrowsable (EditorBrowsableState.Never)]
266                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
267                 public new int TabIndex {
268                         get { return 0; }
269                         set { }
270                 }
271
272                 [Browsable (false)]
273                 [DefaultValue (ToolStripTextDirection.Horizontal)]
274                 public override ToolStripTextDirection TextDirection {
275                         get { return base.TextDirection; }
276                         set { base.TextDirection = value; }
277                 }
278
279                 [Browsable (false)]
280                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
281                 [EditorBrowsable (EditorBrowsableState.Advanced)]
282                 public bool TopLevel {
283                         get { return GetTopLevel (); }
284                         set { SetTopLevel (value); }
285                 }
286                 
287                 [Browsable (false)]
288                 [Localizable (true)]
289                 [DefaultValue (false)]
290                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
291                 public new bool Visible {
292                         get { return base.Visible; }
293                         set { base.Visible = value; }
294                 }
295                 #endregion
296
297                 #region Protected Properties
298                 protected override CreateParams CreateParams {
299                         get {
300                                 CreateParams cp = base.CreateParams;
301
302                                 cp.Style = unchecked ((int)(WindowStyles.WS_POPUP | WindowStyles.WS_CLIPCHILDREN));
303                                 cp.ClassStyle |= (int)XplatUIWin32.ClassStyle.CS_DROPSHADOW;
304                                 cp.ExStyle |= (int)(WindowExStyles.WS_EX_TOOLWINDOW | WindowExStyles.WS_EX_TOPMOST);
305
306                                 if (Opacity < 1.0 && allow_transparency)
307                                         cp.ExStyle |= (int)WindowExStyles.WS_EX_LAYERED;
308                                 if (TopMost)
309                                         cp.ExStyle |= (int) WindowExStyles.WS_EX_TOPMOST;
310
311                                 return cp;
312                         }
313                 }
314
315                 protected override DockStyle DefaultDock {
316                         get { return DockStyle.None; }
317                 }
318
319                 protected override Padding DefaultPadding {
320                         get { return new Padding (1, 2, 1, 2); }
321                 }
322
323                 protected override bool DefaultShowItemToolTips {
324                         get { return true; }
325                 }
326
327                 protected internal override Size MaxItemSize {
328                         get { return new Size (Screen.PrimaryScreen.Bounds.Width - 2, Screen.PrimaryScreen.Bounds.Height - 34); }
329                 }
330
331                 protected virtual bool TopMost {
332                         get { return true; }
333                 }
334                 #endregion
335
336                 #region Public Methods
337                 public void Close ()
338                 {
339                         this.Close (ToolStripDropDownCloseReason.CloseCalled);
340                 }
341
342                 public void Close (ToolStripDropDownCloseReason reason)
343                 {
344                         if (!this.Visible)
345                                 return;
346                                 
347                         // Give users a chance to cancel the close
348                         ToolStripDropDownClosingEventArgs e = new ToolStripDropDownClosingEventArgs (reason);
349                         this.OnClosing (e);
350
351                         if (e.Cancel)
352                                 return;
353
354                         // Don't actually close if AutoClose == true unless explicitly called
355                         if (!this.auto_close && reason != ToolStripDropDownCloseReason.CloseCalled)
356                                 return;
357
358                         // Detach from the tracker
359                         ToolStripManager.AppClicked -= new EventHandler (ToolStripMenuTracker_AppClicked); ;
360                         ToolStripManager.AppFocusChange -= new EventHandler (ToolStripMenuTracker_AppFocusChange);
361
362                         // Hide this dropdown
363                         this.Hide ();
364
365                         // Owner MenuItem needs to be told to redraw (it's no longer selected)
366                         if (owner_item != null)
367                                 owner_item.Invalidate ();
368
369                         // Recursive hide all child dropdowns
370                         foreach (ToolStripItem tsi in this.Items)
371                                 tsi.Dismiss (reason);
372                         
373                         this.OnClosed (new ToolStripDropDownClosedEventArgs (reason));
374                 }
375
376                 [Browsable (false)]
377                 [EditorBrowsable (EditorBrowsableState.Never)]
378                 public new void Show ()
379                 {
380                         Show (Location, DefaultDropDownDirection);
381                 }
382                 
383                 public void Show (Point screenLocation)
384                 {
385                         Show (screenLocation, DefaultDropDownDirection);
386                 }
387                 
388                 public void Show (Control control, Point position)
389                 {
390                         if (control == null)
391                                 throw new ArgumentNullException ("control");
392                         
393                         XplatUI.SetOwner (Handle, control.Handle);
394                         Show (control.PointToScreen (position), DefaultDropDownDirection);
395                 }
396                 
397                 public void Show (int x, int y)
398                 {
399                         Show (new Point (x, y), DefaultDropDownDirection);
400                 }
401                 
402                 public void Show (Point position, ToolStripDropDownDirection direction)
403                 {
404                         this.PerformLayout ();
405                         
406                         Point show_point = position;
407                         Point max_screen = new Point (SystemInformation.VirtualScreen.Width, SystemInformation.VirtualScreen.Height);
408                         
409                         if (this is ContextMenuStrip) {
410                                 // If we are going to go offscreen, adjust our direction so we don't...
411                                 // X direction
412                                 switch (direction) {
413                                         case ToolStripDropDownDirection.AboveLeft:
414                                                 if (show_point.X - this.Width < 0)
415                                                         direction = ToolStripDropDownDirection.AboveRight;
416                                                 break;
417                                         case ToolStripDropDownDirection.BelowLeft:
418                                                 if (show_point.X - this.Width < 0)
419                                                         direction = ToolStripDropDownDirection.BelowRight;
420                                                 break;
421                                         case ToolStripDropDownDirection.Left:
422                                                 if (show_point.X - this.Width < 0)
423                                                         direction = ToolStripDropDownDirection.Right;
424                                                 break;
425                                         case ToolStripDropDownDirection.AboveRight:
426                                                 if (show_point.X + this.Width > max_screen.X)
427                                                         direction = ToolStripDropDownDirection.AboveLeft;
428                                                 break;
429                                         case ToolStripDropDownDirection.BelowRight:
430                                         case ToolStripDropDownDirection.Default:
431                                                 if (show_point.X + this.Width > max_screen.X)
432                                                         direction = ToolStripDropDownDirection.BelowLeft;
433                                                 break;
434                                         case ToolStripDropDownDirection.Right:
435                                                 if (show_point.X + this.Width > max_screen.X)
436                                                         direction = ToolStripDropDownDirection.Left;
437                                                 break;
438                                 }
439
440                                 // Y direction
441                                 switch (direction) {
442                                         case ToolStripDropDownDirection.AboveLeft:
443                                                 if (show_point.Y - this.Height < 0)
444                                                         direction = ToolStripDropDownDirection.BelowLeft;
445                                                 break;
446                                         case ToolStripDropDownDirection.AboveRight:
447                                                 if (show_point.Y - this.Height < 0)
448                                                         direction = ToolStripDropDownDirection.BelowRight;
449                                                 break;
450                                         case ToolStripDropDownDirection.BelowLeft:
451                                                 if (show_point.Y + this.Height > max_screen.Y && show_point.Y - this.Height > 0)
452                                                         direction = ToolStripDropDownDirection.AboveLeft;
453                                                 break;
454                                         case ToolStripDropDownDirection.BelowRight:
455                                         case ToolStripDropDownDirection.Default:
456                                                 if (show_point.Y + this.Height > max_screen.Y && show_point.Y - this.Height > 0)
457                                                         direction = ToolStripDropDownDirection.AboveRight;
458                                                 break;
459                                         case ToolStripDropDownDirection.Left:
460                                                 if (show_point.Y + this.Height > max_screen.Y && show_point.Y - this.Height > 0)
461                                                         direction = ToolStripDropDownDirection.AboveLeft;
462                                                 break;
463                                         case ToolStripDropDownDirection.Right:
464                                                 if (show_point.Y + this.Height > max_screen.Y && show_point.Y - this.Height > 0)
465                                                         direction = ToolStripDropDownDirection.AboveRight;
466                                                 break;
467                                 }
468                         }
469                 
470                         switch (direction) {
471                                 case ToolStripDropDownDirection.AboveLeft:
472                                         show_point.Y -= this.Height;
473                                         show_point.X -= this.Width;
474                                         break;
475                                 case ToolStripDropDownDirection.AboveRight:
476                                         show_point.Y -= this.Height;
477                                         break;
478                                 case ToolStripDropDownDirection.BelowLeft:
479                                         show_point.X -= this.Width;
480                                         break;
481                                 case ToolStripDropDownDirection.Left:
482                                         show_point.X -= this.Width;
483                                         break;
484                                 case ToolStripDropDownDirection.Right:
485                                         break;
486                         }
487
488                         // Fix offscreen horizontal positions
489                         if ((show_point.X + this.Width) > max_screen.X)
490                                 show_point.X = max_screen.X - this.Width;
491                         if (show_point.X < 0)
492                                 show_point.X = 0;
493
494                         // Fix offscreen vertical positions
495                         if ((show_point.Y + this.Height) > max_screen.Y)
496                                 show_point.Y = max_screen.Y - this.Height;
497                         if (show_point.Y < 0)
498                                 show_point.Y = 0;
499
500                         if (this.Location != show_point)
501                                 this.Location = show_point;
502
503                         CancelEventArgs e = new CancelEventArgs ();
504                         this.OnOpening (e);
505
506                         if (e.Cancel)
507                                 return;
508
509                         // The tracker lets us know when the form is clicked or loses focus
510                         ToolStripManager.AppClicked += new EventHandler (ToolStripMenuTracker_AppClicked);
511                         ToolStripManager.AppFocusChange += new EventHandler (ToolStripMenuTracker_AppFocusChange);
512
513                         base.Show ();
514
515                         ToolStripManager.SetActiveToolStrip (this, ToolStripManager.ActivatedByKeyboard);
516
517                         this.OnOpened (EventArgs.Empty);
518                 }
519                 
520                 public void Show (Control control, int x, int y)
521                 {
522                         if (control == null)
523                                 throw new ArgumentNullException ("control");
524
525                         Show (control, new Point (x, y));
526                 }
527                 
528                 public void Show (Control control, Point position, ToolStripDropDownDirection direction)
529                 {
530                         if (control == null)
531                                 throw new ArgumentNullException ("control");
532
533                         XplatUI.SetOwner (Handle, control.Handle);
534                         Show (control.PointToScreen (position), direction);
535                 }
536                 #endregion
537
538                 #region Protected Methods
539                 protected override AccessibleObject CreateAccessibilityInstance ()
540                 {
541                         return new ToolStripDropDownAccessibleObject (this);
542                 }
543                 
544                 protected override void CreateHandle ()
545                 {
546                         base.CreateHandle ();
547                 }
548
549                 protected override LayoutSettings CreateLayoutSettings (ToolStripLayoutStyle style)
550                 {
551                         return base.CreateLayoutSettings (style);
552                 }
553                 
554                 protected override void Dispose (bool disposing)
555                 {
556                         base.Dispose (disposing);
557                 }
558
559                 protected virtual void OnClosed (ToolStripDropDownClosedEventArgs e)
560                 {
561                         ToolStripDropDownClosedEventHandler eh = (ToolStripDropDownClosedEventHandler)(Events [ClosedEvent]);
562                         if (eh != null)
563                                 eh (this, e);
564                 }
565
566                 protected virtual void OnClosing (ToolStripDropDownClosingEventArgs e)
567                 {
568                         ToolStripDropDownClosingEventHandler eh = (ToolStripDropDownClosingEventHandler)(Events [ClosingEvent]);
569                         if (eh != null)
570                                 eh (this, e);
571                 }
572
573                 protected override void OnHandleCreated (EventArgs e)
574                 {
575                         base.OnHandleCreated (e);
576
577                         if (Application.MWFThread.Current.Context != null && Application.MWFThread.Current.Context.MainForm != null)
578                                 XplatUI.SetOwner (this.Handle, Application.MWFThread.Current.Context.MainForm.Handle);
579                 }
580
581                 protected override void OnItemClicked (ToolStripItemClickedEventArgs e)
582                 {
583                         base.OnItemClicked (e);
584                 }
585
586                 protected override void OnLayout (LayoutEventArgs e)
587                 {
588                         // Find the widest menu item, so we know how wide to make our dropdown
589                         int widest = 0;
590
591                         foreach (ToolStripItem tsi in this.Items) {
592                                 if (!tsi.Available) 
593                                         continue;
594                                         
595                                 tsi.SetPlacement (ToolStripItemPlacement.Main);
596                                 
597                                 widest = Math.Max (widest, tsi.GetPreferredSize (Size.Empty).Width + tsi.Margin.Horizontal);
598                         }
599                         
600                         // Add any padding our dropdown has set
601                         widest += this.Padding.Horizontal;
602                         
603                         int x = this.Padding.Left;
604                         int y = this.Padding.Top;
605
606                         foreach (ToolStripItem tsi in this.Items) {
607                                 if (!tsi.Available)
608                                         continue;
609
610                                 y += tsi.Margin.Top;
611
612                                 int height = 0;
613
614                                 Size preferred_size = tsi.GetPreferredSize (Size.Empty);
615
616                                 if (preferred_size.Height > 22)
617                                         height = preferred_size.Height;
618                                 else if (tsi is ToolStripSeparator)
619                                         height = 7;
620                                 else
621                                         height = 22;
622
623                                 tsi.SetBounds (new Rectangle (x, y, preferred_size.Width, height));
624                                 y += height + tsi.Margin.Bottom;
625                         }
626
627                         this.Size = new Size (widest, y + this.Padding.Bottom);
628                         this.SetDisplayedItems ();
629                         this.OnLayoutCompleted (EventArgs.Empty);
630                         this.Invalidate ();
631                 }
632
633                 protected override void OnMouseUp (MouseEventArgs mea)
634                 {
635                         base.OnMouseUp (mea);
636                 }
637
638                 protected virtual void OnOpened (EventArgs e)
639                 {
640                         EventHandler eh = (EventHandler)(Events [OpenedEvent]);
641                         if (eh != null)
642                                 eh (this, e);
643                 }
644
645                 protected virtual void OnOpening (CancelEventArgs e)
646                 {
647                         CancelEventHandler eh = (CancelEventHandler)(Events [OpeningEvent]);
648                         if (eh != null)
649                                 eh (this, e);
650                 }
651
652                 protected override void OnParentChanged (EventArgs e)
653                 {
654                         base.OnParentChanged (e);
655                         
656                         if (Parent is ToolStrip)
657                                 this.Renderer = (Parent as ToolStrip).Renderer;
658                 }
659
660                 protected override void OnVisibleChanged (EventArgs e)
661                 {
662                         base.OnVisibleChanged (e);
663
664                         if (owner_item != null && owner_item is ToolStripDropDownItem) {
665                                 ToolStripDropDownItem dropdown_owner = (ToolStripDropDownItem)owner_item;
666                                 if (Visible)
667                                         dropdown_owner.OnDropDownOpened (EventArgs.Empty);
668                                 else
669                                         dropdown_owner.OnDropDownClosed (EventArgs.Empty);
670                         }
671                 }
672
673                 [EditorBrowsable (EditorBrowsableState.Advanced)]
674                 protected override bool ProcessDialogChar (char charCode)
675                 {
676                         return base.ProcessDialogChar (charCode);
677                 }
678
679                 protected override bool ProcessDialogKey (Keys keyData)
680                 {
681                         // We don't want to let our base change the active ToolStrip
682                         switch (keyData) {
683                                 case Keys.Control | Keys.Tab:
684                                 case Keys.Control | Keys.Shift | Keys.Tab:
685                                         return true;
686                         }
687                         
688                         return base.ProcessDialogKey (keyData);
689                 }
690
691                 protected override bool ProcessMnemonic (char charCode)
692                 {
693                         return base.ProcessMnemonic (charCode);
694                 }
695
696                 protected override void ScaleControl (SizeF factor, BoundsSpecified specified)
697                 {
698                         base.ScaleControl (factor, specified);
699                 }
700                 
701                 [EditorBrowsable (EditorBrowsableState.Never)]
702                 protected override void ScaleCore (float dx, float dy)
703                 {
704                         base.ScaleCore (dx, dy);
705                 }
706
707                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
708                 {
709                         base.SetBoundsCore (x, y, width, height, specified);
710                 }
711
712                 protected override void SetVisibleCore (bool visible)
713                 {
714                         base.SetVisibleCore (visible);
715                 }
716
717                 protected override void WndProc (ref Message m)
718                 {
719                         const int MA_NOACTIVATE = 0x0003;
720
721                         // Don't activate when the WM tells us to
722                         if ((Msg)m.Msg == Msg.WM_MOUSEACTIVATE) {
723                                 m.Result = (IntPtr)MA_NOACTIVATE;
724                                 return;
725                         }
726
727                         base.WndProc (ref m);
728                 }
729                 #endregion
730
731                 #region Public Events
732                 static object ClosedEvent = new object ();
733                 static object ClosingEvent = new object ();
734                 static object OpenedEvent = new object ();
735                 static object OpeningEvent = new object ();
736                 static object ScrollEvent = new object ();
737
738                 [Browsable (false)]
739                 public new event EventHandler BackgroundImageChanged {
740                         add { base.BackgroundImageChanged += value; }
741                         remove { base.BackgroundImageChanged -= value; }
742                 }
743
744                 [Browsable (false)]
745                 public new event EventHandler BackgroundImageLayoutChanged {
746                         add { base.BackgroundImageLayoutChanged += value; }
747                         remove { base.BackgroundImageLayoutChanged -= value; }
748                 }
749
750                 [Browsable (false)]
751                 public new event EventHandler BindingContextChanged {
752                         add { base.BindingContextChanged += value; }
753                         remove { base.BindingContextChanged -= value; }
754                 }
755
756                 [Browsable (false)]
757                 [EditorBrowsable (EditorBrowsableState.Always)]
758                 public new event UICuesEventHandler ChangeUICues {
759                         add { base.ChangeUICues += value; }
760                         remove { base.ChangeUICues -= value; }
761                 }
762
763                 public event ToolStripDropDownClosedEventHandler Closed {
764                         add { Events.AddHandler (ClosedEvent, value); }
765                         remove { Events.RemoveHandler (ClosedEvent, value); }
766                 }
767
768                 public event ToolStripDropDownClosingEventHandler Closing {
769                         add { Events.AddHandler (ClosingEvent, value); }
770                         remove { Events.RemoveHandler (ClosingEvent, value); }
771                 }
772
773                 [Browsable (false)]
774                 [EditorBrowsable (EditorBrowsableState.Never)]
775                 public new event EventHandler ContextMenuChanged {
776                         add { base.ContextMenuChanged += value; }
777                         remove { base.ContextMenuChanged -= value; }
778                 }
779
780                 [Browsable (false)]
781                 [EditorBrowsable (EditorBrowsableState.Always)]
782                 public new event EventHandler ContextMenuStripChanged {
783                         add { base.ContextMenuStripChanged += value; }
784                         remove { base.ContextMenuStripChanged -= value; }
785                 }
786
787                 [Browsable (false)]
788                 [EditorBrowsable (EditorBrowsableState.Always)]
789                 public new event EventHandler DockChanged {
790                         add { base.DockChanged += value; }
791                         remove { base.DockChanged -= value; }
792                 }
793
794                 [Browsable (false)]
795                 [EditorBrowsable (EditorBrowsableState.Always)]
796                 public new event EventHandler Enter {
797                         add { base.Enter += value; }
798                         remove { base.Enter -= value; }
799                 }
800
801                 [Browsable (false)]
802                 [EditorBrowsable (EditorBrowsableState.Always)]
803                 public new event EventHandler FontChanged {
804                         add { base.FontChanged += value; }
805                         remove { base.FontChanged -= value; }
806                 }
807
808                 [Browsable (false)]
809                 [EditorBrowsable (EditorBrowsableState.Never)]
810                 public new event EventHandler ForeColorChanged {
811                         add { base.ForeColorChanged += value; }
812                         remove { base.ForeColorChanged -= value; }
813                 }
814
815                 [Browsable (false)]
816                 [EditorBrowsable (EditorBrowsableState.Never)]
817                 public new event GiveFeedbackEventHandler GiveFeedback {
818                         add { base.GiveFeedback += value; }
819                         remove { base.GiveFeedback -= value; }
820                 }
821
822                 [Browsable (false)]
823                 [EditorBrowsable (EditorBrowsableState.Always)]
824                 public new event HelpEventHandler HelpRequested {
825                         add { base.HelpRequested += value; }
826                         remove { base.HelpRequested -= value; }
827                 }
828
829                 [Browsable (false)]
830                 [EditorBrowsable (EditorBrowsableState.Always)]
831                 public new event EventHandler ImeModeChanged {
832                         add { base.ImeModeChanged += value; }
833                         remove { base.ImeModeChanged -= value; }
834                 }
835
836                 [Browsable (false)]
837                 [EditorBrowsable (EditorBrowsableState.Always)]
838                 public new event KeyEventHandler KeyDown {
839                         add { base.KeyDown += value; }
840                         remove { base.KeyDown -= value; }
841                 }
842
843                 [Browsable (false)]
844                 [EditorBrowsable (EditorBrowsableState.Always)]
845                 public new event KeyPressEventHandler KeyPress {
846                         add { base.KeyPress += value; }
847                         remove { base.KeyPress -= value; }
848                 }
849
850                 [Browsable (false)]
851                 [EditorBrowsable (EditorBrowsableState.Always)]
852                 public new event KeyEventHandler KeyUp {
853                         add { base.KeyUp += value; }
854                         remove { base.KeyUp -= value; }
855                 }
856
857                 [Browsable (false)]
858                 [EditorBrowsable (EditorBrowsableState.Always)]
859                 public new event EventHandler Leave {
860                         add { base.Leave += value; }
861                         remove { base.Leave -= value; }
862                 }
863
864                 public event EventHandler Opened {
865                         add { Events.AddHandler (OpenedEvent, value); }
866                         remove { Events.RemoveHandler (OpenedEvent, value); }
867                 }
868
869                 public event CancelEventHandler Opening {
870                         add { Events.AddHandler (OpeningEvent, value); }
871                         remove { Events.RemoveHandler (OpeningEvent, value); }
872                 }
873
874                 [Browsable (false)]
875                 [EditorBrowsable (EditorBrowsableState.Always)]
876                 public new event EventHandler RegionChanged {
877                         add { base.RegionChanged += value; }
878                         remove { base.RegionChanged -= value; }
879                 }
880
881                 [Browsable (false)]
882                 [EditorBrowsable (EditorBrowsableState.Never)]
883                 public new event ScrollEventHandler Scroll {
884                         add { Events.AddHandler (ScrollEvent, value); }
885                         remove { Events.RemoveHandler (ScrollEvent, value); }
886                 }
887
888                 [Browsable (false)]
889                 [EditorBrowsable (EditorBrowsableState.Always)]
890                 public new event EventHandler StyleChanged {
891                         add { base.StyleChanged += value; }
892                         remove { base.StyleChanged -= value; }
893                 }
894
895                 [Browsable (false)]
896                 [EditorBrowsable (EditorBrowsableState.Never)]
897                 public new event EventHandler TabIndexChanged {
898                         add { base.TabIndexChanged += value; }
899                         remove { base.TabIndexChanged -= value; }
900                 }
901
902                 [Browsable (false)]
903                 [EditorBrowsable (EditorBrowsableState.Never)]
904                 public new event EventHandler TabStopChanged {
905                         add { base.TabStopChanged += value; }
906                         remove { base.TabStopChanged -= value; }
907                 }
908
909                 [Browsable (false)]
910                 [EditorBrowsable (EditorBrowsableState.Never)]
911                 public new event EventHandler TextChanged {
912                         add { base.TextChanged += value; }
913                         remove { base.TextChanged -= value; }
914                 }
915
916                 [Browsable (false)]
917                 [EditorBrowsable (EditorBrowsableState.Never)]
918                 public new event EventHandler Validated {
919                         add { base.Validated += value; }
920                         remove { base.Validated -= value; }
921                 }
922
923                 [Browsable (false)]
924                 [EditorBrowsable (EditorBrowsableState.Never)]
925                 public new event CancelEventHandler Validating {
926                         add { base.Validating += value; }
927                         remove { base.Validating -= value; }
928                 }
929                 #endregion
930
931                 #region Private Methods
932                 internal override void Dismiss (ToolStripDropDownCloseReason reason)
933                 {
934                         this.Close (reason);
935                         base.Dismiss (reason);
936
937                         // ContextMenuStrip won't have a parent
938                         if (this.OwnerItem == null)
939                                 return;
940                         
941                         // Ensure Submenu loes keyboard capture when closing.
942                         ToolStripManager.SetActiveToolStrip (null, false);                      
943                 }
944
945                 internal override ToolStrip GetTopLevelToolStrip ()
946                 {
947                         if (this.OwnerItem == null)
948                                 return this;
949                                 
950                         return this.OwnerItem.GetTopLevelToolStrip ();
951                 }
952
953                 internal override bool ProcessArrowKey (Keys keyData)
954                 {
955                         switch (keyData) {
956                                 case Keys.Down:
957                                 case Keys.Tab:
958                                         this.SelectNextToolStripItem (this.GetCurrentlySelectedItem (), true);
959                                         return true;
960                                 case Keys.Up:
961                                 case Keys.Shift | Keys.Tab:
962                                         this.SelectNextToolStripItem (this.GetCurrentlySelectedItem (), false);
963                                         return true;
964                                 case Keys.Right:
965                                         this.GetTopLevelToolStrip ().SelectNextToolStripItem (this.TopLevelOwnerItem, true);
966                                         return true;
967                                 case Keys.Left:
968                                 case Keys.Escape:
969                                         this.Dismiss (ToolStripDropDownCloseReason.Keyboard);
970                                         
971                                         // ContextMenuStrip won't have a parent
972                                         if (this.OwnerItem == null)
973                                                 return true;
974                                                 
975                                         ToolStrip parent_strip = this.OwnerItem.Parent;
976                                         ToolStripManager.SetActiveToolStrip (parent_strip, true);
977                                         
978                                         if (parent_strip is MenuStrip && keyData == Keys.Left) {
979                                                 parent_strip.SelectNextToolStripItem (this.TopLevelOwnerItem, false);
980                                                 this.TopLevelOwnerItem.Invalidate ();
981                                         } else if (parent_strip is MenuStrip && keyData == Keys.Escape) {
982                                                 (parent_strip as MenuStrip).MenuDroppedDown = false;
983                                                 this.TopLevelOwnerItem.Select ();
984                                         }                               
985                                         return true;
986                         }
987                         
988                         return false;
989                 }
990
991                 internal override ToolStripItem SelectNextToolStripItem (ToolStripItem start, bool forward)
992                 {
993                         ToolStripItem next_item = this.GetNextItem (start, forward ? ArrowDirection.Down : ArrowDirection.Up);
994
995                         if (next_item != null)
996                                 this.ChangeSelection (next_item);
997                                 
998                         return (next_item);
999                 }
1000                 
1001                 private void ToolStripMenuTracker_AppFocusChange (object sender, EventArgs e)
1002                 {
1003                         this.GetTopLevelToolStrip ().Dismiss (ToolStripDropDownCloseReason.AppFocusChange);
1004                 }
1005
1006                 private void ToolStripMenuTracker_AppClicked (object sender, EventArgs e)
1007                 {
1008                         this.GetTopLevelToolStrip ().Dismiss (ToolStripDropDownCloseReason.AppClicked);
1009                 }
1010                 #endregion
1011
1012                 #region Internal Properties
1013                 internal override bool ActivateOnShow { get { return false; } }
1014                 
1015                 internal ToolStripItem TopLevelOwnerItem {
1016                         get {
1017                                 ToolStripItem owner_item = this.OwnerItem;
1018                                 ToolStrip ts = null;
1019
1020                                 while (owner_item != null) {
1021                                         ts = owner_item.Owner;
1022
1023                                         if (ts != null && (ts is ToolStripDropDown))
1024                                                 owner_item = (ts as ToolStripDropDown).OwnerItem;
1025                                         else
1026                                                 return owner_item;
1027                                 }
1028
1029                                 return null;
1030                         }
1031                 }
1032                 #endregion
1033
1034                 #region ToolStripDropDownAccessibleObject
1035                 [ComVisible (true)]
1036                 public class ToolStripDropDownAccessibleObject : ToolStripAccessibleObject
1037                 {
1038                         #region Public Constructor
1039                         public ToolStripDropDownAccessibleObject (ToolStripDropDown owner) : base (owner)
1040                         {
1041                         }
1042                         #endregion
1043                         
1044                         #region Public Properties
1045                         public override string Name {
1046                                 get { return base.Name; }
1047                                 set { base.Name = value; }
1048                         }
1049
1050                         public override AccessibleRole Role {
1051                                 get { return AccessibleRole.MenuPopup; }
1052                         }
1053                         #endregion
1054                 }
1055                 #endregion
1056         }
1057 }