using System; using System.Collections.Generic; using System.Linq; using Unity.UIWidgets.ui; namespace Unity.UIWidgets.foundation { public interface Listenable { void addListener(VoidCallback listener); void removeListener(VoidCallback listener); } public static class ListenableUtils { public static Listenable merge(this List listenables) { return new _MergingListenable(listenables); } } public interface ValueListenable : Listenable { T value { get; } } public class ChangeNotifier : Listenable { ObserverList _listeners = new ObserverList(); bool _debugAssertNotDisposed() { D.assert(() => { if (this._listeners == null) { throw new UIWidgetsError( string.Format("A {0} was used after being disposed.\n" + "Once you have called dispose() on a {0}, it can no longer be used.", this.GetType())); } return true; }); return true; } protected bool hasListeners { get { D.assert(this._debugAssertNotDisposed()); return this._listeners.isNotEmpty(); } } public void addListener(VoidCallback listener) { D.assert(this._debugAssertNotDisposed()); this._listeners.Add(listener); } public void removeListener(VoidCallback listener) { D.assert(this._debugAssertNotDisposed()); this._listeners.Remove(listener); } public virtual void dispose() { D.assert(this._debugAssertNotDisposed()); this._listeners = null; } protected virtual void notifyListeners() { D.assert(this._debugAssertNotDisposed()); if (this._listeners != null) { var localListeners = new List(this._listeners); foreach (VoidCallback listener in localListeners) { try { if (this._listeners.Contains(listener)) { listener(); } } catch (Exception ex) { UIWidgetsError.reportError(new UIWidgetsErrorDetails( exception: ex, library: "foundation library", context: "while dispatching notifications for " + this.GetType(), informationCollector: information => { information.AppendLine("The " + this.GetType() + " sending notification was:"); information.Append(" " + this); } )); } } } } } class _MergingListenable : ChangeNotifier { internal _MergingListenable(List _children) { this._children = _children; foreach (Listenable child in _children) { if (child != null) { child.addListener(this.notifyListeners); } } } readonly List _children; public override void dispose() { foreach (Listenable child in this._children) { if (child != null) { child.removeListener(this.notifyListeners); } } base.dispose(); } public override string ToString() { return "Listenable.merge([" + string.Join(", ", this._children.Select(c => c.ToString()).ToArray()) + "])"; } } public class ValueNotifier : ChangeNotifier, ValueListenable { public ValueNotifier(T value) { this._value = value; } public T value { get { return this._value; } set { if (Equals(value, this._value)) { return; } this._value = value; this.notifyListeners(); } } T _value; public override string ToString() { return Diagnostics.describeIdentity(this) + "(" + this._value + ")"; } } }