using Annulus;
using Azimuth;
using System;
using System.Collections.Generic;
namespace Glass.Testbed
{
///
/// A guided tour whose spotlight the user can move or dismiss, so it needs a Setup to put itself back.
///
public class SpotlightTestCase : TestCase
{
///
/// Sits below whatever it is a child of, which under a Spotlight is the highlighted control.
///
private class CoachMark : Panel
{
public Vector Offset { get; set; }
public override void Update(TimeSpan elapsed, UpdateState state)
{
base.Update(elapsed, state);
Bounds = Rect.FromPositionAndSize(
new Vector(0, state.ParentClientRect.Height) + Offset, Bounds.Size);
}
}
private static readonly Vector ButtonSize = new Vector(190, 56);
private static readonly Vector CoachButtonSize = new Vector(140, 44);
private readonly List targets = new List();
private readonly Spotlight spotlight;
private readonly TextMaterial coachLabel;
private int step;
public SpotlightTestCase(string name) : base(name)
{
spotlight = new Spotlight(new SolidColorMaterial
{
Color = System.Drawing.Color.FromArgb(170, 0, 0, 0),
})
{
DebugName = "spotlight",
};
coachLabel = Widgets.ButtonLabel("Click");
}
///
/// Re-parenting is the whole move: nothing else tells the spotlight where its new target sits.
///
private void MoveSpotlightTo(int target)
{
targets[step].ChildControls.Remove(spotlight);
step = target;
targets[step].ChildControls.Add(spotlight);
coachLabel.Text = $"Click {targets[step].DebugName}";
}
private void BuildTargets()
{
Rect buttonRow = ContentAggregator.NewRow(ButtonSize.Y);
foreach (string name in new[] { "Build", "Attack", "Harvest" })
{
string buttonName = name;
int clicks = 0;
TextMaterial label = Widgets.ButtonLabel($"{buttonName}: 0");
Button target = new Panel { Material = label }.FillParent(new Button
{
DebugName = buttonName,
ButtonMaterial = UiPacksheetMaterials.Button,
Bounds = buttonRow.NewCol(ButtonSize.X, margin: Gutter),
});
target.OnClick += delegate (in MouseState _, MouseButtonFlags __)
{
++clicks;
label.Text = $"{buttonName}: {clicks}";
};
Add(target);
targets.Add(target);
}
}
private void BuildCoachMark()
{
Panel coachText = coachLabel.BuildControl(Constraints.Unbounded);
// Laid out before the mark exists, so the mark can be sized to what it ends up holding rather than to a
// guess that has to stay in step with it. The button row sets the width, and the label centres across it.
var content = new RectAggregator(
Rect.FromPositionAndSize(Vector.Zero, new Vector(2 * CoachButtonSize.X + Gutter, 0)),
new Vector(0, Gutter));
coachText.Bounds = content.NewRow(coachText.Bounds.Height);
Rect coachButtonRow = content.NewRow(CoachButtonSize.Y);
Button next = new Panel { Material = Widgets.ButtonLabel("Next") }.FillParent(new Button
{
DebugName = "next step",
ButtonMaterial = UiPacksheetMaterials.Button,
Bounds = coachButtonRow.NewCol(CoachButtonSize.X, margin: Gutter),
});
Button done = new Panel { Material = Widgets.ButtonLabel("Done") }.FillParent(new Button
{
DebugName = "done",
ButtonMaterial = UiPacksheetMaterials.Button,
Bounds = coachButtonRow.NewCol(CoachButtonSize.X),
});
var coachMark = new CoachMark
{
DebugName = "coach mark",
Material = UiPacksheetMaterials.YellowPanel,
Bounds = Rect.FromPositionAndSize(
Vector.Zero, UiPacksheetMaterials.YellowPanel.BoundsFor(content.Rect).Size),
Offset = new Vector(0, Gutter),
};
spotlight.ChildControls.Add(coachMark);
coachMark.ChildControls.Add(coachText);
coachMark.ChildControls.Add(next);
coachMark.ChildControls.Add(done);
next.OnClick += delegate (in MouseState _, MouseButtonFlags __)
{
MoveSpotlightTo((step + 1) % targets.Count);
};
done.OnClick += delegate (in MouseState _, MouseButtonFlags __)
{
targets[step].ChildControls.Remove(spotlight);
};
}
protected override void Populate()
{
AddCaption("Everything dims but the highlighted button, which still takes its clicks");
AddCaption("Modal means the tab strip is blocked too — Done releases it");
BuildTargets();
BuildCoachMark();
}
///
/// Cases are built once, so a tour the user left part way through or dismissed restarts here.
///
protected override void Setup()
{
MoveSpotlightTo(0);
}
}
}