diff --git a/sky/packages/sky/lib/rendering.dart b/sky/packages/sky/lib/rendering.dart index 24e7b460540..52a57e8e8c1 100644 --- a/sky/packages/sky/lib/rendering.dart +++ b/sky/packages/sky/lib/rendering.dart @@ -20,6 +20,7 @@ export 'src/rendering/image.dart'; export 'src/rendering/layer.dart'; export 'src/rendering/node.dart'; export 'src/rendering/object.dart'; +export 'src/rendering/overflow.dart'; export 'src/rendering/paragraph.dart'; export 'src/rendering/proxy_box.dart'; export 'src/rendering/shifted_box.dart'; diff --git a/sky/packages/sky/lib/src/rendering/overflow.dart b/sky/packages/sky/lib/src/rendering/overflow.dart new file mode 100644 index 00000000000..7090f44b556 --- /dev/null +++ b/sky/packages/sky/lib/src/rendering/overflow.dart @@ -0,0 +1,170 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'box.dart'; +import 'object.dart'; + +export 'package:flutter/src/painting/box_painter.dart'; + +/// A render object that imposes different constraints on its child than it gets +/// from its parent, possibly allowing the child to overflow the parent. +/// +/// A render overflow box proxies most functions in the render box protocol to +/// its child, except that when laying out its child, it passes constraints +/// based on the minWidth, maxWidth, minHeight, and maxHeight fields instead of +/// just passing the parent's constraints in. Specifically, it overrides any of +/// the equivalent fields on the constraints given by the parent with the +/// constraints given by these fields for each such field that is not null. It +/// then sizes itself based on the parent's constraints' maxWidth and maxHeight, +/// ignoring the child's dimensions. +/// +/// For example, if you wanted a box to always render 50 pixels high, regardless +/// of where it was rendered, you would wrap it in a RenderOverflow with +/// minHeight and maxHeight set to 50.0. Generally speaking, to avoid confusing +/// behaviour around hit testing, a RenderOverflowBox should usually be wrapped +/// in a RenderClipRect. +/// +/// 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 RenderBox with RenderObjectWithChildMixin { + RenderOverflowBox({ + RenderBox child, + double minWidth, + double maxWidth, + double minHeight, + double maxHeight + }) : _minWidth = minWidth, _maxWidth = maxWidth, _minHeight = minHeight, _maxHeight = maxHeight { + this.child = child; + } + + /// The minimum width constraint to give the child. Set this to null (the + /// default) to use the constraint from the parent instead. + double get minWidth => _minWidth; + double _minWidth; + void set minWidth (double value) { + if (_minWidth == value) + return; + _minWidth = value; + markNeedsLayout(); + } + + /// The maximum width constraint to give the child. Set this to null (the + /// default) to use the constraint from the parent instead. + double get maxWidth => _maxWidth; + double _maxWidth; + void set maxWidth (double value) { + if (_maxWidth == value) + return; + _maxWidth = value; + markNeedsLayout(); + } + + /// The minimum height constraint to give the child. Set this to null (the + /// default) to use the constraint from the parent instead. + double get minHeight => _minHeight; + double _minHeight; + void set minHeight (double value) { + if (_minHeight == value) + return; + _minHeight = value; + markNeedsLayout(); + } + + /// The maximum height constraint to give the child. Set this to null (the + /// default) to use the constraint from the parent instead. + double get maxHeight => _maxHeight; + double _maxHeight; + void set maxHeight (double value) { + if (_maxHeight == value) + return; + _maxHeight = value; + markNeedsLayout(); + } + + BoxConstraints _getInnerConstraints(BoxConstraints constraints) { + return new BoxConstraints( + minWidth: _minWidth ?? constraints.minWidth, + maxWidth: _maxWidth ?? constraints.maxWidth, + minHeight: _minHeight ?? constraints.minHeight, + maxHeight: _maxHeight ?? constraints.maxHeight + ); + } + + double getMinIntrinsicWidth(BoxConstraints constraints) { + return constraints.constrainWidth(); + } + + double getMaxIntrinsicWidth(BoxConstraints constraints) { + return constraints.constrainWidth(); + } + + double getMinIntrinsicHeight(BoxConstraints constraints) { + return constraints.constrainHeight(); + } + + double getMaxIntrinsicHeight(BoxConstraints constraints) { + return constraints.constrainHeight(); + } + + bool get sizedByParent => true; + + void performResize() { + size = constraints.biggest; + } + + void performLayout() { + if (child != null) + child.layout(_getInnerConstraints(constraints)); + } + + void hitTestChildren(HitTestResult result, { Point position }) { + if (child != null) + child.hitTest(result, position: position); + else + super.hitTestChildren(result, position: position); + } + + void paint(PaintingContext context, Offset offset) { + if (child != null) + context.paintChild(child, offset.toPoint()); + } + + String debugDescribeSettings(String prefix) { + return '${super.debugDescribeSettings(prefix)}' + + '${prefix}minWidth: ${minWidth ?? "use parent minWidth constraint"}\n' + + '${prefix}maxWidth: ${maxWidth ?? "use parent maxWidth constraint"}\n' + + '${prefix}minHeight: ${minHeight ?? "use parent minHeight constraint"}\n' + + '${prefix}maxHeight: ${maxHeight ?? "use parent maxHeight constraint"}\n'; + } +} + + +/// 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. +class RenderOffStage extends RenderBox with RenderObjectWithChildMixin { + RenderOffStage({ RenderBox child }) { + this.child = child; + } + + double getMinIntrinsicWidth(BoxConstraints constraints) => constraints.minWidth; + double getMaxIntrinsicWidth(BoxConstraints constraints) => constraints.minWidth; + double getMinIntrinsicHeight(BoxConstraints constraints) => constraints.minHeight; + double getMaxIntrinsicHeight(BoxConstraints constraints) => constraints.minHeight; + + bool get sizedByParent => true; + + void performResize() { + size = constraints.smallest; + } + + void performLayout() { + if (child != null) + child.layout(constraints); + } + + bool hitTest(HitTestResult result, { Point position }) => false; + void paint(PaintingContext context, Offset offset) { } +} diff --git a/sky/packages/sky/lib/src/rendering/proxy_box.dart b/sky/packages/sky/lib/src/rendering/proxy_box.dart index a0456d57e07..b98ba838a09 100644 --- a/sky/packages/sky/lib/src/rendering/proxy_box.dart +++ b/sky/packages/sky/lib/src/rendering/proxy_box.dart @@ -239,125 +239,6 @@ class RenderFractionallySizedBox extends RenderProxyBox { } } -/// A render object that imposes different constraints on its child than it gets -/// from its parent, possibly allowing the child to overflow the parent. -/// -/// A render overflow box proxies most functions in the render box protocol to -/// its child, except that when laying out its child, it passes constraints -/// based on the minWidth, maxWidth, minHeight, and maxHeight fields instead of -/// just passing the parent's constraints in. Specifically, it overrides any of -/// the equivalent fields on the constraints given by the parent with the -/// constraints given by these fields for each such field that is not null. It -/// then sizes itself based on the parent's constraints' maxWidth and maxHeight, -/// ignoring the child's dimensions. -/// -/// For example, if you wanted a box to always render 50 pixels high, regardless -/// of where it was rendered, you would wrap it in a RenderOverflow with -/// minHeight and maxHeight set to 50.0. Generally speaking, to avoid confusing -/// behaviour around hit testing, a RenderOverflowBox should usually be wrapped -/// in a RenderClipRect. -/// -/// 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 RenderProxyBox { - RenderOverflowBox({ - RenderBox child, - double minWidth, - double maxWidth, - double minHeight, - double maxHeight - }) : _minWidth = minWidth, _maxWidth = maxWidth, _minHeight = minHeight, _maxHeight = maxHeight, super(child); - - /// The minimum width constraint to give the child. Set this to null (the - /// default) to use the constraint from the parent instead. - double get minWidth => _minWidth; - double _minWidth; - void set minWidth (double value) { - if (_minWidth == value) - return; - _minWidth = value; - markNeedsLayout(); - } - - /// The maximum width constraint to give the child. Set this to null (the - /// default) to use the constraint from the parent instead. - double get maxWidth => _maxWidth; - double _maxWidth; - void set maxWidth (double value) { - if (_maxWidth == value) - return; - _maxWidth = value; - markNeedsLayout(); - } - - /// The minimum height constraint to give the child. Set this to null (the - /// default) to use the constraint from the parent instead. - double get minHeight => _minHeight; - double _minHeight; - void set minHeight (double value) { - if (_minHeight == value) - return; - _minHeight = value; - markNeedsLayout(); - } - - /// The maximum height constraint to give the child. Set this to null (the - /// default) to use the constraint from the parent instead. - double get maxHeight => _maxHeight; - double _maxHeight; - void set maxHeight (double value) { - if (_maxHeight == value) - return; - _maxHeight = value; - markNeedsLayout(); - } - - BoxConstraints _getInnerConstraints(BoxConstraints constraints) { - return new BoxConstraints( - minWidth: _minWidth ?? constraints.minWidth, - maxWidth: _maxWidth ?? constraints.maxWidth, - minHeight: _minHeight ?? constraints.minHeight, - maxHeight: _maxHeight ?? constraints.maxHeight - ); - } - - double getMinIntrinsicWidth(BoxConstraints constraints) { - return constraints.constrainWidth(); - } - - double getMaxIntrinsicWidth(BoxConstraints constraints) { - return constraints.constrainWidth(); - } - - double getMinIntrinsicHeight(BoxConstraints constraints) { - return constraints.constrainHeight(); - } - - double getMaxIntrinsicHeight(BoxConstraints constraints) { - return constraints.constrainHeight(); - } - - bool get sizedByParent => true; - - void performResize() { - size = constraints.biggest; - } - - void performLayout() { - if (child != null) - child.layout(_getInnerConstraints(constraints)); - } - - String debugDescribeSettings(String prefix) { - return '${super.debugDescribeSettings(prefix)}' + - '${prefix}minWidth: ${minWidth ?? "use parent minWidth constraint"}\n' + - '${prefix}maxWidth: ${maxWidth ?? "use parent maxWidth constraint"}\n' + - '${prefix}minHeight: ${minHeight ?? "use parent minHeight constraint"}\n' + - '${prefix}maxHeight: ${maxHeight ?? "use parent maxHeight constraint"}\n'; - } -} - /// Forces child to layout at a specific aspect ratio /// /// The width of this render object is the largest width permited by the layout diff --git a/sky/packages/sky/lib/src/widgets/basic.dart b/sky/packages/sky/lib/src/widgets/basic.dart index f048dfe5200..8e21acc9853 100644 --- a/sky/packages/sky/lib/src/widgets/basic.dart +++ b/sky/packages/sky/lib/src/widgets/basic.dart @@ -346,6 +346,13 @@ class OverflowBox extends OneChildRenderObjectWidget { } } +class OffStage extends OneChildRenderObjectWidget { + OffStage({ Key key, Widget child }) + : super(key: key, child: child); + + RenderOffStage createRenderObject() => new RenderOffStage(); +} + class AspectRatio extends OneChildRenderObjectWidget { AspectRatio({ Key key, this.aspectRatio, Widget child }) : super(key: key, child: child) {