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

Side by Side Diff: sky/sdk/lib/framework/rendering/flex.dart

Issue 1177383006: Rename all the things (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: fix imports Created 5 years, 6 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 unified diff | Download patch
« no previous file with comments | « sky/sdk/lib/framework/rendering/box.dart ('k') | sky/sdk/lib/framework/rendering/object.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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:math' as math;
6 import 'box.dart';
7 import 'object.dart';
8
9 class FlexBoxParentData extends BoxParentData with ContainerParentDataMixin<Rend erBox> {
10 int flex;
11
12 void merge(FlexBoxParentData other) {
13 if (other.flex != null)
14 flex = other.flex;
15 super.merge(other);
16 }
17
18 String toString() => '${super.toString()}; flex=$flex';
19 }
20
21 enum FlexDirection { horizontal, vertical }
22
23 enum FlexJustifyContent {
24 flexStart,
25 flexEnd,
26 center,
27 spaceBetween,
28 spaceAround,
29 }
30
31 enum FlexAlignItems {
32 flexStart,
33 flexEnd,
34 center,
35 }
36
37 typedef double _ChildSizingFunction(RenderBox child, BoxConstraints constraints) ;
38
39 class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl exBoxParentData>,
40 RenderBoxContainerDefaultsMixin<RenderBo x, FlexBoxParentData> {
41 // lays out RenderBox children using flexible layout
42
43 RenderFlex({
44 FlexDirection direction: FlexDirection.horizontal,
45 FlexJustifyContent justifyContent: FlexJustifyContent.flexStart,
46 FlexAlignItems alignItems: FlexAlignItems.center
47 }) : _direction = direction, _justifyContent = justifyContent, _alignItems = a lignItems;
48
49 FlexDirection _direction;
50 FlexDirection get direction => _direction;
51 void set direction (FlexDirection value) {
52 if (_direction != value) {
53 _direction = value;
54 markNeedsLayout();
55 }
56 }
57
58 FlexJustifyContent _justifyContent;
59 FlexJustifyContent get justifyContent => _justifyContent;
60 void set justifyContent (FlexJustifyContent value) {
61 if (_justifyContent != value) {
62 _justifyContent = value;
63 markNeedsLayout();
64 }
65 }
66
67 FlexAlignItems _alignItems;
68 FlexAlignItems get alignItems => _alignItems;
69 void set alignItems (FlexAlignItems value) {
70 if (_alignItems != value) {
71 _alignItems = value;
72 markNeedsLayout();
73 }
74 }
75
76 void setParentData(RenderBox child) {
77 if (child.parentData is! FlexBoxParentData)
78 child.parentData = new FlexBoxParentData();
79 }
80
81 double _getIntrinsicSize({ BoxConstraints constraints,
82 FlexDirection sizingDirection,
83 _ChildSizingFunction childSize }) {
84 // http://www.w3.org/TR/2015/WD-css-flexbox-1-20150514/#intrinsic-sizes
85 if (_direction == sizingDirection) {
86 // INTRINSIC MAIN SIZE
87 // Intrinsic main size is the smallest size the flex container can take
88 // while maintaining the min/max-content contributions of its flex items.
89 BoxConstraints childConstraints;
90 switch(_direction) {
91 case FlexDirection.horizontal:
92 childConstraints = new BoxConstraints(maxHeight: constraints.maxHeight );
93 break;
94 case FlexDirection.vertical:
95 childConstraints = new BoxConstraints(maxWidth: constraints.maxWidth);
96 break;
97 }
98
99 double totalFlex = 0.0;
100 double inflexibleSpace = 0.0;
101 double maxFlexFractionSoFar = 0.0;
102 RenderBox child = firstChild;
103 while (child != null) {
104 int flex = _getFlex(child);
105 totalFlex += flex;
106 if (flex > 0) {
107 double flexFraction = childSize(child, childConstraints) / _getFlex(ch ild);
108 maxFlexFractionSoFar = math.max(maxFlexFractionSoFar, flexFraction);
109 } else {
110 inflexibleSpace += childSize(child, childConstraints);
111 }
112 child = child.parentData.nextSibling;
113 }
114 double mainSize = maxFlexFractionSoFar * totalFlex + inflexibleSpace;
115
116 // Ensure that we don't violate the given constraints with our result
117 switch(_direction) {
118 case FlexDirection.horizontal:
119 return constraints.constrainWidth(mainSize);
120 case FlexDirection.vertical:
121 return constraints.constrainHeight(mainSize);
122 }
123 } else {
124 // INTRINSIC CROSS SIZE
125 // The spec wants us to perform layout into the given available main-axis
126 // space and return the cross size. That's too expensive, so instead we
127 // size inflexible children according to their max intrinsic size in the
128 // main direction and use those constraints to determine their max
129 // intrinsic size in the cross direction. We don't care if the caller
130 // asked for max or min -- the answer is always computed using the
131 // max size in the main direction.
132
133 double availableMainSpace;
134 BoxConstraints childConstraints;
135 switch(_direction) {
136 case FlexDirection.horizontal:
137 childConstraints = new BoxConstraints(maxWidth: constraints.maxWidth);
138 availableMainSpace = constraints.maxWidth;
139 break;
140 case FlexDirection.vertical:
141 childConstraints = new BoxConstraints(maxHeight: constraints.maxHeight );
142 availableMainSpace = constraints.maxHeight;
143 break;
144 }
145
146 // Get inflexible space using the max in the main direction
147 int totalFlex = 0;
148 double inflexibleSpace = 0.0;
149 double maxCrossSize = 0.0;
150 RenderBox child = firstChild;
151 while (child != null) {
152 int flex = _getFlex(child);
153 totalFlex += flex;
154 double mainSize;
155 double crossSize;
156 if (flex == 0) {
157 switch (_direction) {
158 case FlexDirection.horizontal:
159 mainSize = child.getMaxIntrinsicWidth(childConstraints);
160 BoxConstraints widthConstraints =
161 new BoxConstraints(minWidth: mainSize, maxWidth: mainSize);
162 crossSize = child.getMaxIntrinsicHeight(widthConstraints);
163 break;
164 case FlexDirection.vertical:
165 mainSize = child.getMaxIntrinsicHeight(childConstraints);
166 BoxConstraints heightConstraints =
167 new BoxConstraints(minWidth: mainSize, maxWidth: mainSize);
168 crossSize = child.getMaxIntrinsicWidth(heightConstraints);
169 break;
170 }
171 inflexibleSpace += mainSize;
172 maxCrossSize = math.max(maxCrossSize, crossSize);
173 }
174 child = child.parentData.nextSibling;
175 }
176
177 // Determine the spacePerFlex by allocating the remaining available space
178 double spacePerFlex = (availableMainSpace - inflexibleSpace) / totalFlex;
179
180 // Size remaining items, find the maximum cross size
181 child = firstChild;
182 while (child != null) {
183 int flex = _getFlex(child);
184 if (flex > 0) {
185 double childMainSize = spacePerFlex * flex;
186 double crossSize;
187 switch (_direction) {
188 case FlexDirection.horizontal:
189 BoxConstraints childConstraints =
190 new BoxConstraints(minWidth: childMainSize, maxWidth: childMainS ize);
191 crossSize = child.getMaxIntrinsicHeight(childConstraints);
192 break;
193 case FlexDirection.vertical:
194 BoxConstraints childConstraints =
195 new BoxConstraints(minHeight: childMainSize, maxHeight: childMai nSize);
196 crossSize = child.getMaxIntrinsicWidth(childConstraints);
197 break;
198 }
199 maxCrossSize = math.max(maxCrossSize, crossSize);
200 }
201 child = child.parentData.nextSibling;
202 }
203
204 // Ensure that we don't violate the given constraints with our result
205 switch(_direction) {
206 case FlexDirection.horizontal:
207 return constraints.constrainHeight(maxCrossSize);
208 case FlexDirection.vertical:
209 return constraints.constrainWidth(maxCrossSize);
210 }
211 }
212 }
213
214 double getMinIntrinsicWidth(BoxConstraints constraints) {
215 return _getIntrinsicSize(
216 constraints: constraints,
217 sizingDirection: FlexDirection.horizontal,
218 childSize: (c, innerConstraints) => c.getMinIntrinsicWidth(innerConstraint s)
219 );
220 }
221
222 double getMaxIntrinsicWidth(BoxConstraints constraints) {
223 return _getIntrinsicSize(
224 constraints: constraints,
225 sizingDirection: FlexDirection.horizontal,
226 childSize: (c, innerConstraints) => c.getMaxIntrinsicWidth(innerConstraint s)
227 );
228 }
229
230 double getMinIntrinsicHeight(BoxConstraints constraints) {
231 return _getIntrinsicSize(
232 constraints: constraints,
233 sizingDirection: FlexDirection.vertical,
234 childSize: (c, innerConstraints) => c.getMinIntrinsicHeight(innerConstrain ts)
235 );
236 }
237
238 double getMaxIntrinsicHeight(BoxConstraints constraints) {
239 return _getIntrinsicSize(
240 constraints: constraints,
241 sizingDirection: FlexDirection.vertical,
242 childSize: (c, innerConstraints) => c.getMaxIntrinsicHeight(innerConstrain ts));
243 }
244
245 int _getFlex(RenderBox child) {
246 assert(child.parentData is FlexBoxParentData);
247 return child.parentData.flex != null ? child.parentData.flex : 0;
248 }
249
250 double _getCrossSize(RenderBox child) {
251 return (_direction == FlexDirection.horizontal) ? child.size.height : child. size.width;
252 }
253
254 double _getMainSize(RenderBox child) {
255 return (_direction == FlexDirection.horizontal) ? child.size.width : child.s ize.height;
256 }
257
258 void performLayout() {
259 // Based on http://www.w3.org/TR/css-flexbox-1/ Section 9.7 Resolving Flexib le Lengths
260 // Steps 1-3. Determine used flex factor, size inflexible items, calculate f ree space
261 int totalFlex = 0;
262 int totalChildren = 0;
263 assert(constraints != null);
264 final double mainSize = (_direction == FlexDirection.horizontal) ? constrain ts.maxWidth : constraints.maxHeight;
265 double crossSize = 0.0; // This will be determined after laying out the chi ldren
266 double freeSpace = mainSize;
267 RenderBox child = firstChild;
268 while (child != null) {
269 totalChildren++;
270 int flex = _getFlex(child);
271 if (flex > 0) {
272 totalFlex += child.parentData.flex;
273 } else {
274 BoxConstraints innerConstraints = new BoxConstraints(maxHeight: constrai nts.maxHeight,
275 maxWidth: constrain ts.maxWidth);
276 child.layout(innerConstraints, parentUsesSize: true);
277 freeSpace -= _getMainSize(child);
278 crossSize = math.max(crossSize, _getCrossSize(child));
279 }
280 child = child.parentData.nextSibling;
281 }
282
283 // Steps 4-5. Distribute remaining space to flexible children.
284 double spacePerFlex = totalFlex > 0 ? (freeSpace / totalFlex) : 0.0;
285 double usedSpace = 0.0;
286 child = firstChild;
287 while (child != null) {
288 int flex = _getFlex(child);
289 if (flex > 0) {
290 double spaceForChild = spacePerFlex * flex;
291 BoxConstraints innerConstraints;
292 switch (_direction) {
293 case FlexDirection.horizontal:
294 innerConstraints = new BoxConstraints(maxHeight: constraints.maxHeig ht,
295 minWidth: spaceForChild,
296 maxWidth: spaceForChild);
297 break;
298 case FlexDirection.vertical:
299 innerConstraints = new BoxConstraints(minHeight: spaceForChild,
300 maxHeight: spaceForChild,
301 maxWidth: constraints.maxWidth );
302 break;
303 }
304 child.layout(innerConstraints, parentUsesSize: true);
305 usedSpace += _getMainSize(child);
306 crossSize = math.max(crossSize, _getCrossSize(child));
307 }
308 child = child.parentData.nextSibling;
309 }
310
311 // Section 8.2: Axis Alignment using the justify-content property
312 double remainingSpace = math.max(0.0, freeSpace - usedSpace);
313 double leadingSpace;
314 double betweenSpace;
315 child = firstChild;
316 switch (_justifyContent) {
317 case FlexJustifyContent.flexStart:
318 leadingSpace = 0.0;
319 betweenSpace = 0.0;
320 break;
321 case FlexJustifyContent.flexEnd:
322 leadingSpace = remainingSpace;
323 betweenSpace = 0.0;
324 break;
325 case FlexJustifyContent.center:
326 leadingSpace = remainingSpace / 2.0;
327 betweenSpace = 0.0;
328 break;
329 case FlexJustifyContent.spaceBetween:
330 leadingSpace = 0.0;
331 betweenSpace = totalChildren > 1 ? remainingSpace / (totalChildren - 1) : 0.0;
332 break;
333 case FlexJustifyContent.spaceAround:
334 betweenSpace = totalChildren > 0 ? remainingSpace / totalChildren : 0.0;
335 leadingSpace = betweenSpace / 2.0;
336 break;
337 }
338
339 switch (_direction) {
340 case FlexDirection.horizontal:
341 size = constraints.constrain(new Size(mainSize, crossSize));
342 crossSize = size.height;
343 break;
344 case FlexDirection.vertical:
345 size = constraints.constrain(new Size(crossSize, mainSize));
346 crossSize = size.width;
347 break;
348 }
349
350 // Position elements. For now, center the flex items in the cross direction
351 double childMainPosition = leadingSpace;
352 child = firstChild;
353 while (child != null) {
354 double childCrossPosition;
355 switch (_alignItems) {
356 case FlexAlignItems.flexStart:
357 childCrossPosition = 0.0;
358 break;
359 case FlexAlignItems.flexEnd:
360 childCrossPosition = crossSize - _getCrossSize(child);
361 break;
362 case FlexAlignItems.center:
363 childCrossPosition = crossSize / 2.0 - _getCrossSize(child) / 2.0;
364 break;
365 }
366 switch (_direction) {
367 case FlexDirection.horizontal:
368 child.parentData.position = new Point(childMainPosition, childCrossPos ition);
369 break;
370 case FlexDirection.vertical:
371 child.parentData.position = new Point(childCrossPosition, childMainPos ition);
372 break;
373 }
374 childMainPosition += _getMainSize(child) + betweenSpace;
375 child = child.parentData.nextSibling;
376 }
377 }
378
379 void hitTestChildren(HitTestResult result, { Point position }) {
380 defaultHitTestChildren(result, position: position);
381 }
382
383 void paint(RenderObjectDisplayList canvas) {
384 defaultPaint(canvas);
385 }
386 }
OLDNEW
« no previous file with comments | « sky/sdk/lib/framework/rendering/box.dart ('k') | sky/sdk/lib/framework/rendering/object.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698