Make widget use layers for all the SVG
!function() {
LSD.Trait.Layers = new Class({
options: {
layers: {},
events: {
self: {
attach: function() {
this.style.layers = {};
for (var name in this.options.layers) this.addLayer(name, this.options.layers[name]);
}
}
}
},
initialize: function() {
this.offset = {
inside: {},
outside: {},
padding: {}
};
this.layers = {};
this.shapes = {};
this.parent.apply(this, arguments);
},
addLayer: function(name, value) {
var slots = this.style.layers;
var layer = this.layers[name] = LSD.Layer.get(name, Array.concat(value));
for (var i = 0, painter; painter = layer.painters[i++];) {
for (var group = painter.keys, j = 0, property; property = group[j++];) {
if (!slots[property]) slots[property] = [];
slots[property].push(name);
}
}
},
renderLayers: function(dirty) {
var updated = new FastArray, style = this.style, layers = style.layers, offset = this.offset;
for (var property in dirty) if (layers[property]) updated.push.apply(updated, layers[property]);
var result = {};
for (var name in this.layers) {
if (!updated[name]) continue;
var layer = this.layers[name];
var sizes = Object.append({box: this.size}, {size: Object.append({}, this.size)});
result = layer.draw(this, Object.append(result.inside ? {inside: result.inside, outside: result.outside} : {}, sizes))
}
var inside = offset.inside = Object.append({left: 0, right: 0, top: 0, bottom: 0}, result.inside);
var outside = offset.outside = Object.append({left: 0, right: 0, top: 0, bottom: 0}, result.outside);
offset.shape = /*this.shape.getOffset ? this.shape.getOffset(style.current) : */{left: 0, right: 0, top: 0, bottom: 0};
for (var name in this.shapes) {
var layer = this.shapes[name];
if (!layer) continue;
if (!layer.injected) {
for (var layers = Object.keys(this.layers), i = layers.indexOf(layer.name), key, next; key = layers[++i];) {
if ((next = this.layers[key]) && next.injected && next.shape) {
layer.inject(next.shape, 'before');
break;
}
}
if (!layer.injected) layer.inject(this.getCanvas());
layer.injected = true;
}
}
},
render: function() {
var style = this.style, last = style.last, old = style.size, paint = style.paint, changed = style.changed;
this.parent.apply(this, arguments);
this.setSize(this.getStyles('height', 'width'));
var size = this.size;
if (size && (!old || (old.width != size.width || old.height != size.height))) {
this.fireEvent('resize', [size, old]);
changed = paint;
}
if (Object.getLength(changed) > 0) this.renderLayers(changed);
style.changed = {};
style.last = Object.append({}, paint);
style.size = Object.append({}, size);
this.renderOffsets();
},
renderStyles: function() {
this.parent.apply(this, arguments);
var style = this.style, current = style.current;
Object.append(this.offset, {
padding: {left: current.paddingLeft || 0, right: current.paddingRight || 0, top: current.paddingTop || 0, bottom: current.paddingBottom || 0},
margin: {left: current.marginLeft || 0, right: current.marginRight || 0, top: current.marginTop || 0, bottom: current.marginBottom || 0}
});
},
renderOffsets: function() {
var element = this.element,
current = this.style.current,
offset = this.offset, // Offset that is provided by:
inside = offset.inside, // layers, inside the widget
outside = offset.outside, // layers, outside of the widget
shape = offset.shape, // shape
padding = offset.padding, // padding style declarations
margin = offset.margin, // margin style declarations
inner = {}, // all inside offsets above, converted to padding
outer = {}; // all outside offsets above, converted to margin
for (var property in inside) {
var cc = property.capitalize();
if (offset.inner) var last = offset.inner[property];
inner[property] = padding[property] + inside[property] + shape[property] + outside[property];
if (last != null ? last != inner[property] : inner[property]) element.style['padding' + cc] = inner[property] + 'px';
if (offset.outer) last = offset.outer[property];
outer[property] = margin[property] - outside[property];
if (last != null ? last != outer[property] : outer[property]) element.style['margin' + cc] = outer[property] + 'px';
}
if (inside) Object.append(offset, {inner: inner, outer: outer});
}
});
}();