Commit 91a72d9f authored by Ian Hickson's avatar Ian Hickson

Merge pull request #879 from Hixie/RenderBlockViewport

Abstract out syncChildren().
parents e51525cf e6f34f86
......@@ -272,7 +272,8 @@ class RenderBlockViewport extends RenderBlockBase {
result = intrinsicCallback(constraints);
if (result == null)
result = constrainer(0.0);
assert(constrainer(result) == result);
else
result = constrainer(result);
} finally {
_inCallback = false;
}
......
......@@ -979,6 +979,7 @@ abstract class RenderObjectWrapper extends Widget {
}
void syncRenderObject(RenderObjectWrapper old) {
assert(old == null || old.renderObject == renderObject);
ParentData parentData = null;
Widget ancestor = parent;
while (ancestor != null && ancestor is! RenderObjectWrapper) {
......@@ -998,134 +999,8 @@ abstract class RenderObjectWrapper extends Widget {
}
}
void dependenciesChanged() {
// called by Inherited.sync()
syncRenderObject(this);
}
void remove() {
assert(renderObject != null);
_nodeMap.remove(renderObject);
super.remove();
}
void detachRenderObject() {
assert(_ancestor != null);
assert(renderObject != null);
_ancestor.detachChildRenderObject(this);
}
}
abstract class LeafRenderObjectWrapper extends RenderObjectWrapper {
LeafRenderObjectWrapper({ Key key }) : super(key: key);
void insertChildRenderObject(RenderObjectWrapper child, dynamic slot) {
assert(false);
}
void detachChildRenderObject(RenderObjectWrapper child) {
assert(false);
}
}
abstract class OneChildRenderObjectWrapper extends RenderObjectWrapper {
OneChildRenderObjectWrapper({ Key key, Widget child })
: _child = child, super(key: key);
Widget _child;
Widget get child => _child;
void walkChildren(WidgetTreeWalker walker) {
if (child != null)
walker(child);
}
void syncRenderObject(RenderObjectWrapper old) {
super.syncRenderObject(old);
Widget oldChild = old == null ? null : (old as OneChildRenderObjectWrapper).child;
Widget newChild = child;
_child = syncChild(newChild, oldChild, null);
assert((newChild == null && child == null) || (newChild != null && child.parent == this));
assert(oldChild == null || child == oldChild || oldChild.parent == null);
}
void insertChildRenderObject(RenderObjectWrapper child, dynamic slot) {
final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
assert(renderObject is RenderObjectWithChildMixin);
assert(slot == null);
renderObject.child = child.renderObject;
assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
}
void detachChildRenderObject(RenderObjectWrapper child) {
final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
assert(renderObject is RenderObjectWithChildMixin);
assert(renderObject.child == child.renderObject);
renderObject.child = null;
assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
}
}
abstract class MultiChildRenderObjectWrapper extends RenderObjectWrapper {
// In MultiChildRenderObjectWrapper subclasses, slots are the Widget
// nodes whose RenderObjects are to be used as the "insert before"
// sibling in ContainerRenderObjectMixin.add() calls
MultiChildRenderObjectWrapper({ Key key, List<Widget> children })
: this.children = children == null ? const [] : children,
super(key: key) {
assert(!_debugHasDuplicateIds());
}
final List<Widget> children;
void walkChildren(WidgetTreeWalker walker) {
for (Widget child in children)
walker(child);
}
void insertChildRenderObject(RenderObjectWrapper child, Widget slot) {
final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
RenderObject nextSibling = slot != null ? slot.renderObject : null;
assert(nextSibling == null || nextSibling is RenderObject);
assert(renderObject is ContainerRenderObjectMixin);
renderObject.add(child.renderObject, before: nextSibling);
assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
}
void detachChildRenderObject(RenderObjectWrapper child) {
final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
assert(renderObject is ContainerRenderObjectMixin);
assert(child.renderObject.parent == renderObject);
renderObject.remove(child.renderObject);
assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
}
bool _debugHasDuplicateIds() {
var idSet = new HashSet<Key>();
for (var child in children) {
assert(child != null);
if (child.key == null)
continue; // when these nodes are reordered, we just reassign the data
if (!idSet.add(child.key)) {
throw '''If multiple keyed nodes exist as children of another node, they must have unique keys. $this has duplicate child key "${child.key}".''';
}
}
return false;
}
void syncRenderObject(MultiChildRenderObjectWrapper old) {
super.syncRenderObject(old);
final ContainerRenderObjectMixin renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
assert(renderObject is ContainerRenderObjectMixin);
assert(old == null || old.renderObject == renderObject);
// for use by subclasses that manage their children using lists
void syncChildren(List<Widget> newChildren, List<Widget> oldChildren) {
// This attempts to diff the new child list (this.children) with
// the old child list (old.children), and update our renderObject
......@@ -1158,8 +1033,9 @@ abstract class MultiChildRenderObjectWrapper extends RenderObjectWrapper {
// 6. Sync null with any items in the list of keys that are still
// mounted.
final List<Widget> newChildren = children;
final List<Widget> oldChildren = old == null ? const <Widget>[] : old.children;
final ContainerRenderObjectMixin renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
assert(renderObject is ContainerRenderObjectMixin);
int childrenTop = 0;
int newChildrenBottom = newChildren.length-1;
int oldChildrenBottom = oldChildren.length-1;
......@@ -1260,6 +1136,133 @@ abstract class MultiChildRenderObjectWrapper extends RenderObjectWrapper {
assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
}
void dependenciesChanged() {
// called by Inherited.sync()
syncRenderObject(this);
}
void remove() {
assert(renderObject != null);
_nodeMap.remove(renderObject);
super.remove();
}
void detachRenderObject() {
assert(_ancestor != null);
assert(renderObject != null);
_ancestor.detachChildRenderObject(this);
}
}
abstract class LeafRenderObjectWrapper extends RenderObjectWrapper {
LeafRenderObjectWrapper({ Key key }) : super(key: key);
void insertChildRenderObject(RenderObjectWrapper child, dynamic slot) {
assert(false);
}
void detachChildRenderObject(RenderObjectWrapper child) {
assert(false);
}
}
abstract class OneChildRenderObjectWrapper extends RenderObjectWrapper {
OneChildRenderObjectWrapper({ Key key, Widget child })
: _child = child, super(key: key);
Widget _child;
Widget get child => _child;
void walkChildren(WidgetTreeWalker walker) {
if (child != null)
walker(child);
}
void syncRenderObject(RenderObjectWrapper old) {
super.syncRenderObject(old);
Widget oldChild = old == null ? null : (old as OneChildRenderObjectWrapper).child;
Widget newChild = child;
_child = syncChild(newChild, oldChild, null);
assert((newChild == null && child == null) || (newChild != null && child.parent == this));
assert(oldChild == null || child == oldChild || oldChild.parent == null);
}
void insertChildRenderObject(RenderObjectWrapper child, dynamic slot) {
final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
assert(renderObject is RenderObjectWithChildMixin);
assert(slot == null);
renderObject.child = child.renderObject;
assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
}
void detachChildRenderObject(RenderObjectWrapper child) {
final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
assert(renderObject is RenderObjectWithChildMixin);
assert(renderObject.child == child.renderObject);
renderObject.child = null;
assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
}
}
abstract class MultiChildRenderObjectWrapper extends RenderObjectWrapper {
// In MultiChildRenderObjectWrapper subclasses, slots are the Widget
// nodes whose RenderObjects are to be used as the "insert before"
// sibling in ContainerRenderObjectMixin.add() calls
MultiChildRenderObjectWrapper({ Key key, List<Widget> children })
: this.children = children == null ? const [] : children,
super(key: key) {
assert(!_debugHasDuplicateIds());
}
final List<Widget> children;
void walkChildren(WidgetTreeWalker walker) {
for (Widget child in children)
walker(child);
}
void insertChildRenderObject(RenderObjectWrapper child, Widget slot) {
final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
RenderObject nextSibling = slot != null ? slot.renderObject : null;
assert(nextSibling == null || nextSibling is RenderObject);
assert(renderObject is ContainerRenderObjectMixin);
renderObject.add(child.renderObject, before: nextSibling);
assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
}
void detachChildRenderObject(RenderObjectWrapper child) {
final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
assert(renderObject is ContainerRenderObjectMixin);
assert(child.renderObject.parent == renderObject);
renderObject.remove(child.renderObject);
assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
}
bool _debugHasDuplicateIds() {
var idSet = new HashSet<Key>();
for (var child in children) {
assert(child != null);
if (child.key == null)
continue; // when these nodes are reordered, we just reassign the data
if (!idSet.add(child.key)) {
throw '''If multiple keyed nodes exist as children of another node, they must have unique keys. $this has duplicate child key "${child.key}".''';
}
}
return false;
}
void syncRenderObject(MultiChildRenderObjectWrapper old) {
super.syncRenderObject(old);
syncChildren(children, old == null ? const <Widget>[] : old.children);
}
}
class WidgetSkyBinding extends SkyBinding {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment