summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Pages/DataSourceList.cs
diff options
context:
space:
mode:
authorJason Smith <jason.smith@xamarin.com>2016-04-24 12:25:26 -0400
committerRui Marinho <me@ruimarinho.net>2016-04-24 12:25:26 -0400
commit5907152c50ee2c658b266f2804e6b383bb15a6f1 (patch)
tree9beb907623359723456c5c03b08922bebc4f41f3 /Xamarin.Forms.Pages/DataSourceList.cs
parentfeac1ba3ed6df5e27b3fa2076bd15c190cbacd1c (diff)
downloadxamarin-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.cs233
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