New tests.
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ToolStripDropDownItem.cs
1 //
2 // ToolStripDropDownItem.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 using System.Threading;
34
35 namespace System.Windows.Forms
36 {
37         [DefaultProperty ("DropDownItems")]
38         [Designer ("System.Windows.Forms.Design.ToolStripMenuItemDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
39         public abstract class ToolStripDropDownItem : ToolStripItem
40         {
41                 internal ToolStripDropDown drop_down;
42                 private ToolStripDropDownDirection drop_down_direction;
43
44                 #region Protected Constructors
45                 protected ToolStripDropDownItem () : this (string.Empty, null, null, string.Empty)
46                 {
47                 }
48
49                 protected ToolStripDropDownItem (string text, Image image, EventHandler onClick)
50                         : this (text, image, onClick, string.Empty)
51                 {
52                 }
53
54                 protected ToolStripDropDownItem (string text, Image image, params ToolStripItem[] dropDownItems)
55                         : this (text, image, null, string.Empty)
56                 {
57                 }
58
59                 protected ToolStripDropDownItem (string text, Image image, EventHandler onClick, string name)
60                         : base (text, image, onClick, name)
61                 {
62                 }
63                 #endregion
64
65                 #region Public Properties
66                 [TypeConverter (typeof (ReferenceConverter))]
67                 public ToolStripDropDown DropDown {
68                         get {
69                                 if (this.drop_down == null) {
70                                         this.drop_down = CreateDefaultDropDown ();
71                                         this.drop_down.ItemAdded += new ToolStripItemEventHandler (DropDown_ItemAdded);
72                                 }
73                         
74                                 return this.drop_down;
75                         }
76                         set { 
77                                 this.drop_down = value;
78                                 this.drop_down.OwnerItem = this;
79                         }
80                 }
81
82                 [Browsable (false)]
83                 public ToolStripDropDownDirection DropDownDirection {
84                         get { return this.drop_down_direction; }
85                         set {
86                                 if (!Enum.IsDefined (typeof (ToolStripDropDownDirection), value))
87                                         throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripDropDownDirection", value));
88
89                                 this.drop_down_direction = value;
90                         }
91                 }
92
93                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
94                 public ToolStripItemCollection DropDownItems {
95                         get { return this.DropDown.Items; }
96                 }
97
98                 [Browsable (false)]
99                 public virtual bool HasDropDownItems {
100                         get { return this.drop_down != null && this.DropDown.Items.Count != 0; }
101                 }
102
103                 [Browsable (false)]
104                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
105                 public override bool Pressed {
106                         get { return base.Pressed || (this.drop_down != null && this.DropDown.Visible); }
107                 }
108                 #endregion
109
110                 #region Protected Properties
111                 protected internal virtual Point DropDownLocation {
112                         get {
113                                 Point p;
114
115                                 if (this.IsOnDropDown) {
116                                         p = Parent.PointToScreen (new Point (this.Bounds.Left, this.Bounds.Top - 1));
117                                         p.X += this.Bounds.Width;
118                                         p.Y += this.Bounds.Left;
119                                         return p;
120                                 }
121                                 else
122                                         p = new Point (this.Bounds.Left, this.Bounds.Bottom - 1);
123
124                                 return Parent.PointToScreen (p);
125                         }
126                 }
127                 #endregion
128
129                 #region Public Methods
130                 public void HideDropDown ()
131                 {
132                         if (this.drop_down == null || !this.DropDown.Visible)
133                                 return;
134
135                         // OnDropDownHide is called before actually closing DropDown
136                         this.OnDropDownHide (EventArgs.Empty);
137                         this.DropDown.Close (ToolStripDropDownCloseReason.CloseCalled);
138                         this.is_pressed = false;
139                         this.Invalidate ();
140                 }
141
142                 public void ShowDropDown ()
143                 {
144                         // Don't go through this whole deal if
145                         // the DropDown is already visible
146                         if (this.DropDown.Visible)
147                                 return;
148                                 
149                         // Call this before the HasDropDownItems check to give
150                         // users a chance to handle it and add drop down items
151                         this.OnDropDownShow (EventArgs.Empty);
152                         
153                         if (!this.HasDropDownItems)
154                                 return;
155                         
156                         this.Invalidate ();
157                         this.DropDown.Show (this.DropDownLocation);
158                 }
159                 #endregion
160
161                 #region Protected Methods
162                 protected override AccessibleObject CreateAccessibilityInstance ()
163                 {
164                         return new ToolStripDropDownItemAccessibleObject (this);
165                 }
166                 
167                 protected virtual ToolStripDropDown CreateDefaultDropDown ()
168                 {
169                         ToolStripDropDown tsdd = new ToolStripDropDown ();
170                         tsdd.OwnerItem = this;
171                         return tsdd;
172                 }
173
174                 protected override void Dispose (bool disposing)
175                 {
176                         if (!IsDisposed) {
177                                 if (this.HasDropDownItems)
178                                         foreach (ToolStripItem tsi in this.DropDownItems)
179                                                 if (tsi is ToolStripMenuItem)
180                                                         ToolStripManager.RemoveToolStripMenuItem ((ToolStripMenuItem)tsi);
181                                         
182                                 if (drop_down != null)
183                                         ToolStripManager.RemoveToolStrip (drop_down);
184                                 
185                                 base.Dispose (disposing);
186                         }
187                 }
188
189                 protected override void OnBoundsChanged ()
190                 {
191                         base.OnBoundsChanged ();
192                 }
193
194                 protected internal virtual void OnDropDownClosed (EventArgs e)
195                 {
196                         EventHandler eh = (EventHandler)(Events [DropDownClosedEvent]);
197                         if (eh != null)
198                                 eh (this, e);
199                 }
200
201                 protected virtual void OnDropDownHide (EventArgs e)
202                 {
203                 }
204
205                 protected internal virtual void OnDropDownItemClicked (ToolStripItemClickedEventArgs e)
206                 {
207                         ToolStripItemClickedEventHandler eh = (ToolStripItemClickedEventHandler)(Events [DropDownItemClickedEvent]);
208                         if (eh != null)
209                                 eh (this, e);
210                 }
211
212                 protected internal virtual void OnDropDownOpened (EventArgs e)
213                 {
214                         EventHandler eh = (EventHandler)(Events [DropDownOpenedEvent]);
215                         if (eh != null)
216                                 eh (this, e);
217                 }
218
219                 protected virtual void OnDropDownShow (EventArgs e)
220                 {
221                         EventHandler eh = (EventHandler)(Events[DropDownOpeningEvent]);
222                         if (eh != null)
223                                 eh (this, e);
224                 }
225
226                 protected override void OnFontChanged (EventArgs e)
227                 {
228                         base.OnFontChanged (e);
229
230                         // don't use DropDown directly, since doing that
231                         // would created the DropDown control
232                         if (drop_down != null)
233                                 drop_down.Font = Font;
234                 }
235
236                 protected override void OnRightToLeftChanged (EventArgs e)
237                 {
238                         base.OnRightToLeftChanged (e);
239                 }
240                 
241                 protected internal override bool ProcessCmdKey (ref Message m, Keys keyData)
242                 {
243                         if (this.HasDropDownItems)
244                                 foreach (ToolStripItem tsi in this.DropDownItems)
245                                         if (tsi.ProcessCmdKey (ref m, keyData) == true)
246                                                 return true;
247
248                         return base.ProcessCmdKey (ref m, keyData);
249                 }
250
251                 protected internal override bool ProcessDialogKey (Keys keyData)
252                 {
253                         if (!this.Selected || !this.HasDropDownItems)
254                                 return base.ProcessDialogKey (keyData);
255                                 
256                         if (!this.IsOnDropDown) {
257                                 if (this.Parent.Orientation == Orientation.Horizontal) {
258                                         if (keyData == Keys.Down || keyData == Keys.Enter) {
259                                                 if (this.Parent is MenuStrip)
260                                                         (this.Parent as MenuStrip).MenuDroppedDown = true;
261                                                 this.ShowDropDown ();
262                                                 this.DropDown.SelectNextToolStripItem (null, true);
263                                                 return true;
264                                         }
265                                 } else {
266                                         if (keyData == Keys.Right || keyData == Keys.Enter) {
267                                                 if (this.Parent is MenuStrip)
268                                                         (this.Parent as MenuStrip).MenuDroppedDown = true;
269                                                 this.ShowDropDown ();
270                                                 this.DropDown.SelectNextToolStripItem (null, true);
271                                                 return true;
272                                         }
273                                 }
274                         } else {
275                                 if (keyData == Keys.Right || keyData == Keys.Enter) {
276                                         if (this.HasDropDownItems) {
277                                                 this.ShowDropDown ();
278                                                 this.DropDown.SelectNextToolStripItem (null, true);
279                                                 return true;
280                                         }
281                                 }
282                         }
283                         
284                         
285                         return base.ProcessDialogKey (keyData);
286                 }
287                 #endregion
288
289                 #region Public Events
290                 static object DropDownClosedEvent = new object ();
291                 static object DropDownItemClickedEvent = new object ();
292                 static object DropDownOpenedEvent = new object ();
293                 static object DropDownOpeningEvent = new object ();
294
295                 public event EventHandler DropDownClosed {
296                         add { Events.AddHandler (DropDownClosedEvent, value); }
297                         remove { Events.RemoveHandler (DropDownClosedEvent, value); }
298                 }
299
300                 public event ToolStripItemClickedEventHandler DropDownItemClicked {
301                         add { Events.AddHandler (DropDownItemClickedEvent, value); }
302                         remove { Events.RemoveHandler (DropDownItemClickedEvent, value); }
303                 }
304
305                 public event EventHandler DropDownOpened {
306                         add { Events.AddHandler (DropDownOpenedEvent, value); }
307                         remove { Events.RemoveHandler (DropDownOpenedEvent, value); }
308                 }
309
310                 public event EventHandler DropDownOpening {
311                         add { Events.AddHandler (DropDownOpeningEvent, value); }
312                         remove { Events.RemoveHandler (DropDownOpeningEvent, value); }
313                 }
314                 #endregion
315
316                 #region Internal Methods
317                 internal override void Dismiss (ToolStripDropDownCloseReason reason)
318                 {
319                         if (this.HasDropDownItems && this.DropDown.Visible)
320                                 this.DropDown.Dismiss (reason);
321                                 
322                         base.Dismiss (reason);
323                 }
324
325                 internal override void HandleClick (int mouse_clicks, EventArgs e)
326                 {
327                         OnClick (e);
328                 }
329                 
330                 internal void HideDropDown (ToolStripDropDownCloseReason reason)
331                 {
332                         if (this.drop_down == null || !this.DropDown.Visible)
333                                 return;
334
335                         // OnDropDownHide is called before actually closing DropDown
336                         this.OnDropDownHide (EventArgs.Empty);
337                         this.DropDown.Close (reason);
338                         this.is_pressed = false;
339                         this.Invalidate ();
340                 }
341                 
342                 private void DropDown_ItemAdded (object sender, ToolStripItemEventArgs e)
343                 {
344                         e.Item.owner_item = this;
345                 }
346                 #endregion
347         }
348 }
349 #endif