mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-05-31 22:40:43 +00:00
Draw interface labels
This commit is contained in:
parent
9fc90bb0eb
commit
a88d829f4d
9
src/app/cartography/shared/models/interface-label.ts
Normal file
9
src/app/cartography/shared/models/interface-label.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
export class InterfaceLabel {
|
||||||
|
constructor(
|
||||||
|
public x: number,
|
||||||
|
public y: number,
|
||||||
|
public text: string,
|
||||||
|
public style: string,
|
||||||
|
public rotation = 0,
|
||||||
|
) {}
|
||||||
|
}
|
100
src/app/cartography/shared/widgets/interface-label.spec.ts
Normal file
100
src/app/cartography/shared/widgets/interface-label.spec.ts
Normal file
@ -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<SVGGElement, Link, SVGGElement, any>;
|
||||||
|
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<SVGGElement, Link>('g.link')
|
||||||
|
.data(links);
|
||||||
|
|
||||||
|
linksEnter = linksSelection
|
||||||
|
.enter()
|
||||||
|
.append<SVGGElement>('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<SVGGElement, InterfaceLabel>('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('');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -1,13 +1,32 @@
|
|||||||
import { SVGSelection } from "../models/types";
|
import { SVGSelection } from "../models/types";
|
||||||
import { Link } from "../models/link";
|
import { Link } from "../models/link";
|
||||||
|
import { InterfaceLabel } from "../models/interface-label";
|
||||||
|
|
||||||
|
|
||||||
export class InterfaceLabelWidget {
|
export class InterfaceLabelWidget {
|
||||||
draw(selection: SVGSelection) {
|
draw(selection: SVGSelection) {
|
||||||
|
|
||||||
const labels = selection
|
const labels = selection
|
||||||
.selectAll<SVGTextElement, Link>('text.interface_label')
|
.selectAll<SVGTextElement, InterfaceLabel>('text.interface_label')
|
||||||
.data((l: Link) => [l]);
|
.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
|
const enter = labels
|
||||||
.enter()
|
.enter()
|
||||||
@ -18,9 +37,11 @@ export class InterfaceLabelWidget {
|
|||||||
.merge(enter);
|
.merge(enter);
|
||||||
|
|
||||||
merge
|
merge
|
||||||
.text((l: Link) => l.nodes[0].label.text)
|
.text((l: InterfaceLabel) => l.text)
|
||||||
.attr('x', (l: Link) => Math.round(l.source.x + l.nodes[0].label.x))
|
.attr('x', (l: InterfaceLabel) => l.x)
|
||||||
.attr('y', (l: Link) => Math.round(l.source.y + l.nodes[0].label.y));
|
.attr('y', (l: InterfaceLabel) => l.y)
|
||||||
|
.attr('style', (l: InterfaceLabel) => l.style)
|
||||||
|
.attr('transform', (l: InterfaceLabel) => `rotate(${l.rotation}, ${l.x}, ${l.y})`);
|
||||||
|
|
||||||
labels
|
labels
|
||||||
.exit()
|
.exit()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user