acdream/src/AcDream.App/UI/UiMarkupToggle.cs

75 lines
2.5 KiB
C#

using System.Numerics;
namespace AcDream.App.UI;
/// <summary>
/// KSML boolean toggle with the compact lamp-and-caption presentation used by
/// VTank. State and action remain reflected BCL bindings owned by the plugin.
/// </summary>
public sealed class UiMarkupToggle : UiElement
{
private static readonly Vector4 CheckedOuter =
new(0.36f, 0.58f, 0.12f, 1f);
private static readonly Vector4 CheckedInner =
new(0.52f, 1f, 0.08f, 1f);
private static readonly Vector4 UncheckedOuter =
new(0.26f, 0.22f, 0.13f, 1f);
private static readonly Vector4 UncheckedInner =
new(0.38f, 0.34f, 0.23f, 1f);
public string Text { get; set; } = string.Empty;
public Func<string?>? TextSource { get; set; }
public Func<bool>? CheckedSource { get; set; }
public UiDatFont? DatFont { get; set; }
public Vector4 TextColor { get; set; } =
new(0.86f, 0.84f, 0.74f, 1f);
public Action? Toggle { get; set; }
public bool IsChecked => CheckedSource?.Invoke() ?? false;
public override bool HandlesClick => true;
public override bool OnEvent(in UiEvent e)
{
if (e.Type != UiEventType.Click || !Enabled)
return false;
Toggle?.Invoke();
return true;
}
protected override void OnDraw(UiRenderContext ctx)
{
Vector4 outer = IsChecked ? CheckedOuter : UncheckedOuter;
Vector4 inner = IsChecked ? CheckedInner : UncheckedInner;
DrawLamp(ctx, 1f, MathF.Max(1f, (Height - 11f) * 0.5f), outer, inner);
string caption = TextSource?.Invoke() ?? Text;
Vector4 color = Enabled
? TextColor
: new Vector4(TextColor.X, TextColor.Y, TextColor.Z, 0.42f);
float y = DatFont is { } font
? (Height - font.LineHeight) * 0.5f
: 1f;
if (DatFont is { } dat)
ctx.DrawStringDat(dat, caption, 17f, y, color, outline: true);
else
ctx.DrawString(caption, 17f, y, color);
}
private static void DrawLamp(
UiRenderContext ctx,
float x,
float y,
Vector4 outer,
Vector4 inner)
{
// Five bands form the small circular indicator without introducing a
// plugin bitmap or a new renderer primitive.
ctx.DrawFill(x + 3f, y, 5f, 1f, outer);
ctx.DrawFill(x + 1f, y + 1f, 9f, 2f, outer);
ctx.DrawFill(x, y + 3f, 11f, 5f, outer);
ctx.DrawFill(x + 1f, y + 8f, 9f, 2f, outer);
ctx.DrawFill(x + 3f, y + 10f, 5f, 1f, outer);
ctx.DrawFill(x + 3f, y + 3f, 5f, 5f, inner);
}
}