diff options
author | Jason Smith <jason.smith@xamarin.com> | 2016-04-24 12:25:26 -0400 |
---|---|---|
committer | Rui Marinho <me@ruimarinho.net> | 2016-04-24 12:25:26 -0400 |
commit | 5907152c50ee2c658b266f2804e6b383bb15a6f1 (patch) | |
tree | 9beb907623359723456c5c03b08922bebc4f41f3 /Xamarin.Forms.Pages/DataSourceList.cs | |
parent | feac1ba3ed6df5e27b3fa2076bd15c190cbacd1c (diff) | |
download | xamarin-forms-5907152c50ee2c658b266f2804e6b383bb15a6f1.tar.gz xamarin-forms-5907152c50ee2c658b266f2804e6b383bb15a6f1.tar.bz2 xamarin-forms-5907152c50ee2c658b266f2804e6b383bb15a6f1.zip |
Evolve feature branch (#117)
* Initial import of evolve features
* [Android] Add Xamarin.Forms.Platform.Android.AppLinks project
* [iOS] Fix issues with c# 6 features on iOS AppLinks
* Added naive stanza to update-docs-windows.bat to produce Pages docs. Not tested. (#69)
* Update packages
* Add AppLinks android nuspec and fix linker issues
* Fix build
* Fix nusepc
* Fix nuspec
* Update android support nugets to 23.2.1
* Update Xamarin.UITest
* Add CardView
* [iOS] Fix app link for CoreSpotlight
* [Android] Update AppLinks android support libs
* Add Newtonsoft.Json dependency to nuspec
* Fix NRE when setting ControlTemplate to null
* Move to ModernHttpClient for download
* Try fix build
* Preserve android app links
* Fix margin issue
* General coding and simple fixes
Diffstat (limited to 'Xamarin.Forms.Pages/DataSourceList.cs')
-rw-r--r-- | Xamarin.Forms.Pages/DataSourceList.cs | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/Xamarin.Forms.Pages/DataSourceList.cs b/Xamarin.Forms.Pages/DataSourceList.cs new file mode 100644 index 00000000..7f3a59c1 --- /dev/null +++ b/Xamarin.Forms.Pages/DataSourceList.cs @@ -0,0 +1,233 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; + +namespace Xamarin.Forms.Pages +{ + internal class DataSourceList : IList<IDataItem>, IReadOnlyList<IDataItem>, INotifyCollectionChanged + { + readonly List<int> _maskedIndexes = new List<int>(); // Indices + readonly HashSet<string> _maskedKeys = new HashSet<string>(); + IList<IDataItem> _mainList; + + public IList<IDataItem> MainList + { + get { return _mainList; } + set + { + var observable = _mainList as INotifyCollectionChanged; + if (observable != null) + observable.CollectionChanged -= OnMainCollectionChanged; + _mainList = value; + observable = _mainList as INotifyCollectionChanged; + if (observable != null) + observable.CollectionChanged += OnMainCollectionChanged; + _maskedIndexes.Clear(); + for (var i = 0; i < _mainList.Count; i++) + { + IDataItem data = _mainList[i]; + if (_maskedKeys.Contains(data.Name)) + _maskedIndexes.Add(i); + } + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + } + } + + public IEnumerable<string> MaskedKeys => _maskedKeys; + + public void Add(IDataItem item) + { + throw new NotSupportedException(); + } + + public void Clear() + { + throw new NotSupportedException(); + } + + public bool Contains(IDataItem item) + { + return MainList != null && !_maskedKeys.Contains(item.Name) && MainList.Contains(item); + } + + public void CopyTo(IDataItem[] array, int arrayIndex) + { + throw new NotSupportedException(); + } + + public int Count + { + get + { + if (MainList == null) + return 0; + var result = 0; + result += MainList.Count; + result -= _maskedIndexes.Count; + return result; + } + } + + public bool IsReadOnly => true; + + public bool Remove(IDataItem item) + { + throw new NotSupportedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public IEnumerator<IDataItem> GetEnumerator() + { + var index = 0; + if (MainList == null) + yield break; + foreach (IDataItem item in MainList) + { + if (!_maskedIndexes.Contains(index)) + yield return item; + index++; + } + } + + public int IndexOf(IDataItem item) + { + if (_maskedKeys.Contains(item.Name)) + return -1; + + if (MainList != null) + { + int result = MainList.IndexOf(item); + if (result >= 0) + return PublicIndexFromMainIndex(result); + } + return -1; + } + + public void Insert(int index, IDataItem item) + { + throw new NotSupportedException(); + } + + public IDataItem this[int index] + { + get + { + foreach (int i in _maskedIndexes) + { + if (i <= index) + index++; + } + if (_mainList == null) + throw new IndexOutOfRangeException(); + return _mainList[index]; + } + set { throw new NotSupportedException(); } + } + + public void RemoveAt(int index) + { + throw new NotSupportedException(); + } + + public event NotifyCollectionChangedEventHandler CollectionChanged; + + public void MaskKey(string key) + { + if (_maskedKeys.Contains(key) || _mainList == null) + return; + _maskedKeys.Add(key); + var index = 0; + foreach (IDataItem item in _mainList) + { + if (item.Name == key) + { + // We need to keep our indexes list sorted, so we insert everything pre-sorted + var added = false; + for (var i = 0; i < _maskedIndexes.Count; i++) + { + if (_maskedIndexes[i] > index) + { + _maskedIndexes.Insert(i, index); + added = true; + break; + } + } + if (!added) + _maskedIndexes.Add(index); + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, PublicIndexFromMainIndex(index))); + break; + } + index++; + } + } + + public void UnmaskKey(string key) + { + _maskedKeys.Remove(key); + if (_mainList == null) + return; + var index = 0; + foreach (IDataItem item in _mainList) + { + if (item.Name == key) + { + bool removed = _maskedIndexes.Remove(index); + if (removed) + { + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, PublicIndexFromMainIndex(index))); + } + break; + } + index++; + } + } + + protected void OnCollectionChanged(NotifyCollectionChangedEventArgs args) + { + CollectionChanged?.Invoke(this, args); + } + + void OnMainCollectionChanged(object sender, NotifyCollectionChangedEventArgs args) + { + // much complexity to be had here + switch (args.Action) + { + case NotifyCollectionChangedAction.Add: + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, args.NewItems, PublicIndexFromMainIndex(args.NewStartingIndex))); + break; + case NotifyCollectionChangedAction.Move: + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, args.OldItems, PublicIndexFromMainIndex(args.NewStartingIndex), + PublicIndexFromMainIndex(args.OldStartingIndex))); + break; + case NotifyCollectionChangedAction.Remove: + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, args.OldItems, PublicIndexFromMainIndex(args.OldStartingIndex))); + break; + case NotifyCollectionChangedAction.Replace: + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, args.NewItems, args.OldItems, PublicIndexFromMainIndex(args.OldStartingIndex))); + break; + case NotifyCollectionChangedAction.Reset: + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + int PublicIndexFromMainIndex(int index) + { + var count = 0; + for (var x = 0; x < _maskedIndexes.Count; x++) + { + int i = _maskedIndexes[x]; + if (i < index) + count++; + } + return index - count; + } + } +}
\ No newline at end of file |