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