Editor/SmartEnumControlWidget.cs
using Editor;
using Sandbox;
using System;
using System.Linq;
namespace SmarterEnum;
[CustomEditor(typeof(SmartEnum))]
public class SmartEnumControlWidget : ControlWidget
{
private PopupWidget? _menu;
public override bool IsControlActive => base.IsControlActive || _menu.IsValid();
public override bool IsControlButton => true;
public override bool IsControlHovered => base.IsControlHovered || _menu.IsValid();
public override bool SupportsMultiEdit => false;
public SmartEnumControlWidget(SerializedProperty property)
: base(property)
{
Cursor = CursorShape.Finger;
base.Layout = Layout.Row();
base.Layout.Spacing = 2f;
var value = SerializedProperty.GetValue<object>();
if(value is null && !SerializedProperty.IsNullable)
SerializedProperty.SetValue(SmartEnum.GetValues(SerializedProperty.PropertyType).FirstOrDefault());
}
protected override void PaintControl()
{
Color color = (IsControlHovered ? Theme.Blue : Theme.TextControl);
if(IsControlDisabled)
color = color.WithAlpha(0.5f);
Rect localRect = LocalRect;
localRect = localRect.Shrink(8f, 0f);
var name = SerializedProperty.GetValue<SmartEnum>()?.Name;
Paint.SetPen(in color, 0f, PenStyle.Solid);
Paint.DrawText(in localRect, name ?? "Unset", TextFlag.LeftCenter);
Paint.SetPen(in color, 0f, PenStyle.Solid);
Paint.DrawIcon(localRect, "Arrow_Drop_Down", 17f, TextFlag.RightCenter);
}
public override void StartEditing()
{
if(!IsControlDisabled && !_menu.IsValid())
OpenMenu();
}
protected override void OnMouseClick(MouseEvent e)
{
if(!IsControlDisabled && e.LeftMouseButton && !_menu.IsValid())
OpenMenu();
}
protected override void OnDoubleClick(MouseEvent e)
{
}
private SmartEnum? Parse(string name)
{
SmartEnum.TryFromName(SerializedProperty.PropertyType, name, false, out var result);
return result;
}
private bool IsCurrent(string name)
{
var value = SerializedProperty.GetValue<object>();
return object.Equals(value, Parse(name));
}
private void SetValue(string name)
{
SerializedProperty.SetValue(Parse(name) ?? SmartEnum.GetValues(SerializedProperty.PropertyType).First());
}
private void OpenMenu()
{
PropertyStartEdit();
_menu = new PopupWidget(null)
{
Layout = Layout.Column(),
MinimumWidth = base.ScreenRect.Width
};
_menu.OnLostFocus = (Action)Delegate.Combine(_menu.OnLostFocus, new Action(base.PropertyFinishEdit));
foreach(var name in SmartEnum.GetValues(SerializedProperty.PropertyType).Select(v => v.Name))
{
var button = _menu.Layout.Add(new Widget(_menu));
button.MinimumSize = 22;
button.MouseLeftPress = () =>
{
SetValue(name);
_menu.Update();
_menu.Close();
};
button.OnPaintOverride = () => PaintOption(button.LocalRect, name);
}
_menu.Position = base.ScreenRect.BottomLeft;
_menu.Visible = true;
_menu.AdjustSize();
_menu.ConstrainToScreen();
_menu.OnPaintOverride = PaintMenuBackground;
}
private bool PaintMenuBackground()
{
Paint.SetBrushAndPen(Theme.ControlBackground);
Rect rect = Paint.LocalRect;
Paint.DrawRect(in rect, 0f);
return true;
}
private bool PaintOption(Rect rect, string e)
{
var active = IsCurrent(e);
if(Paint.HasMouseOver)
{
Paint.ClearPen();
Paint.SetBrush(Theme.Blue.WithAlpha(0.5f));
Paint.DrawRect(rect.Shrink(3, 0), 0);
Paint.SetPen(Theme.Text);
}
else
{
Paint.SetPen(active ? Theme.Text : Theme.TextControl); // TODO
}
rect = rect.Shrink(8, 0);
if(active)
Paint.DrawIcon(rect, "check", 13, TextFlag.LeftCenter);
rect = rect.Shrink(24, 0, 0, 0);
Paint.SetDefaultFont(8, active ? 1000 : 400);
Paint.DrawText(rect, e, TextFlag.LeftCenter);
return true;
}
}