| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:flutter/foundation.dart'; |
| import 'package:flutter/gestures.dart'; |
| import 'package:flutter/rendering.dart'; |
| import 'package:flutter/widgets.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| import 'package:vector_math/vector_math_64.dart'; |
| |
| import 'rendering_tester.dart'; |
| |
| void main() { |
| test('RenderViewport basic test - no children', () { |
| final RenderViewport root = RenderViewport( |
| crossAxisDirection: AxisDirection.right, |
| offset: ViewportOffset.zero(), |
| ); |
| expect(root, hasAGoodToStringDeep); |
| expect( |
| root.toStringDeep(minLevel: DiagnosticLevel.info), |
| equalsIgnoringHashCodes( |
| 'RenderViewport#00000 NEEDS-LAYOUT NEEDS-PAINT DETACHED\n' |
| ' needs compositing\n' |
| ' parentData: MISSING\n' |
| ' constraints: MISSING\n' |
| ' size: MISSING\n' |
| ' axisDirection: down\n' |
| ' crossAxisDirection: right\n' |
| ' offset: _FixedViewportOffset#00000(offset: 0.0)\n' |
| ' anchor: 0.0\n' |
| ), |
| ); |
| layout(root); |
| root.offset = ViewportOffset.fixed(900.0); |
| expect(root, hasAGoodToStringDeep); |
| expect( |
| root.toStringDeep(minLevel: DiagnosticLevel.info), |
| equalsIgnoringHashCodes( |
| 'RenderViewport#00000 NEEDS-LAYOUT NEEDS-PAINT\n' |
| ' needs compositing\n' |
| ' parentData: <none>\n' |
| ' constraints: BoxConstraints(w=800.0, h=600.0)\n' |
| ' size: Size(800.0, 600.0)\n' |
| ' axisDirection: down\n' |
| ' crossAxisDirection: right\n' |
| ' offset: _FixedViewportOffset#00000(offset: 900.0)\n' |
| ' anchor: 0.0\n', |
| ), |
| ); |
| |
| pumpFrame(); |
| }); |
| |
| test('RenderViewport basic test - down', () { |
| RenderBox a, b, c, d, e; |
| final RenderViewport root = RenderViewport( |
| crossAxisDirection: AxisDirection.right, |
| offset: ViewportOffset.zero(), |
| children: <RenderSliver>[ |
| RenderSliverToBoxAdapter(child: a = RenderSizedBox(const Size(100.0, 400.0))), |
| RenderSliverToBoxAdapter(child: b = RenderSizedBox(const Size(100.0, 400.0))), |
| RenderSliverToBoxAdapter(child: c = RenderSizedBox(const Size(100.0, 400.0))), |
| RenderSliverToBoxAdapter(child: d = RenderSizedBox(const Size(100.0, 400.0))), |
| RenderSliverToBoxAdapter(child: e = RenderSizedBox(const Size(100.0, 400.0))), |
| ], |
| ); |
| expect(root, hasAGoodToStringDeep); |
| layout(root); |
| |
| expect(root.size.width, equals(800.0)); |
| expect(root.size.height, equals(600.0)); |
| |
| expect(root, hasAGoodToStringDeep); |
| expect( |
| root.toStringDeep(minLevel: DiagnosticLevel.info), |
| equalsIgnoringHashCodes( |
| 'RenderViewport#00000 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE\n' |
| ' │ needs compositing\n' |
| ' │ parentData: <none>\n' |
| ' │ constraints: BoxConstraints(w=800.0, h=600.0)\n' |
| ' │ size: Size(800.0, 600.0)\n' |
| ' │ axisDirection: down\n' |
| ' │ crossAxisDirection: right\n' |
| ' │ offset: _FixedViewportOffset#00000(offset: 0.0)\n' |
| ' │ anchor: 0.0\n' |
| ' │\n' |
| ' ├─center child: RenderSliverToBoxAdapter#00000 relayoutBoundary=up1 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE\n' |
| ' │ │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n' |
| ' │ │ constraints: SliverConstraints(AxisDirection.down,\n' |
| ' │ │ GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n' |
| ' │ │ 0.0, remainingPaintExtent: 600.0, crossAxisExtent: 800.0,\n' |
| ' │ │ crossAxisDirection: AxisDirection.right,\n' |
| ' │ │ viewportMainAxisExtent: 600.0, remainingCacheExtent: 850.0,\n' |
| ' │ │ cacheOrigin: 0.0)\n' |
| ' │ │ geometry: SliverGeometry(scrollExtent: 400.0, paintExtent: 400.0,\n' |
| ' │ │ maxPaintExtent: 400.0, cacheExtent: 400.0)\n' |
| ' │ │\n' |
| ' │ └─child: RenderSizedBox#00000 NEEDS-PAINT\n' |
| ' │ parentData: paintOffset=Offset(0.0, -0.0) (can use size)\n' |
| ' │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n' |
| ' │ size: Size(800.0, 400.0)\n' |
| ' │\n' |
| ' ├─child 1: RenderSliverToBoxAdapter#00000 relayoutBoundary=up1 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE\n' |
| ' │ │ parentData: paintOffset=Offset(0.0, 400.0) (can use size)\n' |
| ' │ │ constraints: SliverConstraints(AxisDirection.down,\n' |
| ' │ │ GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n' |
| ' │ │ 0.0, remainingPaintExtent: 200.0, crossAxisExtent: 800.0,\n' |
| ' │ │ crossAxisDirection: AxisDirection.right,\n' |
| ' │ │ viewportMainAxisExtent: 600.0, remainingCacheExtent: 450.0,\n' |
| ' │ │ cacheOrigin: 0.0)\n' |
| ' │ │ geometry: SliverGeometry(scrollExtent: 400.0, paintExtent: 200.0,\n' |
| ' │ │ maxPaintExtent: 400.0, hasVisualOverflow: true, cacheExtent:\n' |
| ' │ │ 400.0)\n' |
| ' │ │\n' |
| ' │ └─child: RenderSizedBox#00000 NEEDS-PAINT\n' |
| ' │ parentData: paintOffset=Offset(0.0, -0.0) (can use size)\n' |
| ' │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n' |
| ' │ size: Size(800.0, 400.0)\n' |
| ' │\n' |
| ' ├─child 2: RenderSliverToBoxAdapter#00000 relayoutBoundary=up1 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE\n' |
| ' │ │ parentData: paintOffset=Offset(0.0, 800.0) (can use size)\n' |
| ' │ │ constraints: SliverConstraints(AxisDirection.down,\n' |
| ' │ │ GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n' |
| ' │ │ 0.0, remainingPaintExtent: 0.0, crossAxisExtent: 800.0,\n' |
| ' │ │ crossAxisDirection: AxisDirection.right,\n' |
| ' │ │ viewportMainAxisExtent: 600.0, remainingCacheExtent: 50.0,\n' |
| ' │ │ cacheOrigin: 0.0)\n' |
| ' │ │ geometry: SliverGeometry(scrollExtent: 400.0, hidden,\n' |
| ' │ │ maxPaintExtent: 400.0, hasVisualOverflow: true, cacheExtent:\n' |
| ' │ │ 50.0)\n' |
| ' │ │\n' |
| ' │ └─child: RenderSizedBox#00000 NEEDS-PAINT\n' |
| ' │ parentData: paintOffset=Offset(0.0, -0.0) (can use size)\n' |
| ' │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n' |
| ' │ size: Size(800.0, 400.0)\n' |
| ' │\n' |
| ' ├─child 3: RenderSliverToBoxAdapter#00000 relayoutBoundary=up1 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE\n' |
| ' │ │ parentData: paintOffset=Offset(0.0, 1200.0) (can use size)\n' |
| ' │ │ constraints: SliverConstraints(AxisDirection.down,\n' |
| ' │ │ GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n' |
| ' │ │ 0.0, remainingPaintExtent: 0.0, crossAxisExtent: 800.0,\n' |
| ' │ │ crossAxisDirection: AxisDirection.right,\n' |
| ' │ │ viewportMainAxisExtent: 600.0, remainingCacheExtent: 0.0,\n' |
| ' │ │ cacheOrigin: 0.0)\n' |
| ' │ │ geometry: SliverGeometry(scrollExtent: 400.0, hidden,\n' |
| ' │ │ maxPaintExtent: 400.0, hasVisualOverflow: true)\n' |
| ' │ │\n' |
| ' │ └─child: RenderSizedBox#00000 NEEDS-PAINT\n' |
| ' │ parentData: paintOffset=Offset(0.0, -0.0) (can use size)\n' |
| ' │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n' |
| ' │ size: Size(800.0, 400.0)\n' |
| ' │\n' |
| ' └─child 4: RenderSliverToBoxAdapter#00000 relayoutBoundary=up1 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE\n' |
| ' │ parentData: paintOffset=Offset(0.0, 1600.0) (can use size)\n' |
| ' │ constraints: SliverConstraints(AxisDirection.down,\n' |
| ' │ GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n' |
| ' │ 0.0, remainingPaintExtent: 0.0, crossAxisExtent: 800.0,\n' |
| ' │ crossAxisDirection: AxisDirection.right,\n' |
| ' │ viewportMainAxisExtent: 600.0, remainingCacheExtent: 0.0,\n' |
| ' │ cacheOrigin: 0.0)\n' |
| ' │ geometry: SliverGeometry(scrollExtent: 400.0, hidden,\n' |
| ' │ maxPaintExtent: 400.0, hasVisualOverflow: true)\n' |
| ' │\n' |
| ' └─child: RenderSizedBox#00000 NEEDS-PAINT\n' |
| ' parentData: paintOffset=Offset(0.0, -0.0) (can use size)\n' |
| ' constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n' |
| ' size: Size(800.0, 400.0)\n' |
| ), |
| ); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 400.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 800.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1200.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1600.0)); |
| |
| expect(a.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 400.0)); |
| expect(b.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 800.0)); |
| expect(c.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 1200.0)); |
| expect(d.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 1600.0)); |
| expect(e.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 2000.0)); |
| |
| root.offset = ViewportOffset.fixed(200.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -200.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 200.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1000.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1400.0)); |
| |
| root.offset = ViewportOffset.fixed(600.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -600.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -200.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 200.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1000.0)); |
| |
| root.offset = ViewportOffset.fixed(900.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -900.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -500.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -100.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 300.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 700.0)); |
| |
| final BoxHitTestResult result = BoxHitTestResult(); |
| root.hitTest(result, position: const Offset(130.0, 150.0)); |
| expect(result.path.first.target, equals(c)); |
| }); |
| |
| test('RenderViewport basic test - up', () { |
| RenderBox a, b, c, d, e; |
| final RenderViewport root = RenderViewport( |
| axisDirection: AxisDirection.up, |
| crossAxisDirection: AxisDirection.right, |
| offset: ViewportOffset.zero(), |
| children: <RenderSliver>[ |
| RenderSliverToBoxAdapter(child: a = RenderSizedBox(const Size(100.0, 400.0))), |
| RenderSliverToBoxAdapter(child: b = RenderSizedBox(const Size(100.0, 400.0))), |
| RenderSliverToBoxAdapter(child: c = RenderSizedBox(const Size(100.0, 400.0))), |
| RenderSliverToBoxAdapter(child: d = RenderSizedBox(const Size(100.0, 400.0))), |
| RenderSliverToBoxAdapter(child: e = RenderSizedBox(const Size(100.0, 400.0))), |
| ], |
| ); |
| layout(root); |
| |
| expect(root.size.width, equals(800.0)); |
| expect(root.size.height, equals(600.0)); |
| |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 200.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -200.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -600.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -1000.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -1400.0)); |
| |
| root.offset = ViewportOffset.fixed(200.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 400.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -800.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -1200.0)); |
| |
| root.offset = ViewportOffset.fixed(600.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 800.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 400.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -800.0)); |
| |
| root.offset = ViewportOffset.fixed(900.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1100.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 700.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 300.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -100.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -500.0)); |
| |
| final BoxHitTestResult result = BoxHitTestResult(); |
| root.hitTest(result, position: const Offset(150.0, 350.0)); |
| expect(result.path.first.target, equals(c)); |
| }); |
| |
| Offset _getPaintOrigin(RenderObject render) { |
| final Vector3 transformed3 = render.getTransformTo(null).perspectiveTransform(Vector3(0.0, 0.0, 0.0)); |
| return Offset(transformed3.x, transformed3.y); |
| } |
| |
| test('RenderViewport basic test - right', () { |
| RenderBox a, b, c, d, e; |
| final RenderViewport root = RenderViewport( |
| axisDirection: AxisDirection.right, |
| crossAxisDirection: AxisDirection.down, |
| offset: ViewportOffset.zero(), |
| children: <RenderSliver>[ |
| RenderSliverToBoxAdapter(child: a = RenderSizedBox(const Size(400.0, 100.0))), |
| RenderSliverToBoxAdapter(child: b = RenderSizedBox(const Size(400.0, 100.0))), |
| RenderSliverToBoxAdapter(child: c = RenderSizedBox(const Size(400.0, 100.0))), |
| RenderSliverToBoxAdapter(child: d = RenderSizedBox(const Size(400.0, 100.0))), |
| RenderSliverToBoxAdapter(child: e = RenderSizedBox(const Size(400.0, 100.0))), |
| ], |
| ); |
| layout(root); |
| |
| expect(root.size.width, equals(800.0)); |
| expect(root.size.height, equals(600.0)); |
| |
| final RenderSliver sliverA = a.parent as RenderSliver; |
| final RenderSliver sliverB = b.parent as RenderSliver; |
| final RenderSliver sliverC = c.parent as RenderSliver; |
| final RenderSliver sliverD = d.parent as RenderSliver; |
| final RenderSliver sliverE = e.parent as RenderSliver; |
| |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(400.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(800.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(1200.0, 0.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(1600.0, 0.0)); |
| |
| expect(_getPaintOrigin(sliverA), const Offset(0.0, 0.0)); |
| expect(_getPaintOrigin(sliverB), const Offset(400.0, 0.0)); |
| expect(_getPaintOrigin(sliverC), const Offset(800.0, 0.0)); |
| expect(_getPaintOrigin(sliverD), const Offset(1200.0, 0.0)); |
| expect(_getPaintOrigin(sliverE), const Offset(1600.0, 0.0)); |
| |
| root.offset = ViewportOffset.fixed(200.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(-200.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(200.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(600.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(1000.0, 0.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(1400.0, 0.0)); |
| |
| expect(_getPaintOrigin(sliverA), const Offset(000.0, 0.0)); |
| expect(_getPaintOrigin(sliverB), const Offset(200.0, 0.0)); |
| expect(_getPaintOrigin(sliverC), const Offset(600.0, 0.0)); |
| expect(_getPaintOrigin(sliverD), const Offset(1000.0, 0.0)); |
| expect(_getPaintOrigin(sliverE), const Offset(1400.0, 0.0)); |
| |
| root.offset = ViewportOffset.fixed(600.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(-600.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(-200.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(200.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(600.0, 0.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(1000.0, 0.0)); |
| |
| expect(_getPaintOrigin(sliverA), const Offset(000.0, 0.0)); |
| expect(_getPaintOrigin(sliverB), const Offset(000.0, 0.0)); |
| expect(_getPaintOrigin(sliverC), const Offset(200.0, 0.0)); |
| expect(_getPaintOrigin(sliverD), const Offset(600.0, 0.0)); |
| expect(_getPaintOrigin(sliverE), const Offset(1000.0, 0.0)); |
| |
| root.offset = ViewportOffset.fixed(900.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(-900.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(-500.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(-100.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(300.0, 0.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(700.0, 0.0)); |
| |
| expect(_getPaintOrigin(sliverA), const Offset(000.0, 0.0)); |
| expect(_getPaintOrigin(sliverB), const Offset(000.0, 0.0)); |
| expect(_getPaintOrigin(sliverC), const Offset(000.0, 0.0)); |
| expect(_getPaintOrigin(sliverD), const Offset(300.0, 0.0)); |
| expect(_getPaintOrigin(sliverE), const Offset(700.0, 0.0)); |
| |
| final BoxHitTestResult result = BoxHitTestResult(); |
| root.hitTest(result, position: const Offset(150.0, 450.0)); |
| expect(result.path.first.target, equals(c)); |
| }); |
| |
| test('RenderViewport basic test - left', () { |
| RenderBox a, b, c, d, e; |
| final RenderViewport root = RenderViewport( |
| axisDirection: AxisDirection.left, |
| crossAxisDirection: AxisDirection.down, |
| offset: ViewportOffset.zero(), |
| children: <RenderSliver>[ |
| RenderSliverToBoxAdapter(child: a = RenderSizedBox(const Size(400.0, 100.0))), |
| RenderSliverToBoxAdapter(child: b = RenderSizedBox(const Size(400.0, 100.0))), |
| RenderSliverToBoxAdapter(child: c = RenderSizedBox(const Size(400.0, 100.0))), |
| RenderSliverToBoxAdapter(child: d = RenderSizedBox(const Size(400.0, 100.0))), |
| RenderSliverToBoxAdapter(child: e = RenderSizedBox(const Size(400.0, 100.0))), |
| ], |
| ); |
| layout(root); |
| |
| expect(root.size.width, equals(800.0)); |
| expect(root.size.height, equals(600.0)); |
| |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(400.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(-400.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(-800.0, 0.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-1200.0, 0.0)); |
| |
| root.offset = ViewportOffset.fixed(200.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(600.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(200.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(-200.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(-600.0, 0.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-1000.0, 0.0)); |
| |
| root.offset = ViewportOffset.fixed(600.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(1000.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(600.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(200.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(-200.0, 0.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-600.0, 0.0)); |
| |
| root.offset = ViewportOffset.fixed(900.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(1300.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(900.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(500.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(100.0, 0.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-300.0, 0.0)); |
| |
| final BoxHitTestResult result = BoxHitTestResult(); |
| root.hitTest(result, position: const Offset(550.0, 150.0)); |
| expect(result.path.first.target, equals(c)); |
| }); |
| |
| // TODO(ianh): test anchor |
| // TODO(ianh): test center |
| // TODO(ianh): test semantics |
| |
| test('RenderShrinkWrappingViewport basic test - no children', () { |
| final RenderShrinkWrappingViewport root = RenderShrinkWrappingViewport( |
| crossAxisDirection: AxisDirection.right, |
| offset: ViewportOffset.zero(), |
| ); |
| expect(root, hasAGoodToStringDeep); |
| layout(root); |
| root.offset = ViewportOffset.fixed(900.0); |
| pumpFrame(); |
| }); |
| |
| test('RenderShrinkWrappingViewport basic test - down', () { |
| RenderBox a, b, c, d, e; |
| final RenderShrinkWrappingViewport root = RenderShrinkWrappingViewport( |
| crossAxisDirection: AxisDirection.right, |
| offset: ViewportOffset.zero(), |
| children: <RenderSliver>[ |
| RenderSliverToBoxAdapter(child: a = RenderSizedBox(const Size(100.0, 400.0))), |
| RenderSliverToBoxAdapter(child: b = RenderSizedBox(const Size(100.0, 400.0))), |
| RenderSliverToBoxAdapter(child: c = RenderSizedBox(const Size(100.0, 400.0))), |
| RenderSliverToBoxAdapter(child: d = RenderSizedBox(const Size(100.0, 400.0))), |
| RenderSliverToBoxAdapter(child: e = RenderSizedBox(const Size(100.0, 400.0))), |
| ], |
| ); |
| layout(root); |
| |
| expect(root.size.width, equals(800.0)); |
| expect(root.size.height, equals(600.0)); |
| |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 400.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 800.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1200.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1600.0)); |
| |
| expect(a.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 400.0)); |
| expect(b.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 800.0)); |
| expect(c.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 1200.0)); |
| expect(d.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 1600.0)); |
| expect(e.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 2000.0)); |
| |
| root.offset = ViewportOffset.fixed(200.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -200.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 200.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1000.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1400.0)); |
| |
| root.offset = ViewportOffset.fixed(600.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -600.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -200.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 200.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1000.0)); |
| |
| root.offset = ViewportOffset.fixed(900.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -900.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -500.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -100.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 300.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 700.0)); |
| |
| final BoxHitTestResult result = BoxHitTestResult(); |
| root.hitTest(result, position: const Offset(130.0, 150.0)); |
| expect(result.path.first.target, equals(c)); |
| }); |
| |
| test('RenderShrinkWrappingViewport basic test - up', () { |
| RenderBox a, b, c, d, e; |
| final RenderShrinkWrappingViewport root = RenderShrinkWrappingViewport( |
| axisDirection: AxisDirection.up, |
| crossAxisDirection: AxisDirection.right, |
| offset: ViewportOffset.zero(), |
| children: <RenderSliver>[ |
| RenderSliverToBoxAdapter(child: a = RenderSizedBox(const Size(100.0, 400.0))), |
| RenderSliverToBoxAdapter(child: b = RenderSizedBox(const Size(100.0, 400.0))), |
| RenderSliverToBoxAdapter(child: c = RenderSizedBox(const Size(100.0, 400.0))), |
| RenderSliverToBoxAdapter(child: d = RenderSizedBox(const Size(100.0, 400.0))), |
| RenderSliverToBoxAdapter(child: e = RenderSizedBox(const Size(100.0, 400.0))), |
| ], |
| ); |
| layout(root); |
| |
| expect(root.size.width, equals(800.0)); |
| expect(root.size.height, equals(600.0)); |
| |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 200.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -200.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -600.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -1000.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -1400.0)); |
| |
| root.offset = ViewportOffset.fixed(200.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 400.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -800.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -1200.0)); |
| |
| root.offset = ViewportOffset.fixed(600.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 800.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 400.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -800.0)); |
| |
| root.offset = ViewportOffset.fixed(900.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1100.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 700.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 300.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -100.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -500.0)); |
| |
| final BoxHitTestResult result = BoxHitTestResult(); |
| root.hitTest(result, position: const Offset(150.0, 350.0)); |
| expect(result.path.first.target, equals(c)); |
| }); |
| |
| test('RenderShrinkWrappingViewport basic test - right', () { |
| RenderBox a, b, c, d, e; |
| final RenderShrinkWrappingViewport root = RenderShrinkWrappingViewport( |
| axisDirection: AxisDirection.right, |
| crossAxisDirection: AxisDirection.down, |
| offset: ViewportOffset.zero(), |
| children: <RenderSliver>[ |
| RenderSliverToBoxAdapter(child: a = RenderSizedBox(const Size(400.0, 100.0))), |
| RenderSliverToBoxAdapter(child: b = RenderSizedBox(const Size(400.0, 100.0))), |
| RenderSliverToBoxAdapter(child: c = RenderSizedBox(const Size(400.0, 100.0))), |
| RenderSliverToBoxAdapter(child: d = RenderSizedBox(const Size(400.0, 100.0))), |
| RenderSliverToBoxAdapter(child: e = RenderSizedBox(const Size(400.0, 100.0))), |
| ], |
| ); |
| layout(root); |
| |
| expect(root.size.width, equals(800.0)); |
| expect(root.size.height, equals(600.0)); |
| |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(400.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(800.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(1200.0, 0.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(1600.0, 0.0)); |
| |
| root.offset = ViewportOffset.fixed(200.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(-200.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(200.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(600.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(1000.0, 0.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(1400.0, 0.0)); |
| |
| root.offset = ViewportOffset.fixed(600.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(-600.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(-200.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(200.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(600.0, 0.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(1000.0, 0.0)); |
| |
| root.offset = ViewportOffset.fixed(900.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(-900.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(-500.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(-100.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(300.0, 0.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(700.0, 0.0)); |
| |
| final BoxHitTestResult result = BoxHitTestResult(); |
| root.hitTest(result, position: const Offset(150.0, 450.0)); |
| expect(result.path.first.target, equals(c)); |
| }); |
| |
| test('RenderShrinkWrappingViewport basic test - left', () { |
| RenderBox a, b, c, d, e; |
| final RenderShrinkWrappingViewport root = RenderShrinkWrappingViewport( |
| axisDirection: AxisDirection.left, |
| crossAxisDirection: AxisDirection.down, |
| offset: ViewportOffset.zero(), |
| children: <RenderSliver>[ |
| RenderSliverToBoxAdapter(child: a = RenderSizedBox(const Size(400.0, 100.0))), |
| RenderSliverToBoxAdapter(child: b = RenderSizedBox(const Size(400.0, 100.0))), |
| RenderSliverToBoxAdapter(child: c = RenderSizedBox(const Size(400.0, 100.0))), |
| RenderSliverToBoxAdapter(child: d = RenderSizedBox(const Size(400.0, 100.0))), |
| RenderSliverToBoxAdapter(child: e = RenderSizedBox(const Size(400.0, 100.0))), |
| ], |
| ); |
| layout(root); |
| |
| expect(root.size.width, equals(800.0)); |
| expect(root.size.height, equals(600.0)); |
| |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(400.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(-400.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(-800.0, 0.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-1200.0, 0.0)); |
| |
| root.offset = ViewportOffset.fixed(200.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(600.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(200.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(-200.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(-600.0, 0.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-1000.0, 0.0)); |
| |
| root.offset = ViewportOffset.fixed(600.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(1000.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(600.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(200.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(-200.0, 0.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-600.0, 0.0)); |
| |
| root.offset = ViewportOffset.fixed(900.0); |
| pumpFrame(); |
| expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(1300.0, 0.0)); |
| expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(900.0, 0.0)); |
| expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(500.0, 0.0)); |
| expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(100.0, 0.0)); |
| expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-300.0, 0.0)); |
| |
| final BoxHitTestResult result = BoxHitTestResult(); |
| root.hitTest(result, position: const Offset(550.0, 150.0)); |
| expect(result.path.first.target, equals(c)); |
| }); |
| |
| test('RenderShrinkWrappingViewport shrinkwrap test - 1 child', () { |
| RenderBox child; |
| final RenderBox root = RenderPositionedBox( |
| child: child = RenderShrinkWrappingViewport( |
| axisDirection: AxisDirection.left, |
| crossAxisDirection: AxisDirection.down, |
| offset: ViewportOffset.fixed(200.0), |
| children: <RenderSliver>[ |
| RenderSliverToBoxAdapter(child: RenderSizedBox(const Size(400.0, 100.0))), |
| ], |
| ), |
| ); |
| layout(root); |
| |
| expect(root.size.width, equals(800.0)); |
| expect(root.size.height, equals(600.0)); |
| expect(child.size.width, equals(400.0)); |
| expect(child.size.height, equals(600.0)); |
| }); |
| |
| test('RenderShrinkWrappingViewport shrinkwrap test - 2 children', () { |
| RenderBox child; |
| final RenderBox root = RenderPositionedBox( |
| child: child = RenderShrinkWrappingViewport( |
| axisDirection: AxisDirection.right, |
| crossAxisDirection: AxisDirection.down, |
| offset: ViewportOffset.fixed(200.0), |
| children: <RenderSliver>[ |
| RenderSliverToBoxAdapter(child: RenderSizedBox(const Size(300.0, 100.0))), |
| RenderSliverToBoxAdapter(child: RenderSizedBox(const Size(150.0, 100.0))), |
| ], |
| ), |
| ); |
| layout(root); |
| |
| expect(root.size.width, equals(800.0)); |
| expect(root.size.height, equals(600.0)); |
| expect(child.size.width, equals(450.0)); |
| expect(child.size.height, equals(600.0)); |
| }); |
| |
| test('SliverGeometry toString', () { |
| expect( |
| const SliverGeometry().toString(), |
| equals('SliverGeometry(scrollExtent: 0.0, hidden, maxPaintExtent: 0.0)'), |
| ); |
| expect( |
| const SliverGeometry( |
| scrollExtent: 100.0, |
| paintExtent: 50.0, |
| layoutExtent: 20.0, |
| visible: true, |
| ).toString(), |
| equals( |
| 'SliverGeometry(scrollExtent: 100.0, paintExtent: 50.0, layoutExtent: 20.0, maxPaintExtent: 0.0, cacheExtent: 20.0)', |
| ), |
| ); |
| expect( |
| const SliverGeometry( |
| scrollExtent: 100.0, |
| paintExtent: 0.0, |
| layoutExtent: 20.0, |
| ).toString(), |
| equals( |
| 'SliverGeometry(scrollExtent: 100.0, hidden, layoutExtent: 20.0, maxPaintExtent: 0.0, cacheExtent: 20.0)', |
| ), |
| ); |
| }); |
| |
| test('Sliver paintBounds and semanticBounds - vertical', () { |
| const double height = 150.0; |
| |
| final RenderSliver sliver = RenderSliverToBoxAdapter( |
| child: RenderSizedBox(const Size(400.0, height)), |
| ); |
| final RenderViewport root = RenderViewport( |
| axisDirection: AxisDirection.down, |
| crossAxisDirection: AxisDirection.right, |
| offset: ViewportOffset.zero(), |
| children: <RenderSliver>[ |
| sliver, |
| ], |
| ); |
| layout(root); |
| |
| final Rect expectedRect = Rect.fromLTWH(0.0, 0.0, root.size.width, height); |
| |
| expect(sliver.paintBounds, expectedRect); |
| expect(sliver.semanticBounds, expectedRect); |
| }); |
| |
| test('Sliver paintBounds and semanticBounds - horizontal', () { |
| const double width = 150.0; |
| |
| final RenderSliver sliver = RenderSliverToBoxAdapter( |
| child: RenderSizedBox(const Size(width, 400.0)), |
| ); |
| final RenderViewport root = RenderViewport( |
| axisDirection: AxisDirection.right, |
| crossAxisDirection: AxisDirection.down, |
| offset: ViewportOffset.zero(), |
| children: <RenderSliver>[ |
| sliver, |
| ], |
| ); |
| layout(root); |
| |
| final Rect expectedRect = Rect.fromLTWH(0.0, 0.0, width, root.size.height); |
| |
| expect(sliver.paintBounds, expectedRect); |
| expect(sliver.semanticBounds, expectedRect); |
| }); |
| |
| test('precedingScrollExtent is 0.0 for first Sliver in list', () { |
| const double viewportWidth = 800.0; |
| final RenderSliver sliver = RenderSliverToBoxAdapter( |
| child: RenderSizedBox(const Size(viewportWidth, 150.0)), |
| ); |
| final RenderViewport root = RenderViewport( |
| axisDirection: AxisDirection.down, |
| crossAxisDirection: AxisDirection.right, |
| offset: ViewportOffset.zero(), |
| children: <RenderSliver>[ |
| sliver, |
| ], |
| ); |
| layout(root); |
| |
| expect(sliver.constraints.precedingScrollExtent, 0.0); |
| }); |
| |
| test('precedingScrollExtent accumulates over multiple Slivers', () { |
| const double viewportWidth = 800.0; |
| final RenderSliver sliver1 = RenderSliverToBoxAdapter( |
| child: RenderSizedBox(const Size(viewportWidth, 150.0)), |
| ); |
| final RenderSliver sliver2 = RenderSliverToBoxAdapter( |
| child: RenderSizedBox(const Size(viewportWidth, 150.0)), |
| ); |
| final RenderSliver sliver3 = RenderSliverToBoxAdapter( |
| child: RenderSizedBox(const Size(viewportWidth, 150.0)), |
| ); |
| final RenderViewport root = RenderViewport( |
| axisDirection: AxisDirection.down, |
| crossAxisDirection: AxisDirection.right, |
| offset: ViewportOffset.zero(), |
| children: <RenderSliver>[ |
| sliver1, |
| sliver2, |
| sliver3, |
| ], |
| ); |
| layout(root); |
| |
| // The 3rd Sliver comes after 300.0px of preceding scroll extent by first 2 Slivers. |
| expect(sliver3.constraints.precedingScrollExtent, 300.0); |
| }); |
| |
| test('precedingScrollExtent is not impacted by scrollOffset', () { |
| const double viewportWidth = 800.0; |
| final RenderSliver sliver1 = RenderSliverToBoxAdapter( |
| child: RenderSizedBox(const Size(viewportWidth, 150.0)), |
| ); |
| final RenderSliver sliver2 = RenderSliverToBoxAdapter( |
| child: RenderSizedBox(const Size(viewportWidth, 150.0)), |
| ); |
| final RenderSliver sliver3 = RenderSliverToBoxAdapter( |
| child: RenderSizedBox(const Size(viewportWidth, 150.0)), |
| ); |
| final RenderViewport root = RenderViewport( |
| axisDirection: AxisDirection.down, |
| crossAxisDirection: AxisDirection.right, |
| offset: ViewportOffset.fixed(100.0), |
| children: <RenderSliver>[ |
| sliver1, |
| sliver2, |
| sliver3, |
| ], |
| ); |
| layout(root); |
| |
| // The 3rd Sliver comes after 300.0px of preceding scroll extent by first 2 Slivers. |
| // In this test a ViewportOffset is applied to simulate a scrollOffset. That |
| // offset is not expected to impact the precedingScrollExtent. |
| expect(sliver3.constraints.precedingScrollExtent, 300.0); |
| }); |
| |
| group('hit testing', () { |
| test('SliverHitTestResult wrapping HitTestResult', () { |
| final HitTestEntry entry1 = HitTestEntry(_DummyHitTestTarget()); |
| final HitTestEntry entry2 = HitTestEntry(_DummyHitTestTarget()); |
| final HitTestEntry entry3 = HitTestEntry(_DummyHitTestTarget()); |
| final Matrix4 transform = Matrix4.translationValues(40.0, 150.0, 0.0); |
| |
| final HitTestResult wrapped = MyHitTestResult() |
| ..publicPushTransform(transform); |
| wrapped.add(entry1); |
| expect(wrapped.path, equals(<HitTestEntry>[entry1])); |
| expect(entry1.transform, transform); |
| |
| final SliverHitTestResult wrapping = SliverHitTestResult.wrap(wrapped); |
| expect(wrapping.path, equals(<HitTestEntry>[entry1])); |
| expect(wrapping.path, same(wrapped.path)); |
| |
| wrapping.add(entry2); |
| expect(wrapping.path, equals(<HitTestEntry>[entry1, entry2])); |
| expect(wrapped.path, equals(<HitTestEntry>[entry1, entry2])); |
| expect(entry2.transform, transform); |
| |
| wrapped.add(entry3); |
| expect(wrapping.path, equals(<HitTestEntry>[entry1, entry2, entry3])); |
| expect(wrapped.path, equals(<HitTestEntry>[entry1, entry2, entry3])); |
| expect(entry3.transform, transform); |
| }); |
| |
| test('addWithAxisOffset', () { |
| final SliverHitTestResult result = SliverHitTestResult(); |
| final List<double> mainAxisPositions = <double>[]; |
| final List<double> crossAxisPositions = <double>[]; |
| const Offset paintOffsetDummy = Offset.zero; |
| |
| bool isHit = result.addWithAxisOffset( |
| paintOffset: paintOffsetDummy, |
| mainAxisOffset: 0.0, |
| crossAxisOffset: 0.0, |
| mainAxisPosition: 0.0, |
| crossAxisPosition: 0.0, |
| hitTest: (SliverHitTestResult result, { double mainAxisPosition, double crossAxisPosition }) { |
| expect(result, isNotNull); |
| mainAxisPositions.add(mainAxisPosition); |
| crossAxisPositions.add(crossAxisPosition); |
| return true; |
| }, |
| ); |
| expect(isHit, isTrue); |
| expect(mainAxisPositions.single, 0.0); |
| expect(crossAxisPositions.single, 0.0); |
| mainAxisPositions.clear(); |
| crossAxisPositions.clear(); |
| |
| isHit = result.addWithAxisOffset( |
| paintOffset: paintOffsetDummy, |
| mainAxisOffset: 5.0, |
| crossAxisOffset: 6.0, |
| mainAxisPosition: 10.0, |
| crossAxisPosition: 20.0, |
| hitTest: (SliverHitTestResult result, { double mainAxisPosition, double crossAxisPosition }) { |
| expect(result, isNotNull); |
| mainAxisPositions.add(mainAxisPosition); |
| crossAxisPositions.add(crossAxisPosition); |
| return false; |
| }, |
| ); |
| expect(isHit, isFalse); |
| expect(mainAxisPositions.single, 10.0 - 5.0); |
| expect(crossAxisPositions.single, 20.0 - 6.0); |
| mainAxisPositions.clear(); |
| crossAxisPositions.clear(); |
| |
| isHit = result.addWithAxisOffset( |
| paintOffset: paintOffsetDummy, |
| mainAxisOffset: -5.0, |
| crossAxisOffset: -6.0, |
| mainAxisPosition: 10.0, |
| crossAxisPosition: 20.0, |
| hitTest: (SliverHitTestResult result, { double mainAxisPosition, double crossAxisPosition }) { |
| expect(result, isNotNull); |
| mainAxisPositions.add(mainAxisPosition); |
| crossAxisPositions.add(crossAxisPosition); |
| return false; |
| }, |
| ); |
| expect(isHit, isFalse); |
| expect(mainAxisPositions.single, 10.0 + 5.0); |
| expect(crossAxisPositions.single, 20.0 + 6.0); |
| mainAxisPositions.clear(); |
| crossAxisPositions.clear(); |
| }); |
| |
| test('addWithAxisOffset with non zero paintOffset', () { |
| final SliverHitTestResult result = SliverHitTestResult(); |
| double recordedMainAxisPosition; |
| double recordedCrossAxisPosition; |
| final HitTestEntry entry = HitTestEntry(_DummyHitTestTarget()); |
| const Offset paintOffset = Offset(7, 11); |
| |
| final bool isHit = result.addWithAxisOffset( |
| paintOffset: paintOffset, |
| mainAxisOffset: 5.0, |
| crossAxisOffset: 6.0, |
| mainAxisPosition: 10.0, |
| crossAxisPosition: 20.0, |
| hitTest: (SliverHitTestResult result, { double mainAxisPosition, double crossAxisPosition }) { |
| expect(result, isNotNull); |
| recordedMainAxisPosition = mainAxisPosition; |
| recordedCrossAxisPosition = crossAxisPosition; |
| result.add(entry); |
| return true; |
| }, |
| ); |
| expect(isHit, isTrue); |
| expect(recordedMainAxisPosition, 10.0 - 5.0); |
| expect(recordedCrossAxisPosition, 20.0 - 6.0); |
| expect( |
| entry.transform..translate(paintOffset.dx, paintOffset.dy), |
| Matrix4.identity(), |
| ); |
| }); |
| }); |
| |
| test('SliverConstraints check for NaN on all double properties', () { |
| const SliverConstraints constraints = SliverConstraints( |
| axisDirection: AxisDirection.down, |
| cacheOrigin: double.nan, |
| crossAxisDirection: AxisDirection.left, |
| crossAxisExtent: double.nan, |
| growthDirection: GrowthDirection.forward, |
| overlap: double.nan, |
| precedingScrollExtent: double.nan, |
| remainingCacheExtent: double.nan, |
| remainingPaintExtent: double.nan, |
| scrollOffset: double.nan, |
| userScrollDirection: ScrollDirection.idle, |
| viewportMainAxisExtent: double.nan, |
| ); |
| bool threw = false; |
| try { |
| constraints.debugAssertIsValid(); |
| } on FlutterError catch (error) { |
| expect( |
| error.message, |
| 'SliverConstraints is not valid:\n' |
| ' The "scrollOffset" is NaN.\n' |
| ' The "overlap" is NaN.\n' |
| ' The "crossAxisExtent" is NaN.\n' |
| ' The "scrollOffset" is NaN, expected greater than or equal to zero.\n' |
| ' The "viewportMainAxisExtent" is NaN, expected greater than or equal to zero.\n' |
| ' The "remainingPaintExtent" is NaN, expected greater than or equal to zero.\n' |
| ' The "remainingCacheExtent" is NaN, expected greater than or equal to zero.\n' |
| ' The "cacheOrigin" is NaN, expected less than or equal to zero.\n' |
| ' The "precedingScrollExtent" is NaN, expected greater than or equal to zero.\n' |
| ' The constraints are not normalized.\n' |
| 'The offending constraints were:\n' |
| ' SliverConstraints(AxisDirection.down, GrowthDirection.forward, ScrollDirection.idle, scrollOffset: NaN, remainingPaintExtent: NaN, overlap: NaN, crossAxisExtent: NaN, crossAxisDirection: AxisDirection.left, viewportMainAxisExtent: NaN, remainingCacheExtent: NaN, cacheOrigin: NaN)', |
| ); |
| threw = true; |
| } |
| expect(threw, true); |
| }); |
| |
| test('SliverConstraints check for sign on relevant double properties', () { |
| const SliverConstraints constraints = SliverConstraints( |
| axisDirection: AxisDirection.down, |
| cacheOrigin: 1.0, |
| crossAxisDirection: AxisDirection.left, |
| crossAxisExtent: 0.0, |
| growthDirection: GrowthDirection.forward, |
| overlap: 0.0, |
| precedingScrollExtent: -1.0, |
| remainingCacheExtent: -1.0, |
| remainingPaintExtent: -1.0, |
| scrollOffset: -1.0, |
| userScrollDirection: ScrollDirection.idle, |
| viewportMainAxisExtent: 0.0, |
| ); |
| bool threw = false; |
| try { |
| constraints.debugAssertIsValid(); |
| } on FlutterError catch (error) { |
| expect( |
| error.message, |
| 'SliverConstraints is not valid:\n' |
| ' The "scrollOffset" is negative.\n' |
| ' The "remainingPaintExtent" is negative.\n' |
| ' The "remainingCacheExtent" is negative.\n' |
| ' The "cacheOrigin" is positive.\n' |
| ' The "precedingScrollExtent" is negative.\n' |
| ' The constraints are not normalized.\n' |
| 'The offending constraints were:\n' |
| ' SliverConstraints(AxisDirection.down, GrowthDirection.forward, ScrollDirection.idle, scrollOffset: -1.0, remainingPaintExtent: -1.0, crossAxisExtent: 0.0, crossAxisDirection: AxisDirection.left, viewportMainAxisExtent: 0.0, remainingCacheExtent: -1.0, cacheOrigin: 1.0)', |
| ); |
| threw = true; |
| } |
| expect(threw, true); |
| }); |
| } |
| |
| class _DummyHitTestTarget implements HitTestTarget { |
| @override |
| void handleEvent(PointerEvent event, HitTestEntry entry) { |
| // Nothing to do. |
| } |
| } |
| |
| class MyHitTestResult extends HitTestResult { |
| void publicPushTransform(Matrix4 transform) => pushTransform(transform); |
| } |