/**
* @module meteoJS/thermodynamicDiagramPluggable
*/
import { SVG } from '@svgdotjs/svg.js';
import Collection from './base/Collection.js';
import DiagramSounding from './thermodynamicDiagram/DiagramSounding.js';
/**
* Options for the constructor.
*
* @typedef {Object} module:meteoJS/thermodynamicDiagramPluggable~options
* @param {external:HTMLElement} [renderTo] - Element to render diagram into.
* @param {integer} [width=undefined] - Width of the whole container.
* @param {integer} [height=undefined] - Height of the whole container.
*/
/**
* Class to draw a SVG thermodynamic diagram.
*
* <pre><code>import ThermodynamicDiagramPluggable from 'meteojs/thermodynamicDiagramPluggable';</code></pre>
*
* @extends module:meteoJS/base/collection.Collection
*/
export class ThermodynamicDiagramPluggable extends Collection {
/**
* @param {module:meteoJS/thermodynamicDiagram~options} options - Options.
*/
constructor({
renderTo = undefined,
width = undefined,
height = undefined
} = {}) {
super({
fireReplace: false,
fireAddRemoveOnReplace: true,
emptyObjectMaker: () => new DiagramSounding()
});
/**
* @type external:SVG
* @private
*/
this._svgNode =
(renderTo === undefined || 'node' in renderTo || 'instance' in renderTo)
? SVG(renderTo) : SVG().addTo(renderTo);
if (width !== undefined ||
height !== undefined)
this._svgNode.size(width, height);
else if (width === undefined &&
height === undefined &&
renderTo !== undefined &&
'getBoundingClientRect' in renderTo) {
let boundingRect = renderTo.getBoundingClientRect(); // size incl. padding
let computedStyle = window.getComputedStyle(renderTo);
this._svgNode.size(
boundingRect.width -
parseFloat(computedStyle.getPropertyValue('padding-left')) -
parseFloat(computedStyle.getPropertyValue('padding-right')),
boundingRect.height -
parseFloat(computedStyle.getPropertyValue('padding-top')) -
parseFloat(computedStyle.getPropertyValue('padding-bottom'))
);
}
/**
* @type Set.<module:meteoJS/thermodynamicDiagram/plotArea.PlotArea>
* @private
*/
this._plotAreas = new Set();
// PlotAltitudeDataArea objects
this._svgNode.on('mousemove', e => {
for (let plotArea of this._plotAreas)
if ('isHoverLabelsRemote' in plotArea)
plotArea.svgNode.dispatchEvent(e);
});
this._svgNode.on('mouseout', e => {
if (this._svgNode.node === e.target)
for (let plotArea of this._plotAreas)
if ('_hoverLabelsGroup' in plotArea)
plotArea._hoverLabelsGroup.clear();
});
// PlotDataArea objects
this.on('add:item', sounding => {
for (let plotArea of this._plotAreas)
if ('addSounding' in plotArea)
plotArea.addSounding(sounding);
});
this.on('remove:item', sounding => {
for (let plotArea of this._plotAreas)
if ('removeSounding' in plotArea)
plotArea.removeSounding(sounding);
});
}
/**
* SVG object of the complete diagram.
*
* @type external:SVG
* @readonly
*/
get svgNode() {
return this._svgNode;
}
/**
* Appends a PlotArea object to this thermodynamic diagram.
*
* @param {module:meteoJS/thermodynamicDiagram/plotArea.PlotArea} plotArea
* PlotArea object.
* @returns {module:meteoJS/thermodynamicDiagramPluggable.ThermodynamicDiagramPluggable}
* This.
*/
appendPlotArea(plotArea) {
if (this._plotAreas.has(plotArea))
return;
this._plotAreas.add(plotArea);
plotArea.addTo(this.svgNode);
plotArea.onCoordinateSystemChange();
for (let sounding of this)
if ('addSounding' in plotArea)
plotArea.addSounding(sounding);
return this;
}
/**
* Removes a PlotArea object from this thermodynamic diagram.
*
* @param {module:meteoJS/thermodynamicDiagram/plotArea.PlotArea} plotArea
* PlotArea object.
* @returns {module:meteoJS/thermodynamicDiagramPluggable.ThermodynamicDiagramPluggable}
* This.
*/
removePlotArea(plotArea) {
if (!this._plotAreas.has(plotArea))
return;
for (let sounding of this)
plotArea.removeSounding(sounding);
this._plotAreas.delete(plotArea);
return this;
}
/**
* Exchanges the coordinate system in the PlotArea objects. The optional,
* second argument defines an already used coordinate system. If this
* argument is passed, only the coordinate system of the PlotArea's with
* this coordinate system will exchanged.
*
* @param {module:meteoJS/thermodynamicDiagram/coordinateSystem.CoordinateSystem}
* coordinateSystem - Coordinate system.
* @param {module:meteoJS/thermodynamicDiagram/coordinateSystem.CoordinateSystem}
* [formerCoordinateSystem=undefined] - Coordinate system.
*/
exchangeCoordinateSystem(
coordinateSystem,
formerCoordinateSystem = undefined
) {
for (let plotArea of this._plotAreas)
if (formerCoordinateSystem === undefined ||
plotArea.coordinateSystem === formerCoordinateSystem)
plotArea.coordinateSystem = coordinateSystem;
}
/**
* Add a sounding to the diagram.
*
* @param {module:meteoJS/sounding.Sounding} sounding - Sounding object.
* @param {module:meteoJS/thermodynamicDiagram/diagramSounding~options}
* [options] - Display options.
* @returns {module:meteoJS/thermodynamicDiagram/diagramSounding.DiagramSounding}
* Sounding object for the diagram with display options.
*/
addSounding(sounding, options = {}) {
let diagramSounding = new DiagramSounding(sounding, options);
let i = 1;
let id = `sounding-${i}`;
while (this.containsId(id)) {
i++;
id = `sounding-${i}`;
}
diagramSounding.id = id;
this.append(diagramSounding);
return diagramSounding;
}
}
export default ThermodynamicDiagramPluggable;