提交 9e73c7ee 编写于 作者: H Hixie

Refactor fn2.dart, since it breached our 1000-line threshold.

This moves input.dart to editing2/, since that way we can define the layering as strictly unidirectional.
It also reorders a bunch of imports to fit the style guide.
I removed the old remnants of the widgets example, and put the fn2 examples into the examples/widgets/ directory, to parallel the framework directory names.

R=abarth@chromium.org

Review URL: https://codereview.chromium.org/1177243002.
上级 c9dd7125
......@@ -2,30 +2,26 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:sky/framework/components2/tool_bar.dart';
import 'package:sky/framework/components2/drawer.dart';
import 'package:sky/framework/components2/drawer_header.dart';
import 'package:sky/framework/components2/floating_action_button.dart';
import 'package:sky/framework/components2/icon.dart';
import 'package:sky/framework/components2/icon_button.dart';
import 'package:sky/framework/components2/menu_divider.dart';
import 'package:sky/framework/components2/menu_item.dart';
import 'package:sky/framework/components2/input.dart';
import 'package:sky/framework/components2/modal_overlay.dart';
import 'package:sky/framework/components2/popup_menu.dart';
import 'package:sky/framework/components2/radio.dart';
import 'package:sky/framework/components2/scaffold.dart';
import 'package:sky/framework/fn2.dart';
import 'package:sky/framework/theme2/typography.dart' as typography;
import 'package:sky/framework/editing2/input.dart';
import 'package:sky/framework/theme2/colors.dart' as colors;
import 'package:sky/framework/widgets/drawer.dart';
import 'package:sky/framework/widgets/drawer_header.dart';
import 'package:sky/framework/widgets/floating_action_button.dart';
import 'package:sky/framework/widgets/icon.dart';
import 'package:sky/framework/widgets/icon_button.dart';
import 'package:sky/framework/widgets/menu_divider.dart';
import 'package:sky/framework/widgets/menu_item.dart';
import 'package:sky/framework/widgets/modal_overlay.dart';
import 'package:sky/framework/widgets/popup_menu.dart';
import 'package:sky/framework/widgets/radio.dart';
import 'package:sky/framework/widgets/scaffold.dart';
import 'package:sky/framework/widgets/tool_bar.dart';
import 'package:sky/framework/widgets/wrappers.dart';
import 'stock_data.dart';
import 'package:sky/framework/rendering/box.dart';
import 'stock_list.dart';
import 'stock_menu.dart';
import 'dart:async';
import 'dart:sky' as sky;
enum StockMode { optimistic, pessimistic }
class StocksApp extends App {
......
......@@ -2,14 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:sky/framework/fn2.dart';
import 'package:vector_math/vector_math.dart';
import 'dart:math' as math;
import 'dart:sky' as sky;
import 'package:sky/framework/rendering/box.dart';
import 'package:sky/framework/rendering/object.dart';
import 'package:sky/framework/theme2/colors.dart' as colors;
import 'dart:math' as math;
import 'dart:sky' as sky;
import 'package:sky/framework/widgets/wrappers.dart';
class StockArrow extends Component {
......
......@@ -4,6 +4,7 @@
import 'dart:convert';
import 'dart:math';
import 'package:sky/framework/net/fetch.dart';
// Snapshot from http://www.nasdaq.com/screening/company-list.aspx
......
......@@ -2,8 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:sky/framework/components2/fixed_height_scrollable.dart';
import 'package:sky/framework/fn2.dart';
import 'package:sky/framework/widgets/fixed_height_scrollable.dart';
import 'package:sky/framework/widgets/wrappers.dart';
import 'stock_data.dart';
import 'stock_row.dart';
......
......@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:sky/framework/fn2.dart';
import 'package:sky/framework/components2/popup_menu.dart';
import 'package:sky/framework/components2/checkbox.dart';
import 'package:sky/framework/widgets/checkbox.dart';
import 'package:sky/framework/widgets/popup_menu.dart';
import 'package:sky/framework/widgets/wrappers.dart';
import 'package:sky/framework/theme/view_configuration.dart';
class StockMenu extends Component {
......
......@@ -3,11 +3,11 @@
// found in the LICENSE file.
import 'dart:sky' as sky;
import 'package:sky/framework/components2/ink_well.dart';
import 'package:sky/framework/fn2.dart';
import 'package:sky/framework/rendering/flex.dart';
import 'package:sky/framework/rendering/box.dart';
import 'package:sky/framework/theme/typography.dart' as typography;
import 'package:sky/framework/widgets/wrappers.dart';
import 'package:sky/framework/widgets/ink_well.dart';
import 'stock_arrow.dart';
import 'stock_data.dart';
......
......@@ -3,8 +3,11 @@
// found in the LICENSE file.
import 'dart:sky' as sky;
import 'package:sky/framework/fn2.dart';
import 'package:sky/framework/rendering/box.dart';
import 'package:sky/framework/widgets/ui_node.dart';
import 'package:sky/framework/widgets/wrappers.dart';
import '../lib/solid_color_box.dart';
class Rectangle extends RenderObjectWrapper {
......@@ -29,7 +32,7 @@ class ContainerApp extends App {
child: new Block([
new Container(
decoration: new BoxDecoration(backgroundColor: const sky.Color(0xFFFFFF00)),
height: 20.0,
height: 20.0
),
new Image(src: "https://www.dartlang.org/logos/dart-logo.png",
size: new sky.Size(300.0, 300.0),
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:sky/framework/fn2.dart';
import 'package:sky/framework/widgets/wrappers.dart';
class HelloWorldApp extends App {
UINode build() {
......
#!mojo mojo:sky_viewer
<!--
// 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.
-->
<sky>
<import src="/sky/framework/debug/shake-to-reload.sky" />
<script>
import 'widgets_app.dart';
void main() {
new WidgetsApp();
}
</script>
</sky>
name: widgets
dependencies:
sky: any
......@@ -43,28 +43,6 @@ dart_pkg("sdk") {
"lib/framework/components/scaffold.dart",
"lib/framework/components/scrollable.dart",
"lib/framework/components/tool_bar.dart",
"lib/framework/components2/animated_component.dart",
"lib/framework/components2/button.dart",
"lib/framework/components2/button_base.dart",
"lib/framework/components2/checkbox.dart",
"lib/framework/components2/drawer.dart",
"lib/framework/components2/drawer_header.dart",
"lib/framework/components2/fixed_height_scrollable.dart",
"lib/framework/components2/floating_action_button.dart",
"lib/framework/components2/icon.dart",
"lib/framework/components2/icon_button.dart",
"lib/framework/components2/ink_well.dart",
"lib/framework/components2/input.dart",
"lib/framework/components2/material.dart",
"lib/framework/components2/menu_divider.dart",
"lib/framework/components2/menu_item.dart",
"lib/framework/components2/modal_overlay.dart",
"lib/framework/components2/popup_menu.dart",
"lib/framework/components2/popup_menu_item.dart",
"lib/framework/components2/radio.dart",
"lib/framework/components2/scaffold.dart",
"lib/framework/components2/scrollable.dart",
"lib/framework/components2/tool_bar.dart",
"lib/framework/debug/shake-to-reload.sky",
"lib/framework/debug/tracing.dart",
"lib/framework/editing/editable_string.dart",
......@@ -72,6 +50,7 @@ dart_pkg("sdk") {
"lib/framework/editing/keyboard.dart",
"lib/framework/editing2/editable_string.dart",
"lib/framework/editing2/editable_text.dart",
"lib/framework/editing2/input.dart",
"lib/framework/editing2/keyboard.dart",
"lib/framework/elements/animation/controller.dart",
"lib/framework/elements/animation/timer.dart",
......@@ -93,7 +72,6 @@ dart_pkg("sdk") {
"lib/framework/elements/sky-toolbar.sky",
"lib/framework/embedder.dart",
"lib/framework/fn.dart",
"lib/framework/fn2.dart",
"lib/framework/layout.dart",
"lib/framework/net/fetch.dart",
"lib/framework/net/image_cache.dart",
......@@ -117,6 +95,29 @@ dart_pkg("sdk") {
"lib/framework/theme2/shadows.dart",
"lib/framework/theme2/typography.dart",
"lib/framework/theme2/view_configuration.dart",
"lib/framework/widgets/animated_component.dart",
"lib/framework/widgets/button.dart",
"lib/framework/widgets/button_base.dart",
"lib/framework/widgets/checkbox.dart",
"lib/framework/widgets/drawer.dart",
"lib/framework/widgets/drawer_header.dart",
"lib/framework/widgets/fixed_height_scrollable.dart",
"lib/framework/widgets/floating_action_button.dart",
"lib/framework/widgets/icon.dart",
"lib/framework/widgets/icon_button.dart",
"lib/framework/widgets/ink_well.dart",
"lib/framework/widgets/material.dart",
"lib/framework/widgets/menu_divider.dart",
"lib/framework/widgets/menu_item.dart",
"lib/framework/widgets/modal_overlay.dart",
"lib/framework/widgets/popup_menu.dart",
"lib/framework/widgets/popup_menu_item.dart",
"lib/framework/widgets/radio.dart",
"lib/framework/widgets/scaffold.dart",
"lib/framework/widgets/scrollable.dart",
"lib/framework/widgets/tool_bar.dart",
"lib/framework/widgets/ui_node.dart",
"lib/framework/widgets/wrappers.dart",
"lib/sky_tool",
"pubspec.yaml",
]
......
Sky Framework
=============
SKY SDK
========
Effen is a functional-reactive framework for Sky which takes inspiration from
[React](http://facebook.github.io/react/). Effen is comprised of three main
parts: a virtual-dom and diffing engine, a component mechanism and a very early
set of widgets for use in creating applications.
Sky and Sky's SDK are designed as layered frameworks, where each layer
depends on the ones below it but could be replaced wholesale.
The central idea is that you build your UI out of components. Components
describe what their view should look like given their current configuration &
state. The diffing engine ensures that the DOM looks how the component describes
by applying minimal diffs to transition it from one state to the next.
The bottom-most layer is the Sky Platform, which is exposed to Dart
code as the ```dart:sky``` package.
If you just want to dive into code, see the [stocks example](../../../../examples/stocks).
Above this are the files in the [painting/](painting/) directory,
which provide APIs related to drawing graphics.
Hello World
-----------
Layout primitives are provided in the next layer, found in the
[rendering/](rendering/) directory. They use ```dart:sky``` and the
APIs exposed in painting/ to provide a retained-mode layout and
rendering model for applications or documents.
To build an application, create a subclass of App and instantiate it.
Widgets are provided by the files in the [widgets/](widgets/)
directory, using a reactive framework.
```HTML
<script>
import 'hello_world.dart';
main() {
new HelloWorldApp();
}
</script>
```
```dart
// In hello_world.dart
import 'package:sky/framework/fn.dart';
class HelloWorldApp extends App {
UINode build() {
return new Text('Hello, world!');
}
}
```
An app is comprised of (and is, itself, a) components. A component's main job is
to implement `UINode build()`. The idea here is that the `build` method describes
the DOM of a component at any given point during its lifetime. In this case, our
`HelloWorldApp`'s `build` method just returns a `Text` node which displays the
obligatory line of text.
Nodes
-----
A component's `build` method must return a single `UINode` which *may* have
children (and so on, forming a *subtree*). Effen comes with a few built-in nodes
which mirror the built-in nodes/elements of sky: `Text`, `Anchor` (`<a />`,
`Image` (`<img />`) and `Container` (`<div />`). `build` can return a tree of
Nodes comprised of any of these nodes and plus any other imported object which
extends `Component`.
How to structure you app
------------------------
If you're familiar with React, the basic idea is the same: Application data
flows *down* from components which have data to components & nodes which they
construct via construction parameters. Generally speaking, View-Model data (data
which is derived from *model* data, but exists only because the view needs it),
is computed during the course of `build` and is short-lived, being handed into
nodes & components as configuration data.
What does "data flowing down the tree" mean?
--------------------------------------------
Consider the case of a checkbox. (i.e. `widgets/checkbox.dart`). The `Checkbox`
constructor looks like this:
```dart
ValueChanged onChanged;
bool checked;
Checkbox({ Object key, this.onChanged, this.checked }) : super(key: key);
```
What this means is that the `Checkbox` component *never* "owns" the state of
the checkbox. It's current state is handed into the `checked` parameter, and
when a click occurs, the checkbox invokes its `onChanged` callback with the
value it thinks it should be changed to -- but it never directly changes the
value itself. This is a bit odd at first look, but if you think about it: a
control isn't very useful unless it gets its value out to someone and if you
think about databinding, the same thing happens: databinding basically tells a
control to *treat some remote variable as its storage*. That's all that is
happening here. In this case, some owning component probably has a set of values
which describe a form.
Stateful vs. Stateless components
---------------------------------
All components have access to two kinds of state: (1) configuration data
(constructor arguments) and (2) private data (data they mutate themselves).
While react components have explicit property bags for these two kinds of state
(`this.prop` and `this.state`), Effen maps these ideas to the public and private
fields of the component. Constructor arguments should (by convention) be
reflected as public fields of the component and state should only be set on
private (with a leading underbar `_`) fields.
All (non-component) Effen nodes are stateless. Some components will be stateful.
This state will likely encapsulate transient states of the UI, such as scroll
position, animation state, uncommitted form values, etc...
A component can become stateful in two ways: (1) by passing `super(stateful:
true)` to its call to the superclass's constructor, or by calling
`setState(Function fn)`. The former is a way to have a component start its life
stateful, and the latter results in the component becoming statefull *as well
as* scheduling the component to re-build at the end of the current animation
frame.
What does it mean to be stateful? It means that the diffing mechanism retains
the specific *instance* of the component as long as the component which builds
it continues to require its presence. The component which constructed it may
have provided new configuration in form of different values for the constructor
parameters, but these values (public fields) will be copied (using reflection)
onto the retained instance whose privates fields are left unmodified.
Rendering
---------
At the end of each animation frame, all components (including the root `App`)
which have `setState` on themselves will be rebuilt and the resulting changes
will be minimally applied to the DOM. Note that components of lower "order"
(those near the root of the tree) will build first because their building may
require rebuilding of higher order (those near the leaves), thus avoiding the
possibility that a component which is dirty build more than once during a single
cycle.
Keys
----
In order to efficiently apply changes to the DOM and to ensure that stateful
components are correctly identified, Effen requires that `no two nodes (except
Text) or components of the same type may exist as children of another element
without being distinguished by unique keys`. [`Text` is excused from this rule].
In many cases, nodes don't require a key because there is only one type amongst
its siblings -- but if there is more one, you must assign each a key. This is
why most nodes will take `({ Object key })` as an optional constructor
parameter. In development mode (i.e. when sky is built `Debug`) Effen will throw
an error if you forget to do this.
Event Handling
--------------
Events logically fire through the Effen node tree. If want to handle an event as
it bubbles from the target to the root, create an `EventListenerNode`. `EventListenerNode`
has named (typed) parameters for a small set of events that we've hit so far, as
well as a 'custom' argument which is a `Map<String, sky.EventListener>`. If
you'd like to add a type argument for an event, just post a patch.
```dart
class MyComp extends Component {
MyComp({
Object key
}) : super(key: key);
void _handleTap(sky.GestureEvent e) {
// do stuff
}
void _customEventCallback(sky.Event e) {
// do other stuff
}
UINode build() {
new EventListenerNode(
new Container(
children: // ...
),
onGestureTap: _handleTap,
custom: {
'myCustomEvent': _customEventCallback
}
);
}
_handleScroll(sky.Event e) {
setState(() {
// update the scroll position
});
}
}
```
Styling
-------
Styling is the part of Effen which is least designed and is likely to change.
There are three ways to specify styles:
* `Style` objects which are interned and can be applied to WrapperNodes via the
``style` constructor parameter. Use `Style` objects for styles which are
`*not* animated.
* An `inlineStyle` string which can be applied to Elements via the
`inlineStyle` constructor parameter. Use `inlineStyle` for styles which
*are* animated.
If you need to apply a Style to a Component or UINode which you didn't construct
(i.e. one that was handed into your constructor), you can wrap it in a
`StyleNode` which also takes a `Style` constructor in it's `style` constructor
parameter.
Animation
---------
Animation is still an area of exploration. Have a look at
[AnimatedComponent](components/animated_component.dart) and
[Drawer](components/drawer.dart) for an example of this this currently works.
Performance
-----------
It is a design goal that it should be *possible* to arrange that all "build"
cycles which happen during animations can complete in less than one milliesecond
on a Nexus 5.
Text input widgets are layered on this mechanism and can be found in
the [editing2/](editing2/) directory.
......@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../fn2.dart';
import '../theme/colors.dart';
import 'dart:async';
import '../widgets/wrappers.dart';
import 'editable_string.dart';
class EditableText extends Component {
......
......@@ -2,15 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../editing2/editable_string.dart';
import '../editing2/editable_text.dart';
import '../editing2/keyboard.dart';
import '../fn2.dart';
import '../theme2/colors.dart';
import '../theme2/typography.dart' as typography;
import '../rendering/flex.dart';
import 'dart:sky' as sky;
import '../rendering/flex.dart';
import '../widgets/wrappers.dart';
import 'editable_string.dart';
import 'editable_text.dart';
import 'keyboard.dart';
typedef void ValueChanged(value);
class Input extends Component {
......
Sky Framework
=============
(This file applies to fn.dart, which we are in the process of porting
to a new architecture.)
Effen is a functional-reactive framework for Sky which takes inspiration from
[React](http://facebook.github.io/react/). Effen is comprised of three main
parts: a virtual-dom and diffing engine, a component mechanism and a very early
set of widgets for use in creating applications.
The central idea is that you build your UI out of components. Components
describe what their view should look like given their current configuration &
state. The diffing engine ensures that the DOM looks how the component describes
by applying minimal diffs to transition it from one state to the next.
If you just want to dive into code, see the [stocks example](../../../../examples/stocks).
Hello World
-----------
To build an application, create a subclass of App and instantiate it.
```HTML
<script>
import 'hello_world.dart';
main() {
new HelloWorldApp();
}
</script>
```
```dart
// In hello_world.dart
import 'package:sky/framework/fn.dart';
class HelloWorldApp extends App {
UINode build() {
return new Text('Hello, world!');
}
}
```
An app is comprised of (and is, itself, a) components. A component's main job is
to implement `UINode build()`. The idea here is that the `build` method describes
the DOM of a component at any given point during its lifetime. In this case, our
`HelloWorldApp`'s `build` method just returns a `Text` node which displays the
obligatory line of text.
Nodes
-----
A component's `build` method must return a single `UINode` which *may* have
children (and so on, forming a *subtree*). Effen comes with a few built-in nodes
which mirror the built-in nodes/elements of sky: `Text`, `Anchor` (`<a />`,
`Image` (`<img />`) and `Container` (`<div />`). `build` can return a tree of
Nodes comprised of any of these nodes and plus any other imported object which
extends `Component`.
How to structure you app
------------------------
If you're familiar with React, the basic idea is the same: Application data
flows *down* from components which have data to components & nodes which they
construct via construction parameters. Generally speaking, View-Model data (data
which is derived from *model* data, but exists only because the view needs it),
is computed during the course of `build` and is short-lived, being handed into
nodes & components as configuration data.
What does "data flowing down the tree" mean?
--------------------------------------------
Consider the case of a checkbox. (i.e. `widgets/checkbox.dart`). The `Checkbox`
constructor looks like this:
```dart
ValueChanged onChanged;
bool checked;
Checkbox({ Object key, this.onChanged, this.checked }) : super(key: key);
```
What this means is that the `Checkbox` component *never* "owns" the state of
the checkbox. It's current state is handed into the `checked` parameter, and
when a click occurs, the checkbox invokes its `onChanged` callback with the
value it thinks it should be changed to -- but it never directly changes the
value itself. This is a bit odd at first look, but if you think about it: a
control isn't very useful unless it gets its value out to someone and if you
think about databinding, the same thing happens: databinding basically tells a
control to *treat some remote variable as its storage*. That's all that is
happening here. In this case, some owning component probably has a set of values
which describe a form.
Stateful vs. Stateless components
---------------------------------
All components have access to two kinds of state: (1) configuration data
(constructor arguments) and (2) private data (data they mutate themselves).
While react components have explicit property bags for these two kinds of state
(`this.prop` and `this.state`), Effen maps these ideas to the public and private
fields of the component. Constructor arguments should (by convention) be
reflected as public fields of the component and state should only be set on
private (with a leading underbar `_`) fields.
All (non-component) Effen nodes are stateless. Some components will be stateful.
This state will likely encapsulate transient states of the UI, such as scroll
position, animation state, uncommitted form values, etc...
A component can become stateful in two ways: (1) by passing `super(stateful:
true)` to its call to the superclass's constructor, or by calling
`setState(Function fn)`. The former is a way to have a component start its life
stateful, and the latter results in the component becoming statefull *as well
as* scheduling the component to re-build at the end of the current animation
frame.
What does it mean to be stateful? It means that the diffing mechanism retains
the specific *instance* of the component as long as the component which builds
it continues to require its presence. The component which constructed it may
have provided new configuration in form of different values for the constructor
parameters, but these values (public fields) will be copied (using reflection)
onto the retained instance whose privates fields are left unmodified.
Rendering
---------
At the end of each animation frame, all components (including the root `App`)
which have `setState` on themselves will be rebuilt and the resulting changes
will be minimally applied to the DOM. Note that components of lower "order"
(those near the root of the tree) will build first because their building may
require rebuilding of higher order (those near the leaves), thus avoiding the
possibility that a component which is dirty build more than once during a single
cycle.
Keys
----
In order to efficiently apply changes to the DOM and to ensure that stateful
components are correctly identified, Effen requires that `no two nodes (except
Text) or components of the same type may exist as children of another element
without being distinguished by unique keys`. [`Text` is excused from this rule].
In many cases, nodes don't require a key because there is only one type amongst
its siblings -- but if there is more one, you must assign each a key. This is
why most nodes will take `({ Object key })` as an optional constructor
parameter. In development mode (i.e. when sky is built `Debug`) Effen will throw
an error if you forget to do this.
Event Handling
--------------
Events logically fire through the Effen node tree. If want to handle an event as
it bubbles from the target to the root, create an `EventListenerNode`. `EventListenerNode`
has named (typed) parameters for a small set of events that we've hit so far, as
well as a 'custom' argument which is a `Map<String, sky.EventListener>`. If
you'd like to add a type argument for an event, just post a patch.
```dart
class MyComp extends Component {
MyComp({
Object key
}) : super(key: key);
void _handleTap(sky.GestureEvent e) {
// do stuff
}
void _customEventCallback(sky.Event e) {
// do other stuff
}
UINode build() {
new EventListenerNode(
new Container(
children: // ...
),
onGestureTap: _handleTap,
custom: {
'myCustomEvent': _customEventCallback
}
);
}
_handleScroll(sky.Event e) {
setState(() {
// update the scroll position
});
}
}
```
Styling
-------
Styling is the part of Effen which is least designed and is likely to change.
There are three ways to specify styles:
* `Style` objects which are interned and can be applied to WrapperNodes via the
``style` constructor parameter. Use `Style` objects for styles which are
`*not* animated.
* An `inlineStyle` string which can be applied to Elements via the
`inlineStyle` constructor parameter. Use `inlineStyle` for styles which
*are* animated.
If you need to apply a Style to a Component or UINode which you didn't construct
(i.e. one that was handed into your constructor), you can wrap it in a
`StyleNode` which also takes a `Style` constructor in it's `style` constructor
parameter.
Animation
---------
Animation is still an area of exploration. Have a look at
[AnimatedComponent](components/animated_component.dart) and
[Drawer](components/drawer.dart) for an example of this this currently works.
Performance
-----------
It is a design goal that it should be *possible* to arrange that all "build"
cycles which happen during animations can complete in less than one milliesecond
on a Nexus 5.
......@@ -4,7 +4,6 @@
import 'dart:math' as math;
import 'dart:sky' as sky;
import 'dart:typed_data';
import 'object.dart';
import '../painting/box_painter.dart';
import 'package:vector_math/vector_math.dart';
......
......@@ -4,7 +4,6 @@
import '../node.dart';
import '../scheduler.dart' as scheduler;
import 'dart:math' as math;
import 'dart:sky' as sky;
import 'dart:sky' show Point, Size, Rect, Color, Paint, Path;
export 'dart:sky' show Point, Size, Rect, Color, Paint, Path;
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:sky' as sky;
typedef void Callback(double timeStamp);
......
......@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../animation/animated_value.dart';
import '../fn2.dart';
import 'dart:async';
import '../animation/animated_value.dart';
import 'wrappers.dart';
typedef void SetterFunction(double value);
class _AnimationEntry {
......
......@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../fn2.dart';
import 'ink_well.dart';
import 'material.dart';
import 'wrappers.dart';
class Button extends Component {
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../fn2.dart';
import 'wrappers.dart';
abstract class ButtonBase extends Component {
......
......@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:sky' as sky;
import 'package:sky/framework/theme2/colors.dart' as colors;
import 'dart:sky' as sky;
import '../fn2.dart';
import '../rendering/box.dart';
import '../rendering/object.dart';
import 'button_base.dart';
import 'wrappers.dart';
typedef void ValueChanged(value);
......
......@@ -2,16 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:math' as math;
import 'dart:sky' as sky;
import 'package:vector_math/vector_math.dart';
import '../animation/animated_value.dart';
import '../animation/curves.dart';
import '../fn2.dart';
import '../theme2/colors.dart';
import '../theme2/shadows.dart';
import 'animated_component.dart';
import 'dart:math' as math;
import 'dart:sky' as sky;
import 'material.dart';
import 'package:vector_math/vector_math.dart';
import 'wrappers.dart';
// TODO(eseidel): Draw width should vary based on device size:
// http://www.google.com/design/spec/layout/structure.html#structure-side-nav
......
......@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../fn2.dart';
import '../theme2/colors.dart';
import '../theme2/view_configuration.dart';
import 'wrappers.dart';
class DrawerHeader extends Component {
......
......@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../animation/scroll_behavior.dart';
import '../fn2.dart';
import 'dart:async';
import 'dart:math' as math;
import 'package:vector_math/vector_math.dart';
import '../animation/scroll_behavior.dart';
import 'scrollable.dart';
import 'wrappers.dart';
abstract class FixedHeightScrollable extends Scrollable {
......
......@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../fn2.dart';
import '../rendering/box.dart';
import 'dart:sky' as sky;
import '../painting/shadows.dart';
import '../theme2/colors.dart';
import 'dart:sky' as sky;
import 'ink_well.dart';
import 'material.dart';
import 'wrappers.dart';
// TODO(eseidel): This needs to change based on device size?
// http://www.google.com/design/spec/layout/metrics-keylines.html#metrics-keylines-keylines-spacing
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../fn2.dart';
import 'wrappers.dart';
// TODO(eseidel): This should use package:.
const String kAssetBase = '/packages/sky/assets/material-design-icons';
......
......@@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../fn2.dart';
import '../rendering/box.dart';
import 'icon.dart';
import 'ui_node.dart';
import 'wrappers.dart';
class IconButton extends Component {
......
......@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:math' as math;
import 'dart:sky' as sky;
import '../animation/animated_value.dart';
import '../animation/curves.dart';
import '../fn2.dart';
import '../rendering/box.dart';
import '../rendering/flex.dart';
import '../rendering/object.dart';
import 'dart:async';
import 'dart:collection';
import 'dart:math' as math;
import 'dart:sky' as sky;
import 'ui_node.dart';
import 'wrappers.dart';
const int _kSplashInitialOpacity = 0x80;
const double _kSplashInitialDelay = 0.0; // we could delay initially in case the user scrolls
......
......@@ -2,8 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../fn2.dart';
import '../theme/shadows.dart';
import 'wrappers.dart';
class Material extends Component {
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../fn2.dart';
import 'wrappers.dart';
class MenuDivider extends Component {
MenuDivider({ Object key }) : super(key: key);
......
......@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../fn2.dart';
import 'button_base.dart';
import 'icon.dart';
import 'ink_well.dart';
import 'ui_node.dart';
import 'wrappers.dart';
const BoxDecoration _kHighlightDecoration = const BoxDecoration(
backgroundColor: const Color.fromARGB(102, 153, 153, 153)
......
......@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../fn2.dart';
import 'ui_node.dart';
import 'wrappers.dart';
class ModalOverlay extends Component {
......
......@@ -7,13 +7,13 @@ import 'dart:math' as math;
import 'dart:sky' as sky;
import '../animation/animated_value.dart';
import '../fn2.dart';
import '../painting/box_painter.dart';
import '../theme2/colors.dart';
import '../theme2/shadows.dart';
import 'animated_component.dart';
import 'material.dart';
import 'popup_menu_item.dart';
import 'wrappers.dart';
const double _kMenuOpenDuration = 300.0;
const double _kMenuCloseDuration = 200.0;
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../fn2.dart';
import 'wrappers.dart';
import 'ink_well.dart';
class PopupMenuItem extends Component {
......
......@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:sky' as sky;
import 'package:sky/framework/theme2/colors.dart' as colors;
import '../fn2.dart';
import '../rendering/object.dart';
import 'button_base.dart';
import 'ink_well.dart';
import 'dart:sky' as sky;
import 'wrappers.dart';
typedef void ValueChanged(value);
......
......@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../fn2.dart';
import '../rendering/box.dart';
import '../rendering/object.dart';
import '../theme2/view_configuration.dart';
import 'ui_node.dart';
enum ScaffoldSlots {
toolbar,
......
......@@ -2,13 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:math' as math;
import 'dart:sky' as sky;
import '../animation/generators.dart';
import '../animation/mechanics.dart';
import '../animation/scroll_behavior.dart';
import '../fn2.dart';
import '../theme/view_configuration.dart' as config;
import 'dart:math' as math;
import 'dart:sky' as sky;
import 'wrappers.dart';
const double _kMillisecondsPerSecond = 1000.0;
......
......@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../fn2.dart';
import '../rendering/flex.dart';
import '../theme2/view_configuration.dart';
import '../theme2/shadows.dart';
import '../theme2/view_configuration.dart';
import 'wrappers.dart';
class ToolBar extends Component {
......
import 'package:vector_math/vector_math.dart';
import '../rendering/block.dart';
import '../rendering/box.dart';
import '../rendering/flex.dart';
import '../rendering/object.dart';
import '../rendering/paragraph.dart';
import '../rendering/stack.dart';
import 'ui_node.dart';
export '../rendering/box.dart' show BoxConstraints, BoxDecoration, Border, BorderSide, EdgeDims;
export '../rendering/flex.dart' show FlexDirection;
export '../rendering/object.dart' show Point, Size, Rect, Color, Paint, Path;
export 'ui_node.dart' show UINode, Component, App, EventListenerNode, ParentDataNode;
// PAINTING NODES
class Opacity extends OneChildRenderObjectWrapper {
Opacity({ this.opacity, UINode child, Object key })
: super(child: child, key: key);
RenderOpacity get root { RenderOpacity result = super.root; return result; }
final double opacity;
RenderOpacity createNode() => new RenderOpacity(opacity: opacity);
void syncRenderObject(Opacity old) {
super.syncRenderObject(old);
root.opacity = opacity;
}
}
class DecoratedBox extends OneChildRenderObjectWrapper {
DecoratedBox({ this.decoration, UINode child, Object key })
: super(child: child, key: key);
RenderDecoratedBox get root { RenderDecoratedBox result = super.root; return result; }
final BoxDecoration decoration;
RenderDecoratedBox createNode() => new RenderDecoratedBox(decoration: decoration);
void syncRenderObject(DecoratedBox old) {
super.syncRenderObject(old);
root.decoration = decoration;
}
}
// TODO(jackson) need a mechanism for marking the RenderCustomPaint as needing paint
class CustomPaint extends OneChildRenderObjectWrapper {
CustomPaint({ this.callback, UINode child, Object key })
: super(child: child, key: key);
RenderCustomPaint get root { RenderCustomPaint result = super.root; return result; }
final CustomPaintCallback callback;
RenderCustomPaint createNode() => new RenderCustomPaint(callback: callback);
void syncRenderObject(CustomPaint old) {
super.syncRenderObject(old);
root.callback = callback;
}
void remove() {
root.callback = null;
super.remove();
}
}
class ClipRect extends OneChildRenderObjectWrapper {
ClipRect({ UINode child, Object key })
: super(child: child, key: key);
RenderClipRect get root { RenderClipRect result = super.root; return result; }
RenderClipRect createNode() => new RenderClipRect();
}
class ClipOval extends OneChildRenderObjectWrapper {
ClipOval({ UINode child, Object key })
: super(child: child, key: key);
RenderClipOval get root { RenderClipOval result = super.root; return result; }
RenderClipOval createNode() => new RenderClipOval();
}
// POSITIONING AND SIZING NODES
class Transform extends OneChildRenderObjectWrapper {
Transform({ this.transform, UINode child, Object key })
: super(child: child, key: key);
RenderTransform get root { RenderTransform result = super.root; return result; }
final Matrix4 transform;
RenderTransform createNode() => new RenderTransform(transform: transform);
void syncRenderObject(Transform old) {
super.syncRenderObject(old);
root.transform = transform;
}
}
class Padding extends OneChildRenderObjectWrapper {
Padding({ this.padding, UINode child, Object key })
: super(child: child, key: key);
RenderPadding get root { RenderPadding result = super.root; return result; }
final EdgeDims padding;
RenderPadding createNode() => new RenderPadding(padding: padding);
void syncRenderObject(Padding old) {
super.syncRenderObject(old);
root.padding = padding;
}
}
class SizedBox extends OneChildRenderObjectWrapper {
SizedBox({
double width: double.INFINITY,
double height: double.INFINITY,
UINode child,
Object key
}) : desiredSize = new Size(width, height), super(child: child, key: key);
RenderSizedBox get root { RenderSizedBox result = super.root; return result; }
final Size desiredSize;
RenderSizedBox createNode() => new RenderSizedBox(desiredSize: desiredSize);
void syncRenderObject(SizedBox old) {
super.syncRenderObject(old);
root.desiredSize = desiredSize;
}
}
class ConstrainedBox extends OneChildRenderObjectWrapper {
ConstrainedBox({ this.constraints, UINode child, Object key })
: super(child: child, key: key);
RenderConstrainedBox get root { RenderConstrainedBox result = super.root; return result; }
final BoxConstraints constraints;
RenderConstrainedBox createNode() => new RenderConstrainedBox(additionalConstraints: constraints);
void syncRenderObject(ConstrainedBox old) {
super.syncRenderObject(old);
root.additionalConstraints = constraints;
}
}
class ShrinkWrapWidth extends OneChildRenderObjectWrapper {
ShrinkWrapWidth({ UINode child, Object key }) : super(child: child, key: key);
RenderShrinkWrapWidth get root { RenderShrinkWrapWidth result = super.root; return result; }
RenderShrinkWrapWidth createNode() => new RenderShrinkWrapWidth();
}
class SizeObserver extends OneChildRenderObjectWrapper {
SizeObserver({ this.callback, UINode child, Object key })
: super(child: child, key: key);
RenderSizeObserver get root { RenderSizeObserver result = super.root; return result; }
final SizeChangedCallback callback;
RenderSizeObserver createNode() => new RenderSizeObserver(callback: callback);
void syncRenderObject(SizeObserver old) {
super.syncRenderObject(old);
root.callback = callback;
}
void remove() {
root.callback = null;
super.remove();
}
}
// CONVENIENCE CLASS TO COMBINE COMMON PAINTING, POSITIONING, AND SIZING NODES
class Container extends Component {
Container({
Object key,
this.child,
this.constraints,
this.decoration,
this.width,
this.height,
this.margin,
this.padding,
this.transform
}) : super(key: key);
final UINode child;
final BoxConstraints constraints;
final BoxDecoration decoration;
final EdgeDims margin;
final EdgeDims padding;
final Matrix4 transform;
final double width;
final double height;
UINode build() {
UINode current = child;
if (child == null && width == null && height == null)
current = new SizedBox();
if (padding != null)
current = new Padding(padding: padding, child: current);
if (decoration != null)
current = new DecoratedBox(decoration: decoration, child: current);
if (width != null || height != null)
current = new SizedBox(
width: width == null ? double.INFINITY : width,
height: height == null ? double.INFINITY : height,
child: current
);
if (constraints != null)
current = new ConstrainedBox(constraints: constraints, child: current);
if (margin != null)
current = new Padding(padding: margin, child: current);
if (transform != null)
current = new Transform(transform: transform, child: current);
return current;
}
}
// LAYOUT NODES
class Block extends MultiChildRenderObjectWrapper {
Block(List<UINode> children, { Object key })
: super(key: key, children: children);
RenderBlock get root { RenderBlock result = super.root; return result; }
RenderBlock createNode() => new RenderBlock();
}
class Stack extends MultiChildRenderObjectWrapper {
Stack(List<UINode> children, { Object key })
: super(key: key, children: children);
RenderStack get root { RenderStack result = super.root; return result; }
RenderStack createNode() => new RenderStack();
}
class StackPositionedChild extends ParentDataNode {
StackPositionedChild(UINode content, {
double top, double right, double bottom, double left
}) : super(content, new StackParentData()..top = top
..right = right
..bottom = bottom
..left = left);
}
class Flex extends MultiChildRenderObjectWrapper {
Flex(List<UINode> children, {
Object key,
this.direction: FlexDirection.horizontal,
this.justifyContent: FlexJustifyContent.flexStart,
this.alignItems: FlexAlignItems.center
}) : super(key: key, children: children);
RenderFlex get root { RenderFlex result = super.root; return result; }
RenderFlex createNode() => new RenderFlex(direction: this.direction);
final FlexDirection direction;
final FlexJustifyContent justifyContent;
final FlexAlignItems alignItems;
void syncRenderObject(UINode old) {
super.syncRenderObject(old);
root.direction = direction;
root.justifyContent = justifyContent;
root.alignItems = alignItems;
}
}
class FlexExpandingChild extends ParentDataNode {
FlexExpandingChild(UINode content, { int flex: 1, Object key })
: super(content, new FlexBoxParentData()..flex = flex, key: key);
}
class Paragraph extends RenderObjectWrapper {
Paragraph({ Object key, this.text }) : super(key: key);
RenderParagraph get root { RenderParagraph result = super.root; return result; }
RenderParagraph createNode() => new RenderParagraph(text: text);
final String text;
void syncRenderObject(UINode old) {
super.syncRenderObject(old);
root.text = text;
}
void insert(RenderObjectWrapper child, dynamic slot) {
assert(false);
// Paragraph does not support having children currently
}
}
class Text extends Component {
Text(this.data) : super(key: '*text*');
final String data;
bool get interchangeable => true;
UINode build() => new Paragraph(text: data);
}
class Image extends RenderObjectWrapper {
Image({
Object key,
this.src,
this.size
}) : super(key: key);
RenderImage get root { RenderImage result = super.root; return result; }
RenderImage createNode() => new RenderImage(this.src, this.size);
final String src;
final Size size;
void syncRenderObject(UINode old) {
super.syncRenderObject(old);
root.src = src;
root.requestedSize = size;
}
void insert(RenderObjectWrapper child, dynamic slot) {
assert(false);
// Image does not support having children currently
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册