import Component from '../common/Component' ; import { DEBUG , SN } from '../common/definitions' ; import Timeline from '../Timeline' ; import Axis from '../Axis' ; import AxisBody from '../Axis/AxisBody' ; import AxisScale from '../Axis/AxisScale' ; import AxisMilestone from '../Axis/AxisMilestone' ; import Event from '../Event' ; import EventBody from '../Event/EventBody' ; import EventMark from '../Event/EventMark' ; import EventAxis from '../Event/EventAxis' ; import BreakpointAnimation , { BreakpointAnimationConfig } from './BreakpointAnimation' ; import BoxElementGenerator from './BoxElementGenerator' ; import IdGenerator from './IdGenerator' ; import PositionCounter from './PositionCounter' ; import ConflictFixer from './ConflictFixer' ; export { BoxElementGenerator , IdGenerator , PositionCounter , BreakpointAnimation , ConflictFixer , } ; property property export enum ExtensionType { Debug = 'debug' , DebugOnly = 'debug-only' } export interface Extension { /**
     * Specify the purpose of extension.
     * */ type ? : ExtensionType ; onConstruct ( comp ) : void ; onApply ( comp ) : Promise < void > ; onDraw ( comp ) : void ; onHide ( comp ) : void ; onDestroy ( comp ) : void ; } type ExtensionHandler = 'onConstruct' | 'onApply' | 'onDraw' | 'onHide' | 'onDestroy' ; export interface ExtraData { } const METHODS = [ 'onConstruct' , 'onApply' , 'onDestroy' , 'onHide' , 'onDraw' ] ; /**
 * Manage ExtensionManager#components.
 * */ export class Base implements Partial < Extension > { constructor ( public ext ) { } onConstruct ( comp ) { ( < any > this . ext . components ) [ comp . name ] . push ( comp ) ; } onDestroy ( comp ) { ( < any > this . ext . components ) [ comp . name ] . splice ( ( < any > this . ext . components ) [ comp . name ] . indexOf ( comp ) , 1 ) ; } } export class ExtensionManager implements Extension { constructor ( { breakpointAnimation , disableAll = false , disableAllButDebug = false } = { } ) { this . disableAll = disableAll ; this . disableAllButDebug = disableAllButDebug ; this . breakpoint = new BreakpointAnimation ( this , breakpointAnimation ) ; this . extensions = [ new Base ( this ) , new IdGenerator ( this ) , new BoxElementGenerator ( this ) , new PositionCounter ( this ) , new ConflictFixer ( this ) , this . breakpoint , ] ; } /**
     * Disable all of extensions but enable the extensions supported debug.
     * */ disableAllButDebug : boolean ; /**
     * Disable all of extensions.
     * */ disableAll : boolean ; /**
     * A shared object for every Component.
     * For extends, re-declare the ExtData.
     * */ extraData : ExtraData = { } ; breakpoint : BreakpointAnimation ; components : { [ SN . Timeline ] : Timeline [ ] ; [ SN . Axis ] : Axis [ ] ; [ SN . AxisBody ] : AxisBody [ ] ; [ SN . AxisScale ] : AxisScale [ ] ; [ SN . AxisMilestone ] : AxisMilestone [ ] ; [ SN . Event ] : Event [ ] ; [ SN . EventBody ] : EventBody [ ] ; [ SN . EventMark ] : EventMark [ ] ; [ SN . EventAxis ] : EventAxis [ ] ; } = { [ SN . Timeline ] : [ ] , [ SN . Axis ] : [ ] , [ SN . AxisBody ] : [ ] , [ SN . AxisScale ] : [ ] , [ SN . AxisMilestone ] : [ ] , [ SN . Event ] : [ ] , [ SN . EventBody ] : [ ] , [ SN . EventMark ] : [ ] , [ SN . EventAxis ] : [ ] , } ; extensions : Partial < Extension > [ ] ; getParent ( comp ) ; getParent ( comp ) ; getParent ( comp ) ; getParent ( comp ) { if ( Axis . is ( comp ) ) return this . components [ SN . Timeline ] [ 0 ] ; if ( Event . is ( comp ) ) return this . components [ SN . Timeline ] [ 0 ] ; if ( AxisBody . is ( comp ) ) return this . components [ SN . Axis ] [ 0 ] ; if ( AxisMilestone . is ( comp ) ) return this . components [ SN . Axis ] [ 0 ] ; if ( AxisScale . is ( comp ) ) return this . components [ SN . Axis ] [ 0 ] ; if ( EventBody . is ( comp ) ) return this . components [ SN . Event ] . find ( event => event . body === comp ) ; if ( EventAxis . is ( comp ) ) return this . components [ SN . Event ] . find ( event => event . axis === comp ) ; if ( EventMark . is ( comp ) ) return this . components [ SN . Event ] . find ( event => event . mark === comp ) ; throw new TypeError ( `Cannot find parent of ${ comp . constructor . name }` ) ; } onConstruct = createHandler ( 'onConstruct' , this ) ; onApply = createHandler ( 'onApply' , this ) ; onHide = createHandler ( 'onHide' , this ) ; onDraw = createHandler ( 'onDraw' , this ) ; onDestroy = createHandler ( 'onDestroy' , this ) ; } function createHandler ( methodName , ext ) { return async function extensionManagerMethod ( comp ) { if ( ext . disableAll ) return ; skip_extension : for ( const extension of ext . extensions ) { if ( extension . type === ExtensionType . DebugOnly && ! DEBUG ) continue skip_extension ; if ( ext . disableAllButDebug ) { if ( ! DEBUG ) continue skip_extension ; if ( ! extension . type ) continue skip_extension ; if ( ! [ ExtensionType . DebugOnly , ExtensionType . Debug ] . includes ( extension . type ) ) continue skip_extension ; } if ( methodName in extension ) { if ( methodName === 'onApply' ) { await extension [ methodName ] ! ( comp ) ; } else { extension [ methodName ] ! ( comp ) ; } } } } ; }