Refactoring how _position is called to be promise-based

The render method now returns a promise. Once this promise is resolved,
the _position method for that node will be called (if applicable). This
promise must be resolved only after all subordinate nodes have completed
their render phase (the promise returned by subordinate node's render
method has resolved). Node that do not have subordinates can return the
result of calling terminalRender, and proxied renders only need to
return the result of calling proxy.

With this change, it is no longer necessary to explicitly position
subordinate nodes. They will already be positioned once their render
promise is resolved.
This commit is contained in:
Jeff Avallone 2014-12-13 09:09:58 -05:00
parent bc84f68250
commit 773fd5c1a6
12 changed files with 64 additions and 73 deletions

View File

@ -6,5 +6,6 @@ export default _.extend({}, Base, {
_render() {
this.renderLabel('any character');
return this.terminalRender();
}
});

View File

@ -1,4 +1,5 @@
import _ from 'lodash';
import Q from 'q';
export default {
setContainer(container) {
@ -50,37 +51,43 @@ export default {
}
this._labelGroups = [];
this._render();
},
position() {
if (this._proxy) {
this._proxy.position();
} else {
return this._render().then((function() {
if (!this._proxy) {
_.each(this._labelGroups, this.positionLabel.bind(this));
this._position();
}
return this;
}).bind(this));
},
proxy(node) {
this._proxy = node;
this._proxy.render(this.container);
return this._proxy.render(this.container);
},
terminalRender() {
var deferred = Q.defer();
setTimeout(() => { deferred.resolve() });
return deferred.promise;
},
_render() {
console.log(this);
console.log(this.type, this);
this.container.addClass('placeholder');
this.renderLabel(this.textValue)
this.renderLabel(this.type + ': ' + this.textValue)
.select('rect').attr({
rx: 10,
ry: 10
});
return this.terminalRender();
},
_position() {
},
_position() {},
spaceHorizontally(items, options) {
var verticalCenter = 0;

View File

@ -1,4 +1,5 @@
import _ from 'lodash';
import Q from 'q';
import Base from './base.js';
export default _.extend({}, Base, {
@ -9,14 +10,12 @@ export default _.extend({}, Base, {
this.partContainer = this.container.group();
_.each(this.parts.elements, (part => {
part.render(this.partContainer.group());
}).bind(this));
return Q.all(_.map(this.parts.elements, (part => {
return part.render(this.partContainer.group());
}).bind(this)));
},
_position() {
_.invoke(this.parts.elements, 'position');
this.spaceVertically(this.parts.elements, {
padding: 5
});

View File

@ -1,23 +1,23 @@
import _ from 'lodash';
import Q from 'q';
import Base from './base.js';
export default _.extend({}, Base, {
type: 'charset-range',
_render() {
this.first.render(this.container.group());
this.last.render(this.container.group());
this.hyphen = this.container.text()
.attr({
text: '-'
});
return Q.all([
this.first.render(this.container.group()),
this.last.render(this.container.group())
]);
},
_position() {
this.first.position();
this.last.position();
this.spaceHorizontally([this.first, this.hyphen, this.last], {
padding: 5
});

View File

@ -18,6 +18,8 @@ export default _.extend({}, Base, {
rx: 3,
ry: 3
});
return this.terminalRender();
},
// Escape code mappings

View File

@ -10,5 +10,7 @@ export default _.extend({}, Base, {
rx: 3,
ry: 3
});
return this.terminalRender();
}
});

View File

@ -1,4 +1,5 @@
import _ from 'lodash';
import Q from 'q';
import Base from './base.js';
export default _.extend({}, Base, {
@ -18,20 +19,17 @@ export default _.extend({}, Base, {
}
if (this.contents.anchor_start || this.contents.anchor_end || this.contents.parts.length !== 1) {
_.each(this.contents.parts, (function(part) {
part.render(this.container.group());
}).bind(this));
return Q.all(_.map(this.contents.parts, (function(part) {
return part.render(this.container.group());
}).bind(this)));
} else {
this.proxy(this.contents.parts[0]);
return this.proxy(this.contents.parts[0]);
}
},
_position() {
var items;
var items = _(this.contents).at('anchor_start', 'parts', 'anchor_end').flatten().compact().value();
_.invoke(this.contents.parts, 'position');
items = _(this.contents).at('anchor_start', 'parts', 'anchor_end').flatten().compact().value();
this.spaceHorizontally(items, {
padding: 10
});

View File

@ -6,16 +6,15 @@ export default _.extend({}, Base, {
_render() {
if (this._repeat.textValue === '') {
this.proxy(this._content);
return this.proxy(this._content);
} else {
this._content.render(this.container.group());
return this._content.render(this.container.group());
}
},
_position() {
var box, paths = [];
this._content.position();
this._content.transform(this._repeat.contentPosition());
box = this._content.getBBox();

View File

@ -1,4 +1,5 @@
import _ from 'lodash';
import Q from 'q';
import Base from './base.js';
export default _.extend({}, Base, {
@ -8,14 +9,14 @@ export default _.extend({}, Base, {
var matches = this.matches();
if (matches.length === 1) {
this.proxy(matches[0]);
return this.proxy(matches[0]);
} else {
this.matchContainer = this.container.group()
.addClass('regexp-matches');
_.each(matches, (match => {
match.render(this.matchContainer.group());
}).bind(this));
return Q.all(_.map(matches, (match => {
return match.render(this.matchContainer.group());
}).bind(this)));
}
},
@ -24,8 +25,6 @@ export default _.extend({}, Base, {
containerBox,
paths;
_.invoke(matches, 'position');
this.spaceVertically(matches, {
padding: 5
});

View File

@ -5,7 +5,7 @@ export default _.extend({}, Base, {
type: 'root',
_render() {
this.regexp.render(this.container.group());
var promise = this.regexp.render(this.container.group());
this.regexp.transform(Snap.matrix()
.translate(10, 0));
@ -15,14 +15,12 @@ export default _.extend({}, Base, {
this.end = this.container.circle()
.addClass('pin')
.attr({ r: 5 });
return promise;
},
_position() {
var contentBox;
this.regexp.position();
contentBox = this.regexp.getBBox();
var contentBox = this.regexp.getBBox();
this.start.transform(Snap.matrix()
.translate(0, contentBox.cy));

View File

@ -18,15 +18,13 @@ export default _.extend({}, Base, {
if (label) {
this.renderLabeledBox(label);
this.regexp.render(this.container.group());
return this.regexp.render(this.container.group());
} else {
this.proxy(this.regexp);
return this.proxy(this.regexp);
}
},
_position() {
this.regexp.position();
this.positionLabeledBox(this.regexp, {
padding: 10
});

View File

@ -88,18 +88,11 @@ export default class Regexper {
parser.resetGroupCounter();
return Q.fcall(parser.parse.bind(parser), expression)
.then(null, this.showError.bind(this))
.invoke('render', snap.group())
.then((result) => {
result.render(snap.group());
return result;
}, this.showError.bind(this))
.then((result) => {
var deferred = Q.defer();
setTimeout(() => {
var box;
result.position();
box = result.getBBox();
result.container.transform(Snap.matrix()
.translate(padding - box.x, padding - box.y));
@ -107,11 +100,6 @@ export default class Regexper {
width: box.width + padding * 2,
height: box.height + padding * 2
});
deferred.resolve();
});
return deferred.promise;
});
}
}