aboutsummaryrefslogtreecommitdiff
path: root/source/ShiftUI/Menu/MenuAPI.cs
diff options
context:
space:
mode:
Diffstat (limited to 'source/ShiftUI/Menu/MenuAPI.cs')
-rw-r--r--source/ShiftUI/Menu/MenuAPI.cs836
1 files changed, 836 insertions, 0 deletions
diff --git a/source/ShiftUI/Menu/MenuAPI.cs b/source/ShiftUI/Menu/MenuAPI.cs
new file mode 100644
index 0000000..79a7a1d
--- /dev/null
+++ b/source/ShiftUI/Menu/MenuAPI.cs
@@ -0,0 +1,836 @@
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (c) 2004-2005 Novell, Inc.
+//
+// Authors:
+// Jordi Mas i Hernandez, [email protected]
+// Mike Kestner <[email protected]>
+// Everaldo Canuto <[email protected]>
+//
+
+using System.Collections;
+using System.Drawing;
+using System.Threading;
+using System;
+
+namespace ShiftUI {
+
+ /*
+ When writing this code the Wine project was of great help to
+ understand the logic behind some Win32 issues. Thanks to them. Jordi,
+ */
+ // UIA Framework Note: This class used by UIA for its mouse action methods.
+ internal class MenuTracker {
+
+ internal bool active;
+ internal bool popup_active;
+ internal bool popdown_menu;
+ internal bool hotkey_active;
+ private bool mouse_down = false;
+ public Menu CurrentMenu;
+ public Menu TopMenu;
+ public Widget GrabControl;
+ Point last_motion = Point.Empty;
+
+ public MenuTracker (Menu top_menu)
+ {
+ TopMenu = CurrentMenu = top_menu;
+ foreach (MenuItem item in TopMenu.MenuItems)
+ AddShortcuts (item);
+ }
+
+ enum KeyNavState {
+ Idle,
+ Startup,
+ NoPopups,
+ Navigating
+ }
+
+ KeyNavState keynav_state = KeyNavState.Idle;
+
+ public bool Navigating {
+ get { return keynav_state != KeyNavState.Idle || active; }
+ }
+
+ internal static Point ScreenToMenu (Menu menu, Point pnt)
+ {
+ int x = pnt.X;
+ int y = pnt.Y;
+ XplatUI.ScreenToMenu (menu.Wnd.window.Handle, ref x, ref y);
+ return new Point (x, y);
+ }
+
+ private void UpdateCursor ()
+ {
+ Widget child_control = GrabControl.GetRealChildAtPoint (Cursor.Position);
+ if (child_control != null) {
+ if (active)
+ XplatUI.SetCursor (child_control.Handle, Cursors.Default.handle);
+ else
+ XplatUI.SetCursor (child_control.Handle, child_control.Cursor.handle);
+ }
+ }
+
+ internal void Deactivate ()
+ {
+ bool redrawbar = (keynav_state != KeyNavState.Idle) && (TopMenu is MainMenu);
+
+ active = false;
+ popup_active = false;
+ hotkey_active = false;
+ if (GrabControl != null)
+ GrabControl.ActiveTracker = null;
+ keynav_state = KeyNavState.Idle;
+ CurrentMenu = TopMenu;
+
+ if (redrawbar)
+ (TopMenu as MainMenu).Draw ();
+ }
+
+ MenuItem FindItemByCoords (Menu menu, Point pt)
+ {
+ if (menu is MainMenu)
+ pt = ScreenToMenu (menu, pt);
+ else {
+ if (menu.Wnd == null) {
+ return null;
+ }
+ pt = menu.Wnd.PointToClient (pt);
+ }
+ foreach (MenuItem item in menu.MenuItems) {
+ Rectangle rect = item.bounds;
+ if (rect.Contains (pt))
+ return item;
+ }
+
+ return null;
+ }
+
+ MenuItem GetItemAtXY (int x, int y)
+ {
+ Point pnt = new Point (x, y);
+ MenuItem item = null;
+ return item;
+ }
+
+ // UIA Framework Note: Used to expand/collapse MenuItems
+ public bool OnMouseDown (MouseEventArgs args)
+ {
+ MenuItem item = GetItemAtXY (args.X, args.Y);
+
+ mouse_down = true;
+
+ if (item == null) {
+ Deactivate ();
+ return false;
+ }
+
+ if ((args.Button & MouseButtons.Left) == 0)
+ return true;
+
+ if (!item.Enabled)
+ return true;
+
+ popdown_menu = active && item.VisibleItems;
+
+ if (item.IsPopup || (item.Parent is MainMenu)) {
+ active = true;
+ item.Parent.InvalidateItem (item);
+ }
+
+ if ((CurrentMenu == TopMenu) && !popdown_menu)
+ SelectItem (item.Parent, item, item.IsPopup);
+
+ GrabControl.ActiveTracker = this;
+ return true;
+ }
+
+ // UIA Framework Note: Used to select MenuItems
+ public void OnMotion (MouseEventArgs args)
+ {
+ // Windows helpfully sends us MOUSEMOVE messages when any key is pressed.
+ // So if the mouse hasn't actually moved since the last MOUSEMOVE, ignore it.
+ if (args.Location == last_motion)
+ return;
+
+ last_motion = args.Location;
+
+ MenuItem item = GetItemAtXY (args.X, args.Y);
+
+ UpdateCursor ();
+
+ if (CurrentMenu.SelectedItem == item)
+ return;
+
+ GrabControl.ActiveTracker = (active || item != null) ? this : null;
+
+ if (item == null) {
+ MenuItem old_item = CurrentMenu.SelectedItem;
+
+ // Return when is a popup with visible subitems for MainMenu
+ if ((active && old_item.VisibleItems && old_item.IsPopup && (CurrentMenu is MainMenu)))
+ return;
+
+ // Also returns when keyboard navigating
+ if (keynav_state == KeyNavState.Navigating)
+ return;
+
+ // Select parent menu when move outside of menu item
+ if (old_item.Parent is MenuItem) {
+ MenuItem new_item = (old_item.Parent as MenuItem);
+ if (new_item.IsPopup) {
+ SelectItem (new_item.Parent, new_item, false);
+ return;
+ }
+ }
+ if (CurrentMenu != TopMenu)
+ CurrentMenu = CurrentMenu.parent_menu;
+
+ DeselectItem (old_item);
+ } else {
+ keynav_state = KeyNavState.Idle;
+ SelectItem (item.Parent, item, active && item.IsPopup && popup_active && (CurrentMenu.SelectedItem != item));
+ }
+ }
+
+ // UIA Framework Note: Used to expand/collapse MenuItems
+ public void OnMouseUp (MouseEventArgs args)
+ {
+ /* mouse down dont comes from menu */
+ if (!mouse_down)
+ return;
+
+ mouse_down = false;
+
+ /* is not left button */
+ if ((args.Button & MouseButtons.Left) == 0)
+ return;
+
+ MenuItem item = GetItemAtXY (args.X, args.Y);
+
+ /* the user released the mouse button outside the menu */
+ if (item == null) {
+ Deactivate ();
+ return;
+ }
+
+ if (!item.Enabled)
+ return;
+
+ /* Perform click when is not a popup */
+ if (!item.IsPopup) {
+ DeselectItem (item);
+
+ // Raise the form's MenuComplete event
+ if (TopMenu != null && TopMenu.Wnd != null) {
+ Form f = TopMenu.Wnd.FindForm ();
+
+ if (f != null)
+ f.OnMenuComplete (EventArgs.Empty);
+ }
+
+ item.PerformClick ();
+ }
+ }
+
+ static public bool TrackPopupMenu (Menu menu, Point pnt)
+ {
+ return true;
+ }
+
+ void DeselectItem (MenuItem item)
+ {
+ if (item == null)
+ return;
+
+ item.Selected = false;
+
+ /* When popup item then close all sub popups and unselect all sub items */
+ if (item.IsPopup) {
+ HideSubPopups (item, TopMenu);
+
+ /* Unselect all selected sub itens */
+ foreach (MenuItem subitem in item.MenuItems)
+ if (subitem.Selected)
+ DeselectItem (subitem);
+ }
+
+ Menu menu = item.Parent;
+ menu.InvalidateItem (item);
+ }
+
+ void SelectItem (Menu menu, MenuItem item, bool execute)
+ {
+ MenuItem prev_item = CurrentMenu.SelectedItem;
+
+ if (prev_item != item.Parent) {
+ DeselectItem (prev_item);
+ if ((CurrentMenu != menu) && (prev_item.Parent != item) && (prev_item.Parent is MenuItem)) {
+ DeselectItem (prev_item.Parent as MenuItem);
+ }
+ }
+
+ if (CurrentMenu != menu)
+ CurrentMenu = menu;
+
+ item.Selected = true;
+ menu.InvalidateItem (item);
+
+ if (((CurrentMenu == TopMenu) && execute) || ((CurrentMenu != TopMenu) && popup_active))
+ item.PerformSelect ();
+
+ if ((execute) && ((prev_item == null) || (item != prev_item.Parent)))
+ ExecFocusedItem (menu, item);
+ }
+
+ // Used when the user executes the action of an item (press enter, shortcut)
+ // or a sub-popup menu has to be shown
+ void ExecFocusedItem (Menu menu, MenuItem item)
+ {
+ if (item == null)
+ return;
+
+ if (!item.Enabled)
+ return;
+
+ if (item.IsPopup) {
+ ShowSubPopup (menu, item);
+ } else {
+ Deactivate ();
+ item.PerformClick ();
+ }
+ }
+
+ // Create a popup window and show it or only show it if it is already created
+ void ShowSubPopup (Menu menu, MenuItem item)
+ {
+ if (item.Enabled == false)
+ return;
+
+ if (!popdown_menu || !item.VisibleItems)
+ item.PerformPopup ();
+
+ if (item.VisibleItems == false)
+ return;
+
+ if (item.Wnd != null) {
+ item.Wnd.Dispose ();
+ }
+
+ popup_active = true;
+ PopUpWindow puw = new PopUpWindow (GrabControl, item);
+
+ Point pnt;
+ if (menu is MainMenu)
+ pnt = new Point (item.X, item.Y + item.Height - 2 - menu.Height);
+ else
+ pnt = new Point (item.X + item.Width - 3, item.Y - 3);
+ pnt = menu.Wnd.PointToScreen (pnt);
+ puw.Location = pnt;
+ item.Wnd = puw;
+
+ puw.ShowWindow ();
+ }
+
+ static public void HideSubPopups (Menu menu, Menu topmenu)
+ {
+ foreach (MenuItem item in menu.MenuItems)
+ if (item.IsPopup)
+ HideSubPopups (item, null);
+
+ if (menu.Wnd == null)
+ return;
+
+ PopUpWindow puw = menu.Wnd as PopUpWindow;
+ if (puw != null) {
+ puw.Hide ();
+ puw.Dispose ();
+ }
+ menu.Wnd = null;
+
+ if ((topmenu != null) && (topmenu is MainMenu))
+ ((MainMenu) topmenu).OnCollapse (EventArgs.Empty);
+ }
+
+ MenuItem FindSubItemByCoord (Menu menu, Point pnt)
+ {
+ foreach (MenuItem item in menu.MenuItems) {
+
+ if (item.IsPopup && item.Wnd != null && item.Wnd.Visible && item == menu.SelectedItem) {
+ MenuItem result = FindSubItemByCoord (item, pnt);
+ if (result != null)
+ return result;
+ }
+
+ if (menu.Wnd == null || !menu.Wnd.Visible)
+ continue;
+
+ Rectangle rect = item.bounds;
+ Point pnt_client = menu.Wnd.PointToScreen (new Point (item.X, item.Y));
+ rect.X = pnt_client.X;
+ rect.Y = pnt_client.Y;
+
+ if (rect.Contains (pnt) == true)
+ return item;
+ }
+
+ return null;
+ }
+
+ static MenuItem FindItemByKey (Menu menu, IntPtr key)
+ {
+ char key_char = Char.ToUpper ((char) (key.ToInt32() & 0xff));
+ foreach (MenuItem item in menu.MenuItems) {
+ if (item.Mnemonic == key_char)
+ return item;
+ }
+
+ string key_str = key_char.ToString ();
+ foreach (MenuItem item in menu.MenuItems) {
+ //if (item.Mnemonic == key_char)
+ if (item.Text.StartsWith (key_str))
+ return item;
+ }
+
+ return null;
+ }
+
+ enum ItemNavigation {
+ First,
+ Last,
+ Next,
+ Previous,
+ }
+
+ static MenuItem GetNextItem (Menu menu, ItemNavigation navigation)
+ {
+ int pos = 0;
+ bool selectable_items = false;
+ MenuItem item;
+
+ // Check if there is at least a selectable item
+ for (int i = 0; i < menu.MenuItems.Count; i++) {
+ item = menu.MenuItems [i];
+ if (item.Separator == false && item.Visible == true) {
+ selectable_items = true;
+ break;
+ }
+ }
+
+ if (selectable_items == false)
+ return null;
+
+ switch (navigation) {
+ case ItemNavigation.First:
+
+ /* First item that is not separator and it is visible*/
+ for (pos = 0; pos < menu.MenuItems.Count; pos++) {
+ item = menu.MenuItems [pos];
+ if (item.Separator == false && item.Visible == true)
+ break;
+ }
+
+ break;
+
+ case ItemNavigation.Last: // Not used
+ break;
+
+ case ItemNavigation.Next:
+
+ pos = menu.SelectedItem == null ? - 1 : menu.SelectedItem.Index;
+
+ /* Next item that is not separator and it is visible*/
+ for (pos++; pos < menu.MenuItems.Count; pos++) {
+ item = menu.MenuItems [pos];
+ if (item.Separator == false && item.Visible == true)
+ break;
+ }
+
+ if (pos >= menu.MenuItems.Count) { /* Jump at the start of the menu */
+ pos = 0;
+ /* Next item that is not separator and it is visible*/
+ for (; pos < menu.MenuItems.Count; pos++) {
+ item = menu.MenuItems [pos];
+ if (item.Separator == false && item.Visible == true)
+ break;
+ }
+ }
+ break;
+
+ case ItemNavigation.Previous:
+
+ if (menu.SelectedItem != null)
+ pos = menu.SelectedItem.Index;
+
+ /* Previous item that is not separator and it is visible*/
+ for (pos--; pos >= 0; pos--) {
+ item = menu.MenuItems [pos];
+ if (item.Separator == false && item.Visible == true)
+ break;
+ }
+
+ if (pos < 0 ) { /* Jump at the end of the menu*/
+ pos = menu.MenuItems.Count - 1;
+ /* Previous item that is not separator and it is visible*/
+ for (; pos >= 0; pos--) {
+ item = menu.MenuItems [pos];
+ if (item.Separator == false && item.Visible == true)
+ break;
+ }
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ return menu.MenuItems [pos];
+ }
+
+ void ProcessMenuKey (Msg msg_type)
+ {
+ if (TopMenu.MenuItems.Count == 0)
+ return;
+
+ MainMenu main_menu = TopMenu as MainMenu;
+
+ switch (msg_type) {
+ case Msg.WM_SYSKEYDOWN:
+ switch (keynav_state) {
+ case KeyNavState.Idle:
+ keynav_state = KeyNavState.Startup;
+ hotkey_active = true;
+ GrabControl.ActiveTracker = this;
+ CurrentMenu = TopMenu;
+ main_menu.Draw ();
+ break;
+ case KeyNavState.Startup:
+ break;
+ default:
+ Deactivate ();
+ main_menu.Draw ();
+ break;
+ }
+ break;
+
+ case Msg.WM_SYSKEYUP:
+ switch (keynav_state) {
+ case KeyNavState.Idle:
+ case KeyNavState.Navigating:
+ break;
+ case KeyNavState.Startup:
+ keynav_state = KeyNavState.NoPopups;
+ SelectItem (TopMenu, TopMenu.MenuItems [0], false);
+ break;
+ default:
+ Deactivate ();
+ main_menu.Draw ();
+ break;
+ }
+ break;
+ }
+ }
+
+ bool ProcessMnemonic (Message msg, Keys key_data)
+ {
+ keynav_state = KeyNavState.Navigating;
+ MenuItem item = FindItemByKey (CurrentMenu, msg.WParam);
+ if ((item == null) || (GrabControl == null) || (GrabControl.ActiveTracker == null))
+ return false;
+
+ active = true;
+ GrabControl.ActiveTracker = this;
+
+ SelectItem (CurrentMenu, item, true);
+ if (item.IsPopup) {
+ CurrentMenu = item;
+ SelectItem (item, item.MenuItems [0], false);
+ }
+ return true;
+ }
+
+ Hashtable shortcuts = new Hashtable ();
+
+ public void AddShortcuts (MenuItem item)
+ {
+ foreach (MenuItem child in item.MenuItems) {
+ AddShortcuts (child);
+ if (child.Shortcut != Shortcut.None)
+ shortcuts [(int)child.Shortcut] = child;
+ }
+
+ if (item.Shortcut != Shortcut.None)
+ shortcuts [(int)item.Shortcut] = item;
+ }
+
+ public void RemoveShortcuts (MenuItem item)
+ {
+ foreach (MenuItem child in item.MenuItems) {
+ RemoveShortcuts (child);
+ if (child.Shortcut != Shortcut.None)
+ shortcuts.Remove ((int)child.Shortcut);
+ }
+
+ if (item.Shortcut != Shortcut.None)
+ shortcuts.Remove ((int)item.Shortcut);
+ }
+
+ bool ProcessShortcut (Keys keyData)
+ {
+ MenuItem item = shortcuts [(int)keyData] as MenuItem;
+ if (item == null || !item.Enabled)
+ return false;
+
+ if (active)
+ Deactivate ();
+ item.PerformClick ();
+ return true;
+ }
+
+ public bool ProcessKeys (ref Message msg, Keys keyData)
+ {
+ // We should process Alt+key only if we don't have an active menu,
+ // and hide it otherwise.
+ if ((keyData & Keys.Alt) == Keys.Alt && active) {
+ Deactivate ();
+ return false;
+ }
+
+ // If we get Alt-F4, Windows will ignore it because we have a capture,
+ // release the capture and the program will exit. (X11 doesn't care.)
+ if ((keyData & Keys.Alt) == Keys.Alt && (keyData & Keys.F4) == Keys.F4) {
+ if (GrabControl != null)
+ GrabControl.ActiveTracker = null;
+
+ return false;
+ }
+
+ if ((Msg)msg.Msg != Msg.WM_SYSKEYUP && ProcessShortcut (keyData))
+ return true;
+ else if ((keyData & Keys.KeyCode) == Keys.Menu && TopMenu is MainMenu) {
+ ProcessMenuKey ((Msg) msg.Msg);
+ return true;
+ } else if ((keyData & Keys.Alt) == Keys.Alt)
+ return ProcessMnemonic (msg, keyData);
+ else if ((Msg)msg.Msg == Msg.WM_SYSKEYUP)
+ return false;
+ else if (!Navigating)
+ return false;
+
+ MenuItem item;
+
+ switch (keyData) {
+ case Keys.Up:
+ if (CurrentMenu is MainMenu)
+ return true;
+ else if (CurrentMenu.MenuItems.Count == 1 && CurrentMenu.parent_menu == TopMenu) {
+ DeselectItem (CurrentMenu.SelectedItem);
+ CurrentMenu = TopMenu;
+ return true;
+ }
+ item = GetNextItem (CurrentMenu, ItemNavigation.Previous);
+ if (item != null)
+ SelectItem (CurrentMenu, item, false);
+ break;
+
+ case Keys.Down:
+ if (CurrentMenu is MainMenu) {
+ if (CurrentMenu.SelectedItem != null && CurrentMenu.SelectedItem.IsPopup) {
+ keynav_state = KeyNavState.Navigating;
+ item = CurrentMenu.SelectedItem;
+ ShowSubPopup (CurrentMenu, item);
+ SelectItem (item, item.MenuItems [0], false);
+ CurrentMenu = item;
+ active = true;
+ GrabControl.ActiveTracker = this;
+ }
+ return true;
+ }
+ item = GetNextItem (CurrentMenu, ItemNavigation.Next);
+ if (item != null)
+ SelectItem (CurrentMenu, item, false);
+ break;
+
+ case Keys.Right:
+ if (CurrentMenu is MainMenu) {
+ item = GetNextItem (CurrentMenu, ItemNavigation.Next);
+ bool popup = item.IsPopup && keynav_state != KeyNavState.NoPopups;
+ SelectItem (CurrentMenu, item, popup);
+ if (popup) {
+ SelectItem (item, item.MenuItems [0], false);
+ CurrentMenu = item;
+ }
+ } else if (CurrentMenu.SelectedItem != null && CurrentMenu.SelectedItem.IsPopup) {
+ item = CurrentMenu.SelectedItem;
+ ShowSubPopup (CurrentMenu, item);
+ SelectItem (item, item.MenuItems [0], false);
+ CurrentMenu = item;
+ } else {
+ //Search up for a main menu
+ Menu Prnt = CurrentMenu.parent_menu;
+ while (Prnt != null && !(Prnt is MainMenu)) {
+ Prnt = Prnt.parent_menu;
+ }
+ if (Prnt is MainMenu)
+ {
+ item = GetNextItem(Prnt, ItemNavigation.Next);
+ SelectItem(Prnt, item, item.IsPopup);
+ if (item.IsPopup)
+ {
+ SelectItem(item, item.MenuItems[0], false);
+ CurrentMenu = item;
+ }
+ }
+ }
+ break;
+
+ case Keys.Left:
+ if (CurrentMenu is MainMenu) {
+ item = GetNextItem (CurrentMenu, ItemNavigation.Previous);
+ bool popup = item.IsPopup && keynav_state != KeyNavState.NoPopups;
+ SelectItem (CurrentMenu, item, popup);
+ if (popup) {
+ SelectItem (item, item.MenuItems [0], false);
+ CurrentMenu = item;
+ }
+ } else if (CurrentMenu.parent_menu is MainMenu) {
+ item = GetNextItem (CurrentMenu.parent_menu, ItemNavigation.Previous);
+ SelectItem (CurrentMenu.parent_menu, item, item.IsPopup);
+ if (item.IsPopup) {
+ SelectItem (item, item.MenuItems [0], false);
+ CurrentMenu = item;
+ }
+ }
+ break;
+
+ case Keys.Return:
+ if (CurrentMenu.SelectedItem != null && CurrentMenu.SelectedItem.IsPopup) {
+ keynav_state = KeyNavState.Navigating;
+ item = CurrentMenu.SelectedItem;
+ ShowSubPopup (CurrentMenu, item);
+ SelectItem (item, item.MenuItems [0], false);
+ CurrentMenu = item;
+ active = true;
+ GrabControl.ActiveTracker = this;
+ } else {
+ ExecFocusedItem (CurrentMenu, CurrentMenu.SelectedItem);
+ }
+ break;
+
+ case Keys.Escape:
+ Deactivate ();
+ break;
+
+ default:
+ ProcessMnemonic (msg, keyData);
+ break;
+ }
+
+ return active;
+ }
+ }
+
+ internal class PopUpWindow : Widget
+ {
+ private Menu menu;
+ private Widget form;
+
+ public PopUpWindow (Widget form, Menu menu): base ()
+ {
+ this.menu = menu;
+ this.form = form;
+ SetStyle (Widgetstyles.UserPaint | Widgetstyles.AllPaintingInWmPaint, true);
+ SetStyle (Widgetstyles.ResizeRedraw | Widgetstyles.Opaque, true);
+ is_visible = false;
+ }
+
+ protected override CreateParams CreateParams
+ {
+ get {
+ CreateParams cp = base.CreateParams;
+ cp.Caption = "Menu PopUp";
+ cp.Style = unchecked ((int)(WindowStyles.WS_POPUP));
+ cp.ExStyle |= (int)(WindowExStyles.WS_EX_TOOLWINDOW | WindowExStyles.WS_EX_TOPMOST);
+ return cp;
+ }
+ }
+
+ public void ShowWindow ()
+ {
+ XplatUI.SetCursor(form.Handle, Cursors.Default.handle);
+ RefreshItems ();
+ Show ();
+ }
+
+ internal override void OnPaintInternal (PaintEventArgs args)
+ {
+ ThemeEngine.Current.DrawPopupMenu (args.Graphics, menu, args.ClipRectangle, ClientRectangle);
+ }
+
+ public void HideWindow ()
+ {
+ XplatUI.SetCursor (form.Handle, form.Cursor.handle);
+ MenuTracker.HideSubPopups (menu, null);
+ Hide ();
+ }
+
+ protected override void CreateHandle ()
+ {
+ base.CreateHandle ();
+ RefreshItems ();
+ }
+
+ // Called when the number of items has changed
+ internal void RefreshItems ()
+ {
+ Point pt = new Point (Location.X, Location.Y);
+
+ ThemeEngine.Current.CalcPopupMenuSize (DeviceContext, menu);
+
+ if ((pt.X + menu.Rect.Width) > SystemInformation.VirtualScreen.Width) {
+ if (((pt.X - menu.Rect.Width) > 0) && !(menu.parent_menu is MainMenu))
+ pt.X = pt.X - menu.Rect.Width;
+ else
+ pt.X = SystemInformation.VirtualScreen.Width - menu.Rect.Width;
+
+ if (pt.X < 0)
+ pt.X = 0;
+ }
+ if ((pt.Y + menu.Rect.Height) > SystemInformation.VirtualScreen.Height) {
+ if ((pt.Y - menu.Rect.Height) > 0)
+ pt.Y = pt.Y - menu.Rect.Height;
+ else
+ pt.Y = SystemInformation.VirtualScreen.Height - menu.Rect.Height;
+
+ if (pt.Y < 0)
+ pt.Y = 0;
+ }
+
+ Location = pt;
+ Width = menu.Rect.Width;
+ Height = menu.Rect.Height;
+ }
+
+ internal override bool ActivateOnShow { get { return false; } }
+ }
+}
+
+