rendering_tester.dart 3.51 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'package:flutter/foundation.dart';
Ian Hickson's avatar
Ian Hickson committed
6
import 'package:flutter/gestures.dart';
7
import 'package:flutter/rendering.dart';
Ian Hickson's avatar
Ian Hickson committed
8 9
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
10

11 12
enum EnginePhase {
  layout,
13
  compositingBits,
14
  paint,
15
  composite,
16
  flushSemantics
17 18
}

19
class TestRenderingFlutterBinding extends BindingBase with SchedulerBinding, ServicesBinding, RendererBinding, GestureBinding {
Ian Hickson's avatar
Ian Hickson committed
20 21
  EnginePhase phase = EnginePhase.composite;

22
  @override
Ian Hickson's avatar
Ian Hickson committed
23
  void beginFrame() {
24
    pipelineOwner.flushLayout();
Ian Hickson's avatar
Ian Hickson committed
25 26
    if (phase == EnginePhase.layout)
      return;
27
    pipelineOwner.flushCompositingBits();
28 29
    if (phase == EnginePhase.compositingBits)
      return;
30
    pipelineOwner.flushPaint();
Ian Hickson's avatar
Ian Hickson committed
31 32
    if (phase == EnginePhase.paint)
      return;
33
    renderView.compositeFrame();
34 35
    if (phase == EnginePhase.composite)
      return;
36 37
    pipelineOwner.flushSemantics();
    assert(phase == EnginePhase.flushSemantics);
Ian Hickson's avatar
Ian Hickson committed
38 39 40 41
  }
}

TestRenderingFlutterBinding _renderer;
42 43 44 45
TestRenderingFlutterBinding get renderer {
  _renderer ??= new TestRenderingFlutterBinding();
  return _renderer;
}
46

47 48
/// Place the box in the render tree, at the given size and with the given
/// alignment on the screen.
49 50 51 52 53 54 55
///
/// If you've updated `box` and want to lay it out again, use [pumpFrame].
///
/// Once a particular [RenderBox] has been passed to [layout], it cannot easily
/// be put in a different place in the tree or passed to [layout] again, because
/// [layout] places the given object into another [RenderBox] which you would
/// need to unparent it from (but that box isn't itself made available).
56 57 58 59 60
void layout(RenderBox box, {
  BoxConstraints constraints,
  FractionalOffset alignment: FractionalOffset.center,
  EnginePhase phase: EnginePhase.layout
}) {
61 62
  assert(box != null); // If you want to just repump the last box, call pumpFrame().
  assert(box.parent == null); // We stick the box in another, so you can't reuse it easily, sorry.
Hixie's avatar
Hixie committed
63

64
  renderer.renderView.child = null;
65 66
  if (constraints != null) {
    box = new RenderPositionedBox(
67
      alignment: alignment,
68 69 70 71 72 73
      child: new RenderConstrainedBox(
        additionalConstraints: constraints,
        child: box
      )
    );
  }
Ian Hickson's avatar
Ian Hickson committed
74
  renderer.renderView.child = box;
Hixie's avatar
Hixie committed
75 76 77 78 79

  pumpFrame(phase: phase);
}

void pumpFrame({ EnginePhase phase: EnginePhase.layout }) {
Ian Hickson's avatar
Ian Hickson committed
80
  assert(renderer != null);
81 82
  assert(renderer.renderView != null);
  assert(renderer.renderView.child != null); // call layout() first!
Ian Hickson's avatar
Ian Hickson committed
83 84
  renderer.phase = phase;
  renderer.beginFrame();
85
}
86 87 88 89 90 91

class TestCallbackPainter extends CustomPainter {
  const TestCallbackPainter({ this.onPaint });

  final VoidCallback onPaint;

92
  @override
93 94 95 96
  void paint(Canvas canvas, Size size) {
    onPaint();
  }

97
  @override
98 99
  bool shouldRepaint(TestCallbackPainter oldPainter) => true;
}
100 101 102 103 104 105 106 107


class RenderSizedBox extends RenderBox {
  RenderSizedBox(this._size);

  final Size _size;

  @override
108
  double computeMinIntrinsicWidth(double height) {
109 110 111 112
    return _size.width;
  }

  @override
113
  double computeMaxIntrinsicWidth(double height) {
114 115 116 117
    return _size.width;
  }

  @override
118
  double computeMinIntrinsicHeight(double width) {
119 120 121 122
    return _size.height;
  }

  @override
123
  double computeMaxIntrinsicHeight(double width) {
124 125 126 127 128 129 130 131
    return _size.height;
  }

  @override
  bool get sizedByParent => true;

  @override
  void performResize() {
132 133
    size = constraints.constrain(_size);
  }
134 135 136

  @override
  void performLayout() { }
137
}