// 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.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); } } } }