OLD | NEW |
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:async'; | 5 import 'dart:async'; |
6 import 'dart:collection'; | 6 import 'dart:collection'; |
7 import 'dart:mirrors'; | 7 import 'dart:mirrors'; |
8 import 'dart:sky' as sky; | 8 import 'dart:sky' as sky; |
9 | 9 |
10 import '../app/view.dart'; | 10 import '../app/view.dart'; |
11 import '../rendering/box.dart'; | 11 import '../rendering/box.dart'; |
12 import '../rendering/object.dart'; | 12 import '../rendering/object.dart'; |
13 | 13 |
14 export '../rendering/box.dart' show BoxConstraints, BoxDecoration, Border, Borde
rSide, EdgeDims; | 14 export '../rendering/box.dart' show BoxConstraints, BoxDecoration, Border, Borde
rSide, EdgeDims; |
15 export '../rendering/flex.dart' show FlexDirection; | 15 export '../rendering/flex.dart' show FlexDirection; |
16 export '../rendering/object.dart' show Point, Size, Rect, Color, Paint, Path; | 16 export '../rendering/object.dart' show Point, Size, Rect, Color, Paint, Path; |
17 | 17 |
18 | |
19 // final sky.Tracing _tracing = sky.window.tracing; | |
20 | |
21 final bool _shouldLogRenderDuration = false; | 18 final bool _shouldLogRenderDuration = false; |
22 | 19 |
23 /* | 20 // All Effen nodes derive from UINode. All nodes have a _parent, a _key and |
24 * All Effen nodes derive from UINode. All nodes have a _parent, a _key and | 21 // can be sync'd. |
25 * can be sync'd. | |
26 */ | |
27 abstract class UINode { | 22 abstract class UINode { |
28 | 23 |
29 UINode({ Object key }) { | 24 UINode({ String key }) { |
30 _key = key == null ? "$runtimeType" : "$runtimeType-$key"; | 25 _key = key == null ? "$runtimeType" : "$runtimeType-$key"; |
31 assert(this is AbstractUINodeRoot || _inRenderDirtyComponents); // you shoul
d not build the UI tree ahead of time, build it only during build() | 26 assert(this is AbstractUINodeRoot || _inRenderDirtyComponents); // you shoul
d not build the UI tree ahead of time, build it only during build() |
32 } | 27 } |
33 | 28 |
34 String _key; | 29 String _key; |
35 String get key => _key; | 30 String get key => _key; |
36 | 31 |
37 UINode _parent; | 32 UINode _parent; |
38 UINode get parent => _parent; | 33 UINode get parent => _parent; |
39 | 34 |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 return node; | 145 return node; |
151 } | 146 } |
152 } | 147 } |
153 | 148 |
154 | 149 |
155 // Descendants of TagNode provide a way to tag RenderObjectWrapper and | 150 // Descendants of TagNode provide a way to tag RenderObjectWrapper and |
156 // Component nodes with annotations, such as event listeners, | 151 // Component nodes with annotations, such as event listeners, |
157 // stylistic information, etc. | 152 // stylistic information, etc. |
158 abstract class TagNode extends UINode { | 153 abstract class TagNode extends UINode { |
159 | 154 |
160 TagNode(UINode content, { Object key }) : this.content = content, super(key: k
ey); | 155 TagNode(UINode content, { String key }) |
| 156 : this.content = content, super(key: key); |
161 | 157 |
162 UINode content; | 158 UINode content; |
163 | 159 |
164 void _sync(UINode old, dynamic slot) { | 160 void _sync(UINode old, dynamic slot) { |
165 UINode oldContent = old == null ? null : (old as TagNode).content; | 161 UINode oldContent = old == null ? null : (old as TagNode).content; |
166 content = syncChild(content, oldContent, slot); | 162 content = syncChild(content, oldContent, slot); |
167 assert(content.root != null); | 163 assert(content.root != null); |
168 _root = content.root; | 164 _root = content.root; |
169 assert(_root == root); // in case a subclass reintroduces it | 165 assert(_root == root); // in case a subclass reintroduces it |
170 } | 166 } |
171 | 167 |
172 void remove() { | 168 void remove() { |
173 if (content != null) | 169 if (content != null) |
174 removeChild(content); | 170 removeChild(content); |
175 super.remove(); | 171 super.remove(); |
176 } | 172 } |
177 | 173 |
178 } | 174 } |
179 | 175 |
180 class ParentDataNode extends TagNode { | 176 class ParentDataNode extends TagNode { |
181 ParentDataNode(UINode content, this.parentData, { Object key }): super(content
, key: key); | 177 ParentDataNode(UINode content, this.parentData, { String key }) |
| 178 : super(content, key: key); |
182 final ParentData parentData; | 179 final ParentData parentData; |
183 } | 180 } |
184 | 181 |
185 typedef void GestureEventListener(sky.GestureEvent e); | 182 typedef void GestureEventListener(sky.GestureEvent e); |
186 typedef void PointerEventListener(sky.PointerEvent e); | 183 typedef void PointerEventListener(sky.PointerEvent e); |
187 typedef void EventListener(sky.Event e); | 184 typedef void EventListener(sky.Event e); |
188 | 185 |
189 class EventListenerNode extends TagNode { | 186 class EventListenerNode extends TagNode { |
190 | 187 |
191 EventListenerNode(UINode content, { | 188 EventListenerNode(UINode content, { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 if (listener != null) { | 265 if (listener != null) { |
269 listener(e); | 266 listener(e); |
270 } | 267 } |
271 } | 268 } |
272 | 269 |
273 } | 270 } |
274 | 271 |
275 | 272 |
276 abstract class Component extends UINode { | 273 abstract class Component extends UINode { |
277 | 274 |
278 Component({ Object key, bool stateful }) | 275 Component({ String key, bool stateful }) |
279 : _stateful = stateful != null ? stateful : false, | 276 : _stateful = stateful != null ? stateful : false, |
280 _order = _currentOrder + 1, | 277 _order = _currentOrder + 1, |
281 super(key: key); | 278 super(key: key); |
282 | 279 |
283 Component.fromArgs(Object key, bool stateful) | |
284 : this(key: key, stateful: stateful); | |
285 | |
286 static Component _currentlyBuilding; | 280 static Component _currentlyBuilding; |
287 bool get _isBuilding => _currentlyBuilding == this; | 281 bool get _isBuilding => _currentlyBuilding == this; |
288 | 282 |
289 bool _stateful; | 283 bool _stateful; |
290 bool _dirty = true; | 284 bool _dirty = true; |
291 bool _disqualifiedFromEverAppearingAgain = false; | 285 bool _disqualifiedFromEverAppearingAgain = false; |
292 | 286 |
293 UINode _built; | 287 UINode _built; |
294 dynamic _slot; // cached slot from the last time we were synced | 288 dynamic _slot; // cached slot from the last time we were synced |
295 | 289 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 // (but don't call super.syncFields() if you inherit directly from | 328 // (but don't call super.syncFields() if you inherit directly from |
335 // Component, since that'll fire an assert). | 329 // Component, since that'll fire an assert). |
336 // If you don't ever become stateful, then don't override this. | 330 // If you don't ever become stateful, then don't override this. |
337 void syncFields(Component source) { | 331 void syncFields(Component source) { |
338 assert(false); | 332 assert(false); |
339 } | 333 } |
340 | 334 |
341 final int _order; | 335 final int _order; |
342 static int _currentOrder = 0; | 336 static int _currentOrder = 0; |
343 | 337 |
344 /* There are three cases here: | 338 // There are three cases here: |
345 * 1) Building for the first time: | 339 // 1) Building for the first time: |
346 * assert(_built == null && old == null) | 340 // assert(_built == null && old == null) |
347 * 2) Re-building (because a dirty flag got set): | 341 // 2) Re-building (because a dirty flag got set): |
348 * assert(_built != null && old == null) | 342 // assert(_built != null && old == null) |
349 * 3) Syncing against an old version | 343 // 3) Syncing against an old version |
350 * assert(_built == null && old != null) | 344 // assert(_built == null && old != null) |
351 */ | |
352 void _sync(UINode old, dynamic slot) { | 345 void _sync(UINode old, dynamic slot) { |
353 assert(_built == null || old == null); | 346 assert(_built == null || old == null); |
354 assert(!_disqualifiedFromEverAppearingAgain); | 347 assert(!_disqualifiedFromEverAppearingAgain); |
355 | 348 |
356 Component oldComponent = old as Component; | 349 Component oldComponent = old as Component; |
357 | 350 |
358 _slot = slot; | 351 _slot = slot; |
359 | 352 |
360 var oldBuilt; | 353 var oldBuilt; |
361 if (oldComponent == null) { | 354 if (oldComponent == null) { |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 assert(!_inRenderDirtyComponents); | 442 assert(!_inRenderDirtyComponents); |
450 _dirtyComponents.add(c); | 443 _dirtyComponents.add(c); |
451 | 444 |
452 if (!_buildScheduled) { | 445 if (!_buildScheduled) { |
453 _buildScheduled = true; | 446 _buildScheduled = true; |
454 new Future.microtask(_buildDirtyComponents); | 447 new Future.microtask(_buildDirtyComponents); |
455 } | 448 } |
456 } | 449 } |
457 | 450 |
458 | 451 |
459 /* | 452 // RenderObjectWrappers correspond to a desired state of a RenderObject. |
460 * RenderObjectWrappers correspond to a desired state of a RenderObject. | 453 // They are fully immutable, with one exception: A UINode which is a |
461 * They are fully immutable, with one exception: A UINode which is a | 454 // Component which lives within an MultiChildRenderObjectWrapper's |
462 * Component which lives within an MultiChildRenderObjectWrapper's | 455 // children list, may be replaced with the "old" instance if it has |
463 * children list, may be replaced with the "old" instance if it has | 456 // become stateful. |
464 * become stateful. | |
465 */ | |
466 abstract class RenderObjectWrapper extends UINode { | 457 abstract class RenderObjectWrapper extends UINode { |
467 | 458 |
468 RenderObjectWrapper({ | 459 RenderObjectWrapper({ String key }) : super(key: key); |
469 Object key | |
470 }) : super(key: key); | |
471 | 460 |
472 RenderObject createNode(); | 461 RenderObject createNode(); |
473 | 462 |
474 void insert(RenderObjectWrapper child, dynamic slot); | 463 void insert(RenderObjectWrapper child, dynamic slot); |
475 | 464 |
476 static final Map<RenderObject, RenderObjectWrapper> _nodeMap = | 465 static final Map<RenderObject, RenderObjectWrapper> _nodeMap = |
477 new HashMap<RenderObject, RenderObjectWrapper>(); | 466 new HashMap<RenderObject, RenderObjectWrapper>(); |
478 | 467 |
479 static RenderObjectWrapper _getMounted(RenderObject node) => _nodeMap[node]; | 468 static RenderObjectWrapper _getMounted(RenderObject node) => _nodeMap[node]; |
480 | 469 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 | 506 |
518 void remove() { | 507 void remove() { |
519 assert(root != null); | 508 assert(root != null); |
520 _nodeMap.remove(root); | 509 _nodeMap.remove(root); |
521 super.remove(); | 510 super.remove(); |
522 } | 511 } |
523 } | 512 } |
524 | 513 |
525 abstract class OneChildRenderObjectWrapper extends RenderObjectWrapper { | 514 abstract class OneChildRenderObjectWrapper extends RenderObjectWrapper { |
526 | 515 |
527 OneChildRenderObjectWrapper({ UINode child, Object key }) : _child = child, su
per(key: key); | 516 OneChildRenderObjectWrapper({ UINode child, String key }) |
| 517 : _child = child, super(key: key); |
528 | 518 |
529 UINode _child; | 519 UINode _child; |
530 UINode get child => _child; | 520 UINode get child => _child; |
531 | 521 |
532 void syncRenderObject(RenderObjectWrapper old) { | 522 void syncRenderObject(RenderObjectWrapper old) { |
533 super.syncRenderObject(old); | 523 super.syncRenderObject(old); |
534 UINode oldChild = old == null ? null : (old as OneChildRenderObjectWrapper).
child; | 524 UINode oldChild = old == null ? null : (old as OneChildRenderObjectWrapper).
child; |
535 _child = syncChild(child, oldChild, null); | 525 _child = syncChild(child, oldChild, null); |
536 } | 526 } |
537 | 527 |
(...skipping 19 matching lines...) Expand all Loading... |
557 super.remove(); | 547 super.remove(); |
558 } | 548 } |
559 | 549 |
560 } | 550 } |
561 | 551 |
562 abstract class MultiChildRenderObjectWrapper extends RenderObjectWrapper { | 552 abstract class MultiChildRenderObjectWrapper extends RenderObjectWrapper { |
563 | 553 |
564 // In MultiChildRenderObjectWrapper subclasses, slots are RenderObject nodes | 554 // In MultiChildRenderObjectWrapper subclasses, slots are RenderObject nodes |
565 // to use as the "insert before" sibling in ContainerRenderObjectMixin.add() c
alls | 555 // to use as the "insert before" sibling in ContainerRenderObjectMixin.add() c
alls |
566 | 556 |
567 MultiChildRenderObjectWrapper({ | 557 MultiChildRenderObjectWrapper({ String key, List<UINode> children }) |
568 Object key, | 558 : this.children = children == null ? const [] : children, |
569 List<UINode> children | 559 super(key: key) { |
570 }) : this.children = children == null ? const [] : children, | |
571 super(key: key) { | |
572 assert(!_debugHasDuplicateIds()); | 560 assert(!_debugHasDuplicateIds()); |
573 } | 561 } |
574 | 562 |
575 final List<UINode> children; | 563 final List<UINode> children; |
576 | 564 |
577 void insert(RenderObjectWrapper child, dynamic slot) { | 565 void insert(RenderObjectWrapper child, dynamic slot) { |
578 final root = this.root; // TODO(ianh): Remove this once the analyzer is clev
erer | 566 final root = this.root; // TODO(ianh): Remove this once the analyzer is clev
erer |
579 assert(slot == null || slot is RenderObject); | 567 assert(slot == null || slot is RenderObject); |
580 assert(root is ContainerRenderObjectMixin); | 568 assert(root is ContainerRenderObjectMixin); |
581 root.add(child.root, before: slot); | 569 root.add(child.root, before: slot); |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
849 if (root.parent == null) { | 837 if (root.parent == null) { |
850 // we haven't attached it yet | 838 // we haven't attached it yet |
851 assert(_container.child == null); | 839 assert(_container.child == null); |
852 _container.child = root; | 840 _container.child = root; |
853 } | 841 } |
854 assert(root.parent == _container); | 842 assert(root.parent == _container); |
855 } | 843 } |
856 | 844 |
857 UINode build() => builder(); | 845 UINode build() => builder(); |
858 } | 846 } |
OLD | NEW |