Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(659)

Side by Side Diff: sky/examples/style/toolbar-layout.sky

Issue 716013002: Specs: Initial hack at extensible style/layout (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sky/examples/style/sky-core-styles.sky ('k') | sky/specs/apis.md » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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.LengthStyleValueType,
14 inherits: true,
15 initialValue: { value: 8, unit: 'px' },
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) {
55 childHeight = child.layoutManager.getIntrinsicHeight();
56 if (childHeight.value < height)
57 childHeight = childHeight.value;
58 else
59 childHeight = height;
60 dims = child.layoutManager.layout(width, 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 return {
128 width: width,
129 height: height,
130 }
131 }
132 function getIntrinsicWidth() {
133 let width = this.node.getProperty('width');
134 if (typeof height != 'number') {
135 let spacing = this.node.getProperty('toolbar-spacing');
136 if (typeof spacing != 'number')
137 spacing = 0;
138 width = 0;
139 let children = this.walkChildren();
140 let loop = children.next();
141 // we exclude the last child because at our ideal width we wouldn't need it
142 let last1 = null; // last one
143 let last2 = null; // one before the last one
144 while (!loop.done) {
145 if (last1)
146 width += last1.layoutManager.getIntrinsicWidth().value;
147 if (last2)
148 width += spacing;
149 last2 = last1;
150 last1 = loop.value;
151 loop = children.next();
152 }
153 }
154 return super(width); // applies and provides our own min-width/max-width ru les
155 }
156 function getIntrinsicHeight() {
157 // we grow our minimum height to be no smaller than the children's
158 let result = super();
159 let determineHeight = false;
160 let heightProperty = this.node.getProperty('height');
161 if (typeof heightProperty != 'number')
162 determineHeight = true;
163 let children = this.walkChildren();
164 let loop = children.next();
165 // here we include the last child so that if it pops in our height doesn't change
166 while (!loop.done) {
167 let child = loop.value;
168 let childHeight = child.layoutManager.getIntrinsicHeight();
169 if (determineHeight) {
170 if (result.value < childHeight.value)
171 result.value = childHeight.value;
172 }
173 if (result.minimum < childHeight.minimum)
174 result.minimum = childHeight.minimum;
175 loop = children.next();
176 }
177 if (result.minimum > result.maximum)
178 result.maximum = result.minimum;
179 if (result.value > result.maximum)
180 result.value = result.maximum;
181 if (result.value < result.minimum)
182 result.value = result.minimum;
183 return result;
184 }
185 function paintChildren(canvas) {
186 let width = this.node.width;
187 let loop = children.next();
188 while ((!loop.done) && (loop.value != this.firstSkippedChild))
189 this.paintChild(loop.value, canvas);
190 if (this.showingOverflow)
191 this.paintChild(this.overflowChild, canvas);
192 }
193 function paintChild(child, canvas) {
194 if (child.needsPaint) {
195 canvas.save();
196 try {
197 canvas.beginPath();
198 canvas.rect(child.x, child.y, child.width, child.height);
199 canvas.clip();
200 child.paint(canvas);
201 } finally {
202 canvas.restore();
203 }
204 }
205 }
206 }
207 sky.registerLayoutManager('toolbar', module.exports.ToolbarLayoutManager);
208 </script>
OLDNEW
« no previous file with comments | « sky/examples/style/sky-core-styles.sky ('k') | sky/specs/apis.md » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698