list.dart 4.73 KB
Newer Older
Adam Barth's avatar
Adam Barth 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 6
import 'dart:math' as math;

Adam Barth's avatar
Adam Barth committed
7 8 9 10 11 12 13
import 'box.dart';
import 'object.dart';
import 'viewport.dart';

/// Parent data for use with [RenderList].
class ListParentData extends ContainerBoxParentDataMixin<RenderBox> { }

14
class RenderList extends RenderVirtualViewport<ListParentData> {
Adam Barth's avatar
Adam Barth committed
15 16 17
  RenderList({
    List<RenderBox> children,
    double itemExtent,
18
    EdgeInsets padding,
Adam Barth's avatar
Adam Barth committed
19 20
    int virtualChildCount,
    Offset paintOffset: Offset.zero,
21
    Axis mainAxis: Axis.vertical,
22
    ViewportAnchor anchor: ViewportAnchor.start,
23
    RenderObjectPainter overlayPainter,
Adam Barth's avatar
Adam Barth committed
24
    LayoutCallback callback
25 26 27 28 29
  }) : _itemExtent = itemExtent,
       _padding = padding,
       super(
         virtualChildCount: virtualChildCount,
         paintOffset: paintOffset,
30
         mainAxis: mainAxis,
31
         anchor: anchor,
32
         overlayPainter: overlayPainter,
33 34
         callback: callback
       ) {
Adam Barth's avatar
Adam Barth committed
35 36 37 38 39 40 41 42 43 44 45 46 47
    addAll(children);
  }

  double get itemExtent => _itemExtent;
  double _itemExtent;
  void set itemExtent (double newValue) {
    assert(newValue != null);
    if (_itemExtent == newValue)
      return;
    _itemExtent = newValue;
    markNeedsLayout();
  }

48 49 50
  EdgeInsets get padding => _padding;
  EdgeInsets _padding;
  void set padding (EdgeInsets newValue) {
51 52 53 54 55 56
    if (_padding == newValue)
      return;
    _padding = newValue;
    markNeedsLayout();
  }

57
  @override
Adam Barth's avatar
Adam Barth committed
58 59 60 61 62
  void setupParentData(RenderBox child) {
    if (child.parentData is! ListParentData)
      child.parentData = new ListParentData();
  }

63
  double get _scrollAxisPadding {
64
    switch (mainAxis) {
65
      case Axis.vertical:
66
        return padding.vertical;
67
      case Axis.horizontal:
68 69 70
        return padding.horizontal;
    }
  }
Adam Barth's avatar
Adam Barth committed
71

72
  double get _preferredExtent {
73 74
    if (itemExtent == null)
      return double.INFINITY;
75 76 77 78
    int count = virtualChildCount;
    if (count == null)
      return double.INFINITY;
    double extent = itemExtent * count;
79 80 81 82 83 84
    if (padding != null)
      extent += _scrollAxisPadding;
    return extent;
  }

  double _getIntrinsicWidth(BoxConstraints constraints) {
Hixie's avatar
Hixie committed
85
    assert(constraints.debugAssertIsNormalized);
86
    switch (mainAxis) {
87
      case Axis.vertical:
88
        return constraints.constrainWidth(0.0);
89
      case Axis.horizontal:
90 91 92 93
        return constraints.constrainWidth(_preferredExtent);
    }
  }

94
  @override
95 96
  double getMinIntrinsicWidth(BoxConstraints constraints) {
    return _getIntrinsicWidth(constraints);
Adam Barth's avatar
Adam Barth committed
97 98
  }

99
  @override
Adam Barth's avatar
Adam Barth committed
100
  double getMaxIntrinsicWidth(BoxConstraints constraints) {
101 102 103 104
    return _getIntrinsicWidth(constraints);
  }

  double _getIntrinsicHeight(BoxConstraints constraints) {
Hixie's avatar
Hixie committed
105
    assert(constraints.debugAssertIsNormalized);
106
    switch (mainAxis) {
107
      case Axis.vertical:
108
        return constraints.constrainHeight(_preferredExtent);
109
      case Axis.horizontal:
110 111
        return constraints.constrainHeight(0.0);
    }
Adam Barth's avatar
Adam Barth committed
112 113
  }

114
  @override
Adam Barth's avatar
Adam Barth committed
115
  double getMinIntrinsicHeight(BoxConstraints constraints) {
116
    return _getIntrinsicHeight(constraints);
Adam Barth's avatar
Adam Barth committed
117 118
  }

119
  @override
Adam Barth's avatar
Adam Barth committed
120
  double getMaxIntrinsicHeight(BoxConstraints constraints) {
121
    return _getIntrinsicHeight(constraints);
Adam Barth's avatar
Adam Barth committed
122 123
  }

124
  @override
Adam Barth's avatar
Adam Barth committed
125
  void performLayout() {
126
    switch (mainAxis) {
127
      case Axis.vertical:
128 129 130
        size = new Size(constraints.maxWidth,
                        constraints.constrainHeight(_preferredExtent));
        break;
131
      case Axis.horizontal:
132 133 134 135
        size = new Size(constraints.constrainWidth(_preferredExtent),
                        constraints.maxHeight);
        break;
    }
Adam Barth's avatar
Adam Barth committed
136 137 138 139

    if (callback != null)
      invokeLayoutCallback(callback);

140 141 142 143 144 145 146 147 148
    double itemWidth;
    double itemHeight;

    double x = 0.0;
    double dx = 0.0;

    double y = 0.0;
    double dy = 0.0;

149
    switch (mainAxis) {
150
      case Axis.vertical:
151
        itemWidth = math.max(0.0, size.width - (padding == null ? 0.0 : padding.horizontal));
152
        itemHeight = itemExtent ?? size.height;
153
        x = padding != null ? padding.left : 0.0;
154
        dy = itemHeight;
155
        break;
156
      case Axis.horizontal:
157
        itemWidth = itemExtent ?? size.width;
158
        itemHeight = math.max(0.0, size.height - (padding == null ? 0.0 : padding.vertical));
159
        y = padding != null ? padding.top : 0.0;
160
        dx = itemWidth;
161 162 163
        break;
    }

Adam Barth's avatar
Adam Barth committed
164
    BoxConstraints innerConstraints =
165
        new BoxConstraints.tightFor(width: itemWidth, height: itemHeight);
Adam Barth's avatar
Adam Barth committed
166 167 168 169

    RenderBox child = firstChild;
    while (child != null) {
      child.layout(innerConstraints);
170

Adam Barth's avatar
Adam Barth committed
171
      final ListParentData childParentData = child.parentData;
172 173 174 175
      childParentData.offset = new Offset(x, y);
      x += dx;
      y += dy;

Adam Barth's avatar
Adam Barth committed
176 177 178 179 180
      assert(child.parentData == childParentData);
      child = childParentData.nextSibling;
    }
  }
}