OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 import 'dart:sky' as sky; |
| 6 import 'render_node.dart'; |
| 7 import 'render_box.dart'; |
| 8 import 'render_node.dart'; |
| 9 |
| 10 class FlexBoxParentData extends BoxParentData with ContainerParentDataMixin<Rend
erBox> { |
| 11 int flex; |
| 12 void merge(FlexBoxParentData other) { |
| 13 if (other.flex != null) |
| 14 flex = other.flex; |
| 15 super.merge(other); |
| 16 } |
| 17 } |
| 18 |
| 19 enum FlexDirection { Horizontal, Vertical } |
| 20 |
| 21 class RenderFlex extends RenderBox with ContainerRenderNodeMixin<RenderBox, Flex
BoxParentData>, |
| 22 RenderBoxContainerDefaultsMixin<RenderBo
x, FlexBoxParentData> { |
| 23 // lays out RenderBox children using flexible layout |
| 24 |
| 25 RenderFlex({ |
| 26 FlexDirection direction: FlexDirection.Horizontal |
| 27 }) : _direction = direction; |
| 28 |
| 29 FlexDirection _direction; |
| 30 FlexDirection get direction => _direction; |
| 31 void set direction (FlexDirection value) { |
| 32 if (_direction != value) { |
| 33 _direction = value; |
| 34 markNeedsLayout(); |
| 35 } |
| 36 } |
| 37 |
| 38 void setParentData(RenderBox child) { |
| 39 if (child.parentData is! FlexBoxParentData) |
| 40 child.parentData = new FlexBoxParentData(); |
| 41 } |
| 42 |
| 43 bool get sizedByParent => true; |
| 44 void performResize() { |
| 45 size = constraints.constrain(new sky.Size(constraints.maxWidth, constraints.
maxHeight)); |
| 46 assert(size.height < double.INFINITY); |
| 47 assert(size.width < double.INFINITY); |
| 48 } |
| 49 |
| 50 int _getFlex(RenderBox child) { |
| 51 assert(child.parentData is FlexBoxParentData); |
| 52 return child.parentData.flex != null ? child.parentData.flex : 0; |
| 53 } |
| 54 |
| 55 void performLayout() { |
| 56 // Based on http://www.w3.org/TR/css-flexbox-1/ Section 9.7 Resolving Flexib
le Lengths |
| 57 // Steps 1-3. Determine used flex factor, size inflexible items, calculate f
ree space |
| 58 int totalFlex = 0; |
| 59 assert(constraints != null); |
| 60 double freeSpace = (_direction == FlexDirection.Horizontal) ? constraints.ma
xWidth : constraints.maxHeight; |
| 61 RenderBox child = firstChild; |
| 62 while (child != null) { |
| 63 int flex = _getFlex(child); |
| 64 if (flex > 0) { |
| 65 totalFlex += child.parentData.flex; |
| 66 } else { |
| 67 BoxConstraints innerConstraints = new BoxConstraints(maxHeight: constrai
nts.maxHeight, |
| 68 maxWidth: constrain
ts.maxWidth); |
| 69 child.layout(innerConstraints, parentUsesSize: true); |
| 70 freeSpace -= (_direction == FlexDirection.Horizontal) ? child.size.width
: child.size.height; |
| 71 } |
| 72 child = child.parentData.nextSibling; |
| 73 } |
| 74 |
| 75 // Steps 4-5. Distribute remaining space to flexible children. |
| 76 double spacePerFlex = totalFlex > 0 ? (freeSpace / totalFlex) : 0.0; |
| 77 double usedSpace = 0.0; |
| 78 child = firstChild; |
| 79 while (child != null) { |
| 80 int flex = _getFlex(child); |
| 81 if (flex > 0) { |
| 82 double spaceForChild = spacePerFlex * flex; |
| 83 BoxConstraints innerConstraints; |
| 84 switch (_direction) { |
| 85 case FlexDirection.Horizontal: |
| 86 innerConstraints = new BoxConstraints(maxHeight: constraints.maxHeig
ht, |
| 87 minWidth: spaceForChild, |
| 88 maxWidth: spaceForChild); |
| 89 break; |
| 90 case FlexDirection.Vertical: |
| 91 innerConstraints = new BoxConstraints(minHeight: spaceForChild, |
| 92 maxHeight: spaceForChild, |
| 93 maxWidth: constraints.maxWidth
); |
| 94 break; |
| 95 } |
| 96 child.layout(innerConstraints, parentUsesSize: true); |
| 97 } |
| 98 |
| 99 // For now, center the flex items in the cross direction |
| 100 switch (_direction) { |
| 101 case FlexDirection.Horizontal: |
| 102 child.parentData.position = new sky.Point(usedSpace, size.height / 2.0
- child.size.height / 2.0); |
| 103 usedSpace += child.size.width; |
| 104 break; |
| 105 case FlexDirection.Vertical: |
| 106 child.parentData.position = new sky.Point(size.width / 2.0 - child.siz
e.width / 2.0, usedSpace); |
| 107 usedSpace += child.size.height; |
| 108 break; |
| 109 } |
| 110 child = child.parentData.nextSibling; |
| 111 } |
| 112 } |
| 113 |
| 114 void hitTestChildren(HitTestResult result, { sky.Point position }) { |
| 115 defaultHitTestChildren(result, position: position); |
| 116 } |
| 117 |
| 118 void paint(RenderNodeDisplayList canvas) { |
| 119 defaultPaint(canvas); |
| 120 } |
| 121 } |
OLD | NEW |