From 1782c6c3d350eceee0ad10bca5c6825ff5ac0a90 Mon Sep 17 00:00:00 2001
From: ziajka <dominik@gns3.net>
Date: Mon, 16 Apr 2018 15:09:04 +0200
Subject: [PATCH] Normalize positions of elements, Ref: #111, Fix double nodes
 and drawings

---
 .../shared/datasources/datasource.spec.ts      | 12 ++++++++++++
 .../shared/datasources/datasource.ts           |  9 +++++++--
 .../shared/widgets/ethernet-link.ts            |  4 ++--
 .../shared/widgets/interface-label.ts          | 18 ++++++++++++------
 src/app/cartography/shared/widgets/links.ts    |  8 ++++----
 src/app/cartography/shared/widgets/nodes.ts    | 12 +++++++-----
 6 files changed, 44 insertions(+), 19 deletions(-)

diff --git a/src/app/cartography/shared/datasources/datasource.spec.ts b/src/app/cartography/shared/datasources/datasource.spec.ts
index e80a6722..bd5f87f6 100644
--- a/src/app/cartography/shared/datasources/datasource.spec.ts
+++ b/src/app/cartography/shared/datasources/datasource.spec.ts
@@ -33,6 +33,18 @@ describe('TestDataSource', () => {
     });
   });
 
