Stop creating dummy divs around every Element in a collage, fixes ordering issue in elm-at-pldi-2013

This commit is contained in:
Evan Czaplicki 2013-11-03 02:29:51 +01:00
parent 1e1b0c1281
commit b4440ad607

View file

@ -173,16 +173,16 @@ function str(n) {
function makeTransform(w, h, form, matrices) { function makeTransform(w, h, form, matrices) {
var props = form.form._0.props; var props = form.form._0.props;
var m = A6( Transform.matrix, 1, 0, 0, 1, var m = A6( Transform.matrix, 1, 0, 0, -1,
(w - props.width)/2, (w - props.width ) / 2,
(h - props.height)/2 ); (h - props.height) / 2 );
var len = matrices.length; var len = matrices.length;
for (var i = 0; i < len; ++i) { m = A2( Transform.multiply, m, matrices[i] ); } for (var i = 0; i < len; ++i) { m = A2( Transform.multiply, m, matrices[i] ); }
m = A2( Transform.multiply, m, formToMatrix(form) ); m = A2( Transform.multiply, m, formToMatrix(form) );
return 'matrix(' + str( m[0]) + ',' + str( m[3]) + ',' + return 'matrix(' + str( m[0]) + ', ' + str( m[3]) + ', ' +
str(-m[1]) + ',' + str(-m[4]) + ',' + str(-m[1]) + ', ' + str(-m[4]) + ', ' +
str( m[2]) + ',' + str( m[5]) + ')'; str( m[2]) + ', ' + str( m[5]) + ')';
} }
function stepperHelp(list) { function stepperHelp(list) {
@ -200,7 +200,7 @@ function stepperHelp(list) {
return { peekNext:peekNext, next:next }; return { peekNext:peekNext, next:next };
} }
function stepper(forms) { function formStepper(forms) {
var ps = [stepperHelp(forms)]; var ps = [stepperHelp(forms)];
var matrices = []; var matrices = [];
var alphas = []; var alphas = [];
@ -253,11 +253,12 @@ function makeCanvas(w,h) {
function render(model) { function render(model) {
var div = newElement('div'); var div = newElement('div');
div.style.overflow = 'hidden';
update(div, model, model); update(div, model, model);
return div; return div;
} }
function updateTracker(w,h,div) { function nodeStepper(w,h,div) {
var kids = div.childNodes; var kids = div.childNodes;
var i = 0; var i = 0;
function transform(transforms, ctx) { function transform(transforms, ctx) {
@ -271,7 +272,7 @@ function updateTracker(w,h,div) {
} }
return ctx; return ctx;
} }
function getContext(transforms) { function nextContext(transforms) {
while (i < kids.length) { while (i < kids.length) {
var node = kids[i]; var node = kids[i];
if (node.getContext) { if (node.getContext) {
@ -290,75 +291,61 @@ function updateTracker(w,h,div) {
++i; ++i;
return transform(transforms, canvas.getContext('2d')); return transform(transforms, canvas.getContext('2d'));
} }
function element(matrices, alpha, form) { function addElement(matrices, alpha, form) {
var container = kids[i]; var kid = kids[i];
if (!container || container.getContext) {
container = newElement('div');
container.style.overflow = 'hidden';
container.style.position = 'absolute';
addTransform(container.style, 'scaleY(-1)');
var kid = kids[i];
kid ? div.insertBefore(container, kid)
: div.appendChild(container);
}
// we have added a new node, so we must step our position
++i;
container.style.width = w + 'px';
container.style.height = h + 'px';
container.style.opacity = alpha * form.alpha;
var elem = form.form._0; var elem = form.form._0;
var node = container.firstChild;
if (node) { var node = (!kid || kid.getContext)
Render.update(node, node.oldElement, elem); ? Render.render(elem)
node = container.firstChild; : (Render.update(kid, kid.oldElement, elem), kids[i]);
} else {
node = Render.render(elem); node.style.position = 'absolute';
container.appendChild(node); node.style.opacity = alpha * form.alpha;
}
node.oldElement = elem;
addTransform(node.style, makeTransform(w, h, form, matrices)); addTransform(node.style, makeTransform(w, h, form, matrices));
node.oldElement = elem;
++i;
if (!kid) {
div.appendChild(node);
} else if (kid.getContext) {
div.insertBefore(node, kid);
}
} }
function clearRest() { function clearRest() {
while (i < kids.length) { while (i < kids.length) {
div.removeChild(kids[i]); div.removeChild(kids[i]);
} }
} }
return { getContext:getContext, element:element, clearRest:clearRest }; return { nextContext:nextContext, addElement:addElement, clearRest:clearRest };
} }
function update(div, _, model) { function update(div, _, model) {
var w = model.w; var w = model.w;
var h = model.h; var h = model.h;
div.style.width = w + 'px';
div.style.height = h + 'px'; var forms = formStepper(model.forms);
if (model.forms.ctor === 'Nil') { var nodes = nodeStepper(w,h,div);
while (div.hasChildNodes()) {
div.removeChild(div.lastChild);
}
}
var stpr = stepper(model.forms);
var tracker = updateTracker(w,h,div);
var ctx = null; var ctx = null;
var formType = ''; var formType = '';
while (formType = stpr.peekNext()) { while (formType = forms.peekNext()) {
// make sure we have context if we need it
if (ctx === null && formType !== 'FElement') { if (ctx === null && formType !== 'FElement') {
ctx = tracker.getContext(stpr.transforms()); ctx = nodes.nextContext(forms.transforms());
ctx.globalAlpha = stpr.alpha(); ctx.globalAlpha = forms.alpha();
} }
var form = stpr.next(ctx);
var form = forms.next(ctx);
// if it is FGroup, all updates are made within formStepper when next is called.
if (formType === 'FElement') { if (formType === 'FElement') {
tracker.element(stpr.transforms(), stpr.alpha(), form); // update or insert an element, get a new context
nodes.addElement(forms.transforms(), forms.alpha(), form);
ctx = null; ctx = null;
} else if (formType !== 'FGroup') { } else if (formType !== 'FGroup') {
renderForm(function() { update(div, model, model); }, ctx, form); renderForm(function() { update(div, model, model); }, ctx, form);
} }
} }
tracker.clearRest(); nodes.clearRest();
return false; return false;
} }