summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Core/ObservableList.cs
blob: 82a6c4931d1242c3b520a9c0161be7ac0209f62e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;

namespace Xamarin.Forms
{
	internal class ObservableList<T> : ObservableCollection<T>
	{
		// There's lots of special-casing optimizations that could be done here
		// but right now this is only being used for tests.

		public void AddRange(IEnumerable<T> range)
		{
			if (range == null)
				throw new ArgumentNullException("range");

			List<T> items = range.ToList();
			int index = Items.Count;
			foreach (T item in items)
				Items.Add(item);

			OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, items, index));
		}

		public void InsertRange(int index, IEnumerable<T> range)
		{
			if (index < 0 || index > Count)
				throw new ArgumentOutOfRangeException("index");
			if (range == null)
				throw new ArgumentNullException("range");

			int originalIndex = index;

			List<T> items = range.ToList();
			foreach (T item in items)
				Items.Insert(index++, item);

			OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, items, originalIndex));
		}

		public void Move(int oldIndex, int newIndex, int count)
		{
			if (oldIndex < 0 || oldIndex + count > Count)
				throw new ArgumentOutOfRangeException("oldIndex");
			if (newIndex < 0 || newIndex + count > Count)
				throw new ArgumentOutOfRangeException("newIndex");

			var items = new List<T>(count);
			for (var i = 0; i < count; i++)
			{
				T item = Items[oldIndex];
				items.Add(item);
				Items.RemoveAt(oldIndex);
			}

			int index = newIndex;
			if (newIndex > oldIndex)
				index -= items.Count - 1;

			for (var i = 0; i < items.Count; i++)
				Items.Insert(index + i, items[i]);

			OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, items, newIndex, oldIndex));
		}

		public void RemoveAt(int index, int count)
		{
			if (index < 0 || index + count > Count)
				throw new ArgumentOutOfRangeException("index");

			T[] items = Items.Skip(index).Take(count).ToArray();
			for (int i = index; i < count; i++)
				Items.RemoveAt(i);

			OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, items, index));
		}

		public void RemoveRange(IEnumerable<T> range)
		{
			if (range == null)
				throw new ArgumentNullException("range");

			List<T> items = range.ToList();
			foreach (T item in items)
				Items.Remove(item);

			OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, items));
		}

		public void ReplaceRange(int startIndex, IEnumerable<T> items)
		{
			if (items == null)
				throw new ArgumentNullException("items");

			T[] ritems = items.ToArray();

			if (startIndex < 0 || startIndex + ritems.Length > Count)
				throw new ArgumentOutOfRangeException("startIndex");

			var oldItems = new T[ritems.Length];
			for (var i = 0; i < ritems.Length; i++)
			{
				oldItems[i] = Items[i + startIndex];
				Items[i + startIndex] = ritems[i];
			}

			OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, ritems, oldItems, startIndex));
		}
	}
}