Commit 5ea50bf4 authored by Hans Muller's avatar Hans Muller

Adds CustomMultiChildLayout

CustomMultiChildLayout delegates to a MultiChildLayoutDelegate. Widget children are specified by their index in the list of children.
parent f8d5ccbf
......@@ -10,6 +10,7 @@ export 'src/rendering/basic_types.dart';
export 'src/rendering/binding.dart';
export 'src/rendering/block.dart';
export 'src/rendering/box.dart';
export 'src/rendering/custom_layout.dart';
export 'src/rendering/debug.dart';
export 'src/rendering/editable_paragraph.dart';
export 'src/rendering/error.dart';
......
// 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 'box.dart';
import 'object.dart';
class _MultiChildParentData extends ContainerBoxParentDataMixin<RenderBox> { }
abstract class MultiChildLayoutDelegate {
final List<RenderBox> _indexToChild = <RenderBox>[];
/// Returns the size of this object given the incomming constraints.
Size getSize(BoxConstraints constraints) => constraints.biggest;
/// Ask the child to update its layout within the limits specified by
/// the constraints parameter. The child's size is returned.
Size layoutChild(int childIndex, BoxConstraints constraints) {
final RenderBox child = _indexToChild[childIndex];
child.layout(constraints, parentUsesSize: true);
return child.size;
}
/// Specify the child's origin relative to this origin.
void positionChild(int childIndex, Point position) {
final RenderBox child = _indexToChild[childIndex];
final _MultiChildParentData childParentData = child.parentData;
childParentData.position = position;
}
void _callPerformLayout(Size size, BoxConstraints constraints, RenderBox firstChild) {
RenderBox child = firstChild;
while (child != null) {
_indexToChild.add(child);
final _MultiChildParentData childParentData = child.parentData;
child = childParentData.nextSibling;
}
performLayout(size, constraints, _indexToChild.length);
_indexToChild.clear();
}
/// Layout and position all children given this widget's size and the specified
/// constraints. This method must apply layoutChild() to each child. It should
/// specify the final position of each child with positionChild().
void performLayout(Size size, BoxConstraints constraints, int childCount);
}
class RenderCustomMultiChildLayoutBox extends RenderBox
with ContainerRenderObjectMixin<RenderBox, _MultiChildParentData>,
RenderBoxContainerDefaultsMixin<RenderBox, _MultiChildParentData> {
RenderCustomMultiChildLayoutBox({
List<RenderBox> children,
MultiChildLayoutDelegate delegate
}) : _delegate = delegate {
assert(delegate != null);
addAll(children);
}
void setupParentData(RenderBox child) {
if (child.parentData is! _MultiChildParentData)
child.parentData = new _MultiChildParentData();
}
MultiChildLayoutDelegate get delegate => _delegate;
MultiChildLayoutDelegate _delegate;
void set delegate (MultiChildLayoutDelegate newDelegate) {
assert(newDelegate != null);
if (_delegate == newDelegate)
return;
_delegate = newDelegate;
markNeedsLayout();
}
Size _getSize(BoxConstraints constraints) {
return constraints.constrain(_delegate.getSize(constraints));
}
double getMinIntrinsicWidth(BoxConstraints constraints) {
return _getSize(constraints).width;
}
double getMaxIntrinsicWidth(BoxConstraints constraints) {
return _getSize(constraints).width;
}
double getMinIntrinsicHeight(BoxConstraints constraints) {
return _getSize(constraints).height;
}
double getMaxIntrinsicHeight(BoxConstraints constraints) {
return _getSize(constraints).height;
}
bool get sizedByParent => true;
void performResize() {
size = _getSize(constraints);
}
void performLayout() {
delegate._callPerformLayout(size, constraints, firstChild);
}
void paint(PaintingContext context, Offset offset) {
defaultPaint(context, offset);
}
void hitTestChildren(HitTestResult result, { Point position }) {
defaultHitTestChildren(result, position: position);
}
}
......@@ -282,6 +282,29 @@ class CustomOneChildLayout extends OneChildRenderObjectWidget {
}
}
class CustomMultiChildLayout extends MultiChildRenderObjectWidget {
CustomMultiChildLayout(List<Widget> children, {
Key key,
this.delegate,
this.token
}) : super(key: key, children: children) {
assert(delegate != null);
}
final MultiChildLayoutDelegate delegate;
final Object token;
RenderCustomMultiChildLayoutBox createRenderObject() {
return new RenderCustomMultiChildLayoutBox(delegate: delegate);
}
void updateRenderObject(RenderCustomMultiChildLayoutBox renderObject, CustomMultiChildLayout oldWidget) {
if (oldWidget.token != token)
renderObject.markNeedsLayout();
renderObject.delegate = delegate;
}
}
class SizedBox extends OneChildRenderObjectWidget {
SizedBox({ Key key, this.width, this.height, Widget child })
: super(key: key, child: child);
......
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:test/test.dart';
import 'widget_tester.dart';
class TestMultiChildLayoutDelegate extends MultiChildLayoutDelegate {
BoxConstraints getSizeConstraints;
Size getSize(BoxConstraints constraints) {
getSizeConstraints = constraints;
return new Size(200.0, 300.0);
}
Size performLayoutSize;
BoxConstraints performLayoutConstraints;
int performLayoutChildCount;
Size performLayoutSize0;
Size performLayoutSize1;
void performLayout(Size size, BoxConstraints constraints, int childCount) {
performLayoutSize = size;
performLayoutConstraints = constraints;
performLayoutChildCount = childCount;
performLayoutSize0 = layoutChild(0, constraints);
performLayoutSize1 = layoutChild(1, constraints);
}
}
void main() {
test('Control test for CustomMultiChildLayout', () {
testWidgets((WidgetTester tester) {
TestMultiChildLayoutDelegate delegate = new TestMultiChildLayoutDelegate();
tester.pumpWidget(new Center(
child: new CustomMultiChildLayout([
new Container(width: 150.0, height: 100.0),
new Container(width: 100.0, height: 200.0)
],
delegate: delegate
)
));
expect(delegate.getSizeConstraints.minWidth, 0.0);
expect(delegate.getSizeConstraints.maxWidth, 800.0);
expect(delegate.getSizeConstraints.minHeight, 0.0);
expect(delegate.getSizeConstraints.maxHeight, 600.0);
expect(delegate.performLayoutSize.width, 200.0);
expect(delegate.performLayoutSize.height, 300.0);
expect(delegate.performLayoutConstraints.minWidth, 0.0);
expect(delegate.performLayoutConstraints.maxWidth, 800.0);
expect(delegate.performLayoutConstraints.minHeight, 0.0);
expect(delegate.performLayoutConstraints.maxHeight, 600.0);
expect(delegate.performLayoutChildCount, 2);
expect(delegate.performLayoutSize0.width, 150.0);
expect(delegate.performLayoutSize0.height, 100.0);
expect(delegate.performLayoutSize1.width, 100.0);
expect(delegate.performLayoutSize1.height, 200.0);
});
});
}
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