提交 e3812af9 编写于 作者: A Adam Barth

Move fn.dart into /sky/framework

It's awkward to work on fn.dart in the examples directory so this CL moves it
to /sky/framework. Also, I've merged the whole library into one file instead of
using the |part| mechanism. The whole thing isn't that big.

R=eseidel@chromium.org

Review URL: https://codereview.chromium.org/987463002
上级 adc56ba3
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
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;
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");
});
}
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
part of fn;
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);
}
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library fn;
import 'dart:async';
import 'dart:collection';
import 'dart:sky' as sky;
import 'reflect.dart' as reflect;
part 'component.dart';
part 'event.dart';
part 'node.dart';
part 'style.dart';
bool _checkedMode;
bool _debugWarnings() {
void testFn(double i) {}
if (_checkedMode == null) {
_checkedMode = false;
try {
testFn('not a double');
} catch (ex) {
_checkedMode = true;
}
}
return _checkedMode;
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
part of fn;
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);
}
library item;
import '../../../framework/fn.dart';
import 'dart:sky' as sky;
import 'fn.dart';
import 'widgets.dart';
enum Color { RED, GREEN }
......
library widgets;
import '../lib/fn.dart';
import '../../../framework/animation/curves.dart';
import '../../../framework/animation/fling-curve.dart';
import '../../../framework/fn.dart';
import '../../../framework/theme/colors.dart';
import '../../../framework/theme/shadows.dart';
import 'dart:collection';
......
library stocksapp;
import '../../framework/fn.dart';
import '../data/stocks.dart';
import '../fn/lib/fn.dart';
import '../fn/widgets/widgets.dart';
import 'dart:collection';
import 'dart:math';
......
......@@ -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");
});
}
}
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library reflect;
import 'dart:mirrors';
import 'dart:collection';
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册