GUI2 Topo Allow selection of multiple nodes at once

Change-Id: I0bb226d4697e3df49da0a049d440a70aed172263
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.html b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.html
index 399955c..e87e1a8 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.html
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.html
@@ -47,7 +47,7 @@
 <svg:g xmlns:svg="http://www.w3.org/2000/svg"
        [attr.transform]="'translate(' + device?.x + ',' + device?.y + '), scale(' + scale + ')'"
         [ngClass]="['node', 'device', device.online?'online':'', selected?'selected':'']"
-        (click)="toggleSelected(device)">
+        (click)="toggleSelected(device, $event)">
     <svg:desc>Device {{device.id}}</svg:desc>
     <!-- Template explanation: Creates an SVG Rectangle and in
         line 1) set a css style and shift so that it's centred
@@ -88,4 +88,4 @@
     </svg:text>
     <svg:use [attr.xlink:href]="'#' + deviceIcon()" width="36" height="36" x="-18" y="-18">
     </svg:use>
-</svg:g>
\ No newline at end of file
+</svg:g>
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.ts
index ce6bd46..adcd788 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.ts
@@ -24,7 +24,7 @@
 } from '@angular/core';
 import {Device, LabelToggle, UiElement} from '../../models';
 import {IconService, LocMeta, LogService, MetaUi, ZoomUtils} from 'gui2-fw-lib';
-import {NodeVisual} from '../nodevisual';
+import {NodeVisual, SelectedEvent} from '../nodevisual';
 import {animate, state, style, transition, trigger} from '@angular/animations';
 import {LocationType} from '../../../backgroundsvg/backgroundsvg.component';
 
@@ -68,7 +68,7 @@
     @Input() device: Device;
     @Input() scale: number = 1.0;
     @Input() labelToggle: LabelToggle.Enum = LabelToggle.Enum.NONE;
-    @Output() selectedEvent = new EventEmitter<UiElement>();
+    @Output() selectedEvent = new EventEmitter<SelectedEvent>();
     textWidth: number = 36;
     constructor(
         protected log: LogService,
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.html b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.html
index ccce65a..0ce4a4a 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.html
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.html
@@ -45,7 +45,7 @@
 <svg:g  xmlns:svg="http://www.w3.org/2000/svg"
         [attr.transform]="'translate(' + host?.x + ',' + host?.y + '), scale(' + scale + ')'"
         [ngClass]="['node', 'host', 'endstation', 'fixed', selected?'selected':'', 'hovered']"
-        (click)="toggleSelected(host)">
+        (click)="toggleSelected(host, $event)">
     <svg:desc>Host {{host.id}}</svg:desc>
     <!-- Template explanation: Creates an SVG Circle and in
         line 1) Apply the drop shadow defined above to this circle
@@ -67,4 +67,4 @@
         *ngIf="labelToggle != 0"
         dy="30" text-anchor="middle"
         >{{hostName()}}</svg:text>
-</svg:g>
\ No newline at end of file
+</svg:g>
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.ts
index 26c105a..806f9b2 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.ts
@@ -23,7 +23,7 @@
 } from '@angular/core';
 import {Host, HostLabelToggle, Node} from '../../models';
 import {LogService} from 'gui2-fw-lib';
-import {NodeVisual} from '../nodevisual';
+import {NodeVisual, SelectedEvent} from '../nodevisual';
 
 /**
  * The Host node in the force graph
@@ -40,7 +40,7 @@
     @Input() host: Host;
     @Input() scale: number = 1.0;
     @Input() labelToggle: HostLabelToggle.Enum = HostLabelToggle.Enum.IP;
-    @Output() selectedEvent = new EventEmitter<Node>();
+    @Output() selectedEvent = new EventEmitter<SelectedEvent>();
 
     constructor(
         protected log: LogService
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.html b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.html
index c856763..a94914d 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.html
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.html
@@ -39,7 +39,7 @@
         [attr.x2]="link.target?.x" [attr.y2]="link.target?.y"
         [ngClass]="['link', selected?'selected':'', enhanced?'enhanced':'', highlighted]"
         [ngStyle]="{'stroke-width': (enhanced ? 4 : 2) * scale + 'px'}"
-        (click)="toggleSelected(link)"
+        (click)="toggleSelected(link, $event)"
         (mouseover)="enhance()"
         [attr.filter]="highlighted?'url(#glow)':'none'">
 </svg:line>
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts
index eab533f..9853889 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts
@@ -20,7 +20,7 @@
 } from '@angular/core';
 import {Link, LinkHighlight, UiElement} from '../../models';
 import {LogService} from 'gui2-fw-lib';
-import {NodeVisual} from '../nodevisual';
+import {NodeVisual, SelectedEvent} from '../nodevisual';
 import {animate, state, style, transition, trigger} from '@angular/animations';
 
 interface Point {
@@ -52,7 +52,7 @@
     @Input() label: string;
     @Input() scale = 1.0;
     isHighlighted: boolean = false;
-    @Output() selectedEvent = new EventEmitter<UiElement>();
+    @Output() selectedEvent = new EventEmitter<SelectedEvent>();
     @Output() enhancedEvent = new EventEmitter<Link>();
     enhanced: boolean = false;
     labelPosSrc: Point = {x: 0, y: 0};
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/nodevisual.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/nodevisual.ts
index a41df62..10bf3d8 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/nodevisual.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/nodevisual.ts
@@ -16,20 +16,30 @@
 import {EventEmitter} from '@angular/core';
 import {UiElement} from '../models';
 
+export interface SelectedEvent {
+    uiElement: UiElement;
+    deselecting: boolean;
+    isShift: boolean;
+    isCtrl: boolean;
+    isAlt: boolean;
+}
+
 /**
  * A base class for the Host and Device components
  */
 export abstract class NodeVisual {
     selected: boolean;
-    selectedEvent = new EventEmitter<UiElement>();
+    selectedEvent = new EventEmitter<SelectedEvent>();
 
-    toggleSelected(uiElement: UiElement) {
+    toggleSelected(uiElement: UiElement, event: MouseEvent) {
         this.selected = !this.selected;
-        if (this.selected) {
-            this.selectedEvent.emit(uiElement);
-        } else {
-            this.selectedEvent.emit();
-        }
+        this.selectedEvent.emit(<SelectedEvent>{
+            uiElement: uiElement,
+            deselecting: !this.selected,
+            isShift: event.shiftKey,
+            isCtrl: event.ctrlKey,
+            isAlt: event.altKey
+        });
     }
 
     deselect() {