From a88d829f4de14bfb32976af5dd1407c442186775 Mon Sep 17 00:00:00 2001 From: ziajka Date: Thu, 12 Apr 2018 13:15:25 +0200 Subject: [PATCH] Draw interface labels --- .../shared/models/interface-label.ts | 9 ++ .../shared/widgets/interface-label.spec.ts | 100 ++++++++++++++++++ .../shared/widgets/interface-label.ts | 31 +++++- 3 files changed, 135 insertions(+), 5 deletions(-) create mode 100644 src/app/cartography/shared/models/interface-label.ts create mode 100644 src/app/cartography/shared/widgets/interface-label.spec.ts diff --git a/src/app/cartography/shared/models/interface-label.ts b/src/app/cartography/shared/models/interface-label.ts new file mode 100644 index 00000000..6a222c8e --- /dev/null +++ b/src/app/cartography/shared/models/interface-label.ts @@ -0,0 +1,9 @@ +export class InterfaceLabel { + constructor( + public x: number, + public y: number, + public text: string, + public style: string, + public rotation = 0, + ) {} +} diff --git a/src/app/cartography/shared/widgets/interface-label.spec.ts b/src/app/cartography/shared/widgets/interface-label.spec.ts new file mode 100644 index 00000000..6cf6a693 --- /dev/null +++ b/src/app/cartography/shared/widgets/interface-label.spec.ts @@ -0,0 +1,100 @@ +import { Selection } from "d3-selection"; + +import { TestSVGCanvas } from "../../testing"; +import { LayersWidget } from "./layers"; +import { Layer } from "../models/layer"; +import { Node } from "../models/node"; +import { Link } from "../models/link"; +import { InterfaceLabelWidget } from "./interface-label"; +import { LinkNode } from "../models/link-node"; +import { Label } from "../models/label"; +import { InterfaceLabel } from "../models/interface-label"; + + +describe('InterfaceLabelsWidget', () => { + let svg: TestSVGCanvas; + let widget: InterfaceLabelWidget; + let linksEnter: Selection; + let links: Link[]; + + beforeEach(() => { + svg = new TestSVGCanvas(); + + const node_1 = new Node(); + node_1.node_id = "1"; + node_1.x = 100; + node_1.y = 200; + + const node_2 = new Node(); + node_2.node_id = "2"; + node_2.x = 300; + node_2.y = 400; + + const link_node_1 = new LinkNode(); + link_node_1.label = new Label(); + link_node_1.label.rotation = 5; + link_node_1.label.text = "Interface 1"; + link_node_1.label.x = 10; + link_node_1.label.y = 20; + link_node_1.label.style = "font-size: 12px"; + + const link_node_2 = new LinkNode(); + link_node_2.label = new Label(); + link_node_2.label.rotation = 0; + link_node_2.label.text = "Interface 2"; + link_node_2.label.x = -30; + link_node_2.label.y = -40; + link_node_1.label.style = ""; + + const link_1 = new Link(); + link_1.link_id = "link1"; + link_1.source = node_1; + link_1.target = node_2; + link_1.nodes = [ link_node_1, link_node_2]; + link_1.link_type = "ethernet"; + + links = [link_1]; + + const linksSelection = svg.canvas + .selectAll('g.link') + .data(links); + + linksEnter = linksSelection + .enter() + .append('g') + .attr('class', 'link'); + + linksSelection + .exit() + .remove(); + + widget = new InterfaceLabelWidget(); + }); + + afterEach(() => { + svg.destroy(); + }); + + it('should draw interface labels', () => { + widget.draw(linksEnter); + + const drew = svg.canvas.selectAll('text.interface_label'); + + expect(drew.nodes().length).toEqual(2); + + const sourceInterface = drew.nodes()[0]; + expect(sourceInterface.innerHTML).toEqual('Interface 1'); + expect(sourceInterface.getAttribute('x')).toEqual('110'); + expect(sourceInterface.getAttribute('y')).toEqual('220'); + expect(sourceInterface.getAttribute('transform')).toEqual('rotate(5, 110, 220)'); + expect(sourceInterface.getAttribute('style')).toEqual('font-size: 12px'); + + const targetInterface = drew.nodes()[1]; + expect(targetInterface.innerHTML).toEqual('Interface 2'); + expect(targetInterface.getAttribute('x')).toEqual('270'); + expect(targetInterface.getAttribute('y')).toEqual('360'); + expect(targetInterface.getAttribute('transform')).toEqual('rotate(0, 270, 360)'); + expect(sourceInterface.getAttribute('style')).toEqual(''); + }); + +}); diff --git a/src/app/cartography/shared/widgets/interface-label.ts b/src/app/cartography/shared/widgets/interface-label.ts index 7418f271..c561e995 100644 --- a/src/app/cartography/shared/widgets/interface-label.ts +++ b/src/app/cartography/shared/widgets/interface-label.ts @@ -1,13 +1,32 @@ import { SVGSelection } from "../models/types"; import { Link } from "../models/link"; +import { InterfaceLabel } from "../models/interface-label"; export class InterfaceLabelWidget { draw(selection: SVGSelection) { const labels = selection - .selectAll('text.interface_label') - .data((l: Link) => [l]); + .selectAll('text.interface_label') + .data((l: Link) => { + const sourceInterface = new InterfaceLabel( + Math.round(l.source.x + l.nodes[0].label.x), + Math.round(l.source.y + l.nodes[0].label.y), + l.nodes[0].label.text, + l.nodes[0].label.style, + l.nodes[0].label.rotation + ); + + const targetInterface = new InterfaceLabel( + Math.round(l.target.x + l.nodes[1].label.x), + Math.round(l.target.y + l.nodes[1].label.y), + l.nodes[1].label.text, + l.nodes[1].label.style, + l.nodes[1].label.rotation + ); + + return [sourceInterface, targetInterface]; + }); const enter = labels .enter() @@ -18,9 +37,11 @@ export class InterfaceLabelWidget { .merge(enter); merge - .text((l: Link) => l.nodes[0].label.text) - .attr('x', (l: Link) => Math.round(l.source.x + l.nodes[0].label.x)) - .attr('y', (l: Link) => Math.round(l.source.y + l.nodes[0].label.y)); + .text((l: InterfaceLabel) => l.text) + .attr('x', (l: InterfaceLabel) => l.x) + .attr('y', (l: InterfaceLabel) => l.y) + .attr('style', (l: InterfaceLabel) => l.style) + .attr('transform', (l: InterfaceLabel) => `rotate(${l.rotation}, ${l.x}, ${l.y})`); labels .exit()