mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-06-18 06:48:09 +00:00
Precalculate labels position in converters
This commit is contained in:
@ -39,6 +39,8 @@ import { SelectionControlComponent } from './components/selection-control/select
|
|||||||
import { SelectionSelectComponent } from './components/selection-select/selection-select.component';
|
import { SelectionSelectComponent } from './components/selection-select/selection-select.component';
|
||||||
import { DraggableSelectionComponent } from './components/draggable-selection/draggable-selection.component';
|
import { DraggableSelectionComponent } from './components/draggable-selection/draggable-selection.component';
|
||||||
import { MapSettingsManager } from './managers/map-settings-manager';
|
import { MapSettingsManager } from './managers/map-settings-manager';
|
||||||
|
import { FontBBoxCalculator } from './helpers/font-bbox-calculator';
|
||||||
|
import { StylesToFontConverter } from './converters/styles-to-font-converter';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -89,6 +91,8 @@ import { MapSettingsManager } from './managers/map-settings-manager';
|
|||||||
MapSymbolsDataSource,
|
MapSymbolsDataSource,
|
||||||
SelectionEventSource,
|
SelectionEventSource,
|
||||||
MapSettingsManager,
|
MapSettingsManager,
|
||||||
|
FontBBoxCalculator,
|
||||||
|
StylesToFontConverter,
|
||||||
...D3_MAP_IMPORTS
|
...D3_MAP_IMPORTS
|
||||||
],
|
],
|
||||||
exports: [ D3MapComponent, ExperimentalMapComponent ]
|
exports: [ D3MapComponent, ExperimentalMapComponent ]
|
||||||
|
@ -3,10 +3,18 @@ import { Injectable } from "@angular/core";
|
|||||||
import { Converter } from "../converter";
|
import { Converter } from "../converter";
|
||||||
import { Label } from "../../models/label";
|
import { Label } from "../../models/label";
|
||||||
import { MapLabel } from "../../models/map/map-label";
|
import { MapLabel } from "../../models/map/map-label";
|
||||||
|
import { FontBBoxCalculator } from '../../helpers/font-bbox-calculator';
|
||||||
|
import { CssFixer } from '../../helpers/css-fixer';
|
||||||
|
import { FontFixer } from '../../helpers/font-fixer';
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LabelToMapLabelConverter implements Converter<Label, MapLabel> {
|
export class LabelToMapLabelConverter implements Converter<Label, MapLabel> {
|
||||||
|
constructor(
|
||||||
|
private fontBBoxCalculator: FontBBoxCalculator,
|
||||||
|
private cssFixer: CssFixer,
|
||||||
|
private fontFixer: FontFixer
|
||||||
|
) {}
|
||||||
convert(label: Label, paramaters?: {[node_id: string]: string}) {
|
convert(label: Label, paramaters?: {[node_id: string]: string}) {
|
||||||
const mapLabel = new MapLabel();
|
const mapLabel = new MapLabel();
|
||||||
mapLabel.rotation = label.rotation;
|
mapLabel.rotation = label.rotation;
|
||||||
@ -14,10 +22,26 @@ export class LabelToMapLabelConverter implements Converter<Label, MapLabel> {
|
|||||||
mapLabel.text = label.text;
|
mapLabel.text = label.text;
|
||||||
mapLabel.x = label.x;
|
mapLabel.x = label.x;
|
||||||
mapLabel.y = label.y;
|
mapLabel.y = label.y;
|
||||||
|
mapLabel.originalX = label.x;
|
||||||
|
mapLabel.originalY = label.y;
|
||||||
|
|
||||||
if (paramaters !== undefined) {
|
if (paramaters !== undefined) {
|
||||||
mapLabel.id = paramaters.node_id;
|
mapLabel.id = paramaters.node_id;
|
||||||
mapLabel.nodeId = paramaters.node_id;
|
mapLabel.nodeId = paramaters.node_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fixedCss = this.cssFixer.fix(mapLabel.style);
|
||||||
|
const fixedFont = this.fontFixer.fixStyles(fixedCss);
|
||||||
|
const box = this.fontBBoxCalculator.calculate(mapLabel.text, fixedFont);
|
||||||
|
|
||||||
|
if (mapLabel.x !== null) {
|
||||||
|
mapLabel.x += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapLabel.y !== null) {
|
||||||
|
mapLabel.y += box.height;
|
||||||
|
}
|
||||||
|
|
||||||
return mapLabel;
|
return mapLabel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,33 @@ import { Injectable } from "@angular/core";
|
|||||||
import { Converter } from "../converter";
|
import { Converter } from "../converter";
|
||||||
import { Label } from "../../models/label";
|
import { Label } from "../../models/label";
|
||||||
import { MapLabel } from "../../models/map/map-label";
|
import { MapLabel } from "../../models/map/map-label";
|
||||||
|
import { FontBBoxCalculator } from '../../helpers/font-bbox-calculator';
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MapLabelToLabelConverter implements Converter<MapLabel, Label> {
|
export class MapLabelToLabelConverter implements Converter<MapLabel, Label> {
|
||||||
|
constructor(
|
||||||
|
private fontBBoxCalculator: FontBBoxCalculator
|
||||||
|
) {}
|
||||||
|
|
||||||
convert(mapLabel: MapLabel) {
|
convert(mapLabel: MapLabel) {
|
||||||
|
const box = this.fontBBoxCalculator.calculate(mapLabel.text, mapLabel.style);
|
||||||
|
|
||||||
const label = new Label();
|
const label = new Label();
|
||||||
label.rotation = mapLabel.rotation;
|
label.rotation = mapLabel.rotation;
|
||||||
label.style = mapLabel.style;
|
label.style = mapLabel.style;
|
||||||
label.text = mapLabel.text;
|
label.text = mapLabel.text;
|
||||||
label.x = mapLabel.x;
|
label.x = mapLabel.x;
|
||||||
label.y = mapLabel.y;
|
label.y = mapLabel.y;
|
||||||
|
|
||||||
|
if (label.x !== null) {
|
||||||
|
label.x += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (label.y !== null) {
|
||||||
|
label.y -= box.height;
|
||||||
|
}
|
||||||
|
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,38 +5,41 @@ import { MapNode } from "../../models/map/map-node";
|
|||||||
import { MapLabelToLabelConverter } from "./map-label-to-label-converter";
|
import { MapLabelToLabelConverter } from "./map-label-to-label-converter";
|
||||||
import { MapPortToPortConverter } from "./map-port-to-port-converter";
|
import { MapPortToPortConverter } from "./map-port-to-port-converter";
|
||||||
import { Node } from "../../models/node";
|
import { Node } from "../../models/node";
|
||||||
|
import { FontBBoxCalculator } from '../../helpers/font-bbox-calculator';
|
||||||
|
import { CssFixer } from '../../helpers/css-fixer';
|
||||||
|
import { FontFixer } from '../../helpers/font-fixer';
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MapNodeToNodeConverter implements Converter<MapNode, Node> {
|
export class MapNodeToNodeConverter implements Converter<MapNode, Node> {
|
||||||
constructor(
|
constructor(
|
||||||
private mapLabelToLabel: MapLabelToLabelConverter,
|
private mapLabelToLabel: MapLabelToLabelConverter,
|
||||||
private mapPortToPort: MapPortToPortConverter
|
private mapPortToPort: MapPortToPortConverter
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
convert(mapNode: MapNode) {
|
convert(mapNode: MapNode) {
|
||||||
const node = new Node();
|
const node = new Node();
|
||||||
node.node_id = mapNode.id;
|
node.node_id = mapNode.id;
|
||||||
node.command_line = mapNode.commandLine;
|
node.command_line = mapNode.commandLine;
|
||||||
node.compute_id = mapNode.computeId;
|
node.compute_id = mapNode.computeId;
|
||||||
node.console = mapNode.console;
|
node.console = mapNode.console;
|
||||||
node.console_host = mapNode.consoleHost;
|
node.console_host = mapNode.consoleHost;
|
||||||
node.first_port_name = mapNode.firstPortName;
|
node.first_port_name = mapNode.firstPortName;
|
||||||
node.height = mapNode.height;
|
node.height = mapNode.height;
|
||||||
node.label = mapNode.label ? this.mapLabelToLabel.convert(mapNode.label) : undefined;
|
node.label = mapNode.label ? this.mapLabelToLabel.convert(mapNode.label) : undefined;
|
||||||
node.name = mapNode.name;
|
node.name = mapNode.name;
|
||||||
node.node_directory = mapNode.nodeDirectory;
|
node.node_directory = mapNode.nodeDirectory;
|
||||||
node.node_type = mapNode.nodeType;
|
node.node_type = mapNode.nodeType;
|
||||||
node.port_name_format = mapNode.portNameFormat;
|
node.port_name_format = mapNode.portNameFormat;
|
||||||
node.port_segment_size = mapNode.portSegmentSize;
|
node.port_segment_size = mapNode.portSegmentSize;
|
||||||
node.ports = mapNode.ports ? mapNode.ports.map((mapPort) => this.mapPortToPort.convert(mapPort)) : [];
|
node.ports = mapNode.ports ? mapNode.ports.map((mapPort) => this.mapPortToPort.convert(mapPort)) : [];
|
||||||
node.project_id = mapNode.projectId;
|
node.project_id = mapNode.projectId;
|
||||||
node.status = mapNode.status;
|
node.status = mapNode.status;
|
||||||
node.symbol = mapNode.symbol;
|
node.symbol = mapNode.symbol;
|
||||||
node.width = mapNode.width;
|
node.width = mapNode.width;
|
||||||
node.x = mapNode.x;
|
node.x = mapNode.x;
|
||||||
node.y = mapNode.y;
|
node.y = mapNode.y;
|
||||||
node.z = mapNode.z;
|
node.z = mapNode.z;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,38 +5,56 @@ import { MapNode } from "../../models/map/map-node";
|
|||||||
import { Node } from "../../models/node";
|
import { Node } from "../../models/node";
|
||||||
import { LabelToMapLabelConverter } from "./label-to-map-label-converter";
|
import { LabelToMapLabelConverter } from "./label-to-map-label-converter";
|
||||||
import { PortToMapPortConverter } from "./port-to-map-port-converter";
|
import { PortToMapPortConverter } from "./port-to-map-port-converter";
|
||||||
|
import { FontBBoxCalculator } from '../../helpers/font-bbox-calculator';
|
||||||
|
import { CssFixer } from '../../helpers/css-fixer';
|
||||||
|
import { FontFixer } from '../../helpers/font-fixer';
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class NodeToMapNodeConverter implements Converter<Node, MapNode> {
|
export class NodeToMapNodeConverter implements Converter<Node, MapNode> {
|
||||||
constructor(
|
constructor(
|
||||||
private labelToMapLabel: LabelToMapLabelConverter,
|
private labelToMapLabel: LabelToMapLabelConverter,
|
||||||
private portToMapPort: PortToMapPortConverter
|
private portToMapPort: PortToMapPortConverter,
|
||||||
) {}
|
private fontBBoxCalculator: FontBBoxCalculator,
|
||||||
|
private cssFixer: CssFixer,
|
||||||
|
private fontFixer: FontFixer
|
||||||
|
) {}
|
||||||
|
|
||||||
convert(node: Node) {
|
convert(node: Node) {
|
||||||
const mapNode = new MapNode();
|
const mapNode = new MapNode();
|
||||||
mapNode.id = node.node_id;
|
mapNode.id = node.node_id;
|
||||||
mapNode.commandLine = node.command_line;
|
mapNode.commandLine = node.command_line;
|
||||||
mapNode.computeId = node.compute_id;
|
mapNode.computeId = node.compute_id;
|
||||||
mapNode.console = node.console;
|
mapNode.console = node.console;
|
||||||
mapNode.consoleHost = node.console_host;
|
mapNode.consoleHost = node.console_host;
|
||||||
mapNode.firstPortName = node.first_port_name;
|
mapNode.firstPortName = node.first_port_name;
|
||||||
mapNode.height = node.height;
|
mapNode.height = node.height;
|
||||||
mapNode.label = this.labelToMapLabel.convert(node.label, { node_id: node.node_id });
|
mapNode.label = this.labelToMapLabel.convert(node.label, { node_id: node.node_id });
|
||||||
mapNode.name = node.name;
|
mapNode.name = node.name;
|
||||||
mapNode.nodeDirectory = node.node_directory;
|
mapNode.nodeDirectory = node.node_directory;
|
||||||
mapNode.nodeType = node.node_type;
|
mapNode.nodeType = node.node_type;
|
||||||
mapNode.portNameFormat = node.port_name_format;
|
mapNode.portNameFormat = node.port_name_format;
|
||||||
mapNode.portSegmentSize = node.port_segment_size;
|
mapNode.portSegmentSize = node.port_segment_size;
|
||||||
mapNode.ports = node.ports.map((port) => this.portToMapPort.convert(port));
|
mapNode.ports = node.ports.map((port) => this.portToMapPort.convert(port));
|
||||||
mapNode.projectId = node.project_id;
|
mapNode.projectId = node.project_id;
|
||||||
mapNode.status = node.status;
|
mapNode.status = node.status;
|
||||||
mapNode.symbol = node.symbol;
|
mapNode.symbol = node.symbol;
|
||||||
mapNode.width = node.width;
|
mapNode.width = node.width;
|
||||||
mapNode.x = node.x;
|
mapNode.x = node.x;
|
||||||
mapNode.y = node.y;
|
mapNode.y = node.y;
|
||||||
mapNode.z = node.z;
|
mapNode.z = node.z;
|
||||||
return mapNode;
|
|
||||||
|
|
||||||
|
if (mapNode.label !== undefined) {
|
||||||
|
const fixedCss = this.cssFixer.fix(mapNode.label.style);
|
||||||
|
const fixedFont = this.fontFixer.fixStyles(fixedCss);
|
||||||
|
const box = this.fontBBoxCalculator.calculate(mapNode.label.text, fixedFont);
|
||||||
|
|
||||||
|
if (node.label.x === null || node.label.y === null) {
|
||||||
|
mapNode.label.x = node.width / 2. - box.width / 2. + 3;
|
||||||
|
mapNode.label.y = -8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return mapNode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
import { Font } from "../models/font";
|
||||||
|
import { StylesToFontConverter } from './styles-to-font-converter';
|
||||||
|
|
||||||
|
|
||||||
|
describe('StylesToFontConverter', () => {
|
||||||
|
let converter: StylesToFontConverter;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
converter = new StylesToFontConverter();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should parse fonts from styles', () => {
|
||||||
|
const styles = "font-family: TypeWriter; font-size: 10px; font-weight: bold";
|
||||||
|
|
||||||
|
const expectedFont: Font = {
|
||||||
|
'font_family': 'TypeWriter',
|
||||||
|
'font_size': 10,
|
||||||
|
'font_weight': 'bold'
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(converter.convert(styles)).toEqual(expectedFont);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
47
src/app/cartography/converters/styles-to-font-converter.ts
Normal file
47
src/app/cartography/converters/styles-to-font-converter.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import * as csstree from 'css-tree';
|
||||||
|
|
||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
import { Converter } from './converter';
|
||||||
|
import { Font } from '../models/font';
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class StylesToFontConverter implements Converter<string, Font> {
|
||||||
|
convert(styles: string) {
|
||||||
|
const font: Font = {
|
||||||
|
'font_family': undefined,
|
||||||
|
'font_size': undefined,
|
||||||
|
'font_weight': undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
const ast = csstree.parse(styles, {
|
||||||
|
'context': 'declarationList'
|
||||||
|
});
|
||||||
|
|
||||||
|
ast.children.forEach((child) => {
|
||||||
|
if (child.property === 'font-size') {
|
||||||
|
child.value.children.forEach((value) => {
|
||||||
|
if (value.type === 'Dimension') {
|
||||||
|
font.font_size = parseInt(value.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (child.property === 'font-family') {
|
||||||
|
child.value.children.forEach((value) => {
|
||||||
|
if (value.type === "Identifier") {
|
||||||
|
font.font_family = value.name;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (child.property === 'font-weight') {
|
||||||
|
child.value.children.forEach((value) => {
|
||||||
|
if (value.type === "Identifier") {
|
||||||
|
font.font_weight = value.name;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
}
|
@ -62,7 +62,6 @@ export class Draggable<GElement extends DraggedElementBaseType, Datum> {
|
|||||||
const evt = new DraggableDrag<Datum>(datum);
|
const evt = new DraggableDrag<Datum>(datum);
|
||||||
evt.dx = event.sourceEvent.clientX - lastX;
|
evt.dx = event.sourceEvent.clientX - lastX;
|
||||||
evt.dy = event.sourceEvent.clientY - lastY;
|
evt.dy = event.sourceEvent.clientY - lastY;
|
||||||
|
|
||||||
lastX = event.sourceEvent.clientX;
|
lastX = event.sourceEvent.clientX;
|
||||||
lastY = event.sourceEvent.clientY;
|
lastY = event.sourceEvent.clientY;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import { Injectable } from "@angular/core";
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class CssFixer {
|
export class CssFixer {
|
||||||
|
|
||||||
public fix(styles: string) {
|
public fix(styles: string): string {
|
||||||
const ast = csstree.parse(styles, {
|
const ast = csstree.parse(styles, {
|
||||||
'context': 'declarationList'
|
'context': 'declarationList'
|
||||||
});
|
});
|
||||||
|
24
src/app/cartography/helpers/font-bbox-calculator.spec.ts
Normal file
24
src/app/cartography/helpers/font-bbox-calculator.spec.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { FontBBoxCalculator } from "./font-bbox-calculator";
|
||||||
|
|
||||||
|
|
||||||
|
describe('FontBBoxCalculator', () => {
|
||||||
|
let calculator: FontBBoxCalculator;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
calculator = new FontBBoxCalculator();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should calculate font width and height', () => {
|
||||||
|
const box = calculator.calculate("My text", "font-family:Arial; font-size: 12px; font-weight:bold");
|
||||||
|
|
||||||
|
expect(box.height).toEqual(14);
|
||||||
|
expect(box.width).toEqual(41.34375);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should calculate font width and height for different font', () => {
|
||||||
|
const box = calculator.calculate("My text", "font-family:Tahoma; font-size: 14px; font-weight:bold");
|
||||||
|
|
||||||
|
expect(box.height).toEqual(15);
|
||||||
|
expect(box.width).toEqual(46.25);
|
||||||
|
});
|
||||||
|
});
|
20
src/app/cartography/helpers/font-bbox-calculator.ts
Normal file
20
src/app/cartography/helpers/font-bbox-calculator.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class FontBBoxCalculator {
|
||||||
|
calculate(text: string, styles: string) {
|
||||||
|
const element = document.createElement("text");
|
||||||
|
element.innerText = text;
|
||||||
|
element.setAttribute("fill", "#00000");
|
||||||
|
element.setAttribute("fill-opacity", "0");
|
||||||
|
element.setAttribute("style", styles);
|
||||||
|
document.documentElement.appendChild(element);
|
||||||
|
const bbox = element.getBoundingClientRect();
|
||||||
|
document.documentElement.removeChild(element);
|
||||||
|
|
||||||
|
return {
|
||||||
|
width: bbox.width,
|
||||||
|
height: bbox.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,5 +7,7 @@ export class MapLabel implements Indexed {
|
|||||||
text: string;
|
text: string;
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
|
originalX: number;
|
||||||
|
originalY: number;
|
||||||
nodeId: string;
|
nodeId: string;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ export class LabelWidget implements Widget {
|
|||||||
private cssFixer: CssFixer,
|
private cssFixer: CssFixer,
|
||||||
private fontFixer: FontFixer,
|
private fontFixer: FontFixer,
|
||||||
private selectionManager: SelectionManager,
|
private selectionManager: SelectionManager,
|
||||||
private mapSettings: MapSettingsManager,
|
private mapSettings: MapSettingsManager
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public redrawLabel(view: SVGSelection, label: MapLabel) {
|
public redrawLabel(view: SVGSelection, label: MapLabel) {
|
||||||
@ -56,6 +56,8 @@ export class LabelWidget implements Widget {
|
|||||||
|
|
||||||
|
|
||||||
private drawLabel(view: SVGSelection) {
|
private drawLabel(view: SVGSelection) {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
const label_body = view.selectAll<SVGGElement, MapLabel>("g.label_body")
|
const label_body = view.selectAll<SVGGElement, MapLabel>("g.label_body")
|
||||||
.data((label) => [label]);
|
.data((label) => [label]);
|
||||||
|
|
||||||
@ -77,31 +79,14 @@ export class LabelWidget implements Widget {
|
|||||||
label_body_merge
|
label_body_merge
|
||||||
.select<SVGTextElement>('text.label')
|
.select<SVGTextElement>('text.label')
|
||||||
.attr('label_id', (l: MapLabel) => l.id)
|
.attr('label_id', (l: MapLabel) => l.id)
|
||||||
// .attr('y', (n: Node) => n.label.y - n.height / 2. + 10) // @todo: server computes y in auto way
|
|
||||||
.attr('style', (l: MapLabel) => {
|
.attr('style', (l: MapLabel) => {
|
||||||
let styles = this.cssFixer.fix(l.style);
|
let styles = this.cssFixer.fix(l.style);
|
||||||
styles = this.fontFixer.fixStyles(styles);
|
styles = this.fontFixer.fixStyles(styles);
|
||||||
return styles;
|
return styles;
|
||||||
})
|
})
|
||||||
.text((l: MapLabel) => l.text)
|
.text((l: MapLabel) => l.text)
|
||||||
.attr('x', function (this: SVGTextElement, l: MapLabel) {
|
.attr('x', (l: MapLabel) => l.x)
|
||||||
// if (l.x === null) {
|
.attr('y', (l: MapLabel) => l.y)
|
||||||
// // center
|
|
||||||
// const bbox = this.getBBox();
|
|
||||||
// return -bbox.width / 2.;
|
|
||||||
// }
|
|
||||||
return l.x + LabelWidget.NODE_LABEL_MARGIN;
|
|
||||||
})
|
|
||||||
.attr('y', function (this: SVGTextElement, l: MapLabel) {
|
|
||||||
let bbox = this.getBBox();
|
|
||||||
|
|
||||||
// if (n.label.x === null) {
|
|
||||||
// // center
|
|
||||||
// bbox = this.getBBox();
|
|
||||||
// return - n.height / 2. - bbox.height ;
|
|
||||||
// }
|
|
||||||
return l.y + bbox.height - LabelWidget.NODE_LABEL_MARGIN - bbox.height*0.14;
|
|
||||||
})
|
|
||||||
.attr('transform', (l: MapLabel) => {
|
.attr('transform', (l: MapLabel) => {
|
||||||
return `rotate(${l.rotation}, ${l.x}, ${l.y})`;
|
return `rotate(${l.rotation}, ${l.x}, ${l.y})`;
|
||||||
})
|
})
|
||||||
|
@ -23,6 +23,9 @@ import { MapNode } from '../../../cartography/models/map/map-node';
|
|||||||
import { MapLabelToLabelConverter } from '../../../cartography/converters/map/map-label-to-label-converter';
|
import { MapLabelToLabelConverter } from '../../../cartography/converters/map/map-label-to-label-converter';
|
||||||
import { MapPortToPortConverter } from '../../../cartography/converters/map/map-port-to-port-converter';
|
import { MapPortToPortConverter } from '../../../cartography/converters/map/map-port-to-port-converter';
|
||||||
import { Node } from '../../../cartography/models/node';
|
import { Node } from '../../../cartography/models/node';
|
||||||
|
import { FontBBoxCalculator } from '../../../cartography/helpers/font-bbox-calculator';
|
||||||
|
import { CssFixer } from '../../../cartography/helpers/css-fixer';
|
||||||
|
import { FontFixer } from '../../../cartography/helpers/font-fixer';
|
||||||
|
|
||||||
|
|
||||||
describe('ProjectMapShortcutsComponent', () => {
|
describe('ProjectMapShortcutsComponent', () => {
|
||||||
@ -56,7 +59,11 @@ describe('ProjectMapShortcutsComponent', () => {
|
|||||||
SettingsService,
|
SettingsService,
|
||||||
MapNodeToNodeConverter,
|
MapNodeToNodeConverter,
|
||||||
MapLabelToLabelConverter,
|
MapLabelToLabelConverter,
|
||||||
MapPortToPortConverter
|
MapPortToPortConverter,
|
||||||
|
MapLabelToLabelConverter,
|
||||||
|
FontBBoxCalculator,
|
||||||
|
CssFixer,
|
||||||
|
FontFixer
|
||||||
],
|
],
|
||||||
declarations: [ ProjectMapShortcutsComponent ]
|
declarations: [ ProjectMapShortcutsComponent ]
|
||||||
})
|
})
|
||||||
|
@ -39,6 +39,7 @@ import { MapPortToPortConverter } from '../../cartography/converters/map/map-por
|
|||||||
import { SettingsService, Settings } from '../../services/settings.service';
|
import { SettingsService, Settings } from '../../services/settings.service';
|
||||||
import { MapLabel } from '../../cartography/models/map/map-label';
|
import { MapLabel } from '../../cartography/models/map/map-label';
|
||||||
import { MapLinkNode } from '../../cartography/models/map/map-link-node';
|
import { MapLinkNode } from '../../cartography/models/map/map-link-node';
|
||||||
|
import { MapLabelToLabelConverter } from '../../cartography/converters/map/map-label-to-label-converter';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -91,6 +92,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
private drawingsEventSource: DrawingsEventSource,
|
private drawingsEventSource: DrawingsEventSource,
|
||||||
private linksEventSource: LinksEventSource,
|
private linksEventSource: LinksEventSource,
|
||||||
private settingsService: SettingsService,
|
private settingsService: SettingsService,
|
||||||
|
private mapLabelToLabel: MapLabelToLabelConverter
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@ -234,7 +236,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
onNodeCreation(appliance: Appliance) {
|
onNodeCreation(appliance: Appliance) {
|
||||||
this.nodeService
|
this.nodeService
|
||||||
.createFromAppliance(this.server, this.project, appliance, 0, 0, 'local')
|
.createFromAppliance(this.server, this.project, appliance, 0, 0, 'local')
|
||||||
.subscribe(() => {
|
.subscribe((createdNode: Node) => {
|
||||||
this.projectService
|
this.projectService
|
||||||
.nodes(this.server, this.project.project_id)
|
.nodes(this.server, this.project.project_id)
|
||||||
.subscribe((nodes: Node[]) => {
|
.subscribe((nodes: Node[]) => {
|
||||||
@ -257,8 +259,12 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
private onNodeLabelDragged(draggedEvent: DraggedDataEvent<MapLabel>) {
|
private onNodeLabelDragged(draggedEvent: DraggedDataEvent<MapLabel>) {
|
||||||
const node = this.nodesDataSource.get(draggedEvent.datum.nodeId);
|
const node = this.nodesDataSource.get(draggedEvent.datum.nodeId);
|
||||||
node.label.x += draggedEvent.dx;
|
const mapLabel = draggedEvent.datum;
|
||||||
node.label.y += draggedEvent.dy;
|
mapLabel.x += draggedEvent.dx;
|
||||||
|
mapLabel.y += draggedEvent.dy;
|
||||||
|
|
||||||
|
const label = this.mapLabelToLabel.convert(mapLabel);
|
||||||
|
node.label = label;
|
||||||
|
|
||||||
this.nodeService
|
this.nodeService
|
||||||
.updateLabel(this.server, node, node.label)
|
.updateLabel(this.server, node, node.label)
|
||||||
|
Reference in New Issue
Block a user