From 508b26ac6973a07a7edb6870ec13e065b055a21c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 7 Sep 2019 07:31:07 +0300 Subject: [PATCH 01/31] Implement basic layout --- .../UserInterface/TestScenePageSelector.cs | 29 +++++ .../Graphics/UserInterface/PageSelector.cs | 100 ++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs create mode 100644 osu.Game/Graphics/UserInterface/PageSelector.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs new file mode 100644 index 0000000000..9911a23bf1 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -0,0 +1,29 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Game.Graphics.UserInterface; +using osu.Framework.Graphics; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestScenePageSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(PageSelector) + }; + + public TestScenePageSelector() + { + PageSelector pageSelector; + + Child = pageSelector = new PageSelector(10) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; + } + } +} diff --git a/osu.Game/Graphics/UserInterface/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector.cs new file mode 100644 index 0000000000..53f112ed68 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/PageSelector.cs @@ -0,0 +1,100 @@ +// 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.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Game.Graphics.Containers; +using osu.Framework.Bindables; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Graphics.UserInterface +{ + public class PageSelector : CompositeDrawable + { + private BindableInt currentPage = new BindableInt(1); + + private readonly int maxPages; + private readonly FillFlowContainer pillsFlow; + + public PageSelector(int maxPages) + { + this.maxPages = maxPages; + + AutoSizeAxes = Axes.Both; + InternalChild = pillsFlow = new FillFlowContainer + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + currentPage.BindValueChanged(page => redraw(page.NewValue), true); + } + + private void redraw(int newPage) + { + pillsFlow.Clear(); + + for (int i = 0; i < maxPages; i++) + { + addPagePill(i); + } + } + + private void addPagePill(int page) + { + var pill = new Pill(page); + + if (page != currentPage.Value) + pill.Action = () => currentPage.Value = page; + + pillsFlow.Add(pill); + } + + private class Pill : OsuClickableContainer + { + private const int height = 20; + + private readonly Box background; + + public Pill(int page) + { + AutoSizeAxes = Axes.X; + Height = height; + Child = new CircularContainer + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Masking = true, + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + new SpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = page.ToString(), + Margin = new MarginPadding { Horizontal = 8 } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.Seafoam; + } + } + } +} From f77cd6582d94811874d74315265d4e91b5f81321 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 7 Sep 2019 08:20:09 +0300 Subject: [PATCH 02/31] Implement CurrentPage class --- .../Graphics/UserInterface/PageSelector.cs | 150 ++++++++++++++---- 1 file changed, 119 insertions(+), 31 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector.cs index 53f112ed68..fef35ab229 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector.cs @@ -8,6 +8,9 @@ using osu.Framework.Bindables; using osu.Framework.Allocation; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Framework.Extensions.Color4Extensions; +using System; namespace osu.Game.Graphics.UserInterface { @@ -42,59 +45,144 @@ namespace osu.Game.Graphics.UserInterface { pillsFlow.Clear(); - for (int i = 0; i < maxPages; i++) + for (int i = 1; i <= maxPages; i++) { - addPagePill(i); + if (i == currentPage.Value) + addCurrentPagePill(); + else + addPagePill(i); } } private void addPagePill(int page) { - var pill = new Pill(page); - - if (page != currentPage.Value) - pill.Action = () => currentPage.Value = page; - - pillsFlow.Add(pill); + pillsFlow.Add(new Page(page.ToString(), () => currentPage.Value = page)); } - private class Pill : OsuClickableContainer + private void addCurrentPagePill() + { + pillsFlow.Add(new CurrentPage(currentPage.Value.ToString())); + } + + private abstract class DrawablePage : CompositeDrawable { private const int height = 20; + private const int margin = 8; - private readonly Box background; + protected readonly string Text; - public Pill(int page) + protected DrawablePage(string text) { + Text = text; + AutoSizeAxes = Axes.X; Height = height; - Child = new CircularContainer - { - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Masking = true, - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both, - }, - new SpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = page.ToString(), - Margin = new MarginPadding { Horizontal = 8 } - } - } - }; + + var background = CreateBackground(); + + if (background != null) + AddInternal(background); + + var content = CreateContent(); + content.Margin = new MarginPadding { Horizontal = margin }; + + AddInternal(content); + } + + protected abstract Drawable CreateContent(); + + protected virtual Drawable CreateBackground() => null; + } + + private abstract class ActivatedDrawablePage : DrawablePage + { + private readonly Action action; + + public ActivatedDrawablePage(string text, Action action) + : base(text) + { + this.action = action; + } + + protected override bool OnClick(ClickEvent e) + { + action?.Invoke(); + return base.OnClick(e); + } + } + + private class Page : ActivatedDrawablePage + { + private SpriteText text; + + private OsuColour colours; + + public Page(string text, Action action) + : base(text, action) + { } [BackgroundDependencyLoader] private void load(OsuColour colours) { + this.colours = colours; + text.Colour = colours.Seafoam; + } + + protected override bool OnHover(HoverEvent e) + { + text.Colour = colours.Seafoam.Lighten(30f); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + text.Colour = colours.Seafoam; + base.OnHoverLost(e); + } + + protected override Drawable CreateContent() => text = new SpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = Text + }; + } + + private class CurrentPage : DrawablePage + { + private SpriteText text; + + private Box background; + + public CurrentPage(string text) + : base(text) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + text.Colour = colours.GreySeafoam; background.Colour = colours.Seafoam; } + + protected override Drawable CreateContent() => text = new SpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = Text + }; + + protected override Drawable CreateBackground() => new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = background = new Box + { + RelativeSizeAxes = Axes.Both, + } + }; } } } From cea26baaefb58171ca76b1b3b39a70772d8eb7a5 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 7 Sep 2019 08:46:16 +0300 Subject: [PATCH 03/31] Implement placeholder and correct redraw algorithm --- .../UserInterface/TestScenePageSelector.cs | 4 +- .../Graphics/UserInterface/PageSelector.cs | 63 +++++++++++++++---- 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index 9911a23bf1..e5efa65c91 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -17,9 +17,7 @@ namespace osu.Game.Tests.Visual.UserInterface public TestScenePageSelector() { - PageSelector pageSelector; - - Child = pageSelector = new PageSelector(10) + Child = new PageSelector(200) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Graphics/UserInterface/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector.cs index fef35ab229..244e87f023 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector.cs @@ -3,7 +3,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; -using osu.Game.Graphics.Containers; using osu.Framework.Bindables; using osu.Framework.Allocation; using osu.Framework.Graphics.Shapes; @@ -16,7 +15,7 @@ namespace osu.Game.Graphics.UserInterface { public class PageSelector : CompositeDrawable { - private BindableInt currentPage = new BindableInt(1); + public readonly BindableInt CurrentPage = new BindableInt(); private readonly int maxPages; private readonly FillFlowContainer pillsFlow; @@ -38,30 +37,47 @@ namespace osu.Game.Graphics.UserInterface { base.LoadComplete(); - currentPage.BindValueChanged(page => redraw(page.NewValue), true); + CurrentPage.BindValueChanged(_ => redraw(), true); } - private void redraw(int newPage) + private void redraw() { pillsFlow.Clear(); - for (int i = 1; i <= maxPages; i++) + if (CurrentPage.Value > 3) + addDrawablePage(1); + + if (CurrentPage.Value > 4) + addPlaceholder(); + + for (int i = Math.Max(CurrentPage.Value - 2, 1); i <= Math.Min(CurrentPage.Value + 2, maxPages); i++) { - if (i == currentPage.Value) + if (i == CurrentPage.Value) addCurrentPagePill(); else - addPagePill(i); + addDrawablePage(i); } + + if (CurrentPage.Value + 2 < maxPages - 1) + addPlaceholder(); + + if (CurrentPage.Value + 2 < maxPages) + addDrawablePage(maxPages); } - private void addPagePill(int page) + private void addDrawablePage(int page) { - pillsFlow.Add(new Page(page.ToString(), () => currentPage.Value = page)); + pillsFlow.Add(new Page(page.ToString(), () => CurrentPage.Value = page)); + } + + private void addPlaceholder() + { + pillsFlow.Add(new Placeholder()); } private void addCurrentPagePill() { - pillsFlow.Add(new CurrentPage(currentPage.Value.ToString())); + pillsFlow.Add(new SelectedPage(CurrentPage.Value.ToString())); } private abstract class DrawablePage : CompositeDrawable @@ -149,13 +165,13 @@ namespace osu.Game.Graphics.UserInterface }; } - private class CurrentPage : DrawablePage + private class SelectedPage : DrawablePage { private SpriteText text; private Box background; - public CurrentPage(string text) + public SelectedPage(string text) : base(text) { } @@ -184,5 +200,28 @@ namespace osu.Game.Graphics.UserInterface } }; } + + private class Placeholder : DrawablePage + { + private SpriteText text; + + public Placeholder() + : base("...") + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + text.Colour = colours.Seafoam; + } + + protected override Drawable CreateContent() => text = new SpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = Text + }; + } } } From 9bd4220e9f6817e3200926c7abce593b6f8e52aa Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 7 Sep 2019 09:20:11 +0300 Subject: [PATCH 04/31] Add prev/next buttons --- .../Graphics/UserInterface/PageSelector.cs | 206 ++++++++++++++++-- 1 file changed, 184 insertions(+), 22 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector.cs index 244e87f023..d93dcdace9 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector.cs @@ -10,12 +10,13 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Framework.Extensions.Color4Extensions; using System; +using osuTK; namespace osu.Game.Graphics.UserInterface { public class PageSelector : CompositeDrawable { - public readonly BindableInt CurrentPage = new BindableInt(); + public readonly BindableInt CurrentPage = new BindableInt(1); private readonly int maxPages; private readonly FillFlowContainer pillsFlow; @@ -44,6 +45,11 @@ namespace osu.Game.Graphics.UserInterface { pillsFlow.Clear(); + if (CurrentPage.Value == 1) + addPreviousPageButton(); + else + addPreviousPageButton(() => CurrentPage.Value -= 1); + if (CurrentPage.Value > 3) addDrawablePage(1); @@ -63,6 +69,11 @@ namespace osu.Game.Graphics.UserInterface if (CurrentPage.Value + 2 < maxPages) addDrawablePage(maxPages); + + if (CurrentPage.Value == maxPages) + addNextPageButton(); + else + addNextPageButton(() => CurrentPage.Value += 1); } private void addDrawablePage(int page) @@ -80,12 +91,23 @@ namespace osu.Game.Graphics.UserInterface pillsFlow.Add(new SelectedPage(CurrentPage.Value.ToString())); } + private void addPreviousPageButton(Action action = null) + { + pillsFlow.Add(new PreviousPageButton(action)); + } + + private void addNextPageButton(Action action = null) + { + pillsFlow.Add(new NextPageButton(action)); + } + private abstract class DrawablePage : CompositeDrawable { private const int height = 20; private const int margin = 8; protected readonly string Text; + protected readonly Drawable Content; protected DrawablePage(string text) { @@ -99,10 +121,10 @@ namespace osu.Game.Graphics.UserInterface if (background != null) AddInternal(background); - var content = CreateContent(); - content.Margin = new MarginPadding { Horizontal = margin }; + Content = CreateContent(); + Content.Margin = new MarginPadding { Horizontal = margin }; - AddInternal(content); + AddInternal(Content); } protected abstract Drawable CreateContent(); @@ -112,25 +134,23 @@ namespace osu.Game.Graphics.UserInterface private abstract class ActivatedDrawablePage : DrawablePage { - private readonly Action action; + protected readonly Action Action; - public ActivatedDrawablePage(string text, Action action) + public ActivatedDrawablePage(string text, Action action = null) : base(text) { - this.action = action; + Action = action; } protected override bool OnClick(ClickEvent e) { - action?.Invoke(); + Action?.Invoke(); return base.OnClick(e); } } private class Page : ActivatedDrawablePage { - private SpriteText text; - private OsuColour colours; public Page(string text, Action action) @@ -142,22 +162,22 @@ namespace osu.Game.Graphics.UserInterface private void load(OsuColour colours) { this.colours = colours; - text.Colour = colours.Seafoam; + Content.Colour = colours.Seafoam; } protected override bool OnHover(HoverEvent e) { - text.Colour = colours.Seafoam.Lighten(30f); + Content.Colour = colours.Seafoam.Lighten(30f); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - text.Colour = colours.Seafoam; + Content.Colour = colours.Seafoam; base.OnHoverLost(e); } - protected override Drawable CreateContent() => text = new SpriteText + protected override Drawable CreateContent() => new SpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -167,8 +187,6 @@ namespace osu.Game.Graphics.UserInterface private class SelectedPage : DrawablePage { - private SpriteText text; - private Box background; public SelectedPage(string text) @@ -179,11 +197,11 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(OsuColour colours) { - text.Colour = colours.GreySeafoam; + Content.Colour = colours.GreySeafoam; background.Colour = colours.Seafoam; } - protected override Drawable CreateContent() => text = new SpriteText + protected override Drawable CreateContent() => new SpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -203,8 +221,6 @@ namespace osu.Game.Graphics.UserInterface private class Placeholder : DrawablePage { - private SpriteText text; - public Placeholder() : base("...") { @@ -213,15 +229,161 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(OsuColour colours) { - text.Colour = colours.Seafoam; + Content.Colour = colours.Seafoam; } - protected override Drawable CreateContent() => text = new SpriteText + protected override Drawable CreateContent() => new SpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, Text = Text }; } + + private class PreviousPageButton : ActivatedDrawablePage + { + private OsuColour colours; + private Box background; + + public PreviousPageButton(Action action) + : base("prev", action) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + this.colours = colours; + Content.Colour = colours.Seafoam; + background.Colour = colours.GreySeafoam; + + if (Action == null) + { + Content.FadeColour(colours.GrayA); + background.FadeColour(colours.GrayA); + } + } + + protected override bool OnHover(HoverEvent e) + { + Content.Colour = colours.Seafoam.Lighten(30f); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + Content.Colour = colours.Seafoam; + base.OnHoverLost(e); + } + + protected override Drawable CreateContent() => new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(3), + Children = new Drawable[] + { + new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Icon = FontAwesome.Solid.CaretLeft, + Size = new Vector2(10), + }, + new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = Text.ToUpper(), + } + } + }; + + protected override Drawable CreateBackground() => new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = background = new Box + { + RelativeSizeAxes = Axes.Both, + } + }; + } + + private class NextPageButton : ActivatedDrawablePage + { + private OsuColour colours; + private Box background; + + public NextPageButton(Action action) + : base("next", action) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + this.colours = colours; + Content.Colour = colours.Seafoam; + background.Colour = colours.GreySeafoam; + + if (Action == null) + { + Content.FadeColour(colours.GrayA); + background.FadeColour(colours.GrayA); + } + } + + protected override bool OnHover(HoverEvent e) + { + Content.Colour = colours.Seafoam.Lighten(30f); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + Content.Colour = colours.Seafoam; + base.OnHoverLost(e); + } + + protected override Drawable CreateContent() => new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(3), + Children = new Drawable[] + { + new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = Text.ToUpper(), + }, + new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Icon = FontAwesome.Solid.CaretRight, + Size = new Vector2(10), + }, + } + }; + + protected override Drawable CreateBackground() => new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = background = new Box + { + RelativeSizeAxes = Axes.Both, + } + }; + } } } From ba18f77b628496569cb5d5718081ea271b51e4f3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 7 Sep 2019 22:31:08 +0300 Subject: [PATCH 05/31] Use OsuHoverContainer for prev/next buttons --- .../Graphics/UserInterface/PageSelector.cs | 231 ++++++------------ 1 file changed, 78 insertions(+), 153 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector.cs index d93dcdace9..3ca133d64b 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector.cs @@ -11,6 +11,8 @@ using osu.Framework.Input.Events; using osu.Framework.Extensions.Color4Extensions; using System; using osuTK; +using osu.Game.Graphics.Containers; +using System.Collections.Generic; namespace osu.Game.Graphics.UserInterface { @@ -21,16 +23,34 @@ namespace osu.Game.Graphics.UserInterface private readonly int maxPages; private readonly FillFlowContainer pillsFlow; + private readonly Button previousPageButton; + private readonly Button nextPageButton; + public PageSelector(int maxPages) { this.maxPages = maxPages; AutoSizeAxes = Axes.Both; - InternalChild = pillsFlow = new FillFlowContainer + InternalChild = new FillFlowContainer { - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + previousPageButton = new Button(false, "prev") + { + Action = () => CurrentPage.Value -= 1, + }, + pillsFlow = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + }, + nextPageButton = new Button(true, "next") + { + Action = () => CurrentPage.Value += 1 + } + } }; } @@ -43,12 +63,10 @@ namespace osu.Game.Graphics.UserInterface private void redraw() { - pillsFlow.Clear(); + previousPageButton.Enabled.Value = CurrentPage.Value != 1; + nextPageButton.Enabled.Value = CurrentPage.Value != maxPages; - if (CurrentPage.Value == 1) - addPreviousPageButton(); - else - addPreviousPageButton(() => CurrentPage.Value -= 1); + pillsFlow.Clear(); if (CurrentPage.Value > 3) addDrawablePage(1); @@ -69,11 +87,6 @@ namespace osu.Game.Graphics.UserInterface if (CurrentPage.Value + 2 < maxPages) addDrawablePage(maxPages); - - if (CurrentPage.Value == maxPages) - addNextPageButton(); - else - addNextPageButton(() => CurrentPage.Value += 1); } private void addDrawablePage(int page) @@ -91,16 +104,6 @@ namespace osu.Game.Graphics.UserInterface pillsFlow.Add(new SelectedPage(CurrentPage.Value.ToString())); } - private void addPreviousPageButton(Action action = null) - { - pillsFlow.Add(new PreviousPageButton(action)); - } - - private void addNextPageButton(Action action = null) - { - pillsFlow.Add(new NextPageButton(action)); - } - private abstract class DrawablePage : CompositeDrawable { private const int height = 20; @@ -240,150 +243,72 @@ namespace osu.Game.Graphics.UserInterface }; } - private class PreviousPageButton : ActivatedDrawablePage + private class Button : OsuHoverContainer { - private OsuColour colours; - private Box background; + private const int height = 20; + private const int margin = 8; - public PreviousPageButton(Action action) - : base("prev", action) + private readonly Anchor alignment; + private readonly Box background; + + protected override IEnumerable EffectTargets => new[] { background }; + + public Button(bool rightAligned, string text) { - } + alignment = rightAligned ? Anchor.x0 : Anchor.x2; - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - this.colours = colours; - Content.Colour = colours.Seafoam; - background.Colour = colours.GreySeafoam; + AutoSizeAxes = Axes.X; + Height = height; - if (Action == null) + Child = new CircularContainer { - Content.FadeColour(colours.GrayA); - background.FadeColour(colours.GrayA); - } - } - - protected override bool OnHover(HoverEvent e) - { - Content.Colour = colours.Seafoam.Lighten(30f); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - Content.Colour = colours.Seafoam; - base.OnHoverLost(e); - } - - protected override Drawable CreateContent() => new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(3), - Children = new Drawable[] - { - new SpriteIcon + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Masking = true, + Children = new Drawable[] { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Icon = FontAwesome.Solid.CaretLeft, - Size = new Vector2(10), - }, - new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Text = Text.ToUpper(), + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + new Container + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Horizontal = margin }, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + new SpriteText + { + Anchor = Anchor.y1 | alignment, + Origin = Anchor.y1 | alignment, + Text = text.ToUpper(), + }, + new SpriteIcon + { + Anchor = Anchor.y1 | alignment, + Origin = Anchor.y1 | alignment, + Icon = alignment == Anchor.x2 ? FontAwesome.Solid.ChevronLeft : FontAwesome.Solid.ChevronRight, + Size = new Vector2(10), + }, + } + } + } } - } - }; - - protected override Drawable CreateBackground() => new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - Child = background = new Box - { - RelativeSizeAxes = Axes.Both, - } - }; - } - - private class NextPageButton : ActivatedDrawablePage - { - private OsuColour colours; - private Box background; - - public NextPageButton(Action action) - : base("next", action) - { + }; } [BackgroundDependencyLoader] private void load(OsuColour colours) { - this.colours = colours; - Content.Colour = colours.Seafoam; - background.Colour = colours.GreySeafoam; - - if (Action == null) - { - Content.FadeColour(colours.GrayA); - background.FadeColour(colours.GrayA); - } + IdleColour = colours.GreySeafoamDark; + HoverColour = colours.GrayA; } - - protected override bool OnHover(HoverEvent e) - { - Content.Colour = colours.Seafoam.Lighten(30f); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - Content.Colour = colours.Seafoam; - base.OnHoverLost(e); - } - - protected override Drawable CreateContent() => new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(3), - Children = new Drawable[] - { - new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Text = Text.ToUpper(), - }, - new SpriteIcon - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Icon = FontAwesome.Solid.CaretRight, - Size = new Vector2(10), - }, - } - }; - - protected override Drawable CreateBackground() => new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - Child = background = new Box - { - RelativeSizeAxes = Axes.Both, - } - }; } } } From ec8298ac53108d65a7901228bf524ebcae794356 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 7 Sep 2019 22:33:26 +0300 Subject: [PATCH 06/31] Simplify redraw function --- .../Graphics/UserInterface/PageSelector.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector.cs index 3ca133d64b..0b0c2eec83 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector.cs @@ -58,34 +58,34 @@ namespace osu.Game.Graphics.UserInterface { base.LoadComplete(); - CurrentPage.BindValueChanged(_ => redraw(), true); + CurrentPage.BindValueChanged(page => redraw(page.NewValue), true); } - private void redraw() + private void redraw(int newPage) { - previousPageButton.Enabled.Value = CurrentPage.Value != 1; - nextPageButton.Enabled.Value = CurrentPage.Value != maxPages; + previousPageButton.Enabled.Value = newPage != 1; + nextPageButton.Enabled.Value = newPage != maxPages; pillsFlow.Clear(); - if (CurrentPage.Value > 3) + if (newPage > 3) addDrawablePage(1); - if (CurrentPage.Value > 4) + if (newPage > 4) addPlaceholder(); - for (int i = Math.Max(CurrentPage.Value - 2, 1); i <= Math.Min(CurrentPage.Value + 2, maxPages); i++) + for (int i = Math.Max(newPage - 2, 1); i <= Math.Min(newPage + 2, maxPages); i++) { - if (i == CurrentPage.Value) + if (i == newPage) addCurrentPagePill(); else addDrawablePage(i); } - if (CurrentPage.Value + 2 < maxPages - 1) + if (newPage + 2 < maxPages - 1) addPlaceholder(); - if (CurrentPage.Value + 2 < maxPages) + if (newPage + 2 < maxPages) addDrawablePage(maxPages); } From df29465ba44c974290bdaa775d78b736a2340f8d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 7 Sep 2019 23:42:30 +0300 Subject: [PATCH 07/31] Implement a single PageItem component --- .../Graphics/UserInterface/PageSelector.cs | 237 +++++++----------- 1 file changed, 86 insertions(+), 151 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector.cs index 0b0c2eec83..9dea9232ac 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector.cs @@ -7,12 +7,12 @@ using osu.Framework.Bindables; using osu.Framework.Allocation; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Events; using osu.Framework.Extensions.Color4Extensions; using System; using osuTK; using osu.Game.Graphics.Containers; using System.Collections.Generic; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Graphics.UserInterface { @@ -21,7 +21,7 @@ namespace osu.Game.Graphics.UserInterface public readonly BindableInt CurrentPage = new BindableInt(1); private readonly int maxPages; - private readonly FillFlowContainer pillsFlow; + private readonly FillFlowContainer itemsFlow; private readonly Button previousPageButton; private readonly Button nextPageButton; @@ -41,7 +41,7 @@ namespace osu.Game.Graphics.UserInterface { Action = () => CurrentPage.Value -= 1, }, - pillsFlow = new FillFlowContainer + itemsFlow = new FillFlowContainer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, @@ -66,7 +66,7 @@ namespace osu.Game.Graphics.UserInterface previousPageButton.Enabled.Value = newPage != 1; nextPageButton.Enabled.Value = newPage != maxPages; - pillsFlow.Clear(); + itemsFlow.Clear(); if (newPage > 3) addDrawablePage(1); @@ -77,7 +77,7 @@ namespace osu.Game.Graphics.UserInterface for (int i = Math.Max(newPage - 2, 1); i <= Math.Min(newPage + 2, maxPages); i++) { if (i == newPage) - addCurrentPagePill(); + addDrawableCurrentPage(); else addDrawablePage(i); } @@ -89,137 +89,101 @@ namespace osu.Game.Graphics.UserInterface addDrawablePage(maxPages); } - private void addDrawablePage(int page) + private void addDrawablePage(int page) => itemsFlow.Add(new DrawablePage(page.ToString()) { - pillsFlow.Add(new Page(page.ToString(), () => CurrentPage.Value = page)); - } + Action = () => CurrentPage.Value = page, + }); - private void addPlaceholder() - { - pillsFlow.Add(new Placeholder()); - } + private void addPlaceholder() => itemsFlow.Add(new Placeholder()); - private void addCurrentPagePill() - { - pillsFlow.Add(new SelectedPage(CurrentPage.Value.ToString())); - } + private void addDrawableCurrentPage() => itemsFlow.Add(new SelectedPage(CurrentPage.Value.ToString())); - private abstract class DrawablePage : CompositeDrawable + private abstract class PageItem : OsuHoverContainer { - private const int height = 20; private const int margin = 8; + private const int height = 20; - protected readonly string Text; - protected readonly Drawable Content; - - protected DrawablePage(string text) + protected PageItem(string text) { - Text = text; - AutoSizeAxes = Axes.X; Height = height; + var contentContainer = new CircularContainer + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Masking = true, + }; + var background = CreateBackground(); - if (background != null) - AddInternal(background); + contentContainer.Add(background); - Content = CreateContent(); - Content.Margin = new MarginPadding { Horizontal = margin }; + var drawableText = CreateText(text); + if (drawableText != null) + { + drawableText.Margin = new MarginPadding { Horizontal = margin }; + contentContainer.Add(drawableText); + } - AddInternal(Content); + Add(contentContainer); } - protected abstract Drawable CreateContent(); + protected abstract Drawable CreateText(string text); - protected virtual Drawable CreateBackground() => null; + protected abstract Drawable CreateBackground(); } - private abstract class ActivatedDrawablePage : DrawablePage + private class DrawablePage : PageItem { - protected readonly Action Action; + protected SpriteText SpriteText; - public ActivatedDrawablePage(string text, Action action = null) + protected override IEnumerable EffectTargets => new[] { SpriteText }; + + public DrawablePage(string text) : base(text) { - Action = action; } - protected override bool OnClick(ClickEvent e) + protected override Drawable CreateBackground() => null; + + protected override Drawable CreateText(string text) => SpriteText = new SpriteText { - Action?.Invoke(); - return base.OnClick(e); - } - } - - private class Page : ActivatedDrawablePage - { - private OsuColour colours; - - public Page(string text, Action action) - : base(text, action) - { - } + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = text, + }; [BackgroundDependencyLoader] private void load(OsuColour colours) { - this.colours = colours; - Content.Colour = colours.Seafoam; + IdleColour = colours.Seafoam; + HoverColour = colours.Seafoam.Lighten(30f); } - - protected override bool OnHover(HoverEvent e) - { - Content.Colour = colours.Seafoam.Lighten(30f); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - Content.Colour = colours.Seafoam; - base.OnHoverLost(e); - } - - protected override Drawable CreateContent() => new SpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = Text - }; } private class SelectedPage : DrawablePage { private Box background; + protected override IEnumerable EffectTargets => null; + public SelectedPage(string text) : base(text) { } + protected override Drawable CreateBackground() => background = new Box + { + RelativeSizeAxes = Axes.Both, + }; + [BackgroundDependencyLoader] private void load(OsuColour colours) { - Content.Colour = colours.GreySeafoam; background.Colour = colours.Seafoam; + SpriteText.Colour = colours.GreySeafoamDark; } - - protected override Drawable CreateContent() => new SpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = Text - }; - - protected override Drawable CreateBackground() => new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - Child = background = new Box - { - RelativeSizeAxes = Axes.Both, - } - }; } private class Placeholder : DrawablePage @@ -228,79 +192,28 @@ namespace osu.Game.Graphics.UserInterface : base("...") { } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - Content.Colour = colours.Seafoam; - } - - protected override Drawable CreateContent() => new SpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = Text - }; } - private class Button : OsuHoverContainer + private class Button : PageItem { - private const int height = 20; - private const int margin = 8; - - private readonly Anchor alignment; - private readonly Box background; + private Box background; + private FillFlowContainer textContainer; + private SpriteIcon icon; protected override IEnumerable EffectTargets => new[] { background }; public Button(bool rightAligned, string text) + : base(text) { - alignment = rightAligned ? Anchor.x0 : Anchor.x2; + var alignment = rightAligned ? Anchor.x0 : Anchor.x2; - AutoSizeAxes = Axes.X; - Height = height; - - Child = new CircularContainer + textContainer.ForEach(drawable => { - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Masking = true, - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both, - }, - new Container - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Child = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Horizontal = margin }, - Direction = FillDirection.Horizontal, - Children = new Drawable[] - { - new SpriteText - { - Anchor = Anchor.y1 | alignment, - Origin = Anchor.y1 | alignment, - Text = text.ToUpper(), - }, - new SpriteIcon - { - Anchor = Anchor.y1 | alignment, - Origin = Anchor.y1 | alignment, - Icon = alignment == Anchor.x2 ? FontAwesome.Solid.ChevronLeft : FontAwesome.Solid.ChevronRight, - Size = new Vector2(10), - }, - } - } - } - } - }; + drawable.Anchor = Anchor.y1 | alignment; + drawable.Origin = Anchor.y1 | alignment; + }); + + icon.Icon = alignment == Anchor.x2 ? FontAwesome.Solid.ChevronLeft : FontAwesome.Solid.ChevronRight; } [BackgroundDependencyLoader] @@ -309,6 +222,28 @@ namespace osu.Game.Graphics.UserInterface IdleColour = colours.GreySeafoamDark; HoverColour = colours.GrayA; } + + protected override Drawable CreateBackground() => background = new Box + { + RelativeSizeAxes = Axes.Both, + }; + + protected override Drawable CreateText(string text) => textContainer = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + new SpriteText + { + Text = text.ToUpper(), + }, + icon = new SpriteIcon + { + Size = new Vector2(10), + }, + } + }; } } } From b0884d16fbcc4a540af86f40aa359a577d39d988 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 8 Sep 2019 00:13:23 +0300 Subject: [PATCH 08/31] Visual adjustments --- .../Graphics/UserInterface/PageSelector.cs | 67 +++++++++++++------ 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector.cs index 9dea9232ac..9a5ffad0d4 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector.cs @@ -13,6 +13,7 @@ using osuTK; using osu.Game.Graphics.Containers; using System.Collections.Generic; using osu.Framework.Extensions.IEnumerableExtensions; +using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface { @@ -100,38 +101,47 @@ namespace osu.Game.Graphics.UserInterface private abstract class PageItem : OsuHoverContainer { - private const int margin = 8; + private const int margin = 10; private const int height = 20; + protected override Container Content => contentContainer; + + private readonly CircularContainer contentContainer; + protected PageItem(string text) { AutoSizeAxes = Axes.X; Height = height; - var contentContainer = new CircularContainer + base.Content.Add(contentContainer = new CircularContainer { AutoSizeAxes = Axes.X, RelativeSizeAxes = Axes.Y, Masking = true, - }; + }); var background = CreateBackground(); if (background != null) - contentContainer.Add(background); + Add(background); var drawableText = CreateText(text); if (drawableText != null) { drawableText.Margin = new MarginPadding { Horizontal = margin }; - contentContainer.Add(drawableText); + Add(drawableText); } + } - Add(contentContainer); + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + IdleColour = colours.Seafoam; + HoverColour = colours.Seafoam.Lighten(30f); } protected abstract Drawable CreateText(string text); - protected abstract Drawable CreateBackground(); + protected virtual Drawable CreateBackground() => null; } private class DrawablePage : PageItem @@ -145,28 +155,20 @@ namespace osu.Game.Graphics.UserInterface { } - protected override Drawable CreateBackground() => null; - protected override Drawable CreateText(string text) => SpriteText = new SpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, Text = text, + Font = OsuFont.GetFont(size: 12), }; - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - IdleColour = colours.Seafoam; - HoverColour = colours.Seafoam.Lighten(30f); - } } private class SelectedPage : DrawablePage { private Box background; - protected override IEnumerable EffectTargets => null; + protected override IEnumerable EffectTargets => new[] { background }; public SelectedPage(string text) : base(text) @@ -181,7 +183,6 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(OsuColour colours) { - background.Colour = colours.Seafoam; SpriteText.Colour = colours.GreySeafoamDark; } } @@ -196,11 +197,14 @@ namespace osu.Game.Graphics.UserInterface private class Button : PageItem { + private const int duration = 100; + private Box background; private FillFlowContainer textContainer; private SpriteIcon icon; + private readonly Box fadeBox; - protected override IEnumerable EffectTargets => new[] { background }; + protected override IEnumerable EffectTargets => new[] { textContainer }; public Button(bool rightAligned, string text) : base(text) @@ -214,13 +218,29 @@ namespace osu.Game.Graphics.UserInterface }); icon.Icon = alignment == Anchor.x2 ? FontAwesome.Solid.ChevronLeft : FontAwesome.Solid.ChevronRight; + + Add(fadeBox = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(100) + }); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - IdleColour = colours.GreySeafoamDark; - HoverColour = colours.GrayA; + background.Colour = colours.GreySeafoamDark; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Enabled.BindValueChanged(onEnabledChanged, true); + } + + private void onEnabledChanged(ValueChangedEvent enabled) + { + fadeBox.FadeTo(enabled.NewValue ? 0 : 1, duration); } protected override Drawable CreateBackground() => background = new Box @@ -231,16 +251,19 @@ namespace osu.Game.Graphics.UserInterface protected override Drawable CreateText(string text) => textContainer = new FillFlowContainer { AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Direction = FillDirection.Horizontal, Children = new Drawable[] { new SpriteText { Text = text.ToUpper(), + Font = OsuFont.GetFont(size: 12), }, icon = new SpriteIcon { - Size = new Vector2(10), + Size = new Vector2(8), }, } }; From b97f4a81db6a35ba5fac734bbdb0f8b42a948419 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 8 Sep 2019 00:27:40 +0300 Subject: [PATCH 09/31] Add more testing --- .../UserInterface/TestScenePageSelector.cs | 22 +++++++++++++++++++ .../Graphics/UserInterface/PageSelector.cs | 18 +++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index e5efa65c91..cb83fbd028 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -22,6 +22,28 @@ namespace osu.Game.Tests.Visual.UserInterface Anchor = Anchor.Centre, Origin = Anchor.Centre, }; + + AddStep("1 max pages", () => redraw(1)); + AddStep("10 max pages", () => redraw(10)); + AddStep("200 max pages, current 199", () => redraw(200, 199)); + AddStep("200 max pages, current 201", () => redraw(200, 201)); + AddStep("200 max pages, current -10", () => redraw(200, -10)); + } + + private void redraw(int maxPages, int currentPage = 0) + { + Clear(); + + var selector = new PageSelector(maxPages) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; + + if (currentPage != 0) + selector.CurrentPage.Value = currentPage; + + Add(selector); } } } diff --git a/osu.Game/Graphics/UserInterface/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector.cs index 9a5ffad0d4..79a1680e4b 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector.cs @@ -59,11 +59,25 @@ namespace osu.Game.Graphics.UserInterface { base.LoadComplete(); - CurrentPage.BindValueChanged(page => redraw(page.NewValue), true); + CurrentPage.BindValueChanged(_ => redraw(), true); } - private void redraw(int newPage) + private void redraw() { + if (CurrentPage.Value > maxPages) + { + CurrentPage.Value = maxPages; + return; + } + + if (CurrentPage.Value < 1) + { + CurrentPage.Value = 1; + return; + } + + int newPage = CurrentPage.Value; + previousPageButton.Enabled.Value = newPage != 1; nextPageButton.Enabled.Value = newPage != maxPages; From 0451b45fab4ed1a377f99e7f508e7b9c0b451ef6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 8 Sep 2019 00:37:11 +0300 Subject: [PATCH 10/31] Add missing blank line --- osu.Game/Graphics/UserInterface/PageSelector.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Graphics/UserInterface/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector.cs index 79a1680e4b..9db6366ad6 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector.cs @@ -139,6 +139,7 @@ namespace osu.Game.Graphics.UserInterface Add(background); var drawableText = CreateText(text); + if (drawableText != null) { drawableText.Margin = new MarginPadding { Horizontal = margin }; From bee7760d29e884dff532828e3bbb1f1d71fd3d6d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 10 Sep 2019 01:36:25 +0300 Subject: [PATCH 11/31] Make MaxPages value a bindable --- .../UserInterface/TestScenePageSelector.cs | 47 ++++++++++--------- .../Graphics/UserInterface/PageSelector.cs | 40 ++++++++++++---- 2 files changed, 57 insertions(+), 30 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index cb83fbd028..14cb27c97e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -15,35 +15,40 @@ namespace osu.Game.Tests.Visual.UserInterface typeof(PageSelector) }; + private readonly PageSelector pageSelector; + public TestScenePageSelector() { - Child = new PageSelector(200) + Child = pageSelector = new PageSelector { Anchor = Anchor.Centre, Origin = Anchor.Centre, }; - AddStep("1 max pages", () => redraw(1)); - AddStep("10 max pages", () => redraw(10)); - AddStep("200 max pages, current 199", () => redraw(200, 199)); - AddStep("200 max pages, current 201", () => redraw(200, 201)); - AddStep("200 max pages, current -10", () => redraw(200, -10)); - } - - private void redraw(int maxPages, int currentPage = 0) - { - Clear(); - - var selector = new PageSelector(maxPages) + AddStep("10 max pages", () => setMaxPages(10)); + AddStep("200 max pages, current 199", () => { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }; - - if (currentPage != 0) - selector.CurrentPage.Value = currentPage; - - Add(selector); + setMaxPages(200); + setCurrentPage(199); + }); + AddStep("200 max pages, current 201", () => + { + setMaxPages(200); + setCurrentPage(201); + }); + AddStep("200 max pages, current -10", () => + { + setMaxPages(200); + setCurrentPage(-10); + }); + AddStep("-10 max pages", () => + { + setMaxPages(-10); + }); } + + private void setMaxPages(int maxPages) => pageSelector.MaxPages.Value = maxPages; + + private void setCurrentPage(int currentPage) => pageSelector.CurrentPage.Value = currentPage; } } diff --git a/osu.Game/Graphics/UserInterface/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector.cs index 9db6366ad6..66f51a6dad 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector.cs @@ -20,17 +20,15 @@ namespace osu.Game.Graphics.UserInterface public class PageSelector : CompositeDrawable { public readonly BindableInt CurrentPage = new BindableInt(1); + public readonly BindableInt MaxPages = new BindableInt(1); - private readonly int maxPages; private readonly FillFlowContainer itemsFlow; private readonly Button previousPageButton; private readonly Button nextPageButton; - public PageSelector(int maxPages) + public PageSelector() { - this.maxPages = maxPages; - AutoSizeAxes = Axes.Both; InternalChild = new FillFlowContainer { @@ -59,24 +57,48 @@ namespace osu.Game.Graphics.UserInterface { base.LoadComplete(); - CurrentPage.BindValueChanged(_ => redraw(), true); + MaxPages.BindValueChanged(pagesAmount => onMaxPagesChanged(pagesAmount.NewValue), true); + CurrentPage.BindValueChanged(page => onCurrentPageChanged(page.NewValue), true); } - private void redraw() + private void onMaxPagesChanged(int pagesAmount) { - if (CurrentPage.Value > maxPages) + if (pagesAmount < 1) { - CurrentPage.Value = maxPages; + MaxPages.Value = 1; return; } - if (CurrentPage.Value < 1) + if (CurrentPage.Value > pagesAmount) + { + CurrentPage.Value = pagesAmount; + return; + } + + redraw(); + } + + private void onCurrentPageChanged(int newPage) + { + if (newPage > MaxPages.Value) + { + CurrentPage.Value = MaxPages.Value; + return; + } + + if (newPage < 1) { CurrentPage.Value = 1; return; } + redraw(); + } + + private void redraw() + { int newPage = CurrentPage.Value; + int maxPages = MaxPages.Value; previousPageButton.Enabled.Value = newPage != 1; nextPageButton.Enabled.Value = newPage != maxPages; From eb683b079b5c8dd20888a8dab9ce5ac8daf6077a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 10 Sep 2019 05:12:50 +0300 Subject: [PATCH 12/31] Adjust colours --- osu.Game/Graphics/UserInterface/PageSelector.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector.cs index 66f51a6dad..25e6ed654c 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector.cs @@ -172,8 +172,8 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(OsuColour colours) { - IdleColour = colours.Seafoam; - HoverColour = colours.Seafoam.Lighten(30f); + IdleColour = colours.Lime; + HoverColour = colours.Lime.Lighten(20f); } protected abstract Drawable CreateText(string text); From 41be9b3f8f08dd691a38ab1ff50872d126fe9f2e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 19 Sep 2019 16:45:38 +0300 Subject: [PATCH 13/31] Add asserts to the test scene --- osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index 14cb27c97e..3516e23f98 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -36,15 +36,18 @@ namespace osu.Game.Tests.Visual.UserInterface setMaxPages(200); setCurrentPage(201); }); + AddAssert("Current equals max", () => pageSelector.CurrentPage.Value == pageSelector.MaxPages.Value); AddStep("200 max pages, current -10", () => { setMaxPages(200); setCurrentPage(-10); }); + AddAssert("Current is 1", () => pageSelector.CurrentPage.Value == 1); AddStep("-10 max pages", () => { setMaxPages(-10); }); + AddAssert("Current is 1, max is 1", () => pageSelector.CurrentPage.Value == 1 && pageSelector.MaxPages.Value == 1); } private void setMaxPages(int maxPages) => pageSelector.MaxPages.Value = maxPages; From 2c0694257cd82e1dd539e0fb88424db7a6e1daba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Dec 2019 14:44:34 +0900 Subject: [PATCH 14/31] Fix incorrect spritetext usage --- osu.Game/Graphics/UserInterface/PageSelector.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector.cs index 25e6ed654c..c9f0f3c74d 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector.cs @@ -13,6 +13,7 @@ using osuTK; using osu.Game.Graphics.Containers; using System.Collections.Generic; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Game.Graphics.Sprites; using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface @@ -192,7 +193,7 @@ namespace osu.Game.Graphics.UserInterface { } - protected override Drawable CreateText(string text) => SpriteText = new SpriteText + protected override Drawable CreateText(string text) => SpriteText = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -293,7 +294,7 @@ namespace osu.Game.Graphics.UserInterface Direction = FillDirection.Horizontal, Children = new Drawable[] { - new SpriteText + new OsuSpriteText { Text = text.ToUpper(), Font = OsuFont.GetFont(size: 12), From 6fbbee3093a124021ee80bb053807dba8ec71832 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 4 Jan 2020 19:03:39 +0300 Subject: [PATCH 15/31] Move PageSelector to another namespace and organize TestScene --- .../UserInterface/TestScenePageSelector.cs | 18 +++++++++++++----- .../{ => PageSelector}/PageSelector.cs | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) rename osu.Game/Graphics/UserInterface/{ => PageSelector}/PageSelector.cs (99%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index 3516e23f98..59491b7f90 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -3,8 +3,9 @@ using System; using System.Collections.Generic; -using osu.Game.Graphics.UserInterface; +using NUnit.Framework; using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface.PageSelector; namespace osu.Game.Tests.Visual.UserInterface { @@ -19,12 +20,19 @@ namespace osu.Game.Tests.Visual.UserInterface public TestScenePageSelector() { - Child = pageSelector = new PageSelector + AddRange(new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }; + pageSelector = new PageSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }); + } + [Test] + public void TestPageSelectorValues() + { AddStep("10 max pages", () => setMaxPages(10)); AddStep("200 max pages, current 199", () => { diff --git a/osu.Game/Graphics/UserInterface/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs similarity index 99% rename from osu.Game/Graphics/UserInterface/PageSelector.cs rename to osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs index c9f0f3c74d..6767cb3a75 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs @@ -16,7 +16,7 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Graphics.Sprites; using osuTK.Graphics; -namespace osu.Game.Graphics.UserInterface +namespace osu.Game.Graphics.UserInterface.PageSelector { public class PageSelector : CompositeDrawable { From 70387c19f3f4be9413541b2588d1cf0d9de49d60 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 4 Jan 2020 19:36:05 +0300 Subject: [PATCH 16/31] Implement proper DrawablePage component --- .../UserInterface/TestScenePageSelector.cs | 17 ++- .../PageSelector/DrawablePage.cs | 108 ++++++++++++++++++ .../PageSelector/PageSelector.cs | 2 + 3 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index 59491b7f90..aad640ab58 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -13,10 +13,12 @@ namespace osu.Game.Tests.Visual.UserInterface { public override IReadOnlyList RequiredTypes => new[] { - typeof(PageSelector) + typeof(PageSelector), + typeof(DrawablePage) }; private readonly PageSelector pageSelector; + private readonly DrawablePage drawablePage; public TestScenePageSelector() { @@ -26,6 +28,12 @@ namespace osu.Game.Tests.Visual.UserInterface { Anchor = Anchor.Centre, Origin = Anchor.Centre, + }, + drawablePage = new DrawablePage(1234) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Margin = new MarginPadding { Top = 50 }, } }); } @@ -58,6 +66,13 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("Current is 1, max is 1", () => pageSelector.CurrentPage.Value == 1 && pageSelector.MaxPages.Value == 1); } + [Test] + public void TestDrawablePage() + { + AddStep("Select", () => drawablePage.Selected = true); + AddStep("Deselect", () => drawablePage.Selected = false); + } + private void setMaxPages(int maxPages) => pageSelector.MaxPages.Value = maxPages; private void setCurrentPage(int currentPage) => pageSelector.CurrentPage.Value = currentPage; diff --git a/osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs b/osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs new file mode 100644 index 0000000000..fe91874159 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs @@ -0,0 +1,108 @@ +// 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.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Framework.Bindables; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Extensions.Color4Extensions; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Framework.Input.Events; + +namespace osu.Game.Graphics.UserInterface.PageSelector +{ + public class DrawablePage : OsuClickableContainer + { + private const int duration = 200; + + private readonly BindableBool selected = new BindableBool(); + + public bool Selected + { + get => selected.Value; + set => selected.Value = value; + } + + [Resolved] + private OsuColour colours { get; set; } + + private readonly Box background; + private readonly OsuSpriteText text; + + public DrawablePage(int page) + { + AutoSizeAxes = Axes.X; + Height = PageSelector.HEIGHT; + Child = new CircularContainer + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Masking = true, + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + }, + text = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = page.ToString(), + Font = OsuFont.GetFont(size: 12), + Margin = new MarginPadding { Horizontal = 10 } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load() + { + background.Colour = colours.Lime; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + selected.BindValueChanged(onSelectedChanged, true); + } + + private void onSelectedChanged(ValueChangedEvent selected) + { + background.FadeTo(selected.NewValue ? 1 : 0, duration, Easing.OutQuint); + text.FadeColour(selected.NewValue ? colours.GreySeafoamDarker : colours.Lime, duration, Easing.OutQuint); + } + + protected override bool OnClick(ClickEvent e) + { + if (!selected.Value) + selected.Value = true; + + return base.OnClick(e); + } + + protected override bool OnHover(HoverEvent e) + { + updateHoverState(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + updateHoverState(); + } + + private void updateHoverState() + { + if (selected.Value) + return; + + text.FadeColour(IsHovered ? colours.Lime.Lighten(20f) : colours.Lime, duration, Easing.OutQuint); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs index 6767cb3a75..54e3a035ec 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs @@ -20,6 +20,8 @@ namespace osu.Game.Graphics.UserInterface.PageSelector { public class PageSelector : CompositeDrawable { + public const int HEIGHT = 20; + public readonly BindableInt CurrentPage = new BindableInt(1); public readonly BindableInt MaxPages = new BindableInt(1); From 9af9da039da0c696a3277f4f19d5251a7561883f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 4 Jan 2020 21:14:56 +0300 Subject: [PATCH 17/31] Implement proper PageSelectorItem --- .../UserInterface/TestScenePageSelector.cs | 5 +- .../PageSelector/DrawablePage.cs | 79 ++--- .../PageSelector/PageSelector.cs | 284 +++--------------- .../PageSelector/PageSelectorButton.cs | 77 +++++ .../PageSelector/PageSelectorItem.cs | 75 +++++ 5 files changed, 222 insertions(+), 298 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs create mode 100644 osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index aad640ab58..33deff58dc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -14,7 +14,9 @@ namespace osu.Game.Tests.Visual.UserInterface public override IReadOnlyList RequiredTypes => new[] { typeof(PageSelector), - typeof(DrawablePage) + typeof(DrawablePage), + typeof(PageSelectorButton), + typeof(PageSelectorItem) }; private readonly PageSelector pageSelector; @@ -42,6 +44,7 @@ namespace osu.Game.Tests.Visual.UserInterface public void TestPageSelectorValues() { AddStep("10 max pages", () => setMaxPages(10)); + AddStep("11 max pages", () => setMaxPages(11)); AddStep("200 max pages, current 199", () => { setMaxPages(200); diff --git a/osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs b/osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs index fe91874159..20f418085d 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs @@ -1,22 +1,16 @@ // 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.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Bindables; using osu.Framework.Allocation; -using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions.Color4Extensions; -using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Framework.Input.Events; namespace osu.Game.Graphics.UserInterface.PageSelector { - public class DrawablePage : OsuClickableContainer + public class DrawablePage : PageSelectorItem { - private const int duration = 200; - private readonly BindableBool selected = new BindableBool(); public bool Selected @@ -25,44 +19,33 @@ namespace osu.Game.Graphics.UserInterface.PageSelector set => selected.Value = value; } - [Resolved] - private OsuColour colours { get; set; } + public int Page { get; private set; } - private readonly Box background; - private readonly OsuSpriteText text; + private OsuSpriteText text; public DrawablePage(int page) { - AutoSizeAxes = Axes.X; - Height = PageSelector.HEIGHT; - Child = new CircularContainer + Page = page; + text.Text = page.ToString(); + + Background.Alpha = 0; + + Action = () => { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Masking = true, - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - }, - text = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = page.ToString(), - Font = OsuFont.GetFont(size: 12), - Margin = new MarginPadding { Horizontal = 10 } - } - } + if (!selected.Value) + selected.Value = true; }; } + protected override Drawable CreateContent() => text = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 12), + }; + [BackgroundDependencyLoader] private void load() { - background.Colour = colours.Lime; + Background.Colour = Colours.Lime; } protected override void LoadComplete() @@ -73,36 +56,16 @@ namespace osu.Game.Graphics.UserInterface.PageSelector private void onSelectedChanged(ValueChangedEvent selected) { - background.FadeTo(selected.NewValue ? 1 : 0, duration, Easing.OutQuint); - text.FadeColour(selected.NewValue ? colours.GreySeafoamDarker : colours.Lime, duration, Easing.OutQuint); + Background.FadeTo(selected.NewValue ? 1 : 0, DURATION, Easing.OutQuint); + text.FadeColour(selected.NewValue ? Colours.GreySeafoamDarker : Colours.Lime, DURATION, Easing.OutQuint); } - protected override bool OnClick(ClickEvent e) - { - if (!selected.Value) - selected.Value = true; - - return base.OnClick(e); - } - - protected override bool OnHover(HoverEvent e) - { - updateHoverState(); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - base.OnHoverLost(e); - updateHoverState(); - } - - private void updateHoverState() + protected override void UpdateHoverState() { if (selected.Value) return; - text.FadeColour(IsHovered ? colours.Lime.Lighten(20f) : colours.Lime, duration, Easing.OutQuint); + text.FadeColour(IsHovered ? Colours.Lime.Lighten(20f) : Colours.Lime, DURATION, Easing.OutQuint); } } } diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs index 54e3a035ec..ae6fc2b500 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs @@ -4,17 +4,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Bindables; -using osu.Framework.Allocation; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Extensions.Color4Extensions; -using System; -using osuTK; -using osu.Game.Graphics.Containers; -using System.Collections.Generic; using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Game.Graphics.Sprites; -using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface.PageSelector { @@ -25,10 +15,10 @@ namespace osu.Game.Graphics.UserInterface.PageSelector public readonly BindableInt CurrentPage = new BindableInt(1); public readonly BindableInt MaxPages = new BindableInt(1); - private readonly FillFlowContainer itemsFlow; + private readonly FillFlowContainer itemsFlow; - private readonly Button previousPageButton; - private readonly Button nextPageButton; + private readonly PageSelectorButton previousPageButton; + private readonly PageSelectorButton nextPageButton; public PageSelector() { @@ -39,16 +29,16 @@ namespace osu.Game.Graphics.UserInterface.PageSelector Direction = FillDirection.Horizontal, Children = new Drawable[] { - previousPageButton = new Button(false, "prev") + previousPageButton = new PageSelectorButton(false, "prev") { Action = () => CurrentPage.Value -= 1, }, - itemsFlow = new FillFlowContainer + itemsFlow = new FillFlowContainer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, }, - nextPageButton = new Button(true, "next") + nextPageButton = new PageSelectorButton(true, "next") { Action = () => CurrentPage.Value += 1 } @@ -60,253 +50,69 @@ namespace osu.Game.Graphics.UserInterface.PageSelector { base.LoadComplete(); - MaxPages.BindValueChanged(pagesAmount => onMaxPagesChanged(pagesAmount.NewValue), true); - CurrentPage.BindValueChanged(page => onCurrentPageChanged(page.NewValue), true); - } - - private void onMaxPagesChanged(int pagesAmount) - { - if (pagesAmount < 1) - { - MaxPages.Value = 1; - return; - } - - if (CurrentPage.Value > pagesAmount) - { - CurrentPage.Value = pagesAmount; - return; - } - + MaxPages.BindValueChanged(_ => redraw()); + CurrentPage.BindValueChanged(page => onCurrentPageChanged(page.NewValue)); redraw(); } private void onCurrentPageChanged(int newPage) { - if (newPage > MaxPages.Value) - { - CurrentPage.Value = MaxPages.Value; - return; - } - if (newPage < 1) { CurrentPage.Value = 1; return; } - redraw(); + if (newPage > MaxPages.Value) + { + CurrentPage.Value = MaxPages.Value; + return; + } + + itemsFlow.ForEach(page => page.Selected = page.Page == newPage ? true : false); + updateButtonsState(); } private void redraw() + { + itemsFlow.Clear(); + + if (MaxPages.Value < 1) + { + MaxPages.Value = 1; + return; + } + + for (int i = 1; i <= MaxPages.Value; i++) + addDrawablePage(i); + + if (CurrentPage.Value > MaxPages.Value) + { + CurrentPage.Value = MaxPages.Value; + return; + } + + if (CurrentPage.Value < 1) + { + CurrentPage.Value = 1; + return; + } + + CurrentPage.TriggerChange(); + } + + private void updateButtonsState() { int newPage = CurrentPage.Value; int maxPages = MaxPages.Value; previousPageButton.Enabled.Value = newPage != 1; nextPageButton.Enabled.Value = newPage != maxPages; - - itemsFlow.Clear(); - - if (newPage > 3) - addDrawablePage(1); - - if (newPage > 4) - addPlaceholder(); - - for (int i = Math.Max(newPage - 2, 1); i <= Math.Min(newPage + 2, maxPages); i++) - { - if (i == newPage) - addDrawableCurrentPage(); - else - addDrawablePage(i); - } - - if (newPage + 2 < maxPages - 1) - addPlaceholder(); - - if (newPage + 2 < maxPages) - addDrawablePage(maxPages); } - private void addDrawablePage(int page) => itemsFlow.Add(new DrawablePage(page.ToString()) + private void addDrawablePage(int page) => itemsFlow.Add(new DrawablePage(page) { Action = () => CurrentPage.Value = page, }); - - private void addPlaceholder() => itemsFlow.Add(new Placeholder()); - - private void addDrawableCurrentPage() => itemsFlow.Add(new SelectedPage(CurrentPage.Value.ToString())); - - private abstract class PageItem : OsuHoverContainer - { - private const int margin = 10; - private const int height = 20; - - protected override Container Content => contentContainer; - - private readonly CircularContainer contentContainer; - - protected PageItem(string text) - { - AutoSizeAxes = Axes.X; - Height = height; - - base.Content.Add(contentContainer = new CircularContainer - { - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Masking = true, - }); - - var background = CreateBackground(); - if (background != null) - Add(background); - - var drawableText = CreateText(text); - - if (drawableText != null) - { - drawableText.Margin = new MarginPadding { Horizontal = margin }; - Add(drawableText); - } - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - IdleColour = colours.Lime; - HoverColour = colours.Lime.Lighten(20f); - } - - protected abstract Drawable CreateText(string text); - - protected virtual Drawable CreateBackground() => null; - } - - private class DrawablePage : PageItem - { - protected SpriteText SpriteText; - - protected override IEnumerable EffectTargets => new[] { SpriteText }; - - public DrawablePage(string text) - : base(text) - { - } - - protected override Drawable CreateText(string text) => SpriteText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = text, - Font = OsuFont.GetFont(size: 12), - }; - } - - private class SelectedPage : DrawablePage - { - private Box background; - - protected override IEnumerable EffectTargets => new[] { background }; - - public SelectedPage(string text) - : base(text) - { - } - - protected override Drawable CreateBackground() => background = new Box - { - RelativeSizeAxes = Axes.Both, - }; - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - SpriteText.Colour = colours.GreySeafoamDark; - } - } - - private class Placeholder : DrawablePage - { - public Placeholder() - : base("...") - { - } - } - - private class Button : PageItem - { - private const int duration = 100; - - private Box background; - private FillFlowContainer textContainer; - private SpriteIcon icon; - private readonly Box fadeBox; - - protected override IEnumerable EffectTargets => new[] { textContainer }; - - public Button(bool rightAligned, string text) - : base(text) - { - var alignment = rightAligned ? Anchor.x0 : Anchor.x2; - - textContainer.ForEach(drawable => - { - drawable.Anchor = Anchor.y1 | alignment; - drawable.Origin = Anchor.y1 | alignment; - }); - - icon.Icon = alignment == Anchor.x2 ? FontAwesome.Solid.ChevronLeft : FontAwesome.Solid.ChevronRight; - - Add(fadeBox = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black.Opacity(100) - }); - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - background.Colour = colours.GreySeafoamDark; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - Enabled.BindValueChanged(onEnabledChanged, true); - } - - private void onEnabledChanged(ValueChangedEvent enabled) - { - fadeBox.FadeTo(enabled.NewValue ? 0 : 1, duration); - } - - protected override Drawable CreateBackground() => background = new Box - { - RelativeSizeAxes = Axes.Both, - }; - - protected override Drawable CreateText(string text) => textContainer = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Direction = FillDirection.Horizontal, - Children = new Drawable[] - { - new OsuSpriteText - { - Text = text.ToUpper(), - Font = OsuFont.GetFont(size: 12), - }, - icon = new SpriteIcon - { - Size = new Vector2(8), - }, - } - }; - } } } diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs new file mode 100644 index 0000000000..df007b32e0 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs @@ -0,0 +1,77 @@ +// 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.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Extensions.Color4Extensions; +using osu.Game.Graphics.Sprites; +using osu.Framework.Graphics.Sprites; +using osuTK.Graphics; +using osuTK; +using osu.Framework.Extensions.IEnumerableExtensions; + +namespace osu.Game.Graphics.UserInterface.PageSelector +{ + public class PageSelectorButton : PageSelectorItem + { + private readonly Box fadeBox; + private SpriteIcon icon; + private OsuSpriteText name; + private FillFlowContainer buttonContent; + + public PageSelectorButton(bool rightAligned, string text) + { + Add(fadeBox = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(100) + }); + + var alignment = rightAligned ? Anchor.x0 : Anchor.x2; + + buttonContent.ForEach(drawable => + { + drawable.Anchor = Anchor.y1 | alignment; + drawable.Origin = Anchor.y1 | alignment; + }); + + icon.Icon = alignment == Anchor.x2 ? FontAwesome.Solid.ChevronLeft : FontAwesome.Solid.ChevronRight; + + name.Text = text.ToUpper(); + } + + protected override Drawable CreateContent() => buttonContent = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + name = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 12), + }, + icon = new SpriteIcon + { + Size = new Vector2(8), + }, + } + }; + + [BackgroundDependencyLoader] + private void load() + { + Background.Colour = Colours.GreySeafoamDark; + name.Colour = icon.Colour = Colours.Lime; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Enabled.BindValueChanged(enabled => fadeBox.FadeTo(enabled.NewValue ? 0 : 1, DURATION), true); + } + + protected override void UpdateHoverState() => Background.FadeColour(IsHovered ? Colours.GreySeafoam : Colours.GreySeafoamDark, DURATION, Easing.OutQuint); + } +} diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs new file mode 100644 index 0000000000..d457b7ea0e --- /dev/null +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs @@ -0,0 +1,75 @@ +// 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.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Framework.Bindables; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Extensions.Color4Extensions; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Framework.Graphics.Sprites; +using osuTK.Graphics; +using osuTK; +using osu.Framework.Extensions.IEnumerableExtensions; +using JetBrains.Annotations; + +namespace osu.Game.Graphics.UserInterface.PageSelector +{ + public abstract class PageSelectorItem : OsuClickableContainer + { + protected const int DURATION = 200; + + [Resolved] + protected OsuColour Colours { get; private set; } + + protected override Container Content => content; + + protected readonly Box Background; + private readonly CircularContainer content; + + protected PageSelectorItem() + { + AutoSizeAxes = Axes.X; + Height = PageSelector.HEIGHT; + base.Content.Add(content = new CircularContainer + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Masking = true, + Children = new Drawable[] + { + Background = new Box + { + RelativeSizeAxes = Axes.Both + }, + CreateContent().With(content => + { + content.Anchor = Anchor.Centre; + content.Origin = Anchor.Centre; + content.Margin = new MarginPadding { Horizontal = 10 }; + }) + } + }); + } + + [NotNull] + protected abstract Drawable CreateContent(); + + protected override bool OnHover(HoverEvent e) + { + UpdateHoverState(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + UpdateHoverState(); + } + + protected abstract void UpdateHoverState(); + } +} From b1c5e437ccf2ca260d5b8f177d78144651b1d24d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 4 Jan 2020 21:22:45 +0300 Subject: [PATCH 18/31] Remove usings --- .../UserInterface/PageSelector/PageSelectorItem.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs index d457b7ea0e..63eb87a638 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs @@ -3,17 +3,10 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; -using osu.Framework.Bindables; using osu.Framework.Allocation; using osu.Framework.Graphics.Shapes; -using osu.Framework.Extensions.Color4Extensions; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; using osu.Framework.Input.Events; -using osu.Framework.Graphics.Sprites; -using osuTK.Graphics; -using osuTK; -using osu.Framework.Extensions.IEnumerableExtensions; using JetBrains.Annotations; namespace osu.Game.Graphics.UserInterface.PageSelector From 37482b2ad474379ed941a5ab3a8c40f813427eaf Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 4 Jan 2020 22:05:34 +0300 Subject: [PATCH 19/31] CI fixes --- osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs | 2 +- .../Graphics/UserInterface/PageSelector/PageSelectorItem.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs index ae6fc2b500..eaa102bdd2 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs @@ -69,7 +69,7 @@ namespace osu.Game.Graphics.UserInterface.PageSelector return; } - itemsFlow.ForEach(page => page.Selected = page.Page == newPage ? true : false); + itemsFlow.ForEach(page => page.Selected = page.Page == newPage); updateButtonsState(); } diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs index 63eb87a638..5f0bfcdfdb 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs @@ -32,7 +32,7 @@ namespace osu.Game.Graphics.UserInterface.PageSelector RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, Masking = true, - Children = new Drawable[] + Children = new[] { Background = new Box { From d3c2dc43bd28812bafffb6d81a596268ed5ddca1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 4 Jan 2020 22:25:08 +0300 Subject: [PATCH 20/31] TestScene improvements --- .../UserInterface/TestScenePageSelector.cs | 48 +++++++++---------- .../PageSelector/PageSelector.cs | 15 ++---- .../PageSelector/PageSelectorButton.cs | 1 + 3 files changed, 27 insertions(+), 37 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index 33deff58dc..5e1105c834 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -41,32 +41,30 @@ namespace osu.Game.Tests.Visual.UserInterface } [Test] - public void TestPageSelectorValues() + public void TestCurrentPageReset() { - AddStep("10 max pages", () => setMaxPages(10)); - AddStep("11 max pages", () => setMaxPages(11)); - AddStep("200 max pages, current 199", () => - { - setMaxPages(200); - setCurrentPage(199); - }); - AddStep("200 max pages, current 201", () => - { - setMaxPages(200); - setCurrentPage(201); - }); - AddAssert("Current equals max", () => pageSelector.CurrentPage.Value == pageSelector.MaxPages.Value); - AddStep("200 max pages, current -10", () => - { - setMaxPages(200); - setCurrentPage(-10); - }); - AddAssert("Current is 1", () => pageSelector.CurrentPage.Value == 1); - AddStep("-10 max pages", () => - { - setMaxPages(-10); - }); - AddAssert("Current is 1, max is 1", () => pageSelector.CurrentPage.Value == 1 && pageSelector.MaxPages.Value == 1); + AddStep("Set 10 pages", () => setMaxPages(10)); + AddStep("Select 5 page", () => setCurrentPage(5)); + AddStep("Set 11 pages", () => setMaxPages(11)); + AddAssert("Check 1 page is current", () => pageSelector.CurrentPage.Value == 1); + } + + [Test] + public void TestUnexistingPageSelection() + { + AddStep("Set 10 pages", () => setMaxPages(10)); + AddStep("Select 11 page", () => setCurrentPage(11)); + AddAssert("Check current equals max", () => pageSelector.CurrentPage.Value == pageSelector.MaxPages.Value); + + AddStep("Select -1 page", () => setCurrentPage(-1)); + AddAssert("Check current is 1", () => pageSelector.CurrentPage.Value == 1); + } + + [Test] + public void TestNegativeMaxPages() + { + AddStep("Set -10 pages", () => setMaxPages(-10)); + AddAssert("Check current and max is 1", () => pageSelector.CurrentPage.Value == 1 && pageSelector.MaxPages.Value == 1); } [Test] diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs index eaa102bdd2..c2482d6330 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs @@ -86,19 +86,10 @@ namespace osu.Game.Graphics.UserInterface.PageSelector for (int i = 1; i <= MaxPages.Value; i++) addDrawablePage(i); - if (CurrentPage.Value > MaxPages.Value) - { - CurrentPage.Value = MaxPages.Value; - return; - } - - if (CurrentPage.Value < 1) - { + if (CurrentPage.Value == 1) + CurrentPage.TriggerChange(); + else CurrentPage.Value = 1; - return; - } - - CurrentPage.TriggerChange(); } private void updateButtonsState() diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs index df007b32e0..e81ce20d27 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs @@ -46,6 +46,7 @@ namespace osu.Game.Graphics.UserInterface.PageSelector { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, + Spacing = new Vector2(3, 0), Children = new Drawable[] { name = new OsuSpriteText From 753db9599a225784c19e3459b6d830d5f62683c6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 4 Jan 2020 22:29:11 +0300 Subject: [PATCH 21/31] Move items height out of PageSelector --- osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs | 2 -- .../Graphics/UserInterface/PageSelector/PageSelectorItem.cs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs index c2482d6330..8e055faea3 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs @@ -10,8 +10,6 @@ namespace osu.Game.Graphics.UserInterface.PageSelector { public class PageSelector : CompositeDrawable { - public const int HEIGHT = 20; - public readonly BindableInt CurrentPage = new BindableInt(1); public readonly BindableInt MaxPages = new BindableInt(1); diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs index 5f0bfcdfdb..cd61961dbe 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs @@ -26,7 +26,7 @@ namespace osu.Game.Graphics.UserInterface.PageSelector protected PageSelectorItem() { AutoSizeAxes = Axes.X; - Height = PageSelector.HEIGHT; + Height = 20; base.Content.Add(content = new CircularContainer { RelativeSizeAxes = Axes.Y, From 20ab415838fab4cca9fcf4675d908670032d1b56 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 6 Jan 2020 18:04:27 +0900 Subject: [PATCH 22/31] Reword tests --- .../UserInterface/TestScenePageSelector.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index 5e1105c834..6494486d4e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -41,30 +41,31 @@ namespace osu.Game.Tests.Visual.UserInterface } [Test] - public void TestCurrentPageReset() + public void TestResetCurrentPage() { AddStep("Set 10 pages", () => setMaxPages(10)); - AddStep("Select 5 page", () => setCurrentPage(5)); + AddStep("Select page 5", () => setCurrentPage(5)); AddStep("Set 11 pages", () => setMaxPages(11)); - AddAssert("Check 1 page is current", () => pageSelector.CurrentPage.Value == 1); + AddAssert("Page 1 is current", () => pageSelector.CurrentPage.Value == 1); } [Test] - public void TestUnexistingPageSelection() + public void TestOutOfBoundsSelection() { AddStep("Set 10 pages", () => setMaxPages(10)); - AddStep("Select 11 page", () => setCurrentPage(11)); - AddAssert("Check current equals max", () => pageSelector.CurrentPage.Value == pageSelector.MaxPages.Value); + AddStep("Select page 11", () => setCurrentPage(11)); + AddAssert("Page 10 is current", () => pageSelector.CurrentPage.Value == pageSelector.MaxPages.Value); - AddStep("Select -1 page", () => setCurrentPage(-1)); - AddAssert("Check current is 1", () => pageSelector.CurrentPage.Value == 1); + AddStep("Select page -1", () => setCurrentPage(-1)); + AddAssert("Page 1 is current", () => pageSelector.CurrentPage.Value == 1); } [Test] public void TestNegativeMaxPages() { AddStep("Set -10 pages", () => setMaxPages(-10)); - AddAssert("Check current and max is 1", () => pageSelector.CurrentPage.Value == 1 && pageSelector.MaxPages.Value == 1); + AddAssert("Page 1 is current", () => pageSelector.CurrentPage.Value == 1); + AddAssert("Max is 1", () => pageSelector.MaxPages.Value == 1); } [Test] From 1c899e4402bcc891f3e5a46126fae65151372928 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Jan 2022 16:46:42 +0900 Subject: [PATCH 23/31] Fix post-merge issues --- .../Visual/UserInterface/TestScenePageSelector.cs | 10 ---------- .../UserInterface/PageSelector/DrawablePage.cs | 2 +- .../UserInterface/PageSelector/PageSelector.cs | 1 + .../UserInterface/PageSelector/PageSelectorButton.cs | 4 ++-- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index 6494486d4e..8a15dd9b46 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface.PageSelector; @@ -11,14 +9,6 @@ namespace osu.Game.Tests.Visual.UserInterface { public class TestScenePageSelector : OsuTestScene { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(PageSelector), - typeof(DrawablePage), - typeof(PageSelectorButton), - typeof(PageSelectorItem) - }; - private readonly PageSelector pageSelector; private readonly DrawablePage drawablePage; diff --git a/osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs b/osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs index 20f418085d..4ea610bd89 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs @@ -57,7 +57,7 @@ namespace osu.Game.Graphics.UserInterface.PageSelector private void onSelectedChanged(ValueChangedEvent selected) { Background.FadeTo(selected.NewValue ? 1 : 0, DURATION, Easing.OutQuint); - text.FadeColour(selected.NewValue ? Colours.GreySeafoamDarker : Colours.Lime, DURATION, Easing.OutQuint); + text.FadeColour(selected.NewValue ? Colours.GreySeaFoamDarker : Colours.Lime, DURATION, Easing.OutQuint); } protected override void UpdateHoverState() diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs index 8e055faea3..612cf82b9f 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs @@ -21,6 +21,7 @@ namespace osu.Game.Graphics.UserInterface.PageSelector public PageSelector() { AutoSizeAxes = Axes.Both; + InternalChild = new FillFlowContainer { AutoSizeAxes = Axes.Both, diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs index e81ce20d27..4eba549dc3 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs @@ -63,7 +63,7 @@ namespace osu.Game.Graphics.UserInterface.PageSelector [BackgroundDependencyLoader] private void load() { - Background.Colour = Colours.GreySeafoamDark; + Background.Colour = Colours.GreySeaFoamDark; name.Colour = icon.Colour = Colours.Lime; } @@ -73,6 +73,6 @@ namespace osu.Game.Graphics.UserInterface.PageSelector Enabled.BindValueChanged(enabled => fadeBox.FadeTo(enabled.NewValue ? 0 : 1, DURATION), true); } - protected override void UpdateHoverState() => Background.FadeColour(IsHovered ? Colours.GreySeafoam : Colours.GreySeafoamDark, DURATION, Easing.OutQuint); + protected override void UpdateHoverState() => Background.FadeColour(IsHovered ? Colours.GreySeaFoam : Colours.GreySeaFoamDark, DURATION, Easing.OutQuint); } } From db58f5de8e6ea8c6dd14695b59a39aed33c82c9d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Jan 2022 16:58:32 +0900 Subject: [PATCH 24/31] Clean up unnecessary complexity --- .../PageSelector/DrawablePage.cs | 8 +- .../PageSelector/PageSelectorButton.cs | 80 +++++++++++-------- .../PageSelector/PageSelectorItem.cs | 12 ++- 3 files changed, 56 insertions(+), 44 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs b/osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs index 4ea610bd89..2610ae7571 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs @@ -15,20 +15,16 @@ namespace osu.Game.Graphics.UserInterface.PageSelector public bool Selected { - get => selected.Value; set => selected.Value = value; } - public int Page { get; private set; } + public int Page { get; } private OsuSpriteText text; public DrawablePage(int page) { Page = page; - text.Text = page.ToString(); - - Background.Alpha = 0; Action = () => { @@ -40,12 +36,14 @@ namespace osu.Game.Graphics.UserInterface.PageSelector protected override Drawable CreateContent() => text = new OsuSpriteText { Font = OsuFont.GetFont(size: 12), + Text = Page.ToString(), }; [BackgroundDependencyLoader] private void load() { Background.Colour = Colours.Lime; + Background.Alpha = 0; } protected override void LoadComplete() diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs index 4eba549dc3..1492319fc9 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs @@ -1,61 +1,64 @@ // 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.Graphics.Containers; -using osu.Framework.Graphics; using osu.Framework.Allocation; -using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions.Color4Extensions; -using osu.Game.Graphics.Sprites; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; -using osuTK.Graphics; +using osu.Game.Graphics.Sprites; using osuTK; -using osu.Framework.Extensions.IEnumerableExtensions; +using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface.PageSelector { public class PageSelectorButton : PageSelectorItem { - private readonly Box fadeBox; + private readonly string text; + + private Box fadeBox; private SpriteIcon icon; private OsuSpriteText name; - private FillFlowContainer buttonContent; + + private readonly Anchor alignment; public PageSelectorButton(bool rightAligned, string text) { - Add(fadeBox = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black.Opacity(100) - }); - - var alignment = rightAligned ? Anchor.x0 : Anchor.x2; - - buttonContent.ForEach(drawable => - { - drawable.Anchor = Anchor.y1 | alignment; - drawable.Origin = Anchor.y1 | alignment; - }); - - icon.Icon = alignment == Anchor.x2 ? FontAwesome.Solid.ChevronLeft : FontAwesome.Solid.ChevronRight; - - name.Text = text.ToUpper(); + this.text = text; + alignment = rightAligned ? Anchor.x0 : Anchor.x2; } - protected override Drawable CreateContent() => buttonContent = new FillFlowContainer + protected override Drawable CreateContent() => new Container { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(3, 0), + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, Children = new Drawable[] { - name = new OsuSpriteText + new FillFlowContainer { - Font = OsuFont.GetFont(size: 12), - }, - icon = new SpriteIcon - { - Size = new Vector2(8), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Spacing = new Vector2(3, 0), + Children = new Drawable[] + { + name = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 12), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = text.ToUpper(), + }, + icon = new SpriteIcon + { + Icon = alignment == Anchor.x2 ? FontAwesome.Solid.ChevronLeft : FontAwesome.Solid.ChevronRight, + Size = new Vector2(8), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + } }, } }; @@ -70,6 +73,13 @@ namespace osu.Game.Graphics.UserInterface.PageSelector protected override void LoadComplete() { base.LoadComplete(); + + CircularContent.Add(fadeBox = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(100) + }); + Enabled.BindValueChanged(enabled => fadeBox.FadeTo(enabled.NewValue ? 0 : 1, DURATION), true); } diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs index cd61961dbe..92bf958ca9 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs @@ -18,16 +18,20 @@ namespace osu.Game.Graphics.UserInterface.PageSelector [Resolved] protected OsuColour Colours { get; private set; } - protected override Container Content => content; + protected Box Background; - protected readonly Box Background; - private readonly CircularContainer content; + public CircularContainer CircularContent { get; private set; } protected PageSelectorItem() { AutoSizeAxes = Axes.X; Height = 20; - base.Content.Add(content = new CircularContainer + } + + [BackgroundDependencyLoader] + private void load() + { + Add(CircularContent = new CircularContainer { RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, From ee4f5c0e79e11c2f8e9a9c574beddb16a2174652 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Jan 2022 17:52:40 +0900 Subject: [PATCH 25/31] Rename button classes to make more sense --- .../UserInterface/TestScenePageSelector.cs | 8 +- .../PageSelector/PageSelector.cs | 14 +-- .../PageSelector/PageSelectorButton.cs | 112 ++++++++---------- .../PageSelector/PageSelectorItem.cs | 72 ----------- ...wablePage.cs => PageSelectorPageButton.cs} | 4 +- .../PageSelectorPrevNextButton.cs | 88 ++++++++++++++ 6 files changed, 149 insertions(+), 149 deletions(-) delete mode 100644 osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs rename osu.Game/Graphics/UserInterface/PageSelector/{DrawablePage.cs => PageSelectorPageButton.cs} (94%) create mode 100644 osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index 8a15dd9b46..000e75be31 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -10,7 +10,7 @@ namespace osu.Game.Tests.Visual.UserInterface public class TestScenePageSelector : OsuTestScene { private readonly PageSelector pageSelector; - private readonly DrawablePage drawablePage; + private readonly PageSelectorPageButton pageSelectorPageButton; public TestScenePageSelector() { @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual.UserInterface Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - drawablePage = new DrawablePage(1234) + pageSelectorPageButton = new PageSelectorPageButton(1234) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -61,8 +61,8 @@ namespace osu.Game.Tests.Visual.UserInterface [Test] public void TestDrawablePage() { - AddStep("Select", () => drawablePage.Selected = true); - AddStep("Deselect", () => drawablePage.Selected = false); + AddStep("Select", () => pageSelectorPageButton.Selected = true); + AddStep("Deselect", () => pageSelectorPageButton.Selected = false); } private void setMaxPages(int maxPages) => pageSelector.MaxPages.Value = maxPages; diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs index 612cf82b9f..4089fb5511 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs @@ -13,10 +13,10 @@ namespace osu.Game.Graphics.UserInterface.PageSelector public readonly BindableInt CurrentPage = new BindableInt(1); public readonly BindableInt MaxPages = new BindableInt(1); - private readonly FillFlowContainer itemsFlow; + private readonly FillFlowContainer itemsFlow; - private readonly PageSelectorButton previousPageButton; - private readonly PageSelectorButton nextPageButton; + private readonly PageSelectorPrevNextButton previousPageButton; + private readonly PageSelectorPrevNextButton nextPageButton; public PageSelector() { @@ -28,16 +28,16 @@ namespace osu.Game.Graphics.UserInterface.PageSelector Direction = FillDirection.Horizontal, Children = new Drawable[] { - previousPageButton = new PageSelectorButton(false, "prev") + previousPageButton = new PageSelectorPrevNextButton(false, "prev") { Action = () => CurrentPage.Value -= 1, }, - itemsFlow = new FillFlowContainer + itemsFlow = new FillFlowContainer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, }, - nextPageButton = new PageSelectorButton(true, "next") + nextPageButton = new PageSelectorPrevNextButton(true, "next") { Action = () => CurrentPage.Value += 1 } @@ -100,7 +100,7 @@ namespace osu.Game.Graphics.UserInterface.PageSelector nextPageButton.Enabled.Value = newPage != maxPages; } - private void addDrawablePage(int page) => itemsFlow.Add(new DrawablePage(page) + private void addDrawablePage(int page) => itemsFlow.Add(new PageSelectorPageButton(page) { Action = () => CurrentPage.Value = page, }); diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs index 1492319fc9..bdfe66f1d0 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs @@ -1,88 +1,72 @@ // 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.Extensions.Color4Extensions; -using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Framework.Allocation; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics.Sprites; -using osuTK; -using osuTK.Graphics; +using osu.Game.Graphics.Containers; +using osu.Framework.Input.Events; +using JetBrains.Annotations; namespace osu.Game.Graphics.UserInterface.PageSelector { - public class PageSelectorButton : PageSelectorItem + public abstract class PageSelectorButton : OsuClickableContainer { - private readonly string text; + protected const int DURATION = 200; - private Box fadeBox; - private SpriteIcon icon; - private OsuSpriteText name; + [Resolved] + protected OsuColour Colours { get; private set; } - private readonly Anchor alignment; + protected Box Background; - public PageSelectorButton(bool rightAligned, string text) + public CircularContainer CircularContent { get; private set; } + + protected PageSelectorButton() { - this.text = text; - alignment = rightAligned ? Anchor.x0 : Anchor.x2; + AutoSizeAxes = Axes.X; + Height = 20; } - protected override Drawable CreateContent() => new Container - { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Children = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Spacing = new Vector2(3, 0), - Children = new Drawable[] - { - name = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 12), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = text.ToUpper(), - }, - icon = new SpriteIcon - { - Icon = alignment == Anchor.x2 ? FontAwesome.Solid.ChevronLeft : FontAwesome.Solid.ChevronRight, - Size = new Vector2(8), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - } - }, - } - }; - [BackgroundDependencyLoader] private void load() { - Background.Colour = Colours.GreySeaFoamDark; - name.Colour = icon.Colour = Colours.Lime; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - CircularContent.Add(fadeBox = new Box + Add(CircularContent = new CircularContainer { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black.Opacity(100) + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Masking = true, + Children = new[] + { + Background = new Box + { + RelativeSizeAxes = Axes.Both + }, + CreateContent().With(content => + { + content.Anchor = Anchor.Centre; + content.Origin = Anchor.Centre; + content.Margin = new MarginPadding { Horizontal = 10 }; + }) + } }); - - Enabled.BindValueChanged(enabled => fadeBox.FadeTo(enabled.NewValue ? 0 : 1, DURATION), true); } - protected override void UpdateHoverState() => Background.FadeColour(IsHovered ? Colours.GreySeaFoam : Colours.GreySeaFoamDark, DURATION, Easing.OutQuint); + [NotNull] + protected abstract Drawable CreateContent(); + + protected override bool OnHover(HoverEvent e) + { + UpdateHoverState(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + UpdateHoverState(); + } + + protected abstract void UpdateHoverState(); } } diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs deleted file mode 100644 index 92bf958ca9..0000000000 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorItem.cs +++ /dev/null @@ -1,72 +0,0 @@ -// 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.Graphics.Containers; -using osu.Framework.Graphics; -using osu.Framework.Allocation; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics.Containers; -using osu.Framework.Input.Events; -using JetBrains.Annotations; - -namespace osu.Game.Graphics.UserInterface.PageSelector -{ - public abstract class PageSelectorItem : OsuClickableContainer - { - protected const int DURATION = 200; - - [Resolved] - protected OsuColour Colours { get; private set; } - - protected Box Background; - - public CircularContainer CircularContent { get; private set; } - - protected PageSelectorItem() - { - AutoSizeAxes = Axes.X; - Height = 20; - } - - [BackgroundDependencyLoader] - private void load() - { - Add(CircularContent = new CircularContainer - { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Masking = true, - Children = new[] - { - Background = new Box - { - RelativeSizeAxes = Axes.Both - }, - CreateContent().With(content => - { - content.Anchor = Anchor.Centre; - content.Origin = Anchor.Centre; - content.Margin = new MarginPadding { Horizontal = 10 }; - }) - } - }); - } - - [NotNull] - protected abstract Drawable CreateContent(); - - protected override bool OnHover(HoverEvent e) - { - UpdateHoverState(); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - base.OnHoverLost(e); - UpdateHoverState(); - } - - protected abstract void UpdateHoverState(); - } -} diff --git a/osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs similarity index 94% rename from osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs rename to osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs index 2610ae7571..81ab7c7155 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/DrawablePage.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface.PageSelector { - public class DrawablePage : PageSelectorItem + public class PageSelectorPageButton : PageSelectorButton { private readonly BindableBool selected = new BindableBool(); @@ -22,7 +22,7 @@ namespace osu.Game.Graphics.UserInterface.PageSelector private OsuSpriteText text; - public DrawablePage(int page) + public PageSelectorPageButton(int page) { Page = page; diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs new file mode 100644 index 0000000000..eaa3714fea --- /dev/null +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs @@ -0,0 +1,88 @@ +// 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.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Graphics.UserInterface.PageSelector +{ + public class PageSelectorPrevNextButton : PageSelectorButton + { + private readonly string text; + + private Box fadeBox; + private SpriteIcon icon; + private OsuSpriteText name; + + private readonly Anchor alignment; + + public PageSelectorPrevNextButton(bool rightAligned, string text) + { + this.text = text; + alignment = rightAligned ? Anchor.x0 : Anchor.x2; + } + + protected override Drawable CreateContent() => new Container + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Spacing = new Vector2(3, 0), + Children = new Drawable[] + { + name = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 12), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = text.ToUpper(), + }, + icon = new SpriteIcon + { + Icon = alignment == Anchor.x2 ? FontAwesome.Solid.ChevronLeft : FontAwesome.Solid.ChevronRight, + Size = new Vector2(8), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + } + }, + } + }; + + [BackgroundDependencyLoader] + private void load() + { + Background.Colour = Colours.GreySeaFoamDark; + name.Colour = icon.Colour = Colours.Lime; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + CircularContent.Add(fadeBox = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(100) + }); + + Enabled.BindValueChanged(enabled => fadeBox.FadeTo(enabled.NewValue ? 0 : 1, DURATION), true); + } + + protected override void UpdateHoverState() => Background.FadeColour(IsHovered ? Colours.GreySeaFoam : Colours.GreySeaFoamDark, DURATION, Easing.OutQuint); + } +} From d10b8c79b39682f144f7c117a7c8278822485bfb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Jan 2022 17:53:23 +0900 Subject: [PATCH 26/31] Remove pointless test coverage of `DrawablePage` --- .../Visual/UserInterface/TestScenePageSelector.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index 000e75be31..b65af6b1f5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -10,7 +10,6 @@ namespace osu.Game.Tests.Visual.UserInterface public class TestScenePageSelector : OsuTestScene { private readonly PageSelector pageSelector; - private readonly PageSelectorPageButton pageSelectorPageButton; public TestScenePageSelector() { @@ -21,12 +20,6 @@ namespace osu.Game.Tests.Visual.UserInterface Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - pageSelectorPageButton = new PageSelectorPageButton(1234) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Margin = new MarginPadding { Top = 50 }, - } }); } @@ -58,13 +51,6 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("Max is 1", () => pageSelector.MaxPages.Value == 1); } - [Test] - public void TestDrawablePage() - { - AddStep("Select", () => pageSelectorPageButton.Selected = true); - AddStep("Deselect", () => pageSelectorPageButton.Selected = false); - } - private void setMaxPages(int maxPages) => pageSelector.MaxPages.Value = maxPages; private void setCurrentPage(int currentPage) => pageSelector.CurrentPage.Value = currentPage; From 5a11ee7810b705461360c2b3daa2e27b1e3b05ff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Jan 2022 18:14:42 +0900 Subject: [PATCH 27/31] Use `OverlayColourProvider` and fix font weight --- .../UserInterface/TestScenePageSelector.cs | 5 +++ .../PageSelector/PageSelectorButton.cs | 7 ++-- .../PageSelector/PageSelectorPageButton.cs | 9 +++-- .../PageSelectorPrevNextButton.cs | 34 +++++++------------ 4 files changed, 24 insertions(+), 31 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index b65af6b1f5..1595a7f22d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -2,13 +2,18 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface.PageSelector; +using osu.Game.Overlays; namespace osu.Game.Tests.Visual.UserInterface { public class TestScenePageSelector : OsuTestScene { + [Cached] + private OverlayColourProvider provider { get; } = new OverlayColourProvider(OverlayColourScheme.Green); + private readonly PageSelector pageSelector; public TestScenePageSelector() diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs index bdfe66f1d0..a2c6e8532b 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Containers; using osu.Framework.Input.Events; using JetBrains.Annotations; +using osu.Game.Overlays; namespace osu.Game.Graphics.UserInterface.PageSelector { @@ -16,12 +17,10 @@ namespace osu.Game.Graphics.UserInterface.PageSelector protected const int DURATION = 200; [Resolved] - protected OsuColour Colours { get; private set; } + protected OverlayColourProvider ColourProvider { get; private set; } protected Box Background; - public CircularContainer CircularContent { get; private set; } - protected PageSelectorButton() { AutoSizeAxes = Axes.X; @@ -31,7 +30,7 @@ namespace osu.Game.Graphics.UserInterface.PageSelector [BackgroundDependencyLoader] private void load() { - Add(CircularContent = new CircularContainer + Add(new CircularContainer { RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs index 81ab7c7155..31aca0d2f2 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs @@ -4,7 +4,6 @@ using osu.Framework.Graphics; using osu.Framework.Bindables; using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; using osu.Game.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface.PageSelector @@ -35,14 +34,14 @@ namespace osu.Game.Graphics.UserInterface.PageSelector protected override Drawable CreateContent() => text = new OsuSpriteText { - Font = OsuFont.GetFont(size: 12), + Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold), Text = Page.ToString(), }; [BackgroundDependencyLoader] private void load() { - Background.Colour = Colours.Lime; + Background.Colour = ColourProvider.Highlight1; Background.Alpha = 0; } @@ -55,7 +54,7 @@ namespace osu.Game.Graphics.UserInterface.PageSelector private void onSelectedChanged(ValueChangedEvent selected) { Background.FadeTo(selected.NewValue ? 1 : 0, DURATION, Easing.OutQuint); - text.FadeColour(selected.NewValue ? Colours.GreySeaFoamDarker : Colours.Lime, DURATION, Easing.OutQuint); + text.FadeColour(selected.NewValue ? ColourProvider.Dark4 : ColourProvider.Light3, DURATION, Easing.OutQuint); } protected override void UpdateHoverState() @@ -63,7 +62,7 @@ namespace osu.Game.Graphics.UserInterface.PageSelector if (selected.Value) return; - text.FadeColour(IsHovered ? Colours.Lime.Lighten(20f) : Colours.Lime, DURATION, Easing.OutQuint); + text.FadeColour(IsHovered ? ColourProvider.Light2 : ColourProvider.Light1, DURATION, Easing.OutQuint); } } } diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs index eaa3714fea..7503ab8135 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs @@ -2,31 +2,26 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Sprites; using osuTK; -using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface.PageSelector { public class PageSelectorPrevNextButton : PageSelectorButton { + private readonly bool rightAligned; private readonly string text; - private Box fadeBox; private SpriteIcon icon; private OsuSpriteText name; - private readonly Anchor alignment; - public PageSelectorPrevNextButton(bool rightAligned, string text) { + this.rightAligned = rightAligned; this.text = text; - alignment = rightAligned ? Anchor.x0 : Anchor.x2; } protected override Drawable CreateContent() => new Container @@ -47,16 +42,16 @@ namespace osu.Game.Graphics.UserInterface.PageSelector name = new OsuSpriteText { Font = OsuFont.GetFont(size: 12), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, + Anchor = rightAligned ? Anchor.CentreLeft : Anchor.CentreRight, + Origin = rightAligned ? Anchor.CentreLeft : Anchor.CentreRight, Text = text.ToUpper(), }, icon = new SpriteIcon { - Icon = alignment == Anchor.x2 ? FontAwesome.Solid.ChevronLeft : FontAwesome.Solid.ChevronRight, + Icon = rightAligned ? FontAwesome.Solid.ChevronRight : FontAwesome.Solid.ChevronLeft, Size = new Vector2(8), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, + Anchor = rightAligned ? Anchor.CentreLeft : Anchor.CentreRight, + Origin = rightAligned ? Anchor.CentreLeft : Anchor.CentreRight, }, } }, @@ -66,23 +61,18 @@ namespace osu.Game.Graphics.UserInterface.PageSelector [BackgroundDependencyLoader] private void load() { - Background.Colour = Colours.GreySeaFoamDark; - name.Colour = icon.Colour = Colours.Lime; + Background.Colour = ColourProvider.Dark4; + name.Colour = icon.Colour = ColourProvider.Light1; } protected override void LoadComplete() { base.LoadComplete(); - CircularContent.Add(fadeBox = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black.Opacity(100) - }); - - Enabled.BindValueChanged(enabled => fadeBox.FadeTo(enabled.NewValue ? 0 : 1, DURATION), true); + Enabled.BindValueChanged(enabled => Background.FadeTo(enabled.NewValue ? 1 : 0.5f, DURATION), true); } - protected override void UpdateHoverState() => Background.FadeColour(IsHovered ? Colours.GreySeaFoam : Colours.GreySeaFoamDark, DURATION, Easing.OutQuint); + protected override void UpdateHoverState() => + Background.FadeColour(IsHovered ? ColourProvider.Dark3 : ColourProvider.Dark4, DURATION, Easing.OutQuint); } } From e75c9519f32f8e44e1beac1e57b83798a1f8d547 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Jan 2022 18:19:23 +0900 Subject: [PATCH 28/31] Adjust font weighting on selection --- .../UserInterface/PageSelector/PageSelectorPageButton.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs index 31aca0d2f2..6aac75565e 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs @@ -54,7 +54,9 @@ namespace osu.Game.Graphics.UserInterface.PageSelector private void onSelectedChanged(ValueChangedEvent selected) { Background.FadeTo(selected.NewValue ? 1 : 0, DURATION, Easing.OutQuint); + text.FadeColour(selected.NewValue ? ColourProvider.Dark4 : ColourProvider.Light3, DURATION, Easing.OutQuint); + text.Font = text.Font.With(weight: IsHovered ? FontWeight.SemiBold : FontWeight.Regular); } protected override void UpdateHoverState() From 86f72b71b1229c165d30d419047165b00cdaafc7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Jan 2022 18:46:44 +0900 Subject: [PATCH 29/31] Prepare tests and general structure to support omission of pages --- .../UserInterface/TestScenePageSelector.cs | 42 ++++++------ .../PageSelector/PageSelector.cs | 66 +++++++------------ .../PageSelector/PageSelectorPageButton.cs | 8 +-- 3 files changed, 52 insertions(+), 64 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index 1595a7f22d..3b32a2a0dc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -1,9 +1,11 @@ // 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 NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Testing; using osu.Game.Graphics.UserInterface.PageSelector; using osu.Game.Overlays; @@ -28,36 +30,38 @@ namespace osu.Game.Tests.Visual.UserInterface }); } + [Test] + public void TestOmittedPages() + { + setAvailablePages(100); + + AddAssert("Correct page buttons", () => pageSelector.ChildrenOfType().Select(p => p.PageNumber).SequenceEqual(new[] { 1, 2, 3, 100 })); + } + [Test] public void TestResetCurrentPage() { - AddStep("Set 10 pages", () => setMaxPages(10)); - AddStep("Select page 5", () => setCurrentPage(5)); - AddStep("Set 11 pages", () => setMaxPages(11)); - AddAssert("Page 1 is current", () => pageSelector.CurrentPage.Value == 1); + setAvailablePages(10); + selectPage(6); + setAvailablePages(11); + AddAssert("Page 1 is current", () => pageSelector.CurrentPage.Value == 0); } [Test] public void TestOutOfBoundsSelection() { - AddStep("Set 10 pages", () => setMaxPages(10)); - AddStep("Select page 11", () => setCurrentPage(11)); - AddAssert("Page 10 is current", () => pageSelector.CurrentPage.Value == pageSelector.MaxPages.Value); + setAvailablePages(10); + selectPage(11); + AddAssert("Page 10 is current", () => pageSelector.CurrentPage.Value == pageSelector.AvailablePages.Value - 1); - AddStep("Select page -1", () => setCurrentPage(-1)); - AddAssert("Page 1 is current", () => pageSelector.CurrentPage.Value == 1); + selectPage(-1); + AddAssert("Page 1 is current", () => pageSelector.CurrentPage.Value == 0); } - [Test] - public void TestNegativeMaxPages() - { - AddStep("Set -10 pages", () => setMaxPages(-10)); - AddAssert("Page 1 is current", () => pageSelector.CurrentPage.Value == 1); - AddAssert("Max is 1", () => pageSelector.MaxPages.Value == 1); - } + private void selectPage(int pageIndex) => + AddStep($"Select page {pageIndex}", () => pageSelector.CurrentPage.Value = pageIndex); - private void setMaxPages(int maxPages) => pageSelector.MaxPages.Value = maxPages; - - private void setCurrentPage(int currentPage) => pageSelector.CurrentPage.Value = currentPage; + private void setAvailablePages(int availablePages) => + AddStep($"Set available pages to {availablePages}", () => pageSelector.AvailablePages.Value = availablePages); } } diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs index 4089fb5511..ae644bb852 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs @@ -1,19 +1,20 @@ // 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 osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Bindables; -using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Graphics.UserInterface.PageSelector { public class PageSelector : CompositeDrawable { - public readonly BindableInt CurrentPage = new BindableInt(1); - public readonly BindableInt MaxPages = new BindableInt(1); + public readonly BindableInt CurrentPage = new BindableInt { MinValue = 0, }; - private readonly FillFlowContainer itemsFlow; + public readonly BindableInt AvailablePages = new BindableInt(1) { MinValue = 1, }; + + private readonly FillFlowContainer itemsFlow; private readonly PageSelectorPrevNextButton previousPageButton; private readonly PageSelectorPrevNextButton nextPageButton; @@ -32,7 +33,7 @@ namespace osu.Game.Graphics.UserInterface.PageSelector { Action = () => CurrentPage.Value -= 1, }, - itemsFlow = new FillFlowContainer + itemsFlow = new FillFlowContainer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, @@ -49,60 +50,43 @@ namespace osu.Game.Graphics.UserInterface.PageSelector { base.LoadComplete(); - MaxPages.BindValueChanged(_ => redraw()); - CurrentPage.BindValueChanged(page => onCurrentPageChanged(page.NewValue)); - redraw(); + CurrentPage.BindValueChanged(onCurrentPageChanged); + AvailablePages.BindValueChanged(_ => redraw(), true); } - private void onCurrentPageChanged(int newPage) + private void onCurrentPageChanged(ValueChangedEvent currentPage) { - if (newPage < 1) + if (currentPage.NewValue >= AvailablePages.Value) { - CurrentPage.Value = 1; + CurrentPage.Value = AvailablePages.Value - 1; return; } - if (newPage > MaxPages.Value) - { - CurrentPage.Value = MaxPages.Value; - return; - } + foreach (var page in itemsFlow.OfType()) + page.Selected = page.PageNumber == currentPage.NewValue + 1; - itemsFlow.ForEach(page => page.Selected = page.Page == newPage); - updateButtonsState(); + previousPageButton.Enabled.Value = currentPage.NewValue != 0; + nextPageButton.Enabled.Value = currentPage.NewValue < AvailablePages.Value - 1; } private void redraw() { itemsFlow.Clear(); - if (MaxPages.Value < 1) + for (int i = 0; i < AvailablePages.Value; i++) { - MaxPages.Value = 1; - return; + int pageIndex = i; + + itemsFlow.Add(new PageSelectorPageButton(pageIndex + 1) + { + Action = () => CurrentPage.Value = pageIndex, + }); } - for (int i = 1; i <= MaxPages.Value; i++) - addDrawablePage(i); - - if (CurrentPage.Value == 1) - CurrentPage.TriggerChange(); + if (CurrentPage.Value != 0) + CurrentPage.Value = 0; else - CurrentPage.Value = 1; + CurrentPage.TriggerChange(); } - - private void updateButtonsState() - { - int newPage = CurrentPage.Value; - int maxPages = MaxPages.Value; - - previousPageButton.Enabled.Value = newPage != 1; - nextPageButton.Enabled.Value = newPage != maxPages; - } - - private void addDrawablePage(int page) => itemsFlow.Add(new PageSelectorPageButton(page) - { - Action = () => CurrentPage.Value = page, - }); } } diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs index 6aac75565e..247a003492 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs @@ -17,13 +17,13 @@ namespace osu.Game.Graphics.UserInterface.PageSelector set => selected.Value = value; } - public int Page { get; } + public int PageNumber { get; } private OsuSpriteText text; - public PageSelectorPageButton(int page) + public PageSelectorPageButton(int pageNumber) { - Page = page; + PageNumber = pageNumber; Action = () => { @@ -35,7 +35,7 @@ namespace osu.Game.Graphics.UserInterface.PageSelector protected override Drawable CreateContent() => text = new OsuSpriteText { Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold), - Text = Page.ToString(), + Text = PageNumber.ToString(), }; [BackgroundDependencyLoader] From 5ed69338a662165d7374e3de1940ad2997f35faa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Jan 2022 19:05:14 +0900 Subject: [PATCH 30/31] 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()); + } + } } } } From 2bf6b55b19a26add1ad4f3f6e19bc4b553025b95 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Jan 2022 14:53:32 +0900 Subject: [PATCH 31/31] Fix failing test due to changed reset page logic --- .../UserInterface/PageSelector/PageSelector.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs index ce74259289..005729580c 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs @@ -50,8 +50,14 @@ namespace osu.Game.Graphics.UserInterface.PageSelector { base.LoadComplete(); - CurrentPage.BindValueChanged(_ => redraw()); - AvailablePages.BindValueChanged(_ => redraw(), true); + CurrentPage.BindValueChanged(_ => Scheduler.AddOnce(redraw)); + AvailablePages.BindValueChanged(_ => + { + CurrentPage.Value = 0; + + // AddOnce as the reset of CurrentPage may also trigger a redraw. + Scheduler.AddOnce(redraw); + }, true); } private void redraw()