LCOV - code coverage report
Current view: top level - src - property_change_provider.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 37 37 100.0 %
Date: 2019-09-01 16:02:36 Functions: 0 0 -

          Line data    Source code
       1             : import 'package:flutter/widgets.dart';
       2             : import 'package:property_change_notifier/property_change_notifier.dart';
       3             : 
       4             : /// An [InheritedWidget] that provides access to a [PropertyChangeNotifier] to descendant widgets.
       5             : /// The type parameter [T] is the type of the [PropertyChangeNotifier] subclass.
       6             : ///
       7             : /// A descendant widget can access the model instance by using the following syntax.
       8             : /// This will automatically register the widget to be rebuilt whenever any property changes on the model:
       9             : /// ```dart
      10             : /// final model = PropertyChangeProvider.of<MyModel>(context).value;
      11             : /// ```
      12             : ///
      13             : /// To access the property name that was changed, use the following syntax:
      14             : /// ```dart
      15             : /// final property = PropertyChangeProvider.of<MyModel>(context).property;
      16             : /// ```
      17             : ///
      18             : /// To register the widget to be rebuilt only on specific property changes, provide a [properties] parameter:
      19             : /// ```dart
      20             : /// final model = PropertyChangeProvider.of<MyModel>(context, properties: ['foo', 'bar']).value;
      21             : /// ```
      22             : ///
      23             : /// To access the model without registering the widget to be rebuilt, provide a [listen] parameter with a value of false:
      24             : /// ```dart
      25             : /// final model = PropertyChangeProvider.of<MyModel>(context, listen: false).value;
      26             : /// ```
      27             : class PropertyChangeProvider<T extends PropertyChangeNotifier> extends StatefulWidget {
      28             :   /// Retrieves the [PropertyChangeModel] from the nearest ancestor [PropertyChangeProvider].
      29             :   /// If [listen] is true (which is the default), the calling widget will also be rebuilt
      30             :   /// whenever the ancestor's [PropertyChangeNotifier] model changes. To only rebuild
      31             :   /// for certain properties, provide them in the [properties] parameter.
      32             :   /// If [listen] is false, the [properties] parameter must be null or empty.
      33           2 :   static PropertyChangeModel<T> of<T extends PropertyChangeNotifier>(
      34             :     BuildContext context, {
      35             :     Iterable<Object> properties,
      36             :     bool listen = true,
      37             :   }) {
      38           1 :     assert(listen || properties == null, "Don't provide properties if you're not going to listen to them.");
      39             : 
      40           1 :     final typeOf = <T>() => T;
      41             : 
      42           2 :     final nullCheck = (InheritedModel model) {
      43           4 :       assert(model != null, 'Could not find an ancestor PropertyChangeProvider<$T>');
      44             :       return model;
      45             :     };
      46             : 
      47             :     if (!listen) {
      48           1 :       final type = typeOf<PropertyChangeModel<T>>();
      49           2 :       return nullCheck(context.ancestorWidgetOfExactType(type) as PropertyChangeModel);
      50             :     }
      51             : 
      52           2 :     if (properties == null || properties.isEmpty) {
      53           4 :       return nullCheck(InheritedModel.inheritFrom<PropertyChangeModel<T>>(context));
      54             :     }
      55             : 
      56             :     InheritedModel widget;
      57           4 :     for (final property in properties) {
      58           2 :       widget = InheritedModel.inheritFrom<PropertyChangeModel<T>>(context, aspect: property);
      59             :     }
      60             : 
      61           2 :     return nullCheck(widget);
      62             :   }
      63             : 
      64             :   /// Creates a [PropertyChangeProvider] that can be accessed by descendant widgets.
      65           2 :   PropertyChangeProvider({
      66             :     Key key,
      67             :     @required this.value,
      68             :     @required this.child,
      69           1 :   })  : assert(value != null),
      70           1 :         assert(child != null),
      71           2 :         super(key: key);
      72             : 
      73             :   /// The instance of [T] to provide to descendant widgets.
      74             :   final T value;
      75             : 
      76             :   /// The widget below this widget in the tree.
      77             :   ///
      78             :   /// {@macro flutter.widgets.child}
      79             :   final Widget child;
      80             : 
      81           2 :   @override
      82           2 :   _PropertyChangeProviderState createState() => _PropertyChangeProviderState<T>();
      83             : }
      84             : 
      85             : /// The companion [State] object to [PropertyChangeProvider]. For private use only.
      86             : /// Subscribes as a global listener to the [PropertyChangeNotifier] instance at [widget].[value].
      87             : /// Rebuilds whenever a property is changed and creates a new [PropertyChangeModel] with a reference
      88             : /// to itself so it can access the original model instance and newly changed property name.
      89             : class _PropertyChangeProviderState<T extends PropertyChangeNotifier> extends State<PropertyChangeProvider<T>> {
      90             :   Object _property;
      91             : 
      92           2 :   @override
      93             :   void initState() {
      94           2 :     super.initState();
      95           8 :     widget.value.addListener(_listener);
      96             :   }
      97             : 
      98           2 :   @override
      99             :   void dispose() {
     100           8 :     widget.value.removeListener(_listener);
     101           2 :     super.dispose();
     102             :   }
     103             : 
     104           2 :   @override
     105             :   Widget build(BuildContext context) {
     106           2 :     return PropertyChangeModel<T>(
     107             :       state: this,
     108           4 :       child: widget.child,
     109             :     );
     110             :   }
     111             : 
     112           2 :   void _listener(Object property) {
     113           4 :     setState(() {
     114           2 :       _property = property;
     115             :     });
     116             :   }
     117             : }
     118             : 
     119             : /// The [InheritedModel] subclass that is rebuilt by [_PropertyChangeProviderState]
     120             : /// whenever its [PropertyChangeNotifier] is updated. Notifies dependents when the
     121             : /// name of the changed property is contained in the list of properties provided
     122             : /// when the widgets originally called the [PropertyChangeProvider].[of] method.
     123             : /// The type parameter [T] is the type of the [PropertyChangeNotifier] subclass.
     124             : class PropertyChangeModel<T extends PropertyChangeNotifier> extends InheritedModel {
     125             :   final _PropertyChangeProviderState _state;
     126             : 
     127           2 :   PropertyChangeModel({
     128             :     Key key,
     129             :     _PropertyChangeProviderState state,
     130             :     Widget child,
     131             :   })  : _state = state,
     132           2 :         super(key: key, child: child);
     133             : 
     134             :   /// The instance of [T] originally provided to the [PropertyChangeProvider] constructor.
     135           8 :   T get value => _state.widget.value;
     136             : 
     137             :   /// The name of the property that was last changed on the [value] instance.
     138           6 :   Object get property => _state._property;
     139             : 
     140           2 :   @override
     141             :   bool updateShouldNotify(PropertyChangeModel oldWidget) {
     142             :     return true;
     143             :   }
     144             : 
     145           2 :   @override
     146             :   bool updateShouldNotifyDependent(PropertyChangeModel<T> oldWidget, Set<Object> aspects) {
     147           6 :     return aspects.contains(_state._property);
     148             :   }
     149             : }

Generated by: LCOV version 1.14