1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2005 Novell, Inc.
23 // Jordi Mas i Hernandez, jordi@ximian.com
27 // - ShortCut navigation
31 using System.Collections;
32 using System.ComponentModel;
33 using System.ComponentModel.Design;
34 using System.Reflection;
35 using System.Runtime.InteropServices;
37 namespace System.Windows.Forms
39 [Designer ("Microsoft.VisualStudio.Windows.Forms.MenuDesigner, Microsoft.VisualStudio, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", (string)null)]
40 [ToolboxItemFilter("System.Windows.Forms", ToolboxItemFilterType.Allow)]
42 public abstract class Menu : Component
44 internal MenuItemCollection menu_items;
45 internal IntPtr menu_handle = IntPtr.Zero;
46 internal bool is_dirty = true;
47 internal bool creating = false;
48 internal Menu parent_menu = null;
50 public const int FindHandle = 0;
51 public const int FindShortcut = 1;
53 protected Menu (MenuItem[] items)
55 menu_items = new MenuItemCollection (this);
58 menu_items.AddRange (items);
62 #region Public Properties
63 [BrowsableAttribute(false)]
64 [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
65 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
66 public IntPtr Handle {
68 if (IsDirty && creating == false) {
72 if (menu_handle == IntPtr.Zero) {
73 menu_handle = CreateMenuHandle ();
82 [BrowsableAttribute(false)]
83 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
84 public virtual bool IsParent {
86 if (menu_items != null && menu_items.Count > 0)
93 [BrowsableAttribute(false)]
94 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
95 public MenuItem MdiListItem {
97 throw new NotImplementedException ();
101 [BrowsableAttribute(false)]
102 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Content)]
103 [MergableProperty(false)]
104 public MenuItemCollection MenuItems {
105 get { return menu_items; }
108 #endregion Public Properties
110 #region Private Properties
112 internal bool IsDirty {
113 get { return is_dirty; }
114 set { is_dirty = value; }
117 #endregion Private Properties
119 #region Public Methods
121 protected void CloneMenu (Menu menuSrc)
125 menu_items = new MenuItemCollection (this);
127 for (int i = 0; i < menuSrc.MenuItems.Count ; i++)
128 menu_items.Add (menuSrc.MenuItems [i]);
131 protected virtual IntPtr CreateMenuHandle ()
135 menu = MenuAPI.CreatePopupMenu (this);
139 protected override void Dispose (bool disposing)
142 if (menu_handle != IntPtr.Zero)
143 MenuAPI.DestroyMenu (menu_handle);
144 menu_handle = IntPtr.Zero;
148 // From Microsoft documentation is impossible to guess that
149 // this method is supossed to do
150 public MenuItem FindMenuItem (int type, IntPtr value)
155 protected int FindMergePosition (int mergeOrder)
157 int cnt = MenuItems.Count, cur, pos;
159 for (pos = 0; pos < cnt; ) {
160 cur = (pos + cnt) /2;
161 if (MenuItems[cur].MergeOrder > mergeOrder) {
171 public ContextMenu GetContextMenu ()
173 for (Menu item = this; item != null; item = item.parent_menu) {
174 if (item is ContextMenu) {
175 return (ContextMenu) item;
182 public MainMenu GetMainMenu ()
184 for (Menu item = this; item != null; item = item.parent_menu) {
185 if (item is MainMenu) {
186 return (MainMenu) item;
193 public virtual void MergeMenu (Menu menuSrc)
196 throw new ArgumentException ("The menu cannot be merged with itself");
198 for (int i = 0; i < menuSrc.MenuItems.Count; i++){
200 switch (menuSrc.MenuItems[i].MergeType) {
201 case MenuMerge.Remove: // Item not included
206 int pos = FindMergePosition (menuSrc.MenuItems[i].MergeOrder);
207 MenuItems.Add (pos, menuSrc.MenuItems[i].CloneMenu ());
211 case MenuMerge.Replace:
212 case MenuMerge.MergeItems:
214 int pos = FindMergePosition (menuSrc.MenuItems[i].MergeOrder - 1);
215 MenuItems.Add (pos, menuSrc.MenuItems[i].CloneMenu ());
226 protected internal virtual bool ProcessCmdKey (ref Message msg, Keys keyData)
231 public override string ToString ()
233 return base.ToString () + ", Items.Count: " + MenuItems.Count;
236 #endregion Public Methods
238 #region Private Methods
240 internal void CreateItems ()
244 for (int i = 0; i < menu_items.Count; i++)
245 menu_items[i].Create ();
250 #endregion Private Methods
252 [ListBindable(false)]
253 public class MenuItemCollection : IList, ICollection, IEnumerable
256 private ArrayList items = new ArrayList ();
258 public MenuItemCollection (Menu owner)
263 #region Public Properties
265 public virtual int Count {
266 get { return items.Count;}
269 public virtual bool IsReadOnly {
273 bool ICollection.IsSynchronized {
277 object ICollection.SyncRoot {
281 bool IList.IsFixedSize {
285 public MenuItem this [int index] {
287 if (index < 0 || index >= Count)
288 throw new ArgumentOutOfRangeException ("Index of out range");
290 return (MenuItem) items[index];
294 object IList.this[int index] {
295 get { return items[index]; }
296 set { throw new NotSupportedException (); }
299 #endregion Public Properties
301 #region Public Methods
303 public virtual int Add (MenuItem mi)
305 mi.parent_menu = owner;
306 mi.Index = items.Count;
309 owner.IsDirty = true;
310 return items.Count - 1;
313 public virtual MenuItem Add (string s)
315 MenuItem item = new MenuItem (s);
320 public virtual int Add (int index, MenuItem mi)
322 if (index < 0 || index > Count)
323 throw new ArgumentOutOfRangeException ("Index of out range");
325 ArrayList new_items = new ArrayList (Count + 1);
327 for (int i = 0; i < index; i++)
328 new_items.Add (items[i]);
332 for (int i = index; i < Count; i++)
333 new_items.Add (items[i]);
336 UpdateItemsIndices ();
337 owner.IsDirty = true;
342 public virtual MenuItem Add (string s, EventHandler e)
344 MenuItem item = new MenuItem (s, e);
350 public virtual MenuItem Add (string s, MenuItem[] items)
352 MenuItem item = new MenuItem (s, items);
358 public virtual void AddRange (MenuItem[] items)
361 throw new ArgumentNullException ("items");
363 foreach (MenuItem mi in items)
367 public virtual void Clear ()
370 owner.IsDirty = true;
373 public bool Contains (MenuItem value)
375 return items.Contains (value);
378 public virtual void CopyTo (Array dest, int index)
380 items.CopyTo (dest, index);
383 public virtual IEnumerator GetEnumerator ()
385 return items.GetEnumerator ();
388 int IList.Add (object value)
390 return Add ((MenuItem)value);
393 bool IList.Contains (object value)
395 return Contains ((MenuItem)value);
398 int IList.IndexOf (object value)
400 return IndexOf ((MenuItem)value);
403 void IList.Insert (int index, object value)
405 Add (index, (MenuItem) value);
408 void IList.Remove (object value)
410 Remove ((MenuItem) value);
413 public int IndexOf (MenuItem value)
415 return items.IndexOf (value);
418 public virtual void Remove (MenuItem item)
420 RemoveAt (item.Index);
423 public virtual void RemoveAt (int index)
425 if (index < 0 || index >= Count)
426 throw new ArgumentOutOfRangeException ("Index of out range");
428 items.RemoveAt (index);
430 UpdateItemsIndices ();
431 owner.IsDirty = true;
434 #endregion Public Methods
436 #region Private Methods
438 private void UpdateItemsIndices ()
440 for (int i = 0; i < Count; i++) // Recalculate indeces
441 ((MenuItem)items[i]).Index = i;
444 #endregion Private Methods