1
// Copyright 2020 J-P Nurmi
2
//
3
// ItemSelectionNotifier is based on Flutter's ChangeNotifier:
4
// https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/foundation/change_notifier.dart
5
//
6
// Copyright 2014 The Flutter Authors. All rights reserved.
7
//
8
// Redistribution and use in source and binary forms, with or without modification,
9
// are permitted provided that the following conditions are met:
10
//
11
//     * Redistributions of source code must retain the above copyright
12
//       notice, this list of conditions and the following disclaimer.
13
//     * Redistributions in binary form must reproduce the above
14
//       copyright notice, this list of conditions and the following
15
//       disclaimer in the documentation and/or other materials provided
16
//       with the distribution.
17
//     * Neither the name of Google Inc. nor the names of its
18
//       contributors may be used to endorse or promote products derived
19
//       from this software without specific prior written permission.
20
//
21
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
25
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31

32
import 'dart:collection';
33

34
import 'package:flutter/foundation.dart';
35

36
import 'item_selection_types.dart';
37

38
abstract class ItemSelectionNotifier {
39
  /// Adds a [listener] callback for selection changes at any index.
40 1
  void addListener(ItemSelectionChangeCallback listener) {
41 1
    assert(_debugAssertNotDisposed());
42 1
    _listeners.add(listener);
43
  }
44

45
  /// Removes a [listener] callback for selection changes at any index.
46 1
  void removeListener(ItemSelectionChangeCallback listener) {
47 1
    assert(_debugAssertNotDisposed());
48 1
    _listeners.remove(listener);
49
  }
50

51
  /// Adds a [listener] callback for selection changes at a specific [index] only.
52 1
  void addIndexListener(int index, ItemSelectionChangeCallback listener) {
53 1
    assert(_debugAssertNotDisposed());
54 1
    if (!_indexListeners.containsKey(index)) {
55 1
      _indexListeners[index] = ObserverList<ItemSelectionChangeCallback>();
56
    }
57 1
    _indexListeners[index].add(listener);
58
  }
59

60
  /// Removes a [listener] callback for selection changes at a specific [index] only.
61 1
  void removeIndexListener(int index, ItemSelectionChangeCallback listener) {
62 1
    assert(_debugAssertNotDisposed());
63 1
    if (_indexListeners.containsKey(index)) {
64 1
      _indexListeners[index].remove(listener);
65
    }
66
  }
67

68
  /// Notifies all the registered listeners.
69 1
  @protected
70
  void notifyListeners(int index, bool selected) {
71 1
    assert(_debugAssertNotDisposed());
72 1
    if (_listeners != null) {
73 1
      final allListeners = List<ItemSelectionChangeCallback>.from(
74 1
          [..._listeners, ...?_indexListeners[index]]);
75 1
      for (final listener in allListeners) {
76
        try {
77 1
          listener(index, selected);
78
        } catch (exception, stack) {
79 0
          FlutterError.reportError(
80 0
            FlutterErrorDetails(
81
              exception: exception,
82
              stack: stack,
83
              library: 'item_selector',
84 0
              context: ErrorDescription(
85 0
                  'while dispatching notifications for $runtimeType'),
86
              informationCollector: () sync* {
87
                yield DiagnosticsProperty<ItemSelectionNotifier>(
88
                  'The $runtimeType sending notification was',
89
                  this,
90
                  style: DiagnosticsTreeStyle.errorProperty,
91
                );
92
              },
93
            ),
94
          );
95
        }
96
      }
97
    }
98
  }
99

100
  /// Discards the listener callbacks. After this method is called, the notifier
101
  /// object is no longer in a usable state and should be discarded (calls to
102
  /// [addListener] and [removeListener] will throw after the object is
103
  /// disposed).
104
  ///
105
  /// This method should only be called by the object's owner.
106 1
  @mustCallSuper
107
  void dispose() {
108 1
    assert(_debugAssertNotDisposed());
109 1
    _indexListeners = null;
110 1
    _listeners = null;
111
  }
112

113 1
  bool _debugAssertNotDisposed() {
114 1
    assert(() {
115 1
      if (_listeners == null || _indexListeners == null) {
116 1
        throw FlutterError('A $runtimeType was used after being disposed.\n'
117 1
            'Once you have called dispose() on a $runtimeType, it can no longer be used.');
118
      }
119
      return true;
120 1
    }());
121
    return true;
122
  }
123

124
  ObserverList<ItemSelectionChangeCallback> _listeners =
125
      ObserverList<ItemSelectionChangeCallback>();
126
  HashMap<int, ObserverList<ItemSelectionChangeCallback>> _indexListeners =
127
      HashMap<int, ObserverList<ItemSelectionChangeCallback>>();
128
}

Read our documentation on viewing source code .

Loading