|
| 1 | +import 'package:flutter/widgets.dart'; |
| 2 | +import 'package:flutter_policy_engine/src/core/policy_manager.dart'; |
| 3 | + |
| 4 | +/// A widget that provides a [PolicyManager] instance to its descendant widgets. |
| 5 | +/// |
| 6 | +/// This widget uses Flutter's [InheritedWidget] pattern to make the [PolicyManager] |
| 7 | +/// available throughout the widget tree without having to pass it explicitly |
| 8 | +/// through constructors. |
| 9 | +/// |
| 10 | +/// Example usage: |
| 11 | +/// ```dart |
| 12 | +/// PolicyProvider( |
| 13 | +/// policyManager: myPolicyManager, |
| 14 | +/// child: MyApp(), |
| 15 | +/// ) |
| 16 | +/// ``` |
| 17 | +/// |
| 18 | +/// To access the [PolicyManager] in descendant widgets: |
| 19 | +/// ```dart |
| 20 | +/// final policyManager = PolicyProvider.policyManagerOf(context); |
| 21 | +/// ``` |
| 22 | +class PolicyProvider extends InheritedWidget { |
| 23 | + /// Creates a [PolicyProvider] widget. |
| 24 | + /// |
| 25 | + /// The [policyManager] parameter is required and will be made available |
| 26 | + /// to all descendant widgets in the widget tree. |
| 27 | + /// |
| 28 | + /// The [child] parameter is required and represents the widget subtree |
| 29 | + /// that will have access to the provided [PolicyManager]. |
| 30 | + const PolicyProvider({ |
| 31 | + required this.policyManager, |
| 32 | + required super.child, |
| 33 | + super.key, |
| 34 | + }); |
| 35 | + |
| 36 | + /// The [PolicyManager] instance that will be provided to descendant widgets. |
| 37 | + final PolicyManager policyManager; |
| 38 | + |
| 39 | + /// Returns the nearest [PolicyProvider] widget in the widget tree. |
| 40 | + /// |
| 41 | + /// This method uses [BuildContext.dependOnInheritedWidgetOfExactType] to |
| 42 | + /// establish a dependency on the [PolicyProvider] widget, which means |
| 43 | + /// the calling widget will rebuild when the [PolicyProvider] changes. |
| 44 | + /// |
| 45 | + /// Returns `null` if no [PolicyProvider] is found in the widget tree. |
| 46 | + /// |
| 47 | + /// Example: |
| 48 | + /// ```dart |
| 49 | + /// final provider = PolicyProvider.of(context); |
| 50 | + /// if (provider != null) { |
| 51 | + /// // Use provider.policyManager |
| 52 | + /// } |
| 53 | + /// ``` |
| 54 | + static PolicyProvider? of(BuildContext context) { |
| 55 | + return context.dependOnInheritedWidgetOfExactType<PolicyProvider>(); |
| 56 | + } |
| 57 | + |
| 58 | + /// Returns the [PolicyManager] from the nearest [PolicyProvider] widget. |
| 59 | + /// |
| 60 | + /// This is a convenience method that combines finding the [PolicyProvider] |
| 61 | + /// and accessing its [policyManager] property. It throws a [StateError] |
| 62 | + /// if no [PolicyProvider] is found in the widget tree. |
| 63 | + /// |
| 64 | + /// This method establishes a dependency on the [PolicyProvider] widget, |
| 65 | + /// causing the calling widget to rebuild when the provider changes. |
| 66 | + /// |
| 67 | + /// Throws: |
| 68 | + /// - [StateError] if no [PolicyProvider] is found in the widget tree. |
| 69 | + /// |
| 70 | + /// Example: |
| 71 | + /// ```dart |
| 72 | + /// final policyManager = PolicyProvider.policyManagerOf(context); |
| 73 | + /// // Use policyManager directly |
| 74 | + /// ``` |
| 75 | + static PolicyManager policyManagerOf(BuildContext context) { |
| 76 | + final provider = of(context); |
| 77 | + if (provider == null) { |
| 78 | + throw StateError('PolicyProvider not found in context'); |
| 79 | + } |
| 80 | + return provider.policyManager; |
| 81 | + } |
| 82 | + |
| 83 | + /// Determines whether this widget should notify its dependents of changes. |
| 84 | + /// |
| 85 | + /// Returns `true` if the [policyManager] has changed, indicating that |
| 86 | + /// dependent widgets should rebuild. This ensures that widgets using |
| 87 | + /// the [PolicyManager] are updated when the manager instance changes. |
| 88 | + /// |
| 89 | + /// The comparison is done by reference equality, so a new [PolicyManager] |
| 90 | + /// instance will trigger a rebuild even if it has the same configuration. |
| 91 | + @override |
| 92 | + bool updateShouldNotify(PolicyProvider oldWidget) { |
| 93 | + return policyManager != oldWidget.policyManager; |
| 94 | + } |
| 95 | +} |
0 commit comments