Hixie f2cc43a483 Lots of trivial warning fixes
Add type annotations in many places.
Fix some identifiers to have more lint-satisfying names.
Make all operator==s consistent in style.
Reorder some functions for consistency.
Make ParentData no longer dynamic, and fix all the code around that.
2015-10-12 16:31:20 -07:00

152 lines
5.0 KiB
Dart

// 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 'box.dart';
import 'object.dart';
class _GridMetrics {
// Grid is width-in, height-out. We fill the max width and adjust height
// accordingly.
factory _GridMetrics({ double width, int childCount, double maxChildExtent }) {
assert(width != null);
assert(childCount != null);
assert(maxChildExtent != null);
double childExtent = maxChildExtent;
int childrenPerRow = (width / childExtent).floor();
// If the child extent divides evenly into the width use that, otherwise + 1
if (width / childExtent != childrenPerRow.toDouble()) childrenPerRow += 1;
double totalPadding = 0.0;
if (childrenPerRow * childExtent > width) {
// TODO(eseidel): We should snap to pixel bounderies.
childExtent = width / childrenPerRow;
} else {
totalPadding = width - (childrenPerRow * childExtent);
}
double childPadding = totalPadding / (childrenPerRow + 1.0);
int rowCount = (childCount / childrenPerRow).ceil();
double height = childPadding * (rowCount + 1) + (childExtent * rowCount);
Size childSize = new Size(childExtent, childExtent);
Size size = new Size(width, height);
return new _GridMetrics._(size, childSize, childrenPerRow, childPadding, rowCount);
}
const _GridMetrics._(this.size, this.childSize, this.childrenPerRow, this.childPadding, this.rowCount);
final Size size;
final Size childSize;
final int childrenPerRow; // aka columnCount
final double childPadding;
final int rowCount;
}
/// Parent data for use with [RenderGrid]
class GridParentData extends ContainerBoxParentDataMixin<RenderBox> {}
/// Implements the grid layout algorithm
///
/// In grid layout, children are arranged into rows and collumns in on a two
/// dimensional grid. The grid determines how many children will be placed in
/// each row by making the children as wide as possible while still respecting
/// the given [maxChildExtent].
class RenderGrid extends RenderBox with ContainerRenderObjectMixin<RenderBox, GridParentData>,
RenderBoxContainerDefaultsMixin<RenderBox, GridParentData> {
RenderGrid({ List<RenderBox> children, double maxChildExtent }) {
addAll(children);
_maxChildExtent = maxChildExtent;
}
double _maxChildExtent;
bool _hasVisualOverflow = false;
double get maxChildExtent => _maxChildExtent;
void set maxChildExtent (double value) {
if (_maxChildExtent != value) {
_maxChildExtent = value;
markNeedsLayout();
}
}
void setupParentData(RenderBox child) {
if (child.parentData is! GridParentData)
child.parentData = new GridParentData();
}
double getMinIntrinsicWidth(BoxConstraints constraints) {
// We can render at any width.
return constraints.constrainWidth(0.0);
}
double getMaxIntrinsicWidth(BoxConstraints constraints) {
double maxWidth = childCount * _maxChildExtent;
return constraints.constrainWidth(maxWidth);
}
double getMinIntrinsicHeight(BoxConstraints constraints) {
double desiredHeight = _computeMetrics().size.height;
return constraints.constrainHeight(desiredHeight);
}
double getMaxIntrinsicHeight(BoxConstraints constraints) {
return getMinIntrinsicHeight(constraints);
}
double computeDistanceToActualBaseline(TextBaseline baseline) {
return defaultComputeDistanceToHighestActualBaseline(baseline);
}
_GridMetrics _computeMetrics() {
return new _GridMetrics(
width: constraints.maxWidth,
childCount: childCount,
maxChildExtent: _maxChildExtent
);
}
void performLayout() {
// We could shrink-wrap our contents when infinite, but for now we don't.
assert(constraints.maxWidth < double.INFINITY);
_GridMetrics metrics = _computeMetrics();
size = constraints.constrain(metrics.size);
if (constraints.maxHeight < size.height)
_hasVisualOverflow = true;
int row = 0;
int column = 0;
RenderBox child = firstChild;
while (child != null) {
child.layout(new BoxConstraints.tight(metrics.childSize));
double x = (column + 1) * metrics.childPadding + (column * metrics.childSize.width);
double y = (row + 1) * metrics.childPadding + (row * metrics.childSize.height);
final GridParentData childParentData = child.parentData;
childParentData.position = new Point(x, y);
column += 1;
if (column >= metrics.childrenPerRow) {
row += 1;
column = 0;
}
assert(child.parentData == childParentData);
child = childParentData.nextSibling;
}
}
void hitTestChildren(HitTestResult result, { Point position }) {
defaultHitTestChildren(result, position: position);
}
void paint(PaintingContext context, Offset offset) {
if (_hasVisualOverflow) {
context.canvas.save();
context.canvas.clipRect(offset & size);
defaultPaint(context, offset);
context.canvas.restore();
} else {
defaultPaint(context, offset);
}
}
}