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
29 using System.Collections;
30 using System.ComponentModel;
31 using System.ComponentModel.Design;
33 using System.Drawing.Text;
35 namespace System.Windows.Forms
37 [DefaultProperty("Text")]
38 [DefaultEvent("Click")]
39 [DesignTimeVisible(false)]
41 public class MenuItem : Menu
43 internal bool separator;
45 internal bool bar_break;
46 private Shortcut shortcut;
48 private bool checked_;
49 private bool radiocheck;
51 private char mnemonic;
52 private bool showshortcut;
55 private Hashtable mdilist_items;
56 private MdiClient mdicontainer;
57 private bool defaut_item;
59 private bool ownerdraw;
61 private int mergeorder;
63 private int menuheight;
65 private MenuMerge mergetype;
66 internal Rectangle bounds;
68 public MenuItem (): base (null)
70 CommonConstructor (string.Empty);
71 shortcut = Shortcut.None;
74 public MenuItem (string text) : base (null)
76 CommonConstructor (text);
77 shortcut = Shortcut.None;
80 public MenuItem (string text, EventHandler onClick) : base (null)
82 CommonConstructor (text);
83 shortcut = Shortcut.None;
87 public MenuItem (string text, MenuItem[] items) : base (items)
89 CommonConstructor (text);
90 shortcut = Shortcut.None;
93 public MenuItem (string text, EventHandler onClick, Shortcut shortcut) : base (null)
95 CommonConstructor (text);
97 this.shortcut = shortcut;
100 public MenuItem (MenuMerge mergeType, int mergeOrder, Shortcut shortcut, string text,
101 EventHandler onClick, EventHandler onPopup, EventHandler onSelect, MenuItem[] items)
104 CommonConstructor (text);
105 this.shortcut = shortcut;
106 mergeorder = mergeOrder;
107 mergetype = mergeType;
114 private void CommonConstructor (string text)
133 mergetype = MenuMerge.Add;
134 Text = text; // Text can change separator status
138 public event EventHandler Click;
139 public event DrawItemEventHandler DrawItem;
140 public event MeasureItemEventHandler MeasureItem;
141 public event EventHandler Popup;
142 public event EventHandler Select;
145 #region Public Properties
148 [DefaultValue(false)]
149 public bool BarBreak {
150 get { return break_; }
151 set { break_ = value; }
155 [DefaultValue(false)]
157 get { return bar_break; }
158 set { bar_break = value; }
161 [DefaultValue(false)]
162 public bool Checked {
163 get { return checked_; }
164 set { checked_ = value; }
167 [DefaultValue(false)]
168 public bool DefaultItem {
169 get { return defaut_item; }
170 set { defaut_item = value; }
175 public bool Enabled {
176 get { return enabled; }
177 set { enabled = value; }
182 get { return index; }
184 if (Parent != null && Parent.MenuItems != null && (value < 0 || value >= Parent.MenuItems.Count))
185 throw new ArgumentException ("'" + value + "' is not a valid value for 'value'");
191 public override bool IsParent {
192 get { return IsPopup; }
195 [DefaultValue(false)]
196 public bool MdiList {
197 get { return mdilist; }
199 if (mdilist == value)
203 if (mdilist || mdilist_items == null)
206 foreach (MenuItem item in mdilist_items.Keys)
207 MenuItems.Remove (item);
208 mdilist_items.Clear ();
209 mdilist_items = null;
214 protected int MenuID {
215 get { return menuid; }
219 public int MergeOrder {
220 get { return mergeorder; }
221 set { mergeorder = value; }
224 [DefaultValue(MenuMerge.Add)]
225 public MenuMerge MergeType {
226 get { return mergetype; }
228 if (!Enum.IsDefined (typeof (MenuMerge), value))
229 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for MenuMerge", value));
236 public char Mnemonic {
237 get { return mnemonic; }
240 [DefaultValue(false)]
241 public bool OwnerDraw {
242 get { return ownerdraw; }
243 set { ownerdraw = value; }
248 get { return parent_menu;}
251 [DefaultValue(false)]
252 public bool RadioCheck {
253 get { return radiocheck; }
254 set { radiocheck = value; }
257 [DefaultValue(Shortcut.None)]
259 public Shortcut Shortcut {
260 get { return shortcut;}
262 if (!Enum.IsDefined (typeof (Shortcut), value))
263 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for Shortcut", value));
271 public bool ShowShortcut {
272 get { return showshortcut;}
273 set { showshortcut = value; }
293 public bool Visible {
294 get { return visible;}
296 if (value == visible)
301 if (menu_items != null) {
302 foreach (MenuItem mi in menu_items)
306 if (parent_menu != null)
307 parent_menu.OnMenuChanged (EventArgs.Empty);
311 #endregion Public Properties
313 #region Private Properties
315 internal new int Height {
316 get { return bounds.Height; }
317 set { bounds.Height = value; }
320 internal bool IsPopup {
322 if (menu_items.Count > 0)
329 internal bool MeasureEventDefined {
331 if (ownerdraw == true && MeasureItem != null) {
339 internal bool MenuBar {
340 get { return menubar; }
341 set { menubar = value; }
344 internal int MenuHeight {
345 get { return menuheight; }
346 set { menuheight = value; }
350 internal bool Selected {
351 get { return selected; }
352 set { selected = value; }
355 internal bool Separator {
356 get { return separator; }
357 set { separator = value; }
360 internal DrawItemState Status {
362 DrawItemState status = DrawItemState.None;
363 MenuTracker tracker = Parent.Tracker;
365 status |= (tracker.active ? DrawItemState.Selected : DrawItemState.HotLight);
367 status |= DrawItemState.Grayed | DrawItemState.Disabled;
369 status |= DrawItemState.Checked;
370 if (!tracker.Navigating)
371 status |= DrawItemState.NoAccelerator;
376 internal new int Width {
377 get { return bounds.Width; }
378 set { bounds.Width = value; }
382 get { return bounds.X; }
383 set { bounds.X = value; }
388 set { xtab = value; }
392 get { return bounds.Y; }
393 set { bounds.Y = value; }
396 #endregion Private Properties
398 #region Public Methods
400 public virtual MenuItem CloneMenu ()
402 MenuItem item = new MenuItem ();
403 item.CloneMenu (this);
407 protected void CloneMenu (MenuItem menuitem)
409 base.CloneMenu (menuitem); // Copy subitems
412 BarBreak = menuitem.BarBreak;
413 Break = menuitem.Break;
414 Checked = menuitem.Checked;
415 DefaultItem = menuitem.DefaultItem;
416 Enabled = menuitem.Enabled;
417 MergeOrder = menuitem.MergeOrder;
418 MergeType = menuitem.MergeType;
419 OwnerDraw = menuitem.OwnerDraw;
420 //Parent = menuitem.Parent;
421 RadioCheck = menuitem.RadioCheck;
422 Shortcut = menuitem.Shortcut;
423 ShowShortcut = menuitem.ShowShortcut;
424 Text = menuitem.Text;
425 Visible = menuitem.Visible;
428 Click = menuitem.Click;
429 DrawItem = menuitem.DrawItem;
430 MeasureItem = menuitem.MeasureItem;
431 Popup = menuitem.Popup;
432 Select = menuitem.Select;
435 protected override void Dispose (bool disposing)
437 base.Dispose (disposing);
440 // This really clones the item
441 public virtual MenuItem MergeMenu ()
443 MenuItem item = new MenuItem ();
444 item.CloneMenu (this);
448 public void MergeMenu (MenuItem menuitem)
450 base.MergeMenu (menuitem);
453 protected virtual void OnClick (EventArgs e)
459 protected virtual void OnDrawItem (DrawItemEventArgs e)
462 if (DrawItem != null)
467 ThemeEngine.Current.DrawMenuItem (this, e);
471 protected virtual void OnInitMenuPopup (EventArgs e)
476 protected virtual void OnMeasureItem (MeasureItemEventArgs e)
478 if (OwnerDraw && MeasureItem != null)
479 MeasureItem (this, e);
482 protected virtual void OnPopup (EventArgs e)
488 protected virtual void OnSelect (EventArgs e)
494 public void PerformClick ()
496 OnClick (EventArgs.Empty);
499 public virtual void PerformSelect ()
501 OnSelect (EventArgs.Empty);
504 public override string ToString ()
506 return base.ToString () + ", Items.Count: " + MenuItems.Count + ", Text: " + text;
509 #endregion Public Methods
511 #region Private Methods
513 internal void PerformPopup ()
515 OnPopup (EventArgs.Empty);
518 internal void PerformDrawItem (DrawItemEventArgs e)
520 if (mdilist && mdilist_items == null) {
522 // Add the mdilist for the first time
523 mdilist_items = new Hashtable ();
525 MainMenu main = GetMainMenu ();
526 if (main == null || main.GetForm () == null)
529 Form form = main.GetForm ();
530 mdicontainer = form.MdiContainer;
531 if (mdicontainer == null)
534 foreach (Form mdichild in mdicontainer.Controls) {
535 MenuItem item = new MenuItem (mdichild.Text);
536 item.Click += new EventHandler (MdiWindowClickHandler);
537 MenuItems.AddNoEvents (item);
538 mdilist_items.Add (item, form);
547 internal void PerformMeasureItem (MeasureItemEventArgs e)
552 private void ProcessMnemonic ()
554 if (text == null || text.Length < 2) {
559 bool bPrevAmp = false;
560 for (int i = 0; i < text.Length -1 ; i++) {
561 if (text[i] == '&') {
562 if (bPrevAmp == false && (text[i+1] != '&')) {
563 mnemonic = Char.ToUpper (text[i+1]);
576 private string GetShortCutTextCtrl () { return "Ctrl"; }
577 private string GetShortCutTextAlt () { return "Alt"; }
578 private string GetShortCutTextShift () { return "Shift"; }
580 internal string GetShortCutText ()
582 /* Ctrl+A - Ctrl+Z */
583 if (Shortcut >= Shortcut.CtrlA && Shortcut <= Shortcut.CtrlZ)
584 return GetShortCutTextCtrl () + "+" + (char)((int) 'A' + (int)(Shortcut - Shortcut.CtrlA));
587 if (Shortcut >= Shortcut.Alt0 && Shortcut <= Shortcut.Alt9)
588 return GetShortCutTextAlt () + "+" + (char)((int) '0' + (int)(Shortcut - Shortcut.Alt0));
590 /* Alt+F1 - Alt+F2 */
591 if (Shortcut >= Shortcut.AltF1 && Shortcut <= Shortcut.AltF9)
592 return GetShortCutTextAlt () + "+F" + (char)((int) '1' + (int)(Shortcut - Shortcut.AltF1));
594 /* Ctrl+0 - Ctrl+9 */
595 if (Shortcut >= Shortcut.Ctrl0 && Shortcut <= Shortcut.Ctrl9)
596 return GetShortCutTextCtrl () + "+" + (char)((int) '0' + (int)(Shortcut - Shortcut.Ctrl0));
598 /* Ctrl+F0 - Ctrl+F9 */
599 if (Shortcut >= Shortcut.CtrlF1 && Shortcut <= Shortcut.CtrlF9)
600 return GetShortCutTextCtrl () + "+F" + (char)((int) '1' + (int)(Shortcut - Shortcut.CtrlF1));
602 /* Ctrl+Shift+0 - Ctrl+Shift+9 */
603 if (Shortcut >= Shortcut.CtrlShift0 && Shortcut <= Shortcut.CtrlShift9)
604 return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+" + (char)((int) '0' + (int)(Shortcut - Shortcut.CtrlShift0));
606 /* Ctrl+Shift+A - Ctrl+Shift+Z */
607 if (Shortcut >= Shortcut.CtrlShiftA && Shortcut <= Shortcut.CtrlShiftZ)
608 return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+" + (char)((int) 'A' + (int)(Shortcut - Shortcut.CtrlShiftA));
610 /* Ctrl+Shift+F1 - Ctrl+Shift+F9 */
611 if (Shortcut >= Shortcut.CtrlShiftF1 && Shortcut <= Shortcut.CtrlShiftF9)
612 return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+F" + (char)((int) '1' + (int)(Shortcut - Shortcut.CtrlShiftF1));
615 if (Shortcut >= Shortcut.F1 && Shortcut <= Shortcut.F9)
616 return "F" + (char)((int) '1' + (int)(Shortcut - Shortcut.F1));
618 /* Shift+F1 - Shift+F9 */
619 if (Shortcut >= Shortcut.ShiftF1 && Shortcut <= Shortcut.ShiftF9)
620 return GetShortCutTextShift () + "+F" + (char)((int) '1' + (int)(Shortcut - Shortcut.ShiftF1));
624 case Shortcut.AltBksp:
626 case Shortcut.AltF10:
627 return GetShortCutTextAlt () + "+F10";
628 case Shortcut.AltF11:
629 return GetShortCutTextAlt () + "+F11";
630 case Shortcut.AltF12:
631 return GetShortCutTextAlt () + "+F12";
632 case Shortcut.CtrlDel:
633 return GetShortCutTextCtrl () + "+Del";
634 case Shortcut.CtrlF10:
635 return GetShortCutTextCtrl () + "+F10";
636 case Shortcut.CtrlF11:
637 return GetShortCutTextCtrl () + "+F11";
638 case Shortcut.CtrlF12:
639 return GetShortCutTextCtrl () + "+F12";
640 case Shortcut.CtrlIns:
641 return GetShortCutTextCtrl () + "+Ins";
642 case Shortcut.CtrlShiftF10:
643 return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+F10";
644 case Shortcut.CtrlShiftF11:
645 return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+F11";
646 case Shortcut.CtrlShiftF12:
647 return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+F12";
660 case Shortcut.ShiftDel:
661 return GetShortCutTextShift () + "+Del";
662 case Shortcut.ShiftF10:
663 return GetShortCutTextShift () + "+F10";
664 case Shortcut.ShiftF11:
665 return GetShortCutTextShift () + "+F11";
666 case Shortcut.ShiftF12:
667 return GetShortCutTextShift () + "+F12";
668 case Shortcut.ShiftIns:
669 return GetShortCutTextShift () + "+Ins";
677 private void MdiWindowClickHandler (object sender, EventArgs e)
679 Form mdichild = (Form) mdilist_items [SelectedItem];
681 // people could add weird items to the Window menu
682 // so we can't assume its just us
683 if (mdichild == null)
686 mdicontainer.ActivateChild (mdichild);
689 #endregion Private Methods