Commit 7e1e9ef3 authored by Adam Barth's avatar Adam Barth

Add dartdoc for RenderBox

parent 958de183
...@@ -203,13 +203,18 @@ class BoxConstraints extends Constraints { ...@@ -203,13 +203,18 @@ class BoxConstraints extends Constraints {
String toString() => "BoxConstraints($minWidth<=w<$maxWidth, $minHeight<=h<$maxHeight)"; String toString() => "BoxConstraints($minWidth<=w<$maxWidth, $minHeight<=h<$maxHeight)";
} }
/// A hit test entry used by [RenderBox]
class BoxHitTestEntry extends HitTestEntry { class BoxHitTestEntry extends HitTestEntry {
const BoxHitTestEntry(HitTestTarget target, this.localPosition) : super(target); const BoxHitTestEntry(HitTestTarget target, this.localPosition) : super(target);
/// The position of the hit test in the local coordinates of [target]
final Point localPosition; final Point localPosition;
} }
/// Parent data used by [RenderBox] and its subclasses
class BoxParentData extends ParentData { class BoxParentData extends ParentData {
Point _position = Point.origin; Point _position = Point.origin;
/// The point at which to paint the child in the parent's coordinate system
Point get position => _position; Point get position => _position;
void set position(Point value) { void set position(Point value) {
assert(RenderObject.debugDoingLayout); assert(RenderObject.debugDoingLayout);
...@@ -218,6 +223,24 @@ class BoxParentData extends ParentData { ...@@ -218,6 +223,24 @@ class BoxParentData extends ParentData {
String toString() => 'position=$position'; String toString() => 'position=$position';
} }
/// A render object in a 2D cartesian coordinate system
///
/// The size of each box is expressed as a width and a height. Each box has its
/// own coordinate system in which its upper left corner is placed at (0, 0).
/// The lower right corner of the box is therefore at (width, height). The box
/// contains all the points including the upper left corner and extending to,
/// but not including, the lower right corner.
///
/// Box layout is performed by passing a [BoxConstraints] object down the tree.
/// The box constraints establish a min and max value for the child's width
/// and height. In determining its size, the child must respect the constraints
/// given to it by its parent.
///
/// This protocol is sufficient for expressing a number of common box layout
/// data flows. For example, to implement a width-in-height-out data flow, call
/// your child's [layout] function with a set of box constraints with a tight
/// width value (and pass true for parentUsesSize). After the child determines
/// its height, use the child's height to determine your size.
abstract class RenderBox extends RenderObject { abstract class RenderBox extends RenderObject {
void setupParentData(RenderObject child) { void setupParentData(RenderObject child) {
...@@ -225,29 +248,38 @@ abstract class RenderBox extends RenderObject { ...@@ -225,29 +248,38 @@ abstract class RenderBox extends RenderObject {
child.parentData = new BoxParentData(); child.parentData = new BoxParentData();
} }
// getMinIntrinsicWidth() should return the minimum width that this box could /// Returns the minimum width that this box could be without failing to paint
// be without failing to render its contents within itself. /// its contents within itself
///
/// Override in subclasses that implement [performLayout].
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(BoxConstraints constraints) {
return constraints.constrainWidth(0.0); return constraints.constrainWidth(0.0);
} }
// getMaxIntrinsicWidth() should return the smallest width beyond which /// Returns the smallest width beyond which increasing the width never
// increasing the width never decreases the height. /// decreases the height
///
/// Override in subclasses that implement [performLayout].
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(BoxConstraints constraints) {
return constraints.constrainWidth(0.0); return constraints.constrainWidth(0.0);
} }
// getMinIntrinsicHeight() should return the minimum height that this box could /// Return the minimum height that this box could be without failing to render
// be without failing to render its contents within itself. /// its contents within itself.
///
/// Override in subclasses that implement [performLayout].
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(BoxConstraints constraints) {
return constraints.constrainHeight(0.0); return constraints.constrainHeight(0.0);
} }
// getMaxIntrinsicHeight should return the smallest height beyond which /// Returns the smallest height beyond which increasing the height never
// increasing the height never decreases the width. /// decreases the width.
// If the layout algorithm used is width-in-height-out, i.e. the height ///
// depends on the width and not vice versa, then this will return the same /// If the layout algorithm used is width-in-height-out, i.e. the height
// as getMinIntrinsicHeight(). /// depends on the width and not vice versa, then this will return the same
/// as getMinIntrinsicHeight().
///
/// Override in subclasses that implement [performLayout].
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(BoxConstraints constraints) {
return constraints.constrainHeight(0.0); return constraints.constrainHeight(0.0);
} }
...@@ -259,17 +291,20 @@ abstract class RenderBox extends RenderObject { ...@@ -259,17 +291,20 @@ abstract class RenderBox extends RenderObject {
_debugDoingBaseline = value; _debugDoingBaseline = value;
return true; return true;
} }
// getDistanceToBaseline() returns the distance from the
// y-coordinate of the position of the box to the y-coordinate of /// Returns the distance from the y-coordinate of the position of the box to
// the first given baseline in the box's contents. This is used by /// the y-coordinate of the first given baseline in the box's contents.
// certain layout models to align adjacent boxes on a common ///
// baseline, regardless of padding, font size differences, etc. If /// Used by certain layout models to align adjacent boxes on a common
// there is no baseline, and the 'onlyReal' argument was not set to /// baseline, regardless of padding, font size differences, etc. If there is
// true, then it returns the distance from the y-coordinate of the /// no baseline, this function returns the distance from the y-coordinate of
// position of the box to the y-coordinate of the bottom of the box, /// the position of the box to the y-coordinate of the bottom of the box
// i.e., the height of the box. Only call this after layout has been /// (i.e., the height of the box) unless the the caller passes true
// performed. You are only allowed to call this from the parent of /// for `onlyReal`, in which case the function returns null.
// this node during that parent's performLayout() or paint(). ///
/// Only call this function calling [layout] on this box. You are only
/// allowed to call this from the parent of this box during that parent's
/// [performLayout] or [paint] functions.
double getDistanceToBaseline(TextBaseline baseline, { bool onlyReal: false }) { double getDistanceToBaseline(TextBaseline baseline, { bool onlyReal: false }) {
assert(!needsLayout); assert(!needsLayout);
assert(!_debugDoingBaseline); assert(!_debugDoingBaseline);
...@@ -291,10 +326,12 @@ abstract class RenderBox extends RenderObject { ...@@ -291,10 +326,12 @@ abstract class RenderBox extends RenderObject {
return size.height; return size.height;
return result; return result;
} }
// getDistanceToActualBaseline() must only be called from
// getDistanceToBaseline() and computeDistanceToActualBaseline(). Do /// Calls [computeDistanceToActualBaseline] and caches the result.
// not call it directly from outside those two methods. It just ///
// calls computeDistanceToActualBaseline() and caches the result. /// This function must only be called from [getDistanceToBaseline] and
/// [computeDistanceToActualBaseline]. Do not call this function directly from
/// outside those two methods.
double getDistanceToActualBaseline(TextBaseline baseline) { double getDistanceToActualBaseline(TextBaseline baseline) {
assert(_debugDoingBaseline); assert(_debugDoingBaseline);
_ancestorUsesBaseline = true; _ancestorUsesBaseline = true;
...@@ -303,21 +340,25 @@ abstract class RenderBox extends RenderObject { ...@@ -303,21 +340,25 @@ abstract class RenderBox extends RenderObject {
_cachedBaselines.putIfAbsent(baseline, () => computeDistanceToActualBaseline(baseline)); _cachedBaselines.putIfAbsent(baseline, () => computeDistanceToActualBaseline(baseline));
return _cachedBaselines[baseline]; return _cachedBaselines[baseline];
} }
// computeDistanceToActualBaseline() should return the distance from
// the y-coordinate of the position of the box to the y-coordinate /// Returns the distance from the y-coordinate of the position of the box to
// of the first given baseline in the box's contents, if any, or /// the y-coordinate of the first given baseline in the box's contents, if
// null otherwise. This is the method that you should override in /// any, or null otherwise.
// subclasses. This method (computeDistanceToActualBaseline()) ///
// should not be called directly. Use getDistanceToBaseline() if you /// Do not call this function directly. Instead, call [getDistanceToBaseline]
// need to know the baseline of a child from performLayout(). If you /// if you need to know the baseline of a child from an invocation of
// need the baseline during paint, cache it during performLayout(). /// [performLayout] or [paint] and call [getDistanceToActualBaseline] if you
// Use getDistanceToActualBaseline() if you are implementing /// are implementing [computeDistanceToActualBaseline] and need to defer to a
// computeDistanceToActualBaseline() and need to defer to a child. /// child.
///
/// Subclasses should override this function to supply the distances to their
/// baselines.
double computeDistanceToActualBaseline(TextBaseline baseline) { double computeDistanceToActualBaseline(TextBaseline baseline) {
assert(_debugDoingBaseline); assert(_debugDoingBaseline);
return null; return null;
} }
/// The box constraints most recently received from the parent
BoxConstraints get constraints => super.constraints; BoxConstraints get constraints => super.constraints;
bool debugDoesMeetConstraints() { bool debugDoesMeetConstraints() {
assert(constraints != null); assert(constraints != null);
...@@ -363,6 +404,15 @@ abstract class RenderBox extends RenderObject { ...@@ -363,6 +404,15 @@ abstract class RenderBox extends RenderObject {
assert(sizedByParent); assert(sizedByParent);
} }
/// Determines the set of render objects located at the given position
///
/// Returns true if the given point is contained in this render object or one
/// of its descendants. Adds any render objects that contain the point to the
/// given hit test result.
///
/// The caller is responsible for transforming [position] into the local
/// coordinate space of the callee. The callee is responsible for checking
/// whether the given position is within its bounds.
bool hitTest(HitTestResult result, { Point position }) { bool hitTest(HitTestResult result, { Point position }) {
if (position.x >= 0.0 && position.x < _size.width && if (position.x >= 0.0 && position.x < _size.width &&
position.y >= 0.0 && position.y < _size.height) { position.y >= 0.0 && position.y < _size.height) {
...@@ -372,6 +422,13 @@ abstract class RenderBox extends RenderObject { ...@@ -372,6 +422,13 @@ abstract class RenderBox extends RenderObject {
} }
return false; return false;
} }
/// Override this function to check whether any children are located at the
/// given position
///
/// Typically children should be hit tested in reverse paint order so that
/// hit tests at locations where children overlap hit the child that is
/// visually "on top" (i.e., paints later).
void hitTestChildren(HitTestResult result, { Point position }) { } void hitTestChildren(HitTestResult result, { Point position }) { }
// TODO(ianh): move size up to before constraints // TODO(ianh): move size up to before constraints
...@@ -379,6 +436,17 @@ abstract class RenderBox extends RenderObject { ...@@ -379,6 +436,17 @@ abstract class RenderBox extends RenderObject {
// Size size = Size.zero; // Size size = Size.zero;
// In debug builds, however: // In debug builds, however:
Size _size = Size.zero; Size _size = Size.zero;
/// The size of this render box computed during layout
///
/// This value is stale whenever this object is marked as needing layout.
/// During [performLayout], do not read the size of a child unless you pass
/// true for parentUsesSize when calling the child's [layout] function.
///
/// The size of a box should be set only during the box's [performLayout] or
/// [performResize] functions. If you wish to change the size of a box outside
/// of those functins, call [markNeedsLayout] instead to schedule a layout of
/// the box.
Size get size { Size get size {
if (_size is _DebugSize) { if (_size is _DebugSize) {
final _DebugSize _size = this._size; // TODO(ianh): Remove this once the analyzer is cleverer final _DebugSize _size = this._size; // TODO(ianh): Remove this once the analyzer is cleverer
...@@ -405,6 +473,12 @@ abstract class RenderBox extends RenderObject { ...@@ -405,6 +473,12 @@ abstract class RenderBox extends RenderObject {
assert(debugDoesMeetConstraints()); assert(debugDoesMeetConstraints());
} }
/// Multiply the transform from the parent's coordinate system to this box's
/// coordinate system into the given transform
///
/// This function is used to convert coordinate systems between boxes.
/// Subclasses that apply transforms during painting should override this
/// function to factor those transforms into the calculation.
void applyPaintTransform(Matrix4 transform) { void applyPaintTransform(Matrix4 transform) {
if (parentData is BoxParentData) { if (parentData is BoxParentData) {
Point position = (parentData as BoxParentData).position; Point position = (parentData as BoxParentData).position;
...@@ -418,6 +492,8 @@ abstract class RenderBox extends RenderObject { ...@@ -418,6 +492,8 @@ abstract class RenderBox extends RenderObject {
return new Point(transformed3.x, transformed3.y); return new Point(transformed3.x, transformed3.y);
} }
/// Convert the given point from the global coodinate system to the local
/// coordinate system for this box
Point globalToLocal(Point point) { Point globalToLocal(Point point) {
assert(attached); assert(attached);
Matrix4 transform = new Matrix4.identity(); Matrix4 transform = new Matrix4.identity();
...@@ -431,6 +507,8 @@ abstract class RenderBox extends RenderObject { ...@@ -431,6 +507,8 @@ abstract class RenderBox extends RenderObject {
return _transformPoint(transform, point); return _transformPoint(transform, point);
} }
/// Convert the given point from the local coordiante system for this box to
/// the global coordinate sytem
Point localToGlobal(Point point) { Point localToGlobal(Point point) {
List <RenderObject> renderers = <RenderObject>[]; List <RenderObject> renderers = <RenderObject>[];
for (RenderObject renderer = this; renderer != null; renderer = renderer.parent) for (RenderObject renderer = this; renderer != null; renderer = renderer.parent)
...@@ -441,7 +519,21 @@ abstract class RenderBox extends RenderObject { ...@@ -441,7 +519,21 @@ abstract class RenderBox extends RenderObject {
return _transformPoint(transform, point); return _transformPoint(transform, point);
} }
/// Returns a rectangle that contains all the pixels painted by this box
///
/// The paint bounds can be larger or smaller than [size], which is the amount
/// of space this box takes up during layout. For example, if this box casts a
/// shadow, that shadow might extend beyond the space allocated to this box
/// during layout.
///
/// The paint bounds are used to size the buffers into which this box paints.
/// If the box attempts to paints outside its paint bounds, there might not be
/// enough memory allocated to represent the box's visual appearance, which
/// can lead to undefined behavior.
///
/// The returned paint bounds are in the local coordinate system of this box.
Rect get paintBounds => Point.origin & size; Rect get paintBounds => Point.origin & size;
void debugPaint(PaintingContext context, Offset offset) { void debugPaint(PaintingContext context, Offset offset) {
if (debugPaintSizeEnabled) if (debugPaintSizeEnabled)
debugPaintSize(context, offset); debugPaintSize(context, offset);
...@@ -483,13 +575,17 @@ abstract class RenderBox extends RenderObject { ...@@ -483,13 +575,17 @@ abstract class RenderBox extends RenderObject {
String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}size: ${size}\n'; String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}size: ${size}\n';
} }
/// A mixin that provides useful default behaviors for boxes with children managed by the [ContainerRenderObjectMixin] mixin
// HELPER METHODS FOR RENDERBOX CONTAINERS ///
/// By convention, this class doesn't override any members of the superclass.
/// Instead, it provides helpful functions that subclasses can call as
/// appropriate.
abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, ParentDataType extends ContainerParentDataMixin<ChildType>> implements ContainerRenderObjectMixin<ChildType, ParentDataType> { abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, ParentDataType extends ContainerParentDataMixin<ChildType>> implements ContainerRenderObjectMixin<ChildType, ParentDataType> {
// This class, by convention, doesn't override any members of the superclass. /// Returns the baseline of the first child with a baseline
// It only provides helper functions that subclasses can call. ///
/// Useful when the children are displayed vertically in the same order they
/// appear in the child list.
double defaultComputeDistanceToFirstActualBaseline(TextBaseline baseline) { double defaultComputeDistanceToFirstActualBaseline(TextBaseline baseline) {
assert(!needsLayout); assert(!needsLayout);
RenderBox child = firstChild; RenderBox child = firstChild;
...@@ -503,6 +599,10 @@ abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare ...@@ -503,6 +599,10 @@ abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare
return null; return null;
} }
/// Returns the minimum baseline value among every child
///
/// Useful when the vertical position of the children isn't determined by the
/// order in the child list.
double defaultComputeDistanceToHighestActualBaseline(TextBaseline baseline) { double defaultComputeDistanceToHighestActualBaseline(TextBaseline baseline) {
assert(!needsLayout); assert(!needsLayout);
double result; double result;
...@@ -522,6 +622,10 @@ abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare ...@@ -522,6 +622,10 @@ abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare
return result; return result;
} }
/// Performs a hit test on each child by walking the child list backwards
///
/// Stops walking once after the first child reports that it contains the
/// given point. Returns whether any children contain the given point.
bool defaultHitTestChildren(HitTestResult result, { Point position }) { bool defaultHitTestChildren(HitTestResult result, { Point position }) {
// the x, y parameters have the top left of the node's box as the origin // the x, y parameters have the top left of the node's box as the origin
ChildType child = lastChild; ChildType child = lastChild;
...@@ -536,6 +640,7 @@ abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare ...@@ -536,6 +640,7 @@ abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare
return false; return false;
} }
/// Paints each child by walking the child list forwards
void defaultPaint(PaintingContext context, Offset offset) { void defaultPaint(PaintingContext context, Offset offset) {
RenderBox child = firstChild; RenderBox child = firstChild;
while (child != null) { while (child != null) {
......
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