| 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:sky' as sky; | 7 import 'dart:sky' as sky; |
| 8 | 8 |
| 9 import 'package:sky/base/debug.dart'; | 9 import 'package:sky/base/debug.dart'; |
| 10 import 'package:sky/base/hit_test.dart'; | 10 import 'package:sky/base/hit_test.dart'; |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 } | 199 } |
| 200 | 200 |
| 201 assert(oldNode == null || (oldNode.mounted == false && oldNode.parent == nul
l)); | 201 assert(oldNode == null || (oldNode.mounted == false && oldNode.parent == nul
l)); |
| 202 assert(!newNode.mounted); | 202 assert(!newNode.mounted); |
| 203 newNode.setParent(this); | 203 newNode.setParent(this); |
| 204 newNode._sync(oldNode, slot); | 204 newNode._sync(oldNode, slot); |
| 205 assert(newNode.root is RenderObject); | 205 assert(newNode.root is RenderObject); |
| 206 return newNode; | 206 return newNode; |
| 207 } | 207 } |
| 208 | 208 |
| 209 String _adjustPrefixWithParentCheck(Widget child, String prefix) { |
| 210 if (child.parent == this) |
| 211 return prefix; |
| 212 if (child.parent == null) |
| 213 return '$prefix [[DISCONNECTED]] '; |
| 214 return '$prefix [[PARENT IS ${child.parent.toStringName()}]] '; |
| 215 } |
| 216 |
| 209 String toString([String prefix = '', String startPrefix = '']) { | 217 String toString([String prefix = '', String startPrefix = '']) { |
| 210 String childrenString = ''; | 218 String childrenString = ''; |
| 211 List<Widget> children = new List<Widget>(); | 219 List<Widget> children = new List<Widget>(); |
| 212 walkChildren(children.add); | 220 walkChildren(children.add); |
| 213 if (children.length > 0) { | 221 if (children.length > 0) { |
| 214 Widget lastChild = children.removeLast(); | 222 Widget lastChild = children.removeLast(); |
| 215 String nextStartPrefix = prefix + ' +-'; | 223 String nextStartPrefix = prefix + ' +-'; |
| 216 String nextPrefix = prefix + ' | '; | 224 String nextPrefix = prefix + ' | '; |
| 217 for (Widget child in children) | 225 for (Widget child in children) |
| 218 childrenString += child.toString(nextPrefix, nextStartPrefix); | 226 childrenString += child.toString(nextPrefix, _adjustPrefixWithParentChec
k(child, nextStartPrefix)); |
| 219 String lastStartPrefix = prefix + ' \'-'; | 227 nextStartPrefix = prefix + ' \'-'; |
| 220 String lastPrefix = prefix + ' '; | 228 nextPrefix = prefix + ' '; |
| 221 childrenString += lastChild.toString(lastPrefix, lastStartPrefix); | 229 childrenString += lastChild.toString(nextPrefix, _adjustPrefixWithParentCh
eck(lastChild, nextStartPrefix)); |
| 222 } | 230 } |
| 223 return '$startPrefix${toStringName()}\n$childrenString'; | 231 return '$startPrefix${toStringName()}\n$childrenString'; |
| 224 } | 232 } |
| 225 String toStringName() { | 233 String toStringName() { |
| 226 if (key == null) | 234 if (key == null) |
| 227 return '$runtimeType(unkeyed; hashCode=$hashCode)'; | 235 return '$runtimeType(unkeyed; hashCode=$hashCode)'; |
| 228 return '$runtimeType("$key"; hashCode=$hashCode)'; | 236 return '$runtimeType("$key"; hashCode=$hashCode)'; |
| 229 } | 237 } |
| 230 | 238 |
| 231 } | 239 } |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 535 bool retainStatefulNodeIfPossible(StatefulComponent newNode) { | 543 bool retainStatefulNodeIfPossible(StatefulComponent newNode) { |
| 536 assert(!_disqualifiedFromEverAppearingAgain); | 544 assert(!_disqualifiedFromEverAppearingAgain); |
| 537 assert(newNode != null); | 545 assert(newNode != null); |
| 538 assert(runtimeType == newNode.runtimeType); | 546 assert(runtimeType == newNode.runtimeType); |
| 539 assert(key == newNode.key); | 547 assert(key == newNode.key); |
| 540 assert(_built != null); | 548 assert(_built != null); |
| 541 newNode._disqualifiedFromEverAppearingAgain = true; | 549 newNode._disqualifiedFromEverAppearingAgain = true; |
| 542 | 550 |
| 543 newNode._built = _built; | 551 newNode._built = _built; |
| 544 _built = null; | 552 _built = null; |
| 545 | |
| 546 syncFields(newNode); | |
| 547 _dirty = true; | 553 _dirty = true; |
| 548 | 554 |
| 549 return true; | 555 return true; |
| 550 } | 556 } |
| 551 | 557 |
| 558 // because our retainStatefulNodeIfPossible() method returns true, |
| 559 // when _sync is called, our 'old' is actually the new instance that |
| 560 // we are to copy state from. |
| 552 void _sync(Widget old, dynamic slot) { | 561 void _sync(Widget old, dynamic slot) { |
| 553 assert(!_disqualifiedFromEverAppearingAgain); | 562 assert(!_disqualifiedFromEverAppearingAgain); |
| 554 // TODO(ianh): _sync should only be called once when old == null | 563 // TODO(ianh): _sync should only be called once when old == null |
| 555 if (old == null && !_isStateInitialized) { | 564 if (old == null && !_isStateInitialized) { |
| 556 initState(); | 565 initState(); |
| 557 _isStateInitialized = true; | 566 _isStateInitialized = true; |
| 558 } | 567 } |
| 568 if (old != null) |
| 569 syncFields(old); |
| 559 super._sync(old, slot); | 570 super._sync(old, slot); |
| 560 } | 571 } |
| 561 | 572 |
| 562 // Stateful components can override initState if they want | 573 // Stateful components can override initState if they want |
| 563 // to do non-trivial work to initialize state. This is | 574 // to do non-trivial work to initialize state. This is |
| 564 // always called before build(). | 575 // always called before build(). |
| 565 void initState() { } | 576 void initState() { } |
| 566 | 577 |
| 567 // This is called by retainStatefulNodeIfPossible(), during | 578 // This is called by _sync(). Derived classes should override this |
| 568 // syncChild(), just before _sync() is called. Derived | 579 // method to update `this` to account for the new values the parent |
| 569 // classes should override this method to update `this` to | 580 // passed to `source`. Make sure to call super.syncFields(source) |
| 570 // account for the new values the parent passed to `source`. | 581 // unless you are extending StatefulComponent directly. |
| 571 // Make sure to call super.syncFields(source) unless you are | |
| 572 // extending StatefulComponent directly. | |
| 573 void syncFields(Component source); | 582 void syncFields(Component source); |
| 574 | 583 |
| 575 Widget syncChild(Widget node, Widget oldNode, dynamic slot) { | 584 Widget syncChild(Widget node, Widget oldNode, dynamic slot) { |
| 576 assert(!_disqualifiedFromEverAppearingAgain); | 585 assert(!_disqualifiedFromEverAppearingAgain); |
| 577 return super.syncChild(node, oldNode, slot); | 586 return super.syncChild(node, oldNode, slot); |
| 578 } | 587 } |
| 579 | 588 |
| 580 void setState(Function fn()) { | 589 void setState(Function fn()) { |
| 581 assert(!_disqualifiedFromEverAppearingAgain); | 590 assert(!_disqualifiedFromEverAppearingAgain); |
| 582 fn(); | 591 fn(); |
| (...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1090 } | 1099 } |
| 1091 | 1100 |
| 1092 class AppContainer extends AbstractWidgetRoot { | 1101 class AppContainer extends AbstractWidgetRoot { |
| 1093 AppContainer(this.app) { | 1102 AppContainer(this.app) { |
| 1094 assert(SkyBinding.instance is WidgetSkyBinding); | 1103 assert(SkyBinding.instance is WidgetSkyBinding); |
| 1095 } | 1104 } |
| 1096 final App app; | 1105 final App app; |
| 1097 Widget build() => new RenderViewWrapper(child: app); | 1106 Widget build() => new RenderViewWrapper(child: app); |
| 1098 } | 1107 } |
| 1099 | 1108 |
| 1109 AppContainer _container; |
| 1100 void runApp(App app, { RenderView renderViewOverride, bool enableProfilingLoop:
false }) { | 1110 void runApp(App app, { RenderView renderViewOverride, bool enableProfilingLoop:
false }) { |
| 1101 WidgetSkyBinding.initWidgetSkyBinding(renderViewOverride: renderViewOverride); | 1111 WidgetSkyBinding.initWidgetSkyBinding(renderViewOverride: renderViewOverride); |
| 1102 new AppContainer(app); | 1112 _container = new AppContainer(app); |
| 1103 if (enableProfilingLoop) { | 1113 if (enableProfilingLoop) { |
| 1104 new Timer.periodic(const Duration(milliseconds: 20), (_) { | 1114 new Timer.periodic(const Duration(milliseconds: 20), (_) { |
| 1105 app.scheduleBuild(); | 1115 app.scheduleBuild(); |
| 1106 }); | 1116 }); |
| 1107 } | 1117 } |
| 1108 } | 1118 } |
| 1119 void debugDumpApp() { |
| 1120 if (_container != null) |
| 1121 _container.toString().split('\n').forEach(print); |
| 1122 else |
| 1123 print("runApp() not yet called"); |
| 1124 } |
| 1125 |
| 1109 | 1126 |
| 1110 class RenderBoxToWidgetAdapter extends AbstractWidgetRoot { | 1127 class RenderBoxToWidgetAdapter extends AbstractWidgetRoot { |
| 1111 | 1128 |
| 1112 RenderBoxToWidgetAdapter( | 1129 RenderBoxToWidgetAdapter( |
| 1113 RenderObjectWithChildMixin<RenderBox> container, | 1130 RenderObjectWithChildMixin<RenderBox> container, |
| 1114 this.builder | 1131 this.builder |
| 1115 ) : _container = container, super() { | 1132 ) : _container = container, super() { |
| 1116 assert(builder != null); | 1133 assert(builder != null); |
| 1117 } | 1134 } |
| 1118 | 1135 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1140 if (root.parent == null) { | 1157 if (root.parent == null) { |
| 1141 // we haven't attached it yet | 1158 // we haven't attached it yet |
| 1142 assert(_container.child == null); | 1159 assert(_container.child == null); |
| 1143 _container.child = root; | 1160 _container.child = root; |
| 1144 } | 1161 } |
| 1145 assert(root.parent == _container); | 1162 assert(root.parent == _container); |
| 1146 } | 1163 } |
| 1147 | 1164 |
| 1148 Widget build() => builder(); | 1165 Widget build() => builder(); |
| 1149 } | 1166 } |
| OLD | NEW |