745f112ef6
Opt an initial batch of files under samples, samples-dev, utils, and runtime/tools/dartfuzz out of null safety in preparation for switching the flag on by default. Change-Id: Icdfd52a5a969e678a7205903332f73fe3841c223 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166960 Reviewed-by: Daco Harkes <dacoharkes@google.com> Commit-Queue: Leaf Petersen <leafp@google.com>
191 lines
5.2 KiB
Dart
191 lines
5.2 KiB
Dart
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
// @dart = 2.9
|
|
|
|
part of layout;
|
|
|
|
// This file has classes representing the grid tracks and grid template
|
|
|
|
/**
|
|
* The data structure representing the grid-rows or grid-columns
|
|
* properties.
|
|
*/
|
|
class GridTrackList {
|
|
/** The set of tracks defined in CSS via grid-rows and grid-columns */
|
|
final List<GridTrack> tracks;
|
|
|
|
/**
|
|
* Maps edge names to the corresponding track. Depending on whether the index
|
|
* is used as a start or end, it might be interpreted exclusively or
|
|
* inclusively.
|
|
*/
|
|
final Map<String, int> lineNames;
|
|
|
|
GridTrackList(this.tracks, this.lineNames) {}
|
|
}
|
|
|
|
/** Represents a row or a column. */
|
|
class GridTrack {
|
|
/**
|
|
* The start position of this track. Equal to the sum of previous track's
|
|
* usedBreadth.
|
|
*/
|
|
num start;
|
|
|
|
/** The final computed breadth of this track. */
|
|
num usedBreadth;
|
|
|
|
// Fields used internally by the sizing algorithm
|
|
num maxBreadth;
|
|
num updatedBreadth;
|
|
num tempBreadth;
|
|
|
|
final TrackSizing sizing;
|
|
|
|
GridTrack(this.sizing) {}
|
|
|
|
/**
|
|
* Support for the feature that repeats rows and columns, e.g.
|
|
* [:grid-columns: 10px ("content" 250px 10px)[4]:]
|
|
*/
|
|
GridTrack clone() => new GridTrack(sizing.clone());
|
|
|
|
/** The min sizing function for the track. */
|
|
SizingFunction get minSizing => sizing.min;
|
|
|
|
/** The min sizing function for the track. */
|
|
SizingFunction get maxSizing => sizing.max;
|
|
|
|
num get end => start + usedBreadth;
|
|
|
|
bool get isFractional => minSizing.isFraction || maxSizing.isFraction;
|
|
}
|
|
|
|
/** Represents the grid-row-align or grid-column-align. */
|
|
class GridItemAlignment {
|
|
// TODO(jmesserly): should this be stored as an int for performance?
|
|
final String value;
|
|
|
|
// 'start' | 'end' | 'center' | 'stretch'
|
|
GridItemAlignment.fromString(String value)
|
|
: this.value = (value == null) ? 'stretch' : value {
|
|
switch (this.value) {
|
|
case 'start':
|
|
case 'end':
|
|
case 'center':
|
|
case 'stretch':
|
|
break;
|
|
default:
|
|
throw new UnsupportedError('invalid row/column alignment "$value"');
|
|
}
|
|
}
|
|
|
|
_GridLocation align(_GridLocation span, int size) {
|
|
switch (value) {
|
|
case 'start':
|
|
return new _GridLocation(span.start, size);
|
|
case 'end':
|
|
return new _GridLocation(span.end - size, size);
|
|
case 'center':
|
|
size = Math.min(size, span.length);
|
|
num center = span.start + span.length / 2;
|
|
num left = center - size / 2;
|
|
return new _GridLocation(left.round(), size);
|
|
case 'stretch':
|
|
return span;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Represents a grid-template. Used in conjunction with a grid-cell to
|
|
* place cells in the grid, without needing to specify the exact row/column.
|
|
*/
|
|
class GridTemplate {
|
|
final Map<int, _GridTemplateRect> _rects;
|
|
final int _numRows;
|
|
|
|
GridTemplate(List<String> rows)
|
|
: _rects = new Map<int, _GridTemplateRect>(),
|
|
_numRows = rows.length {
|
|
_buildRects(rows);
|
|
}
|
|
|
|
/** Scans the template strings and computes bounds for each one. */
|
|
void _buildRects(List<String> templateRows) {
|
|
for (int r = 0; r < templateRows.length; r++) {
|
|
String row = templateRows[r];
|
|
for (int c = 0; c < row.length; c++) {
|
|
int cell = row.codeUnitAt(c);
|
|
final rect = _rects[cell];
|
|
if (rect != null) {
|
|
rect.add(r + 1, c + 1);
|
|
} else {
|
|
_rects[cell] = new _GridTemplateRect(cell, r + 1, c + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Finally, check that each rectangle is valid (i.e. all spaces filled)
|
|
for (final rect in _rects.values) {
|
|
rect.checkValid();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Looks up the given cell in the template, and returns the rect.
|
|
*/
|
|
_GridTemplateRect lookupCell(String cell) {
|
|
if (cell.length != 1) {
|
|
throw new UnsupportedError(
|
|
'grid-cell "$cell" must be a one character string');
|
|
}
|
|
final rect = _rects[cell.codeUnitAt(0)];
|
|
if (rect == null) {
|
|
throw new UnsupportedError(
|
|
'grid-cell "$cell" not found in parent\'s grid-template');
|
|
}
|
|
return rect;
|
|
}
|
|
}
|
|
|
|
/** Used by GridTemplate to track a single cell's bounds. */
|
|
class _GridTemplateRect {
|
|
int row, column, rowSpan, columnSpan, _count, _char;
|
|
_GridTemplateRect(this._char, this.row, this.column)
|
|
: rowSpan = 1,
|
|
columnSpan = 1,
|
|
_count = 1 {}
|
|
|
|
void add(int r, int c) {
|
|
assert(r >= row && c >= column);
|
|
_count++;
|
|
rowSpan = Math.max(rowSpan, r - row + 1);
|
|
columnSpan = Math.max(columnSpan, c - column + 1);
|
|
}
|
|
|
|
void checkValid() {
|
|
int expected = rowSpan * columnSpan;
|
|
if (expected != _count) {
|
|
// TODO(jmesserly): not sure if we should throw here, due to CSS's
|
|
// permissiveness. At the moment we're noisy about errors.
|
|
String cell = new String.fromCharCodes([_char]);
|
|
throw new UnsupportedError('grid-template "$cell"'
|
|
' is not square, expected $expected cells but got $_count');
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Used to return a row/column and span during parsing of grid-row and
|
|
* grid-column during parsing.
|
|
*/
|
|
class _GridLocation {
|
|
final int start, length;
|
|
_GridLocation(this.start, this.length) {}
|
|
|
|
int get end => start + length;
|
|
}
|