From 90e6a542186628023bad095c12971c02b2ae60d9 Mon Sep 17 00:00:00 2001 From: neuecc Date: Mon, 2 Sep 2024 19:50:59 +0900 Subject: [PATCH] Add ObserveClear, ObserveReverse, ObserverSort --- .../ObservableCollectionR3Extensions.cs | 108 ++++++++++++++++-- .../NotifyCollectionChangedEventArgs.cs | 9 ++ .../ObservableListTest.cs | 6 +- 3 files changed, 108 insertions(+), 15 deletions(-) diff --git a/src/ObservableCollections.R3/ObservableCollectionR3Extensions.cs b/src/ObservableCollections.R3/ObservableCollectionR3Extensions.cs index 724e2b0..2b72713 100644 --- a/src/ObservableCollections.R3/ObservableCollectionR3Extensions.cs +++ b/src/ObservableCollections.R3/ObservableCollectionR3Extensions.cs @@ -34,17 +34,32 @@ public static class ObservableCollectionR3Extensions { return new ObservableCollectionReplace(source, cancellationToken); } - + public static Observable> ObserveMove(this IObservableCollection source, CancellationToken cancellationToken = default) { return new ObservableCollectionMove(source, cancellationToken); } - - public static Observable ObserveReset(this IObservableCollection source, CancellationToken cancellationToken = default) + + public static Observable> ObserveReset(this IObservableCollection source, CancellationToken cancellationToken = default) { return new ObservableCollectionReset(source, cancellationToken); } + public static Observable ObserveClear(this IObservableCollection source, CancellationToken cancellationToken = default) + { + return new ObservableCollectionClear(source, cancellationToken); + } + + public static Observable ObserveReverse(this IObservableCollection source, CancellationToken cancellationToken = default) + { + return new ObservableCollectionReverse(source, cancellationToken); + } + + public static Observable<(int Index, int Count, IComparer Comparer)> ObserveSort(this IObservableCollection source, CancellationToken cancellationToken = default) + { + return new ObservableCollectionSort(source, cancellationToken); + } + public static Observable ObserveCountChanged(this IObservableCollection source, bool notifyCurrentCount = false, CancellationToken cancellationToken = default) { return new ObservableCollectionCountChanged(source, notifyCurrentCount, cancellationToken); @@ -148,7 +163,7 @@ sealed class ObservableCollectionReplace(IObservableCollection collection, { return new _ObservableCollectionReplace(collection, observer, cancellationToken); } - + sealed class _ObservableCollectionReplace( IObservableCollection collection, Observer> observer, @@ -172,7 +187,7 @@ sealed class ObservableCollectionMove(IObservableCollection collection, Ca { return new _ObservableCollectionMove(collection, observer, cancellationToken); } - + sealed class _ObservableCollectionMove( IObservableCollection collection, Observer> observer, @@ -188,16 +203,39 @@ sealed class ObservableCollectionMove(IObservableCollection collection, Ca } } } - sealed class ObservableCollectionReset(IObservableCollection collection, CancellationToken cancellationToken) + : Observable> +{ + protected override IDisposable SubscribeCore(Observer> observer) + { + return new _ObservableCollectionReset(collection, observer, cancellationToken); + } + + sealed class _ObservableCollectionReset( + IObservableCollection collection, + Observer> observer, + CancellationToken cancellationToken) + : ObservableCollectionObserverBase>(collection, observer, cancellationToken) + { + protected override void Handler(in NotifyCollectionChangedEventArgs eventArgs) + { + if (eventArgs.Action == NotifyCollectionChangedAction.Reset) + { + observer.OnNext(eventArgs.SortOperation); + } + } + } +} + +sealed class ObservableCollectionClear(IObservableCollection collection, CancellationToken cancellationToken) : Observable { protected override IDisposable SubscribeCore(Observer observer) { - return new _ObservableCollectionReset(collection, observer, cancellationToken); + return new _ObservableCollectionClear(collection, observer, cancellationToken); } - - sealed class _ObservableCollectionReset( + + sealed class _ObservableCollectionClear( IObservableCollection collection, Observer observer, CancellationToken cancellationToken) @@ -205,7 +243,7 @@ sealed class ObservableCollectionReset(IObservableCollection collection, C { protected override void Handler(in NotifyCollectionChangedEventArgs eventArgs) { - if (eventArgs.Action == NotifyCollectionChangedAction.Reset) + if (eventArgs.Action == NotifyCollectionChangedAction.Reset && eventArgs.SortOperation.IsNull) { observer.OnNext(Unit.Default); } @@ -213,6 +251,52 @@ sealed class ObservableCollectionReset(IObservableCollection collection, C } } +sealed class ObservableCollectionReverse(IObservableCollection collection, CancellationToken cancellationToken) : Observable +{ + protected override IDisposable SubscribeCore(Observer observer) + { + return new _ObservableCollectionReverse(collection, observer, cancellationToken); + } + + sealed class _ObservableCollectionReverse( + IObservableCollection collection, + Observer observer, + CancellationToken cancellationToken) + : ObservableCollectionObserverBase(collection, observer, cancellationToken) + { + protected override void Handler(in NotifyCollectionChangedEventArgs eventArgs) + { + if (eventArgs.Action == NotifyCollectionChangedAction.Reset && eventArgs.SortOperation.IsReverse) + { + observer.OnNext(Unit.Default); + } + } + } +} + +sealed class ObservableCollectionSort(IObservableCollection collection, CancellationToken cancellationToken) : Observable<(int Index, int Count, IComparer Comparer)> +{ + protected override IDisposable SubscribeCore(Observer<(int Index, int Count, IComparer Comparer)> observer) + { + return new _ObservableCollectionSort(collection, observer, cancellationToken); + } + + sealed class _ObservableCollectionSort( + IObservableCollection collection, + Observer<(int Index, int Count, IComparer Comparer)> observer, + CancellationToken cancellationToken) + : ObservableCollectionObserverBase Comparer)>(collection, observer, cancellationToken) + { + protected override void Handler(in NotifyCollectionChangedEventArgs eventArgs) + { + if (eventArgs.Action == NotifyCollectionChangedAction.Reset && eventArgs.SortOperation.IsSort) + { + observer.OnNext(eventArgs.SortOperation.AsTuple()); + } + } + } +} + sealed class ObservableCollectionCountChanged(IObservableCollection collection, bool notifyCurrentCount, CancellationToken cancellationToken) : Observable { @@ -220,7 +304,7 @@ sealed class ObservableCollectionCountChanged(IObservableCollection collec { return new _ObservableCollectionCountChanged(collection, notifyCurrentCount, observer, cancellationToken); } - + sealed class _ObservableCollectionCountChanged : ObservableCollectionObserverBase { int countPrev; @@ -372,7 +456,7 @@ abstract class ObservableCollectionObserverBase : IDisposable this.handlerDelegate = Handler; collection.CollectionChanged += handlerDelegate; - + if (cancellationToken.CanBeCanceled) { cancellationTokenRegistration = cancellationToken.UnsafeRegister(static state => diff --git a/src/ObservableCollections/NotifyCollectionChangedEventArgs.cs b/src/ObservableCollections/NotifyCollectionChangedEventArgs.cs index 05b13fd..4ad53a0 100644 --- a/src/ObservableCollections/NotifyCollectionChangedEventArgs.cs +++ b/src/ObservableCollections/NotifyCollectionChangedEventArgs.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ObservableCollections @@ -16,6 +17,9 @@ namespace ObservableCollections public bool IsReverse => Comparer == ReverseSentinel.Instance; public bool IsNull => Comparer == null; + [MemberNotNullWhen(true, nameof(Comparer))] + public bool IsSort => !IsNull && !IsReverse; + public SortOperation(int index, int count, IComparer? comparer) { Index = index; @@ -23,6 +27,11 @@ namespace ObservableCollections Comparer = comparer ?? NullComparerSentinel.Instance; } + public (int Index, int Count, IComparer Comparer) AsTuple() + { + return (Index, Count, Comparer!); + } + public static SortOperation CreateReverse(int index, int count) { return new SortOperation(index, count, ReverseSentinel.Instance); diff --git a/tests/ObservableCollections.Tests/ObservableListTest.cs b/tests/ObservableCollections.Tests/ObservableListTest.cs index 77e5b1a..f6b867b 100644 --- a/tests/ObservableCollections.Tests/ObservableListTest.cs +++ b/tests/ObservableCollections.Tests/ObservableListTest.cs @@ -157,8 +157,8 @@ namespace ObservableCollections.Tests // list.AddRange(new[] { 10, 21, 30, 44 }); // var filter1 = new TestFilter((x, v) => x % 2 == 0); - // view1.AttachFilter(filter1); - + // view1.AttachFilter((x, v) => x % 2 == 0)); + // filter1.CalledOnCollectionChanged[0].Action.Should().Be(NotifyCollectionChangedAction.Add); // filter1.CalledOnCollectionChanged[0].NewValue.Should().Be(10); // filter1.CalledOnCollectionChanged[1].Action.Should().Be(NotifyCollectionChangedAction.Add); @@ -170,6 +170,6 @@ namespace ObservableCollections.Tests // filter1.CalledWhenTrue.Count.Should().Be(3); // filter1.CalledWhenFalse.Count.Should().Be(1); - //} + //} } } \ No newline at end of file