diff options
author | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 13:02:25 -0700 |
---|---|---|
committer | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 16:13:41 -0700 |
commit | 17fdde66d94155fc62a034fa6658995bef6fd6e5 (patch) | |
tree | b5e5073a2a7b15cdbe826faa5c763e270a505729 /Xamarin.Forms.Core/Interactivity/TriggerBase.cs | |
download | xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.gz xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.bz2 xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.zip |
Initial import
Diffstat (limited to 'Xamarin.Forms.Core/Interactivity/TriggerBase.cs')
-rw-r--r-- | Xamarin.Forms.Core/Interactivity/TriggerBase.cs | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/Xamarin.Forms.Core/Interactivity/TriggerBase.cs b/Xamarin.Forms.Core/Interactivity/TriggerBase.cs new file mode 100644 index 00000000..9418c7ae --- /dev/null +++ b/Xamarin.Forms.Core/Interactivity/TriggerBase.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Xamarin.Forms +{ + public abstract class TriggerBase : BindableObject, IAttachedObject + { + bool _isSealed; + + internal TriggerBase(Type targetType) + { + if (targetType == null) + throw new ArgumentNullException("targetType"); + TargetType = targetType; + + EnterActions = new SealedList<TriggerAction>(); + ExitActions = new SealedList<TriggerAction>(); + } + + internal TriggerBase(Condition condition, Type targetType) : this(targetType) + { + Setters = new SealedList<Setter>(); + Condition = condition; + Condition.ConditionChanged = OnConditionChanged; + } + + public IList<TriggerAction> EnterActions { get; } + + public IList<TriggerAction> ExitActions { get; } + + public bool IsSealed + { + get { return _isSealed; } + private set + { + if (_isSealed == value) + return; + if (!value) + throw new InvalidOperationException("What is sealed can not be unsealed."); + _isSealed = value; + OnSeal(); + } + } + + public Type TargetType { get; } + + internal Condition Condition { get; } + + //Setters and Condition are used by Trigger, DataTrigger and MultiTrigger + internal IList<Setter> Setters { get; } + + void IAttachedObject.AttachTo(BindableObject bindable) + { + IsSealed = true; + + if (bindable == null) + throw new ArgumentNullException("bindable"); + if (!TargetType.IsInstanceOfType(bindable)) + throw new InvalidOperationException("bindable not an instance of AssociatedType"); + OnAttachedTo(bindable); + } + + void IAttachedObject.DetachFrom(BindableObject bindable) + { + if (bindable == null) + throw new ArgumentNullException("bindable"); + OnDetachingFrom(bindable); + } + + internal virtual void OnAttachedTo(BindableObject bindable) + { + if (Condition != null) + Condition.SetUp(bindable); + } + + internal virtual void OnDetachingFrom(BindableObject bindable) + { + if (Condition != null) + Condition.TearDown(bindable); + } + + internal virtual void OnSeal() + { + ((SealedList<TriggerAction>)EnterActions).IsReadOnly = true; + ((SealedList<TriggerAction>)ExitActions).IsReadOnly = true; + if (Setters != null) + ((SealedList<Setter>)Setters).IsReadOnly = true; + if (Condition != null) + Condition.IsSealed = true; + } + + void OnConditionChanged(BindableObject bindable, bool oldValue, bool newValue) + { + if (newValue) + { + foreach (TriggerAction action in EnterActions) + action.DoInvoke(bindable); + foreach (Setter setter in Setters) + setter.Apply(bindable); + } + else + { + foreach (Setter setter in Setters) + setter.UnApply(bindable); + foreach (TriggerAction action in ExitActions) + action.DoInvoke(bindable); + } + } + + internal class SealedList<T> : IList<T> + { + readonly IList<T> _actual; + + bool _isReadOnly; + + public SealedList() + { + _actual = new List<T>(); + } + + public void Add(T item) + { + if (IsReadOnly) + throw new InvalidOperationException("This list is ReadOnly"); + _actual.Add(item); + } + + public void Clear() + { + if (IsReadOnly) + throw new InvalidOperationException("This list is ReadOnly"); + _actual.Clear(); + } + + public bool Contains(T item) + { + return _actual.Contains(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + _actual.CopyTo(array, arrayIndex); + } + + public int Count + { + get { return _actual.Count; } + } + + public bool IsReadOnly + { + get { return _isReadOnly; } + set + { + if (_isReadOnly == value) + return; + if (!value) + throw new InvalidOperationException("Can't change this back to non readonly"); + _isReadOnly = value; + } + } + + public bool Remove(T item) + { + if (IsReadOnly) + throw new InvalidOperationException("This list is ReadOnly"); + return _actual.Remove(item); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)_actual).GetEnumerator(); + } + + public IEnumerator<T> GetEnumerator() + { + return _actual.GetEnumerator(); + } + + public int IndexOf(T item) + { + return _actual.IndexOf(item); + } + + public void Insert(int index, T item) + { + if (IsReadOnly) + throw new InvalidOperationException("This list is ReadOnly"); + _actual.Insert(index, item); + } + + public T this[int index] + { + get { return _actual[index]; } + set + { + if (IsReadOnly) + throw new InvalidOperationException("This list is ReadOnly"); + _actual[index] = value; + } + } + + public void RemoveAt(int index) + { + if (IsReadOnly) + throw new InvalidOperationException("This list is ReadOnly"); + _actual.RemoveAt(index); + } + } + } +}
\ No newline at end of file |