import { removeFromArray } from "../utils/helpers";
import { BaseItem } from "./BaseItem";
import { Item } from "./Item";
/**
* Container
* @extends {Item}
*/
export class Container extends Item {
/**
* Creates an instance of Container.
* @constructor
*/
constructor() {
super();
this.TYPE = Container.TYPE;
this.children = [];
}
/**
* Destruct class
*/
destruct() {
this.empty();
super.destruct();
}
/**
* Emptying the container
*/
empty() {
while (this.children.length) this.removeChildAt(0);
}
/**
* Returns true, if the container contains the BaseItem
* @param {BaseItem} child
* @returns {boolean}
*/
contains(child) {
return this.getChildIndex(child) > -1;
}
/**
* Add BaseItem to the container
* @param {BaseItem} child
*/
addChild(child) {
this.addChildAt(child, this.children.length);
}
/**
* Add BaseItem to a specific index
* @param {BaseItem} child
* @param {number} index
*/
addChildAt(child, index) {
if (child) {
child.parent && child.parent.removeChild(child);
this.children.push(child);
this.setChildIndex(child, index);
child.parent = this;
}
}
/**
* Removes the BaseItem from the container
* @param {BaseItem} child
*/
removeChild(child) {
if (child) {
removeFromArray(this.children, child);
child.parent = null;
}
}
/**
* Removes BaseItem from index
* @param {number} index
*/
removeChildAt(index) {
this.removeChild(this.getChildAt(index));
}
/**
* Returns with a BaseItem from a specific index
* @param {number} index
* @returns {BaseItem}
*/
getChildAt(index) {
return this.children[index];
}
/**
* Set child element index
* @param {BaseItem} child
* @param {number} index
*/
setChildIndex(child, index) {
removeFromArray(this.children, child);
this.children.splice(index, 0, child);
}
/**
* Returns with the child element index
* @param {BaseItem} child
* @returns {number}
*/
getChildIndex(child) {
return this.children.indexOf(child);
}
/**
* Swap two children
* @param {BaseItem} childA
* @param {BaseItem} childB
*/
swapChildren(childA, childB) {
const childAIndex = this.getChildIndex(childA);
const childBIndex = this.getChildIndex(childB);
if (childAIndex > -1 && childBIndex > -1) {
this.setChildIndex(childA, childBIndex);
this.setChildIndex(childB, childAIndex);
}
}
/**
* Returns with the bounds of the container
* @returns {Rectangle}
*/
getBounds() {
const bounds = this.$bounds;
bounds.x = bounds.y = 1 / 0;
bounds.width = bounds.height = -1 / 0;
for (let i = 0, l = this.children.length; i < l; ++i) {
const childBounds = this.children[i].getBounds();
bounds.x = Math.min(bounds.x, childBounds.x);
bounds.y = Math.min(bounds.y, childBounds.y);
bounds.width = Math.max(bounds.width, childBounds.width);
bounds.height = Math.max(bounds.height, childBounds.height);
}
return bounds;
}
/**
* Update container data
*/
update() {
this.$updateProps();
this._updateColor();
}
/**
* Returns with the permultiplied alpha
* @readonly
* @type {number}
*/
get premultipliedAlpha() {
return this.props.alpha * this.$parent.premultipliedAlpha;
}
/**
* @ignore
*/
_updateColor() {
const parent = this.$parent;
const color = this.color;
if (
this.$currentParentColorUpdateId < parent.colorUpdateId ||
this.$currentColorUpdateId < color.updateId
) {
this.$currentColorUpdateId = color.updateId;
this.$currentParentColorUpdateId = parent.colorUpdateId;
++this.colorUpdateId;
const colorCache = this.colorCache;
const parentColorCache = parent.colorCache;
colorCache[0] = parentColorCache[0] * color.r;
colorCache[1] = parentColorCache[1] * color.g;
colorCache[2] = parentColorCache[2] * color.b;
colorCache[3] = parentColorCache[3] * color.a;
}
}
}
/**
* Type "container"
* @string
*/
Container.TYPE = "container";