viewport.dart 3.65 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
// 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.

import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';

import 'framework.dart';

export 'package:flutter/rendering.dart' show
  AxisDirection,
  GrowthDirection;

Adam Barth's avatar
Adam Barth committed
14 15
class Viewport extends MultiChildRenderObjectWidget {
  Viewport({
16 17 18
    Key key,
    this.axisDirection: AxisDirection.down,
    this.anchor: 0.0,
Ian Hickson's avatar
Ian Hickson committed
19
    @required this.offset,
20
    this.center,
21 22
    List<Widget> slivers: const <Widget>[],
  }) : super(key: key, children: slivers) {
Ian Hickson's avatar
Ian Hickson committed
23
    assert(offset != null);
24 25 26 27 28 29 30 31 32
    assert(center == null || children.where((Widget child) => child.key == center).length == 1);
  }

  final AxisDirection axisDirection;
  final double anchor;
  final ViewportOffset offset;
  final Key center;

  @override
Adam Barth's avatar
Adam Barth committed
33 34
  RenderViewport createRenderObject(BuildContext context) {
    return new RenderViewport(
35 36 37 38 39 40 41
      axisDirection: axisDirection,
      anchor: anchor,
      offset: offset,
    );
  }

  @override
Adam Barth's avatar
Adam Barth committed
42
  void updateRenderObject(BuildContext context, RenderViewport renderObject) {
43 44 45 46 47 48
    renderObject.axisDirection = axisDirection;
    renderObject.anchor = anchor;
    renderObject.offset = offset;
  }

  @override
Adam Barth's avatar
Adam Barth committed
49
  ViewportElement createElement() => new ViewportElement(this);
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

  @override
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    description.add('$axisDirection');
    description.add('anchor: $anchor');
    description.add('offset: $offset');
    if (center != null) {
      description.add('center: $center');
    } else if (children.isNotEmpty && children.first.key != null) {
      description.add('center: ${children.first.key} (implicit)');
    }
  }
}

Adam Barth's avatar
Adam Barth committed
65
class ViewportElement extends MultiChildRenderObjectElement {
66
  /// Creates an element that uses the given widget as its configuration.
Adam Barth's avatar
Adam Barth committed
67
  ViewportElement(Viewport widget) : super(widget);
68 69

  @override
Adam Barth's avatar
Adam Barth committed
70
  Viewport get widget => super.widget;
71 72

  @override
Adam Barth's avatar
Adam Barth committed
73
  RenderViewport get renderObject => super.renderObject;
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

  @override
  void mount(Element parent, dynamic newSlot) {
    super.mount(parent, newSlot);
    updateCenter();
  }

  @override
  void update(MultiChildRenderObjectWidget newWidget) {
    super.update(newWidget);
    updateCenter();
  }

  @protected
  void updateCenter() {
    // TODO(ianh): cache the keys to make this faster
    if (widget.center != null) {
      renderObject.center = children.singleWhere(
        (Element element) => element.widget.key == widget.center
      ).renderObject;
    } else if (children.isNotEmpty) {
      renderObject.center = children.first.renderObject;
    } else {
      renderObject.center = null;
    }
  }
}
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136

class ShrinkWrappingViewport extends MultiChildRenderObjectWidget {
  ShrinkWrappingViewport({
    Key key,
    this.axisDirection: AxisDirection.down,
    @required this.offset,
    List<Widget> slivers: const <Widget>[],
  }) : super(key: key, children: slivers) {
    assert(offset != null);
  }

  final AxisDirection axisDirection;
  final ViewportOffset offset;

  @override
  RenderShrinkWrappingViewport createRenderObject(BuildContext context) {
    return new RenderShrinkWrappingViewport(
      axisDirection: axisDirection,
      offset: offset,
    );
  }

  @override
  void updateRenderObject(BuildContext context, RenderShrinkWrappingViewport renderObject) {
    renderObject
      ..axisDirection = axisDirection
      ..offset = offset;
  }

  @override
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    description.add('$axisDirection');
    description.add('offset: $offset');
  }
}