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