Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1055)

Side by Side Diff: sky/sdk/lib/widgets/widget.dart

Issue 1218183009: When syncing a child, we have to update the parent in all cases. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sky/sdk/lib/widgets/scaffold.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « sky/sdk/lib/widgets/scaffold.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698