using Annulus;
using Azimuth;
using System;
using System.Globalization;
namespace Glass.Testbed
{
///
/// NumberFields over a spread of grids, each stepped by its arrows or the wheel, or scrubbed by dragging its number
/// sideways. A readout reports every OnValueChanged.
///
public class NumberFieldTestCase : TestCase
{
private static readonly NumberFieldMaterial FieldMaterial = new NumberFieldMaterial
{
Background = UiPacksheetMaterials.TextField,
Label = Widgets.FieldText("") with { VerticalAlignment = Alignment.Vertical.Center },
IncrementButton = UiPacksheetMaterials.ScrollBarUpArrow,
DecrementButton = UiPacksheetMaterials.ScrollBarDownArrow,
};
private static readonly Cursor ScrubCursor =
new SpriteCursor(ResizeCursorMaterials.DiagonalNeSw, new Point(8, 8));
// One instance for every field but the French one, the way an app shares one across its whole UI.
private readonly NumberFieldBehavior sharedBehavior = new NumberFieldBehavior();
private TextMaterial readout;
public NumberFieldTestCase(string name) : base(name) { }
private NumberField BuildField(string debugName, NumberField.Data data, NumberFieldBehavior behavior)
{
var field = new NumberField(behavior, data)
{
DebugName = debugName,
NumberFieldMaterial = FieldMaterial,
ScrubCursor = ScrubCursor,
};
field.Bounds = Rect.FromPositionAndSize(Vector.Zero, field.PreferredBoundsSize);
field.OnValueChanged += (numberField, valueBefore, valueNow) =>
readout.Text = $"OnValueChanged: {numberField.DebugName} went from {valueBefore} to {valueNow}";
return field;
}
///
/// The shape a game's widget factory takes: it supplies the shared behavior and the look, and the call site's
/// data passes straight through.
///
private NumberField BuildField(string debugName, NumberField.Data data)
{
return BuildField(debugName, data, sharedBehavior);
}
///
/// A row of with beside it.
///
private void AddRow(NumberField field, string description)
{
TextMaterial caption = Widgets.SmallCaption(description);
Vector captionSize = caption.PreferredSize(Constraints.Unbounded);
Rect row = ContentAggregator.NewRow(Math.Max(field.Bounds.Height, captionSize.Y));
Rect fieldSlot = row.NewCol(field.Bounds.Width, margin: Gutter);
field.Bounds = field.Bounds.WithPosition(fieldSlot.TopLeft);
Add(field);
Panel captionPanel = caption.BuildControl(Constraints.Unbounded);
captionPanel.Bounds = captionPanel.Bounds.WithPosition(
row.TopLeft + new Vector(0, (row.Height - captionSize.Y) / 2));
Add(captionPanel);
}
protected override void Populate()
{
AddCaption("Click an arrow, spin the wheel over a field, or drag its number to scrub it: right or up to");
AddCaption("increase, left or down to decrease.");
AddCaption("An arrow greys out at its end of the range.");
readout = Widgets.Caption("OnValueChanged: nothing yet");
Panel readoutPanel = readout.BuildControl(Constraints.Unbounded);
readoutPanel.Bounds = ContentAggregator.NewRow(readoutPanel.Bounds.Height);
Add(readoutPanel);
AddRow(BuildField("whole numbers", new() { Grid = new NumberGrid { Max = 100 } }),
"0 to 100 in ones");
AddRow(BuildField("per unit voltage", new()
{
Grid = new NumberGrid { Min = 0.9m, Max = 1.1m, Resolution = 0.001m, Step = 0.01m },
Value = 1,
}),
"0.9 to 1.1: a 0.001 grid, stepping by 0.01");
AddRow(BuildField("off the lattice", new()
{
Grid = new NumberGrid { Max = 1, Resolution = 0.05m, Step = 0.3m },
Value = 0.45m,
}),
"0 to 1 stepping by 0.3, starting between steps at 0.45; the top step clamps to 1");
AddRow(BuildField("megawatts", new()
{
Grid = new NumberGrid { Max = 500, Step = 10 },
Format = (value, culture) => value.ToString("N0", culture) + " MW",
}),
"A custom format with units, stepping by 10");
var frenchBehavior = new NumberFieldBehavior
{
Culture = CultureInfo.GetCultureInfo("fr-FR"),
ScrubDistancePerStep = 16,
};
AddRow(BuildField("french", new() { Grid = new NumberGrid { Max = 10, Resolution = 0.5m } },
frenchBehavior),
"French culture, and twice the drag per step");
NumberField disabled = BuildField("disabled", new() { Grid = new NumberGrid { Max = 100 }, Value = 50 });
disabled.Enabled = false;
AddRow(disabled, "Disabled");
}
}
}