Migrate swarm's swarm_ui_lib/layout

Change-Id: I3c0809b8115d0b3244824e542c408ece78368bc5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/248346
Reviewed-by: Bob Nystrom <rnystrom@google.com>
Commit-Queue: Vijay Menon <vsm@google.com>
This commit is contained in:
Vijay Menon 2022-06-17 17:28:24 +00:00 committed by Commit Bot
parent 141c05d7d7
commit 65e8411498
8 changed files with 209 additions and 228 deletions

View file

@ -2,9 +2,6 @@
// 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;
/**
@ -47,9 +44,9 @@ part of layout;
// - Optimize for the "incremental update" cases
class GridLayout extends ViewLayout {
/** Configuration parameters defined in CSS. */
final GridTrackList rows;
final GridTrackList columns;
final GridTemplate template;
final GridTrackList? rows;
final GridTrackList? columns;
final GridTemplate? template;
/** The default sizing for new rows. */
final TrackSizing rowSizing;
@ -61,33 +58,33 @@ class GridLayout extends ViewLayout {
* This stores the grid's size during a layout.
* Used for rows/columns with % or fr units.
*/
int _gridWidth, _gridHeight;
int? _gridWidth, _gridHeight;
/**
* During a layout, this stores all row/column size information.
* Because grid-items can implicitly specify their own rows/columns, we can't
* compute this until we know the set of items.
*/
List<GridTrack> _rowTracks, _columnTracks;
late List<GridTrack> _rowTracks, _columnTracks;
/** During a layout, tracks which dimension we're processing. */
Dimension _dimension;
Dimension? _dimension;
GridLayout(Positionable view)
: rows = _GridTrackParser.parse(view.customStyle['grid-rows']),
columns = _GridTrackParser.parse(view.customStyle['grid-columns']),
template = _GridTemplateParser.parse(view.customStyle['grid-template']),
rowSizing = _GridTrackParser
.parseTrackSizing(view.customStyle['grid-row-sizing']),
columnSizing = _GridTrackParser
.parseTrackSizing(view.customStyle['grid-column-sizing']),
rowSizing = _GridTrackParser.parseTrackSizing(
view.customStyle['grid-row-sizing']),
columnSizing = _GridTrackParser.parseTrackSizing(
view.customStyle['grid-column-sizing']),
super(view) {
_rowTracks = rows != null ? rows.tracks : new List<GridTrack>();
_columnTracks = columns != null ? columns.tracks : new List<GridTrack>();
_rowTracks = rows?.tracks ?? [];
_columnTracks = columns?.tracks ?? [];
}
int get currentWidth => _gridWidth;
int get currentHeight => _gridHeight;
int? get currentWidth => _gridWidth;
int? get currentHeight => _gridHeight;
void cacheExistingBrowserLayout() {
// We don't need to do anything as we don't rely on the _cachedViewRect
@ -97,11 +94,11 @@ class GridLayout extends ViewLayout {
// TODO(jacobr): cleanup this method so that it returns a Future
// rather than taking a Completer as an argument.
/** The main entry point for layout computation. */
void measureLayout(Future<Size> size, Completer<bool> changed) {
void measureLayout(Future<Size> size, Completer<bool>? changed) {
_ensureAllTracks();
size.then((value) {
_gridWidth = value.width;
_gridHeight = value.height;
_gridWidth = value.width as int?;
_gridHeight = value.height as int?;
if (_rowTracks.length > 0 && _columnTracks.length > 0) {
_measureTracks();
@ -135,7 +132,7 @@ class GridLayout extends ViewLayout {
}
num _getRemainingSpace(List<GridTrack> tracks) {
num remaining = _getGridContentSize();
num remaining = _getGridContentSize()!;
remaining -= CollectionUtils.sum(tracks, (t) => t.usedBreadth);
return Math.max(0, remaining);
}
@ -152,7 +149,7 @@ class GridLayout extends ViewLayout {
void _computeUsedBreadthOfTracks(List<GridTrack> tracks) {
// TODO(jmesserly): as a performance optimization we could cache this
final items = view.childViews.map((view_) => view_.layout).toList();
CollectionUtils.sortBy(items, (item) => _getSpanCount(item));
CollectionUtils.sortBy(items, (item) => _getSpanCount(item)!);
// 1. Initialize per Grid Track variables
for (final t in tracks) {
@ -224,7 +221,7 @@ class GridLayout extends ViewLayout {
num finalPosition = position;
for (int i = 0; i < tracks.length; i++) {
int startEdge = tracks[i].start;
int startEdge = tracks[i].start as int;
int endEdge;
if (i < tracks.length - 1) {
endEdge = tracks[i + 1].start.round();
@ -266,7 +263,7 @@ class GridLayout extends ViewLayout {
CollectionUtils.sortBy(fractionTracks, (t) => t.tempBreadth);
num spaceNeededFromFractionTracks = _getRemainingSpace(tracks);
num currentBandFractionBreadth = 0;
num? currentBandFractionBreadth = 0;
num accumulatedFractions = 0;
for (final t in fractionTracks) {
if (t.tempBreadth != currentBandFractionBreadth) {
@ -287,7 +284,7 @@ class GridLayout extends ViewLayout {
* computed, updatedBreadth, that represents the Grid Track's share of
* freeSpace.
*/
void _distributeSpaceToTracks(List<GridTrack> tracks, num freeSpace,
void _distributeSpaceToTracks(List<GridTrack?> tracks, num? freeSpace,
_BreadthAccumulator breadth, bool ignoreMaxBreadth) {
// TODO(jmesserly): in some cases it would be safe to sort the passed in
// list in place. Not always though.
@ -298,9 +295,9 @@ class GridLayout extends ViewLayout {
// their maxBreadth values. Because there are different MaxBreadths
// assigned to the different Grid Tracks, this can result in uneven growth.
for (int i = 0; i < tracks.length; i++) {
num share = freeSpace / (tracks.length - i);
share = Math.min(share, tracks[i].maxBreadth);
tracks[i].tempBreadth = share;
num share = freeSpace! / (tracks.length - i);
share = Math.min(share, tracks[i]!.maxBreadth);
tracks[i]!.tempBreadth = share;
freeSpace -= share;
}
@ -309,10 +306,10 @@ class GridLayout extends ViewLayout {
// evenly and assign it to each Grid Track without regard for its
// maxBreadth. This phase of growth will always be even, but only occurs
// when the ignoreMaxBreadth flag is true.
if (freeSpace > 0 && ignoreMaxBreadth) {
if (freeSpace! > 0 && ignoreMaxBreadth) {
for (int i = 0; i < tracks.length; i++) {
final share = freeSpace / (tracks.length - i);
tracks[i].tempBreadth += share;
final share = freeSpace! / (tracks.length - i);
tracks[i]!.tempBreadth = tracks[i]!.tempBreadth + share;
freeSpace -= share;
}
}
@ -320,7 +317,7 @@ class GridLayout extends ViewLayout {
// Note: the spec has us updating all grid tracks, not just the passed in
// tracks, but I think that's a spec bug.
for (final t in tracks) {
t.updatedBreadth = Math.max(t.updatedBreadth, t.tempBreadth);
t!.updatedBreadth = Math.max(t.updatedBreadth, t.tempBreadth);
}
}
@ -352,7 +349,7 @@ class GridLayout extends ViewLayout {
// Remember that we need to update the sizes on these tracks
tracks.addAll(spannedTracks);
// Each time we transition to a new spanCount, update any modified tracks
// Each time we transition to a spanCount, update any modified tracks
bool spanCountFinished = false;
if (i + 1 == items.length) {
spanCountFinished = true;
@ -362,7 +359,7 @@ class GridLayout extends ViewLayout {
if (spanCountFinished) {
for (final t in tracks) {
breadth.setSize(t, Math.max(breadth.getSize(t), t.updatedBreadth));
breadth.setSize(t, Math.max(breadth.getSize(t)!, t.updatedBreadth));
}
tracks = [];
}
@ -373,14 +370,14 @@ class GridLayout extends ViewLayout {
* Returns true if we have an appropriate content sized dimension, and don't
* cross a fractional track.
*/
static bool _hasContentSizedTracks(Iterable<GridTrack> tracks,
static bool _hasContentSizedTracks(Iterable<GridTrack?> tracks,
ContentSizeMode sizeMode, _BreadthAccumulator breadth) {
for (final t in tracks) {
final fn = breadth.getSizingFunction(t);
if (sizeMode == ContentSizeMode.MAX && fn.isMaxContentSized ||
sizeMode == ContentSizeMode.MIN && fn.isContentSized) {
// Make sure we don't cross a fractional track
return tracks.length == 1 || !tracks.any((t_) => t_.isFractional);
return tracks.length == 1 || !tracks.any((t_) => t_!.isFractional);
}
}
return false;
@ -400,7 +397,7 @@ class GridLayout extends ViewLayout {
// Fill in tracks
for (int i = first; i < length; i++) {
if (tracks[i] == null) {
tracks[i] = new GridTrack(sizing);
tracks[i] = GridTrack(sizing);
}
}
}
@ -409,7 +406,7 @@ class GridLayout extends ViewLayout {
* Scans children creating GridLayoutParams as needed, and creates all of the
* rows and columns that we will need.
*
* Note: this can potentially create new rows/columns, so this needs to be
* Note: this can potentially create new qrows/columns, so this needs to be
* run before the track sizing algorithm.
*/
void _ensureAllTracks() {
@ -417,9 +414,9 @@ class GridLayout extends ViewLayout {
for (final child in items) {
if (child.layoutParams == null) {
final p = new GridLayoutParams(child.view, this);
_ensureTrack(_rowTracks, rowSizing, p.row, p.rowSpan);
_ensureTrack(_columnTracks, columnSizing, p.column, p.columnSpan);
final p = GridLayoutParams(child.view, this);
_ensureTrack(_rowTracks, rowSizing, p.row!, p.rowSpan!);
_ensureTrack(_columnTracks, columnSizing, p.column!, p.columnSpan!);
child.layoutParams = p;
}
child.cacheExistingBrowserLayout();
@ -433,12 +430,12 @@ class GridLayout extends ViewLayout {
final items = view.childViews.map((view_) => view_.layout);
for (final item in items) {
GridLayoutParams childLayout = item.layoutParams;
GridLayoutParams childLayout = item.layoutParams as GridLayoutParams;
var xPos = _getTrackLocationX(childLayout);
var yPos = _getTrackLocationY(childLayout);
int left = xPos.start, width = xPos.length;
int top = yPos.start, height = yPos.length;
int? left = xPos.start, width = xPos.length;
int? top = yPos.start, height = yPos.length;
// Somewhat counterintuitively (at least to me):
// grid-col-align is the horizontal alignment
@ -446,11 +443,11 @@ class GridLayout extends ViewLayout {
xPos = childLayout.columnAlign.align(xPos, item.currentWidth);
yPos = childLayout.rowAlign.align(yPos, item.currentHeight);
item.setBounds(xPos.start, yPos.start, xPos.length, yPos.length);
item.setBounds(xPos.start, yPos.start, xPos.length!, yPos.length!);
}
}
num _getGridContentSize() {
num? _getGridContentSize() {
if (_dimension == Dimension.WIDTH) {
return _gridWidth;
} else if (_dimension == Dimension.HEIGHT) {
@ -459,55 +456,52 @@ class GridLayout extends ViewLayout {
}
_GridLocation _getTrackLocationX(GridLayoutParams childLayout) {
int start = childLayout.column - 1;
int end = start + childLayout.columnSpan - 1;
int start = childLayout.column! - 1;
int end = start + childLayout.columnSpan! - 1;
start = _columnTracks[start].start;
end = _columnTracks[end].end;
start = _columnTracks[start].start as int;
end = _columnTracks[end].end as int;
return new _GridLocation(start, end - start);
return _GridLocation(start, end - start);
}
_GridLocation _getTrackLocationY(GridLayoutParams childLayout) {
int start = childLayout.row - 1;
int end = start + childLayout.rowSpan - 1;
int start = childLayout.row! - 1;
int end = start + childLayout.rowSpan! - 1;
start = _rowTracks[start].start;
end = _rowTracks[end].end;
start = _rowTracks[start].start as int;
end = _rowTracks[end].end as int;
return new _GridLocation(start, end - start);
return _GridLocation(start, end - start);
}
/** Gets the tracks that this item crosses. */
// TODO(jmesserly): might be better to return an iterable
List<GridTrack> _getTracks(ViewLayout item) {
GridLayoutParams childLayout = item.layoutParams;
List<GridTrack?> _getTracks(ViewLayout item) {
GridLayoutParams? childLayout = item.layoutParams as GridLayoutParams?;
int start, span;
List<GridTrack> tracks;
int? start, span;
List<GridTrack>? tracks;
if (_dimension == Dimension.WIDTH) {
start = childLayout.column - 1;
start = childLayout!.column! - 1;
span = childLayout.columnSpan;
tracks = _columnTracks;
} else if (_dimension == Dimension.HEIGHT) {
start = childLayout.row - 1;
start = childLayout!.row! - 1;
span = childLayout.rowSpan;
tracks = _rowTracks;
}
assert(start >= 0 && span >= 1);
assert(start! >= 0 && span! >= 1);
final result = new List<GridTrack>(span);
for (int i = 0; i < span; i++) {
result[i] = tracks[start + i];
}
final result = List<GridTrack>.generate(span!, (i) => tracks![start! + i]);
return result;
}
int _getSpanCount(ViewLayout item) {
GridLayoutParams childLayout = item.layoutParams;
int? _getSpanCount(ViewLayout item) {
GridLayoutParams? childLayout = item.layoutParams as GridLayoutParams?;
return (_dimension == Dimension.WIDTH
? childLayout.columnSpan
: childLayout.rowSpan);
? childLayout!.columnSpan
: childLayout!.rowSpan);
}
}

View file

@ -2,8 +2,6 @@
// 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;
/**
@ -16,25 +14,24 @@ part of layout;
// field ends up being mentioned 4 times instead of just twice.
class GridLayoutParams extends LayoutParams {
/** The coordinates of this item in the grid. */
int row;
int column;
int rowSpan;
int columnSpan;
int layer;
int? row;
int? column;
int? rowSpan;
int? columnSpan;
int? layer;
/** Alignment within its box */
GridItemAlignment rowAlign;
GridItemAlignment columnAlign;
GridLayoutParams(Positionable view, GridLayout layout) : super(view.node) {
GridLayoutParams(Positionable view, GridLayout layout)
: rowAlign =
GridItemAlignment.fromString(view.customStyle['grid-row-align']),
columnAlign =
GridItemAlignment.fromString(view.customStyle['grid-column-align']),
super(view.node) {
// TODO(jmesserly): this can be cleaned up a lot by just passing "view"
// into the parsers.
rowAlign =
new GridItemAlignment.fromString(view.customStyle['grid-row-align']);
columnAlign =
new GridItemAlignment.fromString(view.customStyle['grid-column-align']);
layer = StringUtils.parseInt(view.customStyle['grid-layer'], 0);
rowSpan = StringUtils.parseInt(view.customStyle['grid-row-span']);
@ -45,7 +42,7 @@ class GridLayoutParams extends LayoutParams {
row = line.start;
if (line.length != null) {
if (rowSpan != null) {
throw new UnsupportedError(
throw UnsupportedError(
'grid-row-span cannot be with grid-row that defines an end');
}
rowSpan = line.length;
@ -59,14 +56,14 @@ class GridLayoutParams extends LayoutParams {
column = line.start;
if (line.length != null) {
if (columnSpan != null) {
throw new UnsupportedError(
throw UnsupportedError(
'grid-column-span cannot be with grid-column that defines an end');
}
columnSpan = line.length;
}
}
String cell = _GridTemplateParser.parseCell(view.customStyle['grid-cell']);
String? cell = _GridTemplateParser.parseCell(view.customStyle['grid-cell']);
if (cell != null && cell != 'none') {
// TODO(jmesserly): I didn't see anything spec'd about conflicts and
// error handling. For now, throw an error on a misconfigured view.
@ -76,16 +73,16 @@ class GridLayoutParams extends LayoutParams {
column != null ||
rowSpan != null ||
columnSpan != null) {
throw new UnsupportedError(
throw UnsupportedError(
'grid-cell cannot be used with grid-row and grid-column');
}
if (layout.template == null) {
throw new UnsupportedError(
throw UnsupportedError(
'grid-cell requires that grid-template is set on the parent');
}
final rect = layout.template.lookupCell(cell);
final rect = layout.template!.lookupCell(cell);
row = rect.row;
column = rect.column;
rowSpan = rect.rowSpan;
@ -96,7 +93,7 @@ class GridLayoutParams extends LayoutParams {
if (columnSpan == null) columnSpan = 1;
if (row == null && column == null) {
throw new UnsupportedError('grid-flow is not implemented' +
throw UnsupportedError('grid-flow is not implemented' +
' so at least one row or one column must be defined');
}
@ -104,6 +101,6 @@ class GridLayoutParams extends LayoutParams {
if (column == null) column = 1;
}
assert(row > 0 && rowSpan > 0 && column > 0 && columnSpan > 0);
assert(row! > 0 && rowSpan! > 0 && column! > 0 && columnSpan! > 0);
}
}

View file

@ -2,8 +2,6 @@
// 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;
/**
@ -56,7 +54,7 @@ class _Parser {
}
void _error(String msg) {
throw new SyntaxErrorException(msg, _src, _offset);
throw SyntaxErrorException(msg, _src, _offset);
}
int get length => _src.length;
@ -132,7 +130,7 @@ class _Parser {
}
}
String _maybeEatString() {
String? _maybeEatString() {
// TODO(jmesserly): make this match CSS string parsing
String quote = "'";
if (!_maybeEat(quote)) {
@ -171,7 +169,7 @@ class _Parser {
}
/** Eats an integer. */
int _maybeEatInt() {
int? _maybeEatInt() {
int start = _offset;
bool dot = false;
while (_offset < length && _isDigit(_peekChar())) {
@ -186,8 +184,8 @@ class _Parser {
}
/** Eats an integer. */
int _eatInt() {
int result = _maybeEatInt();
int? _eatInt() {
int? result = _maybeEatInt();
if (result == null) {
_error('expected positive integer');
}
@ -224,37 +222,37 @@ class _GridTemplateParser extends _Parser {
_GridTemplateParser._internal(String src) : super(src);
/** Parses the grid-rows and grid-columns CSS properties into object form. */
static GridTemplate parse(String str) {
static GridTemplate? parse(String? str) {
if (str == null) return null;
final p = new _GridTemplateParser._internal(str);
final p = _GridTemplateParser._internal(str);
final result = p._parseTemplate();
p._eatEnd();
return result;
}
/** Parses a grid-cell value. */
static String parseCell(String str) {
static String? parseCell(String? str) {
if (str == null) return null;
final p = new _GridTemplateParser._internal(str);
final p = _GridTemplateParser._internal(str);
final result = p._maybeEatString();
p._eatEnd();
return result;
}
// => <string>+ | 'none'
GridTemplate _parseTemplate() {
GridTemplate? _parseTemplate() {
if (_maybeEat('none')) {
return null;
}
final rows = new List<String>();
String row;
final rows = <String?>[];
String? row;
while ((row = _maybeEatString()) != null) {
rows.add(row);
}
if (rows.length == 0) {
_error('expected at least one cell, or "none"');
}
return new GridTemplate(rows);
return GridTemplate(rows);
}
}
@ -263,9 +261,9 @@ class _GridItemParser extends _Parser {
_GridItemParser._internal(String src) : super(src);
/** Parses the grid-rows and grid-columns CSS properties into object form. */
static _GridLocation parse(String cell, GridTrackList list) {
static _GridLocation? parse(String? cell, GridTrackList? list) {
if (cell == null) return null;
final p = new _GridItemParser._internal(cell);
final p = _GridItemParser._internal(cell);
final result = p._parseTrack(list);
p._eatEnd();
return result;
@ -274,27 +272,27 @@ class _GridItemParser extends _Parser {
// [ [ <integer> | <string> | 'start' | 'end' ]
// [ <integer> | <string> | 'start' | 'end' ]? ]
// | 'auto'
_GridLocation _parseTrack(GridTrackList list) {
_GridLocation? _parseTrack(GridTrackList? list) {
if (_maybeEat('auto')) {
return null;
}
int start = _maybeParseLine(list);
int? start = _maybeParseLine(list);
if (start == null) {
_error('expected row/column number or name');
}
int end = _maybeParseLine(list);
int span = null;
int? end = _maybeParseLine(list);
int? span = null;
if (end != null) {
span = end - start;
span = end - start!;
if (span <= 0) {
_error('expected row/column span to be a positive integer');
}
}
return new _GridLocation(start, span);
return _GridLocation(start, span);
}
// [ <integer> | <string> | 'start' | 'end' ]
int _maybeParseLine(GridTrackList list) {
int? _maybeParseLine(GridTrackList? list) {
if (_maybeEat('start')) {
return 1;
} else if (_maybeEat('end')) {
@ -303,14 +301,14 @@ class _GridItemParser extends _Parser {
// TODO(jmesserly): this won't interact properly with implicit
// rows/columns. Instead it will snap to the number of tracks at the point
// where it is evaluated.
return list.tracks.length + 1;
return list!.tracks.length + 1;
}
String name = _maybeEatString();
String? name = _maybeEatString();
if (name == null) {
return _maybeEatInt();
} else {
int edge = list.lineNames[name];
int? edge = list!.lineNames[name];
if (edge == null) {
_error('row/column name "$name" not found in the parent\'s '
' grid-row/grid-columns properties');
@ -329,17 +327,17 @@ class _GridItemParser extends _Parser {
// CSS units, support for all escape sequences, etc.
class _GridTrackParser extends _Parser {
final List<GridTrack> _tracks;
final Map<String, int> _lineNames;
final Map<String?, int> _lineNames;
_GridTrackParser._internal(String src)
: _tracks = new List<GridTrack>(),
_lineNames = new Map<String, int>(),
: _tracks = <GridTrack>[],
_lineNames = Map<String?, int>(),
super(src);
/** Parses the grid-rows and grid-columns CSS properties into object form. */
static GridTrackList parse(String str) {
static GridTrackList? parse(String? str) {
if (str == null) return null;
final p = new _GridTrackParser._internal(str);
final p = _GridTrackParser._internal(str);
final result = p._parseTrackList();
p._eatEnd();
return result;
@ -349,28 +347,28 @@ class _GridTrackParser extends _Parser {
* Parses the grid-row-sizing and grid-column-sizing CSS properties into
* object form.
*/
static TrackSizing parseTrackSizing(String str) {
static TrackSizing parseTrackSizing(String? str) {
if (str == null) str = 'auto';
final p = new _GridTrackParser._internal(str);
final p = _GridTrackParser._internal(str);
final result = p._parseTrackMinmax();
p._eatEnd();
return result;
}
// <track-list> => [ [ <string> ]* <track-group> [ <string> ]* ]+ | 'none'
GridTrackList _parseTrackList() {
GridTrackList? _parseTrackList() {
if (_maybeEat('none')) {
return null;
}
_parseTrackListHelper();
return new GridTrackList(_tracks, _lineNames);
return GridTrackList(_tracks, _lineNames);
}
/** Code shared by _parseTrackList and _parseTrackGroup */
void _parseTrackListHelper([List<GridTrack> resultTracks = null]) {
void _parseTrackListHelper([List<GridTrack>? resultTracks = null]) {
_maybeEatWhitespace();
while (!endOfInput) {
String name;
String? name;
while ((name = _maybeEatString()) != null) {
_lineNames[name] = _tracks.length + 1; // should be 1-based
}
@ -384,7 +382,7 @@ class _GridTrackParser extends _Parser {
if (_peekChar() == _Parser.R_PAREN) {
return;
}
resultTracks.add(new GridTrack(_parseTrackMinmax()));
resultTracks.add(GridTrack(_parseTrackMinmax()));
} else {
_parseTrackGroup();
}
@ -398,11 +396,11 @@ class _GridTrackParser extends _Parser {
// | <track-minmax>
void _parseTrackGroup() {
if (_maybeEat('(')) {
final tracks = new List<GridTrack>();
final tracks = <GridTrack>[];
_parseTrackListHelper(tracks);
_eat(')');
if (_maybeEat('[')) {
num expand = _eatInt();
num expand = _eatInt()!;
_eat(']');
if (expand <= 0) {
@ -419,7 +417,7 @@ class _GridTrackParser extends _Parser {
}
}
} else {
_tracks.add(new GridTrack(_parseTrackMinmax()));
_tracks.add(GridTrack(_parseTrackMinmax()));
}
}
@ -434,10 +432,10 @@ class _GridTrackParser extends _Parser {
_eat(',');
final max = _parseTrackBreadth();
_eat(')');
return new TrackSizing(min, max);
return TrackSizing(min, max);
} else {
final breadth = _parseTrackBreadth();
return new TrackSizing(breadth, breadth);
return TrackSizing(breadth, breadth);
}
}
@ -460,9 +458,9 @@ class _GridTrackParser extends _Parser {
}
if (units == 'fr') {
return new FractionSizing(value);
return FractionSizing(value);
} else {
return new FixedSizing(value, units);
return FixedSizing(value, units);
}
}
}

View file

@ -2,8 +2,6 @@
// 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
@ -21,7 +19,7 @@ class GridTrackList {
* is used as a start or end, it might be interpreted exclusively or
* inclusively.
*/
final Map<String, int> lineNames;
final Map<String?, int> lineNames;
GridTrackList(this.tracks, this.lineNames) {}
}
@ -32,15 +30,15 @@ class GridTrack {
* The start position of this track. Equal to the sum of previous track's
* usedBreadth.
*/
num start;
late num start;
/** The final computed breadth of this track. */
num usedBreadth;
late num usedBreadth;
// Fields used internally by the sizing algorithm
num maxBreadth;
num updatedBreadth;
num tempBreadth;
late num maxBreadth;
late num updatedBreadth;
late num tempBreadth;
final TrackSizing sizing;
@ -50,7 +48,7 @@ class GridTrack {
* Support for the feature that repeats rows and columns, e.g.
* [:grid-columns: 10px ("content" 250px 10px)[4]:]
*/
GridTrack clone() => new GridTrack(sizing.clone());
GridTrack clone() => GridTrack(sizing.clone());
/** The min sizing function for the track. */
SizingFunction get minSizing => sizing.min;
@ -69,7 +67,7 @@ class GridItemAlignment {
final String value;
// 'start' | 'end' | 'center' | 'stretch'
GridItemAlignment.fromString(String value)
GridItemAlignment.fromString(String? value)
: this.value = (value == null) ? 'stretch' : value {
switch (this.value) {
case 'start':
@ -78,24 +76,25 @@ class GridItemAlignment {
case 'stretch':
break;
default:
throw new UnsupportedError('invalid row/column alignment "$value"');
throw UnsupportedError('invalid row/column alignment "$value"');
}
}
_GridLocation align(_GridLocation span, int size) {
_GridLocation align(_GridLocation span, int? size) {
switch (value) {
case 'start':
return new _GridLocation(span.start, size);
return _GridLocation(span.start, size);
case 'end':
return new _GridLocation(span.end - size, size);
return _GridLocation(span.end - size!, size);
case 'center':
size = Math.min(size, span.length);
num center = span.start + span.length / 2;
size = Math.min(size!, span.length!);
num center = span.start! + span.length! / 2;
num left = center - size / 2;
return new _GridLocation(left.round(), size);
return _GridLocation(left.round(), size);
case 'stretch':
return span;
}
throw UnsupportedError('invalid row/column alignment "$value"');
}
}
@ -107,23 +106,23 @@ class GridTemplate {
final Map<int, _GridTemplateRect> _rects;
final int _numRows;
GridTemplate(List<String> rows)
: _rects = new Map<int, _GridTemplateRect>(),
GridTemplate(List<String?> rows)
: _rects = <int, _GridTemplateRect>{},
_numRows = rows.length {
_buildRects(rows);
}
/** Scans the template strings and computes bounds for each one. */
void _buildRects(List<String> templateRows) {
void _buildRects(List<String?> templateRows) {
for (int r = 0; r < templateRows.length; r++) {
String row = templateRows[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);
_rects[cell] = _GridTemplateRect(cell, r + 1, c + 1);
}
}
}
@ -139,12 +138,12 @@ class GridTemplate {
*/
_GridTemplateRect lookupCell(String cell) {
if (cell.length != 1) {
throw new UnsupportedError(
throw UnsupportedError(
'grid-cell "$cell" must be a one character string');
}
final rect = _rects[cell.codeUnitAt(0)];
if (rect == null) {
throw new UnsupportedError(
throw UnsupportedError(
'grid-cell "$cell" not found in parent\'s grid-template');
}
return rect;
@ -171,8 +170,8 @@ class _GridTemplateRect {
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"'
String cell = String.fromCharCodes([_char]);
throw UnsupportedError('grid-template "$cell"'
' is not square, expected $expected cells but got $_count');
}
}
@ -183,8 +182,8 @@ class _GridTemplateRect {
* grid-column during parsing.
*/
class _GridLocation {
final int start, length;
final int? start, length;
_GridLocation(this.start, this.length) {}
int get end => start + length;
int get end => start! + length!;
}

View file

@ -2,8 +2,6 @@
// 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 sizing functions
@ -20,7 +18,7 @@ class SizingFunction {
bool get isMaxContentSized => false;
bool get isFraction => false;
num resolveLength(num gridSize) => 0;
num resolveLength(num? gridSize) => 0;
num get fractionValue => 0;
@ -46,16 +44,16 @@ class FixedSizing extends SizingFunction {
FixedSizing(this.length, [this.units = 'px']) : _contentSized = false {
if (units != 'px' && units != '%') {
// TODO(jmesserly): support other unit types
throw new UnsupportedError('Units other than px and %');
throw UnsupportedError('Units other than px and %');
}
}
// TODO(jmesserly): this is only needed because of our mutable property
FixedSizing clone() => new FixedSizing(length, units);
FixedSizing clone() => FixedSizing(length, units);
bool get isMinContentSized => _contentSized;
num resolveLength(num gridSize) {
num resolveLength(num? gridSize) {
if (units == '%') {
if (gridSize == null) {
// Use content size when the grid doesn't have an absolute size in this
@ -120,38 +118,38 @@ class TrackSizing {
TrackSizing(this.min, this.max) {}
// TODO(jmesserly): this is only needed because FixedSizing is mutable
TrackSizing clone() => new TrackSizing(min.clone(), max.clone());
TrackSizing clone() => TrackSizing(min.clone(), max.clone());
}
/** Represents a GridTrack breadth property. */
// TODO(jmesserly): these classes could be replaced with reflection/mirrors
abstract class _BreadthAccumulator {
void setSize(GridTrack t, num value);
num getSize(GridTrack t);
void setSize(GridTrack? t, num value);
num? getSize(GridTrack? t);
SizingFunction getSizingFunction(GridTrack t);
SizingFunction getSizingFunction(GridTrack? t);
}
class _UsedBreadthAccumulator implements _BreadthAccumulator {
const _UsedBreadthAccumulator();
void setSize(GridTrack t, num value) {
t.usedBreadth = value;
void setSize(GridTrack? t, num value) {
t!.usedBreadth = value;
}
num getSize(GridTrack t) => t.usedBreadth;
num? getSize(GridTrack? t) => t!.usedBreadth;
SizingFunction getSizingFunction(GridTrack t) => t.minSizing;
SizingFunction getSizingFunction(GridTrack? t) => t!.minSizing;
}
class _MaxBreadthAccumulator implements _BreadthAccumulator {
const _MaxBreadthAccumulator();
void setSize(GridTrack t, num value) {
t.maxBreadth = value;
void setSize(GridTrack? t, num value) {
t!.maxBreadth = value;
}
num getSize(GridTrack t) => t.maxBreadth;
num? getSize(GridTrack? t) => t!.maxBreadth;
SizingFunction getSizingFunction(GridTrack t) => t.maxSizing;
SizingFunction getSizingFunction(GridTrack? t) => t!.maxSizing;
}

View file

@ -2,8 +2,6 @@
// 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;
/** The interface that the layout algorithms use to talk to the view. */
@ -30,9 +28,9 @@ abstract class Positionable {
class LayoutParams {
// TODO(jmesserly): should be const, but there's a bug in DartC preventing us
// from calling "window." in an initializer. See b/5332777
CssStyleDeclaration style;
CssStyleDeclaration? style;
int get layer => 0;
int? get layer => 0;
LayoutParams(Element node) {
style = node.getComputedStyle();
@ -73,9 +71,9 @@ class ViewLayout {
* The layout parameters associated with this view and used by the parent
* to determine how this view should be laid out.
*/
LayoutParams layoutParams;
int _offsetWidth;
int _offsetHeight;
LayoutParams? layoutParams;
int? _offsetWidth;
int? _offsetHeight;
/** The view that this layout belongs to. */
final Positionable view;
@ -85,7 +83,7 @@ class ViewLayout {
* properties in the first pass while computing positions. Then we have a
* second pass that actually moves everything.
*/
int _measuredLeft, _measuredTop, _measuredWidth, _measuredHeight;
int? _measuredLeft, _measuredTop, _measuredWidth, _measuredHeight;
ViewLayout(this.view);
@ -96,9 +94,9 @@ class ViewLayout {
// registered with a LayoutProvider.
factory ViewLayout.fromView(Positionable view) {
if (hasCustomLayout(view)) {
return new GridLayout(view);
return GridLayout(view);
} else {
return new ViewLayout(view);
return ViewLayout(view);
}
}
@ -106,36 +104,36 @@ class ViewLayout {
return view.customStyle['display'] == "-dart-grid";
}
CssStyleDeclaration get _style => layoutParams.style;
CssStyleDeclaration? get _style => layoutParams!.style;
void cacheExistingBrowserLayout() {
_offsetWidth = view.node.offset.width;
_offsetHeight = view.node.offset.height;
_offsetWidth = view.node.offset.width as int?;
_offsetHeight = view.node.offset.height as int?;
}
int get currentWidth {
int? get currentWidth {
return _offsetWidth;
}
int get currentHeight {
int? get currentHeight {
return _offsetHeight;
}
int get borderLeftWidth => _toPixels(_style.borderLeftWidth);
int get borderTopWidth => _toPixels(_style.borderTopWidth);
int get borderRightWidth => _toPixels(_style.borderRightWidth);
int get borderBottomWidth => _toPixels(_style.borderBottomWidth);
int get borderLeftWidth => _toPixels(_style!.borderLeftWidth);
int get borderTopWidth => _toPixels(_style!.borderTopWidth);
int get borderRightWidth => _toPixels(_style!.borderRightWidth);
int get borderBottomWidth => _toPixels(_style!.borderBottomWidth);
int get borderWidth => borderLeftWidth + borderRightWidth;
int get borderHeight => borderTopWidth + borderBottomWidth;
/** Implements the custom layout computation. */
void measureLayout(Future<Size> size, Completer<bool> changed) {}
void measureLayout(Future<Size> size, Completer<bool>? changed) {}
/**
* Positions the view within its parent container.
* Also performs a layout of its children.
*/
void setBounds(int left, int top, int width, int height) {
void setBounds(int? left, int? top, int width, int height) {
assert(width >= 0 && height >= 0);
_measuredLeft = left;
@ -144,8 +142,8 @@ class ViewLayout {
// Note: we need to save the client height
_measuredWidth = width - borderWidth;
_measuredHeight = height - borderHeight;
final completer = new Completer<Size>();
completer.complete(new Size(_measuredWidth, _measuredHeight));
final completer = Completer<Size>();
completer.complete(Size(_measuredWidth!, _measuredHeight!));
measureLayout(completer.future, null);
}
@ -159,7 +157,7 @@ class ViewLayout {
style.top = '${_measuredTop}px';
style.width = '${_measuredWidth}px';
style.height = '${_measuredHeight}px';
style.zIndex = '${layoutParams.layer}';
style.zIndex = '${layoutParams!.layer}';
_measuredLeft = null;
_measuredTop = null;
@ -181,8 +179,8 @@ class ViewLayout {
}
}
int measureContent(ViewLayout parent, Dimension dimension,
[ContentSizeMode mode = null]) {
int? measureContent(ViewLayout parent, Dimension? dimension,
[ContentSizeMode? mode = null]) {
if (dimension == Dimension.WIDTH) {
return measureWidth(parent, mode);
} else if (dimension == Dimension.HEIGHT) {
@ -190,23 +188,23 @@ class ViewLayout {
}
}
int measureWidth(ViewLayout parent, ContentSizeMode mode) {
final style = layoutParams.style;
int? measureWidth(ViewLayout parent, ContentSizeMode? mode) {
final style = layoutParams!.style;
if (mode == ContentSizeMode.MIN) {
return _styleToPixels(style.minWidth, currentWidth, parent.currentWidth);
return _styleToPixels(style!.minWidth, currentWidth, parent.currentWidth);
} else if (mode == ContentSizeMode.MAX) {
return _styleToPixels(style.maxWidth, currentWidth, parent.currentWidth);
return _styleToPixels(style!.maxWidth, currentWidth, parent.currentWidth);
}
}
int measureHeight(ViewLayout parent, ContentSizeMode mode) {
final style = layoutParams.style;
int? measureHeight(ViewLayout parent, ContentSizeMode? mode) {
final style = layoutParams!.style;
if (mode == ContentSizeMode.MIN) {
return _styleToPixels(
style.minHeight, currentHeight, parent.currentHeight);
style!.minHeight, currentHeight, parent.currentHeight);
} else if (mode == ContentSizeMode.MAX) {
return _styleToPixels(
style.maxHeight, currentHeight, parent.currentHeight);
style!.maxHeight, currentHeight, parent.currentHeight);
}
}
@ -215,19 +213,18 @@ class ViewLayout {
return int.parse(style.substring(0, style.length - 2));
} else {
// TODO(jmesserly): other size units
throw new UnsupportedError(
'Unknown min/max content size format: "$style"');
throw UnsupportedError('Unknown min/max content size format: "$style"');
}
}
static int _styleToPixels(String style, num size, num parentSize) {
static int? _styleToPixels(String style, num? size, num? parentSize) {
if (style == 'none') {
// For an unset max-content size, use the actual size
return size;
return size as int?;
}
if (style.endsWith('%')) {
num percent = double.parse(style.substring(0, style.length - 1));
return ((percent / 100) * parentSize).toInt();
return ((percent / 100) * parentSize!).toInt();
}
return _toPixels(style);
}

View file

@ -2,8 +2,6 @@
// 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
library layout;
import 'dart:async';

View file

@ -80,9 +80,9 @@ class CollectionUtils {
}
/** Orders an iterable by its values, or by a key selector. */
static List orderBy(Iterable source,
static List<T> orderBy<T>(Iterable<T> source,
[NumericValueSelector? selector = null]) {
final result = List.from(source);
final result = List<T>.from(source);
sortBy(result, selector);
return result;
}