A set of fluent builder classes for constructing UI menu widgets and composite menu components. Each builder holds a widget instance, exposes configuration methods (with chaining), and ends by adding the configured widget to a MenuScreenBuilder.
namespace Sunless.Libraries.UI;
using System;
using System.Collections.Generic;
public sealed class MenuLinkBuilder
{
readonly MenuScreenBuilder _screen;
readonly MenuLinkWidget _w;
internal MenuLinkBuilder( MenuScreenBuilder screen, string label, string icon )
{
_screen = screen;
_w = new MenuLinkWidget { Label = label, Icon = icon, Style = MenuLinkStyle.Row };
}
public MenuLinkBuilder WithStyle( MenuLinkStyle style ) { _w.Style = style; return this; }
public MenuLinkBuilder WithTone( MenuTone tone ) { _w.Tone = tone; return this; }
public MenuLinkBuilder WithHint( string hint ) { _w.Hint = hint; return this; }
public MenuLinkBuilder WhenEnabled( Func<bool> enabled ) { _w.Enabled = enabled; return this; }
public MenuLinkBuilder WithGoTo( string routeId ) { _w.RouteId = routeId; return this; }
public MenuLinkBuilder WithAction( Action invoke ) { _w.Invoke = invoke; return this; }
public MenuLinkBuilder Grows() { _w.Grow = true; return this; }
public MenuScreenBuilder EndLink()
{
_screen.AddWidget( _w );
return _screen;
}
}
public sealed class MenuToggleBuilder
{
readonly MenuScreenBuilder _screen;
readonly MenuToggleWidget _w;
internal MenuToggleBuilder( MenuScreenBuilder screen, string label )
{
_screen = screen;
_w = new MenuToggleWidget { Label = label };
}
public MenuToggleBuilder WithHint( string hint ) { _w.Hint = hint; return this; }
public MenuToggleBuilder WithGetter( Func<bool> get ) { _w.Get = get; return this; }
public MenuToggleBuilder WithSetter( Action<bool> set ) { _w.Set = set; return this; }
public MenuToggleBuilder Bind( Func<bool> get, Action<bool> set )
{
_w.Get = get;
_w.Set = set;
return this;
}
public MenuScreenBuilder EndToggle()
{
_screen.AddWidget( _w );
return _screen;
}
}
public sealed class MenuRangeBuilder
{
readonly MenuScreenBuilder _screen;
readonly MenuRangeWidget _w;
internal MenuRangeBuilder( MenuScreenBuilder screen, string label )
{
_screen = screen;
_w = new MenuRangeWidget { Label = label, Min = 0f, Max = 1f, Step = 0.01f, Format = "0.00" };
}
public MenuRangeBuilder WithHint( string hint ) { _w.Hint = hint; return this; }
public MenuRangeBuilder WithRange( float min, float max ) { _w.Min = min; _w.Max = max; return this; }
public MenuRangeBuilder WithStep( float step ) { _w.Step = step; return this; }
public MenuRangeBuilder WithFormat( string format ) { _w.Format = format; return this; }
public MenuRangeBuilder Bind( Func<float> get, Action<float> set )
{
_w.Get = get;
_w.Set = set;
return this;
}
public MenuScreenBuilder EndRange()
{
_screen.AddWidget( _w );
return _screen;
}
}
public sealed class MenuSegmentedBuilder
{
readonly MenuScreenBuilder _screen;
readonly MenuSegmentedWidget _w;
internal MenuSegmentedBuilder( MenuScreenBuilder screen, string label, string[] choices )
{
_screen = screen;
_w = new MenuSegmentedWidget { Label = label, Choices = choices };
}
public MenuSegmentedBuilder WithHint( string hint ) { _w.Hint = hint; return this; }
public MenuSegmentedBuilder Bind( Func<int> get, Action<int> set )
{
_w.Get = get;
_w.Set = set;
return this;
}
public MenuScreenBuilder EndSegmented()
{
_screen.AddWidget( _w );
return _screen;
}
}
public sealed class MenuRadioBuilder
{
readonly MenuScreenBuilder _screen;
readonly MenuRadioWidget _w;
readonly List<MenuRadioWidget.Option> _options = new();
internal MenuRadioBuilder( MenuScreenBuilder screen, string label )
{
_screen = screen;
_w = new MenuRadioWidget { Label = label };
}
public MenuRadioBuilder WithHint( string hint ) { _w.Hint = hint; return this; }
public MenuRadioBuilder WithOption( string label, string icon = null, string hint = null )
{
_options.Add( new MenuRadioWidget.Option { Label = label, Icon = icon, Hint = hint } );
return this;
}
public MenuRadioBuilder Bind( Func<int> get, Action<int> set )
{
_w.Get = get;
_w.Set = set;
return this;
}
public MenuScreenBuilder EndRadio()
{
_w.Options = _options;
_screen.AddWidget( _w );
return _screen;
}
}
public sealed class MenuInfoBuilder
{
readonly MenuScreenBuilder _screen;
readonly MenuInfoWidget _w;
internal MenuInfoBuilder( MenuScreenBuilder screen, string label )
{
_screen = screen;
_w = new MenuInfoWidget { Label = label };
}
public MenuInfoBuilder WithIcon( string icon ) { _w.Icon = icon; return this; }
public MenuInfoBuilder WithGetter( Func<string> get ) { _w.Get = get; return this; }
public MenuInfoBuilder WithValue( string value ) { _w.Get = () => value; return this; }
public MenuScreenBuilder EndInfo()
{
_screen.AddWidget( _w );
return _screen;
}
}
public sealed class MenuTextFieldBuilder
{
readonly MenuScreenBuilder _screen;
readonly MenuTextFieldWidget _w;
internal MenuTextFieldBuilder( MenuScreenBuilder screen, string label )
{
_screen = screen;
_w = new MenuTextFieldWidget { Label = label };
}
public MenuTextFieldBuilder WithHint( string hint ) { _w.Hint = hint; return this; }
public MenuTextFieldBuilder Bind( Func<string> get, Action<string> set )
{
_w.Get = get;
_w.Set = set;
return this;
}
public MenuScreenBuilder EndTextField()
{
_screen.AddWidget( _w );
return _screen;
}
}
// === Composite widgets ===============================================
public sealed class MenuHeroCardBuilder
{
readonly MenuScreenBuilder _screen;
readonly MenuHeroCardWidget _w = new();
internal MenuHeroCardBuilder( MenuScreenBuilder screen ) { _screen = screen; }
public MenuHeroCardBuilder WithTitle( string title ) { _w.Title = title; return this; }
public MenuHeroCardBuilder WithSubtitle( string subtitle ) { _w.Subtitle = subtitle; return this; }
public MenuHeroCardBuilder WithDescription( string description ) { _w.Description = description; return this; }
public MenuHeroCardBuilder WithImage( string url ) { _w.Image = url; return this; }
public MenuHeroCardBuilder WithIcon( string icon ) { _w.Icon = icon; return this; }
public MenuScreenBuilder EndHeroCard()
{
_screen.AddWidget( _w );
return _screen;
}
}
public sealed class MenuMapCardBuilder
{
readonly MenuScreenBuilder _screen;
readonly MenuMapCardWidget _w = new();
internal MenuMapCardBuilder( MenuScreenBuilder screen ) { _screen = screen; }
public MenuMapCardBuilder WithTitle( string title ) { _w.Title = title; return this; }
public MenuMapCardBuilder WithDescription( string description ) { _w.Description = description; return this; }
public MenuMapCardBuilder WithImage( string url ) { _w.Image = url; return this; }
public MenuMapCardBuilder WithChip( string label, string icon = null, MenuTone tone = MenuTone.Confirm )
{
_w.ChipLabel = label;
_w.ChipIcon = icon;
_w.ChipTone = tone;
return this;
}
public MenuMapCardBuilder WithAction( string label, string icon, Action invoke, string routeId = null )
{
_w.ActionLabel = label;
_w.ActionIcon = icon;
_w.ActionInvoke = invoke;
_w.ActionRouteId = routeId;
return this;
}
public MenuScreenBuilder EndMapCard()
{
_screen.AddWidget( _w );
return _screen;
}
}
public sealed class MenuMapGridBuilder
{
readonly MenuScreenBuilder _screen;
readonly MenuMapGridWidget _w = new();
readonly List<MenuMapGridWidget.Card> _cards = new();
internal MenuMapGridBuilder( MenuScreenBuilder screen ) { _screen = screen; }
public MenuMapGridBuilder WithActive( Func<int> get ) { _w.Active = get; return this; }
public MenuMapGridBuilder OnPick( Action<int> set ) { _w.Pick = set; return this; }
public MenuMapCardCardBuilder WithCard( string title )
=> new( this, title );
internal void AddCard( MenuMapGridWidget.Card card ) => _cards.Add( card );
bool _closed;
public MenuScreenBuilder EndMapGrid()
{
if ( _closed ) return _screen;
_closed = true;
_w.Cards = _cards;
_screen.AddWidget( _w );
return _screen;
}
}
public sealed class MenuMapCardCardBuilder
{
readonly MenuMapGridBuilder _grid;
readonly MenuMapGridWidget.Card _c;
internal MenuMapCardCardBuilder( MenuMapGridBuilder grid, string title )
{
_grid = grid;
_c = new MenuMapGridWidget.Card { Title = title };
}
public MenuMapCardCardBuilder WithDescription( string text ) { _c.Description = text; return this; }
public MenuMapCardCardBuilder WithImage( string url ) { _c.Image = url; return this; }
public MenuMapCardCardBuilder WithBadge( string label, MenuTone tone = MenuTone.Confirm )
{
_c.BadgeLabel = label;
_c.BadgeTone = tone;
return this;
}
public MenuMapCardCardBuilder ComingSoon( bool v = true ) { _c.ComingSoon = v; return this; }
public MenuMapCardCardBuilder Locked( bool v = true ) { _c.Locked = v; return this; }
public MenuMapGridBuilder EndCard()
{
_grid.AddCard( _c );
return _grid;
}
}
public sealed class MenuTileGridBuilder
{
readonly MenuScreenBuilder _screen;
readonly MenuTileGridWidget _w = new();
readonly List<MenuTileGridWidget.Item> _items = new();
internal MenuTileGridBuilder( MenuScreenBuilder screen ) { _screen = screen; }
public MenuTileGridBuilder WithTile( string label, string color = null, string image = null )
{
_items.Add( new MenuTileGridWidget.Item { Label = label, Color = color, Image = image } );
return this;
}
public MenuTileGridBuilder WithActive( Func<int> get ) { _w.Active = get; return this; }
public MenuTileGridBuilder OnPick( Action<int> set ) { _w.Pick = set; return this; }
public MenuScreenBuilder EndTileGrid()
{
_w.Items = _items;
_screen.AddWidget( _w );
return _screen;
}
}
public sealed class MenuPlayerListBuilder
{
readonly MenuScreenBuilder _screen;
readonly MenuPlayerListWidget _w = new();
readonly List<MenuPlayerListWidget.Player> _players = new();
internal MenuPlayerListBuilder( MenuScreenBuilder screen ) { _screen = screen; }
public MenuPlayerListBuilder WithPlayer( string name, bool ready = false, bool host = false )
{
_players.Add( new MenuPlayerListWidget.Player { Name = name, Ready = ready, Host = host } );
return this;
}
public MenuScreenBuilder EndPlayerList()
{
_w.Players = _players;
_screen.AddWidget( _w );
return _screen;
}
}
public sealed class MenuKeyBindingsBuilder
{
readonly MenuScreenBuilder _screen;
readonly MenuKeyBindingsWidget _w = new();
readonly List<MenuKeyBindingsWidget.Binding> _bindings = new();
internal MenuKeyBindingsBuilder( MenuScreenBuilder screen ) { _screen = screen; }
public MenuKeyBindingsBuilder WithBinding( string action, params string[] keys )
{
_bindings.Add( new MenuKeyBindingsWidget.Binding { Action = action, Keys = keys } );
return this;
}
public MenuScreenBuilder EndKeyBindings()
{
_w.Bindings = _bindings;
_screen.AddWidget( _w );
return _screen;
}
}
public sealed class MenuPromptCardBuilder
{
readonly MenuScreenBuilder _screen;
readonly MenuPromptCardWidget _w = new() { Verb = "Press" };
internal MenuPromptCardBuilder( MenuScreenBuilder screen ) { _screen = screen; }
public MenuPromptCardBuilder WithVerb( string verb ) { _w.Verb = verb; return this; }
public MenuPromptCardBuilder WithPrompt( string prompt ) { _w.Prompt = prompt; return this; }
public MenuPromptCardBuilder WithGlyph( string ligature ) { _w.Glyph = ligature; return this; }
public MenuPromptCardBuilder WithCost( int cost ) { _w.Cost = cost; return this; }
public MenuPromptCardBuilder WhenDisabled( Func<bool> d ) { _w.Disabled = d; return this; }
public MenuPromptCardBuilder WithHoldProgress( Func<float> p ) { _w.Progress = p; return this; }
public MenuScreenBuilder EndPromptCard()
{
_screen.AddWidget( _w );
return _screen;
}
}
public sealed class MenuActionRowBuilder
{
readonly MenuScreenBuilder _screen;
readonly MenuActionRowWidget _w = new();
readonly List<MenuLinkWidget> _links = new();
internal MenuActionRowBuilder( MenuScreenBuilder screen ) { _screen = screen; }
public MenuActionRowLinkBuilder WithLink( string label, string icon = null )
=> new( this, label, icon );
internal void AddLink( MenuLinkWidget link ) => _links.Add( link );
public MenuScreenBuilder EndActionRow()
{
_w.Links = _links;
_screen.AddWidget( _w );
return _screen;
}
}
public sealed class MenuActionRowLinkBuilder
{
readonly MenuActionRowBuilder _row;
readonly MenuLinkWidget _w;
internal MenuActionRowLinkBuilder( MenuActionRowBuilder row, string label, string icon )
{
_row = row;
_w = new MenuLinkWidget { Label = label, Icon = icon, Style = MenuLinkStyle.Button };
}
public MenuActionRowLinkBuilder WithTone( MenuTone tone ) { _w.Tone = tone; return this; }
public MenuActionRowLinkBuilder WithGoTo( string routeId ) { _w.RouteId = routeId; return this; }
public MenuActionRowLinkBuilder WithAction( Action invoke ) { _w.Invoke = invoke; return this; }
public MenuActionRowLinkBuilder WhenEnabled( Func<bool> enabled ) { _w.Enabled = enabled; return this; }
public MenuActionRowLinkBuilder Grows() { _w.Grow = true; return this; }
public MenuActionRowBuilder EndLink()
{
_row.AddLink( _w );
return _row;
}
}