Simplify the AutoLayout API
This patch makes it easier to use the auto layout API: * We no longer use operator== because that requires an ugly cast by the API user. * Also, "leftEdge" is now just "left" for less verbosity. * AutoLayoutChild not implies its key from the AutoLayoutParam object. * We now correctly layout every child of a RenderAutoLayout object even if the solver doesn't flush any updates to that child.
This commit is contained in:
parent
6e14bd2e8c
commit
c7d71d8ab1
@ -14,33 +14,33 @@ class _MyAutoLayoutDelegate extends AutoLayoutDelegate {
|
|||||||
AutoLayoutParams p3 = new AutoLayoutParams();
|
AutoLayoutParams p3 = new AutoLayoutParams();
|
||||||
AutoLayoutParams p4 = new AutoLayoutParams();
|
AutoLayoutParams p4 = new AutoLayoutParams();
|
||||||
|
|
||||||
List<al.Constraint> getConstraints(AutoLayoutParams parentParams) {
|
List<al.Constraint> getConstraints(AutoLayoutParams parent) {
|
||||||
return <al.Constraint>[
|
return <al.Constraint>[
|
||||||
// Sum of widths of each box must be equal to that of the container
|
// Sum of widths of each box must be equal to that of the container
|
||||||
(p1.width + p2.width + p3.width == parentParams.width) as al.Constraint,
|
parent.width.equals(p1.width + p2.width + p3.width),
|
||||||
|
|
||||||
// The boxes must be stacked left to right
|
// The boxes must be stacked left to right
|
||||||
p1.rightEdge <= p2.leftEdge,
|
p1.right <= p2.left,
|
||||||
p2.rightEdge <= p3.leftEdge,
|
p2.right <= p3.left,
|
||||||
|
|
||||||
// The widths of the first and the third boxes should be equal
|
// The widths of the first and the third boxes should be equal
|
||||||
(p1.width == p3.width) as al.Constraint,
|
p1.width.equals(p3.width),
|
||||||
|
|
||||||
// The width of the second box should be twice as much as that of the first
|
// The width of the second box should be twice as much as that of the first
|
||||||
// and third
|
// and third
|
||||||
(p2.width * al.cm(2.0) == p1.width) as al.Constraint,
|
p1.width.equals(p2.width * al.cm(2.0)),
|
||||||
|
|
||||||
// The height of the three boxes should be equal to that of the container
|
// The height of the three boxes should be equal to that of the container
|
||||||
(p1.height == p2.height) as al.Constraint,
|
p1.height.equals(p2.height),
|
||||||
(p2.height == p3.height) as al.Constraint,
|
p2.height.equals(p3.height),
|
||||||
(p3.height == parentParams.height) as al.Constraint,
|
p3.height.equals(parent.height),
|
||||||
|
|
||||||
// The fourth box should be half as wide as the second and must be attached
|
// The fourth box should be half as wide as the second and must be attached
|
||||||
// to the right edge of the same (by its center)
|
// to the right edge of the same (by its center)
|
||||||
(p4.width == p2.width / al.cm(2.0)) as al.Constraint,
|
p4.width.equals(p2.width / al.cm(2.0)),
|
||||||
(p4.height == al.cm(50.0)) as al.Constraint,
|
p4.height.equals(al.cm(50.0)),
|
||||||
(p4.horizontalCenter == p2.rightEdge) as al.Constraint,
|
p4.horizontalCenter.equals(p2.right),
|
||||||
(p4.verticalCenter == p2.height / al.cm(2.0)) as al.Constraint,
|
p4.verticalCenter.equals(p2.height / al.cm(2.0)),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,53 +13,37 @@ class _MyAutoLayoutDelegate extends AutoLayoutDelegate {
|
|||||||
AutoLayoutParams p3 = new AutoLayoutParams();
|
AutoLayoutParams p3 = new AutoLayoutParams();
|
||||||
AutoLayoutParams p4 = new AutoLayoutParams();
|
AutoLayoutParams p4 = new AutoLayoutParams();
|
||||||
|
|
||||||
List<al.Constraint> getConstraints(AutoLayoutParams parentParams) {
|
List<al.Constraint> getConstraints(AutoLayoutParams parent) {
|
||||||
return <al.Constraint>[
|
return <al.Constraint>[
|
||||||
// Sum of widths of each box must be equal to that of the container
|
// Sum of widths of each box must be equal to that of the container
|
||||||
(p1.width + p2.width + p3.width == parentParams.width) as al.Constraint,
|
parent.width.equals(p1.width + p2.width + p3.width),
|
||||||
|
|
||||||
// The boxes must be stacked left to right
|
// The boxes must be stacked left to right
|
||||||
p1.rightEdge <= p2.leftEdge,
|
p1.right <= p2.left,
|
||||||
p2.rightEdge <= p3.leftEdge,
|
p2.right <= p3.left,
|
||||||
|
|
||||||
// The widths of the first and the third boxes should be equal
|
// The widths of the first and the third boxes should be equal
|
||||||
(p1.width == p3.width) as al.Constraint,
|
p1.width.equals(p3.width),
|
||||||
|
|
||||||
// The width of the second box should be twice as much as that of the first
|
// The width of the second box should be twice as much as that of the first
|
||||||
// and third
|
// and third
|
||||||
(p2.width * al.cm(2.0) == p1.width) as al.Constraint,
|
p1.width.equals(p2.width * al.cm(2.0)),
|
||||||
|
|
||||||
// The height of the three boxes should be equal to that of the container
|
// The height of the three boxes should be equal to that of the container
|
||||||
(p1.height == p2.height) as al.Constraint,
|
p1.height.equals(p2.height),
|
||||||
(p2.height == p3.height) as al.Constraint,
|
p2.height.equals(p3.height),
|
||||||
(p3.height == parentParams.height) as al.Constraint,
|
p3.height.equals(parent.height),
|
||||||
|
|
||||||
// The fourth box should be half as wide as the second and must be attached
|
// The fourth box should be half as wide as the second and must be attached
|
||||||
// to the right edge of the same (by its center)
|
// to the right edge of the same (by its center)
|
||||||
(p4.width == p2.width / al.cm(2.0)) as al.Constraint,
|
p4.width.equals(p2.width / al.cm(2.0)),
|
||||||
(p4.height == al.cm(50.0)) as al.Constraint,
|
p4.height.equals(al.cm(50.0)),
|
||||||
(p4.horizontalCenter == p2.rightEdge) as al.Constraint,
|
p4.horizontalCenter.equals(p2.right),
|
||||||
(p4.verticalCenter == p2.height / al.cm(2.0)) as al.Constraint,
|
p4.verticalCenter.equals(p2.height / al.cm(2.0)),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shouldUpdateConstraints(AutoLayoutDelegate oldDelegate) => true;
|
bool shouldUpdateConstraints(_MyAutoLayoutDelegate oldDelegate) => true;
|
||||||
}
|
|
||||||
|
|
||||||
class ColoredBox extends StatelessComponent {
|
|
||||||
ColoredBox({ Key key, this.params, this.color }) : super(key: key);
|
|
||||||
|
|
||||||
final AutoLayoutParams params;
|
|
||||||
final Color color;
|
|
||||||
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return new AutoLayoutChild(
|
|
||||||
params: params,
|
|
||||||
child: new DecoratedBox(
|
|
||||||
decoration: new BoxDecoration(backgroundColor: color)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ColoredBoxes extends StatefulComponent {
|
class ColoredBoxes extends StatefulComponent {
|
||||||
@ -73,10 +57,30 @@ class _ColoredBoxesState extends State<ColoredBoxes> {
|
|||||||
return new AutoLayout(
|
return new AutoLayout(
|
||||||
delegate: delegate,
|
delegate: delegate,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
new ColoredBox(params: delegate.p1, color: const Color(0xFFFF0000)),
|
new AutoLayoutChild(
|
||||||
new ColoredBox(params: delegate.p2, color: const Color(0xFF00FF00)),
|
params: delegate.p1,
|
||||||
new ColoredBox(params: delegate.p3, color: const Color(0xFF0000FF)),
|
child: new DecoratedBox(
|
||||||
new ColoredBox(params: delegate.p4, color: const Color(0xFFFFFFFF)),
|
decoration: new BoxDecoration(backgroundColor: const Color(0xFFFF0000))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new AutoLayoutChild(
|
||||||
|
params: delegate.p2,
|
||||||
|
child: new DecoratedBox(
|
||||||
|
decoration: new BoxDecoration(backgroundColor: const Color(0xFF00FF00))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new AutoLayoutChild(
|
||||||
|
params: delegate.p3,
|
||||||
|
child: new DecoratedBox(
|
||||||
|
decoration: new BoxDecoration(backgroundColor: const Color(0xFF0000FF))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new AutoLayoutChild(
|
||||||
|
params: delegate.p4,
|
||||||
|
child: new DecoratedBox(
|
||||||
|
decoration: new BoxDecoration(backgroundColor: const Color(0xFFFFFFFF))
|
||||||
|
)
|
||||||
|
),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ abstract class _EquationMember {
|
|||||||
|
|
||||||
Constraint operator <=(_EquationMember m) => asExpression() <= m;
|
Constraint operator <=(_EquationMember m) => asExpression() <= m;
|
||||||
|
|
||||||
operator ==(_EquationMember m) => asExpression() == m;
|
Constraint equals(_EquationMember m) => asExpression().equals(m);
|
||||||
|
|
||||||
Expression operator +(_EquationMember m) => asExpression() + m;
|
Expression operator +(_EquationMember m) => asExpression() + m;
|
||||||
|
|
||||||
|
@ -57,8 +57,8 @@ class Expression extends _EquationMember {
|
|||||||
Constraint operator <=(_EquationMember value) =>
|
Constraint operator <=(_EquationMember value) =>
|
||||||
_createConstraint(value, Relation.lessThanOrEqualTo);
|
_createConstraint(value, Relation.lessThanOrEqualTo);
|
||||||
|
|
||||||
operator ==(_EquationMember value) =>
|
Constraint equals(_EquationMember value) =>
|
||||||
_createConstraint(value, Relation.equalTo); // analyzer says "Type check failed" // analyzer says "The return type 'Constraint' is not a 'bool', as defined by the method '=='"
|
_createConstraint(value, Relation.equalTo);
|
||||||
|
|
||||||
Expression operator +(_EquationMember m) {
|
Expression operator +(_EquationMember m) {
|
||||||
if (m is ConstantMember) {
|
if (m is ConstantMember) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
@ -12,61 +12,35 @@ import 'object.dart';
|
|||||||
/// variables.
|
/// variables.
|
||||||
class AutoLayoutParams {
|
class AutoLayoutParams {
|
||||||
AutoLayoutParams() {
|
AutoLayoutParams() {
|
||||||
_leftEdge = new al.Param.withContext(this);
|
_left = new al.Param();
|
||||||
_rightEdge = new al.Param.withContext(this);
|
_right = new al.Param();
|
||||||
_topEdge = new al.Param.withContext(this);
|
_top = new al.Param();
|
||||||
_bottomEdge = new al.Param.withContext(this);
|
_bottom = new al.Param();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The render box with which these parameters are associated.
|
al.Param _left;
|
||||||
RenderBox _renderBox;
|
al.Param _right;
|
||||||
|
al.Param _top;
|
||||||
|
al.Param _bottom;
|
||||||
|
|
||||||
al.Param _leftEdge;
|
al.Param get left => _left;
|
||||||
al.Param _rightEdge;
|
al.Param get right => _right;
|
||||||
al.Param _topEdge;
|
al.Param get top => _top;
|
||||||
al.Param _bottomEdge;
|
al.Param get bottom => _bottom;
|
||||||
|
|
||||||
al.Param get leftEdge => _leftEdge;
|
al.Expression get width => _right - _left;
|
||||||
al.Param get rightEdge => _rightEdge;
|
al.Expression get height => _bottom - _top;
|
||||||
al.Param get topEdge => _topEdge;
|
|
||||||
al.Param get bottomEdge => _bottomEdge;
|
|
||||||
|
|
||||||
al.Expression get width => _rightEdge - _leftEdge;
|
al.Expression get horizontalCenter => (_left + _right) / al.cm(2.0);
|
||||||
al.Expression get height => _bottomEdge - _topEdge;
|
al.Expression get verticalCenter => (_top + _bottom) / al.cm(2.0);
|
||||||
|
|
||||||
al.Expression get horizontalCenter => (_leftEdge + _rightEdge) / al.cm(2.0);
|
List<al.Constraint> contains(AutoLayoutParams other) {
|
||||||
al.Expression get verticalCenter => (_topEdge + _bottomEdge) / al.cm(2.0);
|
return <al.Constraint>[
|
||||||
|
other.left >= left,
|
||||||
List<al.Constraint> _implicitConstraints;
|
other.right <= right,
|
||||||
|
other.top >= top,
|
||||||
void _addImplicitConstraints() {
|
other.bottom <= bottom,
|
||||||
assert(_renderBox != null);
|
];
|
||||||
if (_renderBox.parent == null)
|
|
||||||
return;
|
|
||||||
assert(_renderBox.parent is RenderAutoLayout);
|
|
||||||
final RenderAutoLayout parent = _renderBox.parent;
|
|
||||||
final AutoLayoutParentData parentData = _renderBox.parentData;
|
|
||||||
final List<al.Constraint> implicit = parentData._constructImplicitConstraints();
|
|
||||||
if (implicit == null || implicit.isEmpty)
|
|
||||||
return;
|
|
||||||
final al.Result result = parent._solver.addConstraints(implicit);
|
|
||||||
assert(result == al.Result.success);
|
|
||||||
parent.markNeedsLayout();
|
|
||||||
_implicitConstraints = implicit;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _removeImplicitConstraints() {
|
|
||||||
assert(_renderBox != null);
|
|
||||||
if (_renderBox.parent == null)
|
|
||||||
return;
|
|
||||||
if (_implicitConstraints == null || _implicitConstraints.isEmpty)
|
|
||||||
return;
|
|
||||||
assert(_renderBox.parent is RenderAutoLayout);
|
|
||||||
final RenderAutoLayout parent = _renderBox.parent;
|
|
||||||
final al.Result result = parent._solver.removeConstraints(_implicitConstraints);
|
|
||||||
assert(result == al.Result.success);
|
|
||||||
parent.markNeedsLayout();
|
|
||||||
_implicitConstraints = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,33 +54,60 @@ class AutoLayoutParentData extends ContainerBoxParentDataMixin<RenderBox> {
|
|||||||
void set params(AutoLayoutParams value) {
|
void set params(AutoLayoutParams value) {
|
||||||
if (_params == value)
|
if (_params == value)
|
||||||
return;
|
return;
|
||||||
if (_params != null) {
|
if (_params != null)
|
||||||
_params._removeImplicitConstraints();
|
_removeImplicitConstraints();
|
||||||
_params._renderBox = null;
|
|
||||||
}
|
|
||||||
_params = value;
|
_params = value;
|
||||||
if (_params != null) {
|
if (_params != null)
|
||||||
assert(_params._renderBox == null);
|
_addImplicitConstraints();
|
||||||
_params._renderBox = _renderBox;
|
|
||||||
_params._addImplicitConstraints();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BoxConstraints get _constraints {
|
BoxConstraints get _constraintsFromSolver {
|
||||||
return new BoxConstraints.tightFor(
|
return new BoxConstraints.tightFor(
|
||||||
width: _params._rightEdge.value - _params._leftEdge.value,
|
width: _params._right.value - _params._left.value,
|
||||||
height: _params._bottomEdge.value - _params._topEdge.value
|
height: _params._bottom.value - _params._top.value
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Offset get _offsetFromSolver {
|
||||||
|
return new Offset(_params._left.value, _params._top.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<al.Constraint> _implicitConstraints;
|
||||||
|
|
||||||
|
void _addImplicitConstraints() {
|
||||||
|
assert(_renderBox != null);
|
||||||
|
if (_renderBox.parent == null || _params == null)
|
||||||
|
return;
|
||||||
|
final List<al.Constraint> implicit = _constructImplicitConstraints();
|
||||||
|
assert(implicit != null && implicit.isNotEmpty);
|
||||||
|
assert(_renderBox.parent is RenderAutoLayout);
|
||||||
|
final RenderAutoLayout parent = _renderBox.parent;
|
||||||
|
final al.Result result = parent._solver.addConstraints(implicit);
|
||||||
|
assert(result == al.Result.success);
|
||||||
|
parent.markNeedsLayout();
|
||||||
|
_implicitConstraints = implicit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _removeImplicitConstraints() {
|
||||||
|
assert(_renderBox != null);
|
||||||
|
if (_renderBox.parent == null || _implicitConstraints == null || _implicitConstraints.isEmpty)
|
||||||
|
return;
|
||||||
|
assert(_renderBox.parent is RenderAutoLayout);
|
||||||
|
final RenderAutoLayout parent = _renderBox.parent;
|
||||||
|
final al.Result result = parent._solver.removeConstraints(_implicitConstraints);
|
||||||
|
assert(result == al.Result.success);
|
||||||
|
parent.markNeedsLayout();
|
||||||
|
_implicitConstraints = null;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the set of implicit constraints that need to be applied to all
|
/// Returns the set of implicit constraints that need to be applied to all
|
||||||
/// instances of this class when they are moved into a render object with an
|
/// instances of this class when they are moved into a render object with an
|
||||||
/// active solver. If no implicit constraints needs to be applied, the object
|
/// active solver. If no implicit constraints needs to be applied, the object
|
||||||
/// may return null.
|
/// may return null.
|
||||||
List<al.Constraint> _constructImplicitConstraints() {
|
List<al.Constraint> _constructImplicitConstraints() {
|
||||||
return <al.Constraint>[
|
return <al.Constraint>[
|
||||||
_params._leftEdge >= al.cm(0.0), // The left edge must be positive.
|
_params._left >= al.cm(0.0), // The left edge must be positive.
|
||||||
_params._rightEdge >= _params._leftEdge, // Width must be positive.
|
_params._right >= _params._left, // Width must be positive.
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,7 +115,7 @@ class AutoLayoutParentData extends ContainerBoxParentDataMixin<RenderBox> {
|
|||||||
abstract class AutoLayoutDelegate {
|
abstract class AutoLayoutDelegate {
|
||||||
const AutoLayoutDelegate();
|
const AutoLayoutDelegate();
|
||||||
|
|
||||||
List<al.Constraint> getConstraints(AutoLayoutParams parentParams);
|
List<al.Constraint> getConstraints(AutoLayoutParams parent);
|
||||||
bool shouldUpdateConstraints(AutoLayoutDelegate oldDelegate);
|
bool shouldUpdateConstraints(AutoLayoutDelegate oldDelegate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,10 +128,10 @@ class RenderAutoLayout extends RenderBox
|
|||||||
List<RenderBox> children
|
List<RenderBox> children
|
||||||
}) : _delegate = delegate, _needToUpdateConstraints = (delegate != null) {
|
}) : _delegate = delegate, _needToUpdateConstraints = (delegate != null) {
|
||||||
_solver.addEditVariables(<al.Variable>[
|
_solver.addEditVariables(<al.Variable>[
|
||||||
_params._leftEdge.variable,
|
_params._left.variable,
|
||||||
_params._rightEdge.variable,
|
_params._right.variable,
|
||||||
_params._topEdge.variable,
|
_params._top.variable,
|
||||||
_params._bottomEdge.variable
|
_params._bottom.variable
|
||||||
], al.Priority.required - 1);
|
], al.Priority.required - 1);
|
||||||
|
|
||||||
addAll(children);
|
addAll(children);
|
||||||
@ -162,14 +163,17 @@ class RenderAutoLayout extends RenderBox
|
|||||||
final al.Solver _solver = new al.Solver();
|
final al.Solver _solver = new al.Solver();
|
||||||
final List<al.Constraint> _explicitConstraints = new List<al.Constraint>();
|
final List<al.Constraint> _explicitConstraints = new List<al.Constraint>();
|
||||||
|
|
||||||
void _addExplicitConstraints(List<al.Constraint> constraints) {
|
void _setExplicitConstraints(List<al.Constraint> constraints) {
|
||||||
if (constraints == null || constraints.isEmpty)
|
assert(constraints != null);
|
||||||
|
if (constraints.isEmpty)
|
||||||
return;
|
return;
|
||||||
if (_solver.addConstraints(constraints) == al.Result.success)
|
if (_solver.addConstraints(constraints) == al.Result.success)
|
||||||
_explicitConstraints.addAll(constraints);
|
_explicitConstraints.addAll(constraints);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _clearExplicitConstraints() {
|
void _clearExplicitConstraints() {
|
||||||
|
if (_explicitConstraints.isEmpty)
|
||||||
|
return;
|
||||||
if (_solver.removeConstraints(_explicitConstraints) == al.Result.success)
|
if (_solver.removeConstraints(_explicitConstraints) == al.Result.success)
|
||||||
_explicitConstraints.clear();
|
_explicitConstraints.clear();
|
||||||
}
|
}
|
||||||
@ -178,13 +182,13 @@ class RenderAutoLayout extends RenderBox
|
|||||||
// Make sure to call super first to setup the parent data
|
// Make sure to call super first to setup the parent data
|
||||||
super.adoptChild(child);
|
super.adoptChild(child);
|
||||||
final AutoLayoutParentData childParentData = child.parentData;
|
final AutoLayoutParentData childParentData = child.parentData;
|
||||||
childParentData._params?._addImplicitConstraints();
|
childParentData._addImplicitConstraints();
|
||||||
assert(child.parentData == childParentData);
|
assert(child.parentData == childParentData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dropChild(RenderObject child) {
|
void dropChild(RenderObject child) {
|
||||||
final AutoLayoutParentData childParentData = child.parentData;
|
final AutoLayoutParentData childParentData = child.parentData;
|
||||||
childParentData._params?._removeImplicitConstraints();
|
childParentData._removeImplicitConstraints();
|
||||||
assert(child.parentData == childParentData);
|
assert(child.parentData == childParentData);
|
||||||
super.dropChild(child);
|
super.dropChild(child);
|
||||||
}
|
}
|
||||||
@ -200,42 +204,40 @@ class RenderAutoLayout extends RenderBox
|
|||||||
size = constraints.biggest;
|
size = constraints.biggest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Size _previousSize;
|
||||||
|
|
||||||
void performLayout() {
|
void performLayout() {
|
||||||
// Step 1: Update constraints if needed.
|
bool needToFlushUpdates = false;
|
||||||
|
|
||||||
if (_needToUpdateConstraints) {
|
if (_needToUpdateConstraints) {
|
||||||
_clearExplicitConstraints();
|
_clearExplicitConstraints();
|
||||||
if (_delegate != null)
|
if (_delegate != null)
|
||||||
_addExplicitConstraints(_delegate.getConstraints(_params));
|
_setExplicitConstraints(_delegate.getConstraints(_params));
|
||||||
_needToUpdateConstraints = false;
|
_needToUpdateConstraints = false;
|
||||||
|
needToFlushUpdates = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2: Update dimensions of this render object.
|
if (size != _previousSize) {
|
||||||
_solver
|
_solver
|
||||||
..suggestValueForVariable(_params._leftEdge.variable, 0.0)
|
..suggestValueForVariable(_params._left.variable, 0.0)
|
||||||
..suggestValueForVariable(_params._topEdge.variable, 0.0)
|
..suggestValueForVariable(_params._top.variable, 0.0)
|
||||||
..suggestValueForVariable(_params._bottomEdge.variable, size.height)
|
..suggestValueForVariable(_params._bottom.variable, size.height)
|
||||||
..suggestValueForVariable(_params._rightEdge.variable, size.width);
|
..suggestValueForVariable(_params._right.variable, size.width);
|
||||||
|
_previousSize = size;
|
||||||
// Step 3: Resolve solver updates and flush parameters
|
needToFlushUpdates = true;
|
||||||
|
|
||||||
// We don't iterate over the children, instead, we ask the solver to tell
|
|
||||||
// us the updated parameters. Attached to the parameters (via the context)
|
|
||||||
// are the AutoLayoutParams instances.
|
|
||||||
for (AutoLayoutParams update in _solver.flushUpdates()) {
|
|
||||||
RenderBox child = update._renderBox;
|
|
||||||
if (child != null)
|
|
||||||
_layoutChild(child);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void _layoutChild(RenderBox child) {
|
if (needToFlushUpdates)
|
||||||
assert(debugDoingThisLayout);
|
_solver.flushUpdates();
|
||||||
assert(child.parent == this);
|
|
||||||
final AutoLayoutParentData childParentData = child.parentData;
|
RenderBox child = firstChild;
|
||||||
child.layout(childParentData._constraints);
|
while (child != null) {
|
||||||
childParentData.offset = new Offset(childParentData._params._leftEdge.value,
|
final AutoLayoutParentData childParentData = child.parentData;
|
||||||
childParentData._params._topEdge.value);
|
child.layout(childParentData._constraintsFromSolver);
|
||||||
assert(child.parentData == childParentData);
|
childParentData.offset = childParentData._offsetFromSolver;
|
||||||
|
assert(child.parentData == childParentData);
|
||||||
|
child = childParentData.nextSibling;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hitTestChildren(HitTestResult result, { Point position }) {
|
bool hitTestChildren(HitTestResult result, { Point position }) {
|
||||||
|
@ -27,8 +27,8 @@ class AutoLayout extends MultiChildRenderObjectWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class AutoLayoutChild extends ParentDataWidget<AutoLayout> {
|
class AutoLayoutChild extends ParentDataWidget<AutoLayout> {
|
||||||
AutoLayoutChild({ Key key, this.params, Widget child })
|
AutoLayoutChild({ AutoLayoutParams params, Widget child })
|
||||||
: super(key: key, child: child);
|
: params = params, super(key: new ObjectKey(params), child: child);
|
||||||
|
|
||||||
final AutoLayoutParams params;
|
final AutoLayoutParams params;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user