提交 31100599 编写于 作者: H Hixie

Cleanup of SkyBinding, and resultant yak shaving.

Some files are moved by this:
  Copy framework/node.dart into types/ - preparing for framework/'s decomissioning.
  Move app/scheduler.dart into sky/scheduler.dart - "app" doesn't really make sense.

As part of the SkyBinding cleanup, I made the hit-testing less
RenderBox-specific, by having the HitTestEntry.target member be a
HitTestTarget, which is an interface with the handleEvent() function,
which is then implemented by RenderBox. In theory, someone could now
extend hit testing from the RenderBox world into their own tree of
nodes, and take part in all the same dispatch logic automatically.

This involved moving all the hit testing type definitions into a new
sky/hittest.dart file.

Renamed SkyBinding._app to SkyBinding._instance for clarity.

Moved code around in SkyBinding so that related things are together.

Made WidgetSkyBinding use the existing SkyBinding.instance singleton
logic rather than having its own copy.

I also added some stub README.md files that describe dependencies.

R=abarth@chromium.org

Review URL: https://codereview.chromium.org/1187393002.
上级 ab23715a
library sprites;
import 'dart:sky';
import 'dart:math' as Math;
import 'package:vector_math/vector_math.dart';
import 'dart:sky';
import 'dart:typed_data';
import 'package:sky/base/scheduler.dart' as scheduler;
import 'package:sky/mojo/net/image_cache.dart' as image_cache;
import 'package:sky/rendering/box.dart';
import 'package:sky/rendering/object.dart';
import 'package:sky/app/scheduler.dart' as scheduler;
import 'package:sky/framework/net/image_cache.dart' as image_cache;
import 'package:vector_math/vector_math.dart';
part 'sprite_box.dart';
part 'node.dart';
part 'node_with_size.dart';
part 'sprite.dart';
part 'image_map.dart';
\ No newline at end of file
part 'image_map.dart';
......@@ -5,7 +5,7 @@
import 'dart:sky' as sky;
import 'dart:math' as math;
import 'package:sky/app/scheduler.dart';
import 'package:sky/base/scheduler.dart';
import 'package:sky/rendering/box.dart';
import 'package:sky/rendering/flex.dart';
import 'package:sky/rendering/sky_binding.dart';
......
......@@ -2,6 +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/rendering/sky_binding.dart';
import 'package:sky/widgets/basic.dart';
import 'package:sky/widgets/navigator.dart';
import 'package:sky/widgets/widget.dart';
......@@ -35,8 +36,8 @@ class StocksApp extends App {
void main() {
print("starting stocks app!");
runApp(new StocksApp());
WidgetSkyBinding.skyBinding.onFrame = () {
SkyBinding.instance.onFrame = () {
// uncomment this for debugging:
// WidgetSkyBinding.skyBinding.debugDumpRenderTree();
// SkyBinding.instance.debugDumpRenderTree();
};
}
......@@ -6,6 +6,7 @@ import 'dart:math' as math;
import 'package:sky/rendering/box.dart';
import 'package:sky/rendering/flex.dart';
import 'package:sky/rendering/sky_binding.dart';
import 'package:sky/theme2/colors.dart';
import 'package:sky/theme2/edges.dart';
import 'package:sky/theme2/typography.dart';
......@@ -136,8 +137,8 @@ class SectorApp extends App {
void main() {
runApp(new SectorApp());
WidgetSkyBinding.skyBinding.onFrame = () {
SkyBinding.instance.onFrame = () {
// uncomment this for debugging:
// WidgetSkyBinding.skyBinding.debugDumpRenderTree();
// SkyBinding.instance.debugDumpRenderTree();
};
}
......@@ -4,9 +4,10 @@
import 'dart:sky' as sky;
import 'package:sky/app/scheduler.dart';
import 'package:sky/base/scheduler.dart';
import 'package:sky/rendering/box.dart';
import 'package:sky/rendering/flex.dart';
import 'package:sky/rendering/sky_binding.dart';
import 'package:sky/widgets/basic.dart';
import 'package:sky/widgets/raised_button.dart';
import 'package:sky/widgets/widget.dart';
......@@ -94,6 +95,6 @@ void main() {
transformBox = new RenderTransform(child: flexRoot, transform: new Matrix4.identity());
RenderPadding root = new RenderPadding(padding: new EdgeDims.all(20.0), child: transformBox);
WidgetSkyBinding.skyBinding.root = root;
SkyBinding.instance.root = root;
addPersistentFrameCallback(rotate);
}
......@@ -15,10 +15,12 @@ dart_pkg("sdk") {
"lib/animation/generators.dart",
"lib/animation/mechanics.dart",
"lib/animation/scroll_behavior.dart",
"lib/app/scheduler.dart",
"lib/assets/.gitignore",
"lib/assets/material-design-icons.sha1",
"lib/debug/utils.dart",
"lib/base/debug.dart",
"lib/base/hit_test.dart",
"lib/base/node.dart",
"lib/base/scheduler.dart",
"lib/download_material_design_icons",
"lib/editing2/editable_string.dart",
"lib/editing2/editable_text.dart",
......
This directory contains animation-related libraries that only depend
on core Dart libraries and ../sky/*.
on core Dart libraries and ../base/*.
......@@ -5,7 +5,7 @@
import 'dart:async';
import 'dart:math' as math;
import '../app/scheduler.dart' as scheduler;
import '../base/scheduler.dart' as scheduler;
import 'curves.dart';
import 'mechanics.dart';
......
Libraries in this directory depend on nothing but Dart's core
libraries and the ```dart:sky``` library exposed by Sky's platform.
// 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.
final bool inDebugBuild = _initInDebugBuild();
......
// 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.
import 'dart:sky' as sky;
abstract class HitTestTarget {
void handleEvent(sky.Event event, HitTestEntry entry);
}
class HitTestEntry {
const HitTestEntry(this.target);
final HitTestTarget target;
}
class HitTestResult {
final List<HitTestEntry> path = new List<HitTestEntry>();
void add(HitTestEntry data) {
path.add(data);
}
}
// 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.
class AbstractNode {
// AbstractNode represents a node in a tree.
// The AbstractNode protocol is as follows:
// - When a subclass is changing the parent of a child, it should
// call either parent.adoptChild(child) or parent.dropChild(child)
// as appropriate. Subclasses should expose an API for
// manipulating the tree if you want to (e.g. a setter for a
// 'child' property, or an 'add()' method to manipulate a list).
// - You can see the current parent by querying 'parent'.
// - You can see the current attachment state by querying
// 'attached'. The root of any tree that is to be considered
// attached should be manually attached by calling 'attach()'.
// Other than that, don't call 'attach()' or 'detach()'. This is
// all managed automatically assuming you call the 'adoptChild()'
// and 'dropChild()' methods appropriately.
// - Subclasses that have children must override 'attach()' and
// 'detach()' as described below.
// - Nodes always have a 'depth' greater than their ancestors'.
// There's no guarantee regarding depth between siblings. The
// depth of a node is used to ensure that nodes are processed in
// depth order. The 'depth' of a child can be more than one
// greater than the 'depth' of the parent, because the 'depth'
// values are never decreased: all that matters is that it's
// greater than the parent. Consider a tree with a root node A, a
// child B, and a grandchild C. Initially, A will have 'depth' 0,
// B 'depth' 1, and C 'depth' 2. If C is moved to be a child of A,
// sibling of B, then the numbers won't change. C's 'depth' will
// still be 2. This is all managed automatically assuming you call
// 'adoptChild()' and 'dropChild()' appropriately.
int _depth = 0;
int get depth => _depth;
void redepthChild(AbstractNode child) { // internal, do not call
assert(child._attached == _attached);
if (child._depth <= _depth) {
child._depth = _depth + 1;
child.redepthChildren();
}
}
void redepthChildren() { // internal, do not call
// override this in subclasses with child nodes
// simply call redepthChild(child) for each child
}
bool _attached = false;
bool get attached => _attached;
void attach() {
// override this in subclasses with child nodes
// simply call attach() for each child then call your superclass
_attached = true;
attachChildren();
}
attachChildren() { } // workaround for lack of inter-class mixins in Dart
void detach() {
// override this in subclasses with child nodes
// simply call detach() for each child then call your superclass
_attached = false;
detachChildren();
}
detachChildren() { } // workaround for lack of inter-class mixins in Dart
AbstractNode _parent;
AbstractNode get parent => _parent;
void adoptChild(AbstractNode child) { // only for use by subclasses
assert(child != null);
assert(child._parent == null);
child._parent = this;
if (attached)
child.attach();
redepthChild(child);
}
void dropChild(AbstractNode child) { // only for use by subclasses
assert(child != null);
assert(child._parent == this);
assert(child.attached == attached);
child._parent = null;
if (attached)
child.detach();
}
}
......@@ -2,8 +2,6 @@
// 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 '../widgets/basic.dart';
import 'editable_string.dart';
import 'editable_text.dart';
......
......@@ -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 '../../app/scheduler.dart' as scheduler;
import '../../base/scheduler.dart' as scheduler;
import 'curves.dart';
import 'dart:async';
import 'dart:math' as math;
......
......@@ -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:mojo/application.dart";
import "dart:sky.internals" as internals;
import "package:mojo/application.dart";
import "package:mojo/bindings.dart" as bindings;
import "package:mojo/core.dart" as core;
import "package:mojom/mojo/service_provider.mojom.dart";
......
......@@ -3,11 +3,13 @@
// found in the LICENSE file.
import "dart:sky.internals" as internals;
import "embedder.dart";
import "package:mojo/application.dart";
import 'package:mojo/core.dart' as core;
import "package:mojom/mojo/service_provider.mojom.dart";
import "embedder.dart";
ApplicationConnection _initConnection() {
int rawHandle = internals.takeServicesProvidedByEmbedder();
core.MojoHandle proxyHandle = new core.MojoHandle(rawHandle);
......
This directory introduces a layout and painting system built on the
Sky APIs. It depends on Dart primitives, ../base/*, ../mojo/*, and
../animation/*.
......@@ -7,7 +7,7 @@ import 'dart:sky' as sky;
import 'package:vector_math/vector_math.dart';
import '../debug/utils.dart';
import '../base/debug.dart';
import '../mojo/net/image_cache.dart' as image_cache;
import '../painting/box_painter.dart';
import 'object.dart';
......@@ -192,9 +192,7 @@ class BoxConstraints {
}
class BoxHitTestEntry extends HitTestEntry {
const BoxHitTestEntry(RenderBox target, this.localPosition)
: super(target);
const BoxHitTestEntry(HitTestTarget target, this.localPosition) : super(target);
final Point localPosition;
}
......
......@@ -6,10 +6,13 @@ import 'dart:math' as math;
import 'dart:sky' as sky;
import 'dart:sky' show Point, Size, Rect, Color, Paint, Path;
import '../app/scheduler.dart' as scheduler;
import '../framework/node.dart';
import '../base/hit_test.dart';
import '../base/node.dart';
import '../base/scheduler.dart' as scheduler;
export 'dart:sky' show Point, Size, Rect, Color, Paint, Path;
export '../base/hit_test.dart' show HitTestTarget, HitTestEntry, HitTestResult;
class ParentData {
void detach() {
......@@ -34,7 +37,7 @@ class RenderObjectDisplayList extends sky.PictureRecorder {
}
}
abstract class RenderObject extends AbstractNode {
abstract class RenderObject extends AbstractNode implements HitTestTarget {
// LAYOUT
......@@ -260,20 +263,6 @@ abstract class RenderObject extends AbstractNode {
}
class HitTestEntry {
const HitTestEntry(this.target);
final RenderObject target;
}
class HitTestResult {
final List<HitTestEntry> path = new List<HitTestEntry>();
void add(HitTestEntry data) {
path.add(data);
}
}
double clamp({ double min: 0.0, double value: 0.0, double max: double.INFINITY }) {
assert(min != null);
assert(value != null);
......
......@@ -4,15 +4,15 @@
import 'dart:sky' as sky;
import '../app/scheduler.dart' as scheduler;
import '../base/scheduler.dart' as scheduler;
import '../base/hit_test.dart';
import 'box.dart';
import 'object.dart';
class PointerState {
PointerState({ this.result, this.lastPosition });
HitTestResult result;
Point lastPosition;
PointerState({ this.result, this.lastPosition });
}
typedef void EventListener(sky.Event event);
......@@ -20,43 +20,41 @@ typedef void EventListener(sky.Event event);
class SkyBinding {
SkyBinding({ RenderBox root: null, RenderView renderViewOverride }) {
assert(_app == null);
_app = this;
assert(_instance == null);
_instance = this;
sky.view.setEventCallback(_handleEvent);
sky.view.setMetricsChangedCallback(_handleMetricsChanged);
scheduler.init();
scheduler.addPersistentFrameCallback(_beginFrame);
if (renderViewOverride == null) {
_renderView = new RenderView(child: root);
_renderView.attach();
_renderView.rootConstraints = _viewConstraints;
_renderView.rootConstraints = _createConstraints();
_renderView.scheduleInitialLayout();
} else {
_renderView = renderViewOverride;
}
assert(_renderView != null);
scheduler.addPersistentFrameCallback(_beginFrame);
assert(_app == this);
assert(_instance == this);
}
static SkyBinding _app; // used to enforce that we're a singleton
static SkyBinding _instance; // used to enforce that we're a singleton
static SkyBinding get instance => _instance;
RenderView _renderView;
RenderView get renderView => _renderView;
ViewConstraints get _viewConstraints =>
new ViewConstraints(width: sky.view.width, height: sky.view.height);
Map<int, PointerState> _stateForPointer = new Map<int, PointerState>();
ViewConstraints _createConstraints() {
return new ViewConstraints(width: sky.view.width, height: sky.view.height);
}
void _handleMetricsChanged() {
_renderView.rootConstraints = _createConstraints();
}
Function onFrame;
final List<EventListener> _eventListeners = new List<EventListener>();
void addEventListener(EventListener e) => _eventListeners.add(e);
bool removeEventListener(EventListener e) => _eventListeners.remove(e);
RenderBox get root => _renderView.child;
void set root(RenderBox value) {
_renderView.child = value;
......@@ -68,6 +66,10 @@ class SkyBinding {
_renderView.paintFrame();
}
final List<EventListener> _eventListeners = new List<EventListener>();
void addEventListener(EventListener e) => _eventListeners.add(e);
bool removeEventListener(EventListener e) => _eventListeners.remove(e);
void _handleEvent(sky.Event event) {
if (event is sky.PointerEvent) {
_handlePointerEvent(event);
......@@ -76,15 +78,12 @@ class SkyBinding {
_renderView.hitTest(result, position: new Point(event.x, event.y));
dispatchEvent(event, result);
} else {
for (EventListener e in _eventListeners) {
for (EventListener e in _eventListeners)
e(event);
}
}
}
void _handleMetricsChanged() {
_renderView.rootConstraints = _viewConstraints;
}
Map<int, PointerState> _stateForPointer = new Map<int, PointerState>();
PointerState _createStateForPointer(sky.PointerEvent event, Point position) {
HitTestResult result = new HitTestResult();
......
......@@ -436,7 +436,9 @@ class WidgetToRenderBoxAdapter extends LeafRenderObjectWrapper {
}
void remove() {
parent.detachChildRoot(this);
RenderObjectWrapper ancestor = findAncestor(RenderObjectWrapper);
assert(ancestor is RenderObjectWrapper);
ancestor.detachChildRoot(this);
super.remove();
}
......
......@@ -55,8 +55,8 @@ class MenuItem extends ButtonBase {
new Flexible(
flex: 1,
child: new Padding(
padding: const EdgeDims.symmetric(horizontal: 16.0)
child: new Flex(children, direction: FlexDirection.horizontal),
padding: const EdgeDims.symmetric(horizontal: 16.0),
child: new Flex(children, direction: FlexDirection.horizontal)
)
)
])
......
......@@ -7,6 +7,7 @@ import 'dart:collection';
import 'dart:mirrors';
import 'dart:sky' as sky;
import '../base/hit_test.dart';
import '../rendering/box.dart';
import '../rendering/object.dart';
import '../rendering/sky_binding.dart';
......@@ -505,6 +506,7 @@ abstract class RenderObjectWrapper extends Widget {
if (_ancestor is RenderObjectWrapper)
_ancestor.insertChildRoot(this, slot);
} else {
assert(old is RenderObjectWrapper);
_root = old.root;
_ancestor = old._ancestor;
}
......@@ -784,19 +786,16 @@ abstract class MultiChildRenderObjectWrapper extends RenderObjectWrapper {
class WidgetSkyBinding extends SkyBinding {
WidgetSkyBinding({ RenderView renderViewOverride: null })
: super(renderViewOverride: renderViewOverride) {
assert(_skyBinding == null);
}
: super(renderViewOverride: renderViewOverride);
static WidgetSkyBinding _skyBinding;
static SkyBinding get skyBinding => _skyBinding;
static void initWidgetSkyBinding({ RenderView renderViewOverride: null }) {
if (_skyBinding == null)
_skyBinding = new WidgetSkyBinding(renderViewOverride: renderViewOverride);
if (SkyBinding.instance == null)
new WidgetSkyBinding(renderViewOverride: renderViewOverride);
assert(SkyBinding.instance is WidgetSkyBinding);
}
void dispatchEvent(sky.Event event, HitTestResult result) {
assert(_skyBinding == this);
assert(SkyBinding.instance == this);
super.dispatchEvent(event, result);
for (HitTestEntry entry in result.path.reversed) {
Widget target = RenderObjectWrapper._getMounted(entry.target);
......@@ -841,16 +840,15 @@ abstract class AbstractWidgetRoot extends Component {
class RenderViewWrapper extends OneChildRenderObjectWrapper {
RenderViewWrapper({ String key, Widget child }) : super(key: key, child: child);
RenderView get root => super.root;
RenderView createNode() => WidgetSkyBinding._skyBinding.renderView;
RenderView createNode() => SkyBinding.instance.renderView;
}
class AppContainer extends AbstractWidgetRoot {
AppContainer(this.app);
AppContainer(this.app) {
assert(SkyBinding.instance is WidgetSkyBinding);
}
final App app;
Widget build() => new RenderViewWrapper(child: app);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册