// 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.Extensions.TypeExtensions; using osu.Framework.Utils; namespace osu.Framework.Bindables { /// /// An interface which can be bound to other s in order to watch for (and react to) Disabled changes. /// public interface IBindable : ICanBeDisabled, IHasDefaultValue, IUnbindable, IHasDescription { /// /// Binds ourselves to another bindable such that we receive any value limitations of the bindable we bind width. /// /// The foreign bindable. This should always be the most permanent end of the bind (ie. a ConfigManager) void BindTo(IBindable them); /// /// An alias of provided for use in object initializer scenarios. /// Passes the provided value as the foreign (more permanent) bindable. /// sealed IBindable BindTarget { set => BindTo(value); } /// /// Retrieve a new bindable instance weakly bound to the configuration backing. /// If you are further binding to events of a bindable retrieved using this method, ensure to hold /// a local reference. /// /// A weakly bound copy of the specified bindable. /// Thrown when attempting to instantiate a copy bindable that's not matching the original's type. IBindable GetBoundCopy(); /// /// Creates a new instance of this for use in . /// The returned instance must have match the most derived type of the bindable class this method is implemented on. /// protected IBindable CreateInstance(); /// /// Helper method which implements for use in final classes. /// /// The source . /// The bindable type. /// The bound copy. protected static T GetBoundCopyImplementation(T source) where T : IBindable { var copy = source.CreateInstance(); if (copy.GetType() != source.GetType()) { ThrowHelper.ThrowInvalidOperationException($"Attempted to create a copy of {source.GetType().ReadableName()}, but the returned instance type was {copy.GetType().ReadableName()}. " + $"Override {source.GetType().ReadableName()}.{nameof(CreateInstance)}() for {nameof(GetBoundCopy)}() to function properly."); } copy.BindTo(source); return (T)copy; } } /// /// An interface which can be bound to other s in order to watch for (and react to) Disabled and Value changes. /// /// The type of value encapsulated by this . public interface IBindable : ICanBeDisabled, IHasDefaultValue, IUnbindable, IHasDescription { /// /// An event which is raised when has changed. /// event Action> ValueChanged; /// /// The current value of this bindable. /// T Value { get; } /// /// The default value of this bindable. Used when querying IsDefault. /// T Default { get; } /// /// Binds ourselves to another bindable such that we receive any values and value limitations of the bindable we bind width. /// /// The foreign bindable. This should always be the most permanent end of the bind (ie. a ConfigManager) void BindTo(IBindable them); /// /// An alias of provided for use in object initializer scenarios. /// Passes the provided value as the foreign (more permanent) bindable. /// IBindable BindTarget { set => BindTo(value); } /// /// Bind an action to with the option of running the bound action once immediately. /// /// The action to perform when changes. /// Whether the action provided in should be run once immediately. void BindValueChanged(Action> onChange, bool runOnceImmediately = false); /// IBindable GetBoundCopy(); } }