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

Unified Diff: sky/framework/fn.dart

Issue 987463002: Move fn.dart into /sky/framework (Closed) Base URL: git@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/stocks-fn/stocksapp.dart ('k') | sky/framework/reflect.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sky/framework/fn.dart
diff --git a/sky/examples/fn/lib/node.dart b/sky/framework/fn.dart
similarity index 66%
rename from sky/examples/fn/lib/node.dart
rename to sky/framework/fn.dart
index 54853b3e83278efc6a1a4aac8e60968ba2ce74e9..cfd25775265a673f5aa94577ae6212a1c2c8ca6b 100644
--- a/sky/examples/fn/lib/node.dart
+++ b/sky/framework/fn.dart
@@ -2,7 +2,76 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-part of fn;
+library fn;
+
+import 'dart:async';
+import 'dart:collection';
+import 'dart:sky' as sky;
+import 'reflect.dart' as reflect;
+
+bool _checkedMode;
+
+bool _debugWarnings() {
+ void testFn(double i) {}
+
+ if (_checkedMode == null) {
+ _checkedMode = false;
+ try {
+ testFn('not a double');
+ } catch (ex) {
+ _checkedMode = true;
+ }
+ }
+
+ return _checkedMode;
+}
+
+class EventHandler {
+ final String type;
+ final sky.EventListener listener;
+
+ EventHandler(this.type, this.listener);
+}
+
+class EventMap {
+ final List<EventHandler> _handlers = new List<EventHandler>();
+
+ void listen(String type, sky.EventListener listener) {
+ assert(listener != null);
+ _handlers.add(new EventHandler(type, listener));
+ }
+
+ void addAll(EventMap events) {
+ _handlers.addAll(events._handlers);
+ }
+}
+
+class Style {
+ final String _className;
+ static final Map<String, Style> _cache = new HashMap<String, Style>();
+
+ static int nextStyleId = 1;
+
+ static String nextClassName(String styles) {
+ assert(sky.document != null);
+ String className = "style$nextStyleId";
+ nextStyleId++;
+
+ sky.Element styleNode = sky.document.createElement('style');
+ styleNode.setChild(new sky.Text(".$className { $styles }"));
+ sky.document.appendChild(styleNode);
+
+ return className;
+ }
+
+ factory Style(String styles) {
+ return _cache.putIfAbsent(styles, () {
+ return new Style._internal(nextClassName(styles));
+ });
+ }
+
+ Style._internal(this._className);
+}
void _parentInsertBefore(sky.ParentNode parent,
sky.Node node,
@@ -433,3 +502,162 @@ class Anchor extends Element {
}
}
}
+
+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;
+ final 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;
+
+ _rendered.events.addAll(events);
+
+ _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/stocks-fn/stocksapp.dart ('k') | sky/framework/reflect.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698