| 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 'package:sky/mojo/activity.dart' as activity; | 10 import 'package:sky/mojo/activity.dart' as activity; |
| 11 | 11 |
| 12 import '../base/hit_test.dart'; | 12 import '../base/hit_test.dart'; |
| 13 import '../rendering/box.dart'; | 13 import '../rendering/box.dart'; |
| 14 import '../rendering/object.dart'; | 14 import '../rendering/object.dart'; |
| 15 import '../rendering/sky_binding.dart'; | 15 import '../rendering/sky_binding.dart'; |
| 16 | 16 |
| 17 export '../rendering/box.dart' show BoxConstraints, BoxDecoration, Border, Borde
rSide, EdgeDims; | 17 export '../rendering/box.dart' show BoxConstraints, BoxDecoration, Border, Borde
rSide, EdgeDims; |
| 18 export '../rendering/flex.dart' show FlexDirection; | 18 export '../rendering/flex.dart' show FlexDirection; |
| 19 export '../rendering/object.dart' show Point, Offset, Size, Rect, Color, Paint,
Path; | 19 export '../rendering/object.dart' show Point, Offset, Size, Rect, Color, Paint,
Path; |
| 20 | 20 |
| 21 final bool _shouldLogRenderDuration = false; | 21 final bool _shouldLogRenderDuration = false; |
| 22 | 22 |
| 23 typedef void WidgetTreeWalker(Widget); | 23 typedef void WidgetTreeWalker(Widget); |
| 24 | 24 |
| 25 // All Effen nodes derive from Widget. All nodes have a _parent, a _key and | 25 /// A base class for elements of the widget tree |
| 26 // can be sync'd. | |
| 27 abstract class Widget { | 26 abstract class Widget { |
| 28 | 27 |
| 29 Widget({ String key }) : _key = key { | 28 Widget({ String key }) : _key = key { |
| 30 assert(_isConstructedDuringBuild()); | 29 assert(_isConstructedDuringBuild()); |
| 31 } | 30 } |
| 32 | 31 |
| 33 // TODO(jackson): Remove this workaround for limitation of Dart mixins | 32 // TODO(jackson): Remove this workaround for limitation of Dart mixins |
| 34 Widget._withKey(String key) : _key = key { | 33 Widget._withKey(String key) : _key = key { |
| 35 assert(_isConstructedDuringBuild()); | 34 assert(_isConstructedDuringBuild()); |
| 36 } | 35 } |
| 37 | 36 |
| 38 // you should not build the UI tree ahead of time, build it only during build(
) | 37 // you should not build the UI tree ahead of time, build it only during build(
) |
| 39 bool _isConstructedDuringBuild() => this is AbstractWidgetRoot || this is App
|| _inRenderDirtyComponents; | 38 bool _isConstructedDuringBuild() => this is AbstractWidgetRoot || this is App
|| _inRenderDirtyComponents; |
| 40 | 39 |
| 41 String _key; | 40 String _key; |
| 41 |
| 42 /// A semantic identifer for this widget |
| 43 /// |
| 44 /// Keys are used to find matches when synchronizing two widget trees, for |
| 45 /// example after a [Component] rebuilds. Without keys, two widgets can match |
| 46 /// if their runtimeType matches. With keys, the keys must match as well. |
| 47 /// Assigning a key to a widget can improve performance by causing the |
| 48 /// framework to sync widgets that share a lot of common structure and can |
| 49 /// help match stateful components semantically rather than positionally. |
| 42 String get key => _key; | 50 String get key => _key; |
| 43 | 51 |
| 44 Widget _parent; | 52 Widget _parent; |
| 53 |
| 54 /// The parent of this widget in the widget tree. |
| 45 Widget get parent => _parent; | 55 Widget get parent => _parent; |
| 46 | 56 |
| 47 bool _mounted = false; | 57 bool _mounted = false; |
| 48 bool _wasMounted = false; | 58 bool _wasMounted = false; |
| 49 bool get mounted => _mounted; | 59 bool get mounted => _mounted; |
| 50 static bool _notifyingMountStatus = false; | 60 static bool _notifyingMountStatus = false; |
| 51 static List<Widget> _mountedChanged = new List<Widget>(); | 61 static List<Widget> _mountedChanged = new List<Widget>(); |
| 52 | 62 |
| 63 /// Called during the synchronizing process to update the widget's parent. |
| 53 void setParent(Widget newParent) { | 64 void setParent(Widget newParent) { |
| 54 assert(!_notifyingMountStatus); | 65 assert(!_notifyingMountStatus); |
| 55 if (_parent == newParent) | 66 if (_parent == newParent) |
| 56 return; | 67 return; |
| 57 _parent = newParent; | 68 _parent = newParent; |
| 58 if (newParent == null) { | 69 if (newParent == null) { |
| 59 if (_mounted) { | 70 if (_mounted) { |
| 60 _mounted = false; | 71 _mounted = false; |
| 61 _mountedChanged.add(this); | 72 _mountedChanged.add(this); |
| 62 } | 73 } |
| 63 } else { | 74 } else { |
| 64 assert(newParent._mounted); | 75 assert(newParent._mounted); |
| 65 if (_parent._mounted != _mounted) { | 76 if (_parent._mounted != _mounted) { |
| 66 _mounted = _parent._mounted; | 77 _mounted = _parent._mounted; |
| 67 _mountedChanged.add(this); | 78 _mountedChanged.add(this); |
| 68 } | 79 } |
| 69 } | 80 } |
| 70 } | 81 } |
| 71 | 82 |
| 72 // Override this if you have children and call walker on each child. | 83 /// Walks the immediate children of this widget |
| 73 // Note that you may be called before the child has had its parent | 84 /// |
| 74 // pointer set to point to you. Your walker, and any methods it | 85 /// Override this if you have children and call walker on each child. |
| 75 // invokes on your descendants, should not rely on the ancestor | 86 /// Note that you may be called before the child has had its parent |
| 76 // chain being correctly configured at this point. | 87 /// pointer set to point to you. Your walker, and any methods it |
| 88 /// invokes on your descendants, should not rely on the ancestor |
| 89 /// chain being correctly configured at this point. |
| 77 void walkChildren(WidgetTreeWalker walker) { } | 90 void walkChildren(WidgetTreeWalker walker) { } |
| 78 | 91 |
| 79 static void _notifyMountStatusChanged() { | 92 static void _notifyMountStatusChanged() { |
| 80 try { | 93 try { |
| 81 sky.tracing.begin("Widget._notifyMountStatusChanged"); | 94 sky.tracing.begin("Widget._notifyMountStatusChanged"); |
| 82 _notifyingMountStatus = true; | 95 _notifyingMountStatus = true; |
| 83 for (Widget node in _mountedChanged) { | 96 for (Widget node in _mountedChanged) { |
| 84 if (node._wasMounted != node._mounted) { | 97 if (node._wasMounted != node._mounted) { |
| 85 if (node._mounted) | 98 if (node._mounted) |
| 86 node.didMount(); | 99 node.didMount(); |
| 87 else | 100 else |
| 88 node.didUnmount(); | 101 node.didUnmount(); |
| 89 node._wasMounted = node._mounted; | 102 node._wasMounted = node._mounted; |
| 90 } | 103 } |
| 91 } | 104 } |
| 92 _mountedChanged.clear(); | 105 _mountedChanged.clear(); |
| 93 } finally { | 106 } finally { |
| 94 _notifyingMountStatus = false; | 107 _notifyingMountStatus = false; |
| 95 sky.tracing.end("Widget._notifyMountStatusChanged"); | 108 sky.tracing.end("Widget._notifyMountStatusChanged"); |
| 96 } | 109 } |
| 97 } | 110 } |
| 111 |
| 112 /// Override this function to learn when this [Widget] enters the widget tree. |
| 98 void didMount() { } | 113 void didMount() { } |
| 114 |
| 115 /// Override this function to learn when this [Widget] leaves the widget tree. |
| 99 void didUnmount() { } | 116 void didUnmount() { } |
| 100 | 117 |
| 101 RenderObject _root; | 118 RenderObject _root; |
| 119 |
| 120 /// The underlying [RenderObject] associated with this [Widget]. |
| 102 RenderObject get root => _root; | 121 RenderObject get root => _root; |
| 103 | 122 |
| 104 // Subclasses which implements Nodes that become stateful may return true | 123 // Subclasses which implements Nodes that become stateful may return true |
| 105 // if the |old| node has become stateful and should be retained. | 124 // if the |old| node has become stateful and should be retained. |
| 106 // This is called immediately before _sync(). | 125 // This is called immediately before _sync(). |
| 107 // Component._retainStatefulNodeIfPossible() calls syncFields(). | 126 // Component._retainStatefulNodeIfPossible() calls syncFields(). |
| 108 bool _retainStatefulNodeIfPossible(Widget old) => false; | 127 bool _retainStatefulNodeIfPossible(Widget old) => false; |
| 109 | 128 |
| 110 void _sync(Widget old, dynamic slot); | 129 void _sync(Widget old, dynamic slot); |
| 111 void updateSlot(dynamic newSlot); | 130 void updateSlot(dynamic newSlot); |
| (...skipping 978 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1090 if (root.parent == null) { | 1109 if (root.parent == null) { |
| 1091 // we haven't attached it yet | 1110 // we haven't attached it yet |
| 1092 assert(_container.child == null); | 1111 assert(_container.child == null); |
| 1093 _container.child = root; | 1112 _container.child = root; |
| 1094 } | 1113 } |
| 1095 assert(root.parent == _container); | 1114 assert(root.parent == _container); |
| 1096 } | 1115 } |
| 1097 | 1116 |
| 1098 Widget build() => builder(); | 1117 Widget build() => builder(); |
| 1099 } | 1118 } |
| OLD | NEW |