From 5ed69338a662165d7374e3de1940ad2997f35faa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Jan 2022 19:05:14 +0900 Subject: [PATCH] Add omission of pages when there are too many --- .../UserInterface/TestScenePageSelector.cs | 22 +++++++-- .../PageSelector/PageEllipsis.cs | 33 +++++++++++++ .../PageSelector/PageSelector.cs | 48 ++++++++++--------- 3 files changed, 76 insertions(+), 27 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/PageSelector/PageEllipsis.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index 3b32a2a0dc..c99ac52cb1 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -35,14 +35,24 @@ namespace osu.Game.Tests.Visual.UserInterface { setAvailablePages(100); - AddAssert("Correct page buttons", () => pageSelector.ChildrenOfType().Select(p => p.PageNumber).SequenceEqual(new[] { 1, 2, 3, 100 })); + selectPageIndex(0); + checkVisiblePageNumbers(new[] { 1, 2, 3, 100 }); + + selectPageIndex(6); + checkVisiblePageNumbers(new[] { 1, 5, 6, 7, 8, 9, 100 }); + + selectPageIndex(49); + checkVisiblePageNumbers(new[] { 1, 48, 49, 50, 51, 52, 100 }); + + selectPageIndex(99); + checkVisiblePageNumbers(new[] { 1, 98, 99, 100 }); } [Test] public void TestResetCurrentPage() { setAvailablePages(10); - selectPage(6); + selectPageIndex(6); setAvailablePages(11); AddAssert("Page 1 is current", () => pageSelector.CurrentPage.Value == 0); } @@ -51,14 +61,16 @@ namespace osu.Game.Tests.Visual.UserInterface public void TestOutOfBoundsSelection() { setAvailablePages(10); - selectPage(11); + selectPageIndex(11); AddAssert("Page 10 is current", () => pageSelector.CurrentPage.Value == pageSelector.AvailablePages.Value - 1); - selectPage(-1); + selectPageIndex(-1); AddAssert("Page 1 is current", () => pageSelector.CurrentPage.Value == 0); } - private void selectPage(int pageIndex) => + private void checkVisiblePageNumbers(int[] expected) => AddAssert($"Sequence is {string.Join(',', expected.Select(i => i.ToString()))}", () => pageSelector.ChildrenOfType().Select(p => p.PageNumber).SequenceEqual(expected)); + + private void selectPageIndex(int pageIndex) => AddStep($"Select page {pageIndex}", () => pageSelector.CurrentPage.Value = pageIndex); private void setAvailablePages(int availablePages) => diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageEllipsis.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageEllipsis.cs new file mode 100644 index 0000000000..d73d9f5824 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageEllipsis.cs @@ -0,0 +1,33 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Overlays; + +namespace osu.Game.Graphics.UserInterface.PageSelector +{ + internal class PageEllipsis : CompositeDrawable + { + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + RelativeSizeAxes = Axes.Y; + AutoSizeAxes = Axes.X; + + InternalChildren = new Drawable[] + { + new OsuSpriteText + { + Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold), + Text = "...", + Colour = colourProvider.Light3, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }; + } + } +} diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs index ae644bb852..ce74259289 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; +using System; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Bindables; @@ -50,43 +50,47 @@ namespace osu.Game.Graphics.UserInterface.PageSelector { base.LoadComplete(); - CurrentPage.BindValueChanged(onCurrentPageChanged); + CurrentPage.BindValueChanged(_ => redraw()); AvailablePages.BindValueChanged(_ => redraw(), true); } - private void onCurrentPageChanged(ValueChangedEvent currentPage) + private void redraw() { - if (currentPage.NewValue >= AvailablePages.Value) + if (CurrentPage.Value >= AvailablePages.Value) { CurrentPage.Value = AvailablePages.Value - 1; return; } - foreach (var page in itemsFlow.OfType()) - page.Selected = page.PageNumber == currentPage.NewValue + 1; + previousPageButton.Enabled.Value = CurrentPage.Value != 0; + nextPageButton.Enabled.Value = CurrentPage.Value < AvailablePages.Value - 1; - previousPageButton.Enabled.Value = currentPage.NewValue != 0; - nextPageButton.Enabled.Value = currentPage.NewValue < AvailablePages.Value - 1; - } - - private void redraw() - { itemsFlow.Clear(); - for (int i = 0; i < AvailablePages.Value; i++) + int totalPages = AvailablePages.Value; + bool lastWasEllipsis = false; + + for (int i = 0; i < totalPages; i++) { int pageIndex = i; - itemsFlow.Add(new PageSelectorPageButton(pageIndex + 1) - { - Action = () => CurrentPage.Value = pageIndex, - }); - } + bool shouldShowPage = pageIndex == 0 || pageIndex == totalPages - 1 || Math.Abs(pageIndex - CurrentPage.Value) <= 2; - if (CurrentPage.Value != 0) - CurrentPage.Value = 0; - else - CurrentPage.TriggerChange(); + if (shouldShowPage) + { + lastWasEllipsis = false; + itemsFlow.Add(new PageSelectorPageButton(pageIndex + 1) + { + Action = () => CurrentPage.Value = pageIndex, + Selected = CurrentPage.Value == pageIndex, + }); + } + else if (!lastWasEllipsis) + { + lastWasEllipsis = true; + itemsFlow.Add(new PageEllipsis()); + } + } } } }