#!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>
