import _ from 'lodash';
export default {
type: 'match-fragment',
definedProperties: {
MatchFragment nodes are part of a Match followed by an optional Repeat node. If no repeat is applied, then rendering is proxied to the content node.
import _ from 'lodash';
export default {
type: 'match-fragment',
definedProperties: {
Default anchor is overridden to apply an transforms from the fragment to its content’s anchor. Essentially, the fragment inherits the anchor of its content.
_anchor: {
get: function() {
var anchor = this.content.getBBox(),
matrix = this.transform().localMatrix;
return {
ax: matrix.x(anchor.ax, anchor.ay),
ax2: matrix.x(anchor.ax2, anchor.ay),
ay: matrix.y(anchor.ax, anchor.ay)
};
}
}
},
Renders the fragment into the currently set container.
_render() {
return this.content.render(this.container.group())
.then(() => {
let box, paths;
Contents must be transformed based on the repeat that is applied.
this.content.transform(this.repeat.contentPosition);
box = this.content.getBBox();
Add skip or repeat paths to the container.
paths = _.flatten([
this.repeat.skipPath(box),
this.repeat.loopPath(box)
]);
let path = this.container.path(paths.join(''));
if (!this.repeat.greedy) {
path.attr({
strokeDasharray: '6,2'
});
}
this.container.prepend(path);
this.loopLabel();
});
},
Renders label for the loop path indicating how many times the content may be matched.
loopLabel() {
let labelStr = this.repeat.label,
tooltipStr = this.repeat.tooltip;
if (labelStr) {
let label = this.container.text(0, 0, [labelStr])
.addClass('repeat-label'),
labelBox = label.getBBox(),
box = this.getBBox();
if (tooltipStr) {
let tooltip = this.container.el('title')
.append(this.container.text(0, 0, tooltipStr));
label.append(tooltip);
}
label.transform(
Snap.matrix().translate(
box.x2 - labelBox.width - (this.repeat.hasSkip ? 5 : 0),
box.y2 + labelBox.height + 10
)
);
}
},
setup() {
Then content of the fragment.
this.content = this.properties.content;
The repetition rule for the fragment.
this.repeat = this.properties.repeat;
if (!this.repeat.hasLoop && !this.repeat.hasSkip) {
For fragments without a skip or loop, rendering is proxied to the content. Also set flag indicating that contents can be merged if the content is a literal node.
this.canMerge = (this.content.type === 'literal');
this.proxy = this.content;
} else {
Fragments that have skip or loop lines cannot be merged with others.
this.canMerge = false;
}
}
};