UNPKG

@amcharts/amcharts5

Version:
373 lines 11.4 kB
import { EventDispatcher } from "./EventDispatcher"; import { Disposer, MultiDisposer } from "./Disposer"; import * as $array from "./Array"; import * as $object from "./Object"; import * as $type from "./Type"; function disposeSettings(settings) { $object.each(settings, (_key, value) => { if ($type.isObject(value) && typeof value.dispose === "function") { value.enableDispose = true; value.dispose(); } }); } export class TemplateState { constructor(name, template, settings) { this._name = name; this._template = template; this._settings = settings; } _dispose() { disposeSettings(this._settings); } get(key, fallback) { const value = this._settings[key]; if (value !== undefined) { return value; } else { return fallback; } } set(key, value) { this._settings[key] = value; // TODO maybe only do this if the value changed ? this._template._stateChanged(this._name); } remove(key) { delete this._settings[key]; // TODO maybe only do this if the value changed ? this._template._stateChanged(this._name); } setAll(settings) { $object.keys(settings).forEach((key) => { this._settings[key] = settings[key]; }); this._template._stateChanged(this._name); } _apply(other, seen) { $object.each(this._settings, (key, value) => { if (!seen[key] && !other._userSettings[key]) { seen[key] = true; other.setRaw(key, value); // came from a theme, so it is not part of the configuration other._computedSettings[key] = true; } }); } } export class TemplateStates { constructor(template) { this._states = {}; this._template = template; } _dispose() { $object.each(this._states, (_key, state) => { state._dispose(); }); } lookup(name) { return this._states[name]; } create(name, settings) { const state = this._states[name]; if (state) { state.setAll(settings); return state; } else { const state = new TemplateState(name, this._template, settings); this._states[name] = state; this._template._stateChanged(name); return state; } } remove(name) { delete this._states[name]; this._template._stateChanged(name); } _apply(entity, state) { $object.each(this._states, (key, value) => { let seen = state.states[key]; if (seen == null) { seen = state.states[key] = {}; } const other = entity.states.create(key, {}); value._apply(other, seen); }); } } export class TemplateAdapters { constructor() { this._callbacks = {}; } add(key, callback) { let callbacks = this._callbacks[key]; if (callbacks === undefined) { callbacks = this._callbacks[key] = []; } callbacks.push(callback); return new Disposer(() => { $array.removeFirst(callbacks, callback); if (callbacks.length === 0) { delete this._callbacks[key]; } }); } remove(key) { const callbacks = this._callbacks[key]; if (callbacks !== undefined) { delete this._callbacks[key]; } } _apply(entity) { const disposers = []; $object.each(this._callbacks, (key, callbacks) => { $array.each(callbacks, (callback) => { disposers.push(entity.adapters.add(key, callback)); }); }); return new MultiDisposer(disposers); } } // TODO maybe extend from Properties ? export class Template { constructor(settings, isReal) { this._disposed = false; this._privateSettings = {}; this._computedSettings = {}; // TODO code duplication with Properties this._settingEvents = {}; this._privateSettingEvents = {}; this._entities = []; this.states = new TemplateStates(this); this.adapters = new TemplateAdapters(); this.events = new EventDispatcher(); if (!isReal) { throw new Error("You cannot use `new Class()`, instead use `Class.new()`"); } this._settings = settings; } /** * Use this method to create an instance of this class. * * @see {@link https://www.amcharts.com/docs/v5/getting-started/#New_element_syntax} for more info * @param root Root element * @param settings Settings * @param template Template * @return Instantiated object */ static new(settings) { return new Template(settings, true); } _dispose() { disposeSettings(this._settings); disposeSettings(this._privateSettings); } /** * Returns `true` if this element is disposed. * * @return Disposed */ isDisposed() { return this._disposed; } /** * Disposes this object. */ dispose() { if (!this._disposed) { this._disposed = true; this._dispose(); } } _checkDisposed() { if (this._disposed) { throw new Error("Template is disposed"); } } /** * Array of all entities using this template. */ get entities() { return this._entities; } get(key, fallback) { this._checkDisposed(); const value = this._settings[key]; if (value !== undefined) { return value; } else { return fallback; } } setRaw(key, value) { this._checkDisposed(); delete this._computedSettings[key]; this._settings[key] = value; } set(key, value) { this._checkDisposed(); delete this._computedSettings[key]; if (this._settings[key] !== value) { this.setRaw(key, value); this._entities.forEach((entity) => { entity._setTemplateProperty(this, key, value); }); } } /** * Same as `set()`, but for a value the library works out itself rather than * one that was asked for, so that it can be left out when serializing. * * @ignore */ _setC(key, value) { const authored = !this._computedSettings[key] && this._settings[key] === value; this.set(key, value); if (!authored) { this._computedSettings[key] = true; } } /** * Sets multiple computed settings at once. * * @ignore */ _setCAll(settings) { $object.each(settings, (key, value) => { this._setC(key, value); }); } /** * Flags already-set settings as computed, without writing anything. * * @ignore */ _markC(...keys) { $array.each(keys, (key) => { this._computedSettings[key] = true; }); return this; } remove(key) { this._checkDisposed(); if (key in this._settings) { delete this._settings[key]; delete this._computedSettings[key]; this._entities.forEach((entity) => { entity._removeTemplateProperty(key); }); } } removeAll() { this._checkDisposed(); $object.each(this._settings, (key, _value) => { this.remove(key); }); } getPrivate(key, fallback) { this._checkDisposed(); const value = this._privateSettings[key]; if (value !== undefined) { return value; } else { return fallback; } } setPrivateRaw(key, value) { this._checkDisposed(); this._privateSettings[key] = value; return value; } setPrivate(key, value) { this._checkDisposed(); if (this._privateSettings[key] !== value) { this.setPrivateRaw(key, value); this._entities.forEach((entity) => { entity._setTemplatePrivateProperty(this, key, value); }); } return value; } removePrivate(key) { this._checkDisposed(); if (key in this._privateSettings) { delete this._privateSettings[key]; this._entities.forEach((entity) => { entity._removeTemplatePrivateProperty(key); }); } } setAll(value) { this._checkDisposed(); $object.each(value, (key, value) => { this.set(key, value); }); } // TODO code duplication with Properties on(key, callback) { this._checkDisposed(); let events = this._settingEvents[key]; if (events === undefined) { events = this._settingEvents[key] = []; } events.push(callback); return new Disposer(() => { $array.removeFirst(events, callback); if (events.length === 0) { delete this._settingEvents[key]; } }); } // TODO code duplication with Properties onPrivate(key, callback) { this._checkDisposed(); let events = this._privateSettingEvents[key]; if (events === undefined) { events = this._privateSettingEvents[key] = []; } events.push(callback); return new Disposer(() => { $array.removeFirst(events, callback); if (events.length === 0) { delete this._privateSettingEvents[key]; } }); } _apply(entity, state) { this._checkDisposed(); const disposers = []; $object.each(this._settingEvents, (key, events) => { $array.each(events, (event) => { disposers.push(entity.on(key, event)); }); }); $object.each(this._privateSettingEvents, (key, events) => { $array.each(events, (event) => { disposers.push(entity.onPrivate(key, event)); }); }); this.states._apply(entity, state); disposers.push(this.adapters._apply(entity)); disposers.push(entity.events.copyFrom(this.events)); return new MultiDisposer(disposers); } _setObjectTemplate(entity) { this._checkDisposed(); this._entities.push(entity); } _removeObjectTemplate(entity) { //this._checkDisposed(); $array.remove(this._entities, entity); } _stateChanged(name) { this._checkDisposed(); this._entities.forEach((entity) => { entity._applyStateByKey(name); }); } } //# sourceMappingURL=Template.js.map