From 6d534046ff2cedc67315f4d6e10f8f810afab33a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Apr 2022 14:46:01 +0900 Subject: [PATCH] Add keyboard traversal support for first run dialog (and tidy up step traversal logic) --- .../TestSceneFirstRunSetupOverlay.cs | 30 ++++- osu.Game/Overlays/FirstRunSetupOverlay.cs | 125 +++++++++++------- 2 files changed, 103 insertions(+), 52 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs index 77a37e7420..ff54e34ca0 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs @@ -60,13 +60,19 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - [Test] - public void TestOverlayRunsToFinish() + [TestCase(false)] + [TestCase(true)] + public void TestOverlayRunsToFinish(bool keyboard) { AddUntilStep("step through", () => { if (overlay.CurrentScreen?.IsLoaded != false) - overlay.NextButton.TriggerClick(); + { + if (keyboard) + InputManager.Key(Key.Enter); + else + overlay.NextButton.TriggerClick(); + } return overlay.State.Value == Visibility.Hidden; }); @@ -80,8 +86,9 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("back at start", () => overlay.CurrentScreen is ScreenWelcome); } - [Test] - public void TestBackButton() + [TestCase(false)] + [TestCase(true)] + public void TestBackButton(bool keyboard) { AddAssert("back button disabled", () => !overlay.BackButton.Enabled.Value); @@ -98,12 +105,23 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("step back to start", () => { if (overlay.CurrentScreen?.IsLoaded != false) - overlay.BackButton.TriggerClick(); + { + if (keyboard) + InputManager.Key(Key.Escape); + else + overlay.BackButton.TriggerClick(); + } return overlay.CurrentScreen is ScreenWelcome; }); AddAssert("back button disabled", () => !overlay.BackButton.Enabled.Value); + + if (keyboard) + { + AddStep("exit via keyboard", () => InputManager.Key(Key.Escape)); + AddAssert("overlay dismissed", () => overlay.State.Value == Visibility.Hidden); + } } [Test] diff --git a/osu.Game/Overlays/FirstRunSetupOverlay.cs b/osu.Game/Overlays/FirstRunSetupOverlay.cs index e8829136f0..00396e6d85 100644 --- a/osu.Game/Overlays/FirstRunSetupOverlay.cs +++ b/osu.Game/Overlays/FirstRunSetupOverlay.cs @@ -12,12 +12,14 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Input.Bindings; using osu.Game.Localisation; using osu.Game.Overlays.FirstRunSetup; using osu.Game.Overlays.Notifications; @@ -215,57 +217,30 @@ namespace osu.Game.Overlays performer.PerformFromScreen(_ => { Show(); }, new[] { typeof(MainMenu) }); } - private void showLastStep() + public override bool OnPressed(KeyBindingPressEvent e) { - Debug.Assert(currentStepIndex > 0); - Debug.Assert(stack != null); - - stack.CurrentScreen.Exit(); - currentStepIndex--; - - BackButton.Enabled.Value = currentStepIndex != 0; - - updateButtonText(); - } - - private void showNextStep() - { - if (currentStepIndex == null) + if (!e.Repeat) { - stackContainer.Child = stack = new ScreenStack + switch (e.Action) { - RelativeSizeAxes = Axes.Both, - }; + case GlobalAction.Select: + NextButton.TriggerClick(); + return true; - currentStepIndex = 0; + case GlobalAction.Back: + if (BackButton.Enabled.Value) + { + BackButton.TriggerClick(); + return true; + } + + // If back button is disabled, we are at the first step. + // The base call will handle dismissal of the overlay. + break; + } } - else - currentStepIndex++; - Debug.Assert(currentStepIndex != null); - Debug.Assert(stack != null); - - BackButton.Enabled.Value = currentStepIndex > 0; - - if (currentStepIndex < steps.Length) - { - stack.Push((Screen)Activator.CreateInstance(steps[currentStepIndex.Value].ScreenType)); - updateButtonText(); - } - else - { - currentStepIndex = null; - Hide(); - } - } - - private void updateButtonText() - { - Debug.Assert(currentStepIndex != null); - - NextButton.Text = currentStepIndex + 1 < steps.Length - ? FirstRunSetupOverlayStrings.Next(steps[currentStepIndex.Value + 1].Description) - : CommonStrings.Finish; + return base.OnPressed(e); } protected override void PopIn() @@ -278,7 +253,7 @@ namespace osu.Game.Overlays this.FadeIn(400, Easing.OutQuint); if (currentStepIndex == null) - showNextStep(); + showFirstStep(); } protected override void PopOut() @@ -308,6 +283,64 @@ namespace osu.Game.Overlays this.FadeOut(200, Easing.OutQuint); } + private void showFirstStep() + { + Debug.Assert(currentStepIndex == null); + + stackContainer.Child = stack = new ScreenStack + { + RelativeSizeAxes = Axes.Both, + }; + + currentStepIndex = -1; + showNextStep(); + } + + private void showLastStep() + { + if (currentStepIndex == 0) + return; + + Debug.Assert(stack != null); + + stack.CurrentScreen.Exit(); + currentStepIndex--; + + BackButton.Enabled.Value = currentStepIndex != 0; + + updateButtonText(); + } + + private void showNextStep() + { + Debug.Assert(currentStepIndex != null); + Debug.Assert(stack != null); + + currentStepIndex++; + + BackButton.Enabled.Value = currentStepIndex > 0; + + if (currentStepIndex < steps.Length) + { + stack.Push((Screen)Activator.CreateInstance(steps[currentStepIndex.Value].ScreenType)); + updateButtonText(); + } + else + { + currentStepIndex = null; + Hide(); + } + } + + private void updateButtonText() + { + Debug.Assert(currentStepIndex != null); + + NextButton.Text = currentStepIndex + 1 < steps.Length + ? FirstRunSetupOverlayStrings.Next(steps[currentStepIndex.Value + 1].Description) + : CommonStrings.Finish; + } + private class FirstRunStep { public readonly Type ScreenType;