mirror of
https://github.com/ppy/osu.git
synced 2025-01-12 11:42:54 +08:00
Refactor ExpandingControlContainer
to no longer rely on controls
This commit is contained in:
parent
b2efce2656
commit
bbef12e72c
@ -1,20 +1,16 @@
|
||||
// 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.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Settings.Sections;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneExpandingControlContainer : OsuManualInputManagerTestScene
|
||||
public class TestSceneExpandingContainer : OsuManualInputManagerTestScene
|
||||
{
|
||||
private TestExpandingContainer container;
|
||||
private SettingsToolboxGroup toolboxGroup;
|
||||
@ -84,44 +80,22 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests hovering over controls expands the parenting container appropriately and does not contract until hover is lost from container.
|
||||
/// Tests hovering expands the container and does not contract until hover is lost.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestHoveringControlExpandsContainer()
|
||||
public void TestHoveringExpandsContainer()
|
||||
{
|
||||
AddAssert("ensure container contracted", () => !container.Expanded.Value);
|
||||
|
||||
AddStep("hover slider", () => InputManager.MoveMouseTo(slider1));
|
||||
AddStep("hover container", () => InputManager.MoveMouseTo(container));
|
||||
AddAssert("container expanded", () => container.Expanded.Value);
|
||||
AddAssert("controls expanded", () => slider1.Expanded.Value && slider2.Expanded.Value);
|
||||
|
||||
AddStep("hover group top", () => InputManager.MoveMouseTo(toolboxGroup.ScreenSpaceDrawQuad.TopLeft + new Vector2(5)));
|
||||
AddAssert("container still expanded", () => container.Expanded.Value);
|
||||
AddAssert("controls still expanded", () => slider1.Expanded.Value && slider2.Expanded.Value);
|
||||
|
||||
AddStep("hover away", () => InputManager.MoveMouseTo(Vector2.Zero));
|
||||
AddAssert("container contracted", () => !container.Expanded.Value);
|
||||
AddAssert("controls contracted", () => !slider1.Expanded.Value && !slider2.Expanded.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests dragging a UI control (e.g. <see cref="OsuSliderBar{T}"/>) outside its parenting container does not contract it until dragging is finished.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestDraggingControlOutsideDoesntContractContainer()
|
||||
{
|
||||
AddStep("hover slider", () => InputManager.MoveMouseTo(slider1));
|
||||
AddAssert("container expanded", () => container.Expanded.Value);
|
||||
|
||||
AddStep("hover slider nub", () => InputManager.MoveMouseTo(slider1.ChildrenOfType<Nub>().Single()));
|
||||
AddStep("hold slider nub", () => InputManager.PressButton(MouseButton.Left));
|
||||
AddStep("drag outside container", () => InputManager.MoveMouseTo(Vector2.Zero));
|
||||
AddAssert("container still expanded", () => container.Expanded.Value);
|
||||
|
||||
AddStep("release slider nub", () => InputManager.ReleaseButton(MouseButton.Left));
|
||||
AddAssert("container contracted", () => !container.Expanded.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests expanding a container will expand underlying groups if contracted.
|
||||
/// </summary>
|
||||
@ -157,21 +131,21 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests expanding a container via <see cref="ExpandingControlContainer{TControl}.Expanded"/> does not get contracted by losing hover.
|
||||
/// Tests expanding a container via <see cref="ExpandingContainer.Expanded"/> does not get contracted by losing hover.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestExpandingContainerDoesntGetContractedByHover()
|
||||
{
|
||||
AddStep("expand container", () => container.Expanded.Value = true);
|
||||
|
||||
AddStep("hover control", () => InputManager.MoveMouseTo(slider1));
|
||||
AddStep("hover container", () => InputManager.MoveMouseTo(container));
|
||||
AddAssert("container still expanded", () => container.Expanded.Value);
|
||||
|
||||
AddStep("hover away", () => InputManager.MoveMouseTo(Vector2.Zero));
|
||||
AddAssert("container still expanded", () => container.Expanded.Value);
|
||||
}
|
||||
|
||||
private class TestExpandingContainer : ExpandingControlContainer<IExpandableControl>
|
||||
private class TestExpandingContainer : ExpandingContainer
|
||||
{
|
||||
public TestExpandingContainer()
|
||||
: base(120, 250)
|
@ -17,7 +17,7 @@ namespace osu.Game.Overlays
|
||||
/// <summary>
|
||||
/// An <see cref="IExpandable"/> implementation for the UI slider bar control.
|
||||
/// </summary>
|
||||
public class ExpandableSlider<T, TSlider> : CompositeDrawable, IExpandableControl, IHasCurrentValue<T>
|
||||
public class ExpandableSlider<T, TSlider> : CompositeDrawable, IExpandable, IHasCurrentValue<T>
|
||||
where T : struct, IEquatable<T>, IComparable<T>, IConvertible
|
||||
where TSlider : OsuSliderBar<T>, new()
|
||||
{
|
||||
@ -72,8 +72,6 @@ namespace osu.Game.Overlays
|
||||
|
||||
public BindableBool Expanded { get; } = new BindableBool();
|
||||
|
||||
bool IExpandable.ShouldBeExpanded => IsHovered || slider.IsDragged;
|
||||
|
||||
public override bool HandlePositionalInput => true;
|
||||
|
||||
public ExpandableSlider()
|
||||
|
@ -1,17 +1,15 @@
|
||||
// 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 osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Overlays
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="ExpandingControlContainer{TControl}"/> with a long hover expansion delay for buttons.
|
||||
/// An <see cref="ExpandingContainer"/> with a long hover expansion delay.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Mostly used for buttons with explanatory labels, in which the label would display after a "long hover".
|
||||
/// </remarks>
|
||||
public class ExpandingButtonContainer : ExpandingControlContainer<OsuButton>
|
||||
public class ExpandingButtonContainer : ExpandingContainer
|
||||
{
|
||||
protected ExpandingButtonContainer(float contractedWidth, float expandedWidth)
|
||||
: base(contractedWidth, expandedWidth)
|
||||
|
@ -1,23 +1,19 @@
|
||||
// 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.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Overlays
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a <see cref="Container"/> with the ability to expand/contract when hovering the controls within it.
|
||||
/// Represents a <see cref="Container"/> with the ability to expand/contract on hover.
|
||||
/// </summary>
|
||||
/// <typeparam name="TControl">The type of UI control to lookup for hover expansion.</typeparam>
|
||||
public class ExpandingControlContainer<TControl> : Container, IExpandingContainer
|
||||
where TControl : class, IDrawable
|
||||
public class ExpandingContainer : Container, IExpandingContainer
|
||||
{
|
||||
private readonly float contractedWidth;
|
||||
private readonly float expandedWidth;
|
||||
@ -33,7 +29,7 @@ namespace osu.Game.Overlays
|
||||
|
||||
protected FillFlowContainer FillFlow { get; }
|
||||
|
||||
protected ExpandingControlContainer(float contractedWidth, float expandedWidth)
|
||||
protected ExpandingContainer(float contractedWidth, float expandedWidth)
|
||||
{
|
||||
this.contractedWidth = contractedWidth;
|
||||
this.expandedWidth = expandedWidth;
|
||||
@ -57,7 +53,6 @@ namespace osu.Game.Overlays
|
||||
}
|
||||
|
||||
private ScheduledDelegate hoverExpandEvent;
|
||||
private TControl activeControl;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
@ -69,61 +64,38 @@ namespace osu.Game.Overlays
|
||||
}, true);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
// if the container was expanded from hovering over a control, we have to check per-frame whether we can contract it back.
|
||||
// that's because contracting the container depends not only on whether it's no longer hovered,
|
||||
// but also on whether the hovered control is no longer in a dragged state (if it was).
|
||||
if (hoverExpandEvent != null && !IsHovered && (activeControl == null || !isControlActive(activeControl)))
|
||||
{
|
||||
hoverExpandEvent?.Cancel();
|
||||
|
||||
Expanded.Value = false;
|
||||
hoverExpandEvent = null;
|
||||
activeControl = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
queueExpandIfHovering();
|
||||
updateHoverExpansion();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnMouseMove(MouseMoveEvent e)
|
||||
{
|
||||
queueExpandIfHovering();
|
||||
updateHoverExpansion();
|
||||
return base.OnMouseMove(e);
|
||||
}
|
||||
|
||||
private void queueExpandIfHovering()
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
// if the same control is hovered or dragged, let the scheduled expand play out..
|
||||
if (activeControl != null && isControlActive(activeControl))
|
||||
if (hoverExpandEvent != null)
|
||||
{
|
||||
hoverExpandEvent?.Cancel();
|
||||
hoverExpandEvent = null;
|
||||
|
||||
Expanded.Value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// ..otherwise check whether a new control is hovered, and if so, queue a new hover operation.
|
||||
hoverExpandEvent?.Cancel();
|
||||
|
||||
// usually we wouldn't use ChildrenOfType in implementations, but this is the simplest way
|
||||
// to handle cases like the editor where the controls may be nested within a child hierarchy.
|
||||
activeControl = FillFlow.ChildrenOfType<TControl>().FirstOrDefault(isControlActive);
|
||||
|
||||
if (activeControl != null && !Expanded.Value)
|
||||
hoverExpandEvent = Scheduler.AddDelayed(() => Expanded.Value = true, HoverExpansionDelay);
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the given control is currently active, by checking whether it's hovered or dragged.
|
||||
/// </summary>
|
||||
private bool isControlActive(TControl control)
|
||||
private void updateHoverExpansion()
|
||||
{
|
||||
if (control is IExpandable expandable)
|
||||
return expandable.ShouldBeExpanded;
|
||||
hoverExpandEvent?.Cancel();
|
||||
|
||||
return control.IsHovered || control.IsDragged;
|
||||
if (IsHovered && !Expanded.Value)
|
||||
hoverExpandEvent = Scheduler.AddDelayed(() => Expanded.Value = true, HoverExpansionDelay);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@
|
||||
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Overlays
|
||||
{
|
||||
@ -16,15 +15,5 @@ namespace osu.Game.Overlays
|
||||
/// Whether this drawable is in an expanded state.
|
||||
/// </summary>
|
||||
BindableBool Expanded { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this drawable should be/stay expanded by a parenting <see cref="IExpandingContainer"/>.
|
||||
/// By default, this is <see langword="true"/> when this drawable is in a hovered or dragged state.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is defined for certain controls which may have a child handling dragging instead.
|
||||
/// (e.g. <see cref="ExpandableSlider{T,TSlider}"/> in which dragging is handled by their underlying <see cref="OsuSliderBar{T}"/> control).
|
||||
/// </remarks>
|
||||
bool ShouldBeExpanded => IsHovered || IsDragged;
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
// 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.
|
||||
|
||||
namespace osu.Game.Overlays
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface for UI controls with the ability to expand/contract.
|
||||
/// </summary>
|
||||
public interface IExpandableControl : IExpandable
|
||||
{
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user