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" );
	}

}