flutter_flutter/examples/style/hex-layout.sky
Hixie a6613e7ef2 Specs: Simplify the paint model. Now you are not responsible for
actually telling your child to paint, you just say where it would
paint. The platform then takes care of making sure all the dirty nodes
have their paint() methods called.

Review URL: https://codereview.chromium.org/744843003
2014-11-20 15:30:30 -08:00

152 lines
4.6 KiB
Plaintext

#!mojo mojo:sky
<import src="sky:core" as="sky"/>
<script>
class BeehiveLayoutManager extends sky.LayoutManager {
function layout(width, height) {
this.markAsLaidOut();
if (width == null)
width = this.getIntrinsicWidth().value;
let autoHeight = false;
if (height == null) {
height = 0;
autoHeight = true;
}
this.assumeDimensions(width, height);
let cellCount = this.node.getProperty('beehive-count');
let cellDim = width / cellCount;
let children = this.walkChildren();
let loop = children.next();
let x = 0;
let y = 0;
while (!loop.done) {
let child = loop.value;
if (child.needsLayout || child.descendantNeedsLayout) {
child.layoutManager.layout(cellDim, cellDim);
// we ignore the size the child reported from layout(), and force it to the cell dimensions
this.setChildSize(child, cellDim, cellDim);
}
this.setChildPosition(child, x * cellDim + (y % 2) * cellDim/2, y * 3/4 * cellDim);
x += 1;
if (x > cellCount) {
y += 1;
x = 0;
}
loop = children.next();
}
if (height == 0)
height = (1 + y * 3/4) * cellDim;
return {
width: width,
height: height,
}
}
function getIntrinsicHeight() {
let height = this.node.getProperty('height');
if (typeof height != 'number') {
// e.g. height: auto
width = this.getIntrinsicWidth().value;
let cellCount = this.node.getProperty('beehive-count');
let cellDim = width / cellCount;
let children = this.walkChildren();
let loop = children.next();
let childCount = 0;
while (!loop.done) {
childCount += 1;
loop.next();
}
if (childCount > 0)
height = cellDim * (1/4 + Math.ceil(childCount / cellCount) * 3/4);
else
height = 0;
}
return super(height); // does the equivalent of getIntrinsicWidth() above, applying min-height etc
}
function paintChildren(canvas) {
let width = this.node.width;
let cellCount = this.node.getProperty('beehive-count');
let cellDim = width / cellCount;
let children = this.walkChildren();
let loop = children.next();
while (!loop.done) {
let child = loop.value;
canvas.save();
try {
canvas.beginPath();
canvas.moveTo(child.x, child.y + cellDim/4);
canvas.lineTo(child.x + cellDim/2, child.y);
canvas.lineTo(child.x + cellDim, child.y + cellDim/4);
canvas.lineTo(child.x + cellDim, child.y + 3*cellDim/4);
canvas.lineTo(child.x + cellDim/2, child.y + cellDim);
canvas.moveTo(child.x, child.y + 3*cellDim/4);
canvas.closePath();
canvas.clip();
canvas.paintChild(child);
} finally {
canvas.restore();
}
loop = children.next();
}
}
function inHex(topLeftX, topLeftY, width, height, hitX, hitY) {
let centerX = topLeftX - width/2;
let absCenteredHitX = Math.abs(hitX - centerX);
if (absCenteredHitX > width/2)
return false;
let centerY = topLeftY - height/2;
let absCenteredHitY = Math.abs(hitY - centerY);
if (absCenteredHitY > height/2)
return false;
if (absCenteredHitY < height * absCenteredHitX / (2 * width) + height / 2)
return true;
return false;
}
function hitTest(x, y) {
let cellCount = this.node.getProperty('beehive-count');
let cellDim = width / cellCount;
let children = this.walkChildren();
let loop = children.next();
while (!loop.done) {
let child = loop.value;
if (this.inHex(child.x, child.y, child.width, child.height, x, y))
return child.layoutManager.hitTest(x-child.x, y-child.y);
loop = children.next();
}
return this.node;
}
}
sky.registerLayoutManager('beehive', BeehiveLayoutManager);
let BeehiveCountStyleValueType = new StyleValueType();
BeehiveCountStyleValueType.addParser((tokens) => {
let token = tokens.next();
if (token.done)
throw new Error();
if (token.value.kind != 'number')
throw new Error();
if (token.value.value <= 0)
throw new Error();
if (Math.trunc(token.value.value) != token.value.value) // is integer
throw new Error();
return {
value: token.value.value;
}
});
sky.registerProperty({
name: 'beehive-count',
type: BeehiveCountStyleValueType,
inherits: true,
initialValue: 5,
needsLayout: true,
});
</script>
<style>
div { display: beehive; beehive-count: 3; }
</style>
<div>
<t>Hello</t>
<t>World</t>
<t>How</t>
<t>Are</t>
<t>You</t>
<t>Today?</t>
</div>