import { isEmpty } from 'lodash'; import { EdgeStyle } from './EdgeStyle'; import { applyLabelStyleAttributes, cloneLabelStyle, equivalentLabelStyles, LabelStyle } from './LabelStyle'; import { applyLinkStyleAttributes, cloneLinkStyle, equivalentLinkStyles, LinkStyle } from './LinkStyle'; import { NodeStyle } from './NodeStyle'; import { applyShapeAttributes, applyShapeStyleAttributes, cloneShapeStyle, equivalentShapeStyles, ShapeStyle } from './ShapeStyle'; // Helper functions function _isEdgeStyle (style: NodeStyle | EdgeStyle): style is EdgeStyle { return (style as EdgeStyle).groups !== undefined; } function _isNodeStyle (style: NodeStyle | EdgeStyle): style is NodeStyle { return (style as NodeStyle).nodes !== undefined; } // Parsing functions function parseLabelStyles (style: NodeStyle | EdgeStyle): Map { const labelStyles: Map = new Map(); const getData = (style: NodeStyle | EdgeStyle): string[] => { if (_isEdgeStyle(style)) return style.groups; if (_isNodeStyle(style)) return style.nodes; return []; }; const nest = (style: NodeStyle | EdgeStyle, data: string[], parent?: LabelStyle) => { let nextStyle: LabelStyle; let nextData: string[]; // If there's a parent labelstyle, compare it to the current labelstyle if (parent) { // If they are equivalent or this style has no labelstyle, add // current data to parent data and pass down to children if (style.label === undefined || isEmpty(style.label) || equivalentLabelStyles(style.label, parent)) { data.push(...getData(style)); nextData = data; nextStyle = parent; } // If they are not equivalent, fill in any missing attributes from // the parent label style and pass down to chilrent else { nextData = getData(style).slice(); nextStyle = cloneLabelStyle(style.label); applyLabelStyleAttributes(nextStyle, parent); } } else { nextData = [...getData(style)]; nextStyle = cloneLabelStyle(style.label || {}); } if (style.children) { style.children.forEach((child: NodeStyle | EdgeStyle) => { nest(child, nextData, nextStyle); }); } labelStyles.set(nextStyle, nextData); }; nest(style, []); return labelStyles; } function parseLinkStyles (style: EdgeStyle): Map { const linkStyles: Map = new Map(); const nest = (style: EdgeStyle, edges: string[], parent?: LinkStyle) => { let nextStyle: LinkStyle; let nextEdges: string[]; if (parent) { if (style.link === undefined || isEmpty(style.link) || equivalentLinkStyles(style.link, parent)) { edges.push(...style.groups); nextEdges = edges; nextStyle = parent; } else { nextEdges = style.groups.slice(); nextStyle = cloneLinkStyle(style.link); applyLinkStyleAttributes(nextStyle, parent); } } else { nextEdges = [...style.groups]; nextStyle = cloneLinkStyle(style.link || {}); } if (style.children) { style.children.forEach(child => { nest(child, nextEdges, nextStyle); }); } linkStyles.set(nextStyle, nextEdges); }; nest(style, []); return linkStyles; } function parseShapeStyles (style: NodeStyle): Map { const shapeStyles: Map = new Map(); const nest = (style: NodeStyle, nodes: string[], parent?: ShapeStyle) => { let nextStyle: ShapeStyle; let nextNodes: string[]; // If there's a parent shapestyle, compare it to the current shapestyle if (parent) { // If they are equivalent or this nodestyle has no shapestyle, add // current nodes to parent shapestyle's nodes and pass down to // children if (style.shape === undefined || isEmpty(style.shape) || equivalentShapeStyles(style.shape, parent)) { nodes.push(...style.nodes); nextNodes = nodes; nextStyle = parent; } // If they are not equivalent, fill in any missing attributes from // the parent shapestyle and pass down to children else { nextNodes = style.nodes.slice(); nextStyle = cloneShapeStyle(style.shape); applyShapeAttributes(nextStyle, parent); applyShapeStyleAttributes(nextStyle, parent); } } else { nextNodes = [...style.nodes]; nextStyle = cloneShapeStyle(style.shape || {}); } if (style.children) { style.children.forEach(child => { nest(child, nextNodes, nextStyle); }); } shapeStyles.set(nextStyle, nextNodes); }; nest(style, []); return shapeStyles; } export { parseLabelStyles, parseLinkStyles, parseShapeStyles }