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:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
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.
19 //
20 // Copyright (c) 2004-2005 Novell, Inc.
21 //
22 // Authors:
23 //	Jordi Mas i Hernandez, jordi@ximian.com
24 //
25 //
26 
27 // NOT COMPLETE
28 
29 using System.Collections;
30 using System.ComponentModel;
31 using System.ComponentModel.Design;
32 using System.Drawing;
33 using System.Drawing.Text;
34 
35 namespace System.Windows.Forms
36 {
37 	[DefaultProperty("Text")]
38 	[DefaultEvent("Click")]
39 	[DesignTimeVisible(false)]
40 	[ToolboxItem(false)]
41 	public class MenuItem : Menu
42 	{
43 		internal bool separator;
44 		internal bool break_;
45 		internal bool bar_break;
46 		private Shortcut shortcut;
47 		private	string text;
48 		private bool checked_;
49 		private bool radiocheck;
50 		private bool enabled;
51 		private char mnemonic;
52 		private bool showshortcut;
53 		private int index;
54 		private bool mdilist;
55 		private Hashtable mdilist_items;
56 		private Hashtable mdilist_forms;
57 		private MdiClient mdicontainer;
58 		private bool is_window_menu_item;
59 		private bool defaut_item;
60 		private bool visible;
61 		private bool ownerdraw;
62 		private int menuid;
63 		private int mergeorder;
64 		private int xtab;
65 		private int menuheight;
66 		private bool menubar;
67 		private MenuMerge mergetype;
68 		// UIA Framework Note: Used to obtain item bounds
69 		internal Rectangle bounds;
70 
MenuItem()71 		public MenuItem (): base (null)
72 		{
73 			CommonConstructor (string.Empty);
74 			shortcut = Shortcut.None;
75 		}
76 
MenuItem(string text)77 		public MenuItem (string text) : base (null)
78 		{
79 			CommonConstructor (text);
80 			shortcut = Shortcut.None;
81 		}
82 
MenuItem(string text, EventHandler onClick)83 		public MenuItem (string text, EventHandler onClick) : base (null)
84 		{
85 			CommonConstructor (text);
86 			shortcut = Shortcut.None;
87 			Click += onClick;
88 		}
89 
MenuItem(string text, MenuItem[] items)90 		public MenuItem (string text, MenuItem[] items) : base (items)
91 		{
92 			CommonConstructor (text);
93 			shortcut = Shortcut.None;
94 		}
95 
MenuItem(string text, EventHandler onClick, Shortcut shortcut)96 		public MenuItem (string text, EventHandler onClick, Shortcut shortcut) : base (null)
97 		{
98 			CommonConstructor (text);
99 			Click += onClick;
100 			this.shortcut = shortcut;
101 		}
102 
MenuItem(MenuMerge mergeType, int mergeOrder, Shortcut shortcut, string text, EventHandler onClick, EventHandler onPopup, EventHandler onSelect, MenuItem[] items)103 		public MenuItem (MenuMerge mergeType, int mergeOrder, Shortcut shortcut, string text,
104 			EventHandler onClick, EventHandler onPopup,  EventHandler onSelect,  MenuItem[] items)
105 			: base (items)
106 		{
107 			CommonConstructor (text);
108 			this.shortcut = shortcut;
109 			mergeorder = mergeOrder;
110 			mergetype = mergeType;
111 
112 			Click += onClick;
113 			Popup += onPopup;
114 			Select += onSelect;
115 		}
116 
CommonConstructor(string text)117 		private void CommonConstructor (string text)
118 		{
119 			defaut_item = false;
120 			separator = false;
121 			break_ = false;
122 			bar_break = false;
123 			checked_ = false;
124 			radiocheck = false;
125 			enabled = true;
126 			showshortcut = true;
127 			visible = true;
128 			ownerdraw = false;
129 			menubar = false;
130 			menuheight = 0;
131 			xtab = 0;
132 			index = -1;
133 			mnemonic = '\0';
134 			menuid = -1;
135 			mergeorder = 0;
136 			mergetype = MenuMerge.Add;
137 			Text = text;	// Text can change separator status
138 		}
139 
140 		#region Events
141 		static object ClickEvent = new object ();
142 		static object DrawItemEvent = new object ();
143 		static object MeasureItemEvent = new object ();
144 		static object PopupEvent = new object ();
145 		static object SelectEvent = new object ();
146 
147 		public event EventHandler Click {
148 			add { Events.AddHandler (ClickEvent, value); }
149 			remove { Events.RemoveHandler (ClickEvent, value); }
150 		}
151 
152 		public event DrawItemEventHandler DrawItem {
153 			add { Events.AddHandler (DrawItemEvent, value); }
154 			remove { Events.RemoveHandler (DrawItemEvent, value); }
155 		}
156 
157 		public event MeasureItemEventHandler MeasureItem {
158 			add { Events.AddHandler (MeasureItemEvent, value); }
159 			remove { Events.RemoveHandler (MeasureItemEvent, value); }
160 		}
161 
162 		public event EventHandler Popup {
163 			add { Events.AddHandler (PopupEvent, value); }
164 			remove { Events.RemoveHandler (PopupEvent, value); }
165 		}
166 
167 		public event EventHandler Select {
168 			add { Events.AddHandler (SelectEvent, value); }
169 			remove { Events.RemoveHandler (SelectEvent, value); }
170 		}
171 
172 		#region UIA Framework Events
173 
174 		static object UIACheckedChangedEvent = new object ();
175 
176 		internal event EventHandler UIACheckedChanged {
177 			add { Events.AddHandler (UIACheckedChangedEvent, value); }
178 			remove { Events.RemoveHandler (UIACheckedChangedEvent, value); }
179 		}
180 
OnUIACheckedChanged(EventArgs e)181 		internal void OnUIACheckedChanged (EventArgs e)
182 		{
183 			EventHandler eh = (EventHandler) Events [UIACheckedChangedEvent];
184 			if (eh != null)
185 				eh (this, e);
186 		}
187 
188 		static object UIARadioCheckChangedEvent = new object ();
189 
190 		internal event EventHandler UIARadioCheckChanged {
191 			add { Events.AddHandler (UIARadioCheckChangedEvent, value); }
192 			remove { Events.RemoveHandler (UIARadioCheckChangedEvent, value); }
193 		}
194 
OnUIARadioCheckChanged(EventArgs e)195 		internal void OnUIARadioCheckChanged (EventArgs e)
196 		{
197 			EventHandler eh = (EventHandler) Events [UIARadioCheckChangedEvent];
198 			if (eh != null)
199 				eh (this, e);
200 		}
201 
202 		static object UIAEnabledChangedEvent = new object ();
203 
204 		internal event EventHandler UIAEnabledChanged {
205 			add { Events.AddHandler (UIAEnabledChangedEvent, value); }
206 			remove { Events.RemoveHandler (UIAEnabledChangedEvent, value); }
207 		}
208 
OnUIAEnabledChanged(EventArgs e)209 		internal void OnUIAEnabledChanged (EventArgs e)
210 		{
211 			EventHandler eh = (EventHandler) Events [UIAEnabledChangedEvent];
212 			if (eh != null)
213 				eh (this, e);
214 		}
215 
216 		static object UIATextChangedEvent = new object ();
217 
218 		internal event EventHandler UIATextChanged {
219 			add { Events.AddHandler (UIATextChangedEvent, value); }
220 			remove { Events.RemoveHandler (UIATextChangedEvent, value); }
221 		}
222 
OnUIATextChanged(EventArgs e)223 		internal void OnUIATextChanged (EventArgs e)
224 		{
225 			EventHandler eh = (EventHandler) Events [UIATextChangedEvent];
226 			if (eh != null)
227 				eh (this, e);
228 		}
229 
230 		#endregion
231 		#endregion // Events
232 
233 		#region Public Properties
234 
235 		[Browsable(false)]
236 		[DefaultValue(false)]
237 		public bool BarBreak {
238 			get { return break_; }
239 			set { break_ = value; }
240 		}
241 
242 		[Browsable(false)]
243 		[DefaultValue(false)]
244 		public bool Break {
245 			get { return bar_break; }
246 			set { bar_break = value; }
247 		}
248 
249 		[DefaultValue(false)]
250 		public bool Checked {
251 			get { return checked_; }
252 			set {
253 				if (checked_ == value)
254 					return;
255 
256 				checked_ = value;
257 
258 				// UIA Framework Event: Checked Changed
259 				OnUIACheckedChanged (EventArgs.Empty);
260 			}
261 		}
262 
263 		[DefaultValue(false)]
264 		public bool DefaultItem {
265 			get { return defaut_item; }
266 			set { defaut_item = value; }
267 		}
268 
269 		[DefaultValue(true)]
270 		[Localizable(true)]
271 		public bool Enabled {
272 			get { return enabled; }
273 			set {
274 				if (enabled == value)
275 					return;
276 
277 				enabled = value;
278 
279 				// UIA Framework Event: Enabled Changed
280 				OnUIAEnabledChanged (EventArgs.Empty);
281 
282 				Invalidate ();
283 			}
284 		}
285 
286 		[Browsable(false)]
287 		public int Index {
288 			get { return index; }
289 			set {
290 				if (Parent != null && Parent.MenuItems != null && (value < 0 || value >= Parent.MenuItems.Count))
291 					throw new ArgumentException ("'" + value + "' is not a valid value for 'value'");
292 				index = value;
293 			}
294 		}
295 
296 		[Browsable(false)]
297 		public override bool IsParent {
298 			get { return IsPopup; }
299 		}
300 
301 		[DefaultValue(false)]
302 		public bool MdiList {
303 			get { return mdilist; }
304 			set {
305 				if (mdilist == value)
306 					return;
307 				mdilist = value;
308 
309 				if (mdilist || mdilist_items == null)
310 					return;
311 
312 				foreach (MenuItem item in mdilist_items.Keys)
313 					MenuItems.Remove (item);
314 				mdilist_items.Clear ();
315 				mdilist_items = null;
316 			}
317 		}
318 
319 		protected int MenuID {
320 			get { return menuid; }
321 		}
322 
323 		[DefaultValue(0)]
324 		public int MergeOrder {
325 			get { return mergeorder; }
326 			set { mergeorder = value; }
327 		}
328 
329 		[DefaultValue(MenuMerge.Add)]
330 		public MenuMerge MergeType {
331 			get { return mergetype;	}
332 			set {
333 				if (!Enum.IsDefined (typeof (MenuMerge), value))
334 					throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for MenuMerge", value));
335 
336 				mergetype = value;
337 			}
338 		}
339 
340 		[Browsable(false)]
341 		public char Mnemonic {
342 			get { return mnemonic; }
343 		}
344 
345 		[DefaultValue(false)]
346 		public bool OwnerDraw {
347 			get { return ownerdraw; }
348 			set { ownerdraw = value; }
349 		}
350 
351 		[Browsable(false)]
352 		public Menu Parent {
353 			get { return parent_menu;}
354 		}
355 
356 		[DefaultValue(false)]
357 		public bool RadioCheck {
358 			get { return radiocheck; }
359 			set {
360 				if (radiocheck == value)
361 					return;
362 
363 				radiocheck = value;
364 
365 				// UIA Framework Event: Checked Changed
366 				OnUIARadioCheckChanged (EventArgs.Empty);
367 			}
368 		}
369 
370 		[DefaultValue(Shortcut.None)]
371 		[Localizable(true)]
372 		public Shortcut Shortcut {
373 			get { return shortcut;}
374 			set {
375 				if (!Enum.IsDefined (typeof (Shortcut), value))
376 					throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for Shortcut", value));
377 
378 				shortcut = value;
379 				UpdateMenuItem ();
380 			}
381 		}
382 
383 		[DefaultValue(true)]
384 		[Localizable(true)]
385 		public bool ShowShortcut {
386 			get { return showshortcut;}
387 			set { showshortcut = value; }
388 		}
389 
390 		[Localizable(true)]
391 		public string Text {
392 			get { return text; }
393 			set {
394 				text = value;
395 
396 				if (text == "-")
397 					separator = true;
398 				else
399 					separator = false;
400 
401 				// UIA Framework Event: Text Changed
402 				OnUIATextChanged (EventArgs.Empty);
403 
404 				ProcessMnemonic ();
405 				Invalidate ();
406 			}
407 		}
408 
409 		[DefaultValue(true)]
410 		[Localizable(true)]
411 		public bool Visible {
412 			get { return visible;}
413 			set {
414 				if (value == visible)
415 					return;
416 
417 				visible = value;
418 
419 				if (menu_items != null) {
420 					foreach (MenuItem mi in menu_items)
421 						mi.Visible = value;
422 				}
423 
424 				if (parent_menu != null)
425 					parent_menu.OnMenuChanged (EventArgs.Empty);
426 			}
427 		}
428 
429 		#endregion Public Properties
430 
431 		#region Private Properties
432 
433 		internal new int Height {
434 			get { return bounds.Height; }
435 			set { bounds.Height = value; }
436 		}
437 
438 		internal bool IsPopup {
439 			get {
440 				if (menu_items.Count > 0)
441 					return true;
442 				else
443 					return false;
444 			}
445 		}
446 
447 		internal bool MeasureEventDefined {
448 			get {
449 				if (ownerdraw == true && Events [MeasureItemEvent] != null) {
450 					return true;
451 				} else {
452 					return false;
453 				}
454 			}
455 		}
456 
457 		internal bool MenuBar {
458 			get { return menubar; }
459 			set { menubar = value; }
460 		}
461 
462 		internal int MenuHeight {
463 			get { return menuheight; }
464 			set { menuheight = value; }
465 		}
466 
467 		bool selected;
468 		internal bool Selected {
469 			get { return selected; }
470 			set { selected = value; }
471 		}
472 
473 		internal bool Separator {
474 			get { return separator; }
475 			set { separator = value; }
476 		}
477 
478 		internal DrawItemState Status {
479 			get {
480 				DrawItemState status = DrawItemState.None;
481 				MenuTracker tracker = Parent.Tracker;
482 				if (Selected)
483 					status |= (tracker.active || tracker.Navigating ? DrawItemState.Selected : DrawItemState.HotLight);
484 				if (!Enabled)
485 					status |= DrawItemState.Grayed | DrawItemState.Disabled;
486 				if (Checked)
487 					status |= DrawItemState.Checked;
488 				if (!tracker.Navigating)
489 					status |= DrawItemState.NoAccelerator;
490 				return status;
491 			}
492 		}
493 
494 		internal bool VisibleItems {
495 			get {
496 				if (menu_items != null) {
497 					foreach (MenuItem mi in menu_items)
498 						if (mi.Visible)
499 							return true;
500 				}
501 				return false;
502 			}
503 		}
504 
505 		internal new int Width {
506 			get { return bounds.Width; }
507 			set { bounds.Width = value; }
508 		}
509 
510 		internal new int X {
511 			get { return bounds.X; }
512 			set { bounds.X = value; }
513 		}
514 
515 		internal int XTab {
516 			get { return xtab; }
517 			set { xtab = value; }
518 		}
519 
520 		internal new int Y {
521 			get { return bounds.Y; }
522 			set { bounds.Y = value; }
523 		}
524 
525 		#endregion Private Properties
526 
527 		#region Public Methods
528 
CloneMenu()529 		public virtual MenuItem CloneMenu ()
530 		{
531 			MenuItem item = new MenuItem ();
532 			item.CloneMenu (this);
533 			return item;
534 		}
535 
CloneMenu(MenuItem itemSrc)536 		protected void CloneMenu (MenuItem itemSrc)
537 		{
538 			base.CloneMenu (itemSrc); // Copy subitems
539 
540 			// Window list
541 			MdiList = itemSrc.MdiList;
542 			is_window_menu_item = itemSrc.is_window_menu_item;
543 			// Remove items corresponding to window menu items, and add new items
544 			// (Otherwise window menu items would show up twice, since the PopulateWindowMenu doesn't
545 			// now them)
546 			bool populated = false;
547 			for (int i = MenuItems.Count - 1; i >= 0; i--) {
548 				if (MenuItems [i].is_window_menu_item) {
549 					MenuItems.RemoveAt (i);
550 					populated = true;
551 				}
552 			}
553 			if (populated)
554 				PopulateWindowMenu ();
555 
556 			// Properties
557 			BarBreak = itemSrc.BarBreak;
558 			Break = itemSrc.Break;
559 			Checked = itemSrc.Checked;
560 			DefaultItem = itemSrc.DefaultItem;
561 			Enabled = itemSrc.Enabled;
562 			MergeOrder = itemSrc.MergeOrder;
563 			MergeType = itemSrc.MergeType;
564 			OwnerDraw = itemSrc.OwnerDraw;
565 			//Parent = menuitem.Parent;
566 			RadioCheck = itemSrc.RadioCheck;
567 			Shortcut = itemSrc.Shortcut;
568 			ShowShortcut = itemSrc.ShowShortcut;
569 			Text = itemSrc.Text;
570 			Visible = itemSrc.Visible;
571 			Name = itemSrc.Name;
572 			Tag = itemSrc.Tag;
573 
574 			// Events
575 			Events[ClickEvent] = itemSrc.Events[ClickEvent];
576 			Events[DrawItemEvent] = itemSrc.Events[DrawItemEvent];
577 			Events[MeasureItemEvent] = itemSrc.Events[MeasureItemEvent];
578 			Events[PopupEvent] = itemSrc.Events[PopupEvent];
579 			Events[SelectEvent] = itemSrc.Events[SelectEvent];
580 		}
581 
Dispose(bool disposing)582 		protected override void Dispose (bool disposing)
583 		{
584 			if (disposing && parent_menu != null)
585 				parent_menu.MenuItems.Remove (this);
586 
587 			base.Dispose (disposing);
588 		}
589 
590 		// This really clones the item
MergeMenu()591 		public virtual MenuItem MergeMenu ()
592 		{
593 			MenuItem item = new MenuItem ();
594 			item.CloneMenu (this);
595 			return item;
596 		}
597 
MergeMenu(MenuItem itemSrc)598 		public void MergeMenu (MenuItem itemSrc)
599 		{
600 			base.MergeMenu (itemSrc);
601 		}
602 
OnClick(EventArgs e)603 		protected virtual void OnClick (EventArgs e)
604 		{
605 			EventHandler eh = (EventHandler)(Events [ClickEvent]);
606 			if (eh != null)
607 				eh (this, e);
608 		}
609 
OnDrawItem(DrawItemEventArgs e)610 		protected virtual void OnDrawItem (DrawItemEventArgs e)
611 		{
612 			DrawItemEventHandler eh = (DrawItemEventHandler)(Events [DrawItemEvent]);
613 			if (eh != null)
614 				eh (this, e);
615 		}
616 
617 
OnInitMenuPopup(EventArgs e)618 		protected virtual void OnInitMenuPopup (EventArgs e)
619 		{
620 			OnPopup (e);
621 		}
622 
OnMeasureItem(MeasureItemEventArgs e)623 		protected virtual void OnMeasureItem (MeasureItemEventArgs e)
624 		{
625 			if (!OwnerDraw)
626 				return;
627 
628 			MeasureItemEventHandler eh = (MeasureItemEventHandler)(Events [MeasureItemEvent]);
629 			if (eh != null)
630 				eh (this, e);
631 		}
632 
OnPopup(EventArgs e)633 		protected virtual void OnPopup (EventArgs e)
634 		{
635 			EventHandler eh = (EventHandler)(Events [PopupEvent]);
636 			if (eh != null)
637 				eh (this, e);
638 		}
639 
OnSelect(EventArgs e)640 		protected virtual void OnSelect (EventArgs e)
641 		{
642 			EventHandler eh = (EventHandler)(Events [SelectEvent]);
643 			if (eh != null)
644 				eh (this, e);
645 		}
646 
PerformClick()647 		public void PerformClick ()
648 		{
649 			OnClick (EventArgs.Empty);
650 		}
651 
PerformSelect()652 		public virtual void PerformSelect ()
653 		{
654 			OnSelect (EventArgs.Empty);
655 		}
656 
ToString()657 		public override string ToString ()
658 		{
659 			return base.ToString () + ", Items.Count: " + MenuItems.Count + ", Text: " + text;
660 		}
661 
662 		#endregion Public Methods
663 
664 		#region Private Methods
665 
Invalidate()666 		internal virtual void Invalidate ()
667 		{
668 			if ((Parent == null) || !(Parent is MainMenu) || (Parent.Wnd == null))
669 				return;
670 
671 			Form form = Parent.Wnd.FindForm ();
672 			if ((form == null) || (!form.IsHandleCreated))
673 				return;
674 
675 			XplatUI.RequestNCRecalc (form.Handle);
676 		}
677 
PerformPopup()678 		internal void PerformPopup ()
679 		{
680 			OnPopup (EventArgs.Empty);
681 		}
682 
PerformDrawItem(DrawItemEventArgs e)683 		internal void PerformDrawItem (DrawItemEventArgs e)
684 		{
685 			PopulateWindowMenu ();
686 			if (OwnerDraw)
687 				OnDrawItem (e);
688 			else
689 				ThemeEngine.Current.DrawMenuItem (this, e);
690 		}
691 
PopulateWindowMenu()692 		private void PopulateWindowMenu ()
693 		{
694 			if (mdilist) {
695 				if (mdilist_items == null) {
696 					mdilist_items = new Hashtable ();
697 					mdilist_forms = new Hashtable ();
698 				}
699 
700 				do {
701 					MainMenu main = GetMainMenu ();
702 					if (main == null || main.GetForm () == null)
703 						break;
704 
705 					Form form = main.GetForm ();
706 					mdicontainer = form.MdiContainer;
707 					if (mdicontainer == null)
708 						break;
709 
710 
711 					// Remove closed forms
712 					MenuItem[] items = new MenuItem[mdilist_items.Count];
713 					mdilist_items.Keys.CopyTo (items, 0);
714 					foreach (MenuItem item in items) {
715 						Form mdichild = (Form) mdilist_items [item];
716 						if (!mdicontainer.mdi_child_list.Contains(mdichild)) {
717 							mdilist_items.Remove (item);
718 							mdilist_forms.Remove (mdichild);
719 							MenuItems.Remove (item);
720 						}
721 					}
722 
723 					// Add new forms and update state for existing forms.
724 					for (int i = 0; i < mdicontainer.mdi_child_list.Count; i++) {
725 						Form mdichild = (Form)mdicontainer.mdi_child_list[i];
726 						MenuItem item;
727 						if (mdilist_forms.Contains (mdichild)) {
728 							item = (MenuItem) mdilist_forms [mdichild];
729 						} else {
730 							item = new MenuItem ();
731 							item.is_window_menu_item = true;
732 							item.Click += new EventHandler (MdiWindowClickHandler);
733 							mdilist_items [item] = mdichild;
734 							mdilist_forms [mdichild] = item;
735 							MenuItems.AddNoEvents (item);
736 						}
737 						item.Visible = mdichild.Visible;
738 						item.Text = "&" + (i + 1).ToString () + " " + mdichild.Text;
739 						item.Checked = form.ActiveMdiChild == mdichild;
740 					}
741 				} while (false);
742 			} else {
743 				// Remove all forms
744 				if (mdilist_items != null) {
745 					foreach (MenuItem item in mdilist_items.Values) {
746 						MenuItems.Remove (item);
747 					}
748 
749 					mdilist_forms.Clear ();
750 					mdilist_items.Clear ();
751 				}
752 			}
753 		}
754 
PerformMeasureItem(MeasureItemEventArgs e)755 		internal void PerformMeasureItem (MeasureItemEventArgs e)
756 		{
757 			OnMeasureItem (e);
758 		}
759 
ProcessMnemonic()760 		private void ProcessMnemonic ()
761 		{
762 			if (text == null || text.Length < 2) {
763 				mnemonic = '\0';
764 				return;
765 			}
766 
767 			bool bPrevAmp = false;
768 			for (int i = 0; i < text.Length -1 ; i++) {
769 				if (text[i] == '&') {
770 					if (bPrevAmp == false &&  (text[i+1] != '&')) {
771 						mnemonic = Char.ToUpper (text[i+1]);
772 						return;
773 					}
774 
775 					bPrevAmp = true;
776 				}
777 				else
778 					bPrevAmp = false;
779 			}
780 
781 			mnemonic = '\0';
782 		}
783 
GetShortCutTextCtrl()784 		private string GetShortCutTextCtrl () { return "Ctrl"; }
GetShortCutTextAlt()785 		private string GetShortCutTextAlt () { return "Alt"; }
GetShortCutTextShift()786 		private string GetShortCutTextShift () { return "Shift"; }
787 
GetShortCutText()788 		internal string GetShortCutText ()
789 		{
790 			/* Ctrl+A - Ctrl+Z */
791 			if (Shortcut >= Shortcut.CtrlA && Shortcut <= Shortcut.CtrlZ)
792 				return GetShortCutTextCtrl () + "+" + (char)((int) 'A' + (int)(Shortcut - Shortcut.CtrlA));
793 
794 			/* Alt+0 - Alt+9 */
795 			if (Shortcut >= Shortcut.Alt0 && Shortcut <= Shortcut.Alt9)
796 				return GetShortCutTextAlt () + "+" + (char)((int) '0' + (int)(Shortcut - Shortcut.Alt0));
797 
798 			/* Alt+F1 - Alt+F2 */
799 			if (Shortcut >= Shortcut.AltF1 && Shortcut <= Shortcut.AltF9)
800 				return GetShortCutTextAlt () + "+F" + (char)((int) '1' + (int)(Shortcut - Shortcut.AltF1));
801 
802 			/* Ctrl+0 - Ctrl+9 */
803 			if (Shortcut >= Shortcut.Ctrl0 && Shortcut <= Shortcut.Ctrl9)
804 				return GetShortCutTextCtrl () + "+" + (char)((int) '0' + (int)(Shortcut - Shortcut.Ctrl0));
805 
806 			/* Ctrl+F0 - Ctrl+F9 */
807 			if (Shortcut >= Shortcut.CtrlF1 && Shortcut <= Shortcut.CtrlF9)
808 				return GetShortCutTextCtrl () + "+F" + (char)((int) '1' + (int)(Shortcut - Shortcut.CtrlF1));
809 
810 			/* Ctrl+Shift+0 - Ctrl+Shift+9 */
811 			if (Shortcut >= Shortcut.CtrlShift0 && Shortcut <= Shortcut.CtrlShift9)
812 				return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+" + (char)((int) '0' + (int)(Shortcut - Shortcut.CtrlShift0));
813 
814 			/* Ctrl+Shift+A - Ctrl+Shift+Z */
815 			if (Shortcut >= Shortcut.CtrlShiftA && Shortcut <= Shortcut.CtrlShiftZ)
816 				return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+" + (char)((int) 'A' + (int)(Shortcut - Shortcut.CtrlShiftA));
817 
818 			/* Ctrl+Shift+F1 - Ctrl+Shift+F9 */
819 			if (Shortcut >= Shortcut.CtrlShiftF1 && Shortcut <= Shortcut.CtrlShiftF9)
820 				return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+F" + (char)((int) '1' + (int)(Shortcut - Shortcut.CtrlShiftF1));
821 
822 			/* F1 - F9 */
823 			if (Shortcut >= Shortcut.F1 && Shortcut <= Shortcut.F9)
824 				return "F" + (char)((int) '1' + (int)(Shortcut - Shortcut.F1));
825 
826 			/* Shift+F1 - Shift+F9 */
827 			if (Shortcut >= Shortcut.ShiftF1 && Shortcut <= Shortcut.ShiftF9)
828 				return GetShortCutTextShift () + "+F" + (char)((int) '1' + (int)(Shortcut - Shortcut.ShiftF1));
829 
830 			/* Special cases */
831 			switch (Shortcut) {
832 				case Shortcut.AltBksp:
833 					return "AltBksp";
834 				case Shortcut.AltF10:
835 					return GetShortCutTextAlt () + "+F10";
836 				case Shortcut.AltF11:
837 					return GetShortCutTextAlt () + "+F11";
838 				case Shortcut.AltF12:
839 					return GetShortCutTextAlt () + "+F12";
840 				case Shortcut.CtrlDel:
841 					return GetShortCutTextCtrl () + "+Del";
842 				case Shortcut.CtrlF10:
843 					return GetShortCutTextCtrl () + "+F10";
844 				case Shortcut.CtrlF11:
845 					return GetShortCutTextCtrl () + "+F11";
846 				case Shortcut.CtrlF12:
847 					return GetShortCutTextCtrl () + "+F12";
848 				case Shortcut.CtrlIns:
849 					return GetShortCutTextCtrl () + "+Ins";
850 				case Shortcut.CtrlShiftF10:
851 					return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+F10";
852 				case Shortcut.CtrlShiftF11:
853 					return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+F11";
854 				case Shortcut.CtrlShiftF12:
855 					return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+F12";
856 				case Shortcut.Del:
857 					return "Del";
858 				case Shortcut.F10:
859 					return "F10";
860 				case Shortcut.F11:
861 					return "F11";
862 				case Shortcut.F12:
863 					return "F12";
864 				case Shortcut.Ins:
865 					return "Ins";
866 				case Shortcut.None:
867 					return "None";
868 				case Shortcut.ShiftDel:
869 					return GetShortCutTextShift () + "+Del";
870 				case Shortcut.ShiftF10:
871 					return GetShortCutTextShift () + "+F10";
872 				case Shortcut.ShiftF11:
873 					return GetShortCutTextShift () + "+F11";
874 				case Shortcut.ShiftF12:
875 					return GetShortCutTextShift () + "+F12";
876 				case Shortcut.ShiftIns:
877 					return GetShortCutTextShift () + "+Ins";
878 				default:
879 					break;
880 				}
881 
882 			return "";
883 		}
884 
MdiWindowClickHandler(object sender, EventArgs e)885 		private void MdiWindowClickHandler (object sender, EventArgs e)
886 		{
887 			Form mdichild = (Form) mdilist_items [sender];
888 
889 			// people could add weird items to the Window menu
890 			// so we can't assume its just us
891 			if (mdichild == null)
892 				return;
893 
894 			mdicontainer.ActivateChild (mdichild);
895 		}
896 
UpdateMenuItem()897 		private void UpdateMenuItem ()
898 		{
899 			if ((parent_menu == null) || (parent_menu.Tracker == null))
900 				return;
901 
902 			parent_menu.Tracker.RemoveShortcuts (this);
903 			parent_menu.Tracker.AddShortcuts (this);
904 		}
905 
906 		#endregion Private Methods
907 
908 	}
909 }
910 
911 
912