| Index: sky/sdk/lib/widgets/widget.dart
|
| diff --git a/sky/sdk/lib/widgets/widget.dart b/sky/sdk/lib/widgets/widget.dart
|
| index 57f5c16bb276e971a6f6f8e2c128a7fe26c2b48d..09dd8b10e8dc1cc6abc4188b7c9a76cb3d88a31f 100644
|
| --- a/sky/sdk/lib/widgets/widget.dart
|
| +++ b/sky/sdk/lib/widgets/widget.dart
|
| @@ -18,14 +18,24 @@ export '../rendering/object.dart' show Point, Size, Rect, Color, Paint, Path;
|
|
|
| final bool _shouldLogRenderDuration = false;
|
|
|
| +typedef void WidgetTreeWalker(Widget);
|
| +
|
| // All Effen nodes derive from Widget. All nodes have a _parent, a _key and
|
| // can be sync'd.
|
| abstract class Widget {
|
|
|
| Widget({ String key }) : _key = key {
|
| - assert(this is AbstractWidgetRoot || this is App || _inRenderDirtyComponents); // you should not build the UI tree ahead of time, build it only during build()
|
| + assert(_isConstructedDuringBuild());
|
| + }
|
| +
|
| + // TODO(jackson): Remove this workaround for limitation of Dart mixins
|
| + Widget._withKey(String key) : _key = key {
|
| + assert(_isConstructedDuringBuild());
|
| }
|
|
|
| + // you should not build the UI tree ahead of time, build it only during build()
|
| + bool _isConstructedDuringBuild() => this is AbstractWidgetRoot || this is App || _inRenderDirtyComponents;
|
| +
|
| String _key;
|
| String get key => _key;
|
|
|
| @@ -55,6 +65,9 @@ abstract class Widget {
|
| }
|
| }
|
|
|
| + // Override this if you have children and call walker on each child
|
| + void walkChildren(WidgetTreeWalker walker) { }
|
| +
|
| static void _notifyMountStatusChanged() {
|
| try {
|
| sky.tracing.begin("Widget._notifyMountStatusChanged");
|
| @@ -171,8 +184,16 @@ abstract class TagNode extends Widget {
|
| TagNode(Widget child, { String key })
|
| : this.child = child, super(key: key);
|
|
|
| + // TODO(jackson): Remove this workaround for limitation of Dart mixins
|
| + TagNode._withKey(Widget child, String key)
|
| + : this.child = child, super._withKey(key);
|
| +
|
| Widget child;
|
|
|
| + void walkChildren(WidgetTreeWalker walker) {
|
| + walker(child);
|
| + }
|
| +
|
| void _sync(Widget old, dynamic slot) {
|
| Widget oldChild = old == null ? null : (old as TagNode).child;
|
| child = syncChild(child, oldChild, slot);
|
| @@ -200,6 +221,56 @@ class ParentDataNode extends TagNode {
|
| final ParentData parentData;
|
| }
|
|
|
| +abstract class _Heir implements Widget {
|
| + Map<Type, Inherited> _traits;
|
| + Inherited inheritedOfType(Type type) => _traits[type];
|
| +
|
| + static _Heir _getHeirAncestor(Widget widget) {
|
| + Widget ancestor = widget;
|
| + while (ancestor != null && !(ancestor is _Heir)) {
|
| + ancestor = ancestor.parent;
|
| + }
|
| + return ancestor as _Heir;
|
| + }
|
| +
|
| + void _updateTraitsFromParent(Widget parent) {
|
| + _Heir ancestor = _getHeirAncestor(parent);
|
| + if (ancestor == null || ancestor._traits == null) return;
|
| + _updateTraits(ancestor._traits);
|
| + }
|
| +
|
| + void _updateTraitsRecursively(Widget widget) {
|
| + if (widget is _Heir)
|
| + widget._updateTraits(_traits);
|
| + else
|
| + widget.walkChildren(_updateTraitsRecursively);
|
| + }
|
| +
|
| + void _updateTraits(Map<Type, Inherited> newTraits) {
|
| + if (newTraits != _traits) {
|
| + _traits = newTraits;
|
| + walkChildren(_updateTraitsRecursively);
|
| + }
|
| + }
|
| +}
|
| +
|
| +abstract class Inherited extends TagNode with _Heir {
|
| + Inherited({ String key, Widget child }) : super._withKey(child, key) {
|
| + _traits = new Map<Type, Inherited>();
|
| + }
|
| +
|
| + void set _traits(Map<Type, Inherited> value) {
|
| + super._traits = new Map<Type, Inherited>.from(value)
|
| + ..[runtimeType] = this;
|
| + }
|
| +
|
| + // TODO(jackson): When Dart supports super in mixins we can move to _Heir
|
| + void setParent(Widget parent) {
|
| + _updateTraitsFromParent(parent);
|
| + super.setParent(parent);
|
| + }
|
| +}
|
| +
|
| typedef void GestureEventListener(sky.GestureEvent e);
|
| typedef void PointerEventListener(sky.PointerEvent e);
|
| typedef void EventListener(sky.Event e);
|
| @@ -291,13 +362,12 @@ class Listener extends TagNode {
|
|
|
| }
|
|
|
| -
|
| -abstract class Component extends Widget {
|
| +abstract class Component extends Widget with _Heir {
|
|
|
| Component({ String key, bool stateful })
|
| : _stateful = stateful != null ? stateful : false,
|
| _order = _currentOrder + 1,
|
| - super(key: key);
|
| + super._withKey(key);
|
|
|
| static Component _currentlyBuilding;
|
| bool get _isBuilding => _currentlyBuilding == this;
|
| @@ -314,6 +384,12 @@ abstract class Component extends Widget {
|
| super.didMount();
|
| }
|
|
|
| + // TODO(jackson): When Dart supports super in mixins we can move to _Heir
|
| + void setParent(Widget parent) {
|
| + _updateTraitsFromParent(parent);
|
| + super.setParent(parent);
|
| + }
|
| +
|
| void remove() {
|
| assert(_built != null);
|
| assert(root != null);
|
| @@ -573,6 +649,10 @@ abstract class OneChildRenderObjectWrapper extends RenderObjectWrapper {
|
| Widget _child;
|
| Widget get child => _child;
|
|
|
| + void walkChildren(WidgetTreeWalker walker) {
|
| + walker(child);
|
| + }
|
| +
|
| void syncRenderObject(RenderObjectWrapper old) {
|
| super.syncRenderObject(old);
|
| Widget oldChild = old == null ? null : (old as OneChildRenderObjectWrapper).child;
|
| @@ -600,7 +680,6 @@ abstract class OneChildRenderObjectWrapper extends RenderObjectWrapper {
|
| removeChild(child);
|
| super.remove();
|
| }
|
| -
|
| }
|
|
|
| abstract class MultiChildRenderObjectWrapper extends RenderObjectWrapper {
|
| @@ -616,6 +695,11 @@ abstract class MultiChildRenderObjectWrapper extends RenderObjectWrapper {
|
|
|
| final List<Widget> children;
|
|
|
| + void walkChildren(WidgetTreeWalker walker) {
|
| + for(Widget child in children)
|
| + walker(child);
|
| + }
|
| +
|
| void insertChildRoot(RenderObjectWrapper child, dynamic slot) {
|
| final root = this.root; // TODO(ianh): Remove this once the analyzer is cleverer
|
| assert(slot == null || slot is RenderObject);
|
|
|