Skip to content

Commit 4cf89cc

Browse files
authored
Remove LiveTestRenderView (flutter#127882)
In the multi view world, `RenderViews` are created by the `View` widget and no longer owned by the binding. Prior to this change, the `LiveTestWidgetsFlutterBinding` owned and managed a special subclass of `RenderView`, the `_LiveTestRenderView`. In the new world, where `RenderView`s can be created anywhere in the widget tree where a `View` widget is used, this setup is no longer feasible. This change removes this special `_LiveTestRenderView` and instead adds debug hocks to `RenderView` to allow the `LiveTestWidgetsFlutterBinding` to draw a debug overlay on top of the content of any `RenderView`.
1 parent 6f8ef1a commit 4cf89cc

File tree

6 files changed

+308
-119
lines changed

6 files changed

+308
-119
lines changed

packages/flutter/lib/src/rendering/view.dart

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ class ViewConfiguration {
3333
final double devicePixelRatio;
3434

3535
/// Creates a transformation matrix that applies the [devicePixelRatio].
36+
///
37+
/// The matrix translates points from the local coordinate system of the
38+
/// app (in logical pixels) to the global coordinate system of the
39+
/// [FlutterView] (in physical pixels).
3640
Matrix4 toMatrix() {
3741
return Matrix4.diagonal3Values(devicePixelRatio, devicePixelRatio, 1.0);
3842
}
@@ -212,6 +216,15 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
212216
if (child != null) {
213217
context.paintChild(child!, offset);
214218
}
219+
assert(() {
220+
final List<DebugPaintCallback> localCallbacks = _debugPaintCallbacks.toList();
221+
for (final DebugPaintCallback paintCallback in localCallbacks) {
222+
if (_debugPaintCallbacks.contains(paintCallback)) {
223+
paintCallback(context, offset, this);
224+
}
225+
}
226+
return true;
227+
}());
215228
}
216229

217230
@override
@@ -381,4 +394,47 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
381394
properties.add(DiagnosticsNode.message('semantics enabled'));
382395
}
383396
}
397+
398+
static final List<DebugPaintCallback> _debugPaintCallbacks = <DebugPaintCallback>[];
399+
400+
/// Registers a [DebugPaintCallback] that is called every time a [RenderView]
401+
/// repaints in debug mode.
402+
///
403+
/// The callback may paint a debug overlay on top of the content of the
404+
/// [RenderView] provided to the callback. Callbacks are invoked in the
405+
/// order they were registered in.
406+
///
407+
/// Neither registering a callback nor the continued presence of a callback
408+
/// changes how often [RenderView]s are repainted. It is up to the owner of
409+
/// the callback to call [markNeedsPaint] on any [RenderView] for which it
410+
/// wants to update the painted overlay.
411+
///
412+
/// Does nothing in release mode.
413+
static void debugAddPaintCallback(DebugPaintCallback callback) {
414+
assert(() {
415+
_debugPaintCallbacks.add(callback);
416+
return true;
417+
}());
418+
}
419+
420+
/// Removes a callback registered with [debugAddPaintCallback].
421+
///
422+
/// It does not schedule a frame to repaint the [RenderView]s without the
423+
/// overlay painted by the removed callback. It is up to the owner of the
424+
/// callback to call [markNeedsPaint] on the relevant [RenderView]s to
425+
/// repaint them without the overlay.
426+
///
427+
/// Does nothing in release mode.
428+
static void debugRemovePaintCallback(DebugPaintCallback callback) {
429+
assert(() {
430+
_debugPaintCallbacks.remove(callback);
431+
return true;
432+
}());
433+
}
384434
}
435+
436+
/// A callback for painting a debug overlay on top of the provided [RenderView].
437+
///
438+
/// Used by [RenderView.debugAddPaintCallback] and
439+
/// [RenderView.debugRemovePaintCallback].
440+
typedef DebugPaintCallback = void Function(PaintingContext context, Offset offset, RenderView renderView);

packages/flutter/test/rendering/view_test.dart

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'package:flutter/rendering.dart';
66
import 'package:flutter_test/flutter_test.dart';
77

8+
import 'mock_canvas.dart';
89
import 'rendering_tester.dart';
910

1011
void main() {
@@ -69,4 +70,76 @@ void main() {
6970
expect(viewConfigurationA.hashCode, viewConfigurationB.hashCode);
7071
expect(viewConfigurationA.hashCode != viewConfigurationC.hashCode, true);
7172
});
73+
74+
test('invokes DebugPaintCallback', () {
75+
final PaintPattern paintsOrangeRect = paints..rect(
76+
color: orange,
77+
rect: orangeRect,
78+
);
79+
final PaintPattern paintsGreenRect = paints..rect(
80+
color: green,
81+
rect: greenRect,
82+
);
83+
final PaintPattern paintOrangeAndGreenRect = paints
84+
..rect(
85+
color: orange,
86+
rect: orangeRect,
87+
)
88+
..rect(
89+
color: green,
90+
rect: greenRect,
91+
);
92+
void paintCallback(PaintingContext context, Offset offset, RenderView renderView) {
93+
context.canvas.drawRect(
94+
greenRect,
95+
Paint()..color = green,
96+
);
97+
}
98+
99+
layout(TestRenderObject());
100+
expect(
101+
TestRenderingFlutterBinding.instance.renderView,
102+
paintsOrangeRect,
103+
);
104+
expect(
105+
TestRenderingFlutterBinding.instance.renderView,
106+
isNot(paintsGreenRect),
107+
);
108+
109+
RenderView.debugAddPaintCallback(paintCallback);
110+
expect(
111+
TestRenderingFlutterBinding.instance.renderView,
112+
paintOrangeAndGreenRect,
113+
);
114+
115+
RenderView.debugRemovePaintCallback(paintCallback);
116+
expect(
117+
TestRenderingFlutterBinding.instance.renderView,
118+
paintsOrangeRect,
119+
);
120+
expect(
121+
TestRenderingFlutterBinding.instance.renderView,
122+
isNot(paintsGreenRect),
123+
);
124+
});
125+
}
126+
127+
const Color orange = Color(0xFFFF9000);
128+
const Color green = Color(0xFF0FF900);
129+
const Rect orangeRect = Rect.fromLTWH(10, 10, 50, 75);
130+
const Rect greenRect = Rect.fromLTWH(20, 20, 100, 150);
131+
132+
class TestRenderObject extends RenderBox {
133+
@override
134+
void performLayout() {
135+
size = constraints.biggest;
136+
}
137+
138+
@override
139+
void paint(PaintingContext context, Offset offset) {
140+
context.canvas.drawRect(
141+
orangeRect,
142+
Paint()..color = orange,
143+
);
144+
}
72145
}

0 commit comments

Comments
 (0)