// 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.Sprites; namespace osu.Game.Graphics.UserInterface { /// /// An which contains and displays a state. /// public abstract class StatefulMenuItem : OsuMenuItem { /// /// The current state that should be displayed. /// public readonly Bindable State = new Bindable(); /// /// Creates a new . /// /// The text to display. /// A function that mutates a state to another state after this is pressed. /// The type of action which this performs. protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type = MenuItemType.Standard) : this(text, changeStateFunc, type, null) { } /// /// Creates a new . /// /// The text to display. /// A function that mutates a state to another state after this is pressed. /// The type of action which this performs. /// A delegate to be invoked when this is pressed. protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) : base(text, type) { Action.Value = () => { State.Value = changeStateFunc?.Invoke(State.Value) ?? State.Value; action?.Invoke(State.Value); }; } /// /// Retrieves the icon to be displayed for a state. /// /// The state to retrieve the relevant icon for. /// The icon to be displayed for . public abstract IconUsage? GetIconForState(object state); } public abstract class StatefulMenuItem : StatefulMenuItem where T : struct { /// /// The current state that should be displayed. /// public new readonly Bindable State = new Bindable(); /// /// Creates a new . /// /// The text to display. /// A function that mutates a state to another state after this is pressed. /// The type of action which this performs. protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type = MenuItemType.Standard) : this(text, changeStateFunc, type, null) { } /// /// Creates a new . /// /// The text to display. /// A function that mutates a state to another state after this is pressed. /// The type of action which this performs. /// A delegate to be invoked when this is pressed. protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) : base(text, o => changeStateFunc?.Invoke((T)o) ?? o, type, o => action?.Invoke((T)o)) { base.State.BindValueChanged(state => { if (state.NewValue == null) base.State.Value = default(T); State.Value = (T)base.State.Value; }, true); State.BindValueChanged(state => base.State.Value = state.NewValue); } public sealed override IconUsage? GetIconForState(object state) => GetIconForState((T)state); /// /// Retrieves the icon to be displayed for a state. /// /// The state to retrieve the relevant icon for. /// The icon to be displayed for . public abstract IconUsage? GetIconForState(T state); } }