From 53e8072632ae3302ec6ee56c0f45e2fddecf7946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 19 Feb 2022 18:45:04 +0100 Subject: [PATCH] Port multiselection from previous design --- .../UserInterface/TestSceneModColumn.cs | 17 +++- osu.Game/Overlays/Mods/ModColumn.cs | 81 ++++++++++++++++++- 2 files changed, 95 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs index 59641ae000..e58649d989 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.UserInterface { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding(30), - Child = new ModColumn(modType) + Child = new ModColumn(modType, false) { Anchor = Anchor.Centre, Origin = Anchor.Centre @@ -44,5 +44,20 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("change ruleset to catch", () => Ruleset.Value = new CatchRuleset().RulesetInfo); AddStep("change ruleset to mania", () => Ruleset.Value = new ManiaRuleset().RulesetInfo); } + + [Test] + public void TestMultiSelection() + { + AddStep("create content", () => Child = new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding(30), + Child = new ModColumn(ModType.DifficultyIncrease, true) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + } + }); + } } } diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index a42b2bcb96..8ca968368e 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -152,7 +152,8 @@ namespace osu.Game.Overlays.Mods if (allowBulkSelection) { - controlContainer.Add(toggleAllCheckbox = new ToggleAllCheckbox + controlContainer.Height = 50; + controlContainer.Add(toggleAllCheckbox = new ToggleAllCheckbox(this) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -218,9 +219,72 @@ namespace osu.Game.Overlays.Mods LoadComponentsAsync(panels, loaded => { panelFlow.ChildrenEnumerable = loaded; + foreach (var panel in panelFlow) + panel.Active.BindValueChanged(_ => updateToggleState()); + updateToggleState(); }, (cancellationTokenSource = new CancellationTokenSource()).Token); } + #region Bulk select / deselect + + private const double initial_multiple_selection_delay = 120; + + private double selectionDelay = initial_multiple_selection_delay; + private double lastSelection; + + private readonly Queue pendingSelectionOperations = new Queue(); + + protected override void Update() + { + base.Update(); + + if (selectionDelay == initial_multiple_selection_delay || Time.Current - lastSelection >= selectionDelay) + { + if (pendingSelectionOperations.TryDequeue(out var dequeuedAction)) + { + dequeuedAction(); + + // each time we play an animation, we decrease the time until the next animation (to ramp the visual and audible elements). + selectionDelay = Math.Max(30, selectionDelay * 0.8f); + lastSelection = Time.Current; + } + else + { + // reset the selection delay after all animations have been completed. + // this will cause the next action to be immediately performed. + selectionDelay = initial_multiple_selection_delay; + } + } + } + + private void updateToggleState() + { + if (toggleAllCheckbox != null && pendingSelectionOperations.Count == 0) + toggleAllCheckbox.Current.Value = panelFlow.All(panel => panel.Active.Value); + } + + /// + /// Selects all mods. + /// + public void SelectAll() + { + pendingSelectionOperations.Clear(); + + foreach (var button in panelFlow.Where(b => !b.Active.Value)) + pendingSelectionOperations.Enqueue(() => button.Active.Value = true); + } + + /// + /// Deselects all mods. + /// + public void DeselectAll() + { + pendingSelectionOperations.Clear(); + + foreach (var button in panelFlow.Where(b => b.Active.Value)) + pendingSelectionOperations.Enqueue(() => button.Active.Value = false); + } + private class ToggleAllCheckbox : OsuCheckbox { private Color4 accentColour; @@ -247,9 +311,12 @@ namespace osu.Game.Overlays.Mods } } - public ToggleAllCheckbox() + private readonly ModColumn column; + + public ToggleAllCheckbox(ModColumn column) : base(false) { + this.column = column; } protected override void ApplyLabelParameters(SpriteText text) @@ -270,6 +337,16 @@ namespace osu.Game.Overlays.Mods Nub.GlowingAccentColour = AccentHoverColour; Nub.GlowColour = AccentHoverColour.Opacity(0.2f); } + + protected override void OnUserChange(bool value) + { + if (value) + column.SelectAll(); + else + column.DeselectAll(); + } } + + #endregion } }