summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Core/NotifyCollectionChangedEventArgsExtensions.cs
blob: 2ddf92c4f4390a8c237d16d452df79a4edf1552d (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
using System;
using System.Collections.Generic;
using System.Collections.Specialized;

namespace Xamarin.Forms
{
	internal static class NotifyCollectionChangedEventArgsExtensions
	{
		public static void Apply<TFrom>(this NotifyCollectionChangedEventArgs self, IList<TFrom> from, IList<object> to)
		{
			self.Apply((o, i, b) => to.Insert(i, o), (o, i) => to.RemoveAt(i), () =>
			{
				to.Clear();
				for (var i = 0; i < from.Count; i++)
					to.Add(from[i]);
			});
		}

		public static NotifyCollectionChangedAction Apply(this NotifyCollectionChangedEventArgs self, Action<object, int, bool> insert, Action<object, int> removeAt, Action reset)
		{
			if (self == null)
				throw new ArgumentNullException("self");
			if (reset == null)
				throw new ArgumentNullException("reset");
			if (insert == null)
				throw new ArgumentNullException("insert");
			if (removeAt == null)
				throw new ArgumentNullException("removeAt");

			switch (self.Action)
			{
				case NotifyCollectionChangedAction.Add:
					if (self.NewStartingIndex < 0)
						goto case NotifyCollectionChangedAction.Reset;

					for (var i = 0; i < self.NewItems.Count; i++)
						insert(self.NewItems[i], i + self.NewStartingIndex, true);

					break;

				case NotifyCollectionChangedAction.Move:
					if (self.NewStartingIndex < 0 || self.OldStartingIndex < 0)
						goto case NotifyCollectionChangedAction.Reset;

					for (var i = 0; i < self.OldItems.Count; i++)
						removeAt(self.OldItems[i], self.OldStartingIndex);

					int insertIndex = self.NewStartingIndex;
					if (self.OldStartingIndex < self.NewStartingIndex)
						insertIndex -= self.OldItems.Count - 1;

					for (var i = 0; i < self.OldItems.Count; i++)
						insert(self.OldItems[i], insertIndex + i, false);

					break;

				case NotifyCollectionChangedAction.Remove:
					if (self.OldStartingIndex < 0)
						goto case NotifyCollectionChangedAction.Reset;

					for (var i = 0; i < self.OldItems.Count; i++)
						removeAt(self.OldItems[i], self.OldStartingIndex);
					break;

				case NotifyCollectionChangedAction.Replace:
					if (self.OldStartingIndex < 0)
						goto case NotifyCollectionChangedAction.Reset;

					for (var i = 0; i < self.OldItems.Count; i++)
					{
						removeAt(self.OldItems[i], i + self.OldStartingIndex);
						insert(self.OldItems[i], i + self.OldStartingIndex, true);
					}
					break;

				case NotifyCollectionChangedAction.Reset:
					reset();
					return NotifyCollectionChangedAction.Reset;
			}

			return self.Action;
		}

		public static NotifyCollectionChangedEventArgsEx WithCount(this NotifyCollectionChangedEventArgs e, int count)
		{
			switch (e.Action)
			{
				case NotifyCollectionChangedAction.Add:
					return new NotifyCollectionChangedEventArgsEx(count, NotifyCollectionChangedAction.Add, e.NewItems, e.NewStartingIndex);

				case NotifyCollectionChangedAction.Remove:
					return new NotifyCollectionChangedEventArgsEx(count, NotifyCollectionChangedAction.Remove, e.OldItems, e.OldStartingIndex);

				case NotifyCollectionChangedAction.Move:
					return new NotifyCollectionChangedEventArgsEx(count, NotifyCollectionChangedAction.Move, e.OldItems, e.NewStartingIndex, e.OldStartingIndex);

				case NotifyCollectionChangedAction.Replace:
					return new NotifyCollectionChangedEventArgsEx(count, NotifyCollectionChangedAction.Replace, e.NewItems, e.OldItems, e.OldStartingIndex);

				default:
					return new NotifyCollectionChangedEventArgsEx(count, NotifyCollectionChangedAction.Reset);
			}
		}
	}
}