From e8ead8bbbe5836a711401cbf59ec89807d99ecaf Mon Sep 17 00:00:00 2001 From: Hixie Date: Fri, 8 May 2015 13:06:47 -0700 Subject: [PATCH] [Effen] Port fn.dart from the legacy sky.Node backend to the RenderNode backend, which is currently just a sky.Node-backed shim, but will eventually be the core Sky interface for layout and painting. - the custom layout class in fn is removed by this patch; a new class will be added in a later CL - the version of layout.dart in this CL is a subset of what we're targetting on the long run with https://codereview.chromium.org/1093633002 - a couple of lines of dead code are removed in this CL also R=eseidel@chromium.org Review URL: https://codereview.chromium.org/1117143003 --- .../components/fixed_height_scrollable.dart | 13 +- framework/components/ink_splash.dart | 14 +- framework/components/ink_well.dart | 5 +- framework/components/popup_menu.dart | 4 +- framework/fn.dart | 291 ++++--------- framework/layout.dart | 406 ++++++++++++++++++ framework/node.dart | 60 +++ 7 files changed, 561 insertions(+), 232 deletions(-) create mode 100644 framework/layout.dart create mode 100644 framework/node.dart diff --git a/framework/components/fixed_height_scrollable.dart b/framework/components/fixed_height_scrollable.dart index 3f3e973d8..2838acbfa 100644 --- a/framework/components/fixed_height_scrollable.dart +++ b/framework/components/fixed_height_scrollable.dart @@ -6,7 +6,6 @@ import '../animation/scroll_behavior.dart'; import '../debug/tracing.dart'; import '../fn.dart'; import 'dart:math' as math; -import 'dart:sky' as sky; import 'dart:async'; import 'scrollable.dart'; @@ -52,14 +51,11 @@ abstract class FixedHeightScrollable extends Scrollable { var item = root.firstChild.firstChild; if (item == null) return; - sky.ClientRect scrollRect = root.getBoundingClientRect(); - sky.ClientRect itemRect = item.getBoundingClientRect(); - assert(scrollRect.height > 0); - assert(itemRect.height > 0); - setState(() { - _height = scrollRect.height; - _itemHeight = itemRect.height; + _height = root.height; + assert(_height > 0); + _itemHeight = item.height; + assert(_itemHeight > 0); scrollBehavior.containerHeight = _height; scrollBehavior.contentsHeight = _itemHeight * _itemCount; }); @@ -82,7 +78,6 @@ abstract class FixedHeightScrollable extends Scrollable { 'transform: translateY(${(-scrollOffset).toStringAsFixed(2)}px)'; } else { drawCount = (_height / _itemHeight).round() + 1; - double alignmentOffset = math.max(0.0, scrollOffset); double alignmentDelta = -scrollOffset % _itemHeight; if (alignmentDelta != 0.0) alignmentDelta -= _itemHeight; diff --git a/framework/components/ink_splash.dart b/framework/components/ink_splash.dart index 810c20c58..3bd18e1df 100644 --- a/framework/components/ink_splash.dart +++ b/framework/components/ink_splash.dart @@ -8,16 +8,16 @@ import '../fn.dart'; import '../theme/view_configuration.dart' as config; import 'dart:async'; import 'dart:math' as math; -import 'dart:sky' as sky; +import '../layout.dart'; const double _kSplashConfirmedDuration = 350.0; const double _kSplashUnconfirmedDuration = config.kDefaultLongPressTimeout; const double _kSplashAbortDuration = 100.0; const double _kSplashInitialDelay = 0.0; // we could delay initially in case the user scrolls -double _getSplashTargetSize(sky.ClientRect rect, double x, double y) { - return 2.0 * math.max(math.max(x - rect.left, rect.right - x), - math.max(y - rect.top, rect.bottom - y)); +double _getSplashTargetSize(Rect rect, double x, double y) { + return 2.0 * math.max(math.max(x - rect.x, rect.x + rect.width - x), + math.max(y - rect.y, rect.y + rect.height - y)); } class SplashController { @@ -56,10 +56,10 @@ class SplashController { _size.stop(); } - SplashController(sky.ClientRect rect, double x, double y, + SplashController(Rect rect, double x, double y, { this.pointer, Function onDone }) - : _offsetX = x - rect.left, - _offsetY = y - rect.top, + : _offsetX = x - rect.x, + _offsetY = y - rect.y, _targetSize = _getSplashTargetSize(rect, x, y) { _styleStream = _size.onValueChanged.map((p) { diff --git a/framework/components/ink_well.dart b/framework/components/ink_well.dart index 096fa0079..cc7181be3 100644 --- a/framework/components/ink_well.dart +++ b/framework/components/ink_well.dart @@ -45,14 +45,13 @@ class InkWell extends Component implements ScrollClient { ); } - sky.ClientRect _getBoundingRect() => (getRoot() as sky.Element).getBoundingClientRect(); - void _startSplash(sky.GestureEvent event) { setState(() { if (_splashes == null) _splashes = new LinkedHashSet(); var splash; - splash = new SplashController(_getBoundingRect(), event.x, event.y, + var root = getRoot(); + splash = new SplashController(root.rect, event.x, event.y, pointer: event.primaryPointer, onDone: () { _splashDone(splash); }); _splashes.add(splash); diff --git a/framework/components/popup_menu.dart b/framework/components/popup_menu.dart index 4375eefed..90e099496 100644 --- a/framework/components/popup_menu.dart +++ b/framework/components/popup_menu.dart @@ -92,8 +92,8 @@ class PopupMenu extends AnimatedComponent { void _measureSize() { setState(() { var root = getRoot(); - _width = root.clientWidth; - _height = root.clientHeight; + _width = root.width.round(); + _height = root.height.round(); }); } diff --git a/framework/fn.dart b/framework/fn.dart index 850ffd259..78672cef0 100644 --- a/framework/fn.dart +++ b/framework/fn.dart @@ -8,51 +8,15 @@ import 'dart:async'; import 'dart:collection'; import 'dart:sky' as sky; import 'reflect.dart' as reflect; +import 'layout.dart'; + +export 'layout.dart' show Style; final sky.Tracing _tracing = sky.window.tracing; final bool _shouldLogRenderDuration = false; final bool _shouldTrace = false; -class Style { - final String _className; - static final Map _cache = new HashMap(); - - static int _nextStyleId = 1; - - static String _getNextClassName() { return "style${_nextStyleId++}"; } - - Style extend(Style other) { - var className = "$_className ${other._className}"; - - return _cache.putIfAbsent(className, () { - return new Style._internal(className); - }); - } - - factory Style(String styles) { - return _cache.putIfAbsent(styles, () { - var className = _getNextClassName(); - sky.Element styleNode = sky.document.createElement('style'); - styleNode.setChild(new sky.Text(".$className { $styles }")); - sky.document.appendChild(styleNode); - return new Style._internal(className); - }); - } - - Style._internal(this._className); -} - -void _parentInsertBefore(sky.ParentNode parent, - sky.Node node, - sky.Node ref) { - if (ref != null) { - ref.insertBefore([node]); - } else { - parent.appendChild(node); - } -} - enum _SyncOperation { IDENTICAL, INSERTION, STATEFUL, STATELESS, REMOVAL } /* @@ -63,7 +27,7 @@ abstract class UINode { String _key; UINode _parent; UINode get parent => _parent; - sky.Node _root; + RenderCSS _root; bool _defunct = false; UINode({ Object key }) { @@ -74,7 +38,7 @@ abstract class UINode { // if the |old| node has become stateful and should be retained. bool _willSync(UINode old) => false; - void _sync(UINode old, sky.ParentNode host, sky.Node insertBefore); + void _sync(UINode old, RenderCSSContainer host, RenderCSS insertBefore); void _remove() { _defunct = true; @@ -118,8 +82,8 @@ abstract class UINode { } // Returns the child which should be retained as the child of this node. - UINode _syncChild(UINode node, UINode oldNode, sky.ParentNode host, - sky.Node insertBefore) { + UINode _syncChild(UINode node, UINode oldNode, RenderCSSContainer host, + RenderCSS insertBefore) { assert(oldNode == null || node._key == oldNode._key); @@ -139,7 +103,7 @@ abstract class UINode { _traceSync(_SyncOperation.STATEFUL, node._key); oldNode._sync(node, host, insertBefore); node._defunct = true; - assert(oldNode._root is sky.Node); + assert(oldNode._root is RenderCSS); return oldNode; } @@ -154,7 +118,7 @@ abstract class UINode { if (oldNode != null) oldNode._defunct = true; - assert(node._root is sky.Node); + assert(node._root is RenderCSS); return node; } } @@ -164,14 +128,16 @@ abstract class ContentNode extends UINode { ContentNode(UINode content) : this.content = content, super(key: content._key); - void _sync(UINode old, sky.ParentNode host, sky.Node insertBefore) { + void _sync(UINode old, RenderCSSContainer host, RenderCSS insertBefore) { UINode oldContent = old == null ? null : (old as ContentNode).content; content = _syncChild(content, oldContent, host, insertBefore); + assert(content._root != null); _root = content._root; } void _remove() { - _removeChild(content); + if (content != null) + _removeChild(content); super._remove(); } } @@ -183,31 +149,33 @@ class StyleNode extends ContentNode { } /* - * SkyNodeWrappers correspond to a desired state of a sky.Node. They are fully + * SkyNodeWrappers correspond to a desired state of a RenderCSS. They are fully * immutable, with one exception: A UINode which is a Component which lives within * an SkyElementWrapper's children list, may be replaced with the "old" instance if it * has become stateful. */ abstract class SkyNodeWrapper extends UINode { - static final Map _nodeMap = - new HashMap(); + static final Map _nodeMap = + new HashMap(); - static SkyNodeWrapper _getMounted(sky.Node node) => _nodeMap[node]; + static SkyNodeWrapper _getMounted(RenderCSS node) => _nodeMap[node]; SkyNodeWrapper({ Object key }) : super(key: key); SkyNodeWrapper get _emptyNode; - sky.Node _createNode(); + RenderCSS _createNode(); - void _sync(UINode old, sky.ParentNode host, sky.Node insertBefore) { + void _sync(UINode old, RenderCSSContainer host, RenderCSS insertBefore) { if (old == null) { _root = _createNode(); - _parentInsertBefore(host, _root, insertBefore); + assert(_root != null); + host.add(_root, before: insertBefore); old = _emptyNode; } else { _root = old._root; + assert(_root != null); } _nodeMap[_root] = this; @@ -216,9 +184,14 @@ abstract class SkyNodeWrapper extends UINode { void _syncNode(SkyNodeWrapper old); + void _removeChild(UINode node) { + assert(_root is RenderCSSContainer); + _root.remove(node._root); + super._removeChild(node); + } + void _remove() { assert(_root != null); - _root.remove(); _nodeMap.remove(_root); super._remove(); } @@ -314,12 +287,12 @@ class EventListenerNode extends ContentNode { } static void _dispatchEvent(sky.Event e) { - UINode target = SkyNodeWrapper._getMounted(e.target); + UINode target = SkyNodeWrapper._getMounted(bridgeEventTargetToRenderNode(e.target)); // TODO(rafaelw): StopPropagation? while (target != null) { if (target is EventListenerNode) { - (target as EventListenerNode)._handleEvent(e); + target._handleEvent(e); } target = target._parent; @@ -332,7 +305,7 @@ class EventListenerNode extends ContentNode { } } - void _sync(UINode old, sky.ParentNode host, sky.Node insertBefore) { + void _sync(UINode old, RenderCSSContainer host, RenderCSS insertBefore) { for (var type in listeners.keys) { _ensureDocumentListener(type); } @@ -354,19 +327,15 @@ class Text extends SkyNodeWrapper { SkyNodeWrapper get _emptyNode => _emptyText; - static final Style _displayParagraph = new Style('display:paragraph'); - - sky.Node _createNode() { - return sky.document.createElement('div') - ..setChild(new sky.Text(this.data)) - ..setAttribute('class', _displayParagraph._className); + RenderCSSText _root; + RenderCSS _createNode() { + return new RenderCSSText(this, this.data); } void _syncNode(SkyNodeWrapper old) { if (old == _emptyText) return; // we set inside _createNode(); - - (_root.firstChild as sky.Text).data = data; + _root.data = data; } } @@ -374,16 +343,10 @@ final List _emptyList = new List(); abstract class SkyElementWrapper extends SkyNodeWrapper { - String get _tagName; - - sky.Node _createNode() => sky.document.createElement(_tagName); - final List children; final Style style; final String inlineStyle; - String _class; - SkyElementWrapper({ Object key, List children, @@ -396,17 +359,18 @@ abstract class SkyElementWrapper extends SkyNodeWrapper { } void _remove() { - super._remove(); - if (children != null) { - for (var child in children) { - _removeChild(child); - } + assert(children != null); + for (var child in children) { + assert(child != null); + _removeChild(child); } + super._remove(); } bool _debugHasDuplicateIds() { var idSet = new HashSet(); for (var child in children) { + assert(child != null); if (child is Text) { continue; // Text nodes all have the same key and are never reordered. } @@ -419,42 +383,28 @@ abstract class SkyElementWrapper extends SkyNodeWrapper { return false; } - void _ensureClass() { - if (_class == null) { - List