From 1710b396e7195f34b024166d74129701ffc21eac Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 27 Oct 2020 22:27:29 +0300 Subject: [PATCH] Implement BeatmapSearchMultipleSelectionFilterRow --- .../TestSceneBeatmapListingSearchControl.cs | 3 +- .../API/Requests/SearchBeatmapSetsRequest.cs | 33 ++------ .../BeatmapListingSearchControl.cs | 3 +- .../BeatmapSearchExtraFilterRow.cs | 79 ++---------------- .../BeatmapListing/BeatmapSearchFilterRow.cs | 64 +------------- ...BeatmapSearchMultipleSelectionFilterRow.cs | 83 +++++++++++++++++++ .../Overlays/BeatmapListing/FilterTabItem.cs | 74 +++++++++++++++++ .../Overlays/BeatmapListing/SearchExtra.cs | 4 +- 8 files changed, 179 insertions(+), 164 deletions(-) create mode 100644 osu.Game/Overlays/BeatmapListing/BeatmapSearchMultipleSelectionFilterRow.cs create mode 100644 osu.Game/Overlays/BeatmapListing/FilterTabItem.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs index 5c9431aad1..9b0ef4d6f2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs @@ -1,6 +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 NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -58,7 +59,7 @@ namespace osu.Game.Tests.Visual.UserInterface control.Category.BindValueChanged(c => category.Text = $"Category: {c.NewValue}", true); control.Genre.BindValueChanged(g => genre.Text = $"Genre: {g.NewValue}", true); control.Language.BindValueChanged(l => language.Text = $"Language: {l.NewValue}", true); - control.Extra.BindValueChanged(e => extra.Text = $"Extra: {e.NewValue}", true); + control.Extra.BindValueChanged(e => extra.Text = $"Extra: {(e.NewValue == null ? "" : string.Join(".", e.NewValue.Select(i => i.ToString().ToLowerInvariant())))}", true); control.Played.BindValueChanged(p => played.Text = $"Played: {p.NewValue}", true); } diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs index 12383e7457..20bbd46529 100644 --- a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs +++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.IO.Network; using osu.Game.Extensions; using osu.Game.Overlays; @@ -21,7 +23,7 @@ namespace osu.Game.Online.API.Requests public SearchLanguage Language { get; } - public SearchExtra Extra { get; } + public List Extra { get; } public SearchPlayed Played { get; } @@ -40,7 +42,7 @@ namespace osu.Game.Online.API.Requests SortDirection sortDirection = SortDirection.Descending, SearchGenre genre = SearchGenre.Any, SearchLanguage language = SearchLanguage.Any, - SearchExtra extra = SearchExtra.Any, + List extra = null, SearchPlayed played = SearchPlayed.Any) { this.query = string.IsNullOrEmpty(query) ? string.Empty : System.Uri.EscapeDataString(query); @@ -74,33 +76,14 @@ namespace osu.Game.Online.API.Requests req.AddParameter("sort", $"{SortCriteria.ToString().ToLowerInvariant()}_{directionString}"); - req.AddCursor(cursor); - - if (Extra != SearchExtra.Any) - { - string extraString = string.Empty; - - switch (Extra) - { - case SearchExtra.Both: - extraString = "video.storyboard"; - break; - - case SearchExtra.Storyboard: - extraString = "storyboard"; - break; - - case SearchExtra.Video: - extraString = "video"; - break; - } - - req.AddParameter("e", extraString); - } + if (Extra != null && Extra.Any()) + req.AddParameter("e", string.Join(".", Extra.Select(e => e.ToString().ToLowerInvariant()))); if (Played != SearchPlayed.Any) req.AddParameter("played", Played.ToString().ToLowerInvariant()); + req.AddCursor(cursor); + return req; } diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs index 80beed6217..f390db3f35 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs @@ -13,6 +13,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osuTK.Graphics; using osu.Game.Rulesets; +using System.Collections.Generic; namespace osu.Game.Overlays.BeatmapListing { @@ -28,7 +29,7 @@ namespace osu.Game.Overlays.BeatmapListing public Bindable Language => languageFilter.Current; - public Bindable Extra => extraFilter.Current; + public Bindable> Extra => extraFilter.Current; public Bindable Played => playedFilter.Current; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchExtraFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchExtraFilterRow.cs index 6e81cd2976..385978096c 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchExtraFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchExtraFilterRow.cs @@ -1,94 +1,31 @@ // 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 osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.UserInterface; -using osu.Framework.Input.Events; -using osuTK; - namespace osu.Game.Overlays.BeatmapListing { - public class BeatmapSearchExtraFilterRow : BeatmapSearchFilterRow + public class BeatmapSearchExtraFilterRow : BeatmapSearchMultipleSelectionFilterRow { public BeatmapSearchExtraFilterRow() : base("Extra") { } - protected override Drawable CreateFilter() => new ExtraFilter(); + protected override MultipleSelectionFilter CreateMultipleSelectionFilter() => new ExtraFilter(); - private class ExtraFilter : FillFlowContainer, IHasCurrentValue + private class ExtraFilter : MultipleSelectionFilter { - private readonly BindableWithCurrent current = new BindableWithCurrent(); - - public Bindable Current + protected override MultipleSelectionFilterTabItem[] CreateItems() => new[] { - get => current.Current; - set => current.Current = value; - } - - private readonly ExtraFilterTabItem videoItem; - private readonly ExtraFilterTabItem storyboardItem; - - public ExtraFilter() - { - Anchor = Anchor.BottomLeft; - Origin = Anchor.BottomLeft; - RelativeSizeAxes = Axes.X; - Height = 15; - Spacing = new Vector2(10, 0); - AddRange(new[] - { - videoItem = new ExtraFilterTabItem(SearchExtra.Video), - storyboardItem = new ExtraFilterTabItem(SearchExtra.Storyboard) - }); - - foreach (var item in Children) - item.StateUpdated += updateBindable; - } - - private void updateBindable() - { - if (videoItem.Active.Value && storyboardItem.Active.Value) - { - Current.Value = SearchExtra.Both; - return; - } - - if (videoItem.Active.Value) - { - Current.Value = SearchExtra.Video; - return; - } - - if (storyboardItem.Active.Value) - { - Current.Value = SearchExtra.Storyboard; - return; - } - - Current.Value = SearchExtra.Any; - } + new ExtraFilterTabItem(SearchExtra.Video), + new ExtraFilterTabItem(SearchExtra.Storyboard) + }; } - private class ExtraFilterTabItem : FilterTabItem + private class ExtraFilterTabItem : MultipleSelectionFilterTabItem { - public event Action StateUpdated; - public ExtraFilterTabItem(SearchExtra value) : base(value) { - Active.BindValueChanged(_ => StateUpdated?.Invoke()); - } - - protected override bool OnClick(ClickEvent e) - { - base.OnClick(e); - Active.Value = !Active.Value; - return true; } protected override string CreateText(SearchExtra value) => $@"Has {value.ToString()}"; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs index ad32475b25..aa0fc0d00e 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs @@ -1,20 +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 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; using Humanizer; using osu.Game.Utils; @@ -98,7 +94,7 @@ namespace osu.Game.Overlays.BeatmapListing protected override Dropdown CreateDropdown() => new FilterDropdown(); - protected override TabItem CreateTabItem(T value) => new FilterTabItem(value); + protected override TabItem CreateTabItem(T value) => new FilterTabItem(value); private class FilterDropdown : OsuTabDropdown { @@ -117,63 +113,5 @@ namespace osu.Game.Overlays.BeatmapListing } } } - - 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 = CreateText(value) - }, - new HoverClickSounds() - }); - - Enabled.Value = true; - } - - protected virtual string CreateText(T value) => (value as Enum)?.GetDescription() ?? value.ToString(); - - [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; - } } } diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchMultipleSelectionFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchMultipleSelectionFilterRow.cs new file mode 100644 index 0000000000..c434e00ff3 --- /dev/null +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchMultipleSelectionFilterRow.cs @@ -0,0 +1,83 @@ +// 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.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osuTK; + +namespace osu.Game.Overlays.BeatmapListing +{ + public abstract class BeatmapSearchMultipleSelectionFilterRow : BeatmapSearchFilterRow> + { + public BeatmapSearchMultipleSelectionFilterRow(string headerName) + : base(headerName) + { + } + + protected override Drawable CreateFilter() => CreateMultipleSelectionFilter(); + + protected abstract MultipleSelectionFilter CreateMultipleSelectionFilter(); + + protected abstract class MultipleSelectionFilter : FillFlowContainer, IHasCurrentValue> + { + private readonly BindableWithCurrent> current = new BindableWithCurrent>(); + + public Bindable> Current + { + get => current.Current; + set => current.Current = value; + } + + public MultipleSelectionFilter() + { + Anchor = Anchor.BottomLeft; + Origin = Anchor.BottomLeft; + RelativeSizeAxes = Axes.X; + Height = 15; + Spacing = new Vector2(10, 0); + AddRange(CreateItems()); + + foreach (var item in Children) + item.StateUpdated += updateBindable; + } + + protected abstract MultipleSelectionFilterTabItem[] CreateItems(); + + private void updateBindable() + { + var selectedValues = new List(); + + foreach (var item in Children) + { + if (item.Active.Value) + selectedValues.Add(item.Value); + } + + Current.Value = selectedValues; + } + } + + protected class MultipleSelectionFilterTabItem : FilterTabItem + { + public event Action StateUpdated; + + public MultipleSelectionFilterTabItem(T value) + : base(value) + { + Active.BindValueChanged(_ => StateUpdated?.Invoke()); + } + + protected override bool OnClick(ClickEvent e) + { + base.OnClick(e); + Active.Value = !Active.Value; + return true; + } + } + } +} diff --git a/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs b/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs new file mode 100644 index 0000000000..32b48862e0 --- /dev/null +++ b/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs @@ -0,0 +1,74 @@ +// 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 osu.Framework.Allocation; +using osu.Framework.Extensions; +using osu.Framework.Graphics; +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.Graphics; + +namespace osu.Game.Overlays.BeatmapListing +{ + public 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 = CreateText(value) + }, + new HoverClickSounds() + }); + + Enabled.Value = true; + } + + protected virtual string CreateText(T value) => (value as Enum)?.GetDescription() ?? value.ToString(); + + [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; + } +} diff --git a/osu.Game/Overlays/BeatmapListing/SearchExtra.cs b/osu.Game/Overlays/BeatmapListing/SearchExtra.cs index 53900211e1..e9b3165d97 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchExtra.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchExtra.cs @@ -5,9 +5,7 @@ namespace osu.Game.Overlays.BeatmapListing { public enum SearchExtra { - Any, Video, - Storyboard, - Both + Storyboard } }