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

Side by Side Diff: sky/sdk/lib/rendering/object.dart

Issue 1222913013: Introduce BlockViewport. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 5 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
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 'dart:math' as math; 5 import 'dart:math' as math;
6 import 'dart:sky' as sky; 6 import 'dart:sky' as sky;
7 import 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path; 7 import 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path;
8 8
9 import '../base/hit_test.dart'; 9 import '../base/hit_test.dart';
10 import '../base/node.dart'; 10 import '../base/node.dart';
(...skipping 21 matching lines...) Expand all
32 void paintChild(RenderObject child, Point point) { 32 void paintChild(RenderObject child, Point point) {
33 child.paint(this, point.toOffset()); 33 child.paint(this, point.toOffset());
34 } 34 }
35 } 35 }
36 36
37 abstract class Constraints { 37 abstract class Constraints {
38 const Constraints(); 38 const Constraints();
39 bool get isTight; 39 bool get isTight;
40 } 40 }
41 41
42 typedef void LayoutCallback(Constraints constraints);
43
42 abstract class RenderObject extends AbstractNode implements HitTestTarget { 44 abstract class RenderObject extends AbstractNode implements HitTestTarget {
43 45
44 // LAYOUT 46 // LAYOUT
45 47
46 // parentData is only for use by the RenderObject that actually lays this 48 // parentData is only for use by the RenderObject that actually lays this
47 // node out, and any other nodes who happen to know exactly what 49 // node out, and any other nodes who happen to know exactly what
48 // kind of node that is. 50 // kind of node that is.
49 dynamic parentData; // TODO(ianh): change the type of this back to ParentData once the analyzer is cleverer 51 dynamic parentData; // TODO(ianh): change the type of this back to ParentData once the analyzer is cleverer
50 void setupParentData(RenderObject child) { 52 void setupParentData(RenderObject child) {
51 // override this to setup .parentData correctly for your class 53 // override this to setup .parentData correctly for your class
52 assert(!debugDoingLayout); 54 assert(debugCanPerformMutations);
53 assert(!debugDoingPaint);
54 if (child.parentData is! ParentData) 55 if (child.parentData is! ParentData)
55 child.parentData = new ParentData(); 56 child.parentData = new ParentData();
56 } 57 }
57 58
58 void adoptChild(RenderObject child) { // only for use by subclasses 59 void adoptChild(RenderObject child) { // only for use by subclasses
59 // call this whenever you decide a node is a child 60 // call this whenever you decide a node is a child
60 assert(!debugDoingLayout); 61 assert(debugCanPerformMutations);
61 assert(!debugDoingPaint);
62 assert(child != null); 62 assert(child != null);
63 setupParentData(child); 63 setupParentData(child);
64 super.adoptChild(child); 64 super.adoptChild(child);
65 markNeedsLayout(); 65 markNeedsLayout();
66 } 66 }
67 void dropChild(RenderObject child) { // only for use by subclasses 67 void dropChild(RenderObject child) { // only for use by subclasses
68 assert(!debugDoingLayout); 68 assert(debugCanPerformMutations);
69 assert(!debugDoingPaint);
70 assert(child != null); 69 assert(child != null);
71 assert(child.parentData != null); 70 assert(child.parentData != null);
72 child._cleanRelayoutSubtreeRoot(); 71 child._cleanRelayoutSubtreeRoot();
73 child.parentData.detach(); 72 child.parentData.detach();
74 super.dropChild(child); 73 super.dropChild(child);
75 markNeedsLayout(); 74 markNeedsLayout();
76 } 75 }
77 76
78 static List<RenderObject> _nodesNeedingLayout = new List<RenderObject>();
79 static bool _debugDoingLayout = false; 77 static bool _debugDoingLayout = false;
80 static bool get debugDoingLayout => _debugDoingLayout; 78 static bool get debugDoingLayout => _debugDoingLayout;
81 bool _debugDoingThisResize = false; 79 bool _debugDoingThisResize = false;
82 bool get debugDoingThisResize => _debugDoingThisResize; 80 bool get debugDoingThisResize => _debugDoingThisResize;
83 bool _debugDoingThisLayout = false; 81 bool _debugDoingThisLayout = false;
84 bool get debugDoingThisLayout => _debugDoingThisLayout; 82 bool get debugDoingThisLayout => _debugDoingThisLayout;
85 static RenderObject _debugActiveLayout = null; 83 static RenderObject _debugActiveLayout = null;
86 static RenderObject get debugActiveLayout => _debugActiveLayout; 84 static RenderObject get debugActiveLayout => _debugActiveLayout;
85 bool _debugDoingThisLayoutWithCallback = false;
86 bool _debugMutationsLocked = false;
87 bool _debugCanParentUseSize; 87 bool _debugCanParentUseSize;
88 bool get debugCanParentUseSize => _debugCanParentUseSize; 88 bool get debugCanParentUseSize => _debugCanParentUseSize;
89 bool get debugCanPerformMutations {
90 RenderObject node = this;
91 while (true) {
92 if (node._debugDoingThisLayoutWithCallback)
93 return true;
94 if (node._debugMutationsLocked)
95 return false;
96 if (node.parent is! RenderObject)
97 return true;
98 node = node.parent;
99 }
100 }
101
102 static List<RenderObject> _nodesNeedingLayout = new List<RenderObject>();
89 bool _needsLayout = true; 103 bool _needsLayout = true;
90 bool get needsLayout => _needsLayout; 104 bool get needsLayout => _needsLayout;
91 RenderObject _relayoutSubtreeRoot; 105 RenderObject _relayoutSubtreeRoot;
92 Constraints _constraints; 106 Constraints _constraints;
93 Constraints get constraints => _constraints; 107 Constraints get constraints => _constraints;
94 bool debugDoesMeetConstraints(); // override this in a subclass to verify that your state matches the constraints object 108 bool debugDoesMeetConstraints(); // override this in a subclass to verify that your state matches the constraints object
95 bool debugAncestorsAlreadyMarkedNeedsLayout() { 109 bool debugAncestorsAlreadyMarkedNeedsLayout() {
96 if (_relayoutSubtreeRoot == null) 110 if (_relayoutSubtreeRoot == null)
97 return true; // we haven't yet done layout even once, so there's nothing f or us to do 111 return true; // we haven't yet done layout even once, so there's nothing f or us to do
98 RenderObject node = this; 112 RenderObject node = this;
99 while (node != _relayoutSubtreeRoot) { 113 while (node != _relayoutSubtreeRoot) {
100 assert(node._relayoutSubtreeRoot == _relayoutSubtreeRoot); 114 assert(node._relayoutSubtreeRoot == _relayoutSubtreeRoot);
101 assert(node.parent != null); 115 assert(node.parent != null);
102 node = node.parent as RenderObject; 116 node = node.parent as RenderObject;
103 if (!node._needsLayout) 117 if (!node._needsLayout)
104 return false; 118 return false;
105 } 119 }
106 assert(node._relayoutSubtreeRoot == node); 120 assert(node._relayoutSubtreeRoot == node);
107 return true; 121 return true;
108 } 122 }
109 void markNeedsLayout() { 123 void markNeedsLayout() {
110 assert(!debugDoingLayout); 124 assert(debugCanPerformMutations);
111 assert(!debugDoingPaint);
112 if (_needsLayout) { 125 if (_needsLayout) {
113 assert(debugAncestorsAlreadyMarkedNeedsLayout()); 126 assert(debugAncestorsAlreadyMarkedNeedsLayout());
114 return; 127 return;
115 } 128 }
116 _needsLayout = true; 129 _needsLayout = true;
117 assert(_relayoutSubtreeRoot != null); 130 assert(_relayoutSubtreeRoot != null);
118 if (_relayoutSubtreeRoot != this) { 131 if (_relayoutSubtreeRoot != this) {
119 final parent = this.parent; // TODO(ianh): Remove this once the analyzer i s cleverer 132 final parent = this.parent; // TODO(ianh): Remove this once the analyzer i s cleverer
120 assert(parent is RenderObject); 133 assert(parent is RenderObject);
121 parent.markNeedsLayout(); 134 parent.markNeedsLayout();
(...skipping 30 matching lines...) Expand all
152 node.layoutWithoutResize(); 165 node.layoutWithoutResize();
153 }); 166 });
154 } finally { 167 } finally {
155 _debugDoingLayout = false; 168 _debugDoingLayout = false;
156 sky.tracing.end('RenderObject.flushLayout'); 169 sky.tracing.end('RenderObject.flushLayout');
157 } 170 }
158 } 171 }
159 void layoutWithoutResize() { 172 void layoutWithoutResize() {
160 try { 173 try {
161 assert(_relayoutSubtreeRoot == this); 174 assert(_relayoutSubtreeRoot == this);
162 _debugCanParentUseSize = false; 175 RenderObject debugPreviousActiveLayout;
163 _debugDoingThisLayout = true; 176 assert(!_debugMutationsLocked);
164 RenderObject debugPreviousActiveLayout = _debugActiveLayout; 177 assert(!_debugDoingThisLayoutWithCallback);
165 _debugActiveLayout = this; 178 assert(() {
179 _debugMutationsLocked = true;
180 _debugCanParentUseSize = false;
181 _debugDoingThisLayout = true;
182 debugPreviousActiveLayout = _debugActiveLayout;
183 _debugActiveLayout = this;
184 return true;
185 });
166 performLayout(); 186 performLayout();
167 _debugActiveLayout = debugPreviousActiveLayout; 187 assert(() {
168 _debugDoingThisLayout = false; 188 _debugActiveLayout = debugPreviousActiveLayout;
169 _debugCanParentUseSize = null; 189 _debugDoingThisLayout = false;
190 _debugCanParentUseSize = null;
191 _debugMutationsLocked = false;
192 return true;
193 });
170 } catch (e, stack) { 194 } catch (e, stack) {
171 print('Exception raised during layout:\n${e}\nContext:\n${this}'); 195 print('Exception raised during layout:\n${e}\nContext:\n${this}');
172 print(stack); 196 print(stack);
173 return; 197 return;
174 } 198 }
175 _needsLayout = false; 199 _needsLayout = false;
176 markNeedsPaint(); 200 markNeedsPaint();
177 } 201 }
178 void layout(Constraints constraints, { bool parentUsesSize: false }) { 202 void layout(Constraints constraints, { bool parentUsesSize: false }) {
179 final parent = this.parent; // TODO(ianh): Remove this once the analyzer is cleverer 203 final parent = this.parent; // TODO(ianh): Remove this once the analyzer is cleverer
180 RenderObject relayoutSubtreeRoot; 204 RenderObject relayoutSubtreeRoot;
181 if (!parentUsesSize || sizedByParent || constraints.isTight || parent is! Re nderObject) 205 if (!parentUsesSize || sizedByParent || constraints.isTight || parent is! Re nderObject)
182 relayoutSubtreeRoot = this; 206 relayoutSubtreeRoot = this;
183 else 207 else
184 relayoutSubtreeRoot = parent._relayoutSubtreeRoot; 208 relayoutSubtreeRoot = parent._relayoutSubtreeRoot;
185 assert(parent == this.parent); // TODO(ianh): Remove this once the analyzer is cleverer 209 assert(parent == this.parent); // TODO(ianh): Remove this once the analyzer is cleverer
186 if (!needsLayout && constraints == _constraints && relayoutSubtreeRoot == _r elayoutSubtreeRoot) 210 if (!needsLayout && constraints == _constraints && relayoutSubtreeRoot == _r elayoutSubtreeRoot)
187 return; 211 return;
188 _constraints = constraints; 212 _constraints = constraints;
189 _relayoutSubtreeRoot = relayoutSubtreeRoot; 213 _relayoutSubtreeRoot = relayoutSubtreeRoot;
190 _debugCanParentUseSize = parentUsesSize; 214 assert(!_debugMutationsLocked);
215 assert(!_debugDoingThisLayoutWithCallback);
216 assert(() {
217 _debugMutationsLocked = true;
218 _debugCanParentUseSize = parentUsesSize;
219 return true;
220 });
191 if (sizedByParent) { 221 if (sizedByParent) {
192 _debugDoingThisResize = true; 222 assert(() { _debugDoingThisResize = true; return true; });
193 performResize(); 223 performResize();
194 _debugDoingThisResize = false; 224 assert(() { _debugDoingThisResize = false; return true; });
195 } 225 }
196 _debugDoingThisLayout = true; 226 RenderObject debugPreviousActiveLayout;
197 RenderObject debugPreviousActiveLayout = _debugActiveLayout; 227 assert(() {
198 _debugActiveLayout = this; 228 _debugDoingThisLayout = true;
229 debugPreviousActiveLayout = _debugActiveLayout;
230 _debugActiveLayout = this;
231 return true;
232 });
199 performLayout(); 233 performLayout();
200 _debugActiveLayout = debugPreviousActiveLayout; 234 assert(() {
201 _debugDoingThisLayout = false; 235 _debugActiveLayout = debugPreviousActiveLayout;
202 _debugCanParentUseSize = null; 236 _debugDoingThisLayout = false;
237 _debugCanParentUseSize = null;
238 _debugMutationsLocked = false;
239 return true;
240 });
203 assert(debugDoesMeetConstraints()); 241 assert(debugDoesMeetConstraints());
204 _needsLayout = false; 242 _needsLayout = false;
205 markNeedsPaint(); 243 markNeedsPaint();
206 assert(parent == this.parent); // TODO(ianh): Remove this once the analyzer is cleverer 244 assert(parent == this.parent); // TODO(ianh): Remove this once the analyzer is cleverer
207 } 245 }
208 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) 246 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)
209 void performResize(); // set the local dimensions, using only the constraints (only called if sizedByParent is true) 247 void performResize(); // set the local dimensions, using only the constraints (only called if sizedByParent is true)
210 void performLayout(); 248 void performLayout();
211 // Override this to perform relayout without your parent's 249 // Override this to perform relayout without your parent's
212 // involvement. 250 // involvement.
213 // 251 //
214 // This is called during layout. If sizedByParent is true, then 252 // This is called during layout. If sizedByParent is true, then
215 // performLayout() should not change your dimensions, only do that 253 // performLayout() should not change your dimensions, only do that
216 // in performResize(). If sizedByParent is false, then set both 254 // in performResize(). If sizedByParent is false, then set both
217 // your dimensions and do your children's layout here. 255 // your dimensions and do your children's layout here.
218 // 256 //
219 // When calling layout() on your children, pass in 257 // When calling layout() on your children, pass in
220 // "parentUsesSize: true" if your size or layout is dependent on 258 // "parentUsesSize: true" if your size or layout is dependent on
221 // your child's size or intrinsic dimensions. 259 // your child's size or intrinsic dimensions.
260 void invokeLayoutCallback(LayoutCallback callback) {
261 assert(_debugMutationsLocked);
262 assert(_debugDoingThisLayout);
263 assert(!_debugDoingThisLayoutWithCallback);
264 assert(() {
265 _debugDoingThisLayoutWithCallback = true;
266 return true;
267 });
268 callback(constraints);
269 assert(() {
270 _debugDoingThisLayoutWithCallback = false;
271 return true;
272 });
273 }
222 274
223 // when the parent has rotated (e.g. when the screen has been turned 275 // when the parent has rotated (e.g. when the screen has been turned
224 // 90 degrees), immediately prior to layout() being called for the 276 // 90 degrees), immediately prior to layout() being called for the
225 // new dimensions, rotate() is called with the old and new angles. 277 // new dimensions, rotate() is called with the old and new angles.
226 // The next time paint() is called, the coordinate space will have 278 // The next time paint() is called, the coordinate space will have
227 // been rotated N quarter-turns clockwise, where: 279 // been rotated N quarter-turns clockwise, where:
228 // N = newAngle-oldAngle 280 // N = newAngle-oldAngle
229 // ...but the rendering is expected to remain the same, pixel for 281 // ...but the rendering is expected to remain the same, pixel for
230 // pixel, on the output device. Then, the layout() method or 282 // pixel, on the output device. Then, the layout() method or
231 // equivalent will be invoked. 283 // equivalent will be invoked.
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 } 496 }
445 void addAll(List<ChildType> children) { 497 void addAll(List<ChildType> children) {
446 if (children != null) 498 if (children != null)
447 for (ChildType child in children) 499 for (ChildType child in children)
448 add(child); 500 add(child);
449 } 501 }
450 void _removeFromChildList(ChildType child) { 502 void _removeFromChildList(ChildType child) {
451 assert(child.parentData is ParentDataType); 503 assert(child.parentData is ParentDataType);
452 assert(_debugUltimatePreviousSiblingOf(child, equals: _firstChild)); 504 assert(_debugUltimatePreviousSiblingOf(child, equals: _firstChild));
453 assert(_debugUltimateNextSiblingOf(child, equals: _lastChild)); 505 assert(_debugUltimateNextSiblingOf(child, equals: _lastChild));
454 _childCount -= 1;
455 assert(_childCount >= 0); 506 assert(_childCount >= 0);
456 if (child.parentData.previousSibling == null) { 507 if (child.parentData.previousSibling == null) {
457 assert(_firstChild == child); 508 assert(_firstChild == child);
458 _firstChild = child.parentData.nextSibling; 509 _firstChild = child.parentData.nextSibling;
459 } else { 510 } else {
460 assert(child.parentData.previousSibling.parentData is ParentDataType); 511 assert(child.parentData.previousSibling.parentData is ParentDataType);
461 child.parentData.previousSibling.parentData.nextSibling = child.parentData .nextSibling; 512 child.parentData.previousSibling.parentData.nextSibling = child.parentData .nextSibling;
462 } 513 }
463 if (child.parentData.nextSibling == null) { 514 if (child.parentData.nextSibling == null) {
464 assert(_lastChild == child); 515 assert(_lastChild == child);
465 _lastChild = child.parentData.previousSibling; 516 _lastChild = child.parentData.previousSibling;
466 } else { 517 } else {
467 assert(child.parentData.nextSibling.parentData is ParentDataType); 518 assert(child.parentData.nextSibling.parentData is ParentDataType);
468 child.parentData.nextSibling.parentData.previousSibling = child.parentData .previousSibling; 519 child.parentData.nextSibling.parentData.previousSibling = child.parentData .previousSibling;
469 } 520 }
470 child.parentData.previousSibling = null; 521 child.parentData.previousSibling = null;
471 child.parentData.nextSibling = null; 522 child.parentData.nextSibling = null;
523 _childCount -= 1;
472 } 524 }
473 void remove(ChildType child) { 525 void remove(ChildType child) {
474 _removeFromChildList(child); 526 _removeFromChildList(child);
475 dropChild(child); 527 dropChild(child);
476 } 528 }
529 void removeAll() {
530 ChildType child = _firstChild;
531 while (child != null) {
532 assert(child.parentData is ParentDataType);
533 ChildType next = child.parentData.nextSibling;
534 child.parentData.previousSibling = null;
535 child.parentData.nextSibling = null;
536 dropChild(child);
537 child = next;
538 }
539 _firstChild = null;
540 _lastChild = null;
541 _childCount = 0;
542 }
477 void move(ChildType child, { ChildType before }) { 543 void move(ChildType child, { ChildType before }) {
478 assert(child != this); 544 assert(child != this);
479 assert(before != this); 545 assert(before != this);
480 assert(child != before); 546 assert(child != before);
481 assert(child.parent == this); 547 assert(child.parent == this);
482 assert(child.parentData is ParentDataType); 548 assert(child.parentData is ParentDataType);
483 if (child.parentData.nextSibling == before) 549 if (child.parentData.nextSibling == before)
484 return; 550 return;
485 _removeFromChildList(child); 551 _removeFromChildList(child);
486 _addToChildList(child, before: before); 552 _addToChildList(child, before: before);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 int count = 1; 596 int count = 1;
531 ChildType child = _firstChild; 597 ChildType child = _firstChild;
532 while (child != null) { 598 while (child != null) {
533 result += '${prefix}child ${count}: ${child.toString(prefix)}'; 599 result += '${prefix}child ${count}: ${child.toString(prefix)}';
534 count += 1; 600 count += 1;
535 child = child.parentData.nextSibling; 601 child = child.parentData.nextSibling;
536 } 602 }
537 return result; 603 return result;
538 } 604 }
539 } 605 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698