2007-01-10 Jonathan Pobst <jpobst@novell.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / MenuItem.cs
index 8a27a25a29e8d852b6e614499b3b084b729a6966..00076ec0e1daace42c0646482f10304dfc8bcfd0 100644 (file)
@@ -53,7 +53,9 @@ namespace System.Windows.Forms
                private int index;
                private bool mdilist;
                private Hashtable mdilist_items;
+               private Hashtable mdilist_forms;
                private MdiClient mdicontainer;
+               private bool is_window_menu_item;
                private bool defaut_item;
                private bool visible;
                private bool ownerdraw;
@@ -62,7 +64,6 @@ namespace System.Windows.Forms
                private int xtab;
                private int menuheight;
                private bool menubar;
-               private DrawItemState status;
                private MenuMerge mergetype;
                internal Rectangle bounds;
                
@@ -124,7 +125,6 @@ namespace System.Windows.Forms
                        showshortcut = true;
                        visible = true;
                        ownerdraw = false;
-                       status = DrawItemState.None;
                        menubar = false;
                        menuheight = 0;
                        xtab = 0;
@@ -137,11 +137,36 @@ namespace System.Windows.Forms
                }
 
                #region Events
-               public event EventHandler Click;
-               public event DrawItemEventHandler DrawItem;
-               public event MeasureItemEventHandler MeasureItem;
-               public event EventHandler Popup;
-               public event EventHandler Select;
+               static object ClickEvent = new object ();
+               static object DrawItemEvent = new object ();
+               static object MeasureItemEvent = new object ();
+               static object PopupEvent = new object ();
+               static object SelectEvent = new object ();
+
+               public event EventHandler Click {
+                       add { Events.AddHandler (ClickEvent, value); }
+                       remove { Events.RemoveHandler (ClickEvent, value); }
+               }
+
+               public event DrawItemEventHandler DrawItem {
+                       add { Events.AddHandler (DrawItemEvent, value); }
+                       remove { Events.RemoveHandler (DrawItemEvent, value); }
+               }
+
+               public event MeasureItemEventHandler MeasureItem {
+                       add { Events.AddHandler (MeasureItemEvent, value); }
+                       remove { Events.RemoveHandler (MeasureItemEvent, value); }
+               }
+
+               public event EventHandler Popup {
+                       add { Events.AddHandler (PopupEvent, value); }
+                       remove { Events.RemoveHandler (PopupEvent, value); }
+               }
+
+               public event EventHandler Select {
+                       add { Events.AddHandler (SelectEvent, value); }
+                       remove { Events.RemoveHandler (SelectEvent, value); }
+               }
                #endregion // Events
 
                #region Public Properties
@@ -176,7 +201,13 @@ namespace System.Windows.Forms
                [Localizable(true)]
                public bool Enabled {
                        get { return enabled; }
-                       set { enabled = value; }
+                       set {
+                               if (enabled == value)
+                                       return;
+                                       
+                               enabled = value;
+                               Invalidate ();
+                       }
                }
 
                [Browsable(false)]
@@ -209,7 +240,6 @@ namespace System.Windows.Forms
                                        MenuItems.Remove (item);
                                mdilist_items.Clear ();
                                mdilist_items = null;
-                               
                        }
                }
 
@@ -287,6 +317,7 @@ namespace System.Windows.Forms
                                        separator = false;
 
                                ProcessMnemonic ();
+                               Invalidate ();
                        }
                }
 
