You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
canvassed/src/create-composite-object.js

98 lines
2.8 KiB
JavaScript

'use strict';
const dotty = require("dotty");
const defaultValue = require("default-value");
const createObject = require("./create-object");
const createPropertyMapper = require("./property-mapper");
const requireProperties = require("./require-properties");
const max = require("./util/max");
const min = require("./util/min");
function getPosition(object) {
return {
x: defaultValue(object.x, 0),
y: defaultValue(object.y, 0)
}
}
module.exports = function createCompositeObject(options) {
requireProperties(options, ["drawOrder", "objects"]);
let mapProperties = createPropertyMapper(options.propertyMap);
let initialPropertySet = mapProperties(options);
let compositeObject = createObject(Object.assign({
onSet: function setCompositeProperties(properties) {
let mappedProperties = mapProperties(properties);
Object.keys(mappedProperties).forEach((objectName) => {
if (objectName !== "_") {
if (this.objects[objectName] != null) {
this.objects[objectName].set(mappedProperties[objectName]);
} else {
throw new Error(`The object specified in the property map as '${objectName}' does not exist`);
}
}
});
/* We return the `_` object here, which contains all the unmapped
* properties - we assume that all unmapped properties are meant to
* apply to the composite object rather than its child objects. The
* original `.set` method (as defined in createObject) will then use
* this result. */
return defaultValue(mappedProperties._, {});
},
onRender: function onRender(context) {
this.drawOrder.forEach((objectName) => {
let object = this.objects[objectName];
let position = getPosition(object);
object.render(context, {
x: object.x - this.offsetX,
y: object.y - this.offsetY
});
});
},
onRecalculateSize: function onRecalculateSize() {
let objectMetrics = Object.keys(this.objects).map((objectName) => {
let object = this.objects[objectName];
let position = getPosition(object);
return {
x1: position.x,
y1: position.y,
x2: position.x + object.renderWidth,
y2: position.y + object.renderHeight
}
});
let x1 = min(objectMetrics.map(object => object.x1));
let y1 = min(objectMetrics.map(object => object.y1));
let x2 = max(objectMetrics.map(object => object.x2));
let y2 = max(objectMetrics.map(object => object.y2));
this.offsetX = x1;
this.offsetY = y1;
return {
width: x2 - x1,
height: y2 - y1
}
}
}, initialPropertySet._));
Object.keys(compositeObject.objects).forEach((objectName) => {
compositeObject.objects[objectName].on("recalculatedSize", () => {
compositeObject.recalculateSize();
});
compositeObject.objects[objectName].on("bustedCache", () => {
compositeObject.bustCache();
});
});
compositeObject.set(options);
return compositeObject;
};