A game framework written with osu! in mind.
at master 113 lines 5.4 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2// See the LICENCE file in the repository root for full licence text. 3 4using System; 5using osu.Framework.Extensions.TypeExtensions; 6using osu.Framework.Utils; 7 8namespace osu.Framework.Bindables 9{ 10 /// <summary> 11 /// An interface which can be bound to other <see cref="IBindable"/>s in order to watch for (and react to) <see cref="ICanBeDisabled.Disabled">Disabled</see> changes. 12 /// </summary> 13 public interface IBindable : ICanBeDisabled, IHasDefaultValue, IUnbindable, IHasDescription 14 { 15 /// <summary> 16 /// Binds ourselves to another bindable such that we receive any value limitations of the bindable we bind width. 17 /// </summary> 18 /// <param name="them">The foreign bindable. This should always be the most permanent end of the bind (ie. a ConfigManager)</param> 19 void BindTo(IBindable them); 20 21 /// <summary> 22 /// An alias of <see cref="BindTo"/> provided for use in object initializer scenarios. 23 /// Passes the provided value as the foreign (more permanent) bindable. 24 /// </summary> 25 sealed IBindable BindTarget 26 { 27 set => BindTo(value); 28 } 29 30 /// <summary> 31 /// Retrieve a new bindable instance weakly bound to the configuration backing. 32 /// If you are further binding to events of a bindable retrieved using this method, ensure to hold 33 /// a local reference. 34 /// </summary> 35 /// <returns>A weakly bound copy of the specified bindable.</returns> 36 /// <exception cref="InvalidOperationException">Thrown when attempting to instantiate a copy bindable that's not matching the original's type.</exception> 37 IBindable GetBoundCopy(); 38 39 /// <summary> 40 /// Creates a new instance of this <see cref="IBindable"/> for use in <see cref="GetBoundCopy"/>. 41 /// The returned instance must have match the most derived type of the bindable class this method is implemented on. 42 /// </summary> 43 protected IBindable CreateInstance(); 44 45 /// <summary> 46 /// Helper method which implements <see cref="GetBoundCopy"/> for use in final classes. 47 /// </summary> 48 /// <param name="source">The source <see cref="IBindable"/>.</param> 49 /// <typeparam name="T">The bindable type.</typeparam> 50 /// <returns>The bound copy.</returns> 51 protected static T GetBoundCopyImplementation<T>(T source) 52 where T : IBindable 53 { 54 var copy = source.CreateInstance(); 55 56 if (copy.GetType() != source.GetType()) 57 { 58 ThrowHelper.ThrowInvalidOperationException($"Attempted to create a copy of {source.GetType().ReadableName()}, but the returned instance type was {copy.GetType().ReadableName()}. " 59 + $"Override {source.GetType().ReadableName()}.{nameof(CreateInstance)}() for {nameof(GetBoundCopy)}() to function properly."); 60 } 61 62 copy.BindTo(source); 63 return (T)copy; 64 } 65 } 66 67 /// <summary> 68 /// An interface which can be bound to other <see cref="IBindable{T}"/>s in order to watch for (and react to) <see cref="ICanBeDisabled.Disabled">Disabled</see> and <see cref="IBindable{T}.Value">Value</see> changes. 69 /// </summary> 70 /// <typeparam name="T">The type of value encapsulated by this <see cref="IBindable{T}"/>.</typeparam> 71 public interface IBindable<T> : ICanBeDisabled, IHasDefaultValue, IUnbindable, IHasDescription 72 { 73 /// <summary> 74 /// An event which is raised when <see cref="Value"/> has changed. 75 /// </summary> 76 event Action<ValueChangedEvent<T>> ValueChanged; 77 78 /// <summary> 79 /// The current value of this bindable. 80 /// </summary> 81 T Value { get; } 82 83 /// <summary> 84 /// The default value of this bindable. Used when querying <see cref="IHasDefaultValue.IsDefault">IsDefault</see>. 85 /// </summary> 86 T Default { get; } 87 88 /// <summary> 89 /// Binds ourselves to another bindable such that we receive any values and value limitations of the bindable we bind width. 90 /// </summary> 91 /// <param name="them">The foreign bindable. This should always be the most permanent end of the bind (ie. a ConfigManager)</param> 92 void BindTo(IBindable<T> them); 93 94 /// <summary> 95 /// An alias of <see cref="BindTo"/> provided for use in object initializer scenarios. 96 /// Passes the provided value as the foreign (more permanent) bindable. 97 /// </summary> 98 IBindable<T> BindTarget 99 { 100 set => BindTo(value); 101 } 102 103 /// <summary> 104 /// Bind an action to <see cref="ValueChanged"/> with the option of running the bound action once immediately. 105 /// </summary> 106 /// <param name="onChange">The action to perform when <see cref="Value"/> changes.</param> 107 /// <param name="runOnceImmediately">Whether the action provided in <paramref name="onChange"/> should be run once immediately.</param> 108 void BindValueChanged(Action<ValueChangedEvent<T>> onChange, bool runOnceImmediately = false); 109 110 /// <inheritdoc cref="IBindable.GetBoundCopy"/> 111 IBindable<T> GetBoundCopy(); 112 } 113}