mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
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
152 lines
4.6 KiB
Plaintext
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>
|