Editor/ChitChat/CustomWidgets/BaseDropdown.cs
using System;
using Sandbox;
using Editor;
using System.Collections.Generic;
using System.Linq;
namespace ChitChat.Editor;
public abstract class BaseDropdown : Widget
{
public Action<int> onItemSelected;
private int _currentSelected;
private PopupWidget _menu;
protected abstract IEnumerable<string> GetDropdownValues();
public BaseDropdown(int firstSelected, Widget parent) : base(parent)
{
_currentSelected = firstSelected;
}
public void UpdateSelected(int selected) => _currentSelected = selected;
protected override void OnPaint()
{
var color = IsUnderMouse ? Theme.Blue : Theme.TextControl;
var rect = LocalRect;
rect = rect.Shrink(8, 0);
Paint.SetBrushAndPen(Theme.ControlBackground);
Paint.DrawRect(LocalRect, 2);
Paint.SetPen(color);
Paint.SetDefaultFont();
IEnumerable<string> strings = GetDropdownValues();
if(strings.Any() && _currentSelected <= strings.Count())
Paint.DrawText(rect.Shrink(new Sandbox.UI.Margin(0, 0, 23, 0)), GetDropdownValues().Skip(_currentSelected).First(), TextFlag.LeftCenter);
else
Paint.DrawText(rect, "None", TextFlag.LeftCenter);
Paint.SetPen(color);
Paint.DrawIcon(rect, "Arrow_Drop_Down", 17, TextFlag.RightCenter);
}
protected override void OnMouseClick(MouseEvent e)
{
if (e.LeftMouseButton && !_menu.IsValid())
{
OpenMenu();
}
}
protected override void OnDoubleClick(MouseEvent e)
{
// nothing
}
void OpenMenu()
{
string[] entries = GetDropdownValues().ToArray();
if(_currentSelected > entries.Length - 1)
_currentSelected = 0;
if(entries.Length == 0) return;
_menu = new PopupWidget(null);
_menu.Layout = Layout.Column();
_menu.Width = ScreenRect.Width;
ScrollArea scroller = _menu.Layout.Add(new ScrollArea(this), 1);
scroller.MaximumWidth = LocalRect.Width;
scroller.HorizontalScrollbarMode = ScrollbarMode.Off;
scroller.Canvas = new Widget(scroller)
{
Layout = Layout.Column(),
VerticalSizeMode = SizeMode.CanGrow | SizeMode.Expand,
MaximumWidth = entries.Length > 10 ? LocalRect.Width - 11 : LocalRect.Width - 1
};
scroller.Canvas.Layout.Alignment = TextFlag.LeftTop;
for (int i = 0; i < entries.Length; i++)
{
var b = scroller.Canvas.Layout.Add(new MenuOption(entries[i], i, i == _currentSelected));
b.SetSizeMode(SizeMode.Expand, SizeMode.Default);
b.onMenuOptionSelected += OnMenuOptionSelected;
}
_menu.Position = ScreenRect.BottomLeft;
_menu.Visible = true;
_menu.AdjustSize();
_menu.ConstrainToScreen();
_menu.OnPaintOverride = PaintMenuBackground;
}
private void OnMenuOptionSelected(int index)
{
_currentSelected = index;
onItemSelected?.Invoke(index);
_menu.Update();
_menu.Close();
}
bool PaintMenuBackground()
{
Paint.SetBrushAndPen(Theme.ControlBackground);
Paint.DrawRect(Paint.LocalRect, 0);
return true;
}
private class MenuOption : Widget
{
public Action<int> onMenuOptionSelected;
private string _name;
private int _index;
private bool _selected;
public MenuOption(string name, int index, bool selected) : base(null)
{
if(string.IsNullOrEmpty(name))
_name = "Unnamed";
else
_name = name;
_index = index;
_selected = selected;
MaximumHeight = 30;
Layout = Layout.Row();
Layout.Margin = new Sandbox.UI.Margin(30, 9, 8, 8);
Layout.AddSpacingCell(8);
Layout c = Layout.AddRow();
Label title = c.Add(new Label(name));
title.SetStyles("font-size: 12px; font-weight: bold; font-family: Poppins; color: white;");
}
protected override void OnMouseClick(MouseEvent e)
{
base.OnMouseClick(e);
onMenuOptionSelected?.Invoke(_index);
}
protected override void OnPaint()
{
Rect iconRect = new Rect(LocalRect.TopLeft.x + 10, LocalRect.Center.y - 10, 20, 20);
if(_selected)
Paint.DrawIcon(iconRect, "check", 20);
else
Paint.DrawIcon(iconRect, "close", 20);
if (Paint.HasMouseOver)
{
Paint.SetBrushAndPen(Theme.Blue.WithAlpha(0.3f));
Paint.DrawRect(LocalRect.Shrink(2), 2);
}
else
{
if (_selected)
{
Paint.SetBrushAndPen(new Color(0.19f, 0.66f, 0.32f, 0.3f));
Paint.DrawRect(LocalRect.Shrink(2), 2);
}
else
{
Paint.SetBrushAndPen(new Color(0.66f, 0.2f, 0.2f, 0.3f));
Paint.DrawRect(LocalRect.Shrink(2), 2);
}
}
}
}
}