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

Side by Side Diff: sky/sdk/lib/framework/rendering/object.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
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 'dart:sky' as sky;
7 import 'dart:sky' show Point, Size, Rect, Color, Paint, Path;
8
9 import '../node.dart';
10 import '../scheduler.dart' as scheduler;
11
12 export 'dart:sky' show Point, Size, Rect, Color, Paint, Path;
13
14 class ParentData {
15 void detach() {
16 detachSiblings();
17 }
18 void detachSiblings() { } // workaround for lack of inter-class mixins in Dart
19 void merge(ParentData other) {
20 // override this in subclasses to merge in data from other into this
21 assert(other.runtimeType == this.runtimeType);
22 }
23 String toString() => '<none>';
24 }
25
26 const kLayoutDirections = 4;
27
28 class RenderObjectDisplayList extends sky.PictureRecorder {
29 RenderObjectDisplayList(double width, double height) : super(width, height);
30 void paintChild(RenderObject child, Point position) {
31 translate(position.x, position.y);
32 child.paint(this);
33 translate(-position.x, -position.y);
34 }
35 }
36
37 abstract class RenderObject extends AbstractNode {
38
39 // LAYOUT
40
41 // parentData is only for use by the RenderObject that actually lays this
42 // node out, and any other nodes who happen to know exactly what
43 // kind of node that is.
44 dynamic parentData; // TODO(ianh): change the type of this back to ParentData once the analyzer is cleverer
45 void setParentData(RenderObject child) {
46 // override this to setup .parentData correctly for your class
47 assert(!debugDoingLayout);
48 assert(!debugDoingPaint);
49 if (child.parentData is! ParentData)
50 child.parentData = new ParentData();
51 }
52
53 void adoptChild(RenderObject child) { // only for use by subclasses
54 // call this whenever you decide a node is a child
55 assert(!debugDoingLayout);
56 assert(!debugDoingPaint);
57 assert(child != null);
58 setParentData(child);
59 super.adoptChild(child);
60 markNeedsLayout();
61 }
62 void dropChild(RenderObject child) { // only for use by subclasses
63 assert(!debugDoingLayout);
64 assert(!debugDoingPaint);
65 assert(child != null);
66 assert(child.parentData != null);
67 child.parentData.detach();
68 if (child._relayoutSubtreeRoot != child) {
69 child._relayoutSubtreeRoot = null;
70 child._needsLayout = true;
71 }
72 super.dropChild(child);
73 markNeedsLayout();
74 }
75
76 static List<RenderObject> _nodesNeedingLayout = new List<RenderObject>();
77 static bool _debugDoingLayout = false;
78 static bool get debugDoingLayout => _debugDoingLayout;
79 bool _needsLayout = true;
80 bool get needsLayout => _needsLayout;
81 RenderObject _relayoutSubtreeRoot;
82 dynamic _constraints;
83 dynamic get constraints => _constraints;
84 bool debugAncestorsAlreadyMarkedNeedsLayout() {
85 if (_relayoutSubtreeRoot == null)
86 return true; // we haven't yet done layout even once, so there's nothing f or us to do
87 RenderObject node = this;
88 while (node != _relayoutSubtreeRoot) {
89 assert(node._relayoutSubtreeRoot == _relayoutSubtreeRoot);
90 assert(node.parent != null);
91 node = node.parent as RenderObject;
92 if (!node._needsLayout)
93 return false;
94 }
95 assert(node._relayoutSubtreeRoot == node);
96 return true;
97 }
98 void markNeedsLayout() {
99 assert(!debugDoingLayout);
100 assert(!debugDoingPaint);
101 if (_needsLayout) {
102 assert(debugAncestorsAlreadyMarkedNeedsLayout());
103 return;
104 }
105 _needsLayout = true;
106 assert(_relayoutSubtreeRoot != null);
107 if (_relayoutSubtreeRoot != this) {
108 final parent = this.parent; // TODO(ianh): Remove this once the analyzer i s cleverer
109 assert(parent is RenderObject);
110 parent.markNeedsLayout();
111 assert(parent == this.parent); // TODO(ianh): Remove this once the analyze r is cleverer
112 } else {
113 _nodesNeedingLayout.add(this);
114 scheduler.ensureVisualUpdate();
115 }
116 }
117 void scheduleInitialLayout() {
118 assert(attached);
119 assert(parent == null);
120 assert(_relayoutSubtreeRoot == null);
121 _relayoutSubtreeRoot = this;
122 _nodesNeedingLayout.add(this);
123 scheduler.ensureVisualUpdate();
124 }
125 static void flushLayout() {
126 _debugDoingLayout = true;
127 List<RenderObject> dirtyNodes = _nodesNeedingLayout;
128 _nodesNeedingLayout = new List<RenderObject>();
129 dirtyNodes..sort((a, b) => a.depth - b.depth)..forEach((node) {
130 if (node._needsLayout && node.attached)
131 node.layoutWithoutResize();
132 });
133 _debugDoingLayout = false;
134 }
135 void layoutWithoutResize() {
136 try {
137 assert(_relayoutSubtreeRoot == this);
138 performLayout();
139 } catch (e, stack) {
140 print('Exception raised during layout of ${this}: ${e}');
141 print(stack);
142 return;
143 }
144 _needsLayout = false;
145 }
146 void layout(dynamic constraints, { bool parentUsesSize: false }) {
147 final parent = this.parent; // TODO(ianh): Remove this once the analyzer is cleverer
148 RenderObject relayoutSubtreeRoot;
149 if (!parentUsesSize || sizedByParent || parent is! RenderObject)
150 relayoutSubtreeRoot = this;
151 else
152 relayoutSubtreeRoot = parent._relayoutSubtreeRoot;
153 assert(parent == this.parent); // TODO(ianh): Remove this once the analyzer is cleverer
154 if (!needsLayout && constraints == _constraints && relayoutSubtreeRoot == _r elayoutSubtreeRoot)
155 return;
156 _constraints = constraints;
157 _relayoutSubtreeRoot = relayoutSubtreeRoot;
158 if (sizedByParent)
159 performResize();
160 performLayout();
161 _needsLayout = false;
162 markNeedsPaint();
163 assert(parent == this.parent); // TODO(ianh): Remove this once the analyzer is cleverer
164 }
165 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)
166 void performResize(); // set the local dimensions, using only the constraints (only called if sizedByParent is true)
167 void performLayout();
168 // Override this to perform relayout without your parent's
169 // involvement.
170 //
171 // This is called during layout. If sizedByParent is true, then
172 // performLayout() should not change your dimensions, only do that
173 // in performResize(). If sizedByParent is false, then set both
174 // your dimensions and do your children's layout here.
175 //
176 // When calling layout() on your children, pass in
177 // "parentUsesSize: true" if your size or layout is dependent on
178 // your child's size.
179
180 // when the parent has rotated (e.g. when the screen has been turned
181 // 90 degrees), immediately prior to layout() being called for the
182 // new dimensions, rotate() is called with the old and new angles.
183 // The next time paint() is called, the coordinate space will have
184 // been rotated N quarter-turns clockwise, where:
185 // N = newAngle-oldAngle
186 // ...but the rendering is expected to remain the same, pixel for
187 // pixel, on the output device. Then, the layout() method or
188 // equivalent will be invoked.
189
190 void rotate({
191 int oldAngle, // 0..3
192 int newAngle, // 0..3
193 Duration time
194 }) { }
195
196
197 // PAINTING
198
199 static bool debugDoingPaint = false;
200 void markNeedsPaint() {
201 assert(!debugDoingPaint);
202 scheduler.ensureVisualUpdate();
203 }
204 void paint(RenderObjectDisplayList canvas) { }
205
206
207 // EVENTS
208
209 void handleEvent(sky.Event event, HitTestEntry entry) {
210 // override this if you have a client, to hand it to the client
211 // override this if you want to do anything with the event
212 }
213
214
215 // HIT TESTING
216
217 // RenderObject subclasses are expected to have a method like the
218 // following (with the signature being whatever passes for coordinates
219 // for this particular class):
220 // bool hitTest(HitTestResult result, { Point position }) {
221 // // If (x,y) is not inside this node, then return false. (You
222 // // can assume that the given coordinate is inside your
223 // // dimensions. You only need to check this if you're an
224 // // irregular shape, e.g. if you have a hole.)
225 // // Otherwise:
226 // // For each child that intersects x,y, in z-order starting from the top,
227 // // call hitTest() for that child, passing it /result/, and the coordinate s
228 // // converted to the child's coordinate origin, and stop at the first chil d
229 // // that returns true.
230 // // Then, add yourself to /result/, and return true.
231 // }
232 // You must not add yourself to /result/ if you return false.
233
234
235 String toString([String prefix = '']) {
236 String header = '${runtimeType}';
237 if (_relayoutSubtreeRoot != null && _relayoutSubtreeRoot != this) {
238 int count = 1;
239 RenderObject target = parent;
240 while (target != null && target != _relayoutSubtreeRoot) {
241 target = target.parent as RenderObject;
242 count += 1;
243 }
244 header += ' relayoutSubtreeRoot=up$count';
245 }
246 if (_needsLayout)
247 header += ' NEEDS-LAYOUT';
248 if (!attached)
249 header += ' DETACHED';
250 prefix += ' ';
251 return '${header}\n${debugDescribeSettings(prefix)}${debugDescribeChildren(p refix)}';
252 }
253 String debugDescribeSettings(String prefix) => '${prefix}parentData: ${parentD ata}\n';
254 String debugDescribeChildren(String prefix) => '';
255
256 }
257
258 class HitTestEntry {
259 const HitTestEntry(this.target);
260
261 final RenderObject target;
262 }
263
264 class HitTestResult {
265 final List<HitTestEntry> path = new List<HitTestEntry>();
266
267 void add(HitTestEntry data) {
268 path.add(data);
269 }
270 }
271
272 double clamp({ double min: 0.0, double value: 0.0, double max: double.INFINITY } ) {
273 assert(min != null);
274 assert(value != null);
275 assert(max != null);
276 return math.max(min, math.min(max, value));
277 }
278
279
280 // GENERIC MIXIN FOR RENDER NODES WITH ONE CHILD
281
282 abstract class RenderObjectWithChildMixin<ChildType extends RenderObject> implem ents RenderObject {
283 ChildType _child;
284 ChildType get child => _child;
285 void set child (ChildType value) {
286 if (_child != null)
287 dropChild(_child);
288 _child = value;
289 if (_child != null)
290 adoptChild(_child);
291 }
292 void attachChildren() {
293 if (_child != null)
294 _child.attach();
295 }
296 void detachChildren() {
297 if (_child != null)
298 _child.detach();
299 }
300 String debugDescribeChildren(String prefix) {
301 if (child != null)
302 return '${prefix}child: ${child.toString(prefix)}';
303 return '';
304 }
305 }
306
307
308 // GENERIC MIXIN FOR RENDER NODES WITH A LIST OF CHILDREN
309
310 abstract class ContainerParentDataMixin<ChildType extends RenderObject> {
311 ChildType previousSibling;
312 ChildType nextSibling;
313 void detachSiblings() {
314 if (previousSibling != null) {
315 assert(previousSibling.parentData is ContainerParentDataMixin<ChildType>);
316 assert(previousSibling != this);
317 assert(previousSibling.parentData.nextSibling == this);
318 previousSibling.parentData.nextSibling = nextSibling;
319 }
320 if (nextSibling != null) {
321 assert(nextSibling.parentData is ContainerParentDataMixin<ChildType>);
322 assert(nextSibling != this);
323 assert(nextSibling.parentData.previousSibling == this);
324 nextSibling.parentData.previousSibling = previousSibling;
325 }
326 previousSibling = null;
327 nextSibling = null;
328 }
329 }
330
331 abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, Parent DataType extends ContainerParentDataMixin<ChildType>> implements RenderObject {
332 // abstract class that has only InlineNode children
333
334 bool _debugUltimatePreviousSiblingOf(ChildType child, { ChildType equals }) {
335 assert(child.parentData is ParentDataType);
336 while (child.parentData.previousSibling != null) {
337 assert(child.parentData.previousSibling != child);
338 child = child.parentData.previousSibling;
339 assert(child.parentData is ParentDataType);
340 }
341 return child == equals;
342 }
343 bool _debugUltimateNextSiblingOf(ChildType child, { ChildType equals }) {
344 assert(child.parentData is ParentDataType);
345 while (child.parentData.nextSibling != null) {
346 assert(child.parentData.nextSibling != child);
347 child = child.parentData.nextSibling;
348 assert(child.parentData is ParentDataType);
349 }
350 return child == equals;
351 }
352
353 ChildType _firstChild;
354 ChildType _lastChild;
355 void add(ChildType child, { ChildType before }) {
356 assert(child != this);
357 assert(before != this);
358 assert(child != before);
359 assert(child != _firstChild);
360 assert(child != _lastChild);
361 adoptChild(child);
362 assert(child.parentData is ParentDataType);
363 assert(child.parentData.nextSibling == null);
364 assert(child.parentData.previousSibling == null);
365 if (before == null) {
366 // append at the end (_lastChild)
367 child.parentData.previousSibling = _lastChild;
368 if (_lastChild != null) {
369 assert(_lastChild.parentData is ParentDataType);
370 _lastChild.parentData.nextSibling = child;
371 }
372 _lastChild = child;
373 if (_firstChild == null)
374 _firstChild = child;
375 } else {
376 assert(_firstChild != null);
377 assert(_lastChild != null);
378 assert(_debugUltimatePreviousSiblingOf(before, equals: _firstChild));
379 assert(_debugUltimateNextSiblingOf(before, equals: _lastChild));
380 assert(before.parentData is ParentDataType);
381 if (before.parentData.previousSibling == null) {
382 // insert at the start (_firstChild); we'll end up with two or more chil dren
383 assert(before == _firstChild);
384 child.parentData.nextSibling = before;
385 before.parentData.previousSibling = child;
386 _firstChild = child;
387 } else {
388 // insert in the middle; we'll end up with three or more children
389 // set up links from child to siblings
390 child.parentData.previousSibling = before.parentData.previousSibling;
391 child.parentData.nextSibling = before;
392 // set up links from siblings to child
393 assert(child.parentData.previousSibling.parentData is ParentDataType);
394 assert(child.parentData.nextSibling.parentData is ParentDataType);
395 child.parentData.previousSibling.parentData.nextSibling = child;
396 child.parentData.nextSibling.parentData.previousSibling = child;
397 assert(before.parentData.previousSibling == child);
398 }
399 }
400 }
401 void remove(ChildType child) {
402 assert(child.parentData is ParentDataType);
403 assert(_debugUltimatePreviousSiblingOf(child, equals: _firstChild));
404 assert(_debugUltimateNextSiblingOf(child, equals: _lastChild));
405 if (child.parentData.previousSibling == null) {
406 assert(_firstChild == child);
407 _firstChild = child.parentData.nextSibling;
408 } else {
409 assert(child.parentData.previousSibling.parentData is ParentDataType);
410 child.parentData.previousSibling.parentData.nextSibling = child.parentData .nextSibling;
411 }
412 if (child.parentData.nextSibling == null) {
413 assert(_lastChild == child);
414 _lastChild = child.parentData.previousSibling;
415 } else {
416 assert(child.parentData.nextSibling.parentData is ParentDataType);
417 child.parentData.nextSibling.parentData.previousSibling = child.parentData .previousSibling;
418 }
419 child.parentData.previousSibling = null;
420 child.parentData.nextSibling = null;
421 dropChild(child);
422 }
423 void redepthChildren() {
424 ChildType child = _firstChild;
425 while (child != null) {
426 redepthChild(child);
427 assert(child.parentData is ParentDataType);
428 child = child.parentData.nextSibling;
429 }
430 }
431 void attachChildren() {
432 ChildType child = _firstChild;
433 while (child != null) {
434 child.attach();
435 assert(child.parentData is ParentDataType);
436 child = child.parentData.nextSibling;
437 }
438 }
439 void detachChildren() {
440 ChildType child = _firstChild;
441 while (child != null) {
442 child.detach();
443 assert(child.parentData is ParentDataType);
444 child = child.parentData.nextSibling;
445 }
446 }
447
448 ChildType get firstChild => _firstChild;
449 ChildType get lastChild => _lastChild;
450 ChildType childAfter(ChildType child) {
451 assert(child.parentData is ParentDataType);
452 return child.parentData.nextSibling;
453 }
454
455 String debugDescribeChildren(String prefix) {
456 String result = '';
457 int count = 1;
458 ChildType child = _firstChild;
459 while (child != null) {
460 result += '${prefix}child ${count}: ${child.toString(prefix)}';
461 count += 1;
462 child = child.parentData.nextSibling;
463 }
464 return result;
465 }
466 }
OLDNEW
« no previous file with comments | « sky/sdk/lib/framework/rendering/flex.dart ('k') | sky/sdk/lib/framework/rendering/paragraph.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698