merge -r 58060:58217
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / MenuItem.cs
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 bool defaut_item;
56                 private bool visible;
57                 private bool ownerdraw;
58                 private int menuid;
59                 private int mergeorder;
60                 private int xtab;
61                 private int menuheight;
62                 private bool menubar;
63                 private DrawItemState status;
64                 private MenuMerge mergetype;
65                 
66                 public MenuItem (): base (null)
67                 {       
68                         CommonConstructor (string.Empty);
69                         shortcut = Shortcut.None;
70                 }
71
72                 public MenuItem (string text) : base (null)
73                 {
74                         CommonConstructor (text);
75                         shortcut = Shortcut.None;
76                 }
77
78                 public MenuItem (string text, EventHandler onClick) : base (null)
79                 {
80                         CommonConstructor (text);
81                         shortcut = Shortcut.None;
82                         Click += onClick;
83                 }
84
85                 public MenuItem (string text, MenuItem[] items) : base (items)
86                 {
87                         CommonConstructor (text);
88                         shortcut = Shortcut.None;
89                 }
90
91                 public MenuItem (string text, EventHandler onClick, Shortcut shortcut) : base (null)
92                 {
93                         CommonConstructor (text);
94                         Click += onClick;
95                         this.shortcut = shortcut;
96                 }
97
98                 public MenuItem (MenuMerge mergeType, int mergeOrder, Shortcut shortcut, string text,
99                         EventHandler onClick, EventHandler onPopup,  EventHandler onSelect,  MenuItem[] items)
100                         : base (items)
101                 {
102                         CommonConstructor (text);
103                         this.shortcut = shortcut;
104                         mergeorder = mergeOrder;
105                         mergetype = mergeType;
106
107                         Click += onClick;
108                         Popup += onPopup;
109                         Select += onSelect;
110                 }
111
112                 private void CommonConstructor (string text)
113                 {
114                         defaut_item = false;
115                         separator = false;
116                         break_ = false;
117                         bar_break = false;
118                         checked_ = false;
119                         radiocheck = false;
120                         enabled = true;
121                         showshortcut = true;
122                         visible = true;
123                         ownerdraw = false;
124                         status = DrawItemState.None;
125                         menubar = false;
126                         menuheight = 0;
127                         xtab = 0;
128                         index = -1;
129                         mnemonic = '\0';
130                         menuid = -1;
131                         mergeorder = 0;
132                         mergetype = MenuMerge.Add;
133                         Text = text;    // Text can change separator status
134                 }
135
136                 #region Events
137                 public event EventHandler Click;
138                 public event DrawItemEventHandler DrawItem;
139                 public event MeasureItemEventHandler MeasureItem;
140                 public event EventHandler Popup;
141                 public event EventHandler Select;
142                 #endregion // Events
143
144                 #region Public Properties
145
146                 [Browsable(false)]
147                 [DefaultValue(false)]
148                 public bool BarBreak {
149                         get { return break_; }
150                         set { break_ = value; }
151                 }
152
153                 [Browsable(false)]
154                 [DefaultValue(false)]
155                 public bool Break {
156                         get { return bar_break; }
157                         set { bar_break = value; }
158                 }
159
160                 [DefaultValue(false)]
161                 public bool Checked {
162                         get { return checked_; }
163                         set { checked_ = value; }
164                 }
165
166                 [DefaultValue(false)]
167                 public bool DefaultItem {
168                         get { return defaut_item; }
169                         set { defaut_item = value; }
170                 }
171
172                 [DefaultValue(true)]
173                 [Localizable(true)]
174                 public bool Enabled {
175                         get { return enabled; }
176                         set { enabled = value; }
177                 }
178
179                 [Browsable(false)]
180                 public int Index {
181                         get { return index; }
182                         set { 
183                                 if (Parent != null && Parent.MenuItems != null && (value < 0 || value >= Parent.MenuItems.Count))
184                                         throw new ArgumentException ("'" + value + "' is not a valid value for 'value'");
185                                 index = value; 
186                         }
187                 }
188
189                 [Browsable(false)]
190                 public override bool IsParent {
191                         get { return IsPopup; }
192                 }
193
194                 [DefaultValue(false)]
195                 public bool MdiList {
196                         get { return mdilist; }
197                         set { mdilist = value; }
198                 }
199
200                 protected int MenuID {
201                         get { return menuid; }
202                 }
203
204                 [DefaultValue(0)]
205                 public int MergeOrder {
206                         get { return mergeorder; }
207                         set { mergeorder = value; }
208                 }
209
210                 [DefaultValue(MenuMerge.Add)]
211                 public MenuMerge MergeType {
212                         get { return mergetype; }
213                         set {
214                                 if (!Enum.IsDefined (typeof (MenuMerge), value))
215                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for MenuMerge", value));
216
217                                 mergetype = value;
218                         }
219                 }
220
221                 [Browsable(false)]
222                 public char Mnemonic {
223                         get { return mnemonic; }
224                 }
225
226                 [DefaultValue(false)]
227                 public bool OwnerDraw {
228                         get { return ownerdraw; }
229                         set { ownerdraw = value; }
230                 }
231
232                 [Browsable(false)]
233                 public Menu Parent {
234                         get { return parent_menu;}
235                 }
236
237                 [DefaultValue(false)]
238                 public bool RadioCheck {
239                         get { return radiocheck; }
240                         set { radiocheck = value; }
241                 }
242
243                 [DefaultValue(Shortcut.None)]
244                 [Localizable(true)]
245                 public Shortcut Shortcut {
246                         get { return shortcut;}
247                         set {
248                                 if (!Enum.IsDefined (typeof (Shortcut), value))
249                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for Shortcut", value));
250
251                                 shortcut = value;
252                         }
253                 }
254
255                 [DefaultValue(true)]
256                 [Localizable(true)]
257                 public bool ShowShortcut {
258                         get { return showshortcut;}
259                         set { showshortcut = value; }
260                 }
261
262                 [Localizable(true)]
263                 public string Text {
264                         get { return text; }
265                         set {
266                                 text = value;
267
268                                 if (text == "-")
269                                         separator = true;
270                                 else
271                                         separator = false;
272
273                                 ProcessMnemonic ();
274                         }
275                 }
276
277                 [DefaultValue(true)]
278                 [Localizable(true)]
279                 public bool Visible {
280                         get { return visible;}
281                         set { 
282                                 if (value == visible)
283                                         return;
284
285                                 visible = value;
286
287                                 if (menu_items != null) {
288                                         foreach (MenuItem mi in menu_items)
289                                                 mi.Visible = value;
290                                 }
291
292                                 if (parent_menu != null) {
293                                         parent_menu.IsDirty = true;
294                                         parent_menu.creating = false;
295                                 }
296                         }
297                 }
298
299                 #endregion Public Properties
300
301                 #region Private Properties
302
303                 internal bool IsPopup {
304                         get {
305                                 if (menu_items.Count > 0)
306                                         return true;
307                                 else
308                                         return false;
309                         }
310                 }
311                 
312                 internal bool MeasureEventDefined {
313                         get { 
314                                 if (ownerdraw == true && MeasureItem != null) {
315                                         return true;
316                                 } else {
317                                         return false;
318                                 }
319                         }
320                 }
321                 
322                 internal bool MenuBar {
323                         get { return menubar; }
324                         set { menubar = value; }
325                 }
326                 
327                 internal int MenuHeight {
328                         get { return menuheight; }
329                         set { menuheight = value; }
330                 }       
331
332                 internal bool Separator {
333                         get { return separator; }
334                         set { separator = value; }
335                 }
336                 
337                 internal DrawItemState Status {
338                         get { return status; }
339                         set { status = value; }
340                 }
341                 
342                 internal int XTab {
343                         get { return xtab; }
344                         set { xtab = value; }
345                 }
346
347                 #endregion Private Properties
348
349                 #region Public Methods
350
351                 public virtual MenuItem CloneMenu ()
352                 {
353                         MenuItem item = new MenuItem ();
354                         item.CloneMenu (this);
355                         return item;
356                 }
357
358                 protected void CloneMenu (MenuItem menuitem)
359                 {
360                         base.CloneMenu (menuitem); // Copy subitems
361
362                         // Properties
363                         BarBreak = menuitem.BarBreak;
364                         Break = menuitem.Break;
365                         Checked = menuitem.Checked;
366                         DefaultItem = menuitem.DefaultItem;
367                         Enabled = menuitem.Enabled;                     
368                         MergeOrder = menuitem.MergeOrder;
369                         MergeType = menuitem.MergeType;
370                         OwnerDraw = menuitem.OwnerDraw;
371                         //Parent = menuitem.Parent;
372                         RadioCheck = menuitem.RadioCheck;
373                         Shortcut = menuitem.Shortcut;
374                         ShowShortcut = menuitem.ShowShortcut;
375                         Text = menuitem.Text;
376                         Visible = menuitem.Visible;
377
378                         // Events
379                         Click = menuitem.Click;
380                         DrawItem = menuitem.DrawItem;
381                         MeasureItem = menuitem.MeasureItem;
382                         Popup = menuitem.Popup;
383                         Select = menuitem.Select;
384                 }
385
386                 protected override void Dispose (bool disposing)
387                 {
388                         base.Dispose (disposing);                       
389                 }
390
391                 // This really clones the item
392                 public virtual MenuItem MergeMenu ()
393                 {
394                         MenuItem item = new MenuItem ();
395                         item.CloneMenu (this);
396                         return item;
397                 }
398
399                 public void MergeMenu (MenuItem menuitem)
400                 {
401                         base.MergeMenu (menuitem);
402                 }
403
404                 protected virtual void OnClick (EventArgs e)
405                 {
406                         if (Click != null)
407                                 Click (this, e);
408                 }
409
410                 protected virtual void OnDrawItem (DrawItemEventArgs e)
411                 {
412                         if (DrawItem != null) {
413                                 DrawItem (this, e);
414                                 return;
415                         }
416                         
417                         ThemeEngine.Current.DrawMenuItem (this, e);     
418                 }
419
420
421                 protected virtual void OnInitMenuPopup (EventArgs e)
422                 {
423                         OnPopup (e);
424                 }
425
426                 protected virtual void OnMeasureItem (MeasureItemEventArgs e)
427                 {
428                         if (MeasureItem != null)
429                                 MeasureItem (this, e);
430                 }
431
432                 protected virtual void OnPopup (EventArgs e)
433                 {
434                         if (Popup != null)
435                                 Popup (this, e);
436                 }
437
438                 protected virtual void OnSelect (EventArgs e)
439                 {
440                         if (Select != null)
441                                 Select (this, e);
442                 }
443
444                 public void PerformClick ()
445                 {
446                         OnClick (EventArgs.Empty);
447                 }
448
449                 public virtual void PerformSelect ()
450                 {
451                         OnSelect (EventArgs.Empty);
452                 }
453
454                 public override string ToString ()
455                 {
456                         return base.ToString () + ", Items.Count: " + MenuItems.Count + ", Text: " + text;
457                 }
458
459                 #endregion Public Methods
460
461                 #region Private Methods
462
463                 internal void Create ()
464                 {
465                         IntPtr hSubMenu = IntPtr.Zero;
466
467                         menuid = index = MenuAPI.InsertMenuItem (Parent.Handle, -1, true, this, ref hSubMenu);
468                         IsDirty = false;
469
470                         if (IsPopup) {
471                                 menu_handle = hSubMenu;
472                                 CreateItems ();
473                         }
474                 }
475                 
476                 internal void PerformDrawItem (DrawItemEventArgs e)
477                 {
478                         OnDrawItem (e);
479                 }
480                 
481                 internal void PerformMeasureItem (MeasureItemEventArgs e)
482                 {
483                         OnMeasureItem (e);
484                 }
485
486                 private void ProcessMnemonic ()
487                 {
488                         if (text.Length < 2) {
489                                 mnemonic = '\0';
490                                 return;
491                         }
492
493                         bool bPrevAmp = false;
494                         for (int i = 0; i < text.Length -1 ; i++) {
495                                 if (text[i] == '&') {
496                                         if (bPrevAmp == false &&  (text[i+1] != '&')) {
497                                                 mnemonic = Char.ToUpper (text[i+1]);
498                                                 return;
499                                         }
500
501                                         bPrevAmp = true;
502                                 }
503                                 else
504                                         bPrevAmp = false;
505                         }
506
507                         mnemonic = '\0';
508                 }
509
510                 private string GetShortCutTextCtrl () { return "Ctrl"; }
511                 private string GetShortCutTextAlt () { return "Alt"; }
512                 private string GetShortCutTextShift () { return "Shift"; }              
513
514                 internal string GetShortCutText ()
515                 {
516                         /* Ctrl+A - Ctrl+Z */
517                         if (Shortcut >= Shortcut.CtrlA && Shortcut <= Shortcut.CtrlZ)
518                                 return GetShortCutTextCtrl () + "+" + (char)((int) 'A' + (int)(Shortcut - Shortcut.CtrlA));
519
520                         /* Alt+0 - Alt+9 */
521                         if (Shortcut >= Shortcut.Alt0 && Shortcut <= Shortcut.Alt9)
522                                 return GetShortCutTextAlt () + "+" + (char)((int) '0' + (int)(Shortcut - Shortcut.Alt0));
523
524                         /* Alt+F1 - Alt+F2 */
525                         if (Shortcut >= Shortcut.AltF1 && Shortcut <= Shortcut.AltF9)
526                                 return GetShortCutTextAlt () + "+F" + (char)((int) '1' + (int)(Shortcut - Shortcut.AltF1));
527
528                         /* Ctrl+0 - Ctrl+9 */
529                         if (Shortcut >= Shortcut.Ctrl0 && Shortcut <= Shortcut.Ctrl9)
530                                 return GetShortCutTextCtrl () + "+" + (char)((int) '0' + (int)(Shortcut - Shortcut.Ctrl0));
531                                                         
532                         /* Ctrl+F0 - Ctrl+F9 */
533                         if (Shortcut >= Shortcut.CtrlF1 && Shortcut <= Shortcut.CtrlF9)
534                                 return GetShortCutTextCtrl () + "+F" + (char)((int) '1' + (int)(Shortcut - Shortcut.CtrlF1));
535                                 
536                         /* Ctrl+Shift+0 - Ctrl+Shift+9 */
537                         if (Shortcut >= Shortcut.CtrlShift0 && Shortcut <= Shortcut.CtrlShift9)
538                                 return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+" + (char)((int) '0' + (int)(Shortcut - Shortcut.CtrlShift0));
539                                 
540                         /* Ctrl+Shift+A - Ctrl+Shift+Z */
541                         if (Shortcut >= Shortcut.CtrlShiftA && Shortcut <= Shortcut.CtrlShiftZ)
542                                 return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+" + (char)((int) 'A' + (int)(Shortcut - Shortcut.CtrlShiftA));
543
544                         /* Ctrl+Shift+F1 - Ctrl+Shift+F9 */
545                         if (Shortcut >= Shortcut.CtrlShiftF1 && Shortcut <= Shortcut.CtrlShiftF9)
546                                 return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+F" + (char)((int) '1' + (int)(Shortcut - Shortcut.CtrlShiftF1));
547                                 
548                         /* F1 - F9 */
549                         if (Shortcut >= Shortcut.F1 && Shortcut <= Shortcut.F9)
550                                 return "F" + (char)((int) '1' + (int)(Shortcut - Shortcut.F1));
551                                 
552                         /* Shift+F1 - Shift+F9 */
553                         if (Shortcut >= Shortcut.ShiftF1 && Shortcut <= Shortcut.ShiftF9)
554                                 return GetShortCutTextShift () + "+F" + (char)((int) '1' + (int)(Shortcut - Shortcut.ShiftF1));
555                         
556                         /* Special cases */
557                         switch (Shortcut) {
558                                 case Shortcut.AltBksp:
559                                         return "AltBksp";
560                                 case Shortcut.AltF10:
561                                         return GetShortCutTextAlt () + "+F10";
562                                 case Shortcut.AltF11:
563                                         return GetShortCutTextAlt () + "+F11";
564                                 case Shortcut.AltF12:
565                                         return GetShortCutTextAlt () + "+F12";
566                                 case Shortcut.CtrlDel:          
567                                         return GetShortCutTextCtrl () + "+Del";
568                                 case Shortcut.CtrlF10:
569                                         return GetShortCutTextCtrl () + "+F10";
570                                 case Shortcut.CtrlF11:
571                                         return GetShortCutTextCtrl () + "+F11";
572                                 case Shortcut.CtrlF12:
573                                         return GetShortCutTextCtrl () + "+F12";
574                                 case Shortcut.CtrlIns:
575                                         return GetShortCutTextCtrl () + "+Ins";
576                                 case Shortcut.CtrlShiftF10:
577                                         return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+F10";
578                                 case Shortcut.CtrlShiftF11:
579                                         return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+F11";
580                                 case Shortcut.CtrlShiftF12:
581                                         return GetShortCutTextCtrl () + "+" + GetShortCutTextShift () + "+F12";
582                                 case Shortcut.Del:
583                                         return "Del";
584                                 case Shortcut.F10:
585                                         return "F10";   
586                                 case Shortcut.F11:
587                                         return "F11";   
588                                 case Shortcut.F12:
589                                         return "F12";   
590                                 case Shortcut.Ins:
591                                         return "Ins";   
592                                 case Shortcut.None:
593                                         return "None";  
594                                 case Shortcut.ShiftDel:
595                                         return GetShortCutTextShift () + "+Del";
596                                 case Shortcut.ShiftF10:
597                                         return GetShortCutTextShift () + "+F10";
598                                 case Shortcut.ShiftF11:
599                                         return GetShortCutTextShift () + "+F11";
600                                 case Shortcut.ShiftF12:
601                                         return GetShortCutTextShift () + "+F12";                                
602                                 case Shortcut.ShiftIns:
603                                         return GetShortCutTextShift () + "+Ins";
604                                 default:
605                                         break;
606                                 }
607                                 
608                         return "";
609                 }
610
611                 #endregion Private Methods
612
613         }
614 }
615
616