From b9adeeb063400477e53e093438c51fb9714d9786 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Thu, 10 May 2018 21:35:26 -0300 Subject: [PATCH] Add ScreenBreadcrumbControl. --- .../Visual/TestCaseScreenBreadcrumbs.cs | 108 ++++++++++++++++++ .../UserInterface/ScreenBreadcrumbControl.cs | 78 +++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs create mode 100644 osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs diff --git a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs new file mode 100644 index 0000000000..5055b0e114 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs @@ -0,0 +1,108 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Screens; +using OpenTK; + +namespace osu.Game.Tests.Visual +{ + [TestFixture] + public class TestCaseScreenBreadcrumbs : OsuTestCase + { + private readonly ScreenBreadcrumbControl breadcrumbs; + + public TestCaseScreenBreadcrumbs() + { + TestScreen startScreen; + OsuSpriteText titleText; + + Children = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(10), + Children = new Drawable[] + { + breadcrumbs = new ScreenBreadcrumbControl + { + RelativeSizeAxes = Axes.X, + }, + titleText = new OsuSpriteText(), + }, + }, + startScreen = new TestScreenOne(), + }; + + breadcrumbs.OnScreenChanged += s => titleText.Text = $"Changed to {s.ToString()}"; + breadcrumbs.CurrentScreen = startScreen; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + breadcrumbs.StripColour = colours.Blue; + } + + private abstract class TestScreen : OsuScreen + { + protected abstract string Title { get; } + protected abstract string NextTitle { get; } + protected abstract TestScreen CreateNextScreen(); + + public override string ToString() => Title; + + protected TestScreen() + { + Child = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(10), + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = Title, + }, + new TriangleButton + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Width = 100, + Text = $"Push {NextTitle}", + Action = () => Push(CreateNextScreen()), + }, + }, + }; + } + } + + private class TestScreenOne : TestScreen + { + protected override string Title => @"Screen One"; + protected override string NextTitle => @"Two"; + protected override TestScreen CreateNextScreen() => new TestScreenTwo(); + } + + private class TestScreenTwo : TestScreen + { + protected override string Title => @"Screen Two"; + protected override string NextTitle => @"One"; + protected override TestScreen CreateNextScreen() => new TestScreenOne(); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs new file mode 100644 index 0000000000..fbdb27a81c --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs @@ -0,0 +1,78 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Screens; + +namespace osu.Game.Graphics.UserInterface +{ + public class ScreenBreadcrumbControl : ScreenBreadcrumbControl + { + } + + public class ScreenBreadcrumbControl : BreadcrumbControl where T : Screen + { + private T currentScreen; + public T CurrentScreen + { + get { return currentScreen; } + set + { + if (value == currentScreen) return; + + if (CurrentScreen != null) + { + CurrentScreen.Exited -= onExited; + CurrentScreen.ModePushed -= onPushed; + } + else + { + // this is the first screen in the stack, so call the initial onPushed + currentScreen = value; + onPushed(CurrentScreen); + } + + currentScreen = value; + + if (CurrentScreen != null) + { + CurrentScreen.Exited += onExited; + CurrentScreen.ModePushed += onPushed; + Current.Value = CurrentScreen; + OnScreenChanged?.Invoke(CurrentScreen); + } + } + } + + public event Action OnScreenChanged; + + public ScreenBreadcrumbControl() + { + Current.ValueChanged += s => + { + if (s != CurrentScreen) + { + CurrentScreen = s; + s.MakeCurrent(); + } + }; + } + + private void onExited(Screen screen) + { + CurrentScreen = screen as T; + } + + private void onPushed(Screen screen) + { + var newScreen = screen as T; + + Items.ToList().SkipWhile(i => i != Current.Value).Skip(1).ForEach(RemoveItem); + AddItem(newScreen); + + CurrentScreen = newScreen; + } + } +}