com.fofx.observething 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/README.md.meta +7 -0
- package/Runtime/CollectionIdProvider.cs +72 -0
- package/Runtime/CollectionIdProvider.cs.meta +2 -0
- package/Runtime/IObservable.cs +66 -0
- package/Runtime/IObservable.cs.meta +2 -0
- package/Runtime/Implementations/Observable.cs +30 -0
- package/Runtime/Implementations/Observable.cs.meta +2 -0
- package/Runtime/Implementations/ObservableBase.cs +173 -0
- package/Runtime/Implementations/ObservableBase.cs.meta +2 -0
- package/Runtime/Implementations/ObservableCollection.cs +141 -0
- package/Runtime/Implementations/ObservableCollection.cs.meta +2 -0
- package/Runtime/Implementations/ObservableDictionary.cs +166 -0
- package/Runtime/Implementations/ObservableDictionary.cs.meta +2 -0
- package/Runtime/Implementations/ObservableList.cs +163 -0
- package/Runtime/Implementations/ObservableList.cs.meta +2 -0
- package/Runtime/Implementations/ObservableSet.cs +137 -0
- package/Runtime/Implementations/ObservableSet.cs.meta +2 -0
- package/Runtime/Implementations/ObservableValue.cs +59 -0
- package/Runtime/Implementations/ObservableValue.cs.meta +2 -0
- package/Runtime/Implementations.meta +8 -0
- package/Runtime/Observables/BatchObservable.cs +72 -0
- package/Runtime/Observables/BatchObservable.cs.meta +2 -0
- package/Runtime/Observables/CastObservable.cs +128 -0
- package/Runtime/Observables/CastObservable.cs.meta +2 -0
- package/Runtime/Observables/CombineObservable.cs +96 -0
- package/Runtime/Observables/CombineObservable.cs.meta +2 -0
- package/Runtime/Observables/CombineValueObservable.cs +319 -0
- package/Runtime/Observables/CombineValueObservable.cs.meta +2 -0
- package/Runtime/Observables/ConcatObservable.cs +75 -0
- package/Runtime/Observables/ConcatObservable.cs.meta +2 -0
- package/Runtime/Observables/ContainsObservable.cs +71 -0
- package/Runtime/Observables/ContainsObservable.cs.meta +2 -0
- package/Runtime/Observables/CountObservable.cs +29 -0
- package/Runtime/Observables/CountObservable.cs.meta +2 -0
- package/Runtime/Observables/DistinctObservable.cs +55 -0
- package/Runtime/Observables/DistinctObservable.cs.meta +2 -0
- package/Runtime/Observables/FirstObservable.cs +53 -0
- package/Runtime/Observables/FirstObservable.cs.meta +2 -0
- package/Runtime/Observables/IndexOfObservable.cs +83 -0
- package/Runtime/Observables/IndexOfObservable.cs.meta +2 -0
- package/Runtime/Observables/OperationStreamObservable.cs +194 -0
- package/Runtime/Observables/OperationStreamObservable.cs.meta +2 -0
- package/Runtime/Observables/OrderByObservable.cs +116 -0
- package/Runtime/Observables/OrderByObservable.cs.meta +2 -0
- package/Runtime/Observables/SelectCollectionObservable.cs +29 -0
- package/Runtime/Observables/SelectCollectionObservable.cs.meta +2 -0
- package/Runtime/Observables/SelectListObservable.cs +29 -0
- package/Runtime/Observables/SelectListObservable.cs.meta +2 -0
- package/Runtime/Observables/SelectManyObservable.cs +78 -0
- package/Runtime/Observables/SelectManyObservable.cs.meta +2 -0
- package/Runtime/Observables/SelectValueObservable.cs +28 -0
- package/Runtime/Observables/SelectValueObservable.cs.meta +2 -0
- package/Runtime/Observables/SkipWhileObservable.cs +32 -0
- package/Runtime/Observables/SkipWhileObservable.cs.meta +2 -0
- package/Runtime/Observables/ThenObservable.cs +209 -0
- package/Runtime/Observables/ThenObservable.cs.meta +2 -0
- package/Runtime/Observables/ToDictionaryObservable.cs +35 -0
- package/Runtime/Observables/ToDictionaryObservable.cs.meta +2 -0
- package/Runtime/Observables/TrackObservable.cs +74 -0
- package/Runtime/Observables/TrackObservable.cs.meta +2 -0
- package/Runtime/Observables/UnwrapCollectionObservable.cs +64 -0
- package/Runtime/Observables/UnwrapCollectionObservable.cs.meta +2 -0
- package/Runtime/Observables/UnwrapListObservable.cs +69 -0
- package/Runtime/Observables/UnwrapListObservable.cs.meta +2 -0
- package/Runtime/Observables/UnwrapValueObservable.cs +56 -0
- package/Runtime/Observables/UnwrapValueObservable.cs.meta +2 -0
- package/Runtime/Observables/WhereObservable.cs +85 -0
- package/Runtime/Observables/WhereObservable.cs.meta +2 -0
- package/Runtime/Observables/WithPreviousObservable.cs +36 -0
- package/Runtime/Observables/WithPreviousObservable.cs.meta +2 -0
- package/Runtime/Observables.cs +467 -0
- package/Runtime/Observables.cs.meta +2 -0
- package/Runtime/Observables.meta +8 -0
- package/Runtime/ObservationContext.cs +126 -0
- package/Runtime/ObservationContext.cs.meta +2 -0
- package/Runtime/Observers.cs +403 -0
- package/Runtime/Observers.cs.meta +2 -0
- package/Runtime/Operators/BatchOperator.cs +71 -0
- package/Runtime/Operators/BatchOperator.cs.meta +2 -0
- package/Runtime/Operators/CollectionOperator.cs +30 -0
- package/Runtime/Operators/CollectionOperator.cs.meta +2 -0
- package/Runtime/Operators/DictionaryOperator.cs +45 -0
- package/Runtime/Operators/DictionaryOperator.cs.meta +2 -0
- package/Runtime/Operators/IInitializationOperationsProvider.cs +10 -0
- package/Runtime/Operators/IInitializationOperationsProvider.cs.meta +2 -0
- package/Runtime/Operators/ListOperator.cs +44 -0
- package/Runtime/Operators/ListOperator.cs.meta +2 -0
- package/Runtime/Operators/ObservableOperator.cs +75 -0
- package/Runtime/Operators/ObservableOperator.cs.meta +2 -0
- package/Runtime/Operators/Operator.cs +65 -0
- package/Runtime/Operators/Operator.cs.meta +2 -0
- package/Runtime/Operators/SetOperator.cs +44 -0
- package/Runtime/Operators/SetOperator.cs.meta +2 -0
- package/Runtime/Operators/ValueOperator.cs +30 -0
- package/Runtime/Operators/ValueOperator.cs.meta +2 -0
- package/Runtime/Operators.meta +8 -0
- package/Runtime/PriorityQueue.cs +1096 -0
- package/Runtime/PriorityQueue.cs.meta +2 -0
- package/Runtime/com.fofx.observething.asmdef +14 -0
- package/Runtime/com.fofx.observething.asmdef.meta +7 -0
- package/Runtime.meta +8 -0
- package/Tests/CollectionObservableTests.cs +739 -0
- package/Tests/CollectionObservableTests.cs.meta +2 -0
- package/Tests/DictionaryObservableTests.cs +85 -0
- package/Tests/DictionaryObservableTests.cs.meta +2 -0
- package/Tests/ListObservableTests.cs +148 -0
- package/Tests/ListObservableTests.cs.meta +2 -0
- package/Tests/ObservationContextTests.cs +359 -0
- package/Tests/ObservationContextTests.cs.meta +2 -0
- package/Tests/ValueObservableTests.cs +322 -0
- package/Tests/ValueObservableTests.cs.meta +2 -0
- package/Tests/com.fofx.observething.tests.asmdef +24 -0
- package/Tests/com.fofx.observething.tests.asmdef.meta +7 -0
- package/Tests.meta +8 -0
- package/package.json +24 -0
- package/package.json.meta +7 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
|
|
4
|
+
namespace ObserveThing
|
|
5
|
+
{
|
|
6
|
+
public class IndexOfObservable<T> : IDisposable
|
|
7
|
+
{
|
|
8
|
+
private ObservableValue<(bool found, int index)> _operand;
|
|
9
|
+
private T _latest = default;
|
|
10
|
+
private List<T> _list = new List<T>();
|
|
11
|
+
private IDisposable _subscriptions;
|
|
12
|
+
|
|
13
|
+
public IndexOfObservable(IListObservable<T> source, IValueObservable<T> value, ObservableValue<(bool found, int index)> operand)
|
|
14
|
+
{
|
|
15
|
+
_operand = operand;
|
|
16
|
+
_subscriptions = new ComposedDisposable(
|
|
17
|
+
|
|
18
|
+
value.Subscribe(
|
|
19
|
+
onNext: HandleNext,
|
|
20
|
+
onError: operand.OnError,
|
|
21
|
+
onDispose: Dispose,
|
|
22
|
+
immediate: true
|
|
23
|
+
),
|
|
24
|
+
|
|
25
|
+
source.Subscribe(
|
|
26
|
+
onAdd: HandleAdd,
|
|
27
|
+
onRemove: HandleRemove,
|
|
28
|
+
onError: operand.OnError,
|
|
29
|
+
onDispose: Dispose,
|
|
30
|
+
immediate: true
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private void HandleAdd(int index, T element)
|
|
37
|
+
{
|
|
38
|
+
_list.Insert(index, element);
|
|
39
|
+
UpdateIndexIfNecessary();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private void HandleRemove(int index, T element)
|
|
43
|
+
{
|
|
44
|
+
_list.RemoveAt(index);
|
|
45
|
+
UpdateIndexIfNecessary();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private void HandleNext(T value)
|
|
49
|
+
{
|
|
50
|
+
_latest = value;
|
|
51
|
+
UpdateIndexIfNecessary();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private void UpdateIndexIfNecessary()
|
|
55
|
+
{
|
|
56
|
+
var newIndex = -1;
|
|
57
|
+
|
|
58
|
+
for (int i = 0; i < _list.Count; i++)
|
|
59
|
+
{
|
|
60
|
+
if (Equals(_latest, _list[i]))
|
|
61
|
+
{
|
|
62
|
+
newIndex = i;
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (newIndex == -1)
|
|
68
|
+
{
|
|
69
|
+
_operand.value = default;
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
_operand.value = new(true, newIndex);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public void Dispose()
|
|
77
|
+
{
|
|
78
|
+
_subscriptions?.Dispose();
|
|
79
|
+
_subscriptions = null;
|
|
80
|
+
_operand.Dispose();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
|
|
4
|
+
namespace ObserveThing
|
|
5
|
+
{
|
|
6
|
+
public class ValueOperationStreamObservable<T> : IInitializationOperationsProvider<ValueOp<T>>, IDisposable
|
|
7
|
+
{
|
|
8
|
+
private IValueObservable<T> _source;
|
|
9
|
+
private Observable<ValueOp<T>> _operand;
|
|
10
|
+
private IDisposable _subscriptions;
|
|
11
|
+
|
|
12
|
+
public ValueOperationStreamObservable(IValueObservable<T> source, Observable<ValueOp<T>> operand)
|
|
13
|
+
{
|
|
14
|
+
_source = source;
|
|
15
|
+
_operand = operand;
|
|
16
|
+
|
|
17
|
+
_subscriptions = _source.Subscribe(
|
|
18
|
+
onNext: x => operand.EnqueueOperation(new() { source = _source, value = x }),
|
|
19
|
+
onDispose: Dispose,
|
|
20
|
+
onError: operand.OnError,
|
|
21
|
+
immediate: true
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public IEnumerable<ValueOp<T>> GetInitializationOperations()
|
|
26
|
+
{
|
|
27
|
+
var initOperations = new List<ValueOp<T>>();
|
|
28
|
+
var subscription = _source.Subscribe(x => initOperations.Add(new ValueOp<T>() { source = _source, value = x }));
|
|
29
|
+
subscription.Dispose();
|
|
30
|
+
|
|
31
|
+
foreach (var op in initOperations)
|
|
32
|
+
yield return op;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public void Dispose()
|
|
36
|
+
{
|
|
37
|
+
_subscriptions?.Dispose();
|
|
38
|
+
_subscriptions = null;
|
|
39
|
+
_operand.Dispose();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public class CollectionOperationStreamObservable<T> : IInitializationOperationsProvider<CollectionOp<T>>, IDisposable
|
|
44
|
+
{
|
|
45
|
+
private ICollectionObservable<T> _source;
|
|
46
|
+
private Observable<CollectionOp<T>> _operand;
|
|
47
|
+
private IDisposable _subscriptions;
|
|
48
|
+
|
|
49
|
+
public CollectionOperationStreamObservable(ICollectionObservable<T> source, Observable<CollectionOp<T>> operand)
|
|
50
|
+
{
|
|
51
|
+
_source = source;
|
|
52
|
+
_operand = operand;
|
|
53
|
+
|
|
54
|
+
_subscriptions = _source.SubscribeWithId(
|
|
55
|
+
onAdd: (id, element) => operand.EnqueueOperation(new() { source = _source, elementId = id, element = element, isRemove = false }),
|
|
56
|
+
onRemove: (id, element) => operand.EnqueueOperation(new() { source = _source, elementId = id, element = element, isRemove = true }),
|
|
57
|
+
onDispose: Dispose,
|
|
58
|
+
onError: operand.OnError,
|
|
59
|
+
immediate: true
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public IEnumerable<CollectionOp<T>> GetInitializationOperations()
|
|
64
|
+
{
|
|
65
|
+
var initOperations = new List<CollectionOp<T>>();
|
|
66
|
+
var subscription = _source.SubscribeWithId((id, element) => initOperations.Add(new CollectionOp<T>() { source = _source, elementId = id, element = element }));
|
|
67
|
+
subscription.Dispose();
|
|
68
|
+
|
|
69
|
+
foreach (var op in initOperations)
|
|
70
|
+
yield return op;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public void Dispose()
|
|
74
|
+
{
|
|
75
|
+
_subscriptions?.Dispose();
|
|
76
|
+
_subscriptions = null;
|
|
77
|
+
_operand.Dispose();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public class ListOperationStreamObservable<T> : IInitializationOperationsProvider<ListOp<T>>, IDisposable
|
|
82
|
+
{
|
|
83
|
+
private IListObservable<T> _source;
|
|
84
|
+
private Observable<ListOp<T>> _operand;
|
|
85
|
+
private IDisposable _subscriptions;
|
|
86
|
+
|
|
87
|
+
public ListOperationStreamObservable(IListObservable<T> source, Observable<ListOp<T>> operand)
|
|
88
|
+
{
|
|
89
|
+
_source = source;
|
|
90
|
+
_operand = operand;
|
|
91
|
+
|
|
92
|
+
_subscriptions = _source.SubscribeWithId(
|
|
93
|
+
onAdd: (id, index, element) => operand.EnqueueOperation(new() { source = _source, elementId = id, index = index, element = element, isRemove = false }),
|
|
94
|
+
onRemove: (id, index, element) => operand.EnqueueOperation(new() { source = _source, elementId = id, index = index, element = element, isRemove = true }),
|
|
95
|
+
onDispose: Dispose,
|
|
96
|
+
onError: operand.OnError,
|
|
97
|
+
immediate: true
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public IEnumerable<ListOp<T>> GetInitializationOperations()
|
|
102
|
+
{
|
|
103
|
+
var initOperations = new List<ListOp<T>>();
|
|
104
|
+
var subscription = _source.SubscribeWithId((id, index, element) => initOperations.Add(new ListOp<T>() { source = _source, elementId = id, index = index, element = element }));
|
|
105
|
+
subscription.Dispose();
|
|
106
|
+
|
|
107
|
+
foreach (var op in initOperations)
|
|
108
|
+
yield return op;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public void Dispose()
|
|
112
|
+
{
|
|
113
|
+
_subscriptions?.Dispose();
|
|
114
|
+
_subscriptions = null;
|
|
115
|
+
_operand.Dispose();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public class DictionaryOperationStreamObservable<TKey, TValue> : IInitializationOperationsProvider<DictionaryOp<TKey, TValue>>, IDisposable
|
|
120
|
+
{
|
|
121
|
+
private IDictionaryObservable<TKey, TValue> _source;
|
|
122
|
+
private Observable<DictionaryOp<TKey, TValue>> _operand;
|
|
123
|
+
private IDisposable _subscriptions;
|
|
124
|
+
|
|
125
|
+
public DictionaryOperationStreamObservable(IDictionaryObservable<TKey, TValue> source, Observable<DictionaryOp<TKey, TValue>> operand)
|
|
126
|
+
{
|
|
127
|
+
_source = source;
|
|
128
|
+
_operand = operand;
|
|
129
|
+
|
|
130
|
+
_subscriptions = _source.SubscribeWithId(
|
|
131
|
+
onAdd: (id, kvp) => operand.EnqueueOperation(new() { source = _source, elementId = id, key = kvp.Key, value = kvp.Value, isRemove = false }),
|
|
132
|
+
onRemove: (id, kvp) => operand.EnqueueOperation(new() { source = _source, elementId = id, key = kvp.Key, value = kvp.Value, isRemove = true }),
|
|
133
|
+
onDispose: Dispose,
|
|
134
|
+
onError: operand.OnError,
|
|
135
|
+
immediate: true
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
public IEnumerable<DictionaryOp<TKey, TValue>> GetInitializationOperations()
|
|
140
|
+
{
|
|
141
|
+
var initOperations = new List<DictionaryOp<TKey, TValue>>();
|
|
142
|
+
var subscription = _source.SubscribeWithId((id, kvp) => initOperations.Add(new DictionaryOp<TKey, TValue>() { source = _source, elementId = id, key = kvp.Key, value = kvp.Value }));
|
|
143
|
+
subscription.Dispose();
|
|
144
|
+
|
|
145
|
+
foreach (var op in initOperations)
|
|
146
|
+
yield return op;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
public void Dispose()
|
|
150
|
+
{
|
|
151
|
+
_subscriptions?.Dispose();
|
|
152
|
+
_subscriptions = null;
|
|
153
|
+
_operand.Dispose();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
public class SetOperationStreamObservable<T> : IInitializationOperationsProvider<SetOp<T>>, IDisposable
|
|
158
|
+
{
|
|
159
|
+
private ISetObservable<T> _source;
|
|
160
|
+
private Observable<SetOp<T>> _operand;
|
|
161
|
+
private IDisposable _subscriptions;
|
|
162
|
+
|
|
163
|
+
public SetOperationStreamObservable(ISetObservable<T> source, Observable<SetOp<T>> operand)
|
|
164
|
+
{
|
|
165
|
+
_source = source;
|
|
166
|
+
_operand = operand;
|
|
167
|
+
|
|
168
|
+
_subscriptions = _source.SubscribeWithId(
|
|
169
|
+
onAdd: (id, element) => operand.EnqueueOperation(new() { source = _source, elementId = id, element = element, isRemove = false }),
|
|
170
|
+
onRemove: (id, element) => operand.EnqueueOperation(new() { source = _source, elementId = id, element = element, isRemove = true }),
|
|
171
|
+
onDispose: Dispose,
|
|
172
|
+
onError: operand.OnError,
|
|
173
|
+
immediate: true
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
public IEnumerable<SetOp<T>> GetInitializationOperations()
|
|
178
|
+
{
|
|
179
|
+
var initOperations = new List<SetOp<T>>();
|
|
180
|
+
var subscription = _source.SubscribeWithId((id, element) => initOperations.Add(new SetOp<T>() { source = _source, elementId = id, element = element }));
|
|
181
|
+
subscription.Dispose();
|
|
182
|
+
|
|
183
|
+
foreach (var op in initOperations)
|
|
184
|
+
yield return op;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
public void Dispose()
|
|
188
|
+
{
|
|
189
|
+
_subscriptions?.Dispose();
|
|
190
|
+
_subscriptions = null;
|
|
191
|
+
_operand.Dispose();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Linq;
|
|
4
|
+
using UnityEngine;
|
|
5
|
+
|
|
6
|
+
namespace ObserveThing
|
|
7
|
+
{
|
|
8
|
+
public class OrderByObservable<T, U> : IDisposable
|
|
9
|
+
{
|
|
10
|
+
private ObservableList<T> _operand;
|
|
11
|
+
private Func<T, IValueObservable<U>> _orderBy;
|
|
12
|
+
private Func<U, U, int> _compare;
|
|
13
|
+
private Dictionary<uint, EntryData> _dataById = new Dictionary<uint, EntryData>();
|
|
14
|
+
private List<EntryData> _order = new List<EntryData>();
|
|
15
|
+
private IDisposable _subscriptions;
|
|
16
|
+
|
|
17
|
+
private class EntryData
|
|
18
|
+
{
|
|
19
|
+
public uint id;
|
|
20
|
+
public T element;
|
|
21
|
+
public U orderBy;
|
|
22
|
+
public IDisposable subscription;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public OrderByObservable(ICollectionObservable<T> source, Func<T, IValueObservable<U>> orderBy, bool descending, ObservableList<T> operand)
|
|
26
|
+
{
|
|
27
|
+
_orderBy = orderBy;
|
|
28
|
+
_compare = descending ? DescendingCompare : AscendingCompare;
|
|
29
|
+
_operand = operand;
|
|
30
|
+
_subscriptions = source.SubscribeWithId(
|
|
31
|
+
onAdd: HandleAdd,
|
|
32
|
+
onRemove: HandleRemove,
|
|
33
|
+
onError: _operand.OnError,
|
|
34
|
+
onDispose: Dispose,
|
|
35
|
+
immediate: true
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private int DescendingCompare(U v1, U v2)
|
|
40
|
+
=> Comparer<U>.Default.Compare(v2, v1);
|
|
41
|
+
|
|
42
|
+
private int AscendingCompare(U v1, U v2)
|
|
43
|
+
=> Comparer<U>.Default.Compare(v1, v2);
|
|
44
|
+
|
|
45
|
+
private void HandleAdd(uint id, T element)
|
|
46
|
+
{
|
|
47
|
+
var data = new EntryData()
|
|
48
|
+
{
|
|
49
|
+
id = id,
|
|
50
|
+
element = element
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
_dataById.Add(id, data);
|
|
54
|
+
data.subscription = _orderBy(element).Subscribe(
|
|
55
|
+
onNext: x =>
|
|
56
|
+
{
|
|
57
|
+
data.orderBy = x;
|
|
58
|
+
Resort(data);
|
|
59
|
+
},
|
|
60
|
+
onError: _operand.OnError,
|
|
61
|
+
immediate: true
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private void HandleRemove(uint id, T element)
|
|
66
|
+
{
|
|
67
|
+
var data = _dataById[id];
|
|
68
|
+
int index = _order.IndexOf(data);
|
|
69
|
+
_dataById.Remove(id);
|
|
70
|
+
_order.RemoveAt(index);
|
|
71
|
+
data.subscription.Dispose();
|
|
72
|
+
_operand.RemoveAt(index);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private void Resort(EntryData data)
|
|
76
|
+
{
|
|
77
|
+
var originalIndex = _order.IndexOf(data);
|
|
78
|
+
|
|
79
|
+
if (originalIndex != -1)
|
|
80
|
+
_order.RemoveAt(originalIndex);
|
|
81
|
+
|
|
82
|
+
int newIndex = -1;
|
|
83
|
+
|
|
84
|
+
for (int i = 0; i < _order.Count; i++)
|
|
85
|
+
{
|
|
86
|
+
var compareTo = _order[i];
|
|
87
|
+
|
|
88
|
+
if (_compare(data.orderBy, compareTo.orderBy) > 0)
|
|
89
|
+
continue;
|
|
90
|
+
|
|
91
|
+
newIndex = i;
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (newIndex == -1)
|
|
96
|
+
newIndex = _order.Count;
|
|
97
|
+
|
|
98
|
+
_order.Insert(newIndex, data);
|
|
99
|
+
|
|
100
|
+
if (originalIndex != newIndex)
|
|
101
|
+
{
|
|
102
|
+
if (originalIndex != -1)
|
|
103
|
+
_operand.RemoveAt(originalIndex);
|
|
104
|
+
|
|
105
|
+
_operand.Insert(newIndex, data.element);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public void Dispose()
|
|
110
|
+
{
|
|
111
|
+
_subscriptions?.Dispose();
|
|
112
|
+
_subscriptions = null;
|
|
113
|
+
_operand.Dispose();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
|
|
3
|
+
namespace ObserveThing
|
|
4
|
+
{
|
|
5
|
+
public class SelectCollectionObservable<T, U> : IDisposable
|
|
6
|
+
{
|
|
7
|
+
private ObservableCollection<U> _operand;
|
|
8
|
+
private IDisposable _subscriptions;
|
|
9
|
+
|
|
10
|
+
public SelectCollectionObservable(ICollectionObservable<T> source, Func<T, U> select, ObservableCollection<U> operand)
|
|
11
|
+
{
|
|
12
|
+
_operand = operand;
|
|
13
|
+
_subscriptions = source.SubscribeWithId(
|
|
14
|
+
onAdd: (id, value) => operand.Add(id, select(value)),
|
|
15
|
+
onRemove: (id, _) => operand.Remove(id),
|
|
16
|
+
onError: operand.OnError,
|
|
17
|
+
onDispose: Dispose,
|
|
18
|
+
immediate: true
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public void Dispose()
|
|
23
|
+
{
|
|
24
|
+
_subscriptions?.Dispose();
|
|
25
|
+
_subscriptions = null;
|
|
26
|
+
_operand.Dispose();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
|
|
3
|
+
namespace ObserveThing
|
|
4
|
+
{
|
|
5
|
+
public class SelectListObservable<T, U> : IDisposable
|
|
6
|
+
{
|
|
7
|
+
private ObservableList<U> _operand;
|
|
8
|
+
private IDisposable _subscriptions;
|
|
9
|
+
|
|
10
|
+
public SelectListObservable(IListObservable<T> source, Func<T, U> select, ObservableList<U> operand)
|
|
11
|
+
{
|
|
12
|
+
_operand = operand;
|
|
13
|
+
_subscriptions = source.Subscribe(
|
|
14
|
+
onAdd: (index, value) => _operand.Insert(index, select(value)),
|
|
15
|
+
onRemove: (index, _) => _operand.RemoveAt(index),
|
|
16
|
+
onError: _operand.OnError,
|
|
17
|
+
onDispose: Dispose,
|
|
18
|
+
immediate: true
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public void Dispose()
|
|
23
|
+
{
|
|
24
|
+
_subscriptions?.Dispose();
|
|
25
|
+
_subscriptions = null;
|
|
26
|
+
_operand.Dispose();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Linq;
|
|
4
|
+
|
|
5
|
+
namespace ObserveThing
|
|
6
|
+
{
|
|
7
|
+
public class SelectManyObservable<T, U> : IDisposable
|
|
8
|
+
{
|
|
9
|
+
private class ElementData
|
|
10
|
+
{
|
|
11
|
+
public IDisposable subscription;
|
|
12
|
+
public Dictionary<uint, uint> elementIds = new Dictionary<uint, uint>();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
private ObservableCollection<U> _operand;
|
|
16
|
+
private Func<T, ICollectionObservable<U>> _select;
|
|
17
|
+
private Dictionary<uint, ElementData> _dataById = new Dictionary<uint, ElementData>();
|
|
18
|
+
private CollectionIdProvider _idProvider;
|
|
19
|
+
private IDisposable _subscriptions;
|
|
20
|
+
|
|
21
|
+
public SelectManyObservable(ICollectionObservable<T> source, Func<T, ICollectionObservable<U>> select, ObservableCollection<U> operand)
|
|
22
|
+
{
|
|
23
|
+
_select = select;
|
|
24
|
+
_operand = operand;
|
|
25
|
+
_idProvider = new CollectionIdProvider(x => _dataById.Values.Any(y => y.elementIds.ContainsKey(x)));
|
|
26
|
+
_subscriptions = source.SubscribeWithId(
|
|
27
|
+
onAdd: HandleAdd,
|
|
28
|
+
onRemove: HandleRemove,
|
|
29
|
+
onError: operand.OnError,
|
|
30
|
+
onDispose: Dispose,
|
|
31
|
+
immediate: true
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private void HandleAdd(uint id, T element)
|
|
36
|
+
{
|
|
37
|
+
var data = new ElementData();
|
|
38
|
+
_dataById.Add(id, data);
|
|
39
|
+
data.subscription = _select(element).SubscribeWithId(
|
|
40
|
+
onAdd: (subId, subElement) =>
|
|
41
|
+
{
|
|
42
|
+
var newId = _idProvider.GetUnusedId();
|
|
43
|
+
data.elementIds.Add(subId, newId);
|
|
44
|
+
_operand.Add(newId, subElement);
|
|
45
|
+
},
|
|
46
|
+
onRemove: (subId, subElement) =>
|
|
47
|
+
{
|
|
48
|
+
var elementId = data.elementIds[subId];
|
|
49
|
+
data.elementIds.Remove(subId);
|
|
50
|
+
_operand.Remove(elementId);
|
|
51
|
+
},
|
|
52
|
+
onError: _operand.OnError,
|
|
53
|
+
immediate: true
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private void HandleRemove(uint id, T element)
|
|
58
|
+
{
|
|
59
|
+
var data = _dataById[id];
|
|
60
|
+
_dataById.Remove(id);
|
|
61
|
+
data.subscription.Dispose();
|
|
62
|
+
|
|
63
|
+
foreach (var elementId in data.elementIds.Values)
|
|
64
|
+
_operand.Remove(elementId);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public void Dispose()
|
|
68
|
+
{
|
|
69
|
+
_subscriptions?.Dispose();
|
|
70
|
+
_subscriptions = null;
|
|
71
|
+
|
|
72
|
+
foreach (var data in _dataById.Values)
|
|
73
|
+
data.subscription.Dispose();
|
|
74
|
+
|
|
75
|
+
_operand.Dispose();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
|
|
3
|
+
namespace ObserveThing
|
|
4
|
+
{
|
|
5
|
+
public class SelectValueOperator<T, U> : IDisposable
|
|
6
|
+
{
|
|
7
|
+
private ObservableValue<U> _operand;
|
|
8
|
+
private IDisposable _subscriptions;
|
|
9
|
+
|
|
10
|
+
public SelectValueOperator(IValueObservable<T> source, Func<T, U> select, ObservableValue<U> operand)
|
|
11
|
+
{
|
|
12
|
+
_operand = operand;
|
|
13
|
+
_subscriptions = source.Subscribe(
|
|
14
|
+
onNext: x => operand.value = select(x),
|
|
15
|
+
onError: operand.OnError,
|
|
16
|
+
onDispose: operand.Dispose,
|
|
17
|
+
immediate: true
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public void Dispose()
|
|
22
|
+
{
|
|
23
|
+
_subscriptions?.Dispose();
|
|
24
|
+
_subscriptions = null;
|
|
25
|
+
_operand.Dispose();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
|
|
3
|
+
namespace ObserveThing
|
|
4
|
+
{
|
|
5
|
+
public class SkipWhileObservable<T> : IDisposable
|
|
6
|
+
{
|
|
7
|
+
private ObservableValue<T> _operand;
|
|
8
|
+
private IDisposable _subscriptions;
|
|
9
|
+
|
|
10
|
+
public SkipWhileObservable(IValueObservable<T> source, Func<bool> skipWhile, ObservableValue<T> operand)
|
|
11
|
+
{
|
|
12
|
+
_operand = operand;
|
|
13
|
+
_subscriptions = source.Subscribe(
|
|
14
|
+
onNext: value =>
|
|
15
|
+
{
|
|
16
|
+
if (!skipWhile())
|
|
17
|
+
_operand.value = value;
|
|
18
|
+
},
|
|
19
|
+
onError: _operand.OnError,
|
|
20
|
+
onDispose: Dispose,
|
|
21
|
+
immediate: true
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public void Dispose()
|
|
26
|
+
{
|
|
27
|
+
_subscriptions?.Dispose();
|
|
28
|
+
_subscriptions = null;
|
|
29
|
+
_operand.Dispose();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|