Line data Source code
1 : import 'dart:collection';
2 :
3 : import 'package:flutter/foundation.dart';
4 : import 'package:collection_providers/collection_providers.dart';
5 :
6 : class SetChangeNotifier<T> extends CollectionChangeNotifier with SetMixin<T> {
7 : Set<T> _set;
8 :
9 2 : SetChangeNotifier([Set<T> backingSet]) {
10 4 : _set = Set<T>.from(backingSet ?? {});
11 : }
12 :
13 : /// Adds [value] to the set.
14 : /// Listeners are only notified if the set changes.
15 : ///
16 : /// Returns `true` if [value] (or an equal value) was not yet in the set.
17 : /// Otherwise returns `false` and the set is not changed
18 1 : @override
19 : bool add(T value) {
20 1 : assert(_debugAssertNotDisposed());
21 2 : final result = _set.add(value);
22 :
23 : // Only notify if things actually changed
24 : if (result) {
25 1 : notifyListeners();
26 : }
27 :
28 : return result;
29 : }
30 :
31 : /// Adds all [elements] to this set.
32 : /// Listeners are notified after all values have been added.
33 : ///
34 : /// Equivalent to adding each element in [elements] using [add].
35 1 : @override
36 : void addAll(Iterable<T> elements) {
37 1 : assert(_debugAssertNotDisposed());
38 1 : assert(elements != null);
39 2 : _set.addAll(elements);
40 1 : notifyListeners();
41 : }
42 :
43 : /// Returns `true` if [value] is in the set.
44 1 : @override
45 : bool contains(Object element) {
46 1 : assert(_debugAssertNotDisposed());
47 2 : return _set.contains(element);
48 : }
49 :
50 : /// Provides an iterator that iterates over the elements of this set.
51 1 : @override
52 : Iterator<T> get iterator {
53 1 : assert(_debugAssertNotDisposed());
54 2 : return _set.iterator;
55 : }
56 :
57 1 : @override
58 : int get length {
59 1 : assert(_debugAssertNotDisposed());
60 2 : return _set.length;
61 : }
62 :
63 : /// If an object equal to [element] is in the set, return it.
64 : ///
65 : /// Checks whether [element] is in the set, like [contains], and if so,
66 : /// returns the object in the set, otherwise returns `null`.
67 1 : @override
68 : T lookup(Object element) {
69 1 : assert(_debugAssertNotDisposed());
70 2 : return _set.lookup(element);
71 : }
72 :
73 : /// Removes [value] from the set. Returns `true` if [value] was in the set.
74 : /// Only notifies the listeners if the set was changed.
75 : ///
76 : /// Returns `false` otherwise. The method has no effect if [value] was not
77 : /// in the set.
78 1 : @override
79 : bool remove(Object value) {
80 1 : assert(_debugAssertNotDisposed());
81 2 : final result = _set.remove(value);
82 :
83 : // Only notify if something changed
84 : if (result) {
85 1 : notifyListeners();
86 : }
87 : return result;
88 : }
89 :
90 : /// Removes each element of [elements] from this set.
91 : /// Listeners are notified after all values have been removed.
92 1 : @override
93 : void removeAll(Iterable<Object> elements) {
94 1 : assert(_debugAssertNotDisposed());
95 1 : assert(elements != null);
96 2 : _set.removeAll(elements);
97 1 : notifyListeners();
98 : }
99 :
100 : /// Removes all elements of this set that are not elements in [elements].
101 : /// Listeners are notified after all values have been removed.
102 : ///
103 : /// Checks for each element of [elements] whether there is an element in this
104 : /// set that is equal to it (according to `this.contains`), and if so, the
105 : /// equal element in this set is retained, and elements that are not equal to
106 : /// any elements in [elements] are removed.
107 1 : @override
108 : void retainAll(Iterable<Object> elements) {
109 1 : assert(_debugAssertNotDisposed());
110 1 : assert(elements != null);
111 2 : _set.retainAll(elements);
112 1 : notifyListeners();
113 : }
114 :
115 : /// Removes all elements of this set that satisfy [test]
116 : /// Listeners are notified after all values have been removed.
117 1 : @override
118 : void removeWhere(bool Function(T element) test) {
119 1 : assert(_debugAssertNotDisposed());
120 1 : assert(test != null);
121 2 : _set.removeWhere(test);
122 1 : notifyListeners();
123 : }
124 :
125 : /// Removes all elements of this set that fail to satisfy [test]
126 : /// Listeners are notified after all values have been removed.
127 1 : @override
128 : void retainWhere(bool Function(T element) test) {
129 1 : assert(_debugAssertNotDisposed());
130 1 : assert(test != null);
131 2 : _set.retainWhere(test);
132 1 : notifyListeners();
133 : }
134 :
135 : /// Removes all elements in the set.
136 : /// Listeners are notified after all valuse have been removed.
137 1 : @override
138 : void clear() {
139 1 : assert(_debugAssertNotDisposed());
140 2 : _set.clear();
141 1 : notifyListeners();
142 : }
143 :
144 : /// Creates a [Set] with the same elements as this `Set`.
145 1 : @override
146 : Set<T> toSet() {
147 1 : assert(_debugAssertNotDisposed());
148 2 : return _set.toSet();
149 : }
150 :
151 : /// Discards the internal resources used by the object.
152 : /// After this is called, the object is not in a usable state and should be discarded.
153 : ///
154 : /// This method should only be called by the object's owner.
155 2 : @override
156 : @mustCallSuper
157 : void dispose() {
158 2 : assert(_debugAssertNotDisposed());
159 2 : _set = null;
160 2 : super.dispose();
161 : }
162 :
163 : /// Reimplemented from [ChangeNotifier]
164 2 : bool _debugAssertNotDisposed() {
165 2 : assert(() {
166 2 : if (_set == null) {
167 3 : throw FlutterError('A $runtimeType was used after being disposed\n'
168 1 : 'Once you have called dispose() on a $runtimeType it can no longer by used.');
169 : }
170 : return true;
171 2 : }());
172 : return true;
173 : }
174 : }
|