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 part of fn; | 5 part of fn; |
6 | 6 |
7 void _parentInsertBefore(sky.ParentNode parent, | 7 void _parentInsertBefore(sky.ParentNode parent, |
8 sky.Node node, | 8 sky.Node node, |
9 sky.Node ref) { | 9 sky.Node ref) { |
10 if (ref != null) { | 10 if (ref != null) { |
11 ref.insertBefore([node]); | 11 ref.insertBefore([node]); |
12 } else { | 12 } else { |
13 parent.appendChild(node); | 13 parent.appendChild(node); |
14 } | 14 } |
15 } | 15 } |
16 | 16 |
17 abstract class Node { | 17 abstract class Node { |
18 String _key = null; | 18 String _key = null; |
19 sky.Node _root = null; | 19 sky.Node _root = null; |
20 | 20 |
| 21 // TODO(abarth): Both Elements and Components have |events| but |Text| |
| 22 // doesn't. Should we add a common base class to contain |events|? |
| 23 final EventMap events = new EventMap(); |
| 24 |
21 Node({ Object key }) { | 25 Node({ Object key }) { |
22 _key = key == null ? "$runtimeType" : "$runtimeType-$key"; | 26 _key = key == null ? "$runtimeType" : "$runtimeType-$key"; |
23 } | 27 } |
24 | 28 |
25 // Return true IFF the old node has *become* the new node (should be | 29 // Return true IFF the old node has *become* the new node (should be |
26 // retained because it is stateful) | 30 // retained because it is stateful) |
27 bool _sync(Node old, sky.ParentNode host, sky.Node insertBefore); | 31 bool _sync(Node old, sky.ParentNode host, sky.Node insertBefore); |
28 | 32 |
29 void _remove() { | 33 void _remove() { |
30 assert(_root != null); | 34 assert(_root != null); |
(...skipping 27 matching lines...) Expand all Loading... |
58 final List<Node> _emptyList = new List<Node>(); | 62 final List<Node> _emptyList = new List<Node>(); |
59 | 63 |
60 abstract class Element extends Node { | 64 abstract class Element extends Node { |
61 | 65 |
62 String get _tagName; | 66 String get _tagName; |
63 | 67 |
64 Element get _emptyElement; | 68 Element get _emptyElement; |
65 | 69 |
66 String inlineStyle; | 70 String inlineStyle; |
67 | 71 |
68 sky.EventListener onClick; | |
69 sky.EventListener onFlingCancel; | |
70 sky.EventListener onFlingStart; | |
71 sky.EventListener onGestureTap; | |
72 sky.EventListener onPointerCancel; | |
73 sky.EventListener onPointerDown; | |
74 sky.EventListener onPointerMove; | |
75 sky.EventListener onPointerUp; | |
76 sky.EventListener onScrollEnd; | |
77 sky.EventListener onScrollStart; | |
78 sky.EventListener onScrollUpdate; | |
79 sky.EventListener onWheel; | |
80 | |
81 List<Node> _children = null; | 72 List<Node> _children = null; |
82 String _className = ''; | 73 String _className = ''; |
83 | 74 |
84 Element({ | 75 Element({ |
85 Object key, | 76 Object key, |
86 List<Node> children, | 77 List<Node> children, |
87 Style style, | 78 Style style, |
88 | 79 |
89 this.inlineStyle, | 80 this.inlineStyle |
90 | |
91 // Events | |
92 this.onClick, | |
93 this.onFlingCancel, | |
94 this.onFlingStart, | |
95 this.onGestureTap, | |
96 this.onPointerCancel, | |
97 this.onPointerDown, | |
98 this.onPointerMove, | |
99 this.onPointerUp, | |
100 this.onScrollEnd, | |
101 this.onScrollStart, | |
102 this.onScrollUpdate, | |
103 this.onWheel | |
104 }) : super(key:key) { | 81 }) : super(key:key) { |
105 | 82 |
106 _className = style == null ? '': style._className; | 83 _className = style == null ? '': style._className; |
107 _children = children == null ? _emptyList : children; | 84 _children = children == null ? _emptyList : children; |
108 | 85 |
109 if (_debugWarnings()) { | 86 if (_debugWarnings()) { |
110 _debugReportDuplicateIds(); | 87 _debugReportDuplicateIds(); |
111 } | 88 } |
112 } | 89 } |
113 | 90 |
(...skipping 14 matching lines...) Expand all Loading... |
128 continue; // Text nodes all have the same key and are never reordered. | 105 continue; // Text nodes all have the same key and are never reordered. |
129 } | 106 } |
130 | 107 |
131 if (!idSet.add(child._key)) { | 108 if (!idSet.add(child._key)) { |
132 throw '''If multiple (non-Text) nodes of the same type exist as children | 109 throw '''If multiple (non-Text) nodes of the same type exist as children |
133 of another node, they must have unique keys.'''; | 110 of another node, they must have unique keys.'''; |
134 } | 111 } |
135 } | 112 } |
136 } | 113 } |
137 | 114 |
138 void _syncEvent(String eventName, sky.EventListener listener, | |
139 sky.EventListener oldListener) { | |
140 sky.Element root = _root as sky.Element; | |
141 if (listener == oldListener) | |
142 return; | |
143 | |
144 if (oldListener != null) { | |
145 root.removeEventListener(eventName, oldListener); | |
146 } | |
147 | |
148 if (listener != null) { | |
149 root.addEventListener(eventName, listener); | |
150 } | |
151 } | |
152 | |
153 void _syncEvents([Element old]) { | 115 void _syncEvents([Element old]) { |
154 _syncEvent('click', onClick, old.onClick); | 116 List<EventHandler> newHandlers = events._handlers; |
155 _syncEvent('gestureflingcancel', onFlingCancel, old.onFlingCancel); | 117 int newStartIndex = 0; |
156 _syncEvent('gestureflingstart', onFlingStart, old.onFlingStart); | 118 int newEndIndex = newHandlers.length; |
157 _syncEvent('gesturescrollend', onScrollEnd, old.onScrollEnd); | 119 |
158 _syncEvent('gesturescrollstart', onScrollStart, old.onScrollStart); | 120 List<EventHandler> oldHandlers = old.events._handlers; |
159 _syncEvent('gesturescrollupdate', onScrollUpdate, old.onScrollUpdate); | 121 int oldStartIndex = 0; |
160 _syncEvent('gesturetap', onGestureTap, old.onGestureTap); | 122 int oldEndIndex = oldHandlers.length; |
161 _syncEvent('pointercancel', onPointerCancel, old.onPointerCancel); | 123 |
162 _syncEvent('pointerdown', onPointerDown, old.onPointerDown); | 124 // Skip over leading handlers that match. |
163 _syncEvent('pointermove', onPointerMove, old.onPointerMove); | 125 while (newStartIndex < newEndIndex && oldStartIndex < oldEndIndex) { |
164 _syncEvent('pointerup', onPointerUp, old.onPointerUp); | 126 EventHandler newHander = newHandlers[newStartIndex]; |
165 _syncEvent('wheel', onWheel, old.onWheel); | 127 EventHandler oldHandler = oldHandlers[oldStartIndex]; |
| 128 if (newHander.type != oldHandler.type |
| 129 || newHander.listener != oldHandler.listener) |
| 130 break; |
| 131 ++newStartIndex; |
| 132 ++oldStartIndex; |
| 133 } |
| 134 |
| 135 // Skip over trailing handlers that match. |
| 136 while (newStartIndex < newEndIndex && oldStartIndex < oldEndIndex) { |
| 137 EventHandler newHander = newHandlers[newEndIndex - 1]; |
| 138 EventHandler oldHandler = oldHandlers[oldEndIndex - 1]; |
| 139 if (newHander.type != oldHandler.type |
| 140 || newHander.listener != oldHandler.listener) |
| 141 break; |
| 142 --newEndIndex; |
| 143 --oldEndIndex; |
| 144 } |
| 145 |
| 146 sky.Element root = _root as sky.Element; |
| 147 |
| 148 for (int i = oldStartIndex; i < oldEndIndex; ++i) { |
| 149 EventHandler oldHandler = oldHandlers[i]; |
| 150 root.removeEventListener(oldHandler.type, oldHandler.listener); |
| 151 } |
| 152 |
| 153 for (int i = newStartIndex; i < newEndIndex; ++i) { |
| 154 EventHandler newHander = newHandlers[i]; |
| 155 root.addEventListener(newHander.type, newHander.listener); |
| 156 } |
166 } | 157 } |
167 | 158 |
168 void _syncNode([Element old]) { | 159 void _syncNode([Element old]) { |
169 if (old == null) { | 160 if (old == null) { |
170 old = _emptyElement; | 161 old = _emptyElement; |
171 } | 162 } |
172 | 163 |
173 _syncEvents(old); | 164 _syncEvents(old); |
174 | 165 |
175 sky.Element root = _root as sky.Element; | 166 sky.Element root = _root as sky.Element; |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 String get _tagName => 'div'; | 340 String get _tagName => 'div'; |
350 | 341 |
351 static final Container _emptyContainer = new Container(); | 342 static final Container _emptyContainer = new Container(); |
352 | 343 |
353 Element get _emptyElement => _emptyContainer; | 344 Element get _emptyElement => _emptyContainer; |
354 | 345 |
355 Container({ | 346 Container({ |
356 Object key, | 347 Object key, |
357 List<Node> children, | 348 List<Node> children, |
358 Style style, | 349 Style style, |
359 String inlineStyle, | 350 String inlineStyle |
360 sky.EventListener onClick, | |
361 sky.EventListener onFlingCancel, | |
362 sky.EventListener onFlingStart, | |
363 sky.EventListener onGestureTap, | |
364 sky.EventListener onPointerCancel, | |
365 sky.EventListener onPointerDown, | |
366 sky.EventListener onPointerMove, | |
367 sky.EventListener onPointerUp, | |
368 sky.EventListener onScrollEnd, | |
369 sky.EventListener onScrollStart, | |
370 sky.EventListener onScrollUpdate, | |
371 sky.EventListener onWheel | |
372 }) : super( | 351 }) : super( |
373 key: key, | 352 key: key, |
374 children: children, | 353 children: children, |
375 style: style, | 354 style: style, |
376 inlineStyle: inlineStyle, | 355 inlineStyle: inlineStyle |
377 onClick: onClick, | |
378 onFlingCancel: onFlingCancel, | |
379 onFlingStart: onFlingStart, | |
380 onGestureTap: onGestureTap, | |
381 onPointerCancel: onPointerCancel, | |
382 onPointerDown: onPointerDown, | |
383 onPointerMove: onPointerMove, | |
384 onPointerUp: onPointerUp, | |
385 onScrollEnd: onScrollEnd, | |
386 onScrollStart: onScrollStart, | |
387 onScrollUpdate: onScrollUpdate, | |
388 onWheel: onWheel | |
389 ); | 356 ); |
390 } | 357 } |
391 | 358 |
392 class Image extends Element { | 359 class Image extends Element { |
393 | 360 |
394 String get _tagName => 'img'; | 361 String get _tagName => 'img'; |
395 | 362 |
396 static final Image _emptyImage = new Image(); | 363 static final Image _emptyImage = new Image(); |
397 Element get _emptyElement => _emptyImage; | 364 Element get _emptyElement => _emptyImage; |
398 | 365 |
399 String src; | 366 String src; |
400 int width; | 367 int width; |
401 int height; | 368 int height; |
402 | 369 |
403 Image({ | 370 Image({ |
404 Object key, | 371 Object key, |
405 List<Node> children, | 372 List<Node> children, |
406 Style style, | 373 Style style, |
407 String inlineStyle, | 374 String inlineStyle, |
408 sky.EventListener onClick, | |
409 sky.EventListener onFlingCancel, | |
410 sky.EventListener onFlingStart, | |
411 sky.EventListener onGestureTap, | |
412 sky.EventListener onPointerCancel, | |
413 sky.EventListener onPointerDown, | |
414 sky.EventListener onPointerMove, | |
415 sky.EventListener onPointerUp, | |
416 sky.EventListener onScrollEnd, | |
417 sky.EventListener onScrollStart, | |
418 sky.EventListener onScrollUpdate, | |
419 sky.EventListener onWheel, | |
420 this.width, | 375 this.width, |
421 this.height, | 376 this.height, |
422 this.src | 377 this.src |
423 }) : super( | 378 }) : super( |
424 key: key, | 379 key: key, |
425 children: children, | 380 children: children, |
426 style: style, | 381 style: style, |
427 inlineStyle: inlineStyle, | 382 inlineStyle: inlineStyle |
428 onClick: onClick, | |
429 onFlingCancel: onFlingCancel, | |
430 onFlingStart: onFlingStart, | |
431 onGestureTap: onGestureTap, | |
432 onPointerCancel: onPointerCancel, | |
433 onPointerDown: onPointerDown, | |
434 onPointerMove: onPointerMove, | |
435 onPointerUp: onPointerUp, | |
436 onScrollEnd: onScrollEnd, | |
437 onScrollStart: onScrollStart, | |
438 onScrollUpdate: onScrollUpdate, | |
439 onWheel: onWheel | |
440 ); | 383 ); |
441 | 384 |
442 void _syncNode([Element old]) { | 385 void _syncNode([Element old]) { |
443 super._syncNode(old); | 386 super._syncNode(old); |
444 | 387 |
445 Image oldImage = old != null ? old : _emptyImage; | 388 Image oldImage = old != null ? old : _emptyImage; |
446 sky.HTMLImageElement skyImage = _root as sky.HTMLImageElement; | 389 sky.HTMLImageElement skyImage = _root as sky.HTMLImageElement; |
447 if (src != oldImage.src) { | 390 if (src != oldImage.src) { |
448 skyImage.src = src; | 391 skyImage.src = src; |
449 } | 392 } |
(...skipping 13 matching lines...) Expand all Loading... |
463 | 406 |
464 static final Anchor _emptyAnchor = new Anchor(); | 407 static final Anchor _emptyAnchor = new Anchor(); |
465 | 408 |
466 String href; | 409 String href; |
467 | 410 |
468 Anchor({ | 411 Anchor({ |
469 Object key, | 412 Object key, |
470 List<Node> children, | 413 List<Node> children, |
471 Style style, | 414 Style style, |
472 String inlineStyle, | 415 String inlineStyle, |
473 sky.EventListener onClick, | |
474 sky.EventListener onFlingCancel, | |
475 sky.EventListener onFlingStart, | |
476 sky.EventListener onGestureTap, | |
477 sky.EventListener onPointerCancel, | |
478 sky.EventListener onPointerDown, | |
479 sky.EventListener onPointerMove, | |
480 sky.EventListener onPointerUp, | |
481 sky.EventListener onScrollEnd, | |
482 sky.EventListener onScrollStart, | |
483 sky.EventListener onScrollUpdate, | |
484 sky.EventListener onWheel, | |
485 this.width, | 416 this.width, |
486 this.height, | 417 this.height, |
487 this.href | 418 this.href |
488 }) : super( | 419 }) : super( |
489 key: key, | 420 key: key, |
490 children: children, | 421 children: children, |
491 style: style, | 422 style: style, |
492 inlineStyle: inlineStyle, | 423 inlineStyle: inlineStyle |
493 onClick: onClick, | |
494 onFlingCancel: onFlingCancel, | |
495 onFlingStart: onFlingStart, | |
496 onGestureTap: onGestureTap, | |
497 onPointerCancel: onPointerCancel, | |
498 onPointerDown: onPointerDown, | |
499 onPointerMove: onPointerMove, | |
500 onPointerUp: onPointerUp, | |
501 onScrollEnd: onScrollEnd, | |
502 onScrollStart: onScrollStart, | |
503 onScrollUpdate: onScrollUpdate, | |
504 onWheel: onWheel | |
505 ); | 424 ); |
506 | 425 |
507 void _syncNode([Element old]) { | 426 void _syncNode([Element old]) { |
508 Anchor oldAnchor = old != null ? old as Anchor : _emptyAnchor; | 427 Anchor oldAnchor = old != null ? old as Anchor : _emptyAnchor; |
509 super._syncNode(oldAnchor); | 428 super._syncNode(oldAnchor); |
510 | 429 |
511 sky.HTMLAnchorElement skyAnchor = _root as sky.HTMLAnchorElement; | 430 sky.HTMLAnchorElement skyAnchor = _root as sky.HTMLAnchorElement; |
512 if (href != oldAnchor.href) { | 431 if (href != oldAnchor.href) { |
513 skyAnchor.href = href; | 432 skyAnchor.href = href; |
514 } | 433 } |
515 } | 434 } |
516 } | 435 } |
OLD | NEW |