| 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 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 * children list, may be replaced with the "old" instance if it has | 280 * children list, may be replaced with the "old" instance if it has |
| 281 * become stateful. | 281 * become stateful. |
| 282 */ | 282 */ |
| 283 abstract class RenderNodeWrapper extends UINode { | 283 abstract class RenderNodeWrapper extends UINode { |
| 284 | 284 |
| 285 static final Map<RenderCSS, RenderNodeWrapper> _nodeMap = | 285 static final Map<RenderCSS, RenderNodeWrapper> _nodeMap = |
| 286 new HashMap<RenderCSS, RenderNodeWrapper>(); | 286 new HashMap<RenderCSS, RenderNodeWrapper>(); |
| 287 | 287 |
| 288 static RenderNodeWrapper _getMounted(RenderCSS node) => _nodeMap[node]; | 288 static RenderNodeWrapper _getMounted(RenderCSS node) => _nodeMap[node]; |
| 289 | 289 |
| 290 RenderNodeWrapper({ Object key }) : super(key: key); | 290 RenderNodeWrapper({ |
| 291 Object key, |
| 292 this.style, |
| 293 this.inlineStyle |
| 294 }) : super(key: key); |
| 291 | 295 |
| 292 RenderNodeWrapper get _emptyNode; | 296 final Style style; |
| 297 final String inlineStyle; |
| 293 | 298 |
| 294 RenderCSS _createNode(); | 299 RenderCSS _createNode(); |
| 300 RenderNodeWrapper get _emptyNode; |
| 295 | 301 |
| 296 void _sync(UINode old, RenderCSSContainer host, RenderCSS insertBefore) { | 302 void _sync(UINode old, RenderCSSContainer host, RenderCSS insertBefore) { |
| 297 if (old == null) { | 303 if (old == null) { |
| 298 _root = _createNode(); | 304 _root = _createNode(); |
| 299 assert(_root != null); | 305 assert(_root != null); |
| 300 host.add(_root, before: insertBefore); | 306 host.add(_root, before: insertBefore); |
| 301 old = _emptyNode; | 307 old = _emptyNode; |
| 302 } else { | 308 } else { |
| 303 _root = old._root; | 309 _root = old._root; |
| 304 assert(_root != null); | 310 assert(_root != null); |
| 305 } | 311 } |
| 306 | 312 |
| 307 _nodeMap[_root] = this; | 313 _nodeMap[_root] = this; |
| 308 _syncNode(old); | 314 _syncRenderNode(old); |
| 309 } | 315 } |
| 310 | 316 |
| 311 void _syncNode(RenderNodeWrapper old); | 317 void _syncRenderNode(RenderNodeWrapper old) { |
| 318 RenderNodeWrapper oldRenderNodeWrapper = old as RenderNodeWrapper; |
| 319 |
| 320 List<Style> styles = new List<Style>(); |
| 321 if (style != null) |
| 322 styles.add(style); |
| 323 ParentData parentData = null; |
| 324 UINode parent = _parent; |
| 325 while (parent != null && parent is! RenderNodeWrapper) { |
| 326 if (parent is StyleNode && parent.style != null) |
| 327 styles.add(parent.style); |
| 328 else |
| 329 if (parent is ParentDataNode && parent.parentData != null) { |
| 330 if (parentData != null) |
| 331 parentData.merge(parent.parentData); // this will throw if the types a
ren't the same |
| 332 else |
| 333 parentData = parent.parentData; |
| 334 } |
| 335 parent = parent._parent; |
| 336 } |
| 337 _root.updateStyles(styles); |
| 338 if (parentData != null) { |
| 339 assert(_root.parentData != null); |
| 340 _root.parentData.merge(parentData); // this will throw if the types aren't
approriate |
| 341 assert(parent != null); |
| 342 assert(parent._root != null); |
| 343 parent._root.markNeedsLayout(); |
| 344 } |
| 345 _root.updateInlineStyle(inlineStyle); |
| 346 } |
| 312 | 347 |
| 313 void _removeChild(UINode node) { | 348 void _removeChild(UINode node) { |
| 314 assert(_root is RenderCSSContainer); | 349 assert(_root is RenderCSSContainer); |
| 315 _root.remove(node._root); | 350 _root.remove(node._root); |
| 316 super._removeChild(node); | 351 super._removeChild(node); |
| 317 } | 352 } |
| 318 | 353 |
| 319 void _remove() { | 354 void _remove() { |
| 320 assert(_root != null); | 355 assert(_root != null); |
| 321 _nodeMap.remove(_root); | 356 _nodeMap.remove(_root); |
| 322 super._remove(); | 357 super._remove(); |
| 323 } | 358 } |
| 324 } | 359 } |
| 325 | 360 |
| 326 final List<UINode> _emptyList = new List<UINode>(); | 361 final List<UINode> _emptyList = new List<UINode>(); |
| 327 | 362 |
| 328 abstract class OneChildListRenderNodeWrapper extends RenderNodeWrapper { | 363 abstract class OneChildListRenderNodeWrapper extends RenderNodeWrapper { |
| 329 | 364 |
| 330 final List<UINode> children; | 365 final List<UINode> children; |
| 331 final Style style; | |
| 332 final String inlineStyle; | |
| 333 | 366 |
| 334 OneChildListRenderNodeWrapper({ | 367 OneChildListRenderNodeWrapper({ |
| 335 Object key, | 368 Object key, |
| 336 List<UINode> children, | 369 List<UINode> children, |
| 337 this.style, | 370 Style style, |
| 338 this.inlineStyle | 371 String inlineStyle |
| 339 }) : this.children = children == null ? _emptyList : children, | 372 }) : this.children = children == null ? _emptyList : children, |
| 340 super(key: key) { | 373 super( |
| 341 | 374 key: key, |
| 375 style: style, |
| 376 inlineStyle: inlineStyle |
| 377 ) { |
| 342 assert(!_debugHasDuplicateIds()); | 378 assert(!_debugHasDuplicateIds()); |
| 343 } | 379 } |
| 344 | 380 |
| 345 void _remove() { | 381 void _remove() { |
| 346 assert(children != null); | 382 assert(children != null); |
| 347 for (var child in children) { | 383 for (var child in children) { |
| 348 assert(child != null); | 384 assert(child != null); |
| 349 _removeChild(child); | 385 _removeChild(child); |
| 350 } | 386 } |
| 351 super._remove(); | 387 super._remove(); |
| 352 } | 388 } |
| 353 | 389 |
| 354 bool _debugHasDuplicateIds() { | 390 bool _debugHasDuplicateIds() { |
| 355 var idSet = new HashSet<String>(); | 391 var idSet = new HashSet<String>(); |
| 356 for (var child in children) { | 392 for (var child in children) { |
| 357 assert(child != null); | 393 assert(child != null); |
| 358 if (child.interchangeable) | 394 if (child.interchangeable) |
| 359 continue; // when these nodes are reordered, we just reassign the data | 395 continue; // when these nodes are reordered, we just reassign the data |
| 360 | 396 |
| 361 if (!idSet.add(child._key)) { | 397 if (!idSet.add(child._key)) { |
| 362 throw '''If multiple non-interchangeable nodes of the same type exist as
children | 398 throw '''If multiple non-interchangeable nodes of the same type exist as
children |
| 363 of another node, they must have unique keys. | 399 of another node, they must have unique keys. |
| 364 Duplicate: "${child._key}"'''; | 400 Duplicate: "${child._key}"'''; |
| 365 } | 401 } |
| 366 } | 402 } |
| 367 return false; | 403 return false; |
| 368 } | 404 } |
| 369 | 405 |
| 370 void _syncNode(RenderNodeWrapper old) { | 406 void _syncRenderNode(OneChildListRenderNodeWrapper old) { |
| 371 OneChildListRenderNodeWrapper oldOneChildListRenderNodeWrapper = old as OneC
hildListRenderNodeWrapper; | 407 super._syncRenderNode(old); |
| 372 | 408 |
| 373 List<Style> styles = new List<Style>(); | |
| 374 if (style != null) | |
| 375 styles.add(style); | |
| 376 ParentData parentData = null; | |
| 377 UINode parent = _parent; | |
| 378 while (parent != null && parent is! RenderNodeWrapper) { | |
| 379 if (parent is StyleNode && parent.style != null) | |
| 380 styles.add(parent.style); | |
| 381 else | |
| 382 if (parent is ParentDataNode && parent.parentData != null) { | |
| 383 if (parentData != null) | |
| 384 parentData.merge(parent.parentData); // this will throw if the types a
ren't the same | |
| 385 else | |
| 386 parentData = parent.parentData; | |
| 387 } | |
| 388 parent = parent._parent; | |
| 389 } | |
| 390 _root.updateStyles(styles); | |
| 391 if (parentData != null) { | |
| 392 assert(_root.parentData != null); | |
| 393 _root.parentData.merge(parentData); // this will throw if the types aren't
approriate | |
| 394 assert(parent != null); | |
| 395 assert(parent._root != null); | |
| 396 parent._root.markNeedsLayout(); | |
| 397 } | |
| 398 _root.updateInlineStyle(inlineStyle); | |
| 399 | |
| 400 _syncChildren(oldOneChildListRenderNodeWrapper); | |
| 401 } | |
| 402 | |
| 403 void _syncChildren(OneChildListRenderNodeWrapper oldOneChildListRenderNodeWrap
per) { | |
| 404 if (_root is! RenderCSSContainer) | 409 if (_root is! RenderCSSContainer) |
| 405 return; | 410 return; |
| 406 | 411 |
| 407 var startIndex = 0; | 412 var startIndex = 0; |
| 408 var endIndex = children.length; | 413 var endIndex = children.length; |
| 409 | 414 |
| 410 var oldChildren = oldOneChildListRenderNodeWrapper.children; | 415 var oldChildren = old.children; |
| 411 var oldStartIndex = 0; | 416 var oldStartIndex = 0; |
| 412 var oldEndIndex = oldChildren.length; | 417 var oldEndIndex = oldChildren.length; |
| 413 | 418 |
| 414 RenderCSS nextSibling = null; | 419 RenderCSS nextSibling = null; |
| 415 UINode currentNode = null; | 420 UINode currentNode = null; |
| 416 UINode oldNode = null; | 421 UINode oldNode = null; |
| 417 | 422 |
| 418 void sync(int atIndex) { | 423 void sync(int atIndex) { |
| 419 children[atIndex] = _syncChild(currentNode, oldNode, _root, nextSibling); | 424 children[atIndex] = _syncChild(currentNode, oldNode, _root, nextSibling); |
| 420 assert(children[atIndex] != null); | 425 assert(children[atIndex] != null); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 return false; // never re-order these nodes | 473 return false; // never re-order these nodes |
| 469 | 474 |
| 470 ensureOldIdMap(); | 475 ensureOldIdMap(); |
| 471 oldNode = oldNodeIdMap[currentNode._key]; | 476 oldNode = oldNodeIdMap[currentNode._key]; |
| 472 if (oldNode == null) | 477 if (oldNode == null) |
| 473 return false; | 478 return false; |
| 474 | 479 |
| 475 oldNodeIdMap[currentNode._key] = null; // mark it reordered | 480 oldNodeIdMap[currentNode._key] = null; // mark it reordered |
| 476 assert(_root is RenderCSSContainer); | 481 assert(_root is RenderCSSContainer); |
| 477 assert(oldNode._root is RenderCSSContainer); | 482 assert(oldNode._root is RenderCSSContainer); |
| 478 oldOneChildListRenderNodeWrapper._root.remove(oldNode._root); | 483 old._root.remove(oldNode._root); |
| 479 _root.add(oldNode._root, before: nextSibling); | 484 _root.add(oldNode._root, before: nextSibling); |
| 480 return true; | 485 return true; |
| 481 } | 486 } |
| 482 | 487 |
| 483 // Scan forwards, this time we may re-order; | 488 // Scan forwards, this time we may re-order; |
| 484 nextSibling = _root.firstChild; | 489 nextSibling = _root.firstChild; |
| 485 while (startIndex < endIndex && oldStartIndex < oldEndIndex) { | 490 while (startIndex < endIndex && oldStartIndex < oldEndIndex) { |
| 486 currentNode = children[startIndex]; | 491 currentNode = children[startIndex]; |
| 487 oldNode = oldChildren[oldStartIndex]; | 492 oldNode = oldChildren[oldStartIndex]; |
| 488 | 493 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 Style style, | 586 Style style, |
| 582 String inlineStyle, | 587 String inlineStyle, |
| 583 this.direction: FlexDirection.Row | 588 this.direction: FlexDirection.Row |
| 584 }) : super( | 589 }) : super( |
| 585 key: key, | 590 key: key, |
| 586 children: children, | 591 children: children, |
| 587 style: style, | 592 style: style, |
| 588 inlineStyle: inlineStyle | 593 inlineStyle: inlineStyle |
| 589 ); | 594 ); |
| 590 | 595 |
| 591 void _syncNode(UINode old) { | 596 void _syncRenderNode(UINode old) { |
| 592 super._syncNode(old); | 597 super._syncRenderNode(old); |
| 593 _root.direction = direction; | 598 _root.direction = direction; |
| 594 } | 599 } |
| 595 } | 600 } |
| 596 | 601 |
| 597 class FillStackContainer extends OneChildListRenderNodeWrapper { | 602 class FillStackContainer extends OneChildListRenderNodeWrapper { |
| 598 | 603 |
| 599 RenderCSSStack _root; | 604 RenderCSSStack _root; |
| 600 RenderCSSStack _createNode() => new RenderCSSStack(this); | 605 RenderCSSStack _createNode() => new RenderCSSStack(this); |
| 601 | 606 |
| 602 static final FillStackContainer _emptyContainer = new FillStackContainer(); | 607 static final FillStackContainer _emptyContainer = new FillStackContainer(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 623 | 628 |
| 624 static List<UINode> _positionNodesToFill(List<UINode> input) { | 629 static List<UINode> _positionNodesToFill(List<UINode> input) { |
| 625 if (input == null) | 630 if (input == null) |
| 626 return null; | 631 return null; |
| 627 return input.map((node) { | 632 return input.map((node) { |
| 628 return new ParentDataNode(node, _fillParentData); | 633 return new ParentDataNode(node, _fillParentData); |
| 629 }).toList(); | 634 }).toList(); |
| 630 } | 635 } |
| 631 } | 636 } |
| 632 | 637 |
| 633 class TextFragment extends OneChildListRenderNodeWrapper { | 638 class TextFragment extends RenderNodeWrapper { |
| 634 | 639 |
| 635 RenderCSSInline _root; | 640 RenderCSSInline _root; |
| 636 RenderCSSInline _createNode() => new RenderCSSInline(this, this.data); | 641 RenderCSSInline _createNode() => new RenderCSSInline(this, this.data); |
| 637 | 642 |
| 638 static final TextFragment _emptyText = new TextFragment(''); | 643 static final TextFragment _emptyText = new TextFragment(''); |
| 639 | 644 |
| 640 RenderNodeWrapper get _emptyNode => _emptyText; | 645 RenderNodeWrapper get _emptyNode => _emptyText; |
| 641 | 646 |
| 642 final String data; | 647 final String data; |
| 643 | 648 |
| 644 TextFragment(this.data, { | 649 TextFragment(this.data, { |
| 645 Object key, | 650 Object key, |
| 646 Style style, | 651 Style style, |
| 647 String inlineStyle | 652 String inlineStyle |
| 648 }) : super( | 653 }) : super( |
| 649 key: key, | 654 key: key, |
| 650 style: style, | 655 style: style, |
| 651 inlineStyle: inlineStyle | 656 inlineStyle: inlineStyle |
| 652 ); | 657 ); |
| 653 | 658 |
| 654 void _syncNode(UINode old) { | 659 void _syncRenderNode(UINode old) { |
| 655 super._syncNode(old); | 660 super._syncRenderNode(old); |
| 656 _root.data = data; | 661 _root.data = data; |
| 657 } | 662 } |
| 658 } | 663 } |
| 659 | 664 |
| 660 class Image extends OneChildListRenderNodeWrapper { | 665 class Image extends RenderNodeWrapper { |
| 661 | 666 |
| 662 RenderCSSImage _root; | 667 RenderCSSImage _root; |
| 663 RenderCSSImage _createNode() => new RenderCSSImage(this, this.src, this.width,
this.height); | 668 RenderCSSImage _createNode() => new RenderCSSImage(this, this.src, this.width,
this.height); |
| 664 | 669 |
| 665 static final Image _emptyImage = new Image(); | 670 static final Image _emptyImage = new Image(); |
| 666 | 671 |
| 667 RenderNodeWrapper get _emptyNode => _emptyImage; | 672 RenderNodeWrapper get _emptyNode => _emptyImage; |
| 668 | 673 |
| 669 final String src; | 674 final String src; |
| 670 final int width; | 675 final int width; |
| 671 final int height; | 676 final int height; |
| 672 | 677 |
| 673 Image({ | 678 Image({ |
| 674 Object key, | 679 Object key, |
| 675 Style style, | 680 Style style, |
| 676 String inlineStyle, | 681 String inlineStyle, |
| 677 this.width, | 682 this.width, |
| 678 this.height, | 683 this.height, |
| 679 this.src | 684 this.src |
| 680 }) : super( | 685 }) : super( |
| 681 key: key, | 686 key: key, |
| 682 style: style, | 687 style: style, |
| 683 inlineStyle: inlineStyle | 688 inlineStyle: inlineStyle |
| 684 ); | 689 ); |
| 685 | 690 |
| 686 void _syncNode(UINode old) { | 691 void _syncRenderNode(UINode old) { |
| 687 super._syncNode(old); | 692 super._syncRenderNode(old); |
| 688 _root.configure(this.src, this.width, this.height); | 693 _root.configure(this.src, this.width, this.height); |
| 689 } | 694 } |
| 690 } | 695 } |
| 691 | 696 |
| 692 | 697 |
| 693 Set<Component> _mountedComponents = new HashSet<Component>(); | 698 Set<Component> _mountedComponents = new HashSet<Component>(); |
| 694 Set<Component> _unmountedComponents = new HashSet<Component>(); | 699 Set<Component> _unmountedComponents = new HashSet<Component>(); |
| 695 | 700 |
| 696 void _enqueueDidMount(Component c) { | 701 void _enqueueDidMount(Component c) { |
| 697 assert(!_notifingMountStatus); | 702 assert(!_notifingMountStatus); |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 _sync(null, _host, _root); | 921 _sync(null, _host, _root); |
| 917 } | 922 } |
| 918 } | 923 } |
| 919 | 924 |
| 920 class Text extends Component { | 925 class Text extends Component { |
| 921 Text(this.data) : super(key: '*text*'); | 926 Text(this.data) : super(key: '*text*'); |
| 922 final String data; | 927 final String data; |
| 923 bool get interchangeable => true; | 928 bool get interchangeable => true; |
| 924 UINode build() => new Paragraph(children: [new TextFragment(data)]); | 929 UINode build() => new Paragraph(children: [new TextFragment(data)]); |
| 925 } | 930 } |
| OLD | NEW |