Ui/ContextMenu.razor
@using System
@using Clover.Data
@using Sandbox;
@using Sandbox.UI;
@inherits Panel
@namespace Clover.Ui
<root>
<div class="context-background" @onclick=@Close @onmousedown=@Close @onrightclick=@Close>
</div>
<div class="context-menu" style="left: @Position.x; top: @Position.y;" @ref="Content">
<div class="context-menu-title">@Title</div>
@foreach ( var item in _items )
{
<button @onclick=@( () => item.Action() )>
@if ( !string.IsNullOrEmpty( item.Icon ) )
{
<i class="icon">@item.Icon</i>
}
else if ( !string.IsNullOrEmpty( item.Image ) )
{
<img src="@item.Image" />
}
<span>@item.Text</span>
</button>
}
</div>
</root>
@code {
public Panel _sourcePanel;
public Vector2 Position { get; set; }
public Panel Content { get; set; }
public string Title { get; set; }
public struct ContextMenuItem
{
public string Text;
public string Icon;
public string Image;
public Action Action;
public ContextMenuItem( string text, string icon, Action action )
{
Text = text;
Icon = icon;
Image = null;
Action = action;
}
}
private List<ContextMenuItem> _items = new List<ContextMenuItem>();
public void Close( PanelEvent e )
{
e.StopPropagation();
Delete();
}
public ContextMenu()
{
}
public ContextMenu( Panel sourcePanel, Vector2 position )
{
_sourcePanel = sourcePanel;
Position = position;
sourcePanel.FindRootPanel().AddChild( this );
Sound.Play( "sounds/ui/menu_open.sound" );
}
public void AddItem( string text, Action action )
{
_items.Add( new ContextMenuItem()
{
Text = text,
Action = action
} );
}
public void AddItem( string text, string icon, Action action )
{
_items.Add( new ContextMenuItem()
{
Text = text,
Icon = icon,
Action = action
} );
}
public override void Tick()
{
base.Tick();
if ( !_sourcePanel.IsValid() )
{
Delete();
}
var margin = 20;
var screenSize = Screen.Size * ScaleFromScreen;
var size = Content.Box.Rect.Size * ScaleFromScreen;
if ( Position.x + size.x > screenSize.x )
{
Position = new Vector2( screenSize.x - size.x - margin, Position.y );
}
if ( Position.y + size.y > screenSize.y )
{
Position = new Vector2( Position.x, screenSize.y - size.y - margin );
}
if ( Position.x < margin )
{
Position = new Vector2( margin, Position.y );
}
if ( Position.y < margin )
{
Position = new Vector2( Position.x, margin );
}
}
public override void Delete( bool immediate = false )
{
base.Delete( immediate );
Sound.Play( "sounds/ui/menu_close.sound" );
}
}