on master help sign in
Stop creating dummy divs around every Element in a collage, fixes ordering issue in elm-at-pldi-2013
b4440adEvan Czaplicki
runtime/Render/Collage.js+39−52
@@ -173,16 +173,16 @@ function str(n) {
173
173
174function makeTransform(w, h, form, matrices) {
174function makeTransform(w, h, form, matrices) {
175 var props = form.form._0.props;
175 var props = form.form._0.props;
176− var m = A6( Transform.matrix, 1, 0, 0, 1,
176+ var m = A6( Transform.matrix, 1, 0, 0, -1,
177− (w - props.width)/2,
177+ (w - props.width ) / 2,
178− (h - props.height)/2 );
178+ (h - props.height) / 2 );
179 var len = matrices.length;
179 var len = matrices.length;
180 for (var i = 0; i < len; ++i) { m = A2( Transform.multiply, m, matrices[i] ); }
180 for (var i = 0; i < len; ++i) { m = A2( Transform.multiply, m, matrices[i] ); }
181 m = A2( Transform.multiply, m, formToMatrix(form) );
181 m = A2( Transform.multiply, m, formToMatrix(form) );
182
182
183− return 'matrix(' + str( m[0]) + ',' + str( m[3]) + ',' +
183+ return 'matrix(' + str( m[0]) + ', ' + str( m[3]) + ', ' +
184− str(-m[1]) + ',' + str(-m[4]) + ',' +
184+ str(-m[1]) + ', ' + str(-m[4]) + ', ' +
185− str( m[2]) + ',' + str( m[5]) + ')';
185+ str( m[2]) + ', ' + str( m[5]) + ')';
186}
186}
187
187
188function stepperHelp(list) {
188function stepperHelp(list) {
@@ -200,7 +200,7 @@ function stepperHelp(list) {
200 return { peekNext:peekNext, next:next };
200 return { peekNext:peekNext, next:next };
201}
201}
202
202
203−function stepper(forms) {
203+function formStepper(forms) {
204 var ps = [stepperHelp(forms)];
204 var ps = [stepperHelp(forms)];
205 var matrices = [];
205 var matrices = [];
206 var alphas = [];
206 var alphas = [];
@@ -253,11 +253,12 @@ function makeCanvas(w,h) {
253
253
254function render(model) {
254function render(model) {
255 var div = newElement('div');
255 var div = newElement('div');
256+ div.style.overflow = 'hidden';
256 update(div, model, model);
257 update(div, model, model);
257 return div;
258 return div;
258}
259}
259
260
260−function updateTracker(w,h,div) {
261+function nodeStepper(w,h,div) {
261 var kids = div.childNodes;
262 var kids = div.childNodes;
262 var i = 0;
263 var i = 0;
263 function transform(transforms, ctx) {
264 function transform(transforms, ctx) {
@@ -271,7 +272,7 @@ function updateTracker(w,h,div) {
271 }
272 }
272 return ctx;
273 return ctx;
273 }
274 }
274− function getContext(transforms) {
275+ function nextContext(transforms) {
275 while (i < kids.length) {
276 while (i < kids.length) {
276 var node = kids[i];
277 var node = kids[i];
277 if (node.getContext) {
278 if (node.getContext) {
@@ -290,75 +291,61 @@ function updateTracker(w,h,div) {
290 ++i;
291 ++i;
291 return transform(transforms, canvas.getContext('2d'));
292 return transform(transforms, canvas.getContext('2d'));
292 }
293 }
293− function element(matrices, alpha, form) {
294+ function addElement(matrices, alpha, form) {
294− var container = kids[i];
295+ var kid = kids[i];
295− if (!container || container.getContext) {
296+ var elem = form.form._0;
296− container = newElement('div');
297− container.style.overflow = 'hidden';
298− container.style.position = 'absolute';
299− addTransform(container.style, 'scaleY(-1)');
300−
301− var kid = kids[i];
302− kid ? div.insertBefore(container, kid)
303− : div.appendChild(container);
304− }
305− // we have added a new node, so we must step our position
306− ++i;
307
297
308− container.style.width = w + 'px';
298+ var node = (!kid || kid.getContext)
309− container.style.height = h + 'px';
299+ ? Render.render(elem)
310− container.style.opacity = alpha * form.alpha;
300+ : (Render.update(kid, kid.oldElement, elem), kids[i]);
311
301
312− var elem = form.form._0;
302+ node.style.position = 'absolute';
313− var node = container.firstChild;
303+ node.style.opacity = alpha * form.alpha;
314− if (node) {
315− Render.update(node, node.oldElement, elem);
316− node = container.firstChild;
317− } else {
318− node = Render.render(elem);
319− container.appendChild(node);
320− }
321− node.oldElement = elem;
322 addTransform(node.style, makeTransform(w, h, form, matrices));
304 addTransform(node.style, makeTransform(w, h, form, matrices));
305+ node.oldElement = elem;
306+ ++i;
307+ if (!kid) {
308+ div.appendChild(node);
309+ } else if (kid.getContext) {
310+ div.insertBefore(node, kid);
311+ }
323 }
312 }
324 function clearRest() {
313 function clearRest() {
325 while (i < kids.length) {
314 while (i < kids.length) {
326 div.removeChild(kids[i]);
315 div.removeChild(kids[i]);
327 }
316 }
328 }
317 }
329− return { getContext:getContext, element:element, clearRest:clearRest };
318+ return { nextContext:nextContext, addElement:addElement, clearRest:clearRest };
330}
319}
331
320
332
321
333function update(div, _, model) {
322function update(div, _, model) {
334 var w = model.w;
323 var w = model.w;
335 var h = model.h;
324 var h = model.h;
336− div.style.width = w + 'px';
325+
337− div.style.height = h + 'px';
326+ var forms = formStepper(model.forms);
338− if (model.forms.ctor === 'Nil') {
327+ var nodes = nodeStepper(w,h,div);
339− while (div.hasChildNodes()) {
340− div.removeChild(div.lastChild);
341− }
342− }
343− var stpr = stepper(model.forms);
344− var tracker = updateTracker(w,h,div);
345 var ctx = null;
328 var ctx = null;
346 var formType = '';
329 var formType = '';
347
330
348− while (formType = stpr.peekNext()) {
331+ while (formType = forms.peekNext()) {
332+ // make sure we have context if we need it
349 if (ctx === null && formType !== 'FElement') {
333 if (ctx === null && formType !== 'FElement') {
350− ctx = tracker.getContext(stpr.transforms());
334+ ctx = nodes.nextContext(forms.transforms());
351− ctx.globalAlpha = stpr.alpha();
335+ ctx.globalAlpha = forms.alpha();
352 }
336 }
337+
353− var form = stpr.next(ctx);
338+ var form = forms.next(ctx);
339+ // if it is FGroup, all updates are made within formStepper when next is called.
354 if (formType === 'FElement') {
340 if (formType === 'FElement') {
341+ // update or insert an element, get a new context
355− tracker.element(stpr.transforms(), stpr.alpha(), form);
342+ nodes.addElement(forms.transforms(), forms.alpha(), form);
356 ctx = null;
343 ctx = null;
357 } else if (formType !== 'FGroup') {
344 } else if (formType !== 'FGroup') {
358 renderForm(function() { update(div, model, model); }, ctx, form);
345 renderForm(function() { update(div, model, model); }, ctx, form);
359 }
346 }
360 }
347 }
361− tracker.clearRest();
348+ nodes.clearRest();
362 return false;
349 return false;
363}
350}
364
351