public IDisposable Subscribe(IObserver <ListChange <T> > observer) { lock (_gate) { if (_value.Count > 0) { var changes = ListChange.Combine(_value.Select((item, index) => ListChange.Insert(index, item))); observer.OnNext(changes); } switch (_state) { case State.Unconnected: case State.Connected: _observers = _observers.Add(observer); return(Disposable.Create(() => { lock (_gate) _observers = _observers.Remove(observer); })); case State.Completed: observer.OnCompleted(); return(Disposable.Empty); case State.Error: observer.OnError(_error); return(Disposable.Empty); default: throw new Exception("ReplayObservableList.Subscribe: Impossible"); } } }
IObserver <ListChange <T> > LeftObserver() { return(Observer.Create <ListChange <T> >( onNext: changes => { lock (_gate) { var newChanges = new List <ListChange <T> >(); changes( insert: (index, item) => { newChanges.Add(ListChange.Insert(index, item)); ++_leftCount; }, replace: (index, item) => { newChanges.Add(ListChange.Replace(index, item)); }, remove: index => { newChanges.Add(ListChange.Remove <T>(index)); --_leftCount; }, clear: () => { if (_rightCount == 0) { newChanges.Add(ListChange.Clear <T>()); } else { for (var i = _leftCount - 1; i >= 0; --i) { newChanges.Add(ListChange.Remove <T>(i)); } } _leftCount = 0; }); if (newChanges.Count > 0) { _observer.OnNext(ListChange.Combine(newChanges)); } } }, onCompleted: () => { lock (_gate) { if (_rightCompleted) { _observer.OnCompleted(); } _leftCompleted = true; } }, onError: e => { lock (_gate) _observer.OnError(e); })); }
public ListBehaviorSubject(IEnumerable <T> value) : this() { var change = ListChange.Combine(value.Select((item, index) => ListChange.Insert(index, item)).ToArray()); OnNext(change); }
public IDisposable Subscribe(IObserver <ListChange <T> > observer) { var mapper = new WhereChangeMapper(); var gate = new object(); return(_source.Subscribe( Observer.Create <ListChange <T> >( onNext: change => { lock (gate) { var newChanges = new List <ListChange <T> >(); change( insert: (index, item) => newChanges.AddRange(mapper.Insert(index, item, _predicate(item))), replace: (index, item) => newChanges.AddRange(mapper.Replace(index, item, _predicate(item))), remove: index => newChanges.AddRange(mapper.Remove <T>(index)), clear: () => newChanges.AddRange(mapper.Clear <T>())); if (newChanges.Count > 0) { observer.OnNext(ListChange.Combine(newChanges)); } } }, onCompleted: observer.OnCompleted, onError: observer.OnError))); }
public void OnNext(ListChange <T> change) { lock (_mutex) { _value = change.Apply(_value); _subject.OnNext(change); } }
public static void ApplyLegacy <T>(this ListChange <T> changes, IList list) { changes( insert: (i, x) => list.Insert(i, x), replace: (i, x) => list[i] = x, remove: list.RemoveAt, clear: list.Clear); }
public static ListChange <TResult> Select <TSource, TResult>(this ListChange <TSource> self, Func <TSource, TResult> select) { return((insert, replace, remove, clear) => self( insert: (i, x) => insert(i, select(x)), replace: (i, x) => replace(i, select(x)), remove: remove, clear: clear)); }
public IDisposable Subscribe(IObserver <ListChange <T> > observer) { if (_changes == null) { _changes = ListChange.Combine(_value.Select((t, i) => ListChange.Insert(i, t))); } observer.OnNext(_changes); observer.OnCompleted(); return(Disposable.Empty); }
public Optional <ListChange <T> > Clear <T>() { var oldTrueCount = _items.Sum(); _items = _items.Clear(); return(oldTrueCount == 0 ? Optional.None <ListChange <T> >() : ListChange.Clear <T>()); }
public Optional <ListChange <T> > Insert <T>(int index, T item, bool predicateTrue) { var toIndex = _items.Sum(index); _items = _items.Insert(index, predicateTrue ? 1 : 0); return(predicateTrue ? ListChange.Insert(toIndex, item) : Optional.None <ListChange <T> >()); }
public IDisposable Subscribe(IObserver <ListChange <T> > observer) { lock (_mutex) { var change = ListChange.Combine(_value.Select((item, index) => ListChange.Insert(index, item)).ToArray()); observer.OnNext(change); return(_subject.Subscribe(observer)); } }
public Optional <ListChange <T> > Remove <T>(int index) { var toIndex = _items.Sum(index); var predicateTrue = _items[index] == 1; _items = _items.RemoveAt(index); return(predicateTrue ? ListChange.Remove <T>(toIndex) : Optional.None <ListChange <T> >()); }
public static SumTree <T> Apply <T>(this ListChange <T> changes, SumTree <T> tree) { var result = tree; changes( insert: (i, x) => result = result.Insert(i, x), replace: (i, x) => result = result.ReplaceAt(i, x), remove: i => result = result.RemoveAt(i), clear: () => result = result.Clear()); return(result); }
public static ImmutableList <T> Apply <T>(this ListChange <T> changes, ImmutableList <T> list) { var result = list; changes( insert: (i, x) => result = result.Insert(i, x), replace: (i, x) => result = result.SetItem(i, x), remove: i => result = result.RemoveAt(i), clear: () => result = ImmutableList <T> .Empty); return(result); }
public void OnNext(ListChange <IObservable <T> > changes) { lock (_gate) { changes( insert: (index, obs) => { var indexedItem = new IndexTrackerList <SingleAssignmentDisposable> .IndexedItem(new SingleAssignmentDisposable()); _innerSubscriptions.Insert(index, indexedItem); _changeMapper.InsertFalse(index); _innerCompleted = _innerCompleted.Insert(index, false); indexedItem.Value.Disposable = SubscribeInner(obs, indexedItem); }, replace: (index, obs) => { _innerSubscriptions[index].Dispose(); var indexedItem = new IndexTrackerList <SingleAssignmentDisposable> .IndexedItem(new SingleAssignmentDisposable()); _innerSubscriptions.Replace(index, indexedItem); _innerCompleted = _innerCompleted.ReplaceAt(index, false); indexedItem.Value.Disposable = SubscribeInner(obs, indexedItem); // The new observable hasn't produced any values left, so remove any leftover old values foreach (var change in _changeMapper.ReplaceFalse <T>(index)) { _observer.OnNext(change); } }, remove: (index) => { _innerSubscriptions[index].Dispose(); _innerSubscriptions.Remove(index); _innerCompleted = _innerCompleted.RemoveAt(index); foreach (var change in _changeMapper.Remove <T>(index)) { _observer.OnNext(change); } }, clear: () => { Disposable.Combine(_innerSubscriptions).Dispose(); _innerSubscriptions.Clear(); _innerCompleted = SumTree <bool> .Empty(false, (d1, d2) => d1 && d2); foreach (var change in _changeMapper.Clear <T>()) { _observer.OnNext(change); } }); } }
public static IObservableList <T> ToObservableList <T>(this IObservable <IImmutableList <T> > self) { return(self .Scan( new { PrevList = (IImmutableList <T>)ImmutableList <T> .Empty, Changes = Optional.None <ListChange <T> >() }, (acc, newList) => new { PrevList = newList, Changes = ListChange.IncrementalChanges(acc.PrevList, newList), }) .SelectMany(acc => acc.Changes) .UnsafeAsObservableList()); }
public static string ToString <T>(this ListChange <T> self) { var results = new List <string>(); self( insert: (index, item) => results.Add("ListChange.Insert(" + index + ", " + item + ")"), replace: (index, item) => results.Add("ListChange.Replace(" + index + ", " + item + ")"), remove: index => results.Add("ListChange.Remove(" + index + ")"), clear: () => results.Add("ListChange.Clear()")); if (results.Count == 0) { return("ListChange.None()"); } if (results.Count == 1) { return(results[0]); } return("ListChange.Combine(" + results.Join(", ") + ")"); }
public Optional <ListChange <T> > Replace <T>(int index, T item, bool predicateTrue) { var toIndex = _items.Sum(index); var oldPredicateTrue = _items[index] == 1; _items = _items.ReplaceAt(index, predicateTrue ? 1 : 0); if (predicateTrue) { return(oldPredicateTrue ? ListChange.Replace(toIndex, item) : ListChange.Insert(toIndex, item)); } else { return(oldPredicateTrue ? ListChange.Remove <T>(toIndex) : Optional.None <ListChange <T> >()); } }
public T this[int i] { get { return(_value[i]); } set { OnNext(ListChange.Replace(i, value)); } }
public void OnInsert(int index, T item) { OnNext(ListChange.Insert(index, item)); }
public static IObservableList <T> SeparateBy <T>(this IObservableList <T> self, Func <T> separator) { return(self .SelectWithState( 0, (changes, res) => { var newChanges = new List <ListChange <T> >(); var count = res; changes( insert: (i, item) => { if (i == count) // inserting at the end { if (count == 0) // inserting first element: skip the separator { newChanges.Add(ListChange.Insert(0, item)); } else // add separator before item { newChanges.Add(ListChange.Insert(i * 2 - 1, separator())); newChanges.Add(ListChange.Insert(i * 2, item)); } } else // add separator after item { newChanges.Add(ListChange.Insert(i * 2, item)); newChanges.Add(ListChange.Insert(i * 2 + 1, separator())); } ++count; }, replace: (i, item) => { newChanges.Add(ListChange.Replace(i * 2, item)); }, remove: i => { if (i == count - 1) // removing at the end { if (i == 0) // removing first element: no separator to remove { newChanges.Add(ListChange.Remove <T>(0)); } else // remove separator before item { newChanges.Add(ListChange.Remove <T>(i * 2)); newChanges.Add(ListChange.Remove <T>(i * 2 - 1)); } } else // remove separator after item { newChanges.Add(ListChange.Remove <T>(i * 2 + 1)); newChanges.Add(ListChange.Remove <T>(i * 2)); } --count; }, clear: () => { newChanges.Add(ListChange.Clear <T>()); count = 0; }); return SelectResult.Create(ListChange.Combine(newChanges), count); }) .UnsafeAsObservableList()); }
public void OnRemove(int index) { OnNext(ListChange.Remove <T>(index)); }
public void OnReplace(int index, T item) { OnNext(ListChange.Replace(index, item)); }
public void OnClear() { OnNext(ListChange.Clear <T>()); }
public void OnAdd(T item) { lock (_mutex) OnNext(ListChange.Insert(_value.Count, item)); }
public static IObservableList <T> Switch <T>(this IObservable <IObservableList <T> > self) { return(self.Select(ol => ol.StartWith(ListChange.Clear <T>())).Switch().UnsafeAsObservableList()); }