2021-07-06 01:22:55 +08:00
|
|
|
// 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.
|
|
|
|
|
2022-06-17 15:37:17 +08:00
|
|
|
#nullable disable
|
|
|
|
|
2021-07-06 19:24:18 +08:00
|
|
|
using System;
|
2021-07-07 12:48:35 +08:00
|
|
|
using System.Diagnostics;
|
2021-07-06 18:07:25 +08:00
|
|
|
using osu.Framework;
|
2021-07-06 01:22:55 +08:00
|
|
|
using osu.Framework.Graphics;
|
|
|
|
using osu.Framework.Graphics.Containers;
|
|
|
|
using osu.Game.Graphics.UserInterface;
|
|
|
|
|
|
|
|
namespace osu.Game.Graphics.Containers
|
|
|
|
{
|
|
|
|
/// <summary>
|
|
|
|
/// A FillFlowContainer that provides functionality to cycle selection between children
|
|
|
|
/// The selection wraps around when overflowing past the first or last child.
|
|
|
|
/// </summary>
|
2021-07-06 18:07:25 +08:00
|
|
|
public partial class SelectionCycleFillFlowContainer<T> : FillFlowContainer<T> where T : Drawable, IStateful<SelectionState>
|
2021-07-06 01:22:55 +08:00
|
|
|
{
|
2021-07-06 20:39:53 +08:00
|
|
|
public T Selected => (selectedIndex >= 0 && selectedIndex < Count) ? this[selectedIndex.Value] : null;
|
|
|
|
|
2021-07-07 12:48:35 +08:00
|
|
|
private int? selectedIndex;
|
2021-07-06 01:22:55 +08:00
|
|
|
|
|
|
|
public void SelectNext()
|
|
|
|
{
|
2021-07-06 17:30:56 +08:00
|
|
|
if (!selectedIndex.HasValue || selectedIndex == Count - 1)
|
2021-07-06 01:22:55 +08:00
|
|
|
setSelected(0);
|
|
|
|
else
|
2021-07-06 17:30:56 +08:00
|
|
|
setSelected(selectedIndex.Value + 1);
|
2021-07-06 01:22:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
public void SelectPrevious()
|
|
|
|
{
|
2021-07-06 17:30:56 +08:00
|
|
|
if (!selectedIndex.HasValue || selectedIndex == 0)
|
2021-07-06 01:22:55 +08:00
|
|
|
setSelected(Count - 1);
|
|
|
|
else
|
2021-07-06 17:30:56 +08:00
|
|
|
setSelected(selectedIndex.Value - 1);
|
2021-07-06 01:22:55 +08:00
|
|
|
}
|
|
|
|
|
2021-07-06 17:30:56 +08:00
|
|
|
public void Deselect() => setSelected(null);
|
2021-07-06 20:39:53 +08:00
|
|
|
|
2021-07-06 17:30:56 +08:00
|
|
|
public void Select(T item)
|
|
|
|
{
|
2021-10-27 12:04:41 +08:00
|
|
|
int newIndex = IndexOf(item);
|
2021-07-06 17:30:56 +08:00
|
|
|
|
|
|
|
if (newIndex < 0)
|
|
|
|
setSelected(null);
|
|
|
|
else
|
|
|
|
setSelected(IndexOf(item));
|
|
|
|
}
|
2021-07-06 01:22:55 +08:00
|
|
|
|
2021-07-06 19:24:18 +08:00
|
|
|
public override void Add(T drawable)
|
|
|
|
{
|
2021-07-07 12:48:35 +08:00
|
|
|
Debug.Assert(drawable != null);
|
2021-07-06 19:24:18 +08:00
|
|
|
|
2024-02-02 18:48:13 +08:00
|
|
|
base.Add(drawable);
|
|
|
|
|
2021-07-07 17:43:54 +08:00
|
|
|
drawable.StateChanged += state => selectionChanged(drawable, state);
|
2021-07-06 19:24:18 +08:00
|
|
|
}
|
|
|
|
|
2022-08-26 14:19:05 +08:00
|
|
|
public override bool Remove(T drawable, bool disposeImmediately)
|
2021-07-07 17:43:54 +08:00
|
|
|
=> throw new NotSupportedException($"Cannot remove drawables from {nameof(SelectionCycleFillFlowContainer<T>)}");
|
2021-07-06 19:24:18 +08:00
|
|
|
|
2021-07-07 12:48:35 +08:00
|
|
|
private void setSelected(int? value)
|
|
|
|
{
|
|
|
|
if (selectedIndex == value)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Deselect the previously-selected button
|
|
|
|
if (selectedIndex.HasValue)
|
|
|
|
this[selectedIndex.Value].State = SelectionState.NotSelected;
|
|
|
|
|
|
|
|
selectedIndex = value;
|
|
|
|
|
|
|
|
// Select the newly-selected button
|
|
|
|
if (selectedIndex.HasValue)
|
|
|
|
this[selectedIndex.Value].State = SelectionState.Selected;
|
|
|
|
}
|
|
|
|
|
2021-07-06 19:24:18 +08:00
|
|
|
private void selectionChanged(T drawable, SelectionState state)
|
|
|
|
{
|
|
|
|
if (state == SelectionState.NotSelected)
|
|
|
|
Deselect();
|
|
|
|
else
|
|
|
|
Select(drawable);
|
|
|
|
}
|
2021-07-06 01:22:55 +08:00
|
|
|
}
|
|
|
|
}
|