namespace Perspex.Controls
{
using Input;
using Interactivity;
using LogicalTree;
using Primitives;
using System;
using System.Reactive.Linq;
public class ContextMenu : SelectingItemsControl
{
private bool _isOpen;
///
/// Defines the ContextMenu.Menu attached property.
///
//public static readonly AttachedProperty ContextMenuProperty =
// PerspexProperty.RegisterAttached("Menu");
///
/// The popup window used to display the active context menu.
///
private static PopupRoot s_popup;
///
/// The control that the currently visible context menu is attached to.
///
private static Control s_current;
///
/// Initializes static members of the class.
///
static ContextMenu()
{
ContextMenuProperty.Changed.Subscribe(ContextMenuChanged);
MenuItem.ClickEvent.AddClassHandler(x => x.OnContextMenuClick);
}
///
/// Gets the value of the ToolTip.Tip attached property.
///
/// The control to get the property from.
///
/// The content to be displayed in the control's tooltip.
///
public static object GetContextMenu(Control element)
{
return element.GetValue(ContextMenuProperty);
}
///
/// Sets the value of the ToolTip.Tip attached property.
///
/// The control to get the property from.
/// The content to be displayed in the control's tooltip.
public static void SetContextMenu(Control element, object value)
{
element.SetValue(ContextMenuProperty, value);
}
///
/// called when the property changes on a control.
///
/// The event args.
private static void ContextMenuChanged(PerspexPropertyChangedEventArgs e)
{
var control = (Control)e.Sender;
if (e.OldValue != null)
{
control.PointerReleased -= ControlPointerReleased;
}
if (e.NewValue != null)
{
control.PointerReleased += ControlPointerReleased;
}
}
///
/// Called when a submenu is clicked somewhere in the menu.
///
/// The event args.
private void OnContextMenuClick(RoutedEventArgs e)
{
Hide();
FocusManager.Instance.Focus(null);
e.Handled = true;
}
///
/// Closes the menu.
///
public void Hide()
{
foreach (MenuItem i in this.GetLogicalChildren())
{
i.IsSubMenuOpen = false;
}
if (s_popup != null && s_popup.IsVisible)
{
s_popup.Hide();
}
SelectedIndex = -1;
_isOpen = false;
}
///
/// Shows a tooltip for the specified control.
///
/// The control.
private static void Show(Control control)
{
if (control != null)
{
if (s_popup == null)
{
s_popup = new PopupRoot
{
Content = new ToolTip(),
};
((ISetLogicalParent)s_popup).SetParent(control);
}
var cp = MouseDevice.Instance?.GetPosition(control);
var position = control.PointToScreen(cp ?? new Point(0, 0));
((ToolTip)s_popup.Content).Content = GetContextMenu(control);
s_popup.Position = position;
s_popup.Show();
s_current = control;
control.ContextMenu._isOpen = true;
}
}
private static void ControlPointerReleased(object sender, PointerReleasedEventArgs e)
{
var control = (Control)sender;
if (e.MouseButton == MouseButton.Right)
{
if(control.ContextMenu._isOpen)
{
control.ContextMenu.Hide();
}
Show(control);
}
else
{
control.ContextMenu.Hide();
}
}
}
}