OLD | NEW |
1 #!mojo mojo:sky | 1 #!mojo mojo:sky |
2 <import src="sky:core" as="sky"/> | 2 <import src="sky:core" as="sky"/> |
3 <script> | 3 <script> |
4 class BeehiveLayoutManager extends sky.LayoutManager { | 4 class BeehiveLayoutManager extends sky.LayoutManager { |
5 function layout(width, height) { | 5 function layout(width, height) { |
6 this.markAsLaidOut(); | 6 this.markAsLaidOut(); |
7 if (width == null) | 7 if (width == null) |
8 width = this.getIntrinsicWidth().value; | 8 width = this.getIntrinsicWidth().value; |
9 let autoHeight = false; | 9 let autoHeight = false; |
10 if (height == null) { | 10 if (height == null) { |
11 height = 0; | 11 height = 0; |
12 autoHeight = true; | 12 autoHeight = true; |
13 } | 13 } |
14 this.assumeDimensions(width, height); | 14 this.assumeDimensions(width, height); |
15 let cellCount = this.node.getProperty('beehive-count'); | 15 let cellCount = this.node.getProperty('beehive-count'); |
16 let cellDim = width / cellCount; | 16 let cellDim = width / cellCount; |
17 let children = this.walkChildren(); | 17 let children = this.walkChildren(); |
18 let loop = children.next(); | 18 let loop = children.next(); |
19 let x = 0; | 19 let x = 0; |
20 let y = 0; | 20 let y = 0; |
21 while (!loop.done) { | 21 while (!loop.done) { |
22 let child = loop.value; | 22 let child = loop.value; |
23 if (child.needsLayout) { | 23 if (child.needsLayout || child.descendantNeedsLayout) { |
24 child.layoutManager.layout(cellDim, cellDim); | 24 child.layoutManager.layout(cellDim, cellDim); |
25 // we ignore the size the child reported from layout(), and force it to
the cell dimensions | 25 // we ignore the size the child reported from layout(), and force it to
the cell dimensions |
26 this.setChildSize(child, cellDim, cellDim); | 26 this.setChildSize(child, cellDim, cellDim); |
27 } | 27 } |
28 this.setChildPosition(child, x * cellDim + (y % 2) * cellDim/2, y * 3/4 *
cellDim); | 28 this.setChildPosition(child, x * cellDim + (y % 2) * cellDim/2, y * 3/4 *
cellDim); |
29 x += 1; | 29 x += 1; |
30 if (x > cellCount) { | 30 if (x > cellCount) { |
31 y += 1; | 31 y += 1; |
32 x = 0; | 32 x = 0; |
33 } | 33 } |
34 loop = children.next(); | 34 loop = children.next(); |
35 } | 35 } |
36 if (height == 0) | 36 if (height == 0) |
37 height = (1 + y * 3/4) * cellDim; | 37 height = (1 + y * 3/4) * cellDim; |
38 return { | 38 return { |
39 width: width, | 39 width: width, |
40 height: height, | 40 height: height, |
41 } | 41 } |
42 } | 42 } |
43 function getIntrinsicWidth() { | |
44 // this is the logic that LayoutManager.getIntrinsicWidth() has by default | |
45 // shown here because I wrote it before realising it should be the default | |
46 let width = this.node.getProperty('width'); | |
47 if (typeof width != 'number') | |
48 width = 0; | |
49 let minWidth = this.node.getProperty('min-width'); | |
50 if (typeof width != 'number') | |
51 minWidth = 0; | |
52 let maxWidth = this.node.getProperty('max-width'); | |
53 if (typeof width != 'number') | |
54 maxWidth = Infinity; | |
55 if (maxWidth < minWidth) | |
56 maxWidth = minWidth; | |
57 if (width > maxWidth) | |
58 width = maxWidth; | |
59 if (width < minWidth) | |
60 width = minWidth; | |
61 return { | |
62 minimum: minWidth, | |
63 value: width, | |
64 maximum: maxWidth, | |
65 }; | |
66 } | |
67 function getIntrinsicHeight() { | 43 function getIntrinsicHeight() { |
68 let height = this.node.getProperty('height'); | 44 let height = this.node.getProperty('height'); |
69 if (typeof height != 'number') { | 45 if (typeof height != 'number') { |
70 // e.g. height: auto | 46 // e.g. height: auto |
71 width = this.getIntrinsicWidth().value; | 47 width = this.getIntrinsicWidth().value; |
72 let cellCount = this.node.getProperty('beehive-count'); | 48 let cellCount = this.node.getProperty('beehive-count'); |
73 let cellDim = width / cellCount; | 49 let cellDim = width / cellCount; |
74 let children = this.walkChildren(); | 50 let children = this.walkChildren(); |
75 let loop = children.next(); | 51 let loop = children.next(); |
76 let childCount = 0; | 52 let childCount = 0; |
77 while (!loop.done) { | 53 while (!loop.done) { |
78 childCount += 1; | 54 childCount += 1; |
79 loop.next(); | 55 loop.next(); |
80 } | 56 } |
81 if (childCount > 0) | 57 if (childCount > 0) |
82 height = cellDim * (1/4 + Math.ceil(childCount / cellCount) * 3/4); | 58 height = cellDim * (1/4 + Math.ceil(childCount / cellCount) * 3/4); |
83 else | 59 else |
84 height = 0; | 60 height = 0; |
85 } | 61 } |
86 return super(height); // does the equivalent of getIntrinsicWidth() above,
applying min-height etc | 62 return super(height); // does the equivalent of getIntrinsicWidth() above,
applying min-height etc |
87 } | 63 } |
88 function paintChildren(canvas) { | 64 function paintChildren(canvas) { |
89 let width = this.node.width; | 65 let width = this.node.width; |
90 let cellCount = this.node.getProperty('beehive-count'); | 66 let cellCount = this.node.getProperty('beehive-count'); |
91 let cellDim = width / cellCount; | 67 let cellDim = width / cellCount; |
92 let children = this.walkChildren(); | 68 let children = this.walkChildren(); |
93 let loop = children.next(); | 69 let loop = children.next(); |
94 while (!loop.done) { | 70 while (!loop.done) { |
95 let child = loop.value; | 71 let child = loop.value; |
96 if (child.needsPaint) { | 72 if (child.needsPaint || child.descendantNeedsPaint) { |
97 canvas.save(); | 73 canvas.save(); |
98 try { | 74 try { |
99 canvas.beginPath(); | 75 canvas.beginPath(); |
100 canvas.translate(child.x, child.y); | 76 canvas.moveTo(child.x, child.y + cellDim/4); |
101 canvas.moveTo(0, cellDim/4); | 77 canvas.lineTo(child.x + cellDim/2, child.y); |
102 canvas.lineTo(cellDim/2, 0); | 78 canvas.lineTo(child.x + cellDim, child.y + cellDim/4); |
103 canvas.lineTo(cellDim, cellDim/4); | 79 canvas.lineTo(child.x + cellDim, child.y + 3*cellDim/4); |
104 canvas.lineTo(cellDim, 3*cellDim/4); | 80 canvas.lineTo(child.x + cellDim/2, child.y + cellDim); |
105 canvas.lineTo(cellDim/2, cellDim); | 81 canvas.moveTo(child.x, child.y + 3*cellDim/4); |
106 canvas.moveTo(0, 3*cellDim/4); | |
107 canvas.closePath(); | 82 canvas.closePath(); |
108 canvas.clip(); | 83 canvas.clip(); |
109 child.paint(canvas); | 84 this.paintChild(child); |
110 } finally { | 85 } finally { |
111 canvas.restore(); | 86 canvas.restore(); |
112 } | 87 } |
113 } | 88 } |
114 loop = children.next(); | 89 loop = children.next(); |
115 } | 90 } |
116 } | 91 } |
117 function inHex(topLeftX, topLeftY, width, height, hitX, hitY) { | 92 function inHex(topLeftX, topLeftY, width, height, hitX, hitY) { |
118 let centerX = topLeftX - width/2; | 93 let centerX = topLeftX - width/2; |
119 let absCenteredHitX = Math.abs(hitX - centerX); | 94 let absCenteredHitX = Math.abs(hitX - centerX); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 div { display: beehive; beehive-count: 3; } | 144 div { display: beehive; beehive-count: 3; } |
170 </style> | 145 </style> |
171 <div> | 146 <div> |
172 <t>Hello</t> | 147 <t>Hello</t> |
173 <t>World</t> | 148 <t>World</t> |
174 <t>How</t> | 149 <t>How</t> |
175 <t>Are</t> | 150 <t>Are</t> |
176 <t>You</t> | 151 <t>You</t> |
177 <t>Today?</t> | 152 <t>Today?</t> |
178 </div> | 153 </div> |
OLD | NEW |