using Annulus;
using Azimuth;
using Glass.Blacklight;
using System;
using System.Globalization;
namespace Glass.Testbed.TestCases.Controls
{
///
/// 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
{
// 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 readonly NumberFieldBehavior typingBehavior = new NumberFieldBehavior { AllowsTyping = true };
private Label readout;
private NumberField BuildField(string debugName, NumberField.Data data, NumberFieldBehavior behavior)
{
var field = new NumberField(behavior, data)
{
DebugName = debugName,
NumberFieldMaterial = Widgets.NumberField,
ScrubCursor = CursorExtraMaterials.Scrub,
};
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)
{
var caption = new Label(Widgets.SmallCaptionStyle, description, Constraints.Unbounded);
Vector captionSize = caption.Bounds.Size;
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);
caption.Bounds = caption.Bounds.WithPosition(row.TopLeft + new Vector(0, (row.Height - captionSize.Y) / 2));
Add(caption);
}
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 = new Label(Widgets.CaptionStyle, "OnValueChanged: nothing yet");
readout.Bounds = ContentAggregator.NewRow(readout.PreferredSize(Constraints.Unbounded).Y);
Add(readout);
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");
AddCaption("These fields can also be typed into: click the number without dragging, or Tab to one");
AddCaption("and press Enter or F2. Enter commits, Escape cancels, and clicking away commits.");
AddCaption("Up and Down still step, Home and End move the caret, and Ctrl+Home and Ctrl+End");
AddCaption("jump the value to its ends.");
AddRow(BuildField("typed whole numbers", new() { Grid = new NumberGrid { Max = 100 } }, typingBehavior),
"0 to 100 in ones; text outside the range clamps");
AddRow(BuildField("typed per unit voltage", new()
{
Grid = new NumberGrid { Min = 0.9m, Max = 1.1m, Resolution = 0.001m, Step = 0.01m },
Value = 1,
}, typingBehavior),
"0.9 to 1.1: typed values snap to the 0.001 grid");
AddRow(BuildField("typed megawatts", new()
{
Grid = new NumberGrid { Max = 500, Step = 10 },
Format = (value, culture) => value.ToString("N0", culture) + " MW",
}, typingBehavior),
"A custom format: the units are in the label, and the typed text is plain digits");
var typedFrench = new NumberFieldBehavior
{
Culture = CultureInfo.GetCultureInfo("fr-FR"),
AllowsTyping = true,
};
AddRow(BuildField("typed french", new() { Grid = new NumberGrid { Max = 10, Resolution = 0.5m } },
typedFrench),
"French culture: type 2,5 or 2.5");
}
}
}