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 library fn; | 5 library fn; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:collection'; | 8 import 'dart:collection'; |
9 import 'dart:sky' as sky; | 9 import 'dart:sky' as sky; |
10 import 'reflect.dart' as reflect; | 10 import 'reflect.dart' as reflect; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 if (ref != null) { | 60 if (ref != null) { |
61 ref.insertBefore([node]); | 61 ref.insertBefore([node]); |
62 } else { | 62 } else { |
63 parent.appendChild(node); | 63 parent.appendChild(node); |
64 } | 64 } |
65 } | 65 } |
66 | 66 |
67 enum _SyncOperation { IDENTICAL, INSERTION, STATEFUL, STATELESS, REMOVAL } | 67 enum _SyncOperation { IDENTICAL, INSERTION, STATEFUL, STATELESS, REMOVAL } |
68 | 68 |
69 /* | 69 /* |
70 * All Effen nodes derive from Node. All nodes have a _parent, a _key and | 70 * All Effen nodes derive from UINode. All nodes have a _parent, a _key and |
71 * can be sync'd. | 71 * can be sync'd. |
72 */ | 72 */ |
73 abstract class Node { | 73 abstract class UINode { |
74 String _key; | 74 String _key; |
75 Node _parent; | 75 UINode _parent; |
76 sky.Node _root; | 76 sky.Node _root; |
77 bool _defunct = false; | 77 bool _defunct = false; |
78 int _nodeDepth; | 78 int _nodeDepth; |
79 | 79 |
80 Node({ Object key }) { | 80 UINode({ Object key }) { |
81 _key = key == null ? "$runtimeType" : "$runtimeType-$key"; | 81 _key = key == null ? "$runtimeType" : "$runtimeType-$key"; |
82 } | 82 } |
83 | 83 |
84 // Subclasses which implements Nodes that become stateful may return true | 84 // Subclasses which implements Nodes that become stateful may return true |
85 // if the |old| node has become stateful and should be retained. | 85 // if the |old| node has become stateful and should be retained. |
86 bool _willSync(Node old) => false; | 86 bool _willSync(UINode old) => false; |
87 | 87 |
88 void _sync(Node old, sky.ParentNode host, sky.Node insertBefore); | 88 void _sync(UINode old, sky.ParentNode host, sky.Node insertBefore); |
89 | 89 |
90 void _remove() { | 90 void _remove() { |
91 _defunct = true; | 91 _defunct = true; |
92 _root = null; | 92 _root = null; |
93 } | 93 } |
94 | 94 |
95 void _ensureDepth() { | 95 void _ensureDepth() { |
96 if (_nodeDepth == null) { | 96 if (_nodeDepth == null) { |
97 _nodeDepth = 0; | 97 _nodeDepth = 0; |
98 Node parent = _parent; | 98 UINode parent = _parent; |
99 while (parent != null) { | 99 while (parent != null) { |
100 _nodeDepth++; | 100 _nodeDepth++; |
101 parent = parent._parent; | 101 parent = parent._parent; |
102 } | 102 } |
103 } | 103 } |
104 } | 104 } |
105 | 105 |
106 void _trace(String message) { | 106 void _trace(String message) { |
107 if (!_shouldTrace) | 107 if (!_shouldTrace) |
108 return; | 108 return; |
(...skipping 10 matching lines...) Expand all Loading... |
119 | 119 |
120 void _traceSync(_SyncOperation op, String key) { | 120 void _traceSync(_SyncOperation op, String key) { |
121 if (!_shouldTrace) | 121 if (!_shouldTrace) |
122 return; | 122 return; |
123 | 123 |
124 String opString = op.toString().toLowerCase(); | 124 String opString = op.toString().toLowerCase(); |
125 String outString = opString.substring(opString.indexOf('.') + 1); | 125 String outString = opString.substring(opString.indexOf('.') + 1); |
126 _trace('_sync($outString) $key'); | 126 _trace('_sync($outString) $key'); |
127 } | 127 } |
128 | 128 |
129 void _removeChild(Node node) { | 129 void _removeChild(UINode node) { |
130 _traceSync(_SyncOperation.REMOVAL, node._key); | 130 _traceSync(_SyncOperation.REMOVAL, node._key); |
131 node._remove(); | 131 node._remove(); |
132 } | 132 } |
133 | 133 |
134 // Returns the child which should be retained as the child of this node. | 134 // Returns the child which should be retained as the child of this node. |
135 Node _syncChild(Node node, Node oldNode, sky.ParentNode host, | 135 UINode _syncChild(UINode node, UINode oldNode, sky.ParentNode host, |
136 sky.Node insertBefore) { | 136 sky.Node insertBefore) { |
137 | 137 |
138 assert(oldNode == null || node._key == oldNode._key); | 138 assert(oldNode == null || node._key == oldNode._key); |
139 | 139 |
140 if (node == oldNode) { | 140 if (node == oldNode) { |
141 _traceSync(_SyncOperation.IDENTICAL, node._key); | 141 _traceSync(_SyncOperation.IDENTICAL, node._key); |
142 return node; // Nothing to do. Subtrees must be identical. | 142 return node; // Nothing to do. Subtrees must be identical. |
143 } | 143 } |
144 | 144 |
145 // TODO(rafaelw): This eagerly removes the old DOM. It may be that a | 145 // TODO(rafaelw): This eagerly removes the old DOM. It may be that a |
(...skipping 20 matching lines...) Expand all Loading... |
166 } | 166 } |
167 node._sync(oldNode, host, insertBefore); | 167 node._sync(oldNode, host, insertBefore); |
168 if (oldNode != null) | 168 if (oldNode != null) |
169 oldNode._defunct = true; | 169 oldNode._defunct = true; |
170 | 170 |
171 assert(node._root is sky.Node); | 171 assert(node._root is sky.Node); |
172 return node; | 172 return node; |
173 } | 173 } |
174 } | 174 } |
175 | 175 |
176 abstract class ContentNode extends Node { | 176 abstract class ContentNode extends UINode { |
177 Node content; | 177 UINode content; |
178 | 178 |
179 ContentNode(Node content) : this.content = content, super(key: content._key); | 179 ContentNode(UINode content) : this.content = content, super(key: content._key)
; |
180 | 180 |
181 void _sync(Node old, sky.ParentNode host, sky.Node insertBefore) { | 181 void _sync(UINode old, sky.ParentNode host, sky.Node insertBefore) { |
182 Node oldContent = old == null ? null : (old as ContentNode).content; | 182 UINode oldContent = old == null ? null : (old as ContentNode).content; |
183 content = _syncChild(content, oldContent, host, insertBefore); | 183 content = _syncChild(content, oldContent, host, insertBefore); |
184 _root = content._root; | 184 _root = content._root; |
185 } | 185 } |
186 | 186 |
187 void _remove() { | 187 void _remove() { |
188 _removeChild(content); | 188 _removeChild(content); |
189 super._remove(); | 189 super._remove(); |
190 } | 190 } |
191 } | 191 } |
192 | 192 |
193 class StyleNode extends ContentNode { | 193 class StyleNode extends ContentNode { |
194 final Style style; | 194 final Style style; |
195 | 195 |
196 StyleNode(Node content, this.style): super(content); | 196 StyleNode(UINode content, this.style): super(content); |
197 } | 197 } |
198 | 198 |
199 /* | 199 /* |
200 * RenderNodes correspond to a desired state of a sky.Node. They are fully | 200 * RenderNodes correspond to a desired state of a sky.Node. They are fully |
201 * immutable, with one exception: A Node which is a Component which lives within | 201 * immutable, with one exception: A UINode which is a Component which lives with
in |
202 * an Element's children list, may be replaced with the "old" instance if it | 202 * an WrapperNode's children list, may be replaced with the "old" instance if it |
203 * has become stateful. | 203 * has become stateful. |
204 */ | 204 */ |
205 abstract class RenderNode extends Node { | 205 abstract class RenderNode extends UINode { |
206 | 206 |
207 static final Map<sky.Node, RenderNode> _nodeMap = | 207 static final Map<sky.Node, RenderNode> _nodeMap = |
208 new HashMap<sky.Node, RenderNode>(); | 208 new HashMap<sky.Node, RenderNode>(); |
209 | 209 |
210 static RenderNode _getMounted(sky.Node node) => _nodeMap[node]; | 210 static RenderNode _getMounted(sky.Node node) => _nodeMap[node]; |
211 | 211 |
212 RenderNode({ Object key }) : super(key: key); | 212 RenderNode({ Object key }) : super(key: key); |
213 | 213 |
214 RenderNode get _emptyNode; | 214 RenderNode get _emptyNode; |
215 | 215 |
216 sky.Node _createNode(); | 216 sky.Node _createNode(); |
217 | 217 |
218 void _sync(Node old, sky.ParentNode host, sky.Node insertBefore) { | 218 void _sync(UINode old, sky.ParentNode host, sky.Node insertBefore) { |
219 if (old == null) { | 219 if (old == null) { |
220 _root = _createNode(); | 220 _root = _createNode(); |
221 _parentInsertBefore(host, _root, insertBefore); | 221 _parentInsertBefore(host, _root, insertBefore); |
222 old = _emptyNode; | 222 old = _emptyNode; |
223 } else { | 223 } else { |
224 _root = old._root; | 224 _root = old._root; |
225 } | 225 } |
226 | 226 |
227 _nodeMap[_root] = this; | 227 _nodeMap[_root] = this; |
228 _syncNode(old); | 228 _syncNode(old); |
229 } | 229 } |
230 | 230 |
231 void _syncNode(RenderNode old); | 231 void _syncNode(RenderNode old); |
232 | 232 |
233 void _remove() { | 233 void _remove() { |
234 assert(_root != null); | 234 assert(_root != null); |
235 _root.remove(); | 235 _root.remove(); |
236 _nodeMap.remove(_root); | 236 _nodeMap.remove(_root); |
237 super._remove(); | 237 super._remove(); |
238 } | 238 } |
239 } | 239 } |
240 | 240 |
241 typedef GestureEventListener(sky.GestureEvent e); | 241 typedef GestureEventListener(sky.GestureEvent e); |
242 typedef PointerEventListener(sky.PointerEvent e); | 242 typedef PointerEventListener(sky.PointerEvent e); |
243 typedef EventListener(sky.Event e); | 243 typedef EventListener(sky.Event e); |
244 | 244 |
245 class EventTarget extends ContentNode { | 245 class EventListenerNode extends ContentNode { |
246 final Map<String, sky.EventListener> listeners; | 246 final Map<String, sky.EventListener> listeners; |
247 | 247 |
248 static final Set<String> _registeredEvents = new HashSet<String>(); | 248 static final Set<String> _registeredEvents = new HashSet<String>(); |
249 | 249 |
250 static Map<String, sky.EventListener> _createListeners({ | 250 static Map<String, sky.EventListener> _createListeners({ |
251 EventListener onWheel, | 251 EventListener onWheel, |
252 GestureEventListener onGestureFlingCancel, | 252 GestureEventListener onGestureFlingCancel, |
253 GestureEventListener onGestureFlingStart, | 253 GestureEventListener onGestureFlingStart, |
254 GestureEventListener onGestureScrollStart, | 254 GestureEventListener onGestureScrollStart, |
255 GestureEventListener onGestureScrollUpdate, | 255 GestureEventListener onGestureScrollUpdate, |
(...skipping 28 matching lines...) Expand all Loading... |
284 if (onPointerDown != null) | 284 if (onPointerDown != null) |
285 listeners['pointerdown'] = onPointerDown; | 285 listeners['pointerdown'] = onPointerDown; |
286 if (onPointerMove != null) | 286 if (onPointerMove != null) |
287 listeners['pointermove'] = onPointerMove; | 287 listeners['pointermove'] = onPointerMove; |
288 if (onPointerUp != null) | 288 if (onPointerUp != null) |
289 listeners['pointerup'] = onPointerUp; | 289 listeners['pointerup'] = onPointerUp; |
290 | 290 |
291 return listeners; | 291 return listeners; |
292 } | 292 } |
293 | 293 |
294 EventTarget(Node content, { | 294 EventListenerNode(UINode content, { |
295 EventListener onWheel, | 295 EventListener onWheel, |
296 GestureEventListener onGestureFlingCancel, | 296 GestureEventListener onGestureFlingCancel, |
297 GestureEventListener onGestureFlingStart, | 297 GestureEventListener onGestureFlingStart, |
298 GestureEventListener onGestureScrollStart, | 298 GestureEventListener onGestureScrollStart, |
299 GestureEventListener onGestureScrollUpdate, | 299 GestureEventListener onGestureScrollUpdate, |
300 GestureEventListener onGestureTap, | 300 GestureEventListener onGestureTap, |
301 GestureEventListener onGestureTapDown, | 301 GestureEventListener onGestureTapDown, |
302 PointerEventListener onPointerCancel, | 302 PointerEventListener onPointerCancel, |
303 PointerEventListener onPointerDown, | 303 PointerEventListener onPointerDown, |
304 PointerEventListener onPointerMove, | 304 PointerEventListener onPointerMove, |
(...skipping 16 matching lines...) Expand all Loading... |
321 super(content); | 321 super(content); |
322 | 322 |
323 void _handleEvent(sky.Event e) { | 323 void _handleEvent(sky.Event e) { |
324 sky.EventListener listener = listeners[e.type]; | 324 sky.EventListener listener = listeners[e.type]; |
325 if (listener != null) { | 325 if (listener != null) { |
326 listener(e); | 326 listener(e); |
327 } | 327 } |
328 } | 328 } |
329 | 329 |
330 static void _dispatchEvent(sky.Event e) { | 330 static void _dispatchEvent(sky.Event e) { |
331 Node target = RenderNode._getMounted(e.target); | 331 UINode target = RenderNode._getMounted(e.target); |
332 | 332 |
333 // TODO(rafaelw): StopPropagation? | 333 // TODO(rafaelw): StopPropagation? |
334 while (target != null) { | 334 while (target != null) { |
335 if (target is EventTarget) { | 335 if (target is EventListenerNode) { |
336 (target as EventTarget)._handleEvent(e); | 336 (target as EventListenerNode)._handleEvent(e); |
337 } | 337 } |
338 | 338 |
339 target = target._parent; | 339 target = target._parent; |
340 } | 340 } |
341 } | 341 } |
342 | 342 |
343 static void _ensureDocumentListener(String eventType) { | 343 static void _ensureDocumentListener(String eventType) { |
344 if (_registeredEvents.add(eventType)) { | 344 if (_registeredEvents.add(eventType)) { |
345 sky.document.addEventListener(eventType, _dispatchEvent); | 345 sky.document.addEventListener(eventType, _dispatchEvent); |
346 } | 346 } |
347 } | 347 } |
348 | 348 |
349 void _sync(Node old, sky.ParentNode host, sky.Node insertBefore) { | 349 void _sync(UINode old, sky.ParentNode host, sky.Node insertBefore) { |
350 for (var type in listeners.keys) { | 350 for (var type in listeners.keys) { |
351 _ensureDocumentListener(type); | 351 _ensureDocumentListener(type); |
352 } | 352 } |
353 | 353 |
354 super._sync(old, host, insertBefore); | 354 super._sync(old, host, insertBefore); |
355 } | 355 } |
356 } | 356 } |
357 | 357 |
358 class Text extends RenderNode { | 358 class Text extends RenderNode { |
359 final String data; | 359 final String data; |
(...skipping 13 matching lines...) Expand all Loading... |
373 } | 373 } |
374 | 374 |
375 void _syncNode(RenderNode old) { | 375 void _syncNode(RenderNode old) { |
376 if (old == _emptyText) | 376 if (old == _emptyText) |
377 return; // we set inside _createNode(); | 377 return; // we set inside _createNode(); |
378 | 378 |
379 (_root as sky.Text).data = data; | 379 (_root as sky.Text).data = data; |
380 } | 380 } |
381 } | 381 } |
382 | 382 |
383 final List<Node> _emptyList = new List<Node>(); | 383 final List<UINode> _emptyList = new List<UINode>(); |
384 | 384 |
385 abstract class Element extends RenderNode { | 385 abstract class WrapperNode extends RenderNode { |
386 | 386 |
387 String get _tagName; | 387 String get _tagName; |
388 | 388 |
389 sky.Node _createNode() => sky.document.createElement(_tagName); | 389 sky.Node _createNode() => sky.document.createElement(_tagName); |
390 | 390 |
391 final List<Node> children; | 391 final List<UINode> children; |
392 final Style style; | 392 final Style style; |
393 final String inlineStyle; | 393 final String inlineStyle; |
394 | 394 |
395 String _class; | 395 String _class; |
396 | 396 |
397 Element({ | 397 WrapperNode({ |
398 Object key, | 398 Object key, |
399 List<Node> children, | 399 List<UINode> children, |
400 this.style, | 400 this.style, |
401 this.inlineStyle | 401 this.inlineStyle |
402 }) : this.children = children == null ? _emptyList : children, | 402 }) : this.children = children == null ? _emptyList : children, |
403 super(key:key) { | 403 super(key:key) { |
404 | 404 |
405 if (_isInCheckedMode) { | 405 if (_isInCheckedMode) { |
406 _debugReportDuplicateIds(); | 406 _debugReportDuplicateIds(); |
407 } | 407 } |
408 } | 408 } |
409 | 409 |
(...skipping 20 matching lines...) Expand all Loading... |
430 } | 430 } |
431 } | 431 } |
432 | 432 |
433 void _ensureClass() { | 433 void _ensureClass() { |
434 if (_class == null) { | 434 if (_class == null) { |
435 List<Style> styles = new List<Style>(); | 435 List<Style> styles = new List<Style>(); |
436 if (style != null) { | 436 if (style != null) { |
437 styles.add(style); | 437 styles.add(style); |
438 } | 438 } |
439 | 439 |
440 Node parent = _parent; | 440 UINode parent = _parent; |
441 while (parent != null && parent is! RenderNode) { | 441 while (parent != null && parent is! RenderNode) { |
442 if (parent is StyleNode && (parent as StyleNode).style != null) | 442 if (parent is StyleNode && (parent as StyleNode).style != null) |
443 styles.add((parent as StyleNode).style); | 443 styles.add((parent as StyleNode).style); |
444 | 444 |
445 parent = parent._parent; | 445 parent = parent._parent; |
446 } | 446 } |
447 | 447 |
448 _class = styles.map((s) => s._className).join(' '); | 448 _class = styles.map((s) => s._className).join(' '); |
449 } | 449 } |
450 } | 450 } |
451 | 451 |
452 void _syncNode(RenderNode old) { | 452 void _syncNode(RenderNode old) { |
453 Element oldElement = old as Element; | 453 WrapperNode oldWrapperNode = old as WrapperNode; |
454 sky.Element root = _root as sky.Element; | 454 sky.Element root = _root as sky.Element; |
455 | 455 |
456 _ensureClass(); | 456 _ensureClass(); |
457 if (_class != oldElement._class && _class != '') | 457 if (_class != oldWrapperNode._class && _class != '') |
458 root.setAttribute('class', _class); | 458 root.setAttribute('class', _class); |
459 | 459 |
460 if (inlineStyle != oldElement.inlineStyle) | 460 if (inlineStyle != oldWrapperNode.inlineStyle) |
461 root.setAttribute('style', inlineStyle); | 461 root.setAttribute('style', inlineStyle); |
462 | 462 |
463 _syncChildren(oldElement); | 463 _syncChildren(oldWrapperNode); |
464 } | 464 } |
465 | 465 |
466 void _syncChildren(Element oldElement) { | 466 void _syncChildren(WrapperNode oldWrapperNode) { |
467 sky.Element root = _root as sky.Element; | 467 sky.Element root = _root as sky.Element; |
468 assert(root != null); | 468 assert(root != null); |
469 | 469 |
470 var startIndex = 0; | 470 var startIndex = 0; |
471 var endIndex = children.length; | 471 var endIndex = children.length; |
472 | 472 |
473 var oldChildren = oldElement.children; | 473 var oldChildren = oldWrapperNode.children; |
474 var oldStartIndex = 0; | 474 var oldStartIndex = 0; |
475 var oldEndIndex = oldChildren.length; | 475 var oldEndIndex = oldChildren.length; |
476 | 476 |
477 sky.Node nextSibling = null; | 477 sky.Node nextSibling = null; |
478 Node currentNode = null; | 478 UINode currentNode = null; |
479 Node oldNode = null; | 479 UINode oldNode = null; |
480 | 480 |
481 void sync(int atIndex) { | 481 void sync(int atIndex) { |
482 children[atIndex] = _syncChild(currentNode, oldNode, _root, nextSibling); | 482 children[atIndex] = _syncChild(currentNode, oldNode, _root, nextSibling); |
483 } | 483 } |
484 | 484 |
485 // Scan backwards from end of list while nodes can be directly synced | 485 // Scan backwards from end of list while nodes can be directly synced |
486 // without reordering. | 486 // without reordering. |
487 while (endIndex > startIndex && oldEndIndex > oldStartIndex) { | 487 while (endIndex > startIndex && oldEndIndex > oldStartIndex) { |
488 currentNode = children[endIndex - 1]; | 488 currentNode = children[endIndex - 1]; |
489 oldNode = oldChildren[oldEndIndex - 1]; | 489 oldNode = oldChildren[oldEndIndex - 1]; |
490 | 490 |
491 if (currentNode._key != oldNode._key) { | 491 if (currentNode._key != oldNode._key) { |
492 break; | 492 break; |
493 } | 493 } |
494 | 494 |
495 endIndex--; | 495 endIndex--; |
496 oldEndIndex--; | 496 oldEndIndex--; |
497 sync(endIndex); | 497 sync(endIndex); |
498 nextSibling = currentNode._root; | 498 nextSibling = currentNode._root; |
499 } | 499 } |
500 | 500 |
501 HashMap<String, Node> oldNodeIdMap = null; | 501 HashMap<String, UINode> oldNodeIdMap = null; |
502 | 502 |
503 bool oldNodeReordered(String key) { | 503 bool oldNodeReordered(String key) { |
504 return oldNodeIdMap != null && | 504 return oldNodeIdMap != null && |
505 oldNodeIdMap.containsKey(key) && | 505 oldNodeIdMap.containsKey(key) && |
506 oldNodeIdMap[key] == null; | 506 oldNodeIdMap[key] == null; |
507 } | 507 } |
508 | 508 |
509 void advanceOldStartIndex() { | 509 void advanceOldStartIndex() { |
510 oldStartIndex++; | 510 oldStartIndex++; |
511 while (oldStartIndex < oldEndIndex && | 511 while (oldStartIndex < oldEndIndex && |
512 oldNodeReordered(oldChildren[oldStartIndex]._key)) { | 512 oldNodeReordered(oldChildren[oldStartIndex]._key)) { |
513 oldStartIndex++; | 513 oldStartIndex++; |
514 } | 514 } |
515 } | 515 } |
516 | 516 |
517 void ensureOldIdMap() { | 517 void ensureOldIdMap() { |
518 if (oldNodeIdMap != null) | 518 if (oldNodeIdMap != null) |
519 return; | 519 return; |
520 | 520 |
521 oldNodeIdMap = new HashMap<String, Node>(); | 521 oldNodeIdMap = new HashMap<String, UINode>(); |
522 for (int i = oldStartIndex; i < oldEndIndex; i++) { | 522 for (int i = oldStartIndex; i < oldEndIndex; i++) { |
523 var node = oldChildren[i]; | 523 var node = oldChildren[i]; |
524 if (node is! Text) { | 524 if (node is! Text) { |
525 oldNodeIdMap.putIfAbsent(node._key, () => node); | 525 oldNodeIdMap.putIfAbsent(node._key, () => node); |
526 } | 526 } |
527 } | 527 } |
528 } | 528 } |
529 | 529 |
530 bool searchForOldNode() { | 530 bool searchForOldNode() { |
531 if (currentNode is Text) | 531 if (currentNode is Text) |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 // Removals | 573 // Removals |
574 currentNode = null; | 574 currentNode = null; |
575 while (oldStartIndex < oldEndIndex) { | 575 while (oldStartIndex < oldEndIndex) { |
576 oldNode = oldChildren[oldStartIndex]; | 576 oldNode = oldChildren[oldStartIndex]; |
577 _removeChild(oldNode); | 577 _removeChild(oldNode); |
578 advanceOldStartIndex(); | 578 advanceOldStartIndex(); |
579 } | 579 } |
580 } | 580 } |
581 } | 581 } |
582 | 582 |
583 class Container extends Element { | 583 class Container extends WrapperNode { |
584 | 584 |
585 String get _tagName => 'div'; | 585 String get _tagName => 'div'; |
586 | 586 |
587 static final Container _emptyContainer = new Container(); | 587 static final Container _emptyContainer = new Container(); |
588 | 588 |
589 RenderNode get _emptyNode => _emptyContainer; | 589 RenderNode get _emptyNode => _emptyContainer; |
590 | 590 |
591 Container({ | 591 Container({ |
592 Object key, | 592 Object key, |
593 List<Node> children, | 593 List<UINode> children, |
594 Style style, | 594 Style style, |
595 String inlineStyle | 595 String inlineStyle |
596 }) : super( | 596 }) : super( |
597 key: key, | 597 key: key, |
598 children: children, | 598 children: children, |
599 style: style, | 599 style: style, |
600 inlineStyle: inlineStyle | 600 inlineStyle: inlineStyle |
601 ); | 601 ); |
602 } | 602 } |
603 | 603 |
604 class Image extends Element { | 604 class Image extends WrapperNode { |
605 | 605 |
606 String get _tagName => 'img'; | 606 String get _tagName => 'img'; |
607 | 607 |
608 static final Image _emptyImage = new Image(); | 608 static final Image _emptyImage = new Image(); |
609 | 609 |
610 RenderNode get _emptyNode => _emptyImage; | 610 RenderNode get _emptyNode => _emptyImage; |
611 | 611 |
612 final String src; | 612 final String src; |
613 final int width; | 613 final int width; |
614 final int height; | 614 final int height; |
615 | 615 |
616 Image({ | 616 Image({ |
617 Object key, | 617 Object key, |
618 List<Node> children, | 618 List<UINode> children, |
619 Style style, | 619 Style style, |
620 String inlineStyle, | 620 String inlineStyle, |
621 this.width, | 621 this.width, |
622 this.height, | 622 this.height, |
623 this.src | 623 this.src |
624 }) : super( | 624 }) : super( |
625 key: key, | 625 key: key, |
626 children: children, | 626 children: children, |
627 style: style, | 627 style: style, |
628 inlineStyle: inlineStyle | 628 inlineStyle: inlineStyle |
629 ); | 629 ); |
630 | 630 |
631 void _syncNode(Node old) { | 631 void _syncNode(UINode old) { |
632 super._syncNode(old); | 632 super._syncNode(old); |
633 | 633 |
634 Image oldImage = old as Image; | 634 Image oldImage = old as Image; |
635 sky.HTMLImageElement skyImage = _root as sky.HTMLImageElement; | 635 sky.HTMLImageElement skyImage = _root as sky.HTMLImageElement; |
636 | 636 |
637 if (src != oldImage.src) | 637 if (src != oldImage.src) |
638 skyImage.src = src; | 638 skyImage.src = src; |
639 | 639 |
640 if (width != oldImage.width) | 640 if (width != oldImage.width) |
641 skyImage.style['width'] = '${width}px'; | 641 skyImage.style['width'] = '${width}px'; |
642 | 642 |
643 if (height != oldImage.height) | 643 if (height != oldImage.height) |
644 skyImage.style['height'] = '${height}px'; | 644 skyImage.style['height'] = '${height}px'; |
645 } | 645 } |
646 } | 646 } |
647 | 647 |
648 class Anchor extends Element { | 648 class Anchor extends WrapperNode { |
649 | 649 |
650 String get _tagName => 'a'; | 650 String get _tagName => 'a'; |
651 | 651 |
652 static final Anchor _emptyAnchor = new Anchor(); | 652 static final Anchor _emptyAnchor = new Anchor(); |
653 | 653 |
654 Node get _emptyNode => _emptyAnchor; | 654 UINode get _emptyNode => _emptyAnchor; |
655 | 655 |
656 final String href; | 656 final String href; |
657 final int width; | 657 final int width; |
658 final int height; | 658 final int height; |
659 | 659 |
660 Anchor({ | 660 Anchor({ |
661 Object key, | 661 Object key, |
662 List<Node> children, | 662 List<UINode> children, |
663 Style style, | 663 Style style, |
664 String inlineStyle, | 664 String inlineStyle, |
665 this.width, | 665 this.width, |
666 this.height, | 666 this.height, |
667 this.href | 667 this.href |
668 }) : super( | 668 }) : super( |
669 key: key, | 669 key: key, |
670 children: children, | 670 children: children, |
671 style: style, | 671 style: style, |
672 inlineStyle: inlineStyle | 672 inlineStyle: inlineStyle |
673 ); | 673 ); |
674 | 674 |
675 void _syncNode(Node old) { | 675 void _syncNode(UINode old) { |
676 super._syncNode(old); | 676 super._syncNode(old); |
677 | 677 |
678 Anchor oldAnchor = old as Anchor; | 678 Anchor oldAnchor = old as Anchor; |
679 sky.HTMLAnchorElement skyAnchor = _root as sky.HTMLAnchorElement; | 679 sky.HTMLAnchorElement skyAnchor = _root as sky.HTMLAnchorElement; |
680 | 680 |
681 if (href != oldAnchor.href) | 681 if (href != oldAnchor.href) |
682 skyAnchor.href = href; | 682 skyAnchor.href = href; |
683 } | 683 } |
684 } | 684 } |
685 | 685 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 void _scheduleComponentForRender(Component c) { | 749 void _scheduleComponentForRender(Component c) { |
750 assert(!_inRenderDirtyComponents); | 750 assert(!_inRenderDirtyComponents); |
751 _dirtyComponents.add(c); | 751 _dirtyComponents.add(c); |
752 | 752 |
753 if (!_buildScheduled) { | 753 if (!_buildScheduled) { |
754 _buildScheduled = true; | 754 _buildScheduled = true; |
755 new Future.microtask(_buildDirtyComponents); | 755 new Future.microtask(_buildDirtyComponents); |
756 } | 756 } |
757 } | 757 } |
758 | 758 |
759 abstract class Component extends Node { | 759 abstract class Component extends UINode { |
760 bool get _isBuilding => _currentlyBuilding == this; | 760 bool get _isBuilding => _currentlyBuilding == this; |
761 bool _dirty = true; | 761 bool _dirty = true; |
762 | 762 |
763 sky.Node get _host => _root.parentNode; | 763 sky.Node get _host => _root.parentNode; |
764 sky.Node get _insertionPoint => _root == null ? _root : _root.nextSibling; | 764 sky.Node get _insertionPoint => _root == null ? _root : _root.nextSibling; |
765 | 765 |
766 Node _built; | 766 UINode _built; |
767 final int _order; | 767 final int _order; |
768 static int _currentOrder = 0; | 768 static int _currentOrder = 0; |
769 bool _stateful; | 769 bool _stateful; |
770 static Component _currentlyBuilding; | 770 static Component _currentlyBuilding; |
771 List<Function> _mountCallbacks; | 771 List<Function> _mountCallbacks; |
772 List<Function> _unmountCallbacks; | 772 List<Function> _unmountCallbacks; |
773 | 773 |
774 void onDidMount(Function fn) { | 774 void onDidMount(Function fn) { |
775 if (_mountCallbacks == null) | 775 if (_mountCallbacks == null) |
776 _mountCallbacks = new List<Function>(); | 776 _mountCallbacks = new List<Function>(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
810 | 810 |
811 void _remove() { | 811 void _remove() { |
812 assert(_built != null); | 812 assert(_built != null); |
813 assert(_root != null); | 813 assert(_root != null); |
814 _removeChild(_built); | 814 _removeChild(_built); |
815 _built = null; | 815 _built = null; |
816 _enqueueDidUnmount(this); | 816 _enqueueDidUnmount(this); |
817 super._remove(); | 817 super._remove(); |
818 } | 818 } |
819 | 819 |
820 bool _willSync(Node old) { | 820 bool _willSync(UINode old) { |
821 Component oldComponent = old as Component; | 821 Component oldComponent = old as Component; |
822 if (oldComponent == null || !oldComponent._stateful) | 822 if (oldComponent == null || !oldComponent._stateful) |
823 return false; | 823 return false; |
824 | 824 |
825 // Make |this| the "old" Component | 825 // Make |this| the "old" Component |
826 _stateful = false; | 826 _stateful = false; |
827 _built = oldComponent._built; | 827 _built = oldComponent._built; |
828 assert(_built != null); | 828 assert(_built != null); |
829 | 829 |
830 // Make |oldComponent| the "new" component | 830 // Make |oldComponent| the "new" component |
831 reflect.copyPublicFields(this, oldComponent); | 831 reflect.copyPublicFields(this, oldComponent); |
832 oldComponent._built = null; | 832 oldComponent._built = null; |
833 oldComponent._dirty = true; | 833 oldComponent._dirty = true; |
834 return true; | 834 return true; |
835 } | 835 } |
836 | 836 |
837 /* There are three cases here: | 837 /* There are three cases here: |
838 * 1) Building for the first time: | 838 * 1) Building for the first time: |
839 * assert(_built == null && old == null) | 839 * assert(_built == null && old == null) |
840 * 2) Re-building (because a dirty flag got set): | 840 * 2) Re-building (because a dirty flag got set): |
841 * assert(_built != null && old == null) | 841 * assert(_built != null && old == null) |
842 * 3) Syncing against an old version | 842 * 3) Syncing against an old version |
843 * assert(_built == null && old != null) | 843 * assert(_built == null && old != null) |
844 */ | 844 */ |
845 void _sync(Node old, sky.ParentNode host, sky.Node insertBefore) { | 845 void _sync(UINode old, sky.ParentNode host, sky.Node insertBefore) { |
846 assert(!_defunct); | 846 assert(!_defunct); |
847 assert(_built == null || old == null); | 847 assert(_built == null || old == null); |
848 | 848 |
849 Component oldComponent = old as Component; | 849 Component oldComponent = old as Component; |
850 | 850 |
851 var oldBuilt; | 851 var oldBuilt; |
852 if (oldComponent == null) { | 852 if (oldComponent == null) { |
853 oldBuilt = _built; | 853 oldBuilt = _built; |
854 } else { | 854 } else { |
855 assert(_built == null); | 855 assert(_built == null); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
887 void setState(Function fn()) { | 887 void setState(Function fn()) { |
888 _stateful = true; | 888 _stateful = true; |
889 fn(); | 889 fn(); |
890 if (_isBuilding || _dirty || _defunct) | 890 if (_isBuilding || _dirty || _defunct) |
891 return; | 891 return; |
892 | 892 |
893 _dirty = true; | 893 _dirty = true; |
894 _scheduleComponentForRender(this); | 894 _scheduleComponentForRender(this); |
895 } | 895 } |
896 | 896 |
897 Node build(); | 897 UINode build(); |
898 } | 898 } |
899 | 899 |
900 abstract class App extends Component { | 900 abstract class App extends Component { |
901 sky.Node _host; | 901 sky.Node _host; |
902 | 902 |
903 App() : super(stateful: true) { | 903 App() : super(stateful: true) { |
904 _host = sky.document.createElement('div'); | 904 _host = sky.document.createElement('div'); |
905 sky.document.appendChild(_host); | 905 sky.document.appendChild(_host); |
906 _scheduleComponentForRender(this); | 906 _scheduleComponentForRender(this); |
907 } | 907 } |
908 } | 908 } |
OLD | NEW |