mirror of
https://github.com/ppy/osu
synced 2025-01-02 12:22:13 +00:00
Add filtering support to mod column
This commit is contained in:
parent
fe4e4bf9c5
commit
a83f96b026
@ -1,6 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
@ -83,5 +84,54 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFiltering()
|
||||
{
|
||||
TestModColumn column = null;
|
||||
|
||||
AddStep("create content", () => Child = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding(30),
|
||||
Child = column = new TestModColumn(ModType.Fun, true)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
}
|
||||
});
|
||||
|
||||
AddStep("set filter", () => column.Filter = mod => mod.Name.Contains("Wind", StringComparison.CurrentCultureIgnoreCase));
|
||||
AddUntilStep("two panels visible", () => column.ChildrenOfType<ModPanel>().Count(panel => !panel.Filtered.Value) == 2);
|
||||
|
||||
clickToggle();
|
||||
AddUntilStep("wait for animation", () => !column.SelectionAnimationRunning);
|
||||
AddAssert("only visible items selected", () => column.ChildrenOfType<ModPanel>().Where(panel => panel.Active.Value).All(panel => !panel.Filtered.Value));
|
||||
|
||||
AddStep("unset filter", () => column.Filter = null);
|
||||
AddUntilStep("all panels visible", () => column.ChildrenOfType<ModPanel>().All(panel => !panel.Filtered.Value));
|
||||
AddAssert("checkbox not selected", () => !column.ChildrenOfType<OsuCheckbox>().Single().Current.Value);
|
||||
|
||||
AddStep("set filter", () => column.Filter = mod => mod.Name.Contains("Wind", StringComparison.CurrentCultureIgnoreCase));
|
||||
AddUntilStep("two panels visible", () => column.ChildrenOfType<ModPanel>().Count(panel => !panel.Filtered.Value) == 2);
|
||||
AddAssert("checkbox selected", () => column.ChildrenOfType<OsuCheckbox>().Single().Current.Value);
|
||||
|
||||
void clickToggle() => AddStep("click toggle", () =>
|
||||
{
|
||||
var checkbox = this.ChildrenOfType<OsuCheckbox>().Single();
|
||||
InputManager.MoveMouseTo(checkbox);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
}
|
||||
|
||||
private class TestModColumn : ModColumn
|
||||
{
|
||||
public new bool SelectionAnimationRunning => base.SelectionAnimationRunning;
|
||||
|
||||
public TestModColumn(ModType modType, bool allowBulkSelection)
|
||||
: base(modType, allowBulkSelection)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,18 @@ namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
public class ModColumn : CompositeDrawable
|
||||
{
|
||||
private Func<Mod, bool>? filter;
|
||||
|
||||
public Func<Mod, bool>? Filter
|
||||
{
|
||||
get => filter;
|
||||
set
|
||||
{
|
||||
filter = value;
|
||||
updateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly ModType modType;
|
||||
|
||||
private readonly Bindable<Dictionary<ModType, IReadOnlyList<Mod>>> availableMods = new Bindable<Dictionary<ModType, IReadOnlyList<Mod>>>();
|
||||
@ -220,9 +232,12 @@ namespace osu.Game.Overlays.Mods
|
||||
LoadComponentsAsync(panels, loaded =>
|
||||
{
|
||||
panelFlow.ChildrenEnumerable = loaded;
|
||||
|
||||
foreach (var panel in panelFlow)
|
||||
panel.Active.BindValueChanged(_ => updateToggleState());
|
||||
updateToggleState();
|
||||
|
||||
updateFilter();
|
||||
}, (cancellationTokenSource = new CancellationTokenSource()).Token);
|
||||
}
|
||||
|
||||
@ -235,6 +250,8 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
private readonly Queue<Action> pendingSelectionOperations = new Queue<Action>();
|
||||
|
||||
protected bool SelectionAnimationRunning => pendingSelectionOperations.Count > 0;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
@ -260,8 +277,8 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
private void updateToggleState()
|
||||
{
|
||||
if (toggleAllCheckbox != null && pendingSelectionOperations.Count == 0)
|
||||
toggleAllCheckbox.Current.Value = panelFlow.All(panel => panel.Active.Value);
|
||||
if (toggleAllCheckbox != null && !SelectionAnimationRunning)
|
||||
toggleAllCheckbox.Current.Value = panelFlow.Where(panel => !panel.Filtered.Value).All(panel => panel.Active.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -271,7 +288,7 @@ namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
pendingSelectionOperations.Clear();
|
||||
|
||||
foreach (var button in panelFlow.Where(b => !b.Active.Value))
|
||||
foreach (var button in panelFlow.Where(b => !b.Active.Value && !b.Filtered.Value))
|
||||
pendingSelectionOperations.Enqueue(() => button.Active.Value = true);
|
||||
}
|
||||
|
||||
@ -282,7 +299,7 @@ namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
pendingSelectionOperations.Clear();
|
||||
|
||||
foreach (var button in panelFlow.Where(b => b.Active.Value))
|
||||
foreach (var button in panelFlow.Where(b => b.Active.Value && !b.Filtered.Value))
|
||||
pendingSelectionOperations.Enqueue(() => button.Active.Value = false);
|
||||
}
|
||||
|
||||
@ -349,5 +366,17 @@ namespace osu.Game.Overlays.Mods
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Filtering support
|
||||
|
||||
private void updateFilter()
|
||||
{
|
||||
foreach (var modPanel in panelFlow)
|
||||
modPanel.ApplyFilter(Filter);
|
||||
|
||||
updateToggleState();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. 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.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
@ -28,6 +29,7 @@ namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
public Mod Mod { get; }
|
||||
public BindableBool Active { get; } = new BindableBool();
|
||||
public BindableBool Filtered { get; } = new BindableBool();
|
||||
|
||||
protected readonly Box Background;
|
||||
protected readonly Container SwitchContainer;
|
||||
@ -157,6 +159,7 @@ namespace osu.Game.Overlays.Mods
|
||||
playStateChangeSamples();
|
||||
UpdateState();
|
||||
});
|
||||
Filtered.BindValueChanged(_ => updateFilterState());
|
||||
|
||||
UpdateState();
|
||||
FinishTransforms(true);
|
||||
@ -235,5 +238,19 @@ namespace osu.Game.Overlays.Mods
|
||||
TextBackground.FadeColour(textBackgroundColour, transitionDuration, Easing.OutQuint);
|
||||
TextFlow.FadeColour(textColour, transitionDuration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
#region Filtering support
|
||||
|
||||
public void ApplyFilter(Func<Mod, bool>? filter)
|
||||
{
|
||||
Filtered.Value = filter != null && !filter.Invoke(Mod);
|
||||
}
|
||||
|
||||
private void updateFilterState()
|
||||
{
|
||||
this.FadeTo(Filtered.Value ? 0 : 1);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user