| Index: sky/examples/raw/sector-layout.dart
|
| diff --git a/sky/examples/raw/sector-layout.dart b/sky/examples/raw/sector-layout.dart
|
| index 843463f1702f20901e880805942f94d84792ddca..3e0e67d6481af74df2cf1193c033ba829aa207f1 100644
|
| --- a/sky/examples/raw/sector-layout.dart
|
| +++ b/sky/examples/raw/sector-layout.dart
|
| @@ -15,7 +15,8 @@ class SectorConstraints {
|
| this.minDeltaRadius: 0.0,
|
| this.maxDeltaRadius: double.INFINITY,
|
| this.minDeltaTheta: 0.0,
|
| - this.maxDeltaTheta: kTwoPi});
|
| + this.maxDeltaTheta: kTwoPi
|
| + });
|
|
|
| const SectorConstraints.tight({ double deltaRadius: 0.0, double deltaTheta: 0.0 })
|
| : minDeltaRadius = deltaRadius,
|
| @@ -70,7 +71,7 @@ abstract class RenderSector extends RenderNode {
|
| return new SectorDimensions.withConstraints(constraints);
|
| }
|
|
|
| - void layout(SectorConstraints constraints, double radius, { RenderNode relayoutSubtreeRoot }) {
|
| + void layout(SectorConstraints constraints, { RenderNode relayoutSubtreeRoot }) {
|
| deltaRadius = constraints.constrainDeltaRadius(0.0);
|
| deltaTheta = constraints.constrainDeltaTheta(0.0);
|
| layoutDone();
|
| @@ -104,11 +105,11 @@ class RenderDecoratedSector extends RenderSector {
|
| if (_decoration.backgroundColor != null) {
|
| sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor;
|
| sky.Path path = new sky.Path();
|
| - double outerRadiusOver2 = (parentData.radius + deltaRadius) / 2.0;
|
| - sky.Rect outerBounds = new sky.Rect()..setLTRB(-outerRadiusOver2, -outerRadiusOver2, outerRadiusOver2, outerRadiusOver2);
|
| + double outerRadius = (parentData.radius + deltaRadius);
|
| + sky.Rect outerBounds = new sky.Rect()..setLTRB(-outerRadius, -outerRadius, outerRadius, outerRadius);
|
| path.arcTo(outerBounds, deg(parentData.theta), deg(deltaTheta), true);
|
| - double innerRadiusOver2 = parentData.radius / 2.0;
|
| - sky.Rect innerBounds = new sky.Rect()..setLTRB(-innerRadiusOver2, -innerRadiusOver2, innerRadiusOver2, innerRadiusOver2);
|
| + double innerRadius = parentData.radius;
|
| + sky.Rect innerBounds = new sky.Rect()..setLTRB(-innerRadius, -innerRadius, innerRadius, innerRadius);
|
| path.arcTo(innerBounds, deg(parentData.theta + deltaTheta), deg(-deltaTheta), false);
|
| path.close();
|
| canvas.drawPath(path, paint);
|
| @@ -140,6 +141,7 @@ class RenderSectorRing extends RenderDecoratedSector with ContainerRenderNodeMix
|
| double _padding;
|
| double get padding => _padding;
|
| void set padding(double value) {
|
| + // TODO(ianh): avoid code duplication
|
| assert(value != null);
|
| if (_padding != value) {
|
| _padding = value;
|
| @@ -148,6 +150,7 @@ class RenderSectorRing extends RenderDecoratedSector with ContainerRenderNodeMix
|
| }
|
|
|
| void setParentData(RenderNode child) {
|
| + // TODO(ianh): avoid code duplication
|
| if (child.parentData is! SectorChildListParentData)
|
| child.parentData = new SectorChildListParentData();
|
| }
|
| @@ -158,21 +161,21 @@ class RenderSectorRing extends RenderDecoratedSector with ContainerRenderNodeMix
|
| double childRadius = radius + padding;
|
| double paddingTheta = math.atan(padding / (radius + outerDeltaRadius));
|
| double innerTheta = paddingTheta; // increments with each child
|
| - double remainingTheta = constraints.maxDeltaTheta - (innerTheta + paddingTheta);
|
| + double remainingDeltaTheta = constraints.maxDeltaTheta - (innerTheta + paddingTheta);
|
| RenderSector child = firstChild;
|
| while (child != null) {
|
| SectorConstraints innerConstraints = new SectorConstraints(
|
| maxDeltaRadius: innerDeltaRadius,
|
| - maxDeltaTheta: remainingTheta
|
| + maxDeltaTheta: remainingDeltaTheta
|
| );
|
| SectorDimensions childDimensions = child.getIntrinsicDimensions(innerConstraints, childRadius);
|
| innerTheta += childDimensions.deltaTheta;
|
| - remainingTheta -= childDimensions.deltaTheta;
|
| + remainingDeltaTheta -= childDimensions.deltaTheta;
|
| assert(child.parentData is SectorChildListParentData);
|
| child = child.parentData.nextSibling;
|
| if (child != null) {
|
| innerTheta += paddingTheta;
|
| - remainingTheta -= paddingTheta;
|
| + remainingDeltaTheta -= paddingTheta;
|
| }
|
| }
|
| return new SectorDimensions.withConstraints(constraints,
|
| @@ -181,44 +184,46 @@ class RenderSectorRing extends RenderDecoratedSector with ContainerRenderNodeMix
|
| }
|
|
|
| SectorConstraints _constraints;
|
| - void layout(SectorConstraints constraints, double radius, { RenderNode relayoutSubtreeRoot }) {
|
| + void layout(SectorConstraints constraints, { RenderNode relayoutSubtreeRoot }) {
|
| if (relayoutSubtreeRoot != null)
|
| saveRelayoutSubtreeRoot(relayoutSubtreeRoot);
|
| relayoutSubtreeRoot = relayoutSubtreeRoot == null ? this : relayoutSubtreeRoot;
|
| deltaRadius = constraints.constrainDeltaRadius(desiredDeltaRadius);
|
| assert(deltaRadius < double.INFINITY);
|
| _constraints = constraints;
|
| - internalLayout(radius, relayoutSubtreeRoot);
|
| + internalLayout(relayoutSubtreeRoot);
|
| }
|
|
|
| void relayout() {
|
| + // TODO(ianh): avoid code duplication
|
| assert(parentData is SectorParentData);
|
| - internalLayout(parentData.radius, this);
|
| + internalLayout(this);
|
| }
|
|
|
| - void internalLayout(double radius, RenderNode relayoutSubtreeRoot) {
|
| + void internalLayout(RenderNode relayoutSubtreeRoot) {
|
| + assert(this.parentData is SectorParentData);
|
| double innerDeltaRadius = deltaRadius - padding * 2.0;
|
| - double childRadius = radius + padding;
|
| - double paddingTheta = math.atan(padding / (radius + deltaRadius));
|
| + double childRadius = this.parentData.radius + padding;
|
| + double paddingTheta = math.atan(padding / (this.parentData.radius + deltaRadius));
|
| double innerTheta = paddingTheta; // increments with each child
|
| - double remainingTheta = _constraints.maxDeltaTheta - (innerTheta + paddingTheta);
|
| + double remainingDeltaTheta = _constraints.maxDeltaTheta - (innerTheta + paddingTheta);
|
| RenderSector child = firstChild;
|
| while (child != null) {
|
| SectorConstraints innerConstraints = new SectorConstraints(
|
| maxDeltaRadius: innerDeltaRadius,
|
| - maxDeltaTheta: remainingTheta
|
| + maxDeltaTheta: remainingDeltaTheta
|
| );
|
| - child.layout(innerConstraints, childRadius, relayoutSubtreeRoot: relayoutSubtreeRoot);
|
| assert(child.parentData is SectorParentData);
|
| child.parentData.theta = innerTheta;
|
| child.parentData.radius = childRadius;
|
| + child.layout(innerConstraints, relayoutSubtreeRoot: relayoutSubtreeRoot);
|
| innerTheta += child.deltaTheta;
|
| - remainingTheta -= child.deltaTheta;
|
| + remainingDeltaTheta -= child.deltaTheta;
|
| assert(child.parentData is SectorChildListParentData);
|
| child = child.parentData.nextSibling;
|
| if (child != null) {
|
| innerTheta += paddingTheta;
|
| - remainingTheta -= paddingTheta;
|
| + remainingDeltaTheta -= paddingTheta;
|
| }
|
| }
|
| deltaTheta = innerTheta;
|
| @@ -229,6 +234,129 @@ class RenderSectorRing extends RenderDecoratedSector with ContainerRenderNodeMix
|
| // paint origin is 0,0 of our circle
|
| // each sector then knows how to paint itself at its location
|
| void paint(RenderNodeDisplayList canvas) {
|
| + // TODO(ianh): avoid code duplication
|
| + super.paint(canvas);
|
| + RenderSector child = firstChild;
|
| + while (child != null) {
|
| + assert(child.parentData is SectorChildListParentData);
|
| + canvas.paintChild(child, 0.0, 0.0);
|
| + child = child.parentData.nextSibling;
|
| + }
|
| + }
|
| +
|
| +}
|
| +
|
| +class RenderSectorSlice extends RenderDecoratedSector with ContainerRenderNodeMixin<RenderSector, SectorChildListParentData> {
|
| + // lays out RenderSector children in a stack
|
| +
|
| + RenderSectorSlice({
|
| + BoxDecoration decoration,
|
| + double deltaTheta: kTwoPi,
|
| + double padding: 0.0
|
| + }) : super(decoration), _padding = padding, _desiredDeltaTheta = deltaTheta;
|
| +
|
| + double _desiredDeltaTheta;
|
| + double get desiredDeltaTheta => _desiredDeltaTheta;
|
| + void set desiredDeltaTheta(double value) {
|
| + assert(value != null);
|
| + if (_desiredDeltaTheta != value) {
|
| + _desiredDeltaTheta = value;
|
| + markNeedsLayout();
|
| + }
|
| + }
|
| +
|
| + double _padding;
|
| + double get padding => _padding;
|
| + void set padding(double value) {
|
| + // TODO(ianh): avoid code duplication
|
| + assert(value != null);
|
| + if (_padding != value) {
|
| + _padding = value;
|
| + markNeedsLayout();
|
| + }
|
| + }
|
| +
|
| + void setParentData(RenderNode child) {
|
| + // TODO(ianh): avoid code duplication
|
| + if (child.parentData is! SectorChildListParentData)
|
| + child.parentData = new SectorChildListParentData();
|
| + }
|
| +
|
| + SectorDimensions getIntrinsicDimensions(SectorConstraints constraints, double radius) {
|
| + assert(this.parentData is SectorParentData);
|
| + double paddingTheta = math.atan(padding / this.parentData.radius);
|
| + double outerDeltaTheta = constraints.constrainDeltaTheta(desiredDeltaTheta);
|
| + double innerDeltaTheta = outerDeltaTheta - paddingTheta * 2.0;
|
| + double childRadius = this.parentData.radius + padding;
|
| + double remainingDeltaRadius = constraints.maxDeltaRadius - (padding * 2.0);
|
| + RenderSector child = firstChild;
|
| + while (child != null) {
|
| + SectorConstraints innerConstraints = new SectorConstraints(
|
| + maxDeltaRadius: remainingDeltaRadius,
|
| + maxDeltaTheta: innerDeltaTheta
|
| + );
|
| + SectorDimensions childDimensions = child.getIntrinsicDimensions(innerConstraints, childRadius);
|
| + childRadius += childDimensions.deltaRadius;
|
| + remainingDeltaRadius -= childDimensions.deltaRadius;
|
| + assert(child.parentData is SectorChildListParentData);
|
| + child = child.parentData.nextSibling;
|
| + childRadius += padding;
|
| + remainingDeltaRadius -= padding;
|
| + }
|
| + return new SectorDimensions.withConstraints(constraints,
|
| + deltaRadius: childRadius - this.parentData.radius,
|
| + deltaTheta: outerDeltaTheta);
|
| + }
|
| +
|
| + SectorConstraints _constraints;
|
| + void layout(SectorConstraints constraints, { RenderNode relayoutSubtreeRoot }) {
|
| + if (relayoutSubtreeRoot != null)
|
| + saveRelayoutSubtreeRoot(relayoutSubtreeRoot);
|
| + relayoutSubtreeRoot = relayoutSubtreeRoot == null ? this : relayoutSubtreeRoot;
|
| + deltaTheta = constraints.constrainDeltaTheta(desiredDeltaTheta);
|
| + assert(deltaTheta <= kTwoPi);
|
| + _constraints = constraints;
|
| + internalLayout(relayoutSubtreeRoot);
|
| + }
|
| +
|
| + void relayout() {
|
| + // TODO(ianh): avoid code duplication
|
| + assert(parentData is SectorParentData);
|
| + internalLayout(this);
|
| + }
|
| +
|
| + void internalLayout(RenderNode relayoutSubtreeRoot) {
|
| + assert(this.parentData is SectorParentData);
|
| + double paddingTheta = math.atan(padding / this.parentData.radius);
|
| + double innerTheta = this.parentData.theta + paddingTheta;
|
| + double innerDeltaTheta = deltaTheta - paddingTheta * 2.0;
|
| + double childRadius = this.parentData.radius + padding;
|
| + double remainingDeltaRadius = _constraints.maxDeltaRadius - (padding * 2.0);
|
| + RenderSector child = firstChild;
|
| + while (child != null) {
|
| + SectorConstraints innerConstraints = new SectorConstraints(
|
| + maxDeltaRadius: remainingDeltaRadius,
|
| + maxDeltaTheta: innerDeltaTheta
|
| + );
|
| + child.parentData.theta = innerTheta;
|
| + child.parentData.radius = childRadius;
|
| + child.layout(innerConstraints);
|
| + childRadius += child.deltaRadius;
|
| + remainingDeltaRadius -= child.deltaRadius;
|
| + assert(child.parentData is SectorChildListParentData);
|
| + child = child.parentData.nextSibling;
|
| + childRadius += padding;
|
| + remainingDeltaRadius -= padding;
|
| + }
|
| + deltaRadius = childRadius - this.parentData.radius;
|
| + }
|
| +
|
| + // TODO(ianh): hit testing et al is pending on adam's patch
|
| +
|
| + // paint origin is 0,0 of our circle
|
| + // each sector then knows how to paint itself at its location
|
| + void paint(RenderNodeDisplayList canvas) {
|
| + // TODO(ianh): avoid code duplication
|
| super.paint(canvas);
|
| RenderSector child = firstChild;
|
| while (child != null) {
|
| @@ -276,7 +404,7 @@ class RenderBoxToRenderSectorAdapter extends RenderBox {
|
| assert(child is RenderSector);
|
| assert(child.parentData is SectorParentData);
|
| assert(!constraints.isInfinite);
|
| - double maxChildDeltaRadius = math.max(constraints.maxWidth, constraints.maxHeight) / 2.0 - innerRadius;
|
| + double maxChildDeltaRadius = math.min(constraints.maxWidth, constraints.maxHeight) / 2.0 - innerRadius;
|
| SectorDimensions childDimensions = child.getIntrinsicDimensions(new SectorConstraints(maxDeltaRadius: maxChildDeltaRadius), innerRadius);
|
| double dimension = (innerRadius + childDimensions.deltaRadius) * 2.0;
|
| return new BoxDimensions.withConstraints(constraints, width: dimension, height: dimension);
|
| @@ -291,16 +419,17 @@ class RenderBoxToRenderSectorAdapter extends RenderBox {
|
| ourDimensions = new BoxDimensions.withConstraints(constraints, width: 0.0, height: 0.0);
|
| } else {
|
| assert(child is RenderSector);
|
| - assert(child.parentData is SectorParentData);
|
| assert(!constraints.isInfinite);
|
| double maxChildDeltaRadius = math.min(constraints.maxWidth, constraints.maxHeight) / 2.0 - innerRadius;
|
| - child.layout(new SectorConstraints(maxDeltaRadius: maxChildDeltaRadius), innerRadius, relayoutSubtreeRoot: relayoutSubtreeRoot);
|
| + assert(child.parentData is SectorParentData);
|
| + child.parentData.radius = innerRadius;
|
| + child.parentData.theta = 0.0;
|
| + child.layout(new SectorConstraints(maxDeltaRadius: maxChildDeltaRadius), relayoutSubtreeRoot: relayoutSubtreeRoot);
|
| double dimension = (innerRadius + child.deltaRadius) * 2.0;
|
| ourDimensions = new BoxDimensions.withConstraints(constraints, width: dimension, height: dimension);
|
| }
|
| width = ourDimensions.width;
|
| height = ourDimensions.height;
|
| - print("adapter is: ${width}x${height}");
|
| layoutDone();
|
| }
|
|
|
| @@ -312,35 +441,28 @@ class RenderBoxToRenderSectorAdapter extends RenderBox {
|
| // paint origin is 0,0 of our circle
|
| void paint(RenderNodeDisplayList canvas) {
|
| super.paint(canvas);
|
| - if (child != null) {
|
| - print("painting child at ${width/2.0},${height/2.0}");
|
| - sky.Paint paint;
|
| - paint = new sky.Paint()..color = 0xFF474700;
|
| - canvas.drawRect(new sky.Rect()..setLTRB(0.0, 0.0, width, height), paint);
|
| - paint = new sky.Paint()..color = 0xFFF7F700;
|
| - canvas.drawRect(new sky.Rect()..setLTRB(10.0, 10.0, width-10.0, height-10.0), paint);
|
| - paint = new sky.Paint()..color = 0xFFFFFFFF;
|
| - canvas.drawRect(new sky.Rect()..setLTRB(width/2.0-5.0, height/2.0-5.0, width/2.0+5.0, height/2.0+5.0), paint);
|
| + if (child != null)
|
| canvas.paintChild(child, width/2.0, height/2.0);
|
| - }
|
| }
|
|
|
| }
|
|
|
| class RenderSolidColor extends RenderDecoratedSector {
|
| - final int backgroundColor;
|
| + RenderSolidColor(int backgroundColor, {
|
| + this.desiredDeltaRadius: double.INFINITY,
|
| + this.desiredDeltaTheta: kTwoPi
|
| + }) : super(new BoxDecoration(backgroundColor: backgroundColor));
|
|
|
| - RenderSolidColor(int backgroundColor)
|
| - : super(new BoxDecoration(backgroundColor: backgroundColor)),
|
| - backgroundColor = backgroundColor;
|
| + double desiredDeltaRadius;
|
| + double desiredDeltaTheta;
|
|
|
| SectorDimensions getIntrinsicDimensions(SectorConstraints constraints, double radius) {
|
| return new SectorDimensions.withConstraints(constraints, deltaTheta: 1.0); // 1.0 radians
|
| }
|
|
|
| - void layout(SectorConstraints constraints, double radius, { RenderNode relayoutSubtreeRoot }) {
|
| - deltaRadius = constraints.constrainDeltaRadius(constraints.maxDeltaRadius);
|
| - deltaTheta = constraints.constrainDeltaTheta(1.0); // 1.0 radians
|
| + void layout(SectorConstraints constraints, { RenderNode relayoutSubtreeRoot }) {
|
| + deltaRadius = constraints.constrainDeltaRadius(desiredDeltaRadius);
|
| + deltaTheta = constraints.constrainDeltaTheta(desiredDeltaTheta);
|
| layoutDone();
|
| }
|
| }
|
| @@ -365,13 +487,17 @@ void main() {
|
| sky.view.setBeginFrameCallback(beginFrame);
|
|
|
| var rootCircle = new RenderSectorRing(padding: 10.0);
|
| - rootCircle.add(new RenderSolidColor(0xFF00FF00));
|
| - rootCircle.add(new RenderSolidColor(0xFF0000FF));
|
| + rootCircle.add(new RenderSolidColor(0xFF00FFFF, desiredDeltaTheta: kTwoPi * 0.25));
|
| + rootCircle.add(new RenderSolidColor(0xFF0000FF, desiredDeltaTheta: kTwoPi * 0.3));
|
| + var stack = new RenderSectorSlice(padding: 10.0);
|
| + stack.add(new RenderSolidColor(0xFFFFFF00, desiredDeltaRadius: 20.0));
|
| + stack.add(new RenderSolidColor(0xFFFF9000, desiredDeltaRadius: 20.0));
|
| + stack.add(new RenderSolidColor(0xFF00FF00, desiredDeltaRadius: 20.0));
|
| + rootCircle.add(stack);
|
|
|
| var root = new RenderBoxToRenderSectorAdapter(innerRadius: 50.0, child: rootCircle);
|
| renderView = new RenderView(root: root);
|
| renderView.layout(newWidth: sky.view.width, newHeight: sky.view.height);
|
|
|
| sky.view.scheduleFrame();
|
| - print("window is ${sky.view.width}x${sky.view.height}");
|
| }
|
|
|