Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(491)

Unified Diff: sky/sdk/lib/framework/layout2.dart

Issue 1151293002: WIP Flexbox Layout Manager for Sky framework. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Rebasing onto master Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sky/sdk/lib/framework/layout2.dart
diff --git a/sky/sdk/lib/framework/layout2.dart b/sky/sdk/lib/framework/layout2.dart
index 0284dc845acb6614d0ece7aed9ff830258694cbe..4980f4cc6a897f118cc03aaa42b1e23561da865c 100644
--- a/sky/sdk/lib/framework/layout2.dart
+++ b/sky/sdk/lib/framework/layout2.dart
@@ -221,6 +221,7 @@ abstract class RenderNode extends AbstractNode {
bool handlePointer(sky.PointerEvent event, { double x: 0.0, double y: 0.0 }) {
// override this if you have children, to hand it to the appropriate child
// override this if you want to do anything with the pointer event
+ return false;
}
@@ -425,10 +426,9 @@ class BoxDimensions {
const BoxDimensions({this.width, this.height});
BoxDimensions.withConstraints(
- BoxConstraints constraints, {double width: 0.0, double height: 0.0}) {
- this.width = constraints.constrainWidth(width);
- this.height = constraints.constrainHeight(height);
- }
+ BoxConstraints constraints, {double width: 0.0, double height: 0.0})
+ : width = constraints.constrainWidth(width),
+ height = constraints.constrainHeight(height);
final double width;
final double height;
@@ -580,6 +580,33 @@ class RenderView extends RenderNode {
}
+// DEFAULT BEHAVIORS FOR RENDERBOX CONTAINERS
+abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, ParentDataType extends ContainerParentDataMixin<ChildType>> implements ContainerRenderNodeMixin<ChildType, ParentDataType> {
+ bool defaultHandlePointer(sky.PointerEvent event, double x, double y) {
+ // the x, y parameters have the top left of the node's box as the origin
+ ChildType child = lastChild;
+ while (child != null) {
+ assert(child.parentData is BoxParentData);
+ if ((x >= child.parentData.x) && (x < child.parentData.x + child.width) &&
+ (y >= child.parentData.y) && (y < child.parentData.y + child.height)) {
+ if (child.handlePointer(event, x: x-child.parentData.x, y: y-child.parentData.y))
+ return true;
+ break;
+ }
+ child = child.parentData.previousSibling;
+ }
+ return false;
+ }
+
+ void defaultPaint(RenderNodeDisplayList canvas) {
+ RenderBox child = firstChild;
+ while (child != null) {
+ assert(child.parentData is BoxParentData);
+ canvas.paintChild(child, child.parentData.x, child.parentData.y);
+ child = child.parentData.nextSibling;
+ }
+ }
+}
// BLOCK LAYOUT MANAGER
@@ -598,7 +625,8 @@ class EdgeDims {
class BlockParentData extends BoxParentData with ContainerParentDataMixin<RenderBox> { }
-class RenderBlock extends RenderDecoratedBox with ContainerRenderNodeMixin<RenderBox, BlockParentData> {
+class RenderBlock extends RenderDecoratedBox with ContainerRenderNodeMixin<RenderBox, BlockParentData>,
+ RenderBoxContainerDefaultsMixin<RenderBox, BlockParentData> {
// lays out RenderBox children in a vertical stack
// uses the maximum width provided by the parent
// sizes itself to the height of its child stack
@@ -634,10 +662,10 @@ class RenderBlock extends RenderDecoratedBox with ContainerRenderNodeMixin<Rende
assert(outerWidth < double.INFINITY);
double innerWidth = outerWidth - (_padding.left + _padding.right);
RenderBox child = _firstChild;
- BoxConstraints constraints = new BoxConstraints(minWidth: innerWidth,
- maxWidth: innerWidth);
+ BoxConstraints innerConstraints = new BoxConstraints(minWidth: innerWidth,
+ maxWidth: innerWidth);
while (child != null) {
- outerHeight += child.getIntrinsicDimensions(constraints).height;
+ outerHeight += child.getIntrinsicDimensions(innerConstraints).height;
assert(child.parentData is BlockParentData);
child = child.parentData.nextSibling;
}
@@ -683,34 +711,19 @@ class RenderBlock extends RenderDecoratedBox with ContainerRenderNodeMixin<Rende
}
bool handlePointer(sky.PointerEvent event, { double x: 0.0, double y: 0.0 }) {
- // the x, y parameters have the top left of the node's box as the origin
- RenderBox child = _lastChild;
- while (child != null) {
- assert(child.parentData is BlockParentData);
- if ((x >= child.parentData.x) && (x < child.parentData.x + child.width) &&
- (y >= child.parentData.y) && (y < child.parentData.y + child.height)) {
- if (child.handlePointer(event, x: x-child.parentData.x, y: y-child.parentData.y))
- return true;
- break;
- }
- child = child.parentData.previousSibling;
- }
- return super.handlePointer(event, x: x, y: y);
+ return defaultHandlePointer(event, x, y) || super.handlePointer(event, x: x, y: y);
}
void paint(RenderNodeDisplayList canvas) {
super.paint(canvas);
- RenderBox child = _firstChild;
- while (child != null) {
- assert(child.parentData is BlockParentData);
- canvas.paintChild(child, child.parentData.x, child.parentData.y);
- child = child.parentData.nextSibling;
- }
+ defaultPaint(canvas);
}
}
-class FlexBoxParentData extends BoxParentData {
+// FLEXBOX LAYOUT MANAGER
+
+class FlexBoxParentData extends BoxParentData with ContainerParentDataMixin<RenderBox> {
int flex;
void merge(FlexBoxParentData other) {
if (other.flex != null)
@@ -719,10 +732,127 @@ class FlexBoxParentData extends BoxParentData {
}
}
-enum FlexDirection { Row, Column }
+enum FlexDirection { Horizontal, Vertical }
+
+class RenderFlex extends RenderDecoratedBox with ContainerRenderNodeMixin<RenderBox, FlexBoxParentData>,
+ RenderBoxContainerDefaultsMixin<RenderBox, BlockParentData> {
+ // lays out RenderBox children using flexible layout
+
+ RenderFlex({
+ BoxDecoration decoration,
+ FlexDirection direction: FlexDirection.Horizontal
+ }) : super(decoration), _direction = direction;
+
+ FlexDirection _direction;
+ FlexDirection get direction => _direction;
+ void set direction (FlexDirection value) {
+ if (_direction != value) {
+ _direction = value;
+ markNeedsLayout();
+ }
+ }
+
+ void setParentData(RenderBox child) {
+ if (child.parentData is! FlexBoxParentData)
+ child.parentData = new FlexBoxParentData();
+ }
+
+ BoxConstraints _constraints; // value cached from parent for relayout call
+ void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) {
+ if (relayoutSubtreeRoot != null)
+ saveRelayoutSubtreeRoot(relayoutSubtreeRoot);
+ relayoutSubtreeRoot = relayoutSubtreeRoot == null ? this : relayoutSubtreeRoot;
+ _constraints = constraints;
+ width = _constraints.constrainWidth(_constraints.maxWidth);
+ height = _constraints.constrainHeight(_constraints.maxHeight);
+ assert(height < double.INFINITY);
+ assert(width < double.INFINITY);
+ internalLayout(relayoutSubtreeRoot);
+ }
+
+ void relayout() {
+ internalLayout(this);
+ }
+
+ int _getFlex(RenderBox child) {
+ assert(child.parentData is FlexBoxParentData);
+ return (child.parentData.flex != null ? child.parentData.flex : 0);
+ }
+
+ void internalLayout(RenderNode relayoutSubtreeRoot) {
+ // Based on http://www.w3.org/TR/css-flexbox-1/ Section 9.7 Resolving Flexible Lengths
+ // Steps 1-3. Determine used flex factor, size inflexible items, calculate free space
+ int numFlexibleChildren = 0;
+ int totalFlex = 0;
+ assert(_constraints != null);
+ double freeSpace = (_direction == FlexDirection.Horizontal) ? _constraints.maxWidth : _constraints.maxHeight;
+ RenderBox child = _firstChild;
+ while (child != null) {
+ int flex = _getFlex(child);
+ if (flex > 0) {
+ numFlexibleChildren++;
+ totalFlex += child.parentData.flex;
+ } else {
+ BoxConstraints constraints = new BoxConstraints(maxHeight: _constraints.maxHeight,
+ maxWidth: _constraints.maxWidth);
+ child.layout(constraints,
+ relayoutSubtreeRoot: relayoutSubtreeRoot);
+ freeSpace -= (_direction == FlexDirection.Horizontal) ? child.width : child.height;
+ }
+ child = child.parentData.nextSibling;
+ }
+
+ // Steps 4-5. Distribute remaining space to flexible children.
+ double spacePerFlex = totalFlex > 0 ? (freeSpace / totalFlex) : 0.0;
+ double usedSpace = 0.0;
+ child = _firstChild;
+ while (child != null) {
+ int flex = _getFlex(child);
+ if (flex > 0) {
+ double spaceForChild = spacePerFlex * flex;
+ BoxConstraints constraints;
+ switch (_direction) {
+ case FlexDirection.Horizontal:
+ constraints = new BoxConstraints(maxHeight: _constraints.maxHeight,
+ minWidth: spaceForChild,
+ maxWidth: spaceForChild);
+ break;
+ case FlexDirection.Vertical:
+ constraints = new BoxConstraints(minHeight: spaceForChild,
+ maxHeight: spaceForChild,
+ maxWidth: _constraints.maxWidth);
+ break;
+ }
+ child.layout(constraints, relayoutSubtreeRoot: relayoutSubtreeRoot);
+ }
-// TODO(ianh): FlexBox
+ // For now, center the flex items in the cross direction
+ switch (_direction) {
+ case FlexDirection.Horizontal:
+ child.parentData.x = usedSpace;
+ usedSpace += child.width;
+ child.parentData.y = height / 2 - child.height / 2;
+ break;
+ case FlexDirection.Vertical:
+ child.parentData.y = usedSpace;
+ usedSpace += child.height;
+ child.parentData.x = width / 2 - child.width / 2;
+ break;
+ }
+ child = child.parentData.nextSibling;
+ }
+ layoutDone();
+ }
+
+ bool handlePointer(sky.PointerEvent event, { double x: 0.0, double y: 0.0 }) {
+ return defaultHandlePointer(event, x, y) || super.handlePointer(event, x: x, y: y);
+ }
+ void paint(RenderNodeDisplayList canvas) {
+ super.paint(canvas);
+ defaultPaint(canvas);
+ }
+}
// SCAFFOLD LAYOUT MANAGER
« sky/examples/raw/simple_render_tree.dart ('K') | « sky/examples/raw/simple_render_tree.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698