Unverified Commit 96233db9 authored by Andre's avatar Andre Committed by GitHub

Make CustomClipper extend Listenable (#55995)

parent 41540110
......@@ -1099,7 +1099,7 @@ class RenderBackdropFilter extends RenderProxyBox {
/// * [ClipOval], which can be customized with a [CustomClipper<Rect>].
/// * [ClipPath], which can be customized with a [CustomClipper<Path>].
/// * [ShapeBorderClipper], for specifying a clip path using a [ShapeBorder].
abstract class CustomClipper<T> {
abstract class CustomClipper<T> extends Listenable {
/// Creates a custom clipper.
///
/// The clipper will update its clip whenever [reclip] notifies its listeners.
......@@ -1107,6 +1107,23 @@ abstract class CustomClipper<T> {
final Listenable _reclip;
/// Register a closure to be notified when it is time to reclip.
///
/// The [CustomClipper] implementation merely forwards to the same method on
/// the [Listenable] provided to the constructor in the `reclip` argument, if
/// it was not null.
@override
void addListener(VoidCallback listener) => _reclip?.addListener(listener);
/// Remove a previously registered closure from the list of closures that the
/// object notifies when it is time to reclip.
///
/// The [CustomClipper] implementation merely forwards to the same method on
/// the [Listenable] provided to the constructor in the `reclip` argument, if
/// it was not null.
@override
void removeListener(VoidCallback listener) => _reclip?.removeListener(listener);
/// Returns a description of the clip given that the render object being
/// clipped is of the given size.
T getClip(Size size);
......@@ -1207,20 +1224,20 @@ abstract class _RenderCustomClip<T> extends RenderProxyBox {
_markNeedsClip();
}
if (attached) {
oldClipper?._reclip?.removeListener(_markNeedsClip);
newClipper?._reclip?.addListener(_markNeedsClip);
oldClipper?.removeListener(_markNeedsClip);
newClipper?.addListener(_markNeedsClip);
}
}
@override
void attach(PipelineOwner owner) {
super.attach(owner);
_clipper?._reclip?.addListener(_markNeedsClip);
_clipper?.addListener(_markNeedsClip);
}
@override
void detach() {
_clipper?._reclip?.removeListener(_markNeedsClip);
_clipper?.removeListener(_markNeedsClip);
super.detach();
}
......
......@@ -40,6 +40,18 @@ class ValueClipper<T> extends CustomClipper<T> {
}
}
class NotifyClipper<T> extends CustomClipper<T> {
NotifyClipper({this.clip}) : super(reclip: clip);
final ValueNotifier<T> clip;
@override
T getClip(Size size) => clip.value;
@override
bool shouldReclip(NotifyClipper<T> oldClipper) => clip != oldClipper.clip;
}
class _UpdateCountedClipRect extends ClipRect {
const _UpdateCountedClipRect({Clip clipBehavior = Clip.antiAlias})
: super(clipBehavior: clipBehavior);
......@@ -837,4 +849,37 @@ void main() {
'getOuterPath Rect.fromLTRB(0.0, 0.0, 800.0, 600.0) TextDirection.ltr',
]);
});
testWidgets('CustomClipper reclips when notified', (WidgetTester tester) async {
final ValueNotifier<Rect> clip = ValueNotifier<Rect>(const Rect.fromLTWH(50.0, 50.0, 100.0, 100.0));
await tester.pumpWidget(
ClipRect(
child: const Placeholder(),
clipper: NotifyClipper<Rect>(clip: clip),
),
);
expect(tester.renderObject(find.byType(ClipRect)).paint, paints
..save()
..clipRect(rect: const Rect.fromLTWH(50.0, 50.0, 100.0, 100.0))
..save()
..path() // Placeholder
..restore()
..restore(),
);
expect(tester.renderObject(find.byType(ClipRect)).debugNeedsPaint, isFalse);
clip.value = const Rect.fromLTWH(50.0, 50.0, 150.0, 100.0);
expect(tester.renderObject(find.byType(ClipRect)).debugNeedsPaint, isTrue);
expect(tester.renderObject(find.byType(ClipRect)).paint, paints
..save()
..clipRect(rect: const Rect.fromLTWH(50.0, 50.0, 150.0, 100.0))
..save()
..path() // Placeholder
..restore()
..restore(),
);
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment