| Index: sky/examples/style/hex-layout.sky
|
| diff --git a/sky/examples/style/hex-layout.sky b/sky/examples/style/hex-layout.sky
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ca286f0401a2c604ea34221c8a48b6502e7f7784
|
| --- /dev/null
|
| +++ b/sky/examples/style/hex-layout.sky
|
| @@ -0,0 +1,146 @@
|
| +#!mojo mojo:sky
|
| +<import src="sky:core" as="sky"/>
|
| +<script>
|
| + class BeehiveLayoutManager extends sky.LayoutManager {
|
| + function layout(width, height) {
|
| + 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.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 getIntrinsicWidth() {
|
| + // this is the logic that LayoutManager.getIntrinsicWidth() has by default
|
| + // shown here because I wrote it before realising it should be the default
|
| + let width = this.node.getProperty('width');
|
| + if (typeof width != 'number')
|
| + width = 0;
|
| + let minWidth = this.node.getProperty('min-width');
|
| + if (typeof width != 'number')
|
| + minWidth = 0;
|
| + let maxWidth = this.node.getProperty('max-width');
|
| + if (typeof width != 'number')
|
| + maxWidth = Infinity;
|
| + if (maxWidth < minWidth)
|
| + maxWidth = minWidth;
|
| + if (width > maxWidth)
|
| + width = maxWidth;
|
| + if (width < minWidth)
|
| + width = minWidth;
|
| + return {
|
| + minimum: minWidth,
|
| + value: width,
|
| + maximum: maxWidth,
|
| + };
|
| + }
|
| + 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(RenderingSurface 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;
|
| + if (child.needsPaint) {
|
| + 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();
|
| + child.paint(canvas);
|
| + } finally {
|
| + canvas.restore();
|
| + }
|
| + }
|
| + loop = children.next();
|
| + }
|
| + }
|
| + }
|
| + 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) throw new Error();
|
| + let result = token.value.value;
|
| + if (!token.next().done) throw new Error();
|
| + return result;
|
| + });
|
| + 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>
|
|
|