import { CanvasSmbl } from '../infrastructure/canvas-smbl.js'; import { PathSmbl } from '../shapes/path-smbl.js'; import { ShapeSmbl } from '../shapes/shape-smbl.js'; import { canvasClear } from './canvas-clear.js'; const v = '1.1'; /** @param {Element} canvas */ export const serialize = (canvas) => serializeShapes(/** @type {Array} */([...canvas.children])); /** @param {Array} shapes */ export function serializeShapes(shapes) { /** @type {DiagramSerialized} */ const diagramSerialized = { v, s: [] }; for (const shape of shapes) { if (shape[ShapeSmbl]) { // shape diagramSerialized.s.push(shape[ShapeSmbl].data); } else { // path /** @param {PathEnd} pathEnd */ function pathSerialize(pathEnd) { const shapeIndex = shapes.indexOf(pathEnd.shape?.shapeEl); return (shapeIndex !== -1) ? { s: shapeIndex, k: pathEnd.shape.connectorKey } : { p: pathEnd.data }; } const pathData = shape[PathSmbl].data; const pathJson = { type: 0, s: pathSerialize(pathData.s), e: pathSerialize(pathData.e) }; if (pathData.styles) { pathJson.c = pathData.styles; } diagramSerialized.s.push(pathJson); } } return diagramSerialized; } /** * @param {CanvasElement} canvas * @param {DiagramSerialized} data * @param {Boolean=} dontClear */ export function deserialize(canvas, data, dontClear) { if (data.v !== v) { alert('Wrong format'); return null; } if (!dontClear) { canvasClear(canvas); } /** @type {Map} */ const shapeDataToElem = new Map(); /** @param {ShapeData} shapeData */ function shapeEnsure(shapeData) { let shapeEl = shapeDataToElem.get(shapeData); if (!shapeEl) { shapeEl = canvas[CanvasSmbl].shapeMap[shapeData.type].create(shapeData); canvas.append(shapeEl); shapeDataToElem.set(shapeData, shapeEl); } return shapeEl; } /** @param {number?} index */ const shapeByIndex = index => shapeEnsure(/** @type {ShapeData} */(data.s[index])); /** @type {PathElement[]} */ const paths = []; for (const shape of data.s) { switch (shape.type) { // path case 0: { /** @param {PathEndSerialized} pathEnd */ const pathDeserialize = pathEnd => pathEnd.p ? { data: pathEnd.p } : { shape: { shapeEl: shapeByIndex(pathEnd.s), connectorKey: pathEnd.k } }; const path = canvas[CanvasSmbl].shapeMap[0].create({ styles: /** @type {PathSerialized} */(shape).c, s: pathDeserialize(/** @type {PathSerialized} */(shape).s), e: pathDeserialize(/** @type {PathSerialized} */(shape).e) }); paths.push(path); canvas.append(path); break; } default: shapeEnsure(/** @type {ShapeData} */(shape)); break; } } return [...shapeDataToElem.values(), ...paths]; } /** @typedef {{v:string, s: Array}} DiagramSerialized */ /** @typedef { import("../shapes/shape-smbl").ShapeElement } ShapeElement */ /** @typedef { import('../shapes/shape-evt-proc').ShapeData } ShapeData */ /** @typedef { import("../shapes/path-smbl").PathElement } PathElement */ /** @typedef { import('../shapes/path').PathEndData } PathEndData */ /** @typedef { import('../shapes/path').PathEnd } PathEnd */ /** @typedef { import('../shapes/path').PathData } PathData */ /** @typedef { {s?:number, k?:string, p?:PathEndData} } PathEndSerialized */ /** @typedef { {type:number, c?:string, s:PathEndSerialized, e:PathEndSerialized} } PathSerialized */ /** @typedef { import('../shapes/shape-evt-proc').CanvasData } CanvasData */ /** @typedef { import('../infrastructure/canvas-smbl.js').CanvasElement } CanvasElement */