diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePaginatedContainerHeader.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePaginatedContainerHeader.cs new file mode 100644 index 0000000000..114a3af1d9 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePaginatedContainerHeader.cs @@ -0,0 +1,77 @@ +using NUnit.Framework; +using osu.Game.Overlays.Profile.Sections; +using osu.Framework.Testing; +using System.Linq; +using osu.Framework.Graphics; +using osu.Game.Overlays; +using osu.Framework.Allocation; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestScenePaginatedContainerHeader : OsuTestScene + { + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink); + + private PaginatedContainerHeader header; + + [Test] + public void TestHiddenCounter() + { + AddStep("Create header", () => createHeader("Header with hidden counter", CounterVisibilityState.AlwaysHidden)); + AddAssert("Value is 0", () => header.Current.Value == 0); + AddAssert("Counter is hidden", () => header.ChildrenOfType().First().Alpha == 0); + AddStep("Set count 10", () => header.Current.Value = 10); + AddAssert("Value is 10", () => header.Current.Value == 10); + AddAssert("Counter is hidden", () => header.ChildrenOfType().First().Alpha == 0); + } + + [Test] + public void TestVisibleCounter() + { + AddStep("Create header", () => createHeader("Header with visible counter", CounterVisibilityState.AlwaysVisible)); + AddAssert("Value is 0", () => header.Current.Value == 0); + AddAssert("Counter is visible", () => header.ChildrenOfType().First().Alpha == 1); + AddStep("Set count 10", () => header.Current.Value = 10); + AddAssert("Value is 10", () => header.Current.Value == 10); + AddAssert("Counter is visible", () => header.ChildrenOfType().First().Alpha == 1); + } + + [Test] + public void TestVisibleWhenZeroCounter() + { + AddStep("Create header", () => createHeader("Header with visible when zero counter", CounterVisibilityState.VisibleWhenNonZero)); + AddAssert("Value is 0", () => header.Current.Value == 0); + AddAssert("Counter is visible", () => header.ChildrenOfType().First().Alpha == 1); + AddStep("Set count 10", () => header.Current.Value = 10); + AddAssert("Value is 10", () => header.Current.Value == 10); + AddAssert("Counter is hidden", () => header.ChildrenOfType().First().Alpha == 0); + AddStep("Set count 0", () => header.Current.Value = 0); + AddAssert("Value is 0", () => header.Current.Value == 0); + AddAssert("Counter is visible", () => header.ChildrenOfType().First().Alpha == 1); + } + + [Test] + public void TestInitialVisibility() + { + AddStep("Create header with 0 value", () => createHeader("Header with visible when zero counter", CounterVisibilityState.VisibleWhenNonZero, 0)); + AddAssert("Value is 0", () => header.Current.Value == 0); + AddAssert("Counter is visible", () => header.ChildrenOfType().First().Alpha == 1); + + AddStep("Create header with 1 value", () => createHeader("Header with visible when zero counter", CounterVisibilityState.VisibleWhenNonZero, 1)); + AddAssert("Value is 1", () => header.Current.Value == 1); + AddAssert("Counter is hidden", () => header.ChildrenOfType().First().Alpha == 0); + } + + private void createHeader(string text, CounterVisibilityState state, int initialValue = 0) + { + Clear(); + Add(header = new PaginatedContainerHeader(text, state) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = { Value = initialValue } + }); + } + } +} diff --git a/osu.Game/Overlays/Profile/Sections/CounterPill.cs b/osu.Game/Overlays/Profile/Sections/CounterPill.cs index 52adefa4ad..131df105ad 100644 --- a/osu.Game/Overlays/Profile/Sections/CounterPill.cs +++ b/osu.Game/Overlays/Profile/Sections/CounterPill.cs @@ -13,8 +13,6 @@ namespace osu.Game.Overlays.Profile.Sections { public class CounterPill : CircularContainer { - private const int duration = 200; - public readonly BindableInt Current = new BindableInt(); private OsuSpriteText counter; @@ -23,7 +21,6 @@ namespace osu.Game.Overlays.Profile.Sections private void load(OverlayColourProvider colourProvider) { AutoSizeAxes = Axes.Both; - Alpha = 0; Masking = true; Children = new Drawable[] { @@ -36,8 +33,8 @@ namespace osu.Game.Overlays.Profile.Sections { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Margin = new MarginPadding { Horizontal = 10, Vertical = 5 }, - Font = OsuFont.GetFont(weight: FontWeight.Bold), + Margin = new MarginPadding { Horizontal = 10, Bottom = 1 }, + Font = OsuFont.GetFont(size: 14 * 0.8f, weight: FontWeight.Bold), Colour = colourProvider.Foreground1 } }; @@ -51,14 +48,7 @@ namespace osu.Game.Overlays.Profile.Sections private void onCurrentChanged(ValueChangedEvent value) { - if (value.NewValue == 0) - { - this.FadeOut(duration, Easing.OutQuint); - return; - } - counter.Text = value.NewValue.ToString("N0"); - this.FadeIn(duration, Easing.OutQuint); } } } diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainerHeader.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainerHeader.cs new file mode 100644 index 0000000000..e965b83682 --- /dev/null +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainerHeader.cs @@ -0,0 +1,129 @@ +using osu.Framework.Allocation; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Bindables; +using System; +using osu.Framework.Graphics.Shapes; +using osuTK; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics; + +namespace osu.Game.Overlays.Profile.Sections +{ + public class PaginatedContainerHeader : CompositeDrawable, IHasCurrentValue + { + public Bindable Current + { + get => current; + set + { + if (value == null) + throw new ArgumentNullException(nameof(value)); + + current.UnbindBindings(); + current.BindTo(value); + } + } + + private readonly Bindable current = new Bindable(); + + private readonly string text; + private readonly CounterVisibilityState counterState; + + private CounterPill counterPill; + + public PaginatedContainerHeader(string text, CounterVisibilityState counterState) + { + this.text = text; + this.counterState = counterState; + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + AutoSizeAxes = Axes.Both; + Padding = new MarginPadding { Vertical = 10 }; + InternalChildren = new Drawable[] + { + new CircularContainer + { + RelativeSizeAxes = Axes.Y, + Height = 0.65f, + Width = 3, + Masking = true, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreRight, + Margin = new MarginPadding { Right = 10 }, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colourProvider.Highlight1 + } + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = text, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), + }, + counterPill = new CounterPill + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Alpha = getInitialCounterAlpha(), + Current = { BindTarget = current } + } + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + current.BindValueChanged(onCurrentChanged); + } + + private float getInitialCounterAlpha() + { + switch (counterState) + { + case CounterVisibilityState.AlwaysHidden: + return 0; + + case CounterVisibilityState.AlwaysVisible: + return 1; + + case CounterVisibilityState.VisibleWhenNonZero: + return current.Value == 0 ? 1 : 0; + + default: + throw new NotImplementedException($"{counterState} has an incorrect value."); + } + } + + private void onCurrentChanged(ValueChangedEvent countValue) + { + if (counterState == CounterVisibilityState.VisibleWhenNonZero) + { + counterPill.Alpha = countValue.NewValue == 0 ? 1 : 0; + } + } + } + + public enum CounterVisibilityState + { + AlwaysHidden, + AlwaysVisible, + VisibleWhenNonZero + } +}