import defaults from "lodash-es/defaults" ; import isString from "lodash-es/isString" ; import Component , { IComponentConstructor , IContainer } from "./Component" ; import ComponentRegistry from "./ComponentRegistry" ; import IMain from "./IMain" ; import TextureSetManager from "./webgl/TextureSetManager" ; /**
 * A Base class for all Components that have a sub component.
 *
 * Manages, cloning and component tree operations.
 */ export default abstract class Container extends Component implements IContainer { protected components : Component [ ] ; private tsm : TextureSetManager ; /**
     * See [[Component.constructor]]
     */ constructor ( main , parent , opts ) { super ( main , parent , opts ) ; delete this . opts . components ; } /**
     * Returns the TextSetManager for this component.
     *
     * A container inherits TextureSetManager from it's own parent
     * unless explicitly overridden by Subclass
     */ public getTSM ( ) { return this . tsm ; } /**
     * Initializes Container. Please override to implement component specific initialization
     *
     * Container init basically instantiates all subcomponents from the `components` option.
     * It also initializes the TextureSetManager to the parent's.
     */ public init ( ) { const components = [ ] ; if ( this . opts . components ) { for ( const opts of this . opts . components ) { const componentClass = this . main . getComponentRegistry ( ) . getComponentClass ( opts . type ) ; if ( ! componentClass ) { console . warn ( `Unknown ComponentClass: ${ opts . type }. Skipping.` ) ; continue ; } const component = new componentClass ( this . main , this , opts ) ; components . push ( component ) ; } } this . components = components ; this . tsm = this . parent && this . parent . getTSM ( ) ; } /**
     * Destroy all subcomponents and itself.
     */ public destroy ( ) { super . destroy ( ) ; for ( const component of this . components ) { component . destroy ( ) ; } } param componentOpts param pos param params public addComponent ( componentOpts , pos = this . components . length , params = { } ) { let component ; if ( componentOpts instanceof Component ) { component = componentOpts ; component . setParent ( this ) ; } else { const componentClass = this . main . getComponentRegistry ( ) . getComponentClass ( componentOpts . type ) ; if ( ! componentClass ) { console . warn ( `Unknown ComponentClass: ${ componentOpts . type }.` ) ; return null ; } component = new componentClass ( this . main , this , componentOpts ) ; } this . components . splice ( pos , 0 , component ) ; params = defaults ( { pos } , params ) ; this . emit ( "addComponent" , component , this , params ) ; return component ; } param pos param params public detachComponent ( pos , params = { } ) { if ( isString ( pos ) ) { const id = pos ; let i ; for ( i = 0 ; i < this . components . length ; i ++ ) { if ( this . components [ i ] . getId ( ) === id ) { pos = i ; break ; } } if ( i === this . components . length ) { return ; } } const component = this . components [ pos ] ; this . components . splice ( pos , 1 ) ; params = defaults ( { pos } , params ) ; this . emit ( "detachComponent" , component , this , params ) ; return component ; } param id public findComponent ( id ) { for ( const component of this . components ) { if ( component . getId ( ) === id ) { return component ; } } for ( const container of this . components ) { if ( ! ( container instanceof Container ) ) { continue ; } const subComponent = container . findComponent ( id ) ; if ( subComponent ) { return subComponent ; } } } /**
     * Returns the JSON representation of the component options.
     */ public toJSON ( ) { const opts = super . toJSON ( ) ; opts . components = [ ] ; for ( const component of this . components ) { opts . components . push ( component . toJSON ( ) ) ; } return opts ; } param tsm protected setTSM ( tsm ) { this . tsm = tsm ; } }