Commit 06efe785 authored by Hixie's avatar Hixie

Add support for 'direction' to MixedViewport.

parent 81b3bdd4
...@@ -8,6 +8,7 @@ import 'package:sky/rendering/block.dart'; ...@@ -8,6 +8,7 @@ import 'package:sky/rendering/block.dart';
import 'package:sky/rendering/box.dart'; import 'package:sky/rendering/box.dart';
import 'package:sky/rendering/object.dart'; import 'package:sky/rendering/object.dart';
import 'package:sky/widgets/framework.dart'; import 'package:sky/widgets/framework.dart';
import 'package:sky/widgets/basic.dart';
// return null if index is greater than index of last entry // return null if index is greater than index of last entry
typedef Widget IndexedBuilder(int index); typedef Widget IndexedBuilder(int index);
...@@ -78,16 +79,19 @@ class MixedViewportLayoutState { ...@@ -78,16 +79,19 @@ class MixedViewportLayoutState {
} }
class MixedViewport extends RenderObjectWrapper { class MixedViewport extends RenderObjectWrapper {
MixedViewport({ Key key, this.builder, this.startOffset, this.token, this.layoutState }) MixedViewport({ Key key, this.startOffset, this.direction: ScrollDirection.vertical, this.builder, this.token, this.layoutState })
: super(key: key) { : super(key: key) {
assert(this.layoutState != null); assert(this.layoutState != null);
} }
IndexedBuilder builder;
double startOffset; double startOffset;
ScrollDirection direction;
IndexedBuilder builder;
Object token; Object token;
MixedViewportLayoutState layoutState; MixedViewportLayoutState layoutState;
// we don't pass the direction or offset to the render object when we create it, because
// the render object is empty so it will not matter
RenderBlockViewport get renderObject => super.renderObject; RenderBlockViewport get renderObject => super.renderObject;
RenderBlockViewport createNode() => new RenderBlockViewport(); RenderBlockViewport createNode() => new RenderBlockViewport();
...@@ -167,13 +171,14 @@ class MixedViewport extends RenderObjectWrapper { ...@@ -167,13 +171,14 @@ class MixedViewport extends RenderObjectWrapper {
layoutState._dirty = true; layoutState._dirty = true;
startOffset = newNode.startOffset; startOffset = newNode.startOffset;
} }
if (token != newNode.token || builder != newNode.builder) { if (direction != newNode.direction || builder != newNode.builder || token != newNode.token) {
layoutState._dirty = true; layoutState._dirty = true;
builder = newNode.builder;
token = newNode.token;
layoutState._didReachLastChild = false; layoutState._didReachLastChild = false;
layoutState._childOffsets = <double>[0.0]; layoutState._childOffsets = <double>[0.0];
layoutState._invalidIndices = new Set<int>(); layoutState._invalidIndices = new Set<int>();
direction = newNode.direction;
builder = newNode.builder;
token = newNode.token;
} }
return true; return true;
} }
...@@ -221,14 +226,19 @@ class MixedViewport extends RenderObjectWrapper { ...@@ -221,14 +226,19 @@ class MixedViewport extends RenderObjectWrapper {
Widget oldWidget = layoutState._childrenByKey[key]; Widget oldWidget = layoutState._childrenByKey[key];
newWidget = syncChild(newWidget, oldWidget, _omit); newWidget = syncChild(newWidget, oldWidget, _omit);
assert(newWidget != null); assert(newWidget != null);
// Update the offsets based on the newWidget's height. // Update the offsets based on the newWidget's dimensions.
RenderBox widgetRoot = newWidget.renderObject; RenderBox widgetRoot = newWidget.renderObject;
assert(widgetRoot is RenderBox); assert(widgetRoot is RenderBox);
double newHeight = widgetRoot.getMaxIntrinsicHeight(innerConstraints); double newOffset;
double oldHeight = offsets[index + 1] - offsets[index]; if (direction == ScrollDirection.vertical) {
double heightDelta = newHeight - oldHeight; newOffset = widgetRoot.getMaxIntrinsicHeight(innerConstraints);
} else {
newOffset = widgetRoot.getMaxIntrinsicWidth(innerConstraints);
}
double oldOffset = offsets[index + 1] - offsets[index];
double offsetDelta = newOffset - oldOffset;
for (int i = index + 1; i <= endIndex; i++) for (int i = index + 1; i <= endIndex; i++)
offsets[i] += heightDelta; offsets[i] += offsetDelta;
return newWidget; return newWidget;
} }
...@@ -247,7 +257,12 @@ class MixedViewport extends RenderObjectWrapper { ...@@ -247,7 +257,12 @@ class MixedViewport extends RenderObjectWrapper {
final double widgetStartOffset = offsets[index]; final double widgetStartOffset = offsets[index];
RenderBox widgetRoot = widget.renderObject; RenderBox widgetRoot = widget.renderObject;
assert(widgetRoot is RenderBox); assert(widgetRoot is RenderBox);
final double widgetEndOffset = widgetStartOffset + widgetRoot.getMaxIntrinsicHeight(innerConstraints); double widgetEndOffset;
if (direction == ScrollDirection.vertical) {
widgetEndOffset = widgetStartOffset + widgetRoot.getMaxIntrinsicHeight(innerConstraints);
} else {
widgetEndOffset = widgetStartOffset + widgetRoot.getMaxIntrinsicWidth(innerConstraints);
}
offsets.add(widgetEndOffset); offsets.add(widgetEndOffset);
} }
return widget; return widget;
...@@ -274,13 +289,28 @@ class MixedViewport extends RenderObjectWrapper { ...@@ -274,13 +289,28 @@ class MixedViewport extends RenderObjectWrapper {
final List<double> offsets = layoutState._childOffsets; final List<double> offsets = layoutState._childOffsets;
final Map<_Key, Widget> childrenByKey = layoutState._childrenByKey; final Map<_Key, Widget> childrenByKey = layoutState._childrenByKey;
final double height = constraints.maxHeight; double extent;
assert(height < double.INFINITY && if (direction == ScrollDirection.vertical) {
'There is no point putting a lazily-built MixedViewport inside a box with infinite internal height ' + extent = constraints.maxHeight;
'(e.g. inside something that scrolls), because it would then just eagerly build all the children. ' + assert(extent < double.INFINITY &&
'You probably want to put the MixedViewport inside a container with a fixed height.' is String); 'There is no point putting a lazily-built vertical MixedViewport inside a box with infinite internal ' +
final double endOffset = startOffset + height; 'height (e.g. inside something else that scrolls vertically), because it would then just eagerly build ' +
BoxConstraints innerConstraints = new BoxConstraints.tightFor(width: constraints.constrainWidth()); 'all the children. You probably want to put the MixedViewport inside a Container with a fixed height.' is String);
} else {
extent = constraints.maxWidth;
assert(extent < double.INFINITY &&
'There is no point putting a lazily-built horizontal MixedViewport inside a box with infinite internal ' +
'width (e.g. inside something else that scrolls horizontally), because it would then just eagerly build ' +
'all the children. You probably want to put the MixedViewport inside a Container with a fixed width.' is String);
}
final double endOffset = startOffset + extent;
BoxConstraints innerConstraints;
if (direction == ScrollDirection.vertical) {
innerConstraints = new BoxConstraints.tightFor(width: constraints.constrainWidth());
} else {
innerConstraints = new BoxConstraints.tightFor(height: constraints.constrainHeight());
}
// Before doing the actual layout, fix the offsets for the widgets // Before doing the actual layout, fix the offsets for the widgets
// whose size or type has changed. // whose size or type has changed.
...@@ -373,8 +403,14 @@ class MixedViewport extends RenderObjectWrapper { ...@@ -373,8 +403,14 @@ class MixedViewport extends RenderObjectWrapper {
int index = startIndex; int index = startIndex;
if (haveChildren) { if (haveChildren) {
// Build all the widgets we need. // Update the renderObject configuration
if (direction == ScrollDirection.vertical) {
renderObject.direction = BlockDirection.vertical;
} else {
renderObject.direction = BlockDirection.horizontal;
}
renderObject.startOffset = offsets[index] - startOffset; renderObject.startOffset = offsets[index] - startOffset;
// Build all the widgets we still need.
while (offsets[index] < endOffset) { while (offsets[index] < endOffset) {
if (!builtChildren.containsKey(index)) { if (!builtChildren.containsKey(index)) {
Widget widget = _getWidget(index, innerConstraints); Widget widget = _getWidget(index, innerConstraints);
......
...@@ -19,7 +19,6 @@ import 'package:sky/widgets/basic.dart'; ...@@ -19,7 +19,6 @@ import 'package:sky/widgets/basic.dart';
import 'package:sky/widgets/framework.dart'; import 'package:sky/widgets/framework.dart';
import 'package:sky/widgets/gesture_detector.dart'; import 'package:sky/widgets/gesture_detector.dart';
import 'package:sky/widgets/mixed_viewport.dart'; import 'package:sky/widgets/mixed_viewport.dart';
import 'package:sky/widgets/scrollable.dart';
export 'package:sky/widgets/mixed_viewport.dart' show MixedViewportLayoutState; export 'package:sky/widgets/mixed_viewport.dart' show MixedViewportLayoutState;
......
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