diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapSearchFilter.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapSearchFilter.cs new file mode 100644 index 0000000000..7b4424e568 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapSearchFilter.cs @@ -0,0 +1,58 @@ +// 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.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Containers; +using osu.Game.Online.API.Requests; +using osu.Game.Overlays; +using osu.Game.Overlays.BeatmapListing; +using osuTK; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneBeatmapSearchFilter : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(BeatmapSearchFilterRow<>), + typeof(BeatmapSearchRulesetFilterRow), + typeof(BeatmapSearchSmallFilterRow<>), + }; + + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); + + private readonly ReverseChildIDFillFlowContainer resizableContainer; + + public TestSceneBeatmapSearchFilter() + { + Add(resizableContainer = new ReverseChildIDFillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 10), + Children = new Drawable[] + { + new BeatmapSearchRulesetFilterRow(), + new BeatmapSearchFilterRow("Categories"), + new BeatmapSearchSmallFilterRow("Header Name") + } + }); + } + + [Test] + public void TestResize() + { + AddStep("Resize to 0.3", () => resizableContainer.ResizeWidthTo(0.3f, 1000)); + AddStep("Resize to 1", () => resizableContainer.ResizeWidthTo(1, 1000)); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 9fa6085035..6c883d9893 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -39,7 +39,7 @@ namespace osu.Game.Graphics.UserInterface private readonly Box strip; - protected override Dropdown CreateDropdown() => new OsuTabDropdown(); + protected override Dropdown CreateDropdown() => new OsuTabDropdown(); protected override TabItem CreateTabItem(T value) => new OsuTabItem(value); @@ -180,100 +180,5 @@ namespace osu.Game.Graphics.UserInterface protected override void OnDeactivated() => fadeInactive(); } - - // todo: this needs to go - private class OsuTabDropdown : OsuDropdown - { - public OsuTabDropdown() - { - RelativeSizeAxes = Axes.X; - } - - protected override DropdownMenu CreateMenu() => new OsuTabDropdownMenu(); - - protected override DropdownHeader CreateHeader() => new OsuTabDropdownHeader - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight - }; - - private class OsuTabDropdownMenu : OsuDropdownMenu - { - public OsuTabDropdownMenu() - { - Anchor = Anchor.TopRight; - Origin = Anchor.TopRight; - - BackgroundColour = Color4.Black.Opacity(0.7f); - MaxHeight = 400; - } - - protected override DrawableDropdownMenuItem CreateDrawableDropdownMenuItem(MenuItem item) => new DrawableOsuTabDropdownMenuItem(item) { AccentColour = AccentColour }; - - private class DrawableOsuTabDropdownMenuItem : DrawableOsuDropdownMenuItem - { - public DrawableOsuTabDropdownMenuItem(MenuItem item) - : base(item) - { - ForegroundColourHover = Color4.Black; - } - } - } - - protected class OsuTabDropdownHeader : OsuDropdownHeader - { - public override Color4 AccentColour - { - get => base.AccentColour; - set - { - base.AccentColour = value; - Foreground.Colour = value; - } - } - - public OsuTabDropdownHeader() - { - RelativeSizeAxes = Axes.None; - AutoSizeAxes = Axes.X; - - BackgroundColour = Color4.Black.Opacity(0.5f); - - Background.Height = 0.5f; - Background.CornerRadius = 5; - Background.Masking = true; - - Foreground.RelativeSizeAxes = Axes.None; - Foreground.AutoSizeAxes = Axes.X; - Foreground.RelativeSizeAxes = Axes.Y; - Foreground.Margin = new MarginPadding(5); - - Foreground.Children = new Drawable[] - { - new SpriteIcon - { - Icon = FontAwesome.Solid.EllipsisH, - Size = new Vector2(14), - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - } - }; - - Padding = new MarginPadding { Left = 5, Right = 5 }; - } - - protected override bool OnHover(HoverEvent e) - { - Foreground.Colour = BackgroundColour; - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - Foreground.Colour = BackgroundColourHover; - base.OnHoverLost(e); - } - } - } } } diff --git a/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs b/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs new file mode 100644 index 0000000000..24b9ca8d90 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs @@ -0,0 +1,107 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osuTK; +using osuTK.Graphics; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; + +namespace osu.Game.Graphics.UserInterface +{ + public class OsuTabDropdown : OsuDropdown + { + public OsuTabDropdown() + { + RelativeSizeAxes = Axes.X; + } + + protected override DropdownMenu CreateMenu() => new OsuTabDropdownMenu(); + + protected override DropdownHeader CreateHeader() => new OsuTabDropdownHeader + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight + }; + + private class OsuTabDropdownMenu : OsuDropdownMenu + { + public OsuTabDropdownMenu() + { + Anchor = Anchor.TopRight; + Origin = Anchor.TopRight; + + BackgroundColour = Color4.Black.Opacity(0.7f); + MaxHeight = 400; + } + + protected override DrawableDropdownMenuItem CreateDrawableDropdownMenuItem(MenuItem item) => new DrawableOsuTabDropdownMenuItem(item) { AccentColour = AccentColour }; + + private class DrawableOsuTabDropdownMenuItem : DrawableOsuDropdownMenuItem + { + public DrawableOsuTabDropdownMenuItem(MenuItem item) + : base(item) + { + ForegroundColourHover = Color4.Black; + } + } + } + + protected class OsuTabDropdownHeader : OsuDropdownHeader + { + public override Color4 AccentColour + { + get => base.AccentColour; + set + { + base.AccentColour = value; + Foreground.Colour = value; + } + } + + public OsuTabDropdownHeader() + { + RelativeSizeAxes = Axes.None; + AutoSizeAxes = Axes.X; + + BackgroundColour = Color4.Black.Opacity(0.5f); + + Background.Height = 0.5f; + Background.CornerRadius = 5; + Background.Masking = true; + + Foreground.RelativeSizeAxes = Axes.None; + Foreground.AutoSizeAxes = Axes.X; + Foreground.RelativeSizeAxes = Axes.Y; + Foreground.Margin = new MarginPadding(5); + + Foreground.Children = new Drawable[] + { + new SpriteIcon + { + Icon = FontAwesome.Solid.EllipsisH, + Size = new Vector2(14), + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + } + }; + + Padding = new MarginPadding { Left = 5, Right = 5 }; + } + + protected override bool OnHover(HoverEvent e) + { + Foreground.Colour = BackgroundColour; + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + Foreground.Colour = BackgroundColourHover; + base.OnHoverLost(e); + } + } + } +} diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs new file mode 100644 index 0000000000..2c046a2bbf --- /dev/null +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs @@ -0,0 +1,173 @@ +// 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 JetBrains.Annotations; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.BeatmapListing +{ + public class BeatmapSearchFilterRow : CompositeDrawable, IHasCurrentValue + { + private readonly BindableWithCurrent current = new BindableWithCurrent(); + + public Bindable Current + { + get => current.Current; + set => current.Current = value; + } + + public BeatmapSearchFilterRow(string headerName) + { + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; + AddInternal(new GridContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Absolute, size: 100), + new Dimension() + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize) + }, + Content = new[] + { + new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.GetFont(size: 10), + Text = headerName.ToUpper() + }, + CreateFilter().With(f => + { + f.Current = current; + }) + } + } + }); + } + + [NotNull] + protected virtual BeatmapSearchFilter CreateFilter() => new BeatmapSearchFilter(); + + protected class BeatmapSearchFilter : TabControl + { + public BeatmapSearchFilter() + { + Anchor = Anchor.BottomLeft; + Origin = Anchor.BottomLeft; + RelativeSizeAxes = Axes.X; + Height = 15; + + TabContainer.Spacing = new Vector2(10, 0); + + if (typeof(T).IsEnum) + { + foreach (var val in (T[])Enum.GetValues(typeof(T))) + AddItem(val); + } + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + ((FilterDropdown)Dropdown).AccentColour = colourProvider.Light2; + } + + protected override Dropdown CreateDropdown() => new FilterDropdown(); + + protected override TabItem CreateTabItem(T value) => new FilterTabItem(value); + + protected class FilterTabItem : TabItem + { + protected virtual float TextSize => 13; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } + + private readonly OsuSpriteText text; + + public FilterTabItem(T value) + : base(value) + { + AutoSizeAxes = Axes.Both; + Anchor = Anchor.BottomLeft; + Origin = Anchor.BottomLeft; + AddRangeInternal(new Drawable[] + { + text = new OsuSpriteText + { + Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Regular), + Text = (value as Enum)?.GetDescription() ?? value.ToString() + }, + new HoverClickSounds() + }); + + Enabled.Value = true; + } + + [BackgroundDependencyLoader] + private void load() + { + updateState(); + } + + protected override bool OnHover(HoverEvent e) + { + base.OnHover(e); + updateState(); + return true; + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + updateState(); + } + + protected override void OnActivated() => updateState(); + + protected override void OnDeactivated() => updateState(); + + private void updateState() => text.FadeColour(Active.Value ? Color4.White : getStateColour(), 200, Easing.OutQuint); + + private Color4 getStateColour() => IsHovered ? colourProvider.Light1 : colourProvider.Light3; + } + + private class FilterDropdown : OsuTabDropdown + { + protected override DropdownHeader CreateHeader() => new FilterHeader + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight + }; + + private class FilterHeader : OsuTabDropdownHeader + { + public FilterHeader() + { + Background.Height = 1; + } + } + } + } + } +} diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchRulesetFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchRulesetFilterRow.cs new file mode 100644 index 0000000000..eebd896cf9 --- /dev/null +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchRulesetFilterRow.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.Game.Rulesets; + +namespace osu.Game.Overlays.BeatmapListing +{ + public class BeatmapSearchRulesetFilterRow : BeatmapSearchFilterRow + { + public BeatmapSearchRulesetFilterRow() + : base(@"Mode") + { + } + + protected override BeatmapSearchFilter CreateFilter() => new RulesetFilter(); + + private class RulesetFilter : BeatmapSearchFilter + { + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets) + { + AddItem(new RulesetInfo + { + Name = @"Any" + }); + + foreach (var r in rulesets.AvailableRulesets) + AddItem(r); + } + } + } +} diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchSmallFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchSmallFilterRow.cs new file mode 100644 index 0000000000..6daa7cb0e0 --- /dev/null +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchSmallFilterRow.cs @@ -0,0 +1,32 @@ +// 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.UserInterface; + +namespace osu.Game.Overlays.BeatmapListing +{ + public class BeatmapSearchSmallFilterRow : BeatmapSearchFilterRow + { + public BeatmapSearchSmallFilterRow(string headerName) + : base(headerName) + { + } + + protected override BeatmapSearchFilter CreateFilter() => new SmallBeatmapSearchFilter(); + + private class SmallBeatmapSearchFilter : BeatmapSearchFilter + { + protected override TabItem CreateTabItem(T value) => new SmallTabItem(value); + + private class SmallTabItem : FilterTabItem + { + public SmallTabItem(T value) + : base(value) + { + } + + protected override float TextSize => 10; + } + } + } +} diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index ececc18c96..afd499cb9e 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -50,6 +50,6 @@ namespace osu.Game.Rulesets } } - public override string ToString() => $"{Name} ({ShortName}) ID: {ID}"; + public override string ToString() => Name ?? $"{Name} ({ShortName}) ID: {ID}"; } }