// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.GUI.ContextMenu
{
///
/// Context Menu button control.
///
///
[HideInEditor]
public class ContextMenuButton : ContextMenuItem
{
private bool _isMouseDown;
///
/// Event fired when user clicks on the button.
///
public event Action Clicked;
///
/// Event fired when user clicks on the button.
///
public event Action ButtonClicked;
///
/// The button text.
///
public string Text;
///
/// The button short keys information (eg. 'Ctrl+C').
///
public string ShortKeys;
///
/// Item icon (best is 16x16).
///
public SpriteHandle Icon;
///
/// The checked state.
///
public bool Checked;
///
/// The automatic check mode.
///
public bool AutoCheck;
///
/// Closes the context menu after clicking the button, otherwise menu will stay open.
///
public bool CloseMenuOnClick = true;
///
/// Initializes a new instance of the class.
///
/// The parent context menu.
/// The text.
/// The short keys tip.
public ContextMenuButton(ContextMenu parent, string text, string shortKeys = "")
: base(parent, 8, 22)
{
Text = text;
ShortKeys = shortKeys;
}
///
/// Sets the automatic check mode. In auto check mode the button sets the check sprite as an icon when user clicks it.
///
/// True if use auto check, otherwise false.
/// This button.
public ContextMenuButton SetAutoCheck(bool value)
{
AutoCheck = value;
return this;
}
///
/// Sets the checked state.
///
/// True if check it, otherwise false.
/// This button.
public ContextMenuButton SetChecked(bool value)
{
Checked = value;
return this;
}
///
/// Clicks this button.
///
public void Click()
{
if (CloseMenuOnClick)
{
// Close topmost context menu
ParentContextMenu?.TopmostCM.Hide();
}
// Auto check logic
if (AutoCheck)
Checked = !Checked;
// Fire event
Clicked?.Invoke();
ButtonClicked?.Invoke(this);
ParentContextMenu?.OnButtonClicked(this);
}
///
public override void Draw()
{
var style = Style.Current;
var backgroundRect = new Rectangle(-X + 3, 0, Parent.Width - 6, Height);
var textRect = new Rectangle(0, 0, Width - 8, Height);
var textColor = Enabled ? style.Foreground : style.ForegroundDisabled;
// Draw background
if (IsMouseOver && Enabled)
Render2D.FillRectangle(backgroundRect, style.LightBackground);
else if (IsFocused)
Render2D.FillRectangle(backgroundRect, style.LightBackground);
base.Draw();
// Draw text
Render2D.DrawText(style.FontMedium, Text, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
if (!string.IsNullOrEmpty(ShortKeys))
{
// Draw short keys
Render2D.DrawText(style.FontMedium, ShortKeys, textRect, textColor, TextAlignment.Far, TextAlignment.Center);
}
// Draw icon
const float iconSize = 14;
var icon = Checked ? Style.Current.CheckBoxTick : Icon;
if (icon.IsValid)
Render2D.DrawSprite(icon, new Rectangle(-iconSize - 1, (Height - iconSize) / 2, iconSize, iconSize), textColor);
}
///
public override void OnMouseLeave()
{
_isMouseDown = false;
base.OnMouseLeave();
}
///
public override bool OnMouseDown(Float2 location, MouseButton button)
{
if (base.OnMouseDown(location, button))
return true;
_isMouseDown = true;
return true;
}
///
public override bool OnMouseUp(Float2 location, MouseButton button)
{
if (base.OnMouseUp(location, button))
return true;
if (_isMouseDown)
{
_isMouseDown = false;
Click();
return true;
}
return false;
}
///
public override bool OnKeyDown(KeyboardKeys key)
{
if (base.OnKeyDown(key))
return true;
switch (key)
{
case KeyboardKeys.ArrowUp:
for (int i = IndexInParent - 1; i >= 0; i--)
{
if (ParentContextMenu.ItemsContainer.Children[i] is ContextMenuButton item && item.Visible && item.Enabled)
{
item.Focus();
ParentContextMenu.ItemsContainer.ScrollViewTo(item);
return true;
}
}
break;
case KeyboardKeys.ArrowDown:
for (int i = IndexInParent + 1; i < ParentContextMenu.ItemsContainer.Children.Count; i++)
{
if (ParentContextMenu.ItemsContainer.Children[i] is ContextMenuButton item && item.Visible && item.Enabled)
{
item.Focus();
ParentContextMenu.ItemsContainer.ScrollViewTo(item);
return true;
}
}
break;
case KeyboardKeys.Return:
Click();
return true;
case KeyboardKeys.Escape:
ParentContextMenu.Hide();
return true;
}
return false;
}
///
public override void OnLostFocus()
{
_isMouseDown = false;
base.OnLostFocus();
}
///
public override float MinimumWidth
{
get
{
var style = Style.Current;
float width = 20;
if (style.FontMedium)
{
width += style.FontMedium.MeasureText(Text).X;
if (!string.IsNullOrEmpty(ShortKeys))
width += 40 + style.FontMedium.MeasureText(ShortKeys).X;
}
return Mathf.Max(width, base.MinimumWidth);
}
}
}
}