| 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 '../base/hit_test.dart'; | 10 import '../base/hit_test.dart'; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 } | 60 } |
| 61 } else { | 61 } else { |
| 62 assert(newParent._mounted); | 62 assert(newParent._mounted); |
| 63 if (_parent._mounted != _mounted) { | 63 if (_parent._mounted != _mounted) { |
| 64 _mounted = _parent._mounted; | 64 _mounted = _parent._mounted; |
| 65 _mountedChanged.add(this); | 65 _mountedChanged.add(this); |
| 66 } | 66 } |
| 67 } | 67 } |
| 68 } | 68 } |
| 69 | 69 |
| 70 // Override this if you have children and call walker on each child | 70 // Override this if you have children and call walker on each child. |
| 71 // Note that you may be called before the child has had its parent |
| 72 // pointer set to point to you. Your walker, and any methods it |
| 73 // invokes on your descendants, should not rely on the ancestor |
| 74 // chain being correctly configured at this point. |
| 71 void walkChildren(WidgetTreeWalker walker) { } | 75 void walkChildren(WidgetTreeWalker walker) { } |
| 72 | 76 |
| 73 static void _notifyMountStatusChanged() { | 77 static void _notifyMountStatusChanged() { |
| 74 try { | 78 try { |
| 75 sky.tracing.begin("Widget._notifyMountStatusChanged"); | 79 sky.tracing.begin("Widget._notifyMountStatusChanged"); |
| 76 _notifyingMountStatus = true; | 80 _notifyingMountStatus = true; |
| 77 for (Widget node in _mountedChanged) { | 81 for (Widget node in _mountedChanged) { |
| 78 if (node._wasMounted != node._mounted) { | 82 if (node._wasMounted != node._mounted) { |
| 79 if (node._mounted) | 83 if (node._mounted) |
| 80 node.didMount(); | 84 node.didMount(); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 111 ancestor = ancestor._parent; | 115 ancestor = ancestor._parent; |
| 112 return ancestor; | 116 return ancestor; |
| 113 } | 117 } |
| 114 | 118 |
| 115 void remove() { | 119 void remove() { |
| 116 _root = null; | 120 _root = null; |
| 117 setParent(null); | 121 setParent(null); |
| 118 } | 122 } |
| 119 | 123 |
| 120 void removeChild(Widget node) { | 124 void removeChild(Widget node) { |
| 125 // Call this when we no longer have a child equivalent to node. |
| 126 // For example, when our child has changed type, or has been set to null. |
| 127 // Do not call this when our child has been replaced by an equivalent but |
| 128 // newer instance that will sync() with the old one, since in that case |
| 129 // the subtree starting from the old node, as well as the render tree that |
| 130 // belonged to the old node, continue to live on in the replacement node. |
| 121 node.remove(); | 131 node.remove(); |
| 132 assert(node.parent == null); |
| 122 } | 133 } |
| 123 | 134 |
| 124 void detachRoot(); | 135 void detachRoot(); |
| 125 | 136 |
| 126 // Returns the child which should be retained as the child of this node. | 137 // Returns the child which should be retained as the child of this node. |
| 127 Widget syncChild(Widget newNode, Widget oldNode, dynamic slot) { | 138 Widget syncChild(Widget newNode, Widget oldNode, dynamic slot) { |
| 128 | 139 |
| 129 assert(oldNode is! Component || | 140 assert(oldNode is! Component || |
| 130 (oldNode is Component && !oldNode._disqualifiedFromEverAppearingAgain
)); // TODO(ianh): Simplify this once the analyzer is cleverer | 141 (oldNode is Component && !oldNode._disqualifiedFromEverAppearingAgain
)); // TODO(ianh): Simplify this once the analyzer is cleverer |
| 131 | 142 |
| 132 if (newNode == oldNode) { | 143 if (newNode == oldNode) { |
| 133 assert(newNode == null || newNode.mounted); | 144 assert(newNode == null || newNode.mounted); |
| 134 assert(newNode is! RenderObjectWrapper || | 145 assert(newNode is! RenderObjectWrapper || |
| 135 (newNode is RenderObjectWrapper && newNode._ancestor != null)); //
TODO(ianh): Simplify this once the analyzer is cleverer | 146 (newNode is RenderObjectWrapper && newNode._ancestor != null)); //
TODO(ianh): Simplify this once the analyzer is cleverer |
| 147 if (newNode != null) |
| 148 newNode.setParent(this); |
| 136 return newNode; // Nothing to do. Subtrees must be identical. | 149 return newNode; // Nothing to do. Subtrees must be identical. |
| 137 } | 150 } |
| 138 | 151 |
| 139 if (newNode == null) { | 152 if (newNode == null) { |
| 140 // the child in this slot has gone away | 153 // the child in this slot has gone away |
| 141 assert(oldNode.mounted); | 154 assert(oldNode.mounted); |
| 142 oldNode.detachRoot(); | 155 oldNode.detachRoot(); |
| 143 removeChild(oldNode); | 156 removeChild(oldNode); |
| 144 assert(!oldNode.mounted); | 157 assert(!oldNode.mounted); |
| 145 return null; | 158 return null; |
| 146 } | 159 } |
| 147 | 160 |
| 148 if (oldNode != null) { | 161 if (oldNode != null) { |
| 149 if (oldNode.runtimeType == newNode.runtimeType && oldNode.key == newNode.k
ey) { | 162 if (oldNode.runtimeType == newNode.runtimeType && oldNode.key == newNode.k
ey) { |
| 150 if (newNode._retainStatefulNodeIfPossible(oldNode)) { | 163 if (newNode._retainStatefulNodeIfPossible(oldNode)) { |
| 151 assert(oldNode.mounted); | 164 assert(oldNode.mounted); |
| 152 assert(!newNode.mounted); | 165 assert(!newNode.mounted); |
| 153 oldNode.setParent(this); | 166 oldNode.setParent(this); |
| 154 oldNode._sync(newNode, slot); | 167 oldNode._sync(newNode, slot); |
| 155 assert(oldNode.root is RenderObject); | 168 assert(oldNode.root is RenderObject); |
| 156 return oldNode; | 169 return oldNode; |
| 170 } else { |
| 171 oldNode.setParent(null); |
| 157 } | 172 } |
| 158 } else { | 173 } else { |
| 159 assert(oldNode.mounted); | 174 assert(oldNode.mounted); |
| 160 oldNode.detachRoot(); | 175 oldNode.detachRoot(); |
| 161 removeChild(oldNode); | 176 removeChild(oldNode); |
| 162 oldNode = null; | 177 oldNode = null; |
| 163 } | 178 } |
| 164 } | 179 } |
| 165 | 180 |
| 181 assert(oldNode == null || (oldNode.mounted == false && oldNode.parent == nul
l)); |
| 166 assert(!newNode.mounted); | 182 assert(!newNode.mounted); |
| 167 newNode.setParent(this); | 183 newNode.setParent(this); |
| 168 newNode._sync(oldNode, slot); | 184 newNode._sync(oldNode, slot); |
| 169 assert(newNode.root is RenderObject); | 185 assert(newNode.root is RenderObject); |
| 170 return newNode; | 186 return newNode; |
| 171 } | 187 } |
| 172 | 188 |
| 173 String toString() { | 189 String toString() { |
| 174 if (key == null) | 190 if (key == null) |
| 175 return '$runtimeType(unkeyed)'; | 191 return '$runtimeType(unkeyed)'; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 193 | 209 |
| 194 Widget child; | 210 Widget child; |
| 195 | 211 |
| 196 void walkChildren(WidgetTreeWalker walker) { | 212 void walkChildren(WidgetTreeWalker walker) { |
| 197 walker(child); | 213 walker(child); |
| 198 } | 214 } |
| 199 | 215 |
| 200 void _sync(Widget old, dynamic slot) { | 216 void _sync(Widget old, dynamic slot) { |
| 201 Widget oldChild = old == null ? null : (old as TagNode).child; | 217 Widget oldChild = old == null ? null : (old as TagNode).child; |
| 202 child = syncChild(child, oldChild, slot); | 218 child = syncChild(child, oldChild, slot); |
| 219 assert(child.parent == this); |
| 203 assert(child.root != null); | 220 assert(child.root != null); |
| 204 _root = child.root; | 221 _root = child.root; |
| 205 assert(_root == root); // in case a subclass reintroduces it | 222 assert(_root == root); // in case a subclass reintroduces it |
| 206 } | 223 } |
| 207 | 224 |
| 208 void remove() { | 225 void remove() { |
| 209 if (child != null) | 226 if (child != null) |
| 210 removeChild(child); | 227 removeChild(child); |
| 211 super.remove(); | 228 super.remove(); |
| 212 } | 229 } |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 int lastOrder = _currentOrder; | 472 int lastOrder = _currentOrder; |
| 456 _currentOrder = _order; | 473 _currentOrder = _order; |
| 457 _currentlyBuilding = this; | 474 _currentlyBuilding = this; |
| 458 _built = build(); | 475 _built = build(); |
| 459 assert(_built != null); | 476 assert(_built != null); |
| 460 _currentlyBuilding = null; | 477 _currentlyBuilding = null; |
| 461 _currentOrder = lastOrder; | 478 _currentOrder = lastOrder; |
| 462 | 479 |
| 463 _built = syncChild(_built, oldBuilt, slot); | 480 _built = syncChild(_built, oldBuilt, slot); |
| 464 assert(_built != null); | 481 assert(_built != null); |
| 482 assert(_built.parent == this); |
| 465 _dirty = false; | 483 _dirty = false; |
| 466 _root = _built.root; | 484 _root = _built.root; |
| 467 assert(_root == root); // in case a subclass reintroduces it | 485 assert(_root == root); // in case a subclass reintroduces it |
| 468 assert(root != null); | 486 assert(root != null); |
| 469 } | 487 } |
| 470 | 488 |
| 471 void _buildIfDirty() { | 489 void _buildIfDirty() { |
| 472 assert(!_disqualifiedFromEverAppearingAgain); | 490 assert(!_disqualifiedFromEverAppearingAgain); |
| 473 if (!_dirty || !_mounted) | 491 if (!_dirty || !_mounted) |
| 474 return; | 492 return; |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 Widget _child; | 674 Widget _child; |
| 657 Widget get child => _child; | 675 Widget get child => _child; |
| 658 | 676 |
| 659 void walkChildren(WidgetTreeWalker walker) { | 677 void walkChildren(WidgetTreeWalker walker) { |
| 660 walker(child); | 678 walker(child); |
| 661 } | 679 } |
| 662 | 680 |
| 663 void syncRenderObject(RenderObjectWrapper old) { | 681 void syncRenderObject(RenderObjectWrapper old) { |
| 664 super.syncRenderObject(old); | 682 super.syncRenderObject(old); |
| 665 Widget oldChild = old == null ? null : (old as OneChildRenderObjectWrapper).
child; | 683 Widget oldChild = old == null ? null : (old as OneChildRenderObjectWrapper).
child; |
| 666 _child = syncChild(child, oldChild, null); | 684 Widget newChild = child; |
| 685 _child = syncChild(newChild, oldChild, null); |
| 686 assert((newChild == null && child == null) || (newChild != null && child.par
ent == this)); |
| 687 assert(oldChild == null || child == oldChild || oldChild.parent == null); |
| 667 } | 688 } |
| 668 | 689 |
| 669 void insertChildRoot(RenderObjectWrapper child, dynamic slot) { | 690 void insertChildRoot(RenderObjectWrapper child, dynamic slot) { |
| 670 final root = this.root; // TODO(ianh): Remove this once the analyzer is clev
erer | 691 final root = this.root; // TODO(ianh): Remove this once the analyzer is clev
erer |
| 671 assert(root is RenderObjectWithChildMixin); | 692 assert(root is RenderObjectWithChildMixin); |
| 672 assert(slot == null); | 693 assert(slot == null); |
| 673 root.child = child.root; | 694 root.child = child.root; |
| 674 assert(root == this.root); // TODO(ianh): Remove this once the analyzer is c
leverer | 695 assert(root == this.root); // TODO(ianh): Remove this once the analyzer is c
leverer |
| 675 } | 696 } |
| 676 | 697 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 696 | 717 |
| 697 MultiChildRenderObjectWrapper({ String key, List<Widget> children }) | 718 MultiChildRenderObjectWrapper({ String key, List<Widget> children }) |
| 698 : this.children = children == null ? const [] : children, | 719 : this.children = children == null ? const [] : children, |
| 699 super(key: key) { | 720 super(key: key) { |
| 700 assert(!_debugHasDuplicateIds()); | 721 assert(!_debugHasDuplicateIds()); |
| 701 } | 722 } |
| 702 | 723 |
| 703 final List<Widget> children; | 724 final List<Widget> children; |
| 704 | 725 |
| 705 void walkChildren(WidgetTreeWalker walker) { | 726 void walkChildren(WidgetTreeWalker walker) { |
| 706 for(Widget child in children) | 727 for (Widget child in children) |
| 707 walker(child); | 728 walker(child); |
| 708 } | 729 } |
| 709 | 730 |
| 710 void insertChildRoot(RenderObjectWrapper child, dynamic slot) { | 731 void insertChildRoot(RenderObjectWrapper child, dynamic slot) { |
| 711 final root = this.root; // TODO(ianh): Remove this once the analyzer is clev
erer | 732 final root = this.root; // TODO(ianh): Remove this once the analyzer is clev
erer |
| 712 assert(slot == null || slot is RenderObject); | 733 assert(slot == null || slot is RenderObject); |
| 713 assert(root is ContainerRenderObjectMixin); | 734 assert(root is ContainerRenderObjectMixin); |
| 714 root.add(child.root, before: slot); | 735 root.add(child.root, before: slot); |
| 715 assert(root == this.root); // TODO(ianh): Remove this once the analyzer is c
leverer | 736 assert(root == this.root); // TODO(ianh): Remove this once the analyzer is c
leverer |
| 716 } | 737 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 var oldStartIndex = 0; | 781 var oldStartIndex = 0; |
| 761 var oldEndIndex = oldChildren.length; | 782 var oldEndIndex = oldChildren.length; |
| 762 | 783 |
| 763 RenderObject nextSibling = null; | 784 RenderObject nextSibling = null; |
| 764 Widget currentNode = null; | 785 Widget currentNode = null; |
| 765 Widget oldNode = null; | 786 Widget oldNode = null; |
| 766 | 787 |
| 767 void sync(int atIndex) { | 788 void sync(int atIndex) { |
| 768 children[atIndex] = syncChild(currentNode, oldNode, nextSibling); | 789 children[atIndex] = syncChild(currentNode, oldNode, nextSibling); |
| 769 assert(children[atIndex] != null); | 790 assert(children[atIndex] != null); |
| 791 assert(children[atIndex].parent == this); |
| 770 } | 792 } |
| 771 | 793 |
| 772 // Scan backwards from end of list while nodes can be directly synced | 794 // Scan backwards from end of list while nodes can be directly synced |
| 773 // without reordering. | 795 // without reordering. |
| 774 while (endIndex > startIndex && oldEndIndex > oldStartIndex) { | 796 while (endIndex > startIndex && oldEndIndex > oldStartIndex) { |
| 775 currentNode = children[endIndex - 1]; | 797 currentNode = children[endIndex - 1]; |
| 776 oldNode = oldChildren[oldEndIndex - 1]; | 798 oldNode = oldChildren[oldEndIndex - 1]; |
| 777 | 799 |
| 778 if (currentNode.runtimeType != oldNode.runtimeType || currentNode.key != o
ldNode.key) { | 800 if (currentNode.runtimeType != oldNode.runtimeType || currentNode.key != o
ldNode.key) { |
| 779 break; | 801 break; |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 863 currentNode = children[startIndex]; | 885 currentNode = children[startIndex]; |
| 864 sync(startIndex); | 886 sync(startIndex); |
| 865 startIndex++; | 887 startIndex++; |
| 866 } | 888 } |
| 867 | 889 |
| 868 // Removals | 890 // Removals |
| 869 currentNode = null; | 891 currentNode = null; |
| 870 while (oldStartIndex < oldEndIndex) { | 892 while (oldStartIndex < oldEndIndex) { |
| 871 oldNode = oldChildren[oldStartIndex]; | 893 oldNode = oldChildren[oldStartIndex]; |
| 872 syncChild(null, oldNode, null); | 894 syncChild(null, oldNode, null); |
| 895 assert(oldNode.parent == null); |
| 873 advanceOldStartIndex(); | 896 advanceOldStartIndex(); |
| 874 } | 897 } |
| 875 | 898 |
| 876 assert(root == this.root); // TODO(ianh): Remove this once the analyzer is c
leverer | 899 assert(root == this.root); // TODO(ianh): Remove this once the analyzer is c
leverer |
| 877 } | 900 } |
| 878 | 901 |
| 879 } | 902 } |
| 880 | 903 |
| 881 class WidgetSkyBinding extends SkyBinding { | 904 class WidgetSkyBinding extends SkyBinding { |
| 882 | 905 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1011 if (root.parent == null) { | 1034 if (root.parent == null) { |
| 1012 // we haven't attached it yet | 1035 // we haven't attached it yet |
| 1013 assert(_container.child == null); | 1036 assert(_container.child == null); |
| 1014 _container.child = root; | 1037 _container.child = root; |
| 1015 } | 1038 } |
| 1016 assert(root.parent == _container); | 1039 assert(root.parent == _container); |
| 1017 } | 1040 } |
| 1018 | 1041 |
| 1019 Widget build() => builder(); | 1042 Widget build() => builder(); |
| 1020 } | 1043 } |
| OLD | NEW |