@@ -330,7 +361,7 @@ namespace System.Windows.Forms
                
                internal bool MeasureEventDefined {
                        get { 
-                               if (ownerdraw == true && MeasureItem != null) {
+                               if (ownerdraw == true && Events [MeasureItemEvent] != null) {
                                        return true;
                                } else {
                                        return false;
@@ -348,16 +379,44 @@ namespace System.Windows.Forms
                        set { menuheight = value; }
                }       
 
+               bool selected;
+               internal bool Selected {
+                       get { return selected; }
+                       set { selected = value; }
+               }
+
                internal bool Separator {
                        get { return separator; }
                        set { separator = value; }
                }
                
                internal DrawItemState Status {
-                       get { return status; }
-                       set { status = value; }
+                       get {
+                               DrawItemState status = DrawItemState.None;
+                               MenuTracker tracker = Parent.Tracker;
+                               if (Selected)
+                                       status |= (tracker.active || tracker.Navigating ? DrawItemState.Selected : DrawItemState.HotLight);
+                               if (!Enabled)
+                                       status |= DrawItemState.Grayed | DrawItemState.Disabled;
+                               if (Checked)
+                                       status |= DrawItemState.Checked;
+                               if (!tracker.Navigating)
+                                       status |= DrawItemState.NoAccelerator;
+                               return status;
+                       }
                }
                
+               internal bool VisibleItems {
+                       get { 
+                               if (menu_items != null) {
+                                       foreach (MenuItem mi in menu_items)
+                                               if (mi.Visible)
+                                                       return true;
+                               }
+                               return false;
+                       }
+               }
+
                internal new int Width {
                        get { return bounds.Width; }
                        set { bounds.Width = value; }
@@ -393,6 +452,22 @@ namespace System.Windows.Forms
                {
                        base.CloneMenu (menuitem); // Copy subitems
 
+                       // Window list
+                       MdiList = menuitem.MdiList;
+                       is_window_menu_item = menuitem.is_window_menu_item;
+                       // Remove items corresponding to window menu items, and add new items
+                       // (Otherwise window menu items would show up twice, since the PopulateWindowMenu doesn't
+                       // now them)
+                       bool populated = false;
+                       for (int i = MenuItems.Count - 1; i >= 0; i--) {
+                               if (MenuItems [i].is_window_menu_item) {
+                                       MenuItems.RemoveAt (i);
+                                       populated = true;
+                               }
+                       }
+                       if (populated)
+                               PopulateWindowMenu ();
+
                        // Properties
                        BarBreak = menuitem.BarBreak;
                        Break = menuitem.Break;
@@ -410,11 +485,11 @@ namespace System.Windows.Forms
                        Visible = menuitem.Visible;
 
                        // Events
-                       Click = menuitem.Click;
-                       DrawItem = menuitem.DrawItem;
-                       MeasureItem = menuitem.MeasureItem;
-                       Popup = menuitem.Popup;
-                       Select = menuitem.Select;
+                       Events[ClickEvent] = menuitem.Events[ClickEvent];
+                       Events[DrawItemEvent] = menuitem.Events[DrawItemEvent];
+                       Events[MeasureItemEvent] = menuitem.Events[MeasureItemEvent];
+                       Events[PopupEvent] = menuitem.Events[PopupEvent];
+                       Events[SelectEvent] = menuitem.Events[SelectEvent];
                }
 
                protected override void Dispose (bool disposing)
@@ -437,17 +512,20 @@ namespace System.Windows.Forms
 
                protected virtual void OnClick (EventArgs e)
                {
-                       if (Click != null)
-                               Click (this, e);
+                       EventHandler eh = (EventHandler)(Events [ClickEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
                protected virtual void OnDrawItem (DrawItemEventArgs e)
                {
-                       if (DrawItem != null) {
-                               DrawItem (this, e);
+                       if (OwnerDraw) {
+                               DrawItemEventHandler eh = (DrawItemEventHandler)(Events [DrawItemEvent]);
+                               if (eh != null)
+                                       eh (this, e);
                                return;
                        }
-                       
+
                        ThemeEngine.Current.DrawMenuItem (this, e);     
                }
 
@@ -459,20 +537,26 @@ namespace System.Windows.Forms
 
                protected virtual void OnMeasureItem (MeasureItemEventArgs e)
                {
-                       if (MeasureItem != null)
-                               MeasureItem (this, e);
+                       if (!OwnerDraw)
+                               return;
+
+                       MeasureItemEventHandler eh = (MeasureItemEventHandler)(Events [MeasureItemEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
                protected virtual void OnPopup (EventArgs e)
                {
-                       if (Popup != null)
-                               Popup (this, e);
+                       EventHandler eh = (EventHandler)(Events [PopupEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
                protected virtual void OnSelect (EventArgs e)
                {
-                       if (Select != null)
-                               Select (this, e);
+                       EventHandler eh = (EventHandler)(Events [SelectEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
                public void PerformClick ()
@@ -494,6 +578,12 @@ namespace System.Windows.Forms
 
                #region Private Methods
 
+               internal virtual void Invalidate ()
+               {
+                       if ((Parent != null) && (Parent is MainMenu) && Parent.Wnd != null)
+                               XplatUI.RequestNCRecalc (Parent.Wnd.FindForm ().Handle);
+               }
+
                internal void PerformPopup ()
                {
                        OnPopup (EventArgs.Empty);
@@ -501,11 +591,19 @@ namespace System.Windows.Forms
 
                internal void PerformDrawItem (DrawItemEventArgs e)
                {
-                       if (mdilist && mdilist_items == null) {
-                               do {
-                                       // Add the mdilist for the first time
+                       PopulateWindowMenu ();
+                       OnDrawItem (e);
+               }
+               
+               private void PopulateWindowMenu ()
+               {
+                       if (mdilist) {
+                               if (mdilist_items == null) {
                                        mdilist_items = new Hashtable ();
-
+                                       mdilist_forms = new Hashtable ();
+                               }
+                               
+                               do {
                                        MainMenu main = GetMainMenu ();
                                        if (main == null || main.GetForm () == null)
                                                break;
@@ -515,17 +613,49 @@ namespace System.Windows.Forms
                                        if (mdicontainer == null)
                                                break;
 
-                                       foreach (Form mdichild in mdicontainer.Controls) {
-                                               MenuItem item = new MenuItem (mdichild.Text);
-                                               item.Click += new EventHandler (MdiWindowClickHandler);
-                                               MenuItems.Add (item);
-                                               mdilist_items.Add (item, form);
+                                       
+                                       // Remove closed forms
+                                       MenuItem[] items = new MenuItem[mdilist_items.Count];
+                                       mdilist_items.Keys.CopyTo (items, 0);
+                                       foreach (MenuItem item in items) {
+                                               Form mdichild = (Form) mdilist_items [item];
+                                               if (!mdicontainer.mdi_child_list.Contains(mdichild)) {
+                                                       mdilist_items.Remove (item);
+                                                       mdilist_forms.Remove (mdichild);
+                                                       MenuItems.Remove (item);
+                                               }
+                                       }
+                                       
+                                       // Add new forms and update state for existing forms.
+                                       for (int i = 0; i < mdicontainer.mdi_child_list.Count; i++) {
+                                               Form mdichild = (Form)mdicontainer.mdi_child_list[i];
+                                               MenuItem item;
+                                               if (mdilist_forms.Contains (mdichild)) {
+                                                       item = (MenuItem) mdilist_forms [mdichild];
+                                               } else {
+                                                       item = new MenuItem ();
+                                                       item.is_window_menu_item = true;
+                                                       item.Click += new EventHandler (MdiWindowClickHandler);
+                                                       mdilist_items [item] = mdichild;
+                                                       mdilist_forms [mdichild] = item;
+                                                       MenuItems.AddNoEvents (item);
+                                               }
+                                               item.Visible = mdichild.Visible;
+                                               item.Text = "&" + (i + 1).ToString () + " " + mdichild.Text;
+                                               item.Checked = form.ActiveMdiChild == mdichild;
                                        }
-
                                } while (false);
+                       } else {
+                               // Remove all forms
+                               if (mdilist_items != null) {
+                                       foreach (MenuItem item in mdilist_items.Values) {
+                                               MenuItems.Remove (item);
+                                       }
+                                       
+                                       mdilist_forms.Clear ();
+                                       mdilist_items.Clear ();
+                               }
                        }
-
-                       OnDrawItem (e);
                }
                
                internal void PerformMeasureItem (MeasureItemEventArgs e)
@@ -535,7 +665,7 @@ namespace System.Windows.Forms
 
                private void ProcessMnemonic ()
                {
-                       if (text.Length < 2) {
+                       if (text == null || text.Length < 2) {
                                mnemonic = '\0';
                                return;
                        }
@@ -660,7 +790,7 @@ namespace System.Windows.Forms
 
                private void MdiWindowClickHandler (object sender, EventArgs e)
                {
-                       Form mdichild = (Form) mdilist_items [SelectedItem];
+                       Form mdichild = (Form) mdilist_items [sender];
 
                        // people could add weird items to the Window menu
                        // so we can't assume its just us