+
+  describe('Item can be added when key duplocates', () => {
+    beforeEach(() => {
+      dataSource.add(new Item("test1", "property1"));
+      dataSource.add(new Item("test1", "property2"));
+    });
+
+    it('item should be in data', () => {
+      expect(data).toEqual([new Item("test1", "property2")]);
+    });
+  });
+
   describe('Items can be set', () => {
     beforeEach(() => {
       dataSource.set([new Item("test1", "property1"), new Item("test2", "property2")]);
diff --git a/src/app/cartography/shared/datasources/datasource.ts b/src/app/cartography/shared/datasources/datasource.ts
index 86ba8474..9d7d0cfc 100644
--- a/src/app/cartography/shared/datasources/datasource.ts
+++ b/src/app/cartography/shared/datasources/datasource.ts
@@ -9,8 +9,13 @@ export abstract class DataSource<T> {
   }
 
   public add(item: T) {
-    this.data.push(item);
-    this.dataChange.next(this.data);
+    const index = this.findIndex(item);
+    if (index >= 0) {
+      this.update(item);
+    } else {
+      this.data.push(item);
+      this.dataChange.next(this.data);
+    }
   }
 
   public set(data: T[]) {
diff --git a/src/app/cartography/shared/widgets/ethernet-link.ts b/src/app/cartography/shared/widgets/ethernet-link.ts
index e84f5c4a..fa46abc6 100644
--- a/src/app/cartography/shared/widgets/ethernet-link.ts
+++ b/src/app/cartography/shared/widgets/ethernet-link.ts
@@ -9,8 +9,8 @@ export class EthernetLinkWidget implements Widget {
 
   public draw(view: SVGSelection, link: Link) {
       const link_data = [[
-        [link.source.x, link.source.y],
-        [link.target.x, link.target.y]
+        [link.source.x + link.source.width / 2., link.source.y + link.source.height / 2.],
+        [link.target.x + link.target.width / 2., link.target.y + link.source.height / 2.]
       ]];
 
       const value_line = line();
diff --git a/src/app/cartography/shared/widgets/interface-label.ts b/src/app/cartography/shared/widgets/interface-label.ts
index dbd3d9f7..977b8202 100644
--- a/src/app/cartography/shared/widgets/interface-label.ts
+++ b/src/app/cartography/shared/widgets/interface-label.ts
@@ -17,16 +17,16 @@ export class InterfaceLabelWidget {
       .selectAll<SVGTextElement, InterfaceLabel>('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),
+          Math.round(l.source.x + l.source.width + l.nodes[0].label.x),
+          Math.round(l.source.y + l.source.height + 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),
+          Math.round(l.target.x + l.target.width / 2. + l.nodes[1].label.x),
+          Math.round(l.target.y + l.target.height / 2.  + l.nodes[1].label.y),
           l.nodes[1].label.text,
           l.nodes[1].label.style,
           l.nodes[1].label.rotation
@@ -45,8 +45,14 @@ export class InterfaceLabelWidget {
 
     merge
       .text((l: InterfaceLabel) => l.text)
-      .attr('x', (l: InterfaceLabel) => l.x)
-      .attr('y', (l: InterfaceLabel) => l.y)
+      .attr('x', function(this: SVGTextElement, l: InterfaceLabel) {
+        const bbox = this.getBBox();
+        return l.x;
+      })
+      .attr('y', function(this: SVGTextElement, l: InterfaceLabel)  {
+        const bbox = this.getBBox();
+        return l.y;
+      })
       .attr('style', (l: InterfaceLabel) => this.cssFixer.fix(l.style))
       .attr('transform', (l: InterfaceLabel) => `rotate(${l.rotation}, ${l.x}, ${l.y})`);
 
diff --git a/src/app/cartography/shared/widgets/links.ts b/src/app/cartography/shared/widgets/links.ts
index 89d2b720..6def1bee 100644
--- a/src/app/cartography/shared/widgets/links.ts
+++ b/src/app/cartography/shared/widgets/links.ts
@@ -51,8 +51,8 @@ export class LinksWidget implements Widget {
 
         const link_path = link_group.select<SVGPathElement>('path');
 
-        const start_point: SVGPoint = link_path.node().getPointAtLength(50);
-        const end_point: SVGPoint = link_path.node().getPointAtLength(link_path.node().getTotalLength() - 50);
+        const start_point: SVGPoint = link_path.node().getPointAtLength(40);
+        const end_point: SVGPoint = link_path.node().getPointAtLength(link_path.node().getTotalLength() - 40);
 
         const statuses = [
           new LinkStatus(start_point.x, start_point.y, l.source.status),
@@ -72,7 +72,7 @@ export class LinksWidget implements Widget {
             .attr('class', 'status_started')
             .attr('cx', (ls: LinkStatus) => ls.x)
             .attr('cy', (ls: LinkStatus) => ls.y)
-            .attr('r', 4)
+            .attr('r', 6)
             .attr('fill', '#2ecc71');
 
         status_started
@@ -87,7 +87,7 @@ export class LinksWidget implements Widget {
           .enter()
             .append<SVGRectElement>('rect');
 
-        const STOPPED_STATUS_RECT_WIDTH = 6;
+        const STOPPED_STATUS_RECT_WIDTH = 10;
 
         status_stopped
           .merge(status_stopped_enter)
diff --git a/src/app/cartography/shared/widgets/nodes.ts b/src/app/cartography/shared/widgets/nodes.ts
index b0e41b3f..f79bb640 100644
--- a/src/app/cartography/shared/widgets/nodes.ts
+++ b/src/app/cartography/shared/widgets/nodes.ts
@@ -68,15 +68,17 @@ export class NodesWidget implements Widget {
             const bbox = this.getBBox();
             return -bbox.width / 2.;
           }
-          return n.label.x - n.width / 2.;
+          return n.label.x;
         })
         .attr('y', function (this: SVGTextElement, n: Node) {
+          let bbox = this.getBBox();
+
           if (n.label.x === null) {
             // center
-            const bbox = this.getBBox();
+            bbox = this.getBBox();
             return - n.height / 2. - bbox.height ;
           }
-          return n.label.y - n.height / 2.;
+          return n.label.y + bbox.height;
         });
 
     selection
@@ -156,8 +158,8 @@ export class NodesWidget implements Widget {
           })
           .attr('width', (n: Node) => n.width)
           .attr('height', (n: Node) => n.height)
-          .attr('x', (n: Node) => -n.width / 2.)
-          .attr('y', (n: Node) => -n.height / 2.)
+          .attr('x', (n: Node) => 0)
+          .attr('y', (n: Node) => 0)
           .on('mouseover', function (this, n: Node) {
             select(this).attr("class", "over");
           })