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

Unified Diff: sky/examples/fn/lib/component.dart

Issue 971183002: Initial commit of Effen reactive framework experiment for Sky (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sky/examples/fn/README.md ('k') | sky/examples/fn/lib/fakesky.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sky/examples/fn/lib/component.dart
diff --git a/sky/examples/fn/lib/component.dart b/sky/examples/fn/lib/component.dart
new file mode 100644
index 0000000000000000000000000000000000000000..1263b416252b540fcc7184dc524e5620ca907873
--- /dev/null
+++ b/sky/examples/fn/lib/component.dart
@@ -0,0 +1,158 @@
+part of fn;
+
+List<Component> _dirtyComponents = new List<Component>();
+bool _renderScheduled = false;
+
+void _renderDirtyComponents() {
+ Stopwatch sw = new Stopwatch()..start();
+
+ _dirtyComponents.sort((a, b) => a._order - b._order);
+ for (var comp in _dirtyComponents) {
+ comp._renderIfDirty();
+ }
+
+ _dirtyComponents.clear();
+ _renderScheduled = false;
+ sw.stop();
+ print("Render took ${sw.elapsedMicroseconds} microseconds");
+}
+
+void _scheduleComponentForRender(Component c) {
+ _dirtyComponents.add(c);
+
+ if (!_renderScheduled) {
+ _renderScheduled = true;
+ new Future.microtask(_renderDirtyComponents);
+ }
+}
+
+abstract class Component extends Node {
+ bool _dirty = true; // components begin dirty because they haven't rendered.
+ Node _rendered = null;
+ bool _removed = false;
+ int _order;
+ static int _currentOrder = 0;
+ bool _stateful;
+ static Component _currentlyRendering;
+
+ Component({ Object key, bool stateful })
+ : _stateful = stateful != null ? stateful : false,
+ _order = _currentOrder + 1,
+ super(key:key);
+
+ void willUnmount() {}
+
+ void _remove() {
+ assert(_rendered != null);
+ assert(_root != null);
+ willUnmount();
+ _rendered._remove();
+ _rendered = null;
+ _root = null;
+ _removed = true;
+ }
+
+ // TODO(rafaelw): It seems wrong to expose DOM at all. This is presently
+ // needed to get sizing info.
+ sky.Node getRoot() => _root;
+
+ bool _sync(Node old, sky.Node host, sky.Node insertBefore) {
+ Component oldComponent = old as Component;
+
+ if (oldComponent == null || oldComponent == this) {
+ _renderInternal(host, insertBefore);
+ return false;
+ }
+
+ assert(oldComponent != null);
+ assert(_dirty);
+ assert(_rendered == null);
+
+ if (oldComponent._stateful) {
+ _stateful = false; // prevent iloop from _renderInternal below.
+
+ reflect.copyPublicFields(this, oldComponent);
+
+ oldComponent._dirty = true;
+ _dirty = false;
+
+ oldComponent._renderInternal(host, insertBefore);
+ return true; // Must retain old component
+ }
+
+ _rendered = oldComponent._rendered;
+ _renderInternal(host, insertBefore);
+ return false;
+ }
+
+ void _renderInternal(sky.Node host, sky.Node insertBefore) {
+ if (!_dirty) {
+ assert(_rendered != null);
+ return;
+ }
+
+ var oldRendered = _rendered;
+ int lastOrder = _currentOrder;
+ _currentOrder = _order;
+ _currentlyRendering = this;
+ _rendered = render();
+ _currentlyRendering = null;
+ _currentOrder = lastOrder;
+
+ _dirty = false;
+
+ // TODO(rafaelw): This prevents components from returning different node
+ // types as their root node at different times. Consider relaxing.
+ assert(oldRendered == null ||
+ _rendered.runtimeType == oldRendered.runtimeType);
+
+ if (_rendered._sync(oldRendered, host, insertBefore)) {
+ _rendered = oldRendered; // retain stateful component
+ }
+ _root = _rendered._root;
+ assert(_rendered._root is sky.Node);
+ }
+
+ void _renderIfDirty() {
+ assert(_rendered != null);
+ assert(!_removed);
+
+ var rendered = _rendered;
+ while (rendered is Component) {
+ rendered = rendered._rendered;
+ }
+ sky.Node root = rendered._root;
+
+ _renderInternal(root.parentNode, root.nextSibling);
+ }
+
+ void setState(Function fn()) {
+ assert(_rendered != null); // cannot setState before mounting.
+ _stateful = true;
+ fn();
+ if (_currentlyRendering != this) {
+ _dirty = true;
+ _scheduleComponentForRender(this);
+ }
+ }
+
+ Node render();
+}
+
+abstract class App extends Component {
+ sky.Node _host = null;
+ App()
+ : super(stateful: true) {
+
+ _host = sky.document.createElement('div');
+ sky.document.appendChild(_host);
+
+ new Future.microtask(() {
+ Stopwatch sw = new Stopwatch()..start();
+ _sync(null, _host, null);
+ assert(_root is sky.Node);
+ sw.stop();
+ print("Initial render: ${sw.elapsedMicroseconds} microseconds");
+ });
+ }
+}
« no previous file with comments | « sky/examples/fn/README.md ('k') | sky/examples/fn/lib/fakesky.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698