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

Side by Side Diff: sky/sdk/lib/framework/layout2.dart

Issue 1161983004: Refactor layout/relayout into a single method. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: 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/fn2.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 import 'node.dart'; 5 import 'node.dart';
6 import 'dart:sky' as sky; 6 import 'dart:sky' as sky;
7 7
8 // ABSTRACT LAYOUT 8 // ABSTRACT LAYOUT
9 9
10 class ParentData { 10 class ParentData {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 assert(child.parentData != null); 67 assert(child.parentData != null);
68 child.parentData.detach(); 68 child.parentData.detach();
69 super.dropChild(child); 69 super.dropChild(child);
70 } 70 }
71 71
72 static List<RenderNode> _nodesNeedingLayout = new List<RenderNode>(); 72 static List<RenderNode> _nodesNeedingLayout = new List<RenderNode>();
73 static bool _debugDoingLayout = false; 73 static bool _debugDoingLayout = false;
74 bool _needsLayout = true; 74 bool _needsLayout = true;
75 bool get needsLayout => _needsLayout; 75 bool get needsLayout => _needsLayout;
76 RenderNode _relayoutSubtreeRoot; 76 RenderNode _relayoutSubtreeRoot;
77 void saveRelayoutSubtreeRoot(RenderNode relayoutSubtreeRoot) { 77 dynamic _constraints;
78 _relayoutSubtreeRoot = relayoutSubtreeRoot; 78 dynamic get constraints => _constraints;
79 assert(_relayoutSubtreeRoot == null || _relayoutSubtreeRoot._relayoutSubtree Root == null);
80 assert(_relayoutSubtreeRoot == null || _relayoutSubtreeRoot == parent || (pa rent is RenderNode && _relayoutSubtreeRoot == parent._relayoutSubtreeRoot));
81 }
82 bool debugAncestorsAlreadyMarkedNeedsLayout() { 79 bool debugAncestorsAlreadyMarkedNeedsLayout() {
83 if (_relayoutSubtreeRoot == null) 80 if (_relayoutSubtreeRoot == null)
84 return true; 81 return true; // we haven't yet done layout even once, so there's nothing f or us to do
85 RenderNode node = this; 82 RenderNode node = this;
86 while (node != _relayoutSubtreeRoot) { 83 while (node != _relayoutSubtreeRoot) {
87 assert(node._relayoutSubtreeRoot == _relayoutSubtreeRoot); 84 assert(node._relayoutSubtreeRoot == _relayoutSubtreeRoot);
88 assert(node.parent != null); 85 assert(node.parent != null);
89 node = node.parent as RenderNode; 86 node = node.parent as RenderNode;
90 if (!node._needsLayout) 87 if (!node._needsLayout)
91 return false; 88 return false;
92 } 89 }
93 assert(node._relayoutSubtreeRoot == null); 90 assert(node._relayoutSubtreeRoot == node);
94 return true; 91 return true;
95 } 92 }
96 void markNeedsLayout() { 93 void markNeedsLayout() {
97 assert(!_debugDoingLayout); 94 assert(!_debugDoingLayout);
98 assert(!_debugDoingPaint); 95 assert(!_debugDoingPaint);
99 if (_needsLayout) { 96 if (_needsLayout) {
100 assert(debugAncestorsAlreadyMarkedNeedsLayout()); 97 assert(debugAncestorsAlreadyMarkedNeedsLayout());
101 return; 98 return;
102 } 99 }
103 _needsLayout = true; 100 _needsLayout = true;
104 if (_relayoutSubtreeRoot != null) { 101 assert(_relayoutSubtreeRoot != null);
102 if (_relayoutSubtreeRoot != this) {
105 assert(parent is RenderNode); 103 assert(parent is RenderNode);
106 parent.markNeedsLayout(); 104 parent.markNeedsLayout();
107 } else { 105 } else {
108 _nodesNeedingLayout.add(this); 106 _nodesNeedingLayout.add(this);
109 } 107 }
110 } 108 }
111 static void flushLayout() { 109 static void flushLayout() {
112 _debugDoingLayout = true; 110 _debugDoingLayout = true;
113 List<RenderNode> dirtyNodes = _nodesNeedingLayout; 111 List<RenderNode> dirtyNodes = _nodesNeedingLayout;
114 _nodesNeedingLayout = new List<RenderNode>(); 112 _nodesNeedingLayout = new List<RenderNode>();
115 dirtyNodes..sort((a, b) => a.depth - b.depth)..forEach((node) { 113 dirtyNodes..sort((a, b) => a.depth - b.depth)..forEach((node) {
116 if (node._needsLayout && node.attached) 114 if (node._needsLayout && node.attached)
117 node._doLayout(); 115 node._doLayout();
118 }); 116 });
119 _debugDoingLayout = false; 117 _debugDoingLayout = false;
120 } 118 }
121 void _doLayout() { 119 void _doLayout() {
122 try { 120 try {
123 assert(_relayoutSubtreeRoot == null); 121 assert(_relayoutSubtreeRoot == this);
124 relayout(); 122 performLayout();
125 } catch (e, stack) { 123 } catch (e, stack) {
126 print('Exception raised during layout of ${this}: ${e}'); 124 print('Exception raised during layout of ${this}: ${e}');
127 print(stack); 125 print(stack);
128 return; 126 return;
129 } 127 }
130 assert(!_needsLayout); // check that the relayout() method marked us "not di rty" 128 assert(!_needsLayout); // check that the relayout() method marked us "not di rty"
131 } 129 }
132 /* // this method's signature is subclass-specific, but will exist in 130 void layout(dynamic constraints, { bool parentUsesSize: false }) {
133 // some form in all subclasses: 131 RenderNode relayoutSubtreeRoot;
134 void layout({arguments..., RenderNode relayoutSubtreeRoot}) { 132 if (!parentUsesSize || sizedByParent || parent is! RenderNode)
135 bool childArgumentsChanged = ...; // true if arguments we're going to pas s to the children are different than last time, false otherwise 133 relayoutSubtreeRoot = this;
136 if (this node has an opinion about its size, e.g. because it autosizes ba sed on kids, or has an intrinsic dimension) { 134 else
137 if (relayoutSubtreeRoot != null) { 135 relayoutSubtreeRoot = parent._relayoutSubtreeRoot;
138 saveRelayoutSubtreeRoot(relayoutSubtreeRoot); 136 if (!needsLayout && constraints == _constraints && relayoutSubtreeRoot == _r elayoutSubtreeRoot)
139 // for each child, if we are going to size ourselves around them: 137 return;
140 if (child.needsLayout || childArgumentsChanged) 138 _constraints = constraints;
141 child.layout(... relayoutSubtreeRoot: relayoutSubtreeRoot); 139 _relayoutSubtreeRoot = relayoutSubtreeRoot;
142 width = ...; 140 if (sizedByParent)
143 height = ...; 141 performResize();
144 } else { 142 performLayout();
145 saveRelayoutSubtreeRoot(null); // you can skip this if there's no way you would ever have called saveRelayoutSubtreeRoot() before 143 _needsLayout = false;
146 // we're the root of the relayout subtree 144 markNeedsPaint();
147 // for each child, if we are going to size ourselves around them: 145 }
148 if (child.needsLayout || childArgumentsChanged) 146 bool get sizedByParent => false; // return true if the constraints are the onl y input to the sizing algorithm (in particular, child nodes have no impact)
149 child.layout(... relayoutSubtreeRoot: this); 147 void performResize(); // set the local dimensions, using only the constraints (only called if sizedByParent is true)
150 width = ...; 148 void performLayout();
151 height = ...;
152 }
153 } else {
154 // we're sizing ourselves exclusively on input from the parent (argumen ts to this function)
155 // ignore relayoutSubtreeRoot
156 saveRelayoutSubtreeRoot(null); // you can skip this if there's no way y ou would ever have called saveRelayoutSubtreeRoot() before
157 width = ...; // based on input from arguments only
158 height = ...; // based on input from arguments only
159 }
160 // for each child whose size we'll ignore when deciding ours:
161 if (child.needsLayout || childArgumentsChanged)
162 child.layout(... relayoutSubtreeRoot: null); // or just omit relayoutSu btreeRoot
163 layoutDone();
164 return;
165 }
166 */
167 void relayout() {
168 // Override this to perform relayout without your parent's 149 // Override this to perform relayout without your parent's
169 // involvement. 150 // involvement.
170 // 151 //
171 // This is what is called after the first layout(), if you mark 152 // This is called during layout. If sizedByParent is true, then
172 // yourself dirty and don't have a _relayoutSubtreeRoot set; in 153 // performLayout() should not change your dimensions, only do that
173 // other words, either if your parent doesn't care what size you 154 // in performResize(). If sizedByParent is false, then set both
174 // are (and thus didn't pass a relayoutSubtreeRoot to your 155 // your dimensions and do your children's layout here.
175 // layout() method) or if you sized yourself entirely based on
176 // what your parents told you, and not based on your children (and
177 // thus you never called saveRelayoutSubtreeRoot()).
178 // 156 //
179 // In the former case, you can resize yourself here at will. In 157 // When calling layout() on your children, pass in
180 // the latter case, just leave your dimensions unchanged. 158 // "parentUsesSize: true" if your size or layout is dependent on
181 // 159 // your child's size.
182 // If _relayoutSubtreeRoot is set (i.e. you called saveRelayout-
183 // SubtreeRoot() in your layout(), with a relayoutSubtreeRoot
184 // argument that was non-null), then if you mark yourself as dirty
185 // then we'll tell that subtree root instead, and the layout will
186 // occur via the layout() tree rather than starting from this
187 // relayout() method.
188 //
189 // when calling children's layout() methods, skip any children
190 // that have needsLayout == false unless the arguments you are
191 // passing in have changed since the last time
192 assert(_relayoutSubtreeRoot == null);
193 layoutDone();
194 }
195 void layoutDone({bool needsPaint: true}) {
196 // make sure to call this at the end of your layout() or relayout()
197 _needsLayout = false;
198 if (needsPaint)
199 markNeedsPaint();
200 }
201 160
202 // when the parent has rotated (e.g. when the screen has been turned 161 // when the parent has rotated (e.g. when the screen has been turned
203 // 90 degrees), immediately prior to layout() being called for the 162 // 90 degrees), immediately prior to layout() being called for the
204 // new dimensions, rotate() is called with the old and new angles. 163 // new dimensions, rotate() is called with the old and new angles.
205 // The next time paint() is called, the coordinate space will have 164 // The next time paint() is called, the coordinate space will have
206 // been rotated N quarter-turns clockwise, where: 165 // been rotated N quarter-turns clockwise, where:
207 // N = newAngle-oldAngle 166 // N = newAngle-oldAngle
208 // ...but the rendering is expected to remain the same, pixel for 167 // ...but the rendering is expected to remain the same, pixel for
209 // pixel, on the output device. Then, the layout() method or 168 // pixel, on the output device. Then, the layout() method or
210 // equivalent will be invoked. 169 // equivalent will be invoked.
211 170
212 void rotate({ 171 void rotate({
213 int oldAngle, // 0..3 172 int oldAngle, // 0..3
214 int newAngle, // 0..3 173 int newAngle, // 0..3
215 Duration time 174 Duration time
216 }) { } 175 }) { }
217 176
218 177
219 // PAINTING 178 // PAINTING
220 179
221 static bool _debugDoingPaint = false; 180 static bool _debugDoingPaint = false;
222 void markNeedsPaint() { 181 void markNeedsPaint() {
223 assert(!_debugDoingPaint); 182 assert(!_debugDoingPaint);
224 // TODO(abarth): It's very redunant to call this for every node in the 183 // TODO(abarth): It's very redundant to call this for every node in the
225 // render tree during layout. We should instead compute a summary bit and 184 // render tree during layout. We should instead compute a summary bit and
226 // call it once at the end of layout. 185 // call it once at the end of layout.
227 sky.view.scheduleFrame(); 186 sky.view.scheduleFrame();
228 } 187 }
229 void paint(RenderNodeDisplayList canvas) { } 188 void paint(RenderNodeDisplayList canvas) { }
230 189
231 190
232 // HIT TESTING 191 // HIT TESTING
233 192
234 void handlePointer(sky.PointerEvent event) { 193 void handlePointer(sky.PointerEvent event) {
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 475
517 // override this to report what dimensions you would have if you 476 // override this to report what dimensions you would have if you
518 // were laid out with the given constraints this can walk the tree 477 // were laid out with the given constraints this can walk the tree
519 // if it must, but it should be as cheap as possible; just get the 478 // if it must, but it should be as cheap as possible; just get the
520 // dimensions and nothing else (e.g. don't calculate hypothetical 479 // dimensions and nothing else (e.g. don't calculate hypothetical
521 // child positions if they're not needed to determine dimensions) 480 // child positions if they're not needed to determine dimensions)
522 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { 481 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) {
523 return new BoxDimensions.withConstraints(constraints); 482 return new BoxDimensions.withConstraints(constraints);
524 } 483 }
525 484
526 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { 485 BoxConstraints get constraints => super.constraints as BoxConstraints;
486 void performResize() {
487 // default behaviour for subclasses that have sizedByParent = true
527 width = constraints.constrainWidth(0.0); 488 width = constraints.constrainWidth(0.0);
528 height = constraints.constrainHeight(0.0); 489 height = constraints.constrainHeight(0.0);
529 layoutDone(); 490 assert(height < double.INFINITY);
491 assert(width < double.INFINITY);
492 }
493 void performLayout() {
494 // descendants have to either override performLayout() to set both
495 // width and height and lay out children, or, set sizedByParent to
496 // true so that performResize()'s logic above does its thing.
497 assert(sizedByParent);
530 } 498 }
531 499
532 bool hitTest(HitTestResult result, { double x, double y }) { 500 bool hitTest(HitTestResult result, { double x, double y }) {
533 hitTestChildren(result, x: x, y: y); 501 hitTestChildren(result, x: x, y: y);
534 result.add(this); 502 result.add(this);
535 return true; 503 return true;
536 } 504 }
537 void hitTestChildren(HitTestResult result, { double x, double y }) { } 505 void hitTestChildren(HitTestResult result, { double x, double y }) { }
538 506
539 double width; 507 double width;
(...skipping 19 matching lines...) Expand all
559 } 527 }
560 528
561 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { 529 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) {
562 assert(padding != null); 530 assert(padding != null);
563 constraints = constraints.deflate(padding); 531 constraints = constraints.deflate(padding);
564 if (child == null) 532 if (child == null)
565 return super.getIntrinsicDimensions(constraints); 533 return super.getIntrinsicDimensions(constraints);
566 return child.getIntrinsicDimensions(constraints); 534 return child.getIntrinsicDimensions(constraints);
567 } 535 }
568 536
569 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { 537 void performLayout() {
570 assert(padding != null); 538 assert(padding != null);
571 constraints = constraints.deflate(padding); 539 BoxConstraints innerConstraints = constraints.deflate(padding);
572 if (child == null) { 540 if (child == null) {
573 width = constraints.constrainWidth(padding.left + padding.right); 541 width = innerConstraints.constrainWidth(padding.left + padding.right);
574 height = constraints.constrainHeight(padding.top + padding.bottom); 542 height = innerConstraints.constrainHeight(padding.top + padding.bottom);
575 return; 543 return;
576 } 544 }
577 if (relayoutSubtreeRoot != null) 545 child.layout(innerConstraints, parentUsesSize: true);
578 saveRelayoutSubtreeRoot(relayoutSubtreeRoot);
579 else
580 relayoutSubtreeRoot = this;
581 child.layout(constraints, relayoutSubtreeRoot: relayoutSubtreeRoot);
582 assert(child.parentData is BoxParentData); 546 assert(child.parentData is BoxParentData);
583 child.parentData.x = padding.left; 547 child.parentData.x = padding.left;
584 child.parentData.y = padding.top; 548 child.parentData.y = padding.top;
585 width = constraints.constrainWidth(padding.left + child.width + padding.righ t); 549 width = constraints.constrainWidth(padding.left + child.width + padding.righ t);
586 height = constraints.constrainHeight(padding.top + child.height + padding.bo ttom); 550 height = constraints.constrainHeight(padding.top + child.height + padding.bo ttom);
587 } 551 }
588 552
589 void paint(RenderNodeDisplayList canvas) { 553 void paint(RenderNodeDisplayList canvas) {
590 if (child != null) 554 if (child != null)
591 canvas.paintChild(child, child.parentData.x, child.parentData.y); 555 canvas.paintChild(child, child.parentData.x, child.parentData.y);
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 if (_decoration.backgroundColor != null) { 621 if (_decoration.backgroundColor != null) {
658 sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor; 622 sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor;
659 canvas.drawCircle(new sky.Rect()..setLTRB(0.0, 0.0, width, height), paint) ; 623 canvas.drawCircle(new sky.Rect()..setLTRB(0.0, 0.0, width, height), paint) ;
660 } 624 }
661 } 625 }
662 } 626 }
663 627
664 628
665 // RENDER VIEW LAYOUT MANAGER 629 // RENDER VIEW LAYOUT MANAGER
666 630
631 class ViewConstraints {
632
633 const ViewConstraints({
634 this.width: 0.0, this.height: 0.0, this.orientation: null
635 });
636
637 final double width;
638 final double height;
639 final int orientation;
640
641 }
642
667 class RenderView extends RenderNode with RenderNodeWithChildMixin<RenderBox> { 643 class RenderView extends RenderNode with RenderNodeWithChildMixin<RenderBox> {
668 644
669 RenderView({ 645 RenderView({
670 RenderBox child, 646 RenderBox child,
671 this.timeForRotation: const Duration(microseconds: 83333) 647 this.timeForRotation: const Duration(microseconds: 83333)
672 }) { 648 }) {
673 this.child = child; 649 this.child = child;
674 } 650 }
675 651
676 double _width; 652 double _width;
677 double get width => _width; 653 double get width => _width;
678 double _height; 654 double _height;
679 double get height => _height; 655 double get height => _height;
680 656
681 int _orientation; // 0..3 657 int _orientation; // 0..3
682 int get orientation => _orientation; 658 int get orientation => _orientation;
683 Duration timeForRotation; 659 Duration timeForRotation;
684 660
685 void layout({ 661 ViewConstraints get constraints => super.constraints as ViewConstraints;
686 double newWidth, 662 bool get sizedByParent => true;
687 double newHeight, 663 void performResize() {
688 int newOrientation 664 if (constraints.orientation != _orientation) {
689 }) { 665 if (_orientation != null && child != null)
690 if (newOrientation != orientation) { 666 child.rotate(oldAngle: _orientation, newAngle: constraints.orientation, time: timeForRotation);
691 if (orientation != null && child != null) 667 _orientation = constraints.orientation;
692 child.rotate(oldAngle: orientation, newAngle: newOrientation, time: time ForRotation);
693 _orientation = newOrientation;
694 } 668 }
695 if ((newWidth != width) || (newHeight != height)) { 669 _width = constraints.width;
696 _width = newWidth; 670 _height = constraints.height;
697 _height = newHeight; 671 assert(height < double.INFINITY);
698 relayout(); 672 assert(width < double.INFINITY);
699 } else {
700 layoutDone();
701 }
702 } 673 }
703 674 void performLayout() {
704 void relayout() {
705 if (child != null) { 675 if (child != null) {
706 child.layout(new BoxConstraints.tight(width: width, height: height)); 676 child.layout(new BoxConstraints.tight(width: width, height: height));
707 assert(child.width == width); 677 assert(child.width == width);
708 assert(child.height == height); 678 assert(child.height == height);
709 } 679 }
710 layoutDone();
711 } 680 }
712 681
713 void rotate({ int oldAngle, int newAngle, Duration time }) { 682 void rotate({ int oldAngle, int newAngle, Duration time }) {
714 assert(false); // nobody tells the screen to rotate, the whole rotate() danc e is started from our layout() 683 assert(false); // nobody tells the screen to rotate, the whole rotate() danc e is started from our performResize()
715 } 684 }
716 685
717 bool hitTest(HitTestResult result, { double x, double y }) { 686 bool hitTest(HitTestResult result, { double x, double y }) {
718 if (child != null && x >= 0.0 && x < child.width && y >= 0.0 && y < child.he ight) 687 if (child != null && x >= 0.0 && x < child.width && y >= 0.0 && y < child.he ight)
719 child.hitTest(result, x: x, y: y); 688 child.hitTest(result, x: x, y: y);
720 result.add(this); 689 result.add(this);
721 return true; 690 return true;
722 } 691 }
723 692
724 void paint(RenderNodeDisplayList canvas) { 693 void paint(RenderNodeDisplayList canvas) {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 while (child != null) { 767 while (child != null) {
799 outerHeight += child.getIntrinsicDimensions(innerConstraints).height; 768 outerHeight += child.getIntrinsicDimensions(innerConstraints).height;
800 assert(child.parentData is BlockParentData); 769 assert(child.parentData is BlockParentData);
801 child = child.parentData.nextSibling; 770 child = child.parentData.nextSibling;
802 } 771 }
803 772
804 return new BoxDimensions(width: outerWidth, 773 return new BoxDimensions(width: outerWidth,
805 height: constraints.constrainHeight(outerHeight)); 774 height: constraints.constrainHeight(outerHeight));
806 } 775 }
807 776
808 BoxConstraints _constraints; // value cached from parent for relayout call 777 void performLayout() {
809 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { 778 assert(constraints is BoxConstraints);
810 if (relayoutSubtreeRoot != null)
811 saveRelayoutSubtreeRoot(relayoutSubtreeRoot);
812 else
813 relayoutSubtreeRoot = this;
814 width = constraints.constrainWidth(constraints.maxWidth); 779 width = constraints.constrainWidth(constraints.maxWidth);
815 assert(width < double.INFINITY); 780 assert(width < double.INFINITY);
816 _constraints = constraints;
817 internalLayout(relayoutSubtreeRoot);
818 }
819
820 void relayout() {
821 internalLayout(this);
822 }
823
824 void internalLayout(RenderNode relayoutSubtreeRoot) {
825 assert(_constraints != null);
826 double y = 0.0; 781 double y = 0.0;
827 double innerWidth = width; 782 double innerWidth = width;
828 RenderBox child = firstChild; 783 RenderBox child = firstChild;
829 while (child != null) { 784 while (child != null) {
830 child.layout(new BoxConstraints(minWidth: innerWidth, maxWidth: innerWidth ), 785 child.layout(new BoxConstraints(minWidth: innerWidth, maxWidth: innerWidth ), parentUsesSize: true);
831 relayoutSubtreeRoot: relayoutSubtreeRoot);
832 assert(child.parentData is BlockParentData); 786 assert(child.parentData is BlockParentData);
833 child.parentData.x = 0.0; 787 child.parentData.x = 0.0;
834 child.parentData.y = y; 788 child.parentData.y = y;
835 y += child.height; 789 y += child.height;
836 child = child.parentData.nextSibling; 790 child = child.parentData.nextSibling;
837 } 791 }
838 height = _constraints.constrainHeight(y); 792 height = constraints.constrainHeight(y);
839 layoutDone();
840 } 793 }
841 794
842 void hitTestChildren(HitTestResult result, { double x, double y }) { 795 void hitTestChildren(HitTestResult result, { double x, double y }) {
843 defaultHitTestChildren(result, x: x, y: y); 796 defaultHitTestChildren(result, x: x, y: y);
844 } 797 }
845 798
846 void paint(RenderNodeDisplayList canvas) { 799 void paint(RenderNodeDisplayList canvas) {
847 super.paint(canvas); 800 super.paint(canvas);
848 defaultPaint(canvas); 801 defaultPaint(canvas);
849 } 802 }
(...skipping 29 matching lines...) Expand all
879 _direction = value; 832 _direction = value;
880 markNeedsLayout(); 833 markNeedsLayout();
881 } 834 }
882 } 835 }
883 836
884 void setParentData(RenderBox child) { 837 void setParentData(RenderBox child) {
885 if (child.parentData is! FlexBoxParentData) 838 if (child.parentData is! FlexBoxParentData)
886 child.parentData = new FlexBoxParentData(); 839 child.parentData = new FlexBoxParentData();
887 } 840 }
888 841
889 BoxConstraints _constraints; // value cached from parent for relayout call 842 bool get sizedByParent => true;
890 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { 843 void performResize() {
891 if (relayoutSubtreeRoot != null)
892 saveRelayoutSubtreeRoot(relayoutSubtreeRoot);
893 else
894 relayoutSubtreeRoot = this;
895 _constraints = constraints;
896 width = _constraints.constrainWidth(_constraints.maxWidth); 844 width = _constraints.constrainWidth(_constraints.maxWidth);
897 height = _constraints.constrainHeight(_constraints.maxHeight); 845 height = _constraints.constrainHeight(_constraints.maxHeight);
898 assert(height < double.INFINITY); 846 assert(height < double.INFINITY);
899 assert(width < double.INFINITY); 847 assert(width < double.INFINITY);
900 internalLayout(relayoutSubtreeRoot);
901 }
902
903 void relayout() {
904 internalLayout(this);
905 } 848 }
906 849
907 int _getFlex(RenderBox child) { 850 int _getFlex(RenderBox child) {
908 assert(child.parentData is FlexBoxParentData); 851 assert(child.parentData is FlexBoxParentData);
909 return child.parentData.flex != null ? child.parentData.flex : 0; 852 return child.parentData.flex != null ? child.parentData.flex : 0;
910 } 853 }
911 854
912 void internalLayout(RenderNode relayoutSubtreeRoot) { 855 void performLayout() {
913 // Based on http://www.w3.org/TR/css-flexbox-1/ Section 9.7 Resolving Flexib le Lengths 856 // Based on http://www.w3.org/TR/css-flexbox-1/ Section 9.7 Resolving Flexib le Lengths
914 // Steps 1-3. Determine used flex factor, size inflexible items, calculate f ree space 857 // Steps 1-3. Determine used flex factor, size inflexible items, calculate f ree space
915 int totalFlex = 0; 858 int totalFlex = 0;
916 assert(_constraints != null); 859 assert(constraints != null);
917 double freeSpace = (_direction == FlexDirection.Horizontal) ? _constraints.m axWidth : _constraints.maxHeight; 860 double freeSpace = (_direction == FlexDirection.Horizontal) ? constraints.ma xWidth : constraints.maxHeight;
918 RenderBox child = firstChild; 861 RenderBox child = firstChild;
919 while (child != null) { 862 while (child != null) {
920 int flex = _getFlex(child); 863 int flex = _getFlex(child);
921 if (flex > 0) { 864 if (flex > 0) {
922 totalFlex += child.parentData.flex; 865 totalFlex += child.parentData.flex;
923 } else { 866 } else {
924 BoxConstraints constraints = new BoxConstraints(maxHeight: _constraints. maxHeight, 867 BoxConstraints innerConstraints = new BoxConstraints(maxHeight: constrai nts.maxHeight,
925 maxWidth: _constraints.m axWidth); 868 maxWidth: constrain ts.maxWidth);
926 child.layout(constraints, 869 child.layout(innerConstraints, parentUsesSize: true);
927 relayoutSubtreeRoot: relayoutSubtreeRoot);
928 freeSpace -= (_direction == FlexDirection.Horizontal) ? child.width : ch ild.height; 870 freeSpace -= (_direction == FlexDirection.Horizontal) ? child.width : ch ild.height;
929 } 871 }
930 child = child.parentData.nextSibling; 872 child = child.parentData.nextSibling;
931 } 873 }
932 874
933 // Steps 4-5. Distribute remaining space to flexible children. 875 // Steps 4-5. Distribute remaining space to flexible children.
934 double spacePerFlex = totalFlex > 0 ? (freeSpace / totalFlex) : 0.0; 876 double spacePerFlex = totalFlex > 0 ? (freeSpace / totalFlex) : 0.0;
935 double usedSpace = 0.0; 877 double usedSpace = 0.0;
936 child = firstChild; 878 child = firstChild;
937 while (child != null) { 879 while (child != null) {
938 int flex = _getFlex(child); 880 int flex = _getFlex(child);
939 if (flex > 0) { 881 if (flex > 0) {
940 double spaceForChild = spacePerFlex * flex; 882 double spaceForChild = spacePerFlex * flex;
941 BoxConstraints constraints; 883 BoxConstraints innerConstraints;
942 switch (_direction) { 884 switch (_direction) {
943 case FlexDirection.Horizontal: 885 case FlexDirection.Horizontal:
944 constraints = new BoxConstraints(maxHeight: _constraints.maxHeight, 886 innerConstraints = new BoxConstraints(maxHeight: constraints.maxHeig ht,
945 minWidth: spaceForChild, 887 minWidth: spaceForChild,
946 maxWidth: spaceForChild); 888 maxWidth: spaceForChild);
947 break; 889 break;
948 case FlexDirection.Vertical: 890 case FlexDirection.Vertical:
949 constraints = new BoxConstraints(minHeight: spaceForChild, 891 innerConstraints = new BoxConstraints(minHeight: spaceForChild,
950 maxHeight: spaceForChild, 892 maxHeight: spaceForChild,
951 maxWidth: _constraints.maxWidth); 893 maxWidth: constraints.maxWidth );
952 break; 894 break;
953 } 895 }
954 child.layout(constraints, relayoutSubtreeRoot: relayoutSubtreeRoot); 896 child.layout(innerConstraints, parentUsesSize: true);
955 } 897 }
956 898
957 // For now, center the flex items in the cross direction 899 // For now, center the flex items in the cross direction
958 switch (_direction) { 900 switch (_direction) {
959 case FlexDirection.Horizontal: 901 case FlexDirection.Horizontal:
960 child.parentData.x = usedSpace; 902 child.parentData.x = usedSpace;
961 usedSpace += child.width; 903 usedSpace += child.width;
962 child.parentData.y = height / 2 - child.height / 2; 904 child.parentData.y = height / 2.0 - child.height / 2.0;
963 break; 905 break;
964 case FlexDirection.Vertical: 906 case FlexDirection.Vertical:
965 child.parentData.y = usedSpace; 907 child.parentData.y = usedSpace;
966 usedSpace += child.height; 908 usedSpace += child.height;
967 child.parentData.x = width / 2 - child.width / 2; 909 child.parentData.x = width / 2.0 - child.width / 2.0;
968 break; 910 break;
969 } 911 }
970 child = child.parentData.nextSibling; 912 child = child.parentData.nextSibling;
971 } 913 }
972 layoutDone();
973 } 914 }
974 915
975 void hitTestChildren(HitTestResult result, { double x, double y }) { 916 void hitTestChildren(HitTestResult result, { double x, double y }) {
976 defaultHitTestChildren(result, x: x, y: y); 917 defaultHitTestChildren(result, x: x, y: y);
977 } 918 }
978 919
979 void paint(RenderNodeDisplayList canvas) { 920 void paint(RenderNodeDisplayList canvas) {
980 super.paint(canvas); 921 super.paint(canvas);
981 defaultPaint(canvas); 922 defaultPaint(canvas);
982 } 923 }
983 } 924 }
OLDNEW
« no previous file with comments | « sky/sdk/lib/framework/fn2.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698