| OLD | NEW |
| (Empty) |
| 1 SKY MODULE | |
| 2 <import src="sky:core" as="sky"/> | |
| 3 <script> | |
| 4 // display: toolbar; | |
| 5 // toolbar-spacing: <length> | |
| 6 // display: spring; // remaining space is split equally amongst the springs | |
| 7 // children are vertically centered, layout out left-to-right with toolbar-spac
ing space between them | |
| 8 // last child is hidden by default unless there's not enough room for the other
s, then it's shown last, right-aligned | |
| 9 module.exports.SpringLayoutManager = class SpringLayoutManager extends sky.Layo
utManager { } | |
| 10 sky.registerLayoutManager('spring', module.exports.SpringLayoutManager); | |
| 11 sky.registerProperty({ | |
| 12 name: 'toolbar-spacing', | |
| 13 type: sky.PositiveLengthStyleGrammar, | |
| 14 inherits: true, | |
| 15 initialValue: 8, | |
| 16 needsLayout: true, | |
| 17 }); | |
| 18 module.exports.ToolbarLayoutManager = class ToolbarLayoutManager extends sky.La
youtManager { | |
| 19 constructor (styleNode) { | |
| 20 super(styleNode); | |
| 21 this.showingOverflow = false; | |
| 22 this.firstSkippedChild = null; | |
| 23 this.overflowChild = null; | |
| 24 } | |
| 25 function layout(width, height) { | |
| 26 let children = null; | |
| 27 let loop = null; | |
| 28 if (height == null) | |
| 29 height = this.getIntrinsicHeight().value; | |
| 30 if (width == null) | |
| 31 this.assumeDimensions(0, height); | |
| 32 else | |
| 33 this.assumeDimensions(width, height); | |
| 34 let spacing = this.node.getProperty('toolbar-spacing'); | |
| 35 if (typeof spacing != 'number') | |
| 36 spacing = 0; | |
| 37 this.overflowChild = null; | |
| 38 this.firstSkippedChild = null; | |
| 39 | |
| 40 // layout children and figure out whether we need to truncate the child lis
t and show the overflow child | |
| 41 let springCount = 0; | |
| 42 let minX = 0; | |
| 43 let overflowChildWidth = 0; | |
| 44 let pendingSpacing = 0; | |
| 45 children = this.walkChildren(); | |
| 46 loop = children.next(); | |
| 47 while (!loop.done) { | |
| 48 let child = loop.value; | |
| 49 let dims = null; | |
| 50 if (child.layoutManager instanceof module.exports.SpringLayoutManager) { | |
| 51 springCount += 1; | |
| 52 pendingSpacing = spacing; // not +=, because we only have one extra spa
cing per batch of springs | |
| 53 } else { | |
| 54 if (child.needsLayout || child.descendantNeedsLayout) { | |
| 55 childHeight = child.layoutManager.getIntrinsicHeight(); | |
| 56 if (childHeight.value < height) | |
| 57 childHeight = childHeight.value; | |
| 58 else | |
| 59 childHeight = height; | |
| 60 dims = child.layoutManager.layout(null, height); | |
| 61 this.setChildSize(child, dims.width, dims.height); | |
| 62 } else { | |
| 63 dims = { | |
| 64 width: child.width, | |
| 65 height: child.height, | |
| 66 }; | |
| 67 } | |
| 68 loop = children.next(); | |
| 69 if (!loop.done) { | |
| 70 if (minX > 0) | |
| 71 minX += spacing + pendingSpacing; | |
| 72 minX += dims.width; | |
| 73 pendingSpacing = 0; | |
| 74 } else { | |
| 75 overflowChildWidth = spacing + dims.width; | |
| 76 this.overflowChild = child; | |
| 77 } | |
| 78 } | |
| 79 } | |
| 80 | |
| 81 // figure out the spacing | |
| 82 this.showingOverflow = false; | |
| 83 let springSize = 0; | |
| 84 if (width != null) { | |
| 85 if (minX <= width) { | |
| 86 if (springCount > 0) | |
| 87 springSize = (width - minX) / sprintCount; | |
| 88 } else { | |
| 89 this.showingOverflow = true; | |
| 90 } | |
| 91 } else { | |
| 92 width = minX; | |
| 93 } | |
| 94 | |
| 95 // position the children | |
| 96 // TODO(ianh): support rtl toolbars | |
| 97 let x = 0; | |
| 98 let lastWasNonSpring = false; | |
| 99 children = this.walkChildren(); | |
| 100 loop = children.next(); | |
| 101 while (!loop.done) { | |
| 102 let child = loop.value; | |
| 103 if (child.layoutManager instanceof module.exports.SpringLayoutManager) { | |
| 104 x += springSize; | |
| 105 if (lastWasNonSpring) | |
| 106 x += spacing; | |
| 107 lastWasNonSpring = false; | |
| 108 } else { | |
| 109 if (!loop.done) { | |
| 110 if (x + child.width + overflowChildWidth > width) { | |
| 111 this.firstSkippedChild = child; | |
| 112 break; // don't display any more children | |
| 113 } | |
| 114 this.setChildPosition(child, x, (height - child.height)/2); | |
| 115 x += child.width + spacing; | |
| 116 lastWasNonSpring = true; | |
| 117 } else { | |
| 118 // assert: this.showingOverflow == false | |
| 119 } | |
| 120 } | |
| 121 } | |
| 122 if (this.showingOverflow) | |
| 123 this.setChildPosition(this.overflowChild, width-this.overflowChild.width,
(height - this.overflowChild.height)/2); | |
| 124 else | |
| 125 this.firstSkippedChild = this.overflowChild; | |
| 126 | |
| 127 this.markAsLaidOut(); | |
| 128 return { | |
| 129 width: width, | |
| 130 height: height, | |
| 131 } | |
| 132 } | |
| 133 function layoutDescendants() { | |
| 134 this.layout(node.width, node.height); | |
| 135 } | |
| 136 function getIntrinsicWidth() { | |
| 137 let width = this.node.getProperty('width'); | |
| 138 if (typeof width != 'number') { | |
| 139 let spacing = this.node.getProperty('toolbar-spacing'); | |
| 140 if (typeof spacing != 'number') | |
| 141 spacing = 0; | |
| 142 width = 0; | |
| 143 let children = this.walkChildren(); | |
| 144 let loop = children.next(); | |
| 145 // we exclude the last child because at our ideal width we wouldn't need
it | |
| 146 let last1 = null; // last one | |
| 147 let last2 = null; // one before the last one | |
| 148 while (!loop.done) { | |
| 149 if (last1) | |
| 150 width += last1.layoutManager.getIntrinsicWidth().value; | |
| 151 if (last2) | |
| 152 width += spacing; | |
| 153 last2 = last1; | |
| 154 last1 = loop.value; | |
| 155 loop = children.next(); | |
| 156 } | |
| 157 } | |
| 158 return super(width); // applies and provides our own min-width/max-width ru
les | |
| 159 } | |
| 160 function getIntrinsicHeight() { | |
| 161 // we grow our minimum height to be no smaller than the children's | |
| 162 let result = super(); | |
| 163 let determineHeight = false; | |
| 164 let heightProperty = this.node.getProperty('height'); | |
| 165 if (typeof heightProperty != 'number') | |
| 166 determineHeight = true; | |
| 167 let children = this.walkChildren(); | |
| 168 let loop = children.next(); | |
| 169 // here we include the last child so that if it pops in our height doesn't
change | |
| 170 while (!loop.done) { | |
| 171 let child = loop.value; | |
| 172 let childHeight = child.layoutManager.getIntrinsicHeight(); | |
| 173 if (determineHeight) { | |
| 174 if (result.value < childHeight.value) | |
| 175 result.value = childHeight.value; | |
| 176 } | |
| 177 if (result.minimum < childHeight.minimum) | |
| 178 result.minimum = childHeight.minimum; | |
| 179 loop = children.next(); | |
| 180 } | |
| 181 if (result.minimum > result.maximum) | |
| 182 result.maximum = result.minimum; | |
| 183 if (result.value > result.maximum) | |
| 184 result.value = result.maximum; | |
| 185 if (result.value < result.minimum) | |
| 186 result.value = result.minimum; | |
| 187 return result; | |
| 188 } | |
| 189 function paintChildren(canvas) { | |
| 190 let width = this.node.width; | |
| 191 let children = this.walkChildren(); | |
| 192 let loop = children.next(); | |
| 193 while ((!loop.done) && (loop.value != this.firstSkippedChild)) | |
| 194 canvas.paintChild(loop.value); | |
| 195 if (this.showingOverflow) | |
| 196 canvas.paintChild(this.overflowChild); | |
| 197 } | |
| 198 function inChild(child, x, y) { | |
| 199 return (x >= child.x) && (y >= child.y) && (x < child.x+child.width) && (y
< child.y+child.height); | |
| 200 } | |
| 201 function hitTest(x, y) { | |
| 202 let children = this.walkChildrenBackwards(); | |
| 203 let loop = children.next(); | |
| 204 while ((!loop.done) && (loop.value != this.firstSkippedChild)) | |
| 205 if (this.inChild(loop.value, x, y)) | |
| 206 return loop.value; | |
| 207 if (this.showingOverflow) | |
| 208 if (this.inChild(this.overflowChild, x, y)) | |
| 209 return this.overflowChild; | |
| 210 return this.node; | |
| 211 } | |
| 212 } | |
| 213 sky.registerLayoutManager('toolbar', module.exports.ToolbarLayoutManager); | |
| 214 </script> | |
| OLD | NEW |