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

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

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

Powered by Google App Engine
This is Rietveld 408576698