Commit 0f4d3765 authored by Adam Barth's avatar Adam Barth

Add dartdoc to RenderBlock and RenderFlex

parent 161789db
......@@ -8,19 +8,32 @@ import 'package:sky/src/rendering/box.dart';
import 'package:sky/src/rendering/object.dart';
import 'package:vector_math/vector_math.dart';
/// Parent data for use with [RenderBlockBase]
class BlockParentData extends BoxParentData with ContainerParentDataMixin<RenderBox> { }
enum BlockDirection { horizontal, vertical }
/// The direction in which the block should lay out
enum BlockDirection {
/// Children are arranged horizontally, from left to right
horizontal,
/// Children are arranged vertically, from top to bottom
vertical
}
typedef double _ChildSizingFunction(RenderBox child, BoxConstraints constraints);
typedef double _Constrainer(double value);
/// Implements the block layout algorithm
///
/// In block layout, children are arranged linearly along the main axis (either
/// horizontally or vertically). In the cross axis, children are stretched to
/// match the block's cross-axis extent. In the main axis, children are given
/// unlimited space and the block expands its main axis to contain all its
/// children. Because blocks expand in the main axis, blocks must be given
/// unlimited space in the main axis, typically by being contained in a
/// viewport with a scrolling direction that matches the block's main axis.
abstract class RenderBlockBase extends RenderBox with ContainerRenderObjectMixin<RenderBox, BlockParentData>,
RenderBoxContainerDefaultsMixin<RenderBox, BlockParentData> {
// lays out RenderBox children in a vertical stack
// uses the maximum width provided by the parent
RenderBlockBase({
List<RenderBox> children,
BlockDirection direction: BlockDirection.vertical,
......@@ -35,8 +48,9 @@ abstract class RenderBlockBase extends RenderBox with ContainerRenderObjectMixin
child.parentData = new BlockParentData();
}
BlockDirection _direction;
/// The direction to use as the main axis
BlockDirection get direction => _direction;
BlockDirection _direction;
void set direction (BlockDirection value) {
if (_direction != value) {
_direction = value;
......@@ -44,8 +58,9 @@ abstract class RenderBlockBase extends RenderBox with ContainerRenderObjectMixin
}
}
double _itemExtent;
/// If non-null, forces children to be exactly this large in the main axis
double get itemExtent => _itemExtent;
double _itemExtent;
void set itemExtent(double value) {
if (value != _itemExtent) {
_itemExtent = value;
......@@ -53,8 +68,9 @@ abstract class RenderBlockBase extends RenderBox with ContainerRenderObjectMixin
}
}
double _minExtent;
/// Forces the block to be at least this large in the main-axis
double get minExtent => _minExtent;
double _minExtent;
void set minExtent(double value) {
if (value != _minExtent) {
_minExtent = value;
......@@ -62,6 +78,7 @@ abstract class RenderBlockBase extends RenderBox with ContainerRenderObjectMixin
}
}
/// Whether the main axis is vertical
bool get isVertical => _direction == BlockDirection.vertical;
BoxConstraints _getInnerConstraints(BoxConstraints constraints) {
......@@ -102,6 +119,7 @@ abstract class RenderBlockBase extends RenderBox with ContainerRenderObjectMixin
String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}direction: ${direction}\n';
}
/// A block layout with a concrete set of children
class RenderBlock extends RenderBlockBase {
RenderBlock({
......@@ -194,21 +212,21 @@ class RenderBlock extends RenderBlockBase {
}
/// A block layout whose children depend on its layout
///
/// This class invokes a callbacks for layout and intrinsic dimensions. The main
/// [callback] (constructor argument and property) is expected to modify the
/// element's child list. The regular block layout algorithm is then applied to
/// the children. The intrinsic dimension callbacks are called to determine
/// intrinsic dimensions; if no value can be returned, they should not be set
/// or, if set, should return null.
class RenderBlockViewport extends RenderBlockBase {
// This class invokes a callbacks for layout and intrinsic
// dimensions. The main callback (constructor argument and property
// called "callback") is expected to modify the element's child
// list. The regular block layout algorithm is then applied to the
// children. The intrinsic dimension callbacks are called to
// determine intrinsic dimensions; if no value can be returned, they
// should not be set or, if set, should return null.
RenderBlockViewport({
LayoutCallback callback,
DimensionCallback totalExtentCallback,
DimensionCallback maxCrossAxisDimensionCallback,
DimensionCallback minCrossAxisDimensionCallback,
ExtentCallback totalExtentCallback,
ExtentCallback maxCrossAxisDimensionCallback,
ExtentCallback minCrossAxisDimensionCallback,
BlockDirection direction: BlockDirection.vertical,
double itemExtent,
double minExtent: 0.0,
......@@ -216,16 +234,19 @@ class RenderBlockViewport extends RenderBlockBase {
List<RenderBox> children
}) : _callback = callback,
_totalExtentCallback = totalExtentCallback,
_maxCrossAxisDimensionCallback = maxCrossAxisDimensionCallback,
_minCrossAxisDimensionCallback = minCrossAxisDimensionCallback,
_maxCrossAxisExtentCallback = maxCrossAxisDimensionCallback,
_minCrossAxisExtentCallback = minCrossAxisDimensionCallback,
_startOffset = startOffset,
super(children: children, direction: direction, itemExtent: itemExtent, minExtent: minExtent);
bool _inCallback = false;
// Called during layout. Mutate the child list appropriately.
LayoutCallback _callback;
/// Called during [layout] to determine the blocks children
///
/// Typically the callback will mutate the child list appropriately, for
/// example so the child list contains only visible children.
LayoutCallback get callback => _callback;
LayoutCallback _callback;
void set callback(LayoutCallback value) {
assert(!_inCallback);
if (value == _callback)
......@@ -234,11 +255,10 @@ class RenderBlockViewport extends RenderBlockBase {
markNeedsLayout();
}
// Return the sum of the extent of all the children that could be included by the callback in one go.
// The extent is the dimension in the direction given by the 'direction' property.
DimensionCallback _totalExtentCallback;
DimensionCallback get totalExtentCallback => _totalExtentCallback;
void set totalExtentCallback(DimensionCallback value) {
/// Returns the total main-axis extent of all the children that could be included by [callback] in one go
ExtentCallback get totalExtentCallback => _totalExtentCallback;
ExtentCallback _totalExtentCallback;
void set totalExtentCallback(ExtentCallback value) {
assert(!_inCallback);
if (value == _totalExtentCallback)
return;
......@@ -246,35 +266,33 @@ class RenderBlockViewport extends RenderBlockBase {
markNeedsLayout();
}
// Return the minimum dimension across all the children that could
// be included in one go, in the direction orthogonal to that given
// by the 'direction' property.
DimensionCallback _minCrossAxisDimensionCallback;
DimensionCallback get minCrossAxisDimensionCallback => _minCrossAxisDimensionCallback;
void set minCrossAxisDimensionCallback(DimensionCallback value) {
/// Returns the minimum cross-axis extent across all the children that could be included by [callback] in one go
ExtentCallback get minCrossAxisExtentCallback => _minCrossAxisExtentCallback;
ExtentCallback _minCrossAxisExtentCallback;
void set minCrossAxisExtentCallback(ExtentCallback value) {
assert(!_inCallback);
if (value == _minCrossAxisDimensionCallback)
if (value == _minCrossAxisExtentCallback)
return;
_minCrossAxisDimensionCallback = value;
_minCrossAxisExtentCallback = value;
markNeedsLayout();
}
// Return the maximum dimension across all the children that could
// be included in one go, in the direction orthogonal to that given
// by the 'direction' property.
DimensionCallback _maxCrossAxisDimensionCallback;
DimensionCallback get maxCrossAxisDimensionCallback => _maxCrossAxisDimensionCallback;
void set maxCrossAxisDimensionCallback(DimensionCallback value) {
/// Returns the maximum cross-axis extent across all the children that could be included by [callback] in one go
ExtentCallback get maxCrossAxisExtentCallback => _maxCrossAxisExtentCallback;
ExtentCallback _maxCrossAxisExtentCallback;
void set maxCrossAxisExtentCallback(ExtentCallback value) {
assert(!_inCallback);
if (value == _maxCrossAxisDimensionCallback)
if (value == _maxCrossAxisExtentCallback)
return;
_maxCrossAxisDimensionCallback = value;
_maxCrossAxisExtentCallback = value;
markNeedsLayout();
}
// you can set this from within the callback if necessary
double _startOffset;
/// The offset at which to paint the first child
///
/// Note: you can modify this property from within [callback], if necessary.
double get startOffset => _startOffset;
double _startOffset;
void set startOffset(double value) {
if (value != _startOffset) {
_startOffset = value;
......@@ -282,7 +300,7 @@ class RenderBlockViewport extends RenderBlockBase {
}
}
double _getIntrinsicDimension(BoxConstraints constraints, DimensionCallback intrinsicCallback, _Constrainer constrainer) {
double _getIntrinsicDimension(BoxConstraints constraints, ExtentCallback intrinsicCallback, _Constrainer constrainer) {
assert(!_inCallback);
double result;
if (intrinsicCallback == null) {
......@@ -307,25 +325,25 @@ class RenderBlockViewport extends RenderBlockBase {
double getMinIntrinsicWidth(BoxConstraints constraints) {
if (isVertical)
return _getIntrinsicDimension(constraints, minCrossAxisDimensionCallback, constraints.constrainWidth);
return _getIntrinsicDimension(constraints, minCrossAxisExtentCallback, constraints.constrainWidth);
return constraints.constrainWidth(minExtent);
}
double getMaxIntrinsicWidth(BoxConstraints constraints) {
if (isVertical)
return _getIntrinsicDimension(constraints, maxCrossAxisDimensionCallback, constraints.constrainWidth);
return _getIntrinsicDimension(constraints, maxCrossAxisExtentCallback, constraints.constrainWidth);
return _getIntrinsicDimension(constraints, totalExtentCallback, new BoxConstraints(minWidth: minExtent).enforce(constraints).constrainWidth);
}
double getMinIntrinsicHeight(BoxConstraints constraints) {
if (!isVertical)
return _getIntrinsicDimension(constraints, minCrossAxisDimensionCallback, constraints.constrainHeight);
return _getIntrinsicDimension(constraints, minCrossAxisExtentCallback, constraints.constrainHeight);
return constraints.constrainHeight(0.0);
}
double getMaxIntrinsicHeight(BoxConstraints constraints) {
if (!isVertical)
return _getIntrinsicDimension(constraints, maxCrossAxisDimensionCallback, constraints.constrainHeight);
return _getIntrinsicDimension(constraints, maxCrossAxisExtentCallback, constraints.constrainHeight);
return _getIntrinsicDimension(constraints, totalExtentCallback, new BoxConstraints(minHeight: minExtent).enforce(constraints).constrainHeight);
}
......
......@@ -12,9 +12,6 @@ import 'package:vector_math/vector_math.dart';
export 'package:sky/painting.dart' show TextBaseline;
// GENERIC BOX RENDERING
// Anything that has a concept of x, y, width, height is going to derive from this
// This class should only be used in debug builds
class _DebugSize extends Size {
_DebugSize(Size source, this._owner, this._canBeUsedByParent): super.copy(source);
......
......@@ -9,7 +9,14 @@ import 'package:sky/src/rendering/object.dart';
export 'package:sky/src/rendering/object.dart' show EventDisposition;
/// Parent data for use with [RenderFlex]
class FlexParentData extends BoxParentData with ContainerParentDataMixin<RenderBox> {
/// The flex factor to use for this child
///
/// If null, the child is inflexible and determines its own size. If non-null,
/// the child is flexible and its extent in the main axis is determined by
/// dividing the free space (after placing the inflexible children)
/// according to the flex factors of the flexible children.
int flex;
void merge(FlexParentData other) {
......@@ -21,29 +28,61 @@ class FlexParentData extends BoxParentData with ContainerParentDataMixin<RenderB
String toString() => '${super.toString()}; flex=$flex';
}
enum FlexDirection { horizontal, vertical }
/// The direction in which the box should flex
enum FlexDirection {
/// Children are arranged horizontally, from left to right
horizontal,
/// Children are arranged vertically, from top to bottom
vertical
}
/// How the children should be placed along the main axis in a flex layout
enum FlexJustifyContent {
/// Place the children as close to the start of the main axis as possible
start,
/// Place the children as close to the end of the main axis as possible
end,
/// Place the children as close to the middle of the main axis as possible
center,
/// Place the free space evenly between the children
spaceBetween,
/// Place the free space evenly between the children as well as before and after the first and last child
spaceAround,
}
/// How the children should be placed along the cross axis in a flex layout
enum FlexAlignItems {
/// Place the children as close to the start of the cross axis as possible
start,
/// Place the children as close to the end of the cross axis as possible
end,
/// Place the children as close to the middle of the cross axis as possible
center,
/// Require the children to fill the cross axis
stretch,
/// Place the children along the cross axis such that their baselines match
baseline,
}
typedef double _ChildSizingFunction(RenderBox child, BoxConstraints constraints);
/// Implements the flex layout algorithm
///
/// In flex layout, children are arranged linearly along the main axis (either
/// horizontally or vertically). First, inflexible children (those with a null
/// flex factor) are allocated space along the main axis. If the flex is given
/// unlimited space in the main axis, the flex sizes its main axis to the total
/// size of the inflexible children along the main axis and forbids flexible
/// children. Otherwise, the flex expands to the maximum max-axis size and the
/// remaining space along is divided among the flexible children according to
/// their flex factors. Any remaining free space (i.e., if there aren't any
/// flexible children) is allocated according to the [justifyContent] property.
///
/// In the cross axis, children determine their own size. The flex then sizes
/// its cross axis to fix the largest of its children. The children are then
/// positioned along the cross axis according to the [alignItems] property.
class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, FlexParentData>,
RenderBoxContainerDefaultsMixin<RenderBox, FlexParentData> {
// lays out RenderBox children using flexible layout
RenderFlex({
List<RenderBox> children,
......@@ -58,8 +97,9 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
addAll(children);
}
FlexDirection _direction;
/// The direction to use as the main axis
FlexDirection get direction => _direction;
FlexDirection _direction;
void set direction (FlexDirection value) {
if (_direction != value) {
_direction = value;
......@@ -67,8 +107,9 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
}
}
FlexJustifyContent _justifyContent;
/// How the children should be placed along the main axis
FlexJustifyContent get justifyContent => _justifyContent;
FlexJustifyContent _justifyContent;
void set justifyContent (FlexJustifyContent value) {
if (_justifyContent != value) {
_justifyContent = value;
......@@ -76,8 +117,9 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
}
}
FlexAlignItems _alignItems;
/// How the children should be placed along the cross axis
FlexAlignItems get alignItems => _alignItems;
FlexAlignItems _alignItems;
void set alignItems (FlexAlignItems value) {
if (_alignItems != value) {
_alignItems = value;
......@@ -85,8 +127,9 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
}
}
TextBaseline _textBaseline;
/// If using aligning items according to their baseline, which baseline to use
TextBaseline get textBaseline => _textBaseline;
TextBaseline _textBaseline;
void set textBaseline (TextBaseline value) {
if (_textBaseline != value) {
_textBaseline = value;
......@@ -94,7 +137,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
}
}
// Set during layout if overflow occurred on the main axis
/// Set during layout if overflow occurred on the main axis
double _overflow;
void setupParentData(RenderBox child) {
......
......@@ -8,6 +8,10 @@ import 'package:sky/painting.dart';
import 'package:sky/src/rendering/object.dart';
import 'package:sky/src/rendering/box.dart';
/// An image in the render tree
///
/// The render image attempts to find a size for itself that fits in the given
/// constraints and preserves the image's intrinisc aspect ratio.
class RenderImage extends RenderBox {
RenderImage({
sky.Image image,
......@@ -24,6 +28,7 @@ class RenderImage extends RenderBox {
_repeat = repeat;
sky.Image _image;
/// The image to display
sky.Image get image => _image;
void set image (sky.Image value) {
if (value == _image)
......@@ -35,6 +40,7 @@ class RenderImage extends RenderBox {
}
double _width;
/// If non-null, requires the image to have this width
double get width => _width;
void set width (double value) {
if (value == _width)
......@@ -44,6 +50,7 @@ class RenderImage extends RenderBox {
}
double _height;
/// If non-null, requires the image to have this height
double get height => _height;
void set height (double value) {
if (value == _height)
......@@ -53,6 +60,7 @@ class RenderImage extends RenderBox {
}
sky.ColorFilter _colorFilter;
/// If non-null, apply this color filter to the image before painint.
sky.ColorFilter get colorFilter => _colorFilter;
void set colorFilter (sky.ColorFilter value) {
if (value == _colorFilter)
......@@ -62,6 +70,7 @@ class RenderImage extends RenderBox {
}
ImageFit _fit;
/// How to inscribe the image into the place allocated during layout
ImageFit get fit => _fit;
void set fit (ImageFit value) {
if (value == _fit)
......@@ -71,6 +80,7 @@ class RenderImage extends RenderBox {
}
ImageRepeat _repeat;
/// Not yet implemented
ImageRepeat get repeat => _repeat;
void set repeat (ImageRepeat value) {
if (value == _repeat)
......@@ -79,6 +89,13 @@ class RenderImage extends RenderBox {
markNeedsPaint();
}
/// Find a size for the render image within the given constraints
///
/// - The dimensions of the RenderImage must fit within the constraints.
/// - The aspect ratio of the RenderImage matches the instrinsic aspect
/// ratio of the image.
/// - The RenderImage's dimension are maximal subject to being smaller than
/// the intrinsic size of the image.
Size _sizeForConstraints(BoxConstraints constraints) {
// Folds the given |width| and |height| into |cosntraints| so they can all
// be treated uniformly.
......@@ -90,16 +107,6 @@ class RenderImage extends RenderBox {
if (constraints.isTight || _image == null)
return constraints.smallest;
// This algorithm attempts to find a size for the RenderImage that fits in
// the given constraints and preserves the image's intrinisc aspect ratio.
// Its goals as follow:
//
// - The dimensions of the RenderImage fit within the constraints.
// - The aspect ratio of the RenderImage matches the instrinsic aspect
// ratio of the image.
// - The RenderImage's dimension are maximal subject to being smaller than
// the intrinsic size of the image.
double width = _image.width.toDouble();
double height = _image.height.toDouble();
assert(width > 0.0);
......
......@@ -366,7 +366,7 @@ abstract class Constraints {
typedef void RenderObjectVisitor(RenderObject child);
typedef void LayoutCallback(Constraints constraints);
typedef double DimensionCallback(Constraints constraints);
typedef double ExtentCallback(Constraints constraints);
/// An object in the render tree
///
......
......@@ -43,16 +43,16 @@ class HomogeneousViewport extends RenderObjectWrapper {
RenderBlockViewport result = new RenderBlockViewport();
result.callback = layout;
result.totalExtentCallback = getTotalExtent;
result.minCrossAxisDimensionCallback = getMinCrossAxisDimension;
result.maxCrossAxisDimensionCallback = getMaxCrossAxisDimension;
result.minCrossAxisExtentCallback = getMinCrossAxisExtent;
result.maxCrossAxisExtentCallback = getMaxCrossAxisExtent;
return result;
}
void remove() {
renderObject.callback = null;
renderObject.totalExtentCallback = null;
renderObject.minCrossAxisDimensionCallback = null;
renderObject.maxCrossAxisDimensionCallback = null;
renderObject.minCrossAxisExtentCallback = null;
renderObject.maxCrossAxisExtentCallback = null;
super.remove();
_children.clear();
_layoutDirty = true;
......@@ -172,11 +172,11 @@ class HomogeneousViewport extends RenderObjectWrapper {
return itemCount != null ? itemCount * itemExtent : double.INFINITY;
}
double getMinCrossAxisDimension(BoxConstraints constraints) {
double getMinCrossAxisExtent(BoxConstraints constraints) {
return 0.0;
}
double getMaxCrossAxisDimension(BoxConstraints constraints) {
double getMaxCrossAxisExtent(BoxConstraints constraints) {
if (direction == ScrollDirection.vertical)
return constraints.maxWidth;
return constraints.maxHeight;
......
......@@ -98,17 +98,17 @@ class MixedViewport extends RenderObjectWrapper {
// create it, because the render object is empty so it will not matter
RenderBlockViewport result = new RenderBlockViewport();
result.callback = layout;
result.totalExtentCallback = _noIntrinsicDimensions;
result.maxCrossAxisDimensionCallback = _noIntrinsicDimensions;
result.minCrossAxisDimensionCallback = _noIntrinsicDimensions;
result.totalExtentCallback = _noIntrinsicExtent;
result.maxCrossAxisExtentCallback = _noIntrinsicExtent;
result.minCrossAxisExtentCallback = _noIntrinsicExtent;
return result;
}
void remove() {
renderObject.callback = null;
renderObject.totalExtentCallback = null;
renderObject.maxCrossAxisDimensionCallback = null;
renderObject.minCrossAxisDimensionCallback = null;
renderObject.maxCrossAxisExtentCallback = null;
renderObject.minCrossAxisExtentCallback = null;
super.remove();
_childrenByKey.clear();
layoutState._dirty = true;
......@@ -140,7 +140,7 @@ class MixedViewport extends RenderObjectWrapper {
assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
}
double _noIntrinsicDimensions(BoxConstraints constraints) {
double _noIntrinsicExtent(BoxConstraints constraints) {
assert(() {
'MixedViewport does not support returning intrinsic dimensions. ' +
'Calculating the intrinsic dimensions would require walking the entire child list, ' +
......@@ -330,7 +330,7 @@ class MixedViewport extends RenderObjectWrapper {
'all the children. You probably want to put the MixedViewport inside a Container with a fixed width.' is String);
}
final double endOffset = startOffset + extent;
BoxConstraints innerConstraints;
if (direction == ScrollDirection.vertical) {
innerConstraints = new BoxConstraints.tightFor(width: constraints.constrainWidth());
......
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