Commit 34cc0c47 authored by Hixie's avatar Hixie

Rationalise the overflow render boxes

New RenderAligningShiftedBox abstract class for render boxes with
"alignment", which as of now is:

 - RenderPositionedBox
 - RenderConstrainedOverflowBox (ex RenderOverflowBox)
 - RenderSizedOverflowBox
 - RenderFractionallySizedOverflowBox (ex RenderFractionallySizedBox)

(The respective widgets are Align, OverflowBox, SizedOverflowBox, and
FractionallySizedBox. They haven't been renamed.)

Also I added some toString details.
parent 839334a5
......@@ -5,79 +5,6 @@
import 'box.dart';
import 'object.dart';
export 'package:flutter/src/painting/box_painter.dart';
/// A render box that's a specific size but passes its original constraints through to its child, which will probably overflow
class RenderSizedOverflowBox extends RenderBox with RenderObjectWithChildMixin<RenderBox> {
RenderSizedOverflowBox({
RenderBox child,
Size requestedSize
}) : _requestedSize = requestedSize {
assert(requestedSize != null);
this.child = child;
}
/// The size this render box should attempt to be.
Size get requestedSize => _requestedSize;
Size _requestedSize;
void set requestedSize (Size value) {
assert(value != null);
if (_requestedSize == value)
return;
_requestedSize = value;
markNeedsLayout();
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsNormalized);
return constraints.constrainWidth(_requestedSize.width);
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsNormalized);
return constraints.constrainWidth(_requestedSize.width);
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsNormalized);
return constraints.constrainHeight(_requestedSize.height);
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsNormalized);
return constraints.constrainHeight(_requestedSize.height);
}
@override
double computeDistanceToActualBaseline(TextBaseline baseline) {
if (child != null)
return child.getDistanceToActualBaseline(baseline);
return super.computeDistanceToActualBaseline(baseline);
}
@override
void performLayout() {
size = constraints.constrain(_requestedSize);
if (child != null)
child.layout(constraints);
}
@override
bool hitTestChildren(HitTestResult result, { Point position }) {
return child?.hitTest(result, position: position) ?? false;
}
@override
void paint(PaintingContext context, Offset offset) {
if (child != null)
context.paintChild(child, offset);
}
}
/// Lays the child out as if it was in the tree, but without painting anything,
/// without making the child available for hit testing, and without taking any
/// room in the parent.
......
......@@ -29,7 +29,6 @@ export 'package:flutter/gestures.dart' show
/// for render objects that wish to mimic most, but not all, of the properties
/// of their child.
class RenderProxyBox extends RenderBox with RenderObjectWithChildMixin<RenderBox> {
RenderProxyBox([RenderBox child = null]) {
this.child = child;
}
......@@ -247,128 +246,6 @@ class RenderConstrainedBox extends RenderProxyBox {
}
}
/// Sizes its child to a fraction of the total available space.
///
/// For both its width and height, this render object imposes a tight
/// constraint on its child that is a multiple (typically less than 1.0) of the
/// maximum constraint it received from its parent on that axis. If the factor
/// for a given axis is null, then the constraints from the parent are just
/// passed through instead.
///
/// It then tries to size itself to the size of its child.
class RenderFractionallySizedBox extends RenderProxyBox {
RenderFractionallySizedBox({
RenderBox child,
double widthFactor,
double heightFactor
}) : _widthFactor = widthFactor, _heightFactor = heightFactor, super(child) {
assert(_widthFactor == null || _widthFactor >= 0.0);
assert(_heightFactor == null || _heightFactor >= 0.0);
}
/// If non-null, the factor of the incoming width to use.
///
/// If non-null, the child is given a tight width constraint that is the max
/// incoming width constraint multipled by this factor. If null, the child is
/// given the incoming width constraings.
double get widthFactor => _widthFactor;
double _widthFactor;
void set widthFactor (double value) {
assert(value == null || value >= 0.0);
if (_widthFactor == value)
return;
_widthFactor = value;
markNeedsLayout();
}
/// If non-null, the factor of the incoming height to use.
///
/// If non-null, the child is given a tight height constraint that is the max
/// incoming width constraint multipled by this factor. If null, the child is
/// given the incoming width constraings.
double get heightFactor => _heightFactor;
double _heightFactor;
void set heightFactor (double value) {
assert(value == null || value >= 0.0);
if (_heightFactor == value)
return;
_heightFactor = value;
markNeedsLayout();
}
BoxConstraints _getInnerConstraints(BoxConstraints constraints) {
double minWidth = constraints.minWidth;
double maxWidth = constraints.maxWidth;
if (_widthFactor != null) {
double width = maxWidth * _widthFactor;
minWidth = width;
maxWidth = width;
}
double minHeight = constraints.minHeight;
double maxHeight = constraints.maxHeight;
if (_heightFactor != null) {
double height = maxHeight * _heightFactor;
minHeight = height;
maxHeight = height;
}
return new BoxConstraints(
minWidth: minWidth,
maxWidth: maxWidth,
minHeight: minHeight,
maxHeight: maxHeight
);
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsNormalized);
if (child != null)
return constraints.constrainWidth(child.getMinIntrinsicWidth(_getInnerConstraints(constraints)));
return constraints.constrainWidth(_getInnerConstraints(constraints).constrainWidth(0.0));
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsNormalized);
if (child != null)
return constraints.constrainWidth(child.getMaxIntrinsicWidth(_getInnerConstraints(constraints)));
return constraints.constrainWidth(_getInnerConstraints(constraints).constrainWidth(0.0));
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsNormalized);
if (child != null)
return constraints.constrainHeight(child.getMinIntrinsicHeight(_getInnerConstraints(constraints)));
return constraints.constrainHeight(_getInnerConstraints(constraints).constrainHeight(0.0));
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsNormalized);
if (child != null)
return constraints.constrainHeight(child.getMaxIntrinsicHeight(_getInnerConstraints(constraints)));
return constraints.constrainHeight(_getInnerConstraints(constraints).constrainHeight(0.0));
}
@override
void performLayout() {
if (child != null) {
child.layout(_getInnerConstraints(constraints), parentUsesSize: true);
size = constraints.constrain(child.size);
} else {
size = constraints.constrain(_getInnerConstraints(constraints).constrain(Size.zero));
}
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('widthFactor: ${_widthFactor ?? "pass-through"}');
description.add('heightFactor: ${_heightFactor ?? "pass-through"}');
}
}
/// Attempts to size the child to a specific aspect ratio.
///
/// The render object first tries the largest width permited by the layout
......
......@@ -218,29 +218,13 @@ class RenderPadding extends RenderShiftedBox {
}
}
/// Aligns its child box within itself.
///
/// For example, to align a box at the bottom right, you would pass this box a
/// tight constraint that is bigger than the child's natural size,
/// with an alignment of [const FractionalOffset(1.0, 1.0)].
///
/// By default, sizes to be as big as possible in both axes. If either axis is
/// unconstrained, then in that direction it will be sized to fit the child's
/// dimensions. Using widthFactor and heightFactor you can force this latter
/// behavior in all cases.
class RenderPositionedBox extends RenderShiftedBox {
RenderPositionedBox({
abstract class RenderAligningShiftedBox extends RenderShiftedBox {
RenderAligningShiftedBox({
RenderBox child,
FractionalOffset alignment: const FractionalOffset(0.5, 0.5),
double widthFactor,
double heightFactor
FractionalOffset alignment: const FractionalOffset(0.5, 0.5)
}) : _alignment = alignment,
_widthFactor = widthFactor,
_heightFactor = heightFactor,
super(child) {
assert(alignment != null && alignment.dx != null && alignment.dy != null);
assert(widthFactor == null || widthFactor >= 0.0);
assert(heightFactor == null || heightFactor >= 0.0);
}
/// How to align the child.
......@@ -254,6 +238,9 @@ class RenderPositionedBox extends RenderShiftedBox {
/// with the center of the parent.
FractionalOffset get alignment => _alignment;
FractionalOffset _alignment;
/// Sets the alignment to a new value, and triggers a layout update.
///
/// The new alignment must not be null or have any null properties.
void set alignment (FractionalOffset newAlignment) {
assert(newAlignment != null && newAlignment.dx != null && newAlignment.dy != null);
if (_alignment == newAlignment)
......@@ -262,6 +249,53 @@ class RenderPositionedBox extends RenderShiftedBox {
markNeedsLayout();
}
/// Apply the current [alignment] to the [child].
///
/// Subclasses should call this method if they have a child, to have
/// this class perform the actual alignment. If there is no child,
/// do not call this method.
///
/// This method must be called after the child has been laid out and
/// this object's own size has been set.
void alignChild() {
assert(child != null);
assert(!child.needsLayout);
assert(child.hasSize);
assert(hasSize);
final BoxParentData childParentData = child.parentData;
childParentData.offset = alignment.alongOffset(size - child.size);
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('alignment: $alignment');
}
}
/// Aligns its child box within itself.
///
/// For example, to align a box at the bottom right, you would pass this box a
/// tight constraint that is bigger than the child's natural size,
/// with an alignment of [const FractionalOffset(1.0, 1.0)].
///
/// By default, sizes to be as big as possible in both axes. If either axis is
/// unconstrained, then in that direction it will be sized to fit the child's
/// dimensions. Using widthFactor and heightFactor you can force this latter
/// behavior in all cases.
class RenderPositionedBox extends RenderAligningShiftedBox {
RenderPositionedBox({
RenderBox child,
double widthFactor,
double heightFactor,
FractionalOffset alignment: const FractionalOffset(0.5, 0.5)
}) : _widthFactor = widthFactor,
_heightFactor = heightFactor,
super(child: child, alignment: alignment) {
assert(widthFactor == null || widthFactor >= 0.0);
assert(heightFactor == null || heightFactor >= 0.0);
}
/// If non-null, sets its width to the child's width multipled by this factor.
///
/// Can be both greater and less than 1.0 but must be positive.
......@@ -297,8 +331,7 @@ class RenderPositionedBox extends RenderShiftedBox {
child.layout(constraints.loosen(), parentUsesSize: true);
size = constraints.constrain(new Size(shrinkWrapWidth ? child.size.width * (_widthFactor ?? 1.0) : double.INFINITY,
shrinkWrapHeight ? child.size.height * (_heightFactor ?? 1.0) : double.INFINITY));
final BoxParentData childParentData = child.parentData;
childParentData.offset = _alignment.alongOffset(size - child.size);
alignChild();
} else {
size = constraints.constrain(new Size(shrinkWrapWidth ? 0.0 : double.INFINITY,
shrinkWrapHeight ? 0.0 : double.INFINITY));
......@@ -366,7 +399,8 @@ class RenderPositionedBox extends RenderShiftedBox {
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('alignment: $alignment');
description.add('widthFactor: ${_widthFactor ?? "expand"}');
description.add('heightFactor: ${_heightFactor ?? "expand"}');
}
}
......@@ -391,8 +425,8 @@ class RenderPositionedBox extends RenderShiftedBox {
/// The child is positioned at the top left of the box. To position a smaller
/// child inside a larger parent, use [RenderPositionedBox] and
/// [RenderConstrainedBox] rather than RenderOverflowBox.
class RenderOverflowBox extends RenderShiftedBox {
RenderOverflowBox({
class RenderConstrainedOverflowBox extends RenderAligningShiftedBox {
RenderConstrainedOverflowBox({
RenderBox child,
double minWidth,
double maxWidth,
......@@ -403,8 +437,7 @@ class RenderOverflowBox extends RenderShiftedBox {
_maxWidth = maxWidth,
_minHeight = minHeight,
_maxHeight = maxHeight,
_alignment = alignment,
super(child);
super(child: child, alignment: alignment);
/// The minimum width constraint to give the child. Set this to null (the
/// default) to use the constraint from the parent instead.
......@@ -450,25 +483,6 @@ class RenderOverflowBox extends RenderShiftedBox {
markNeedsLayout();
}
/// How to align the child.
///
/// The x and y values of the alignment control the horizontal and vertical
/// alignment, respectively. An x value of 0.0 means that the left edge of
/// the child is aligned with the left edge of the parent whereas an x value
/// of 1.0 means that the right edge of the child is aligned with the right
/// edge of the parent. Other values interpolate (and extrapolate) linearly.
/// For example, a value of 0.5 means that the center of the child is aligned
/// with the center of the parent.
FractionalOffset get alignment => _alignment;
FractionalOffset _alignment;
void set alignment (FractionalOffset newAlignment) {
assert(newAlignment != null && newAlignment.dx != null && newAlignment.dy != null);
if (_alignment == newAlignment)
return;
_alignment = newAlignment;
markNeedsLayout();
}
BoxConstraints _getInnerConstraints(BoxConstraints constraints) {
return new BoxConstraints(
minWidth: _minWidth ?? constraints.minWidth,
......@@ -514,8 +528,7 @@ class RenderOverflowBox extends RenderShiftedBox {
void performLayout() {
if (child != null) {
child.layout(_getInnerConstraints(constraints), parentUsesSize: true);
final BoxParentData childParentData = child.parentData;
childParentData.offset = _alignment.alongOffset(size - child.size);
alignChild();
}
}
......@@ -526,7 +539,196 @@ class RenderOverflowBox extends RenderShiftedBox {
description.add('maxWidth: ${maxWidth ?? "use parent maxWidth constraint"}');
description.add('minHeight: ${minHeight ?? "use parent minHeight constraint"}');
description.add('maxHeight: ${maxHeight ?? "use parent maxHeight constraint"}');
description.add('alignment: $alignment');
}
}
/// A render box that's a specific size but passes its original constraints
/// through to its child, which will probably overflow.
class RenderSizedOverflowBox extends RenderAligningShiftedBox {
RenderSizedOverflowBox({
RenderBox child,
Size requestedSize,
FractionalOffset alignment: const FractionalOffset(0.5, 0.5)
}) : _requestedSize = requestedSize,
super(child: child, alignment: alignment) {
assert(requestedSize != null);
}
/// The size this render box should attempt to be.
Size get requestedSize => _requestedSize;
Size _requestedSize;
void set requestedSize (Size value) {
assert(value != null);
if (_requestedSize == value)
return;
_requestedSize = value;
markNeedsLayout();
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsNormalized);
return constraints.constrainWidth(_requestedSize.width);
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsNormalized);
return constraints.constrainWidth(_requestedSize.width);
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsNormalized);
return constraints.constrainHeight(_requestedSize.height);
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsNormalized);
return constraints.constrainHeight(_requestedSize.height);
}
@override
double computeDistanceToActualBaseline(TextBaseline baseline) {
if (child != null)
return child.getDistanceToActualBaseline(baseline);
return super.computeDistanceToActualBaseline(baseline);
}
@override
void performLayout() {
size = constraints.constrain(_requestedSize);
if (child != null) {
child.layout(constraints);
alignChild();
}
}
}
/// Sizes its child to a fraction of the total available space.
///
/// For both its width and height, this render object imposes a tight
/// constraint on its child that is a multiple (typically less than 1.0) of the
/// maximum constraint it received from its parent on that axis. If the factor
/// for a given axis is null, then the constraints from the parent are just
/// passed through instead.
///
/// It then tries to size itself to the size of its child.
class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
RenderFractionallySizedOverflowBox({
RenderBox child,
double widthFactor,
double heightFactor,
FractionalOffset alignment: const FractionalOffset(0.5, 0.5)
}) : _widthFactor = widthFactor,
_heightFactor = heightFactor,
super(child: child, alignment: alignment) {
assert(_widthFactor == null || _widthFactor >= 0.0);
assert(_heightFactor == null || _heightFactor >= 0.0);
}
/// If non-null, the factor of the incoming width to use.
///
/// If non-null, the child is given a tight width constraint that is the max
/// incoming width constraint multipled by this factor. If null, the child is
/// given the incoming width constraings.
double get widthFactor => _widthFactor;
double _widthFactor;
void set widthFactor (double value) {
assert(value == null || value >= 0.0);
if (_widthFactor == value)
return;
_widthFactor = value;
markNeedsLayout();
}
/// If non-null, the factor of the incoming height to use.
///
/// If non-null, the child is given a tight height constraint that is the max
/// incoming width constraint multipled by this factor. If null, the child is
/// given the incoming width constraings.
double get heightFactor => _heightFactor;
double _heightFactor;
void set heightFactor (double value) {
assert(value == null || value >= 0.0);
if (_heightFactor == value)
return;
_heightFactor = value;
markNeedsLayout();
}
BoxConstraints _getInnerConstraints(BoxConstraints constraints) {
double minWidth = constraints.minWidth;
double maxWidth = constraints.maxWidth;
if (_widthFactor != null) {
double width = maxWidth * _widthFactor;
minWidth = width;
maxWidth = width;
}
double minHeight = constraints.minHeight;
double maxHeight = constraints.maxHeight;
if (_heightFactor != null) {
double height = maxHeight * _heightFactor;
minHeight = height;
maxHeight = height;
}
return new BoxConstraints(
minWidth: minWidth,
maxWidth: maxWidth,
minHeight: minHeight,
maxHeight: maxHeight
);
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsNormalized);
if (child != null)
return constraints.constrainWidth(child.getMinIntrinsicWidth(_getInnerConstraints(constraints)));
return constraints.constrainWidth(_getInnerConstraints(constraints).constrainWidth(0.0));
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsNormalized);
if (child != null)
return constraints.constrainWidth(child.getMaxIntrinsicWidth(_getInnerConstraints(constraints)));
return constraints.constrainWidth(_getInnerConstraints(constraints).constrainWidth(0.0));
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsNormalized);
if (child != null)
return constraints.constrainHeight(child.getMinIntrinsicHeight(_getInnerConstraints(constraints)));
return constraints.constrainHeight(_getInnerConstraints(constraints).constrainHeight(0.0));
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsNormalized);
if (child != null)
return constraints.constrainHeight(child.getMaxIntrinsicHeight(_getInnerConstraints(constraints)));
return constraints.constrainHeight(_getInnerConstraints(constraints).constrainHeight(0.0));
}
@override
void performLayout() {
if (child != null) {
child.layout(_getInnerConstraints(constraints), parentUsesSize: true);
size = constraints.constrain(child.size);
alignChild();
} else {
size = constraints.constrain(_getInnerConstraints(constraints).constrain(Size.zero));
}
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('widthFactor: ${_widthFactor ?? "pass-through"}');
description.add('heightFactor: ${_heightFactor ?? "pass-through"}');
}
}
......
......@@ -293,7 +293,7 @@ class Transform extends SingleChildRenderObjectWidget {
/// The alignment of the origin, relative to the size of the box.
///
/// This is equivalent to setting an origin based on the size of the box.
/// If it is specificed at the same time as an offset, both are applied.
/// If it is specified at the same time as an offset, both are applied.
final FractionalOffset alignment;
/// Whether to apply the translation when performing hit tests.
......@@ -443,6 +443,16 @@ class Align extends SingleChildRenderObjectWidget {
..widthFactor = widthFactor
..heightFactor = heightFactor;
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('alignment: $alignment');
if (widthFactor != null)
description.add('widthFactor: $widthFactor');
if (heightFactor != null)
description.add('heightFactor: $heightFactor');
}
}
/// Centers its child within itself.
......@@ -610,10 +620,17 @@ class ConstrainedBox extends SingleChildRenderObjectWidget {
/// Sizes itself to a fraction of the total available space.
///
/// See [RenderFractionallySizedBox] for details.
/// See [RenderFractionallySizedOverflowBox] for details.
class FractionallySizedBox extends SingleChildRenderObjectWidget {
FractionallySizedBox({ Key key, this.width, this.height, Widget child })
: super(key: key, child: child);
FractionallySizedBox({
Key key,
this.alignment: const FractionalOffset(0.5, 0.5),
this.width,
this.height,
Widget child
}) : super(key: key, child: child) {
assert(alignment != null && alignment.dx != null && alignment.dy != null);
}
/// If non-null, the factor of the incoming width to use.
///
......@@ -627,15 +644,28 @@ class FractionallySizedBox extends SingleChildRenderObjectWidget {
/// incoming height constraint multipled by this factor.
final double height;
/// How to align the child.
///
/// The x and y values of the alignment control the horizontal and vertical
/// alignment, respectively. An x value of 0.0 means that the left edge of
/// the child is aligned with the left edge of the parent whereas an x value
/// of 1.0 means that the right edge of the child is aligned with the right
/// edge of the parent. Other values interpolate (and extrapolate) linearly.
/// For example, a value of 0.5 means that the center of the child is aligned
/// with the center of the parent.
final FractionalOffset alignment;
@override
RenderFractionallySizedBox createRenderObject(BuildContext context) => new RenderFractionallySizedBox(
RenderFractionallySizedOverflowBox createRenderObject(BuildContext context) => new RenderFractionallySizedOverflowBox(
alignment: alignment,
widthFactor: width,
heightFactor: height
);
@override
void updateRenderObject(BuildContext context, RenderFractionallySizedBox renderObject) {
void updateRenderObject(BuildContext context, RenderFractionallySizedOverflowBox renderObject) {
renderObject
..alignment = alignment
..widthFactor = width
..heightFactor = height;
}
......@@ -643,6 +673,7 @@ class FractionallySizedBox extends SingleChildRenderObjectWidget {
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('alignment: $alignment');
if (width != null)
description.add('width: $width');
if (height != null)
......@@ -657,14 +688,25 @@ class FractionallySizedBox extends SingleChildRenderObjectWidget {
class OverflowBox extends SingleChildRenderObjectWidget {
OverflowBox({
Key key,
this.alignment: const FractionalOffset(0.5, 0.5),
this.minWidth,
this.maxWidth,
this.minHeight,
this.maxHeight,
this.alignment: const FractionalOffset(0.5, 0.5),
Widget child
}) : super(key: key, child: child);
/// How to align the child.
///
/// The x and y values of the alignment control the horizontal and vertical
/// alignment, respectively. An x value of 0.0 means that the left edge of
/// the child is aligned with the left edge of the parent whereas an x value
/// of 1.0 means that the right edge of the child is aligned with the right
/// edge of the parent. Other values interpolate (and extrapolate) linearly.
/// For example, a value of 0.5 means that the center of the child is aligned
/// with the center of the parent.
final FractionalOffset alignment;
/// The minimum width constraint to give the child. Set this to null (the
/// default) to use the constraint from the parent instead.
final double minWidth;
......@@ -681,39 +723,29 @@ class OverflowBox extends SingleChildRenderObjectWidget {
/// default) to use the constraint from the parent instead.
final double maxHeight;
/// How to align the child.
///
/// The x and y values of the alignment control the horizontal and vertical
/// alignment, respectively. An x value of 0.0 means that the left edge of
/// the child is aligned with the left edge of the parent whereas an x value
/// of 1.0 means that the right edge of the child is aligned with the right
/// edge of the parent. Other values interpolate (and extrapolate) linearly.
/// For example, a value of 0.5 means that the center of the child is aligned
/// with the center of the parent.
final FractionalOffset alignment;
@override
RenderOverflowBox createRenderObject(BuildContext context) => new RenderOverflowBox(
RenderConstrainedOverflowBox createRenderObject(BuildContext context) => new RenderConstrainedOverflowBox(
alignment: alignment,
minWidth: minWidth,
maxWidth: maxWidth,
minHeight: minHeight,
maxHeight: maxHeight,
alignment: alignment
maxHeight: maxHeight
);
@override
void updateRenderObject(BuildContext context, RenderOverflowBox renderObject) {
void updateRenderObject(BuildContext context, RenderConstrainedOverflowBox renderObject) {
renderObject
..alignment = alignment
..minWidth = minWidth
..maxWidth = maxWidth
..minHeight = minHeight
..maxHeight = maxHeight
..alignment = alignment;
..maxHeight = maxHeight;
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('alignment: $alignment');
if (minWidth != null)
description.add('minWidth: $minWidth');
if (maxWidth != null)
......@@ -726,17 +758,49 @@ class OverflowBox extends SingleChildRenderObjectWidget {
}
class SizedOverflowBox extends SingleChildRenderObjectWidget {
SizedOverflowBox({ Key key, this.size, Widget child })
: super(key: key, child: child);
SizedOverflowBox({
Key key,
this.alignment: const FractionalOffset(0.5, 0.5),
this.size,
Widget child
}) : super(key: key, child: child) {
assert(alignment != null && alignment.dx != null && alignment.dy != null);
}
/// How to align the child.
///
/// The x and y values of the alignment control the horizontal and vertical
/// alignment, respectively. An x value of 0.0 means that the left edge of
/// the child is aligned with the left edge of the parent whereas an x value
/// of 1.0 means that the right edge of the child is aligned with the right
/// edge of the parent. Other values interpolate (and extrapolate) linearly.
/// For example, a value of 0.5 means that the center of the child is aligned
/// with the center of the parent.
final FractionalOffset alignment;
final Size size;
@override
RenderSizedOverflowBox createRenderObject(BuildContext context) => new RenderSizedOverflowBox(requestedSize: size);
RenderSizedOverflowBox createRenderObject(BuildContext context) {
return new RenderSizedOverflowBox(
alignment: alignment,
requestedSize: size
);
}
@override
void updateRenderObject(BuildContext context, RenderSizedOverflowBox renderObject) {
renderObject.requestedSize = size;
renderObject
..alignment = alignment
..requestedSize = size;
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('alignment: $alignment');
if (size != null)
description.add('size: $size');
}
}
......
......@@ -13,7 +13,7 @@ void main() {
root = new RenderPositionedBox(
child: new RenderConstrainedBox(
additionalConstraints: new BoxConstraints.tight(const Size(200.0, 200.0)),
child: test = new RenderFractionallySizedBox(
child: test = new RenderFractionallySizedOverflowBox(
widthFactor: 2.0,
heightFactor: 0.5,
child: leaf = new RenderConstrainedBox(
......
......@@ -28,7 +28,7 @@ void main() {
root = new RenderPositionedBox(
child: new RenderCustomPaint(
child: child = new RenderOverflowBox(
child: child = new RenderConstrainedOverflowBox(
child: text = new RenderParagraph(new TextSpan(text: 'Hello World')),
maxHeight: height1 / 2.0,
alignment: const FractionalOffset(0.0, 0.0)
......
......@@ -42,6 +42,7 @@ void main() {
maxHeight: 4.0
).debugFillDescription(description);
expect(description, [
'alignment: FractionalOffset(0.5, 0.5)',
'minWidth: 1.0',
'maxWidth: 2.0',
'minHeight: 3.0',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment