import { LabelPlacement, LinkLabeller } from '../labellers/LinkLabeller'; import { Link } from '../renderables/Link'; import { LinkLabelRenderer } from '../renderers/labels/LinkLabelRenderer'; import { LinkRenderer } from '../renderers/links/LinkRenderer'; import { NaturalCurveRenderer } from '../renderers/links/NaturalCurveRenderer'; import { ShapeRenderer } from '../renderers/shapes/ShapeRenderer'; import { BundleRouter } from '../routers/BundleRouter'; import { Router } from '../routers/Router'; import { EdgeStyle } from '../styles/EdgeStyle'; import { parseLabelStyles, parseLinkStyles } from '../styles/StyleParsers'; import { Edge } from '../types/Edge'; import { Node } from '../types/Node'; class EdgeManager { private _labeller: LinkLabeller; private _router: Router; private _nodes: Node[]; private _edges: Edge[]; private _shapes: ShapeRenderer[]; private _styles: EdgeStyle[]; private _links: LinkRenderer[]; private _labels: LinkLabelRenderer[]; constructor () { this._labeller = new LinkLabeller(); this._router = new BundleRouter(); this._nodes = []; this._edges = []; this._shapes = []; this._styles = []; this._links = []; this._labels = []; } getEdges (): Edge[] { return this._edges; } getLabelPlacement (): LabelPlacement { return this._labeller.getPlacement(); } getRouter (): Router { return this._router; } labelRenderers (): LinkLabelRenderer[] { return this._labels; } linkRenderers (): LinkRenderer[] { return this._links; } setEdges (edges: Edge[]): this { this._edges = edges; return this; } setLabelPlacement (placement: LabelPlacement): this { this._labeller.setPlacement(placement); return this; } setNodes (nodes: Node[]): this { this._nodes = nodes; return this; } setShapes (shapes: ShapeRenderer[]): this { this._shapes = shapes; return this; } setStyles (styles: EdgeStyle[]): this { this._styles = styles; return this; } update () { // Reroute links this._router.setData(this._nodes, this._edges, this._shapes); // Recalculate renderers this._recalculateRenderers(); } updateEdgesConnectedTo (node: Node) { this._router.updateLinksConnectedTo(node); } private _calculateLabelRenderers (): LinkLabelRenderer[] { // Recalculate label placement this._labeller.setLinkMap(this._router.getLinkMap()); this._labeller.update(); // An array to store renderers const renderers: LinkLabelRenderer[] = []; // Create a set of all links const linkset = new Set(this._router.getLinks()); // Flatten styles and build renderers this._styles.forEach(style => { parseLabelStyles(style).forEach((groups, labelstyle) => { // Create the renderer const labelRenderer = new LinkLabelRenderer(labelstyle); // Get the combined list of links in all groups this // renderer is responsible for const links: Link[] = this._router.getLinks(groups); // Remove these links from the link set links.forEach(link => linkset.delete(link)); // Set the links for this renderer labelRenderer.links(links); // Add to the list of renderers renderers.push(labelRenderer); }); }); // Create a default renderer for links not yet assigned if (linkset.size > 0) { const defaultRenderer = new LinkLabelRenderer(); const remaining = Array.from(linkset.values()); defaultRenderer.links(remaining); renderers.push(defaultRenderer); } return renderers; } private _calculateLinkRenderers (): LinkRenderer[] { // An array to store renderers const renderers: LinkRenderer[] = []; // Create a set of all group names in order to keep track of groups // that have been assigned to a renderer const groupnames = new Set(); this._edges.forEach(edge => { if (edge.group) groupnames.add(edge.group); }); // Flatten styles and build renderers this._styles.forEach(style => { parseLinkStyles(style).forEach((groups, linkStyle) => { // Create the renderer const linkRenderer = new NaturalCurveRenderer(linkStyle); // Get the links associated with these groups const links = this._router.getLinks(groups); // Assign the links to the renderer linkRenderer.links(links); // Add the renderer to the list renderers.push(linkRenderer); // Remove groups from set of group names groups.forEach(group => groupnames.delete(group)); }); }); // Create a default renderer for links that are not part of a // styling or whose group does not have a style defined const defaultRenderer = new NaturalCurveRenderer(); const links = this._router .getLinks(Array.from(groupnames)) .concat(this._router.getUngroupedLinks()); defaultRenderer.links(links); renderers.push(defaultRenderer); return renderers; } private _recalculateRenderers (): void { // Create new renderers this._links = this._calculateLinkRenderers(); this._labels = this._calculateLabelRenderers(); } } export { EdgeManager }