GUI2 added in details panel, updated docs

Change-Id: I49a874deeb4de1082f190ea5d0d985c986a978f8
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/glyphdata.service.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/glyphdata.service.ts
index 2ff3e85..3703243 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/glyphdata.service.ts
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/glyphdata.service.ts
@@ -546,6 +546,12 @@
     ['triangleUp', 'M0.5,6.2c0,0,3.8-3.8,4.2-4.2C5,1.7,5.3,2,5.3,2l4.3,' +
     '4.3c0,0,0.4,0.4-0.1,0.4c-1.7,0-8.2,0-8.8,0C0,6.6,0.5,6.2,0.5,6.2z'],
 
+    ['triangleLeft', 'm 6.13,9.63 c 0,0 -3.8,-3.8 -4.2,-4.2 -0.3,-0.3 0,-0.6 0,' +
+        '-0.6 L 6.23,0.54 c 0,0 0.4,-0.4 0.4,0.1 0,1.7 0,8.2 0,8.8 -0.1,0.7 -0.5,0.2 -0.5,0.2 z'],
+
+    ['triangleRight', 'm 4.07,9.6 c 0,0 3.8,-3.8 4.2,-4.2 0.3,-0.3 0,-0.6 0,-0.6' +
+        'l -4.3,-4.3 c 0,0 -0.4,-0.4 -0.4,0.1 0,1.7 0,8.2 0,8.8 0.1,0.7 0.5,0.2 0.5,0.2 z'],
+
     ['triangleDown', 'M9.5,4.2c0,0-3.8,3.8-4.2,4.2c-0.3,0.3-0.5,0-0.5,' +
     '0L0.5,4.2c0,0-0.4-0.4,0.1-0.4c1.7,0,8.2,0,8.8,0C10,3.8,9.5,4.2,' +
     '9.5,4.2z'],
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/icon.service.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/icon.service.ts
index 5b801ab..766cc56 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/icon.service.ts
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/icon.service.ts
@@ -40,11 +40,54 @@
     ['nonzero', 'nonzero'],
     ['close', 'xClose'],
 
+    ['m_cloud', 'm_cloud'],
+    ['m_map', 'm_map'],
+    ['m_selectMap', 'm_selectMap'],
+    ['thatsNoMoon', 'thatsNoMoon'],
     ['m_ports', 'm_ports'],
     ['m_switch', 'm_switch'],
     ['m_roadm', 'm_roadm'],
     ['m_router', 'm_router'],
+    ['m_uiAttached', 'm_uiAttached'],
     ['m_endstation', 'm_endstation'],
+    ['m_summary', 'm_summary'],
+    ['m_details', 'm_details'],
+    ['m_oblique', 'm_oblique'],
+    ['m_filters', 'm_filters'],
+    ['m_cycleLabels', 'm_cycleLabels'],
+    ['m_prev', 'm_prev'],
+    ['m_next', 'm_next'],
+    ['m_flows', 'm_flows'],
+    ['m_allTraffic', 'm_allTraffic'],
+    ['m_xMark', 'm_xMark'],
+    ['m_resetZoom', 'm_resetZoom'],
+    ['m_eqMaster', 'm_eqMaster'],
+    ['m_unknown', 'm_unknown'],
+    ['m_controller', 'm_controller'],
+    ['m_eqMaster', 'm_eqMaster'],
+    ['m_virtual', 'm_virtual'],
+    ['m_other', 'm_other'],
+    ['m_bgpSpeaker', 'm_bgpSpeaker'],
+    ['m_otn', 'm_otn'],
+    ['m_roadm_otn', 'm_roadm_otn'],
+    ['m_fiberSwitch', 'm_fiberSwitch'],
+    ['m_microwave', 'm_microwave'],
+    ['m_relatedIntents', 'm_relatedIntents'],
+    ['m_intentTraffic', 'm_intentTraffic'],
+    ['m_firewall', 'm_firewall'],
+    ['m_balancer', 'm_balancer'],
+    ['m_ips', 'm_ips'],
+    ['m_ids', 'm_ids'],
+    ['m_olt', 'm_olt'],
+    ['m_onu', 'm_onu'],
+    ['m_swap', 'm_swap'],
+    ['m_shortestGeoPath', 'm_shortestGeoPath'],
+    ['m_source', 'm_source'],
+    ['m_destination', 'm_destination'],
+    ['m_topo', 'm_topo'],
+    ['m_shortestPath', 'm_shortestPath'],
+    ['m_disjointPaths', 'm_disjointPaths'],
+    ['m_region', 'm_region'],
 
     ['topo', 'topo'],
     ['bird', 'bird'],
@@ -56,6 +99,8 @@
 
     ['upArrow', 'triangleUp'],
     ['downArrow', 'triangleDown'],
+    ['triangleLeft', 'triangleLeft'],
+    ['triangleRight', 'triangleRight'],
 
     ['appInactive', 'unknown'],
     ['uiAttached', 'uiAttached'],
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/icon/button-theme.css b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/icon/button-theme.css
new file mode 100644
index 0000000..8eff0a0
--- /dev/null
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/icon/button-theme.css
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ ONOS GUI -- Button Service (theme) -- CSS file
+ */
+
+
+/* === SELECTED BUTTONS === */
+
+/* Selected toggle / radio button */
+svg.embeddedIcon .toggleButton.selected .icon rect,
+svg.embeddedIcon .radioButton.selected .icon rect {
+    fill: #e4f0f6;
+}
+
+/* Selected:hover (normal) button */
+svg.embeddedIcon .button:hover .icon rect {
+    stroke: black;
+    stroke-width: 1px;
+}
+
+/* Selected:hover toggle-button */
+svg.embeddedIcon .toggleButton.selected:hover .icon rect {
+    fill: #c0d8f0;
+    stroke: black;
+    stroke-width: 1px;
+}
+
+/* Selected toggle/radio button and normal button glyph color */
+svg.embeddedIcon .button .glyph,
+svg.embeddedIcon .toggleButton.selected .glyph,
+svg.embeddedIcon .radioButton.selected .glyph {
+    fill: #5b99d2;
+}
+
+
+/* === UNSELECTED BUTTONS === */
+
+/* Unselected toggle / radio button */
+svg.embeddedIcon .toggleButton.icon rect,
+svg.embeddedIcon .radioButton.icon rect {
+    /* no fill */
+}
+
+/* Unselected:hover toggle / radio button */
+svg.embeddedIcon .icon.toggleButton:hover rect,
+svg.embeddedIcon .icon.radioButton:hover:not(.selected) rect {
+    fill: #e4f0f6;
+    stroke: black;
+    stroke-width: 1px;
+}
+
+/* Unselected toggle / radio button */
+svg.embeddedIcon .toggleButton .glyph,
+svg.embeddedIcon .radioButton .glyph {
+    fill: #bbb;
+}
+
+/* Unselected:hover toggle / radio button */
+svg.embeddedIcon .toggleButton:hover:not(.selected) .glyph,
+svg.embeddedIcon .radioButton:hover:not(.selected) .glyph {
+    fill: #5b99d2;
+}
+
+
+/* ========== DARK Theme ========== */
+
+/* Selected toggle / radio button */
+.dark .toggleButton.selected svg.embeddedIcon .icon rect,
+.dark .radioButton.selected svg.embeddedIcon .icon rect {
+    fill: #353e45;
+}
+
+/* Selected:hover (normal) button */
+.dark .button:hover svg.embeddedIcon .icon rect {
+    stroke: white;
+    stroke-width: 1px;
+}
+
+/* Selected:hover toggle-button */
+.dark .toggleButton.selected:hover svg.embeddedIcon .icon rect {
+    fill: #444d54;
+    stroke: white;
+    stroke-width: 1px;
+}
+
+/* Selected toggle/radio button and normal button glyph color */
+.dark .button svg.embeddedIcon .glyph,
+.dark .toggleButton.selected svg.embeddedIcon .glyph,
+.dark .radioButton.selected svg.embeddedIcon .glyph {
+    fill: #5b99d2;
+}
+
+
+/* === UNSELECTED BUTTONS === */
+
+/* Unselected toggle / radio button */
+.dark .toggleButton svg.embeddedIcon .icon rect,
+.dark .radioButton svg.embeddedIcon .icon rect {
+    /* no fill */
+}
+
+/* Unselected:hover toggle / radio button */
+.dark .toggleButton:hover svg.embeddedIcon .icon rect,
+.dark .radioButton:hover:not(.selected) svg.embeddedIcon .icon rect {
+    fill: #353e45;
+    stroke: white;
+    stroke-width: 1px;
+}
+
+/* Unselected toggle / radio button */
+.dark .toggleButton svg.embeddedIcon .glyph,
+.dark .radioButton svg.embeddedIcon .glyph {
+    fill: #bbb;
+}
+
+/* Unselected:hover toggle / radio button */
+.dark .toggleButton:hover:not(.selected) svg.embeddedIcon .glyph,
+.dark .radioButton:hover:not(.selected) svg.embeddedIcon .glyph {
+    fill: #5b99d2;
+}
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/icon/icon.component.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/icon/icon.component.ts
index d05c7ed..ad8d382 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/icon/icon.component.ts
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/icon/icon.component.ts
@@ -33,7 +33,7 @@
   styleUrls: [
     './icon.component.css', './icon.theme.css',
     './glyph.css', './glyph-theme.css',
-    './tooltip.css', './tooltip-theme.css'
+    './tooltip.css', './button-theme.css'
     ]
 })
 export class IconComponent implements OnInit, OnChanges {
diff --git a/web/gui2/AngularMigration.md b/web/gui2/AngularMigration.md
index d706255..ad8ee7d 100644
--- a/web/gui2/AngularMigration.md
+++ b/web/gui2/AngularMigration.md
@@ -298,7 +298,7 @@
   so that the enclosing context can be passed in to the lambda
 
 
-# Progress so far - Nov 2018
+# Progress so far - Dec 2018
 The following services are most migrated:
 * fw/util/FnService - full migrated with Unit tests
 * fw/svg/GlyphDataService - mostly migrated. Values are stored in maps as constants
@@ -388,13 +388,15 @@
 are the __layout__ components. In addition some are SVG components that are
 designed to extend an SVG element tree, rather than a HTML one.
 
+Also the icons have got a fresh new look with gradients and drop shadows done in SVG.
+
 All of this will ultimately lead to a framework that can support other paradigms
 especially ones like tiles background maps, such as this from Google and other
 providers.
 
-There is still quite a way to go to finish this consolidated Topology view (as of
-Nov '18), as there are updated vesions of the D3 Force library and the D3 Zoom
-library to migrate to.
+This has progressed a lot since the first version in Nov 18. Now traffic flows are 
+represented as well as node and host labels and link hovering etc. Zoom and Pan
+have been added as well as many of the keyboard shortcuts, familiar from Topo1
 
 The Topology view will eventually be broken out in to its own library, to promote
 reuse.
\ No newline at end of file
diff --git a/web/gui2/README.md b/web/gui2/README.md
index 8f97312..50f5077 100644
--- a/web/gui2/README.md
+++ b/web/gui2/README.md
@@ -57,11 +57,12 @@
 This will install all the vendor Javascript implementations that are listed in package.json
  (including 'ng' - the Angular CLI command) in to ~/onos/web/gui2-fw-lib/node_modules
 
-After this you should be able to cd in to ~/onos/web/gui2-fw-lib and run 'ng -v' and see:
+After this you should be able to cd in to ~/onos/web/gui2-fw-lib and run 'ng version' and see:
 ```
-Angular CLI: 6.0.0
+Angular CLI: 7.0.4
 Node: 8.11.1
 OS: linux x64
+Angular: 7.0.2
 ```
 
 ## GUI FW Lib
@@ -77,7 +78,8 @@
 ng build gui2-fw-lib && \
 cd dist/gui2-fw-lib && \
 npm pack && \
-popd
+popd && \
+npm install gui2-fw-lib
 ```
 
 To test and lint it use
diff --git a/web/gui2/package-lock.json b/web/gui2/package-lock.json
index dcafb26..81356c1 100644
--- a/web/gui2/package-lock.json
+++ b/web/gui2/package-lock.json
@@ -5560,7 +5560,7 @@
     },
     "gui2-fw-lib": {
       "version": "file:../gui2-fw-lib/dist/gui2-fw-lib/gui2-fw-lib-2.0.0.tgz",
-      "integrity": "sha512-4PrjcISAfAmMAajZJ/BUXytnXjs+nuGxMIbSQqkzyWwIgMySql+NjavvAQkRyHX6551jm7ZMIo3p4J6Z4IlH8A==",
+      "integrity": "sha512-DRtcy4kDWJxMllozKJpiS4H820mxXmP01bU91qb5sYa/0HjiuihlOiJhvF4Kyg4hUfISNF+bhDeFwr3UgI5xtA==",
       "requires": {
         "tslib": "1.9.3"
       }
diff --git a/web/gui2/src/main/webapp/app/view/topology/README.md b/web/gui2/src/main/webapp/app/view/topology/README.md
index 3f3e647..35acd31 100644
--- a/web/gui2/src/main/webapp/app/view/topology/README.md
+++ b/web/gui2/src/main/webapp/app/view/topology/README.md
@@ -2,7 +2,8 @@
 
 This is the GUI2 version of the combined Topo and Topo2 views of the older version.
 
-It uses Angular 6 components extensively.
+It uses Angular 7 components extensively. TopologyComponent is the starting point
+for everything in it. 
 
 This should all be moved to its own separate library once all debugging is done
 (it is slightly more difficult to debug the code when in a separate library)
\ No newline at end of file
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.html b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.html
index af33384..c4930c1 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.html
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.html
@@ -1,5 +1,5 @@
 <!--
-~ Copyright 2018-present Open Networking Foundation
+~ Copyright 2019-present Open Networking Foundation
 ~
 ~ Licensed under the Apache License, Version 2.0 (the "License");
 ~ you may not use this file except in compliance with the License.
@@ -13,76 +13,67 @@
 ~ See the License for the specific language governing permissions and
 ~ limitations under the License.
 -->
-<svg:g class="topo2-force" xmlns:svg="http://www.w3.org/2000/svg">
-    <svg:g id="new-zoom-layer">
-        <svg:g class="topo2-links">
-            <!-- Template explanation: Creates an SVG Group and in
-                line 1) use the svg component onos-linksvg, setting it's link
-                 Input parameter to the link item from the next line
-                line 2) Use the built in NgFor directive to iterate through the
-                 set of links filtered by the filteredLinks() function.
-            -->
-            <svg:g onos-linksvg [link]="link"
-                   *ngFor="let link of filteredLinks()"
-                   (selectedEvent)="updateSelected($event)">
-            </svg:g>
-        </svg:g>
-        <svg:g class="topo2-linkLabels" />
-        <svg:g class="topo2-numLinkLabels" />
-        <svg:g class="topo2-nodes">
-            <!-- Template explanation - create an SVG Group and
-                line 1) use the svg component onos-devicenodesvg, setting it's device
-                 Input parameter to the device item from the next line
-                line 2) Use the built in NgFor directive to iterate through all
-                 of the devices in the chosen layer index. The current iteration
-                 is in the device variable
-                line 3) Use the onosDraggable directive and pass this device in to
-                 its draggableNode Input parameter and setting the draggableInGraph
-                 Input parameter to 'graph'
-                line 4) when the onos-devicenodesvg component emits the selectedEvent
-                 call the updateSelected() method of this (forcesvg) component
-            -->
-            <svg:g onos-devicenodesvg [device]="device"
-                   *ngFor="let device of regionData.devices[visibleLayerIdx()]"
-                   onosDraggableNode [draggableNode]="device" [draggableInGraph]="graph"
-                   (selectedEvent)="updateSelected($event)">
-            </svg:g>
-            <!-- Template explanation - only display the hosts if 'showHosts' is set true -->
-            <svg:g *ngIf="showHosts">
-                <!-- Template explanation - create an SVG Group and
-                    line 1) use the svg component onos-hostnodesvg, setting it's host
-                     Input parameter to the host item from the next line
-                    line 2) Use the built in NgFor directive to iterate through all
-                     of the hosts in the chosen layer index. The current iteration
-                     is in the 'host' variable
-                    line 3) Use the onosDraggable directive and pass this host in to
-                     its draggableNode Input parameter and setting the draggableInGraph
-                     Input parameter to 'graph'
-                    line 4) when the onos-hostnodesvg component emits the selectedEvent
-                     call the updateSelected() method of this (forcesvg) component
-                -->
-                <svg:g onos-hostnodesvg [host]="host"
-                       *ngFor="let host of regionData.hosts[visibleLayerIdx()]"
-                       onosDraggableNode [draggableNode]="host" [draggableInGraph]="graph"
-                       (selectedEvent)="updateSelected($event)">
-                </svg:g>
-            </svg:g>
-            <svg:g onos-subregionnodesvg [subRegion]="subRegion"
-                   *ngFor="let subRegion of regionData.subregions"
-                   onosDraggableNode [draggableNode]="host" [draggableInGraph]="graph">
-            </svg:g>
+<svg:desc xmlns:svg="http://www.w3.org/2000/svg">The force layout layer. This is
+    an SVG component that displays Nodes (Devices, Hosts and SubRegions) and
+    Links. Positions of each are driven by a forces computation engine</svg:desc>
+<svg:g xmlns:svg="http://www.w3.org/2000/svg" class="topo2-links">
+    <svg:desc>Topology links</svg:desc>
+    <!-- Template explanation: Creates an SVG Group and in
+        line 1) use the svg component onos-linksvg, setting it's link
+         Input parameter to the link item from the next line
+        line 2) Use the built in NgFor directive to iterate through the
+         set of links filtered by the filteredLinks() function.
+    -->
+    <svg:g onos-linksvg [link]="link"
+           *ngFor="let link of filteredLinks()"
+           [highlightsEnabled]="highlightPorts"
+           (selectedEvent)="updateSelected($event)">
+    </svg:g>
+</svg:g>
+<svg:g xmlns:svg="http://www.w3.org/2000/svg" class="topo2-nodes">
+    <svg:desc>Topology nodes</svg:desc>
+    <!-- Template explanation - create an SVG Group and
+        line 1) use the svg component onos-devicenodesvg, setting it's device
+         Input parameter to the device item from the next line
+        line 2) Use the built in NgFor directive to iterate through all
+         of the devices in the chosen layer index. The current iteration
+         is in the device variable
+        line 3) Use the onosDraggable directive and pass this device in to
+         its draggableNode Input parameter and setting the draggableInGraph
+         Input parameter to 'graph'
+        line 4) when the onos-devicenodesvg component emits the selectedEvent
+         call the updateSelected() method of this (forcesvg) component
+    -->
+    <svg:g onos-devicenodesvg [device]="device"
+           *ngFor="let device of regionData.devices[visibleLayerIdx()]"
+           onosDraggableNode [draggableNode]="device" [draggableInGraph]="graph"
+           (selectedEvent)="updateSelected($event)">
+        <svg:desc>Device nodes</svg:desc>
+    </svg:g>
+    <!-- Template explanation - only display the hosts if 'showHosts' is set true -->
+    <svg:g *ngIf="showHosts">
+        <!-- Template explanation - create an SVG Group and
+            line 1) use the svg component onos-hostnodesvg, setting it's host
+             Input parameter to the host item from the next line
+            line 2) Use the built in NgFor directive to iterate through all
+             of the hosts in the chosen layer index. The current iteration
+             is in the 'host' variable
+            line 3) Use the onosDraggable directive and pass this host in to
+             its draggableNode Input parameter and setting the draggableInGraph
+             Input parameter to 'graph'
+            line 4) when the onos-hostnodesvg component emits the selectedEvent
+             call the updateSelected() method of this (forcesvg) component
+        -->
+        <svg:g onos-hostnodesvg [host]="host"
+               *ngFor="let host of regionData.hosts[visibleLayerIdx()]"
+               onosDraggableNode [draggableNode]="host" [draggableInGraph]="graph"
+               (selectedEvent)="updateSelected($event)">
+            <svg:desc>Host nodes</svg:desc>
         </svg:g>
     </svg:g>
-    <!--<svg:g class="topo2-portLabels">-->
-        <!--&lt;!&ndash;TODO make each of these in to a component that can be inserted &ndash;&gt;-->
-        <!--<svg:g *ngIf="selectedLink !== null" id="topo-port-src" class="portLabel" opacity="1">-->
-            <!--<rect x="0" y="0" width="1" height="1" [ngStyle]="{'transform': 'scale(1)'}"></rect>-->
-            <!--<text dy="0.3em" [ngStyle]="{'transform': 'scale(1)'}">{{ selectedLink.portA }}</text>-->
-        <!--</svg:g>-->
-
-        <!--<svg:g *ngIf="selectedLink !== null" id="topo-port-tgt" class="portLabel" opacity="1">-->
-            <!--<rect x="0" y="0" width="1" height="1" [ngStyle]="{'transform': 'scale(1)'}"></rect>-->
-            <!--<text dy="0.3em" [ngStyle]="{'transform': 'scale(1)'}">{{ selectedLink.portA }}</text>-->
-        <!--</svg:g>-->
-    <!--</svg:g>-->
+    <svg:g onos-subregionnodesvg [subRegion]="subRegion"
+           *ngFor="let subRegion of regionData.subregions"
+           onosDraggableNode [draggableNode]="host" [draggableInGraph]="graph">
+        <svg:desc>Subregion nodes</svg:desc>
+    </svg:g>
 </svg:g>
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.spec.ts b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.spec.ts
index 6b1980a..7a30d75 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.spec.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.spec.ts
@@ -16,7 +16,7 @@
 import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 
 import { ForceSvgComponent } from './forcesvg.component';
-import {IconService, LogService} from 'gui2-fw-lib';
+import {LogService} from 'gui2-fw-lib';
 import {
     DeviceNodeSvgComponent,
     HostNodeSvgComponent, LinkSvgComponent,
@@ -33,10 +33,6 @@
     }
 }
 
-class MockIconService {
-    loadIconDef() { }
-}
-
 describe('ForceSvgComponent', () => {
     let ar: MockActivatedRoute;
     let windowMock: Window;
@@ -71,7 +67,6 @@
             ],
             providers: [
                 { provide: LogService, useValue: logSpy },
-                { provide: IconService, useClass: MockIconService },
             ]
         })
         .compileComponents();
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.ts b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.ts
index 25e52ab..b0b4a0c 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.ts
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-present Open Networking Foundation
+ * Copyright 2019-present Open Networking Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the 'License');
  * you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@
     SimpleChanges,
     ViewChildren
 } from '@angular/core';
-import {IconService, LogService} from 'gui2-fw-lib';
+import {LogService} from 'gui2-fw-lib';
 import {
     Device,
     ForceDirectedGraph,
@@ -71,6 +71,7 @@
     @Output() selectedNodeEvent = new EventEmitter<UiElement>();
     @Input() selectedLink: RegionLink = null;
     @Input() showHosts: boolean = false;
+    @Input() highlightPorts: boolean = true;
     @Input() deviceLabelToggle: LabelToggle = LabelToggle.NONE;
     @Input() hostLabelToggle: HostLabelToggle = HostLabelToggle.NONE;
     @Input() regionData: Region = <Region>{devices: [ [], [], [] ], hosts: [ [], [], [] ], links: []};
@@ -85,7 +86,6 @@
 
     constructor(
         protected log: LogService,
-        protected is: IconService,
         private ref: ChangeDetectorRef
     ) {
         this.selectedLink = null;
@@ -141,10 +141,6 @@
         });
         this.log.debug('ForceSvgComponent initialized - waiting for nodes and links');
 
-        this.is.loadIconDef('m_switch');
-        this.is.loadIconDef('m_roadm');
-        this.is.loadIconDef('m_router');
-        this.is.loadIconDef('m_endstation');
     }
 
     /**
@@ -206,6 +202,10 @@
             this.showHosts = changes['showHosts'].currentValue;
         }
 
+        if (changes['highlightPorts']) {
+            this.highlightPorts = changes['highlightPorts'].currentValue;
+        }
+
         // Pass on the changes to device
         if (changes['deviceLabelToggle']) {
             this.deviceLabelToggle = changes['deviceLabelToggle'].currentValue;
@@ -258,7 +258,7 @@
      * @param selectedNode the newly selected node
      */
     updateSelected(selectedNode: UiElement): void {
-        this.log.debug('Node or link selected', selectedNode);
+        this.log.debug('Node or link selected', selectedNode ? selectedNode.id : 'none');
         this.devices
             .filter((d) =>
                 selectedNode === undefined || d.device.id !== selectedNode.id)
@@ -272,7 +272,7 @@
             .filter((l) =>
                 selectedNode === undefined || l.link.id !== selectedNode.id)
             .forEach((l) => l.deselect());
-
+        // Push the changes back up to parent (Topology Component)
         this.selectedNodeEvent.emit(selectedNode);
     }
 
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/models/link.ts b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/models/link.ts
index eb6d340..28f0b7c 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/models/link.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/models/link.ts
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-present Open Networking Foundation
+ * Copyright 2019-present Open Networking Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the 'License');
  * you may not use this file except in compliance with the License.
@@ -52,6 +52,13 @@
     source: Node;
     target: Node;
 
+    public static deviceNameFromEp(ep: string): string {
+        if (ep !== undefined && ep.lastIndexOf('/') > 0) {
+            return ep.substr(0, ep.lastIndexOf('/'));
+        }
+        return ep;
+    }
+
     constructor(source, target) {
         this.source = source;
         this.target = target;
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.html b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.html
index 70d4d5b..08ccaec 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.html
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.html
@@ -1,5 +1,5 @@
 <!--
-~ Copyright 2018-present Open Networking Foundation
+~ Copyright 2019-present Open Networking Foundation
 ~
 ~ Licensed under the Apache License, Version 2.0 (the "License");
 ~ you may not use this file except in compliance with the License.
@@ -84,9 +84,6 @@
             [@deviceLabelToggleTxt]="labelToggle">
         {{ labelToggle == 0 ? '': labelToggle == 1 ? device.id:device.props.name }}
     </svg:text>
-    <!-- It's not possible to drive the following xref dynamically -->
-    <svg:use *ngIf="device.type == 'switch'" xlink:href="#m_switch" width="36" height="36" x="-18" y="-18">
-    </svg:use>
-    <svg:use *ngIf="device.type == 'roadm'" xlink:href="#m_roadm" width="36" height="36" x="-18" y="-18">
+    <svg:use [attr.xlink:href]="'#m_' + device.type" width="36" height="36" x="-18" y="-18">
     </svg:use>
 </svg:g>
\ No newline at end of file
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/linksvg/linksvg.component.ts b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/linksvg/linksvg.component.ts
index 8202c67..af4d0a9 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/linksvg/linksvg.component.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/linksvg/linksvg.component.ts
@@ -53,6 +53,7 @@
 export class LinkSvgComponent extends NodeVisual implements OnChanges {
     @Input() link: Link;
     @Input() highlighted: string = '';
+    @Input() highlightsEnabled: boolean = true;
     @Input() label: string;
     isHighlighted: boolean = false;
     @Output() selectedEvent = new EventEmitter<UiElement>();
@@ -86,6 +87,9 @@
     }
 
     enhance() {
+        if (!this.highlightsEnabled) {
+            return;
+        }
         this.enhancedEvent.emit(this.link);
         this.enhanced = true;
         this.repositionLabels();
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/layout/layout.component.css b/web/gui2/src/main/webapp/app/view/topology/layer/layout/layout.component.css
deleted file mode 100644
index beb3725..0000000
--- a/web/gui2/src/main/webapp/app/view/topology/layer/layout/layout.component.css
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
\ No newline at end of file
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/layout/layout.component.html b/web/gui2/src/main/webapp/app/view/topology/layer/layout/layout.component.html
deleted file mode 100644
index 8fe566b..0000000
--- a/web/gui2/src/main/webapp/app/view/topology/layer/layout/layout.component.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!--
-~ Copyright 2018-present Open Networking Foundation
-~
-~ Licensed under the Apache License, Version 2.0 (the "License");
-~ you may not use this file except in compliance with the License.
-~ You may obtain a copy of the License at
-~
-~     http://www.apache.org/licenses/LICENSE-2.0
-~
-~ Unless required by applicable law or agreed to in writing, software
-~ distributed under the License is distributed on an "AS IS" BASIS,
-~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-~ See the License for the specific language governing permissions and
-~ limitations under the License.
--->
-<p>
-  layout works!
-</p>
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/layout/layout.component.spec.ts b/web/gui2/src/main/webapp/app/view/topology/layer/layout/layout.component.spec.ts
deleted file mode 100644
index 1691947..0000000
--- a/web/gui2/src/main/webapp/app/view/topology/layer/layout/layout.component.spec.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { LayoutComponent } from './layout.component';
-
-describe('LayoutComponent', () => {
-  let component: LayoutComponent;
-  let fixture: ComponentFixture<LayoutComponent>;
-
-  beforeEach(async(() => {
-    TestBed.configureTestingModule({
-      declarations: [ LayoutComponent ]
-    })
-    .compileComponents();
-  }));
-
-  beforeEach(() => {
-    fixture = TestBed.createComponent(LayoutComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-});
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/layout/layout.component.ts b/web/gui2/src/main/webapp/app/view/topology/layer/layout/layout.component.ts
deleted file mode 100644
index 122c14b..0000000
--- a/web/gui2/src/main/webapp/app/view/topology/layer/layout/layout.component.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { Component, OnInit } from '@angular/core';
-
-@Component({
-    selector: 'onos-layout',
-    templateUrl: './layout.component.html',
-    styleUrls: ['./layout.component.css']
-})
-export class LayoutComponent implements OnInit {
-
-    constructor() { }
-
-    ngOnInit() {
-    }
-
-}
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.html b/web/gui2/src/main/webapp/app/view/topology/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.html
index 9233713..17fba06 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.html
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.html
@@ -16,6 +16,6 @@
 <svg:g xmlns:svg="http://www.w3.org/2000/svg" id="topo-noDevsLayer" transform="translate(500,500)" style="visibility: visible;">
     <svg:g id="reposition" #reposition [attr.transform]="centre(reposition.getBBox())">
         <svg:use width="100" height="100" class="noDevsBird" href="#bird"></svg:use>
-        <svg:text x="120" y="80">No Devices Are Connected</svg:text>
+        <svg:text x="120" y="80">{{lionFn('no_devices_are_connected')}}</svg:text>
     </svg:g>
 </svg:g>
\ No newline at end of file
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.spec.ts b/web/gui2/src/main/webapp/app/view/topology/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.spec.ts
index a467a3d..891a3fb 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.spec.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.spec.ts
@@ -26,7 +26,7 @@
     UrlFnService,
     TableFilterPipe,
     IconComponent,
-    WebSocketService
+    WebSocketService, SvgUtilService, PrefsService
 } from 'gui2-fw-lib';
 import { of } from 'rxjs';
 
@@ -37,11 +37,6 @@
     }
 }
 
-class MockIconService {
-    classes = 'active-close';
-    loadIconDef() { }
-}
-
 class MockWebSocketService {
     createWebSocket() { }
     isConnected() { return false; }
@@ -49,6 +44,15 @@
     bindHandlers() { }
 }
 
+class MockSvgUtilService {
+    translate() {}
+    scale() {}
+}
+
+class MockPrefsService {
+}
+
+
 /**
  * ONOS GUI -- Topology NoDevicesConnected -- Unit Tests
  */
@@ -73,9 +77,10 @@
             declarations: [ NoDeviceConnectedSvgComponent ],
             providers: [
                 { provide: FnService, useValue: fs },
-                { provide: IconService, useClass: MockIconService },
                 { provide: LogService, useValue: logSpy },
+                { provide: SvgUtilService, useClass: MockSvgUtilService },
                 { provide: WebSocketService, useClass: MockWebSocketService },
+                { provide: PrefsService, useClass: MockPrefsService },
                 { provide: 'Window', useValue: windowMock },
             ]
         }).compileComponents();
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.ts b/web/gui2/src/main/webapp/app/view/topology/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.ts
index 2ff9ed1..a245fad 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.ts
@@ -20,7 +20,7 @@
     LogService,
     PrefsService,
     IconService,
-    SvgUtilService
+    SvgUtilService, LionService
 } from 'gui2-fw-lib';
 
 /**
@@ -37,16 +37,24 @@
   styleUrls: ['./nodeviceconnectedsvg.component.css']
 })
 export class NoDeviceConnectedSvgComponent extends ViewControllerImpl implements OnInit {
+    lionFn; // Function
 
     constructor(
         protected fs: FnService,
         protected log: LogService,
         protected ps: PrefsService,
-        protected is: IconService,
-        protected sus: SvgUtilService
+        protected sus: SvgUtilService,
+        private lion: LionService
     ) {
         super(fs, log, ps);
-        this.is.loadIconDef('bird');
+
+        if (this.lion.ubercache.length === 0) {
+            this.lionFn = this.dummyLion;
+            this.lion.loadCbs.set('topo-nodevices', () => this.doLion());
+        } else {
+            this.doLion();
+        }
+
         this.log.debug('NoDeviceConnectedSvgComponent constructed');
     }
 
@@ -64,4 +72,19 @@
         return this.sus.translate([repositionBox.x, repositionBox.y]) + '' + this.sus.scale(scale, scale);
     }
 
+    /**
+     * Read the LION bundle for Details panel and set up the lionFn
+     */
+    doLion() {
+        this.lionFn = this.lion.bundle('core.view.Topo');
+
+    }
+
+    /**
+     * A dummy implementation of the lionFn until the response is received and the LION
+     * bundle is received from the WebSocket
+     */
+    dummyLion(key: string): string {
+        return '%' + key + '%';
+    }
 }
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/zoomable.directive.ts b/web/gui2/src/main/webapp/app/view/topology/layer/zoomable.directive.ts
index c956627..bd69db1 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/zoomable.directive.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/zoomable.directive.ts
@@ -28,6 +28,9 @@
         private log: LogService,
     ) {}
 
+    /**
+     * If the input object is changed then re-establish the zoom
+     */
     ngOnChanges() {
         let zoomed, zoom;
 
@@ -44,4 +47,13 @@
         this.log.debug('Applying zoomable behaviour on', this.zoomableOf, this._element.nativeElement);
     }
 
+    /**
+     * Reset the zoom when the R key is pressed when in Topology view
+     */
+    resetZoom(): void {
+        const container = d3.select(this._element.nativeElement);
+        container.attr('transform', 'translate(0,0) scale(1.0)');
+        this.log.debug('Pan to 0,0 and zoom to 1.0');
+    }
+
 }
diff --git a/web/gui2/src/main/webapp/app/view/topology/panel/details/details.component.css b/web/gui2/src/main/webapp/app/view/topology/panel/details/details.component.css
index 9a35cb3..9ddfe17 100644
--- a/web/gui2/src/main/webapp/app/view/topology/panel/details/details.component.css
+++ b/web/gui2/src/main/webapp/app/view/topology/panel/details/details.component.css
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-present Open Networking Foundation
+ * Copyright 2019-present Open Networking Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,18 +19,18 @@
     padding: 16px;
     top: 370px;
 }
-html[data-platform='iPad'] #topo2-p-detail {
+html[data-platform='iPad'] {
     top: 386px;
 }
 
-#topo2-p-detail .actionBtns .actionBtn {
+.actionBtns .actionBtn {
     display: inline-block;
 }
-#topo2-p-detail .actionBtns .actionBtn svg {
+.actionBtns .actionBtn svg {
     width: 28px;
     height: 28px;
 }
 
-#topo2-p-detail  div.actionBtns {
+div.actionBtns {
     padding-top: 6px;
 }
\ No newline at end of file
diff --git a/web/gui2/src/main/webapp/app/view/topology/panel/details/details.component.html b/web/gui2/src/main/webapp/app/view/topology/panel/details/details.component.html
index d79954b..405fdfc 100644
--- a/web/gui2/src/main/webapp/app/view/topology/panel/details/details.component.html
+++ b/web/gui2/src/main/webapp/app/view/topology/panel/details/details.component.html
@@ -1,5 +1,5 @@
 <!--
-~ Copyright 2018-present Open Networking Foundation
+~ Copyright 2019-present Open Networking Foundation
 ~
 ~ Licensed under the Apache License, Version 2.0 (the "License");
 ~ you may not use this file except in compliance with the License.
@@ -15,112 +15,52 @@
 -->
 <div id="topo2-p-detail" class="floatpanel topo2-p"
      style="opacity: 1; right: 20px; width: 260px; top: 350px;" [@detailsPanelState]="on">
+    <!-- Template explanation - Create a HTML header which has an SVG icon along
+    side title text. -->
     <div class="header">
         <div class="icon clickable">
-            <svg>
-                <use width="26" height="26" class="glyph" xlink:href="#m_switch"></use>
-            </svg>
+            <onos-icon
+                    [iconSize]="26"
+                    [iconId]="showDetails?.glyphId">
+            </onos-icon>
         </div>
-        <h2 class="clickable">{{ selectedNode?.id }}</h2>
+        <h2 class="clickable">{{ showDetails?.title }}</h2>
     </div>
     <div class="body">
         <table>
             <tbody>
-            <tr>
-                <td class="label">URI :</td>
-                <td class="value">{{ selectedNode?.id }}</td>
-            </tr>
-            <tr>
-                <td class="label">Vendor :</td>
-                <td class="value">ONF</td>
-            </tr>
-            <tr>
-                <td class="label">H/W Version :</td>
-                <td class="value">0.1</td>
-            </tr>
-            <tr>
-                <td class="label">S/W Version :</td>
-                <td class="value">0.1</td>
-            </tr>
-            <tr>
-                <td class="label">Serial # :</td>
-                <td class="value">1234</td>
-            </tr>
-            <tr>
-                <td class="label">Protocol :</td>
-                <td class="value"></td>
-            </tr>
-            <tr>
-                <td colspan="2">
-                    <hr>
-                </td>
-            </tr>
-            <tr>
-                <td class="label">Ports :</td>
-                <td class="value">4</td>
-            </tr>
-            <tr>
-                <td class="label">Flows :</td>
-                <td class="value">4</td>
-            </tr>
-            <tr>
-                <td class="label">Tunnels :</td>
-                <td class="value">0</td>
-            </tr>
+            <!-- Template explanation - Inside a HTML table, create a row per
+            item in the propOrder array returned through the WSS showDetails.
+            If the row name contains only '-' then draw a horiz rule otherwise
+            create a cell for the name and another for the value -->
+                <tr *ngFor="let p of showDetails?.propOrder">
+                    <td *ngIf="showDetails?.propLabels[p] !== '-'"
+                        class="label">{{showDetails?.propLabels[p]}} :</td>
+                    <td *ngIf="showDetails?.propLabels[p] !== '-'"
+                        class="value">{{ showDetails?.propValues[p]}}</td>
+                    <!-- If the label is '-' then insert a horiz line -->
+                    <td *ngIf="showDetails?.propLabels[p] === '-'"
+                        colspan="2"><hr></td>
+                </tr>
             </tbody>
         </table>
     </div>
     <div class="footer">
         <hr>
         <div class="actionBtns">
-            <div class="actionBtn">
-                <div class="button" id="topo2-p-detail-core-showDeviceView">
-                    <svg class="embeddedIcon" width="25" height="25" viewBox="0 0 50 50">
-                        <g class="icon">
-                            <rect width="50" height="50" rx="5"></rect>
-                            <use width="50" height="50" class="glyph" xlink:href="#switch"></use>
-                        </g>
-                    </svg>
-                </div>
-            </div>
-            <div class="actionBtn">
-                <div class="button" id="topo2-p-detail-core-showFlowView">
-                    <svg class="embeddedIcon" width="25" height="25" viewBox="0 0 50 50">
-                        <g class="icon">
-                            <rect width="50" height="50" rx="5"></rect>
-                            <use width="50" height="50" class="glyph" xlink:href="#flowTable"></use>
-                        </g>
-                    </svg>
-                </div>
-            </div>
-            <div class="actionBtn">
-                <div class="button" id="topo2-p-detail-core-showPortView">
-                    <svg class="embeddedIcon" width="25" height="25" viewBox="0 0 50 50">
-                        <g class="icon">
-                            <rect width="50" height="50" rx="5"></rect>
-                            <use width="50" height="50" class="glyph" xlink:href="#portTable"></use>
-                        </g>
-                    </svg>
-                </div>
-            </div>
-            <div class="actionBtn">
-                <div class="button" id="topo2-p-detail-core-showGroupView">
-                    <svg class="embeddedIcon" width="25" height="25" viewBox="0 0 50 50">
-                        <g class="icon">
-                            <rect width="50" height="50" rx="5"></rect>
-                            <use width="50" height="50" class="glyph" xlink:href="#groupTable"></use>
-                        </g>
-                    </svg>
-                </div>
-            </div>
-            <div class="actionBtn">
-                <div class="button" id="topo2-p-detail-core-showMeterView">
-                    <svg class="embeddedIcon" width="25" height="25" viewBox="0 0 50 50">
-                        <g class="icon">
-                            <rect width="50" height="50" rx="5"></rect>
-                            <use width="50" height="50" class="glyph" xlink:href="#meterTable"></use>
-                        </g>
-                    </svg>
+            <!-- Template explanation - Inside the panel footer, create an SVG icon
+            per entry in the buttons array returned from the WSS showDetails
+            The icons used here are loaded in the ForceSvgComponent
+            -->
+            <div *ngFor="let btn of showDetails?.buttons" class="actionBtn">
+                <div class="button" id="topo2-p-detail-core-{{ btn }}"
+                     (click)="navto(buttonAttribs(btn).path, showDetails.navPath, showDetails.id)">
+                    <onos-icon
+                            [iconSize]="25"
+                            [iconId]="buttonAttribs(btn).gid"
+                            [toolTip]="lionFn(buttonAttribs(btn).tt)"
+                            classes="icon">
+                    </onos-icon>
                 </div>
             </div>
         </div>
diff --git a/web/gui2/src/main/webapp/app/view/topology/panel/details/details.component.spec.ts b/web/gui2/src/main/webapp/app/view/topology/panel/details/details.component.spec.ts
index 0c0c269..620d931 100644
--- a/web/gui2/src/main/webapp/app/view/topology/panel/details/details.component.spec.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/panel/details/details.component.spec.ts
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-present Open Networking Foundation
+ * Copyright 2019-present Open Networking Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,9 +20,10 @@
 import { DetailsComponent } from './details.component';
 
 import {
-    FnService,
-    LogService
+    FnService, LionService,
+    LogService, IconComponent
 } from 'gui2-fw-lib';
+import {RouterTestingModule} from '@angular/router/testing';
 
 class MockActivatedRoute extends ActivatedRoute {
     constructor(params: Params) {
@@ -42,6 +43,15 @@
     let component: DetailsComponent;
     let fixture: ComponentFixture<DetailsComponent>;
 
+    const bundleObj = {
+        'core.view.Flow': {
+            test: 'test1'
+        }
+    };
+    const mockLion = (key) => {
+        return bundleObj[key] || '%' + key + '%';
+    };
+
     beforeEach(async(() => {
         const logSpy = jasmine.createSpyObj('LogService', ['info', 'debug', 'warn', 'error']);
         ar = new MockActivatedRoute({ 'debug': 'txrx' });
@@ -60,11 +70,20 @@
         fs = new FnService(ar, logSpy, windowMock);
 
         TestBed.configureTestingModule({
-            imports: [ BrowserAnimationsModule ],
-            declarations: [ DetailsComponent ],
+            imports: [ BrowserAnimationsModule, RouterTestingModule ],
+            declarations: [ DetailsComponent, IconComponent ],
             providers: [
                 { provide: FnService, useValue: fs },
                 { provide: LogService, useValue: logSpy },
+                {
+                    provide: LionService, useFactory: (() => {
+                        return {
+                            bundle: ((bundleId) => mockLion),
+                            ubercache: new Array(),
+                            loadCbs: new Map<string, () => void>([])
+                        };
+                    })
+                },
                 { provide: 'Window', useValue: windowMock },
             ]
         })
diff --git a/web/gui2/src/main/webapp/app/view/topology/panel/details/details.component.ts b/web/gui2/src/main/webapp/app/view/topology/panel/details/details.component.ts
index 935b2ce..f63d99a 100644
--- a/web/gui2/src/main/webapp/app/view/topology/panel/details/details.component.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/panel/details/details.component.ts
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-present Open Networking Foundation
+ * Copyright 2019-present Open Networking Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,20 +13,77 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import {Component, Input, OnInit} from '@angular/core';
-import { animate, state, style, transition, trigger } from '@angular/animations';
 import {
-    LogService,
-    LoadingService,
-    FnService,
+    Component,
+    Input,
+    OnChanges,
+    OnDestroy,
+    OnInit,
+    SimpleChanges
+} from '@angular/core';
+import {animate, state, style, transition, trigger} from '@angular/animations';
+import {
     DetailsPanelBaseImpl,
+    FnService, LionService,
+    LoadingService,
+    LogService,
     WebSocketService
 } from 'gui2-fw-lib';
-import {Node} from '../../layer/forcesvg/models';
+import {Host, Link, LinkType, UiElement} from '../../layer/forcesvg/models';
+import {Params, Router} from '@angular/router';
 
-/*
- ONOS GUI -- Topology Details Panel.
- Displays details of selected device.
+
+interface ButtonAttrs {
+    gid: string;
+    tt: string;
+    path: string;
+}
+
+const SHOWDEVICEVIEW: ButtonAttrs = {
+    gid: 'deviceTable',
+    tt: 'tt_ctl_show_device',
+    path: 'device',
+};
+const SHOWFLOWVIEW: ButtonAttrs = {
+    gid: 'flowTable',
+    tt: 'title_flows',
+    path: 'flow',
+};
+const SHOWPORTVIEW: ButtonAttrs = {
+    gid: 'portTable',
+    tt: 'tt_ctl_show_port',
+    path: 'port',
+};
+const SHOWGROUPVIEW: ButtonAttrs = {
+    gid: 'groupTable',
+    tt: 'tt_ctl_show_group',
+    path: 'group',
+};
+const SHOWMETERVIEW: ButtonAttrs = {
+    gid: 'meterTable',
+    tt: 'tt_ctl_show_meter',
+    path: 'meter',
+};
+const SHOWPIPECONFVIEW: ButtonAttrs = {
+    gid: 'pipeconfTable',
+    tt: 'tt_ctl_show_pipeconf',
+    path: 'pipeconf',
+};
+
+interface ShowDetails {
+    buttons: string[];
+    glyphId: string;
+    id: string;
+    navPath: string;
+    propLabels: Object;
+    propOrder: string[];
+    propValues: Object;
+    title: string;
+}
+/**
+ * ONOS GUI -- Topology Details Panel.
+ * Displays details of selected device. When no device is selected the panel slides
+ * off to the side and disappears
  */
 @Component({
     selector: 'onos-details',
@@ -40,7 +97,7 @@
         trigger('detailsPanelState', [
             state('true', style({
                 transform: 'translateX(0%)',
-                opacity: '100'
+                opacity: '1.0'
             })),
             state('false', style({
                 transform: 'translateX(100%)',
@@ -51,21 +108,169 @@
         ])
     ]
 })
-export class DetailsComponent extends DetailsPanelBaseImpl implements OnInit {
-    @Input() selectedNode: Node = undefined;
+export class DetailsComponent extends DetailsPanelBaseImpl implements OnInit, OnDestroy, OnChanges {
+    @Input() selectedNode: UiElement = undefined; // Populated when user selects node or link
+
+    // deferred localization strings
+    lionFn; // Function
+    showDetails: ShowDetails; // Will be populated on callback. Cleared if nothing is selected
 
     constructor(
         protected fs: FnService,
         protected log: LogService,
         protected ls: LoadingService,
+        protected router: Router,
         protected wss: WebSocketService,
+        private lion: LionService
     ) {
         super(fs, ls, log, wss, 'topo');
-        this.log.debug('InstanceComponent constructed');
+
+        if (this.lion.ubercache.length === 0) {
+            this.lionFn = this.dummyLion;
+            this.lion.loadCbs.set('flow', () => this.doLion());
+        } else {
+            this.doLion();
+        }
+
+        this.log.debug('Topo DetailsComponent constructed');
     }
 
-    ngOnInit() {
+    /**
+     * When the component is initializing set up the handler for callbacks of
+     * ShowDetails from the WSS. Set the variable showDetails when ever a callback
+     * is made
+     */
+    ngOnInit(): void {
         this.on = false;
+        this.wss.bindHandlers(new Map<string, (data) => void>([
+            ['showDetails', (data) => {
+                    this.showDetails = data;
+                    // this.log.debug('showDetails received', data);
+                }
+            ]
+        ]));
+        this.log.debug('Topo DetailsComponent initialized');
+    }
+
+    /**
+     * When the component is being unloaded then unbind the WSS handler.
+     */
+    ngOnDestroy(): void {
+        this.wss.unbindHandlers(['showDetails']);
+        this.log.debug('Topo DetailsComponent destroyed');
+    }
+
+    /**
+     * If changes are detected on the Input param selectedNode, call on WSS sendEvent
+     * Note the difference in call to the WSS with requestDetails between a node
+     * and a link - the handling is done in TopologyViewMessageHandler#RequestDetails.process()
+     *
+     * The WSS will call back asynchronously (see fn in ngOnInit())
+     *
+     * @param changes Simple Changes set of updates
+     */
+    ngOnChanges(changes: SimpleChanges): void {
+        if (changes['selectedNode']) {
+            this.selectedNode = changes['selectedNode'].currentValue;
+            let type: any;
+
+            if (this.selectedNode === undefined) {
+                // Selection has been cleared
+                this.showDetails = <ShowDetails>{};
+                return;
+            }
+
+            if (this.selectedNode.hasOwnProperty('nodeType')) { // For Device, Host, SubRegion
+                type = (<Host>this.selectedNode).nodeType;
+                this.wss.sendEvent('requestDetails', {
+                    id: this.selectedNode.id,
+                    class: type,
+                });
+            } else if (this.selectedNode.hasOwnProperty('type')) { // Must be link
+                const link: Link = <Link>this.selectedNode;
+                if (<LinkType><unknown>LinkType[link.type] === LinkType.UiEdgeLink) { // Number based enum
+                    this.wss.sendEvent('requestDetails', {
+                        key: link.id,
+                        class: 'link',
+                        sourceId: link.epA,
+                        targetId: Link.deviceNameFromEp(link.epB),
+                        targetPort: link.portB,
+                        isEdgeLink: true
+                    });
+                } else {
+                    this.wss.sendEvent('requestDetails', {
+                        key: link.id,
+                        class: 'link',
+                        sourceId: Link.deviceNameFromEp(link.epA),
+                        sourcePort: link.portA,
+                        targetId: Link.deviceNameFromEp(link.epB),
+                        targetPort: link.portB,
+                        isEdgeLink: false
+                    });
+                }
+            } else {
+                this.log.warn('Unexpected type for selected element', this.selectedNode);
+            }
+        } else {
+            this.log.warn('Unexpected change in Topo DetailsComponent');
+        }
+    }
+
+    /**
+     * Table of core button attributes to return per button icon
+     * @param btnName The name of the button
+     * @returns A structure with the button attributes
+     */
+    buttonAttribs(btnName: string): ButtonAttrs {
+        switch (btnName) {
+            case 'showDeviceView':
+                return SHOWDEVICEVIEW;
+            case 'showFlowView':
+                return SHOWFLOWVIEW;
+            case 'showPortView':
+                return SHOWPORTVIEW;
+            case 'showGroupView':
+                return SHOWGROUPVIEW;
+            case 'showMeterView':
+                return SHOWMETERVIEW;
+            case 'showPipeConfView':
+                return SHOWPIPECONFVIEW;
+            default:
+                return <ButtonAttrs>{
+                    gid: btnName,
+                    path: btnName
+                };
+        }
+    }
+
+    /**
+     * Navigate using Angular Routing. Combines the parameters to generate a relative URL
+     * e.g. if params are 'meter', 'device' and 'null:0000000000001' then the
+     * navigation URL will become "http://localhost:4200/#/meter?devId=null:0000000000000002"
+     *
+     * @param path The path to navigate to
+     * @param navPath The parameter name to use
+     * @param selId the parameter value to use
+     */
+    navto(path: string, navPath: string, selId: string): void {
+        this.log.debug('navigate to', path, 'for', navPath, '=', selId);
+        // Special case until it's fixed
+        if (selId) {
+            if (navPath === 'device') {
+                navPath = 'devId';
+            }
+            const queryPar: Params = {};
+            queryPar[navPath] = selId;
+            this.router.navigate([path], { queryParams: queryPar });
+        }
+    }
+
+    /**
+     * Read the LION bundle for Details panel and set up the lionFn
+     */
+    doLion() {
+        this.lionFn = this.lion.bundle('core.view.Flow');
+
     }
 
 }
diff --git a/web/gui2/src/main/webapp/app/view/topology/panel/instance/instance.component.html b/web/gui2/src/main/webapp/app/view/topology/panel/instance/instance.component.html
index 0cb4a0b..f5a2859 100644
--- a/web/gui2/src/main/webapp/app/view/topology/panel/instance/instance.component.html
+++ b/web/gui2/src/main/webapp/app/view/topology/panel/instance/instance.component.html
@@ -13,7 +13,7 @@
 ~ See the License for the specific language governing permissions and
 ~ limitations under the License.
 -->
-<div id="topo-p-instance" class="floatpanel" [ngStyle]="{'left': '20px', 'top':divTopPx+'px', 'width': (onosInstances.length * 170)+'px', 'height': '85px'}" [@instancePanelState]="!on">
+<div id="topo-p-instance" class="floatpanel" [ngStyle]="{'left': '20px', 'top':divTopPx+'px', 'width': (onosInstances.length * 170)+'px', 'height': '85px'}" [@instancePanelState]="on">
     <div *ngFor="let inst of onosInstances | keyvalue ; let i=index"
          [ngClass]="['onosInst', inst.value.online?'online':'', inst.value.ready? 'ready': '', mastership?'mastership':'', 'affinity']"
             (click)="chooseMastership(inst.value.id)">
@@ -33,7 +33,7 @@
             <text class="instLabel ip" x="48" y="55">{{ inst.value.ip }}</text>
             <use width="20" height="20" class="glyph badgeIcon bird" xlink:href="#bird" transform="translate(15,10)"></use>
             <use *ngIf="inst.value.ready" width="16" height="16" class="glyph overlay badgeIcon readyBadge" xlink:href="#checkMark" transform="translate(18,40)"></use>
-            <text class="instLabel ns" x="48" y="73">Devices: {{ inst.value.switches }}</text>
+            <text class="instLabel ns" x="48" y="73">{{lionFn('devices')}} {{ inst.value.switches }}</text>
             <use *ngIf="inst.value.uiAttached" width="24" height="24" class="glyph overlay badgeIcon uiBadge" xlink:href="#uiAttached" transform="translate(14,54)"></use>
         </svg>
     </div>
diff --git a/web/gui2/src/main/webapp/app/view/topology/panel/instance/instance.component.ts b/web/gui2/src/main/webapp/app/view/topology/panel/instance/instance.component.ts
index 05e8768..b30c706 100644
--- a/web/gui2/src/main/webapp/app/view/topology/panel/instance/instance.component.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/panel/instance/instance.component.ts
@@ -26,7 +26,7 @@
     FnService,
     PanelBaseImpl,
     IconService,
-    SvgUtilService
+    SvgUtilService, LionService
 } from 'gui2-fw-lib';
 
 /**
@@ -77,18 +77,26 @@
     @Output() mastershipEvent = new EventEmitter<string>();
     public onosInstances: Array<Instance>;
     protected mastership: string;
+    lionFn; // Function
 
     constructor(
         protected fs: FnService,
         protected log: LogService,
         protected ls: LoadingService,
         protected is: IconService,
-        protected sus: SvgUtilService
+        protected sus: SvgUtilService,
+        private lion: LionService
     ) {
         super(fs, ls, log);
         this.onosInstances = <Array<Instance>>[];
-        this.is.loadIconDef('active');
-        this.is.loadIconDef('uiAttached');
+
+        if (this.lion.ubercache.length === 0) {
+            this.lionFn = this.dummyLion;
+            this.lion.loadCbs.set('topo-inst', () => this.doLion());
+        } else {
+            this.doLion();
+        }
+        this.on = true;
         this.log.debug('InstanceComponent constructed');
     }
 
@@ -114,4 +122,12 @@
         this.mastershipEvent.emit(this.mastership);
         this.log.debug('Instance', this.mastership, 'chosen on GUI');
     }
+
+    /**
+     * Read the LION bundle for Details panel and set up the lionFn
+     */
+    doLion() {
+        this.lionFn = this.lion.bundle('core.view.Topo');
+
+    }
 }
diff --git a/web/gui2/src/main/webapp/app/view/topology/panel/summary/summary.component.ts b/web/gui2/src/main/webapp/app/view/topology/panel/summary/summary.component.ts
index c1c41f8..a520c86 100644
--- a/web/gui2/src/main/webapp/app/view/topology/panel/summary/summary.component.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/panel/summary/summary.component.ts
@@ -70,6 +70,7 @@
     ) {
         super(fs, ls, log, 'summary');
         this.summaryData = <SummaryResponse>{};
+        this.on = true;
         this.log.debug('SummaryComponent constructed');
     }
 
diff --git a/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/button.css b/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/button.css
new file mode 100644
index 0000000..1effdbc
--- /dev/null
+++ b/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/button.css
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ ONOS GUI -- Button Service (layout) -- CSS file
+ */
+
+.button,
+.toggleButton,
+.radioSet {
+    display: inline-block;
+    padding: 0 4px;
+}
+.radioButton {
+    display: inline-block;
+    padding: 0 2px;
+}
+
+.button svg.embeddedIcon,
+.toggleButton svg.embeddedIcon,
+.radioButton svg.embeddedIcon {
+    cursor: pointer;
+}
+.button svg.embeddedIcon .icon rect,
+.toggleButton svg.embeddedIcon .icon rect,
+.radioButton svg.embeddedIcon .icon rect{
+    stroke: none;
+}
diff --git a/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.component.css b/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.component.css
index 9dca44c..449d436 100644
--- a/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.component.css
+++ b/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.component.css
@@ -18,6 +18,40 @@
 /*
  ONOS GUI -- Topology Toolbar Panel -- CSS file
  */
+
+
+
+div.tbar-arrow {
+    position: absolute;
+    top: 53%;
+    left: 96%;
+    margin-right: -4%;
+    transform: translate(-50%, -50%);
+    cursor: pointer;
+}
+.safari div.tbar-arrow {
+    top: 46%;
+}
+.firefox div.tbar-arrow {
+    left: 97%;
+    margin-right: -3%;
+}
+
+.toolbar {
+    line-height: 125%;
+}
+.tbar-row {
+    display: inline-block;
+}
+
+.separator {
+    border: 1px solid;
+    margin: 0 4px 0 4px;
+    display: inline-block;
+    height: 23px;
+    width: 0;
+}
+
 #toolbar-topo2-toolbar {
     padding: 6px;
 }
diff --git a/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.component.html b/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.component.html
index ae25507..693e1b5 100644
--- a/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.component.html
+++ b/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.component.html
@@ -15,117 +15,52 @@
 -->
 <div id="toolbar-topo2-toolbar" class="floatpanel toolbar" [@toolbarState]="on"
      style="opacity: 1; left: 0px; width: 261px; top: auto; bottom: 10px;">
-    <div class="tbar-arrow">
-        <svg class="embeddedIcon" width="10" height="10" viewBox="0 0 50 50">
-            <g class="icon" transform="translate(0 50) rotate(-90)">
-                <rect width="50" height="50" rx="5"></rect>
-                <use width="50" height="50" class="glyph" xlink:href="#triangleUp"></use>
-            </g>
-        </svg>
+    <div class="tbar-arrow" (click)="on =! on">
+        <onos-icon [iconSize]="10" [iconId]="on?'triangleLeft':'triangleRight'"></onos-icon>
     </div>
-    <div class="tbar-row">
-        <div class="toggleButton selected" id="toolbar-topo2-toolbar-topo2-instance-tog">
-            <svg class="embeddedIcon" width="25" height="25" viewBox="0 0 50 50">
-                <g class="icon">
-                    <rect width="50" height="50" rx="5"></rect>
-                    <use width="50" height="50" class="glyph" xlink:href="#m_uiAttached"></use>
-                </g>
-            </svg>
+    <div class="tbar-row ctrl-btns">
+        <div class="toggleButton" id="toolbar-topo2-toolbar-topo2-instance-tog" (click)="buttonClicked('instance-tog')">
+            <onos-icon [iconSize]="25" iconId="m_uiAttached" [toolTip]="lionFn('tbtt_tog_instances')" [classes]="['toggleButton', instancesVisible?'selected':'']"></onos-icon>
         </div>
-        <div class="toggleButton selected" id="toolbar-topo2-toolbar-topo2-summary-tog">
-            <svg class="embeddedIcon" width="25" height="25" viewBox="0 0 50 50">
-                <g class="icon">
-                    <rect width="50" height="50" rx="5"></rect>
-                    <use width="50" height="50" class="glyph" xlink:href="#m_summary"></use>
-                </g>
-            </svg>
+        <div class="toggleButton" id="toolbar-topo2-toolbar-topo2-summary-tog" (click)="buttonClicked('summary-tog')">
+            <onos-icon [iconSize]="25" iconId="m_summary" [toolTip]="lionFn('tbtt_tog_summary')" [classes]="['toggleButton', summaryVisible?'selected':'']"></onos-icon>
         </div>
-        <div class="toggleButton selected" id="toolbar-topo2-toolbar-details-tog">
-            <svg class="embeddedIcon" width="25" height="25" viewBox="0 0 50 50">
-                <g class="icon">
-                    <rect width="50" height="50" rx="5"></rect>
-                    <use width="50" height="50" class="glyph" xlink:href="#m_details"></use>
-                </g>
-            </svg>
+        <div class="toggleButton" id="toolbar-topo2-toolbar-details-tog" (click)="buttonClicked('details-tog')">
+            <onos-icon [iconSize]="25" iconId="m_details" [toolTip]="lionFn('tbtt_tog_use_detail')" [classes]="['toggleButton', detailsVisible?'selected':'']"></onos-icon>
         </div>
         <div class="separator"></div>
-        <div class="toggleButton" id="toolbar-topo2-toolbar-hosts-tog">
-            <svg class="embeddedIcon" width="25" height="25" viewBox="0 0 50 50">
-                <g class="icon">
-                    <rect width="50" height="50" rx="5"></rect>
-                    <use width="50" height="50" class="glyph" xlink:href="#m_endstation"></use>
-                </g>
-            </svg>
+        <div class="toggleButton" id="toolbar-topo2-toolbar-hosts-tog" (click)="buttonClicked('hosts-tog')">
+            <onos-icon [iconSize]="25" iconId="m_endstation" [toolTip]="lionFn('tbtt_tog_host')" [classes]="['toggleButton', hostsVisible?'selected':'']"></onos-icon>
         </div>
-        <div class="toggleButton selected" id="toolbar-topo2-toolbar-offline-tog">
-            <svg class="embeddedIcon" width="25" height="25" viewBox="0 0 50 50">
-                <g class="icon">
-                    <rect width="50" height="50" rx="5"></rect>
-                    <use width="50" height="50" class="glyph" xlink:href="#m_switch"></use>
-                </g>
-            </svg>
+        <div class="toggleButton" id="toolbar-topo2-toolbar-offline-tog" (click)="buttonClicked('offline-tog')">
+            <onos-icon [iconSize]="25" iconId="m_switch" [toolTip]="lionFn('tbtt_tog_offline')" classes="toggleButton selected"></onos-icon>
         </div>
-        <div class="toggleButton selected" id="toolbar-topo2-toolbar-topo2-ports-tog">
-            <svg class="embeddedIcon" width="25" height="25" viewBox="0 0 50 50">
-                <g class="icon">
-                    <rect width="50" height="50" rx="5"></rect>
-                    <use width="50" height="50" class="glyph" xlink:href="#m_ports"></use>
-                </g>
-            </svg>
+        <div class="toggleButton" id="toolbar-topo2-toolbar-topo2-ports-tog" (click)="buttonClicked('ports-tog')">
+            <onos-icon [iconSize]="25" iconId="m_ports" [toolTip]="lionFn('tbtt_tog_porthi')" classes="toggleButton selected" [classes]="['toggleButton', portsVisible?'selected':'']"></onos-icon>
         </div>
-        <div class="toggleButton selected" id="toolbar-topo2-toolbar-topo2-bkgrnd-tog">
-            <svg class="embeddedIcon" width="25" height="25" viewBox="0 0 50 50">
-                <g class="icon">
-                    <rect width="50" height="50" rx="5"></rect>
-                    <use width="50" height="50" class="glyph" xlink:href="#m_map"></use>
-                </g>
-            </svg>
+        <div class="toggleButton" id="toolbar-topo2-toolbar-topo2-bkgrnd-tog" (click)="buttonClicked('bkgrnd-tog')">
+            <onos-icon [iconSize]="25" iconId="m_map" [toolTip]="lionFn('tbtt_tog_map')" classes="toggleButton selected" [classes]="['toggleButton', backgroundVisible?'selected':'']"></onos-icon>
         </div>
     </div>
     <br>
     <div class="tbar-row">
-        <div class="button" id="toolbar-topo2-toolbar-topo2-cycleLabels-btn">
-            <svg class="embeddedIcon" width="25" height="25" viewBox="0 0 50 50">
-                <g class="icon">
-                    <rect width="50" height="50" rx="5"></rect>
-                    <use width="50" height="50" class="glyph" xlink:href="#m_cycleLabels"></use>
-                </g>
-            </svg>
+        <div class="button" id="toolbar-topo2-toolbar-topo2-cycleLabels-btn" (click)="buttonClicked('cycleLabels-btn')">
+            <onos-icon [iconSize]="25" iconId="m_cycleLabels" [toolTip]="lionFn('tbtt_cyc_dev_labs')" classes="button"></onos-icon>
         </div>
-        <div class="button" id="toolbar-topo2-toolbar-topo2-resetZoom-btn">
-            <svg class="embeddedIcon" width="25" height="25" viewBox="0 0 50 50">
-                <g class="icon">
-                    <rect width="50" height="50" rx="5"></rect>
-                    <use width="50" height="50" class="glyph" xlink:href="#m_resetZoom"></use>
-                </g>
-            </svg>
+        <div class="button" id="toolbar-topo2-toolbar-topo2-resetZoom-btn" (click)="buttonClicked('resetZoom-btn')">
+            <onos-icon [iconSize]="25" iconId="m_resetZoom" [toolTip]="lionFn('tbtt_reset_zoom')" classes="button"></onos-icon>
         </div>
         <div class="separator"></div>
-        <div class="button" id="toolbar-topo2-toolbar-topo2-eqMaster-btn">
-            <svg class="embeddedIcon" width="25" height="25" viewBox="0 0 50 50">
-                <g class="icon">
-                    <rect width="50" height="50" rx="5"></rect>
-                    <use width="50" height="50" class="glyph" xlink:href="#m_eqMaster"></use>
-                </g>
-            </svg>
+        <div class="button" id="toolbar-topo2-toolbar-topo2-eqMaster-btn" (click)="buttonClicked('eqMaster-btn')">
+            <onos-icon [iconSize]="25" iconId="m_eqMaster" [toolTip]="lionFn('tbtt_eq_master')" classes="button"></onos-icon>
         </div>
         <div class="separator"></div>
-        <div class="radioSet" id="toolbar-topo2-toolbar-topo-overlays">
-            <div class="radioButton selected" id="toolbar-topo2-toolbar-topo-overlays-0">
-                <svg class="embeddedIcon" width="25" height="25" viewBox="0 0 50 50">
-                    <g class="icon">
-                        <rect width="50" height="50" rx="5"></rect>
-                        <use width="50" height="50" class="glyph" xlink:href="#m_unknown"></use>
-                    </g>
-                </svg>
+        <div class="radioSet" id="toolbar-topo2-traffic">
+            <div class="radioButton selected" id="toolbar-topo2-cancel-traffic" (click)="buttonClicked('cancel-traffic')">
+                <onos-icon [iconSize]="25" iconId="m_unknown" [toolTip]="lionFn('tr_btn_cancel_monitoring')" classes="radioButton selected"></onos-icon>
             </div>
-            <div class="radioButton" id="toolbar-topo2-toolbar-topo-overlays-1">
-                <svg class="embeddedIcon" width="25" height="25" viewBox="0 0 50 50">
-                    <g class="icon">
-                        <rect width="50" height="50" rx="5"></rect>
-                        <use width="50" height="50" class="glyph" xlink:href="#m_allTraffic"></use>
-                    </g>
-                </svg>
+            <div class="radioButton" id="toolbar-topo2-all-traffic" (click)="buttonClicked('all-traffic')">
+                <onos-icon [iconSize]="25" iconId="m_allTraffic" [toolTip]="lionFn('tr_btn_show_related_traffic')" classes="radioButton selected"></onos-icon>
             </div>
         </div>
     </div>
diff --git a/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.component.spec.ts b/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.component.spec.ts
index 90a629e..91c1de4 100644
--- a/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.component.spec.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.component.spec.ts
@@ -19,8 +19,8 @@
 import { ToolbarComponent } from './toolbar.component';
 
 import {
-    FnService,
-    LogService
+    FnService, LionService,
+    LogService, IconComponent
 } from 'gui2-fw-lib';
 import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
 
@@ -42,6 +42,15 @@
     let component: ToolbarComponent;
     let fixture: ComponentFixture<ToolbarComponent>;
 
+    const bundleObj = {
+        'core.view.Topo': {
+            test: 'test1'
+        }
+    };
+    const mockLion = (key) => {
+        return bundleObj[key] || '%' + key + '%';
+    };
+
     beforeEach(async(() => {
         const logSpy = jasmine.createSpyObj('LogService', ['info', 'debug', 'warn', 'error']);
         ar = new MockActivatedRoute({ 'debug': 'txrx' });
@@ -60,10 +69,19 @@
         fs = new FnService(ar, logSpy, windowMock);
         TestBed.configureTestingModule({
             imports: [ BrowserAnimationsModule ],
-            declarations: [ ToolbarComponent ],
+            declarations: [ ToolbarComponent, IconComponent ],
             providers: [
                 { provide: FnService, useValue: fs },
                 { provide: LogService, useValue: logSpy },
+                {
+                    provide: LionService, useFactory: (() => {
+                        return {
+                            bundle: ((bundleId) => mockLion),
+                            ubercache: new Array(),
+                            loadCbs: new Map<string, () => void>([])
+                        };
+                    })
+                },
                 { provide: 'Window', useValue: windowMock },
             ]
         })
diff --git a/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.component.ts b/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.component.ts
index 2addffe..1ec3dbb 100644
--- a/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.component.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.component.ts
@@ -13,12 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import { Component, OnInit } from '@angular/core';
+import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
 import {
     LogService,
     LoadingService,
     FnService,
-    PanelBaseImpl
+    PanelBaseImpl, LionService
 } from 'gui2-fw-lib';
 import {animate, state, style, transition, trigger} from '@angular/animations';
 
@@ -32,36 +32,96 @@
     styleUrls: [
         './toolbar.component.css', './toolbar.theme.css',
         '../../topology.common.css',
-        '../../../../fw/widget/panel.css', '../../../../fw/widget/panel-theme.css'
+        '../../../../fw/widget/panel.css', '../../../../fw/widget/panel-theme.css',
+        './button.css'
     ],
     animations: [
         trigger('toolbarState', [
             state('true', style({
                 transform: 'translateX(0%)',
-                opacity: '1.0'
+                // opacity: '1.0'
             })),
             state('false', style({
-                transform: 'translateX(-100%)',
-                opacity: '0.0'
+                transform: 'translateX(-93%)',
+                // opacity: '0.0'
             })),
-            transition('0 => 1', animate('100ms ease-in')),
-            transition('1 => 0', animate('100ms ease-out'))
+            transition('0 => 1', animate('500ms ease-in')),
+            transition('1 => 0', animate('500ms ease-out'))
         ])
     ]
 })
 export class ToolbarComponent extends PanelBaseImpl implements OnInit {
+    // deferred localization strings
+    lionFn; // Function
+    // Used to drive the display of the hosts icon - there is also another such variable on the forcesvg
+    @Input() hostsVisible: boolean = false;
+    @Input() instancesVisible: boolean = true;
+    @Input() summaryVisible: boolean = true;
+    @Input() detailsVisible: boolean = true;
+    @Input() backgroundVisible: boolean = false;
+    @Input() portsVisible: boolean = true;
+
+    @Output() buttonEvent = new EventEmitter<string>();
 
     constructor(
         protected fs: FnService,
         protected log: LogService,
         protected ls: LoadingService,
+        private lion: LionService
     ) {
         super(fs, ls, log);
         this.on = false;
+
+        if (this.lion.ubercache.length === 0) {
+            this.lionFn = this.dummyLion;
+            this.lion.loadCbs.set('topo-toolbar', () => this.doLion());
+        } else {
+            this.doLion();
+        }
+
         this.log.debug('ToolbarComponent constructed');
     }
 
     ngOnInit() {
     }
 
+    /**
+     * Read the LION bundle for Toolbar and set up the lionFn
+     */
+    doLion() {
+        this.lionFn = this.lion.bundle('core.view.Topo');
+    }
+
+    /**
+     * As buttons are clicked on the toolbar, emit events up to the parent
+     *
+     * The toggling of the input variables here is in addition to the control
+     * of these input variables from the parent. This is so that this component
+     * may be reused and is not dependent on a particular parent implementation
+     * to work
+     * @param name The name of button clicked.
+     */
+    buttonClicked(name: string): void {
+        switch (name) {
+            case 'hosts-tog':
+                this.hostsVisible = !this.hostsVisible;
+                break;
+            case 'instance-tog':
+                this.instancesVisible = !this.instancesVisible;
+                break;
+            case 'summary-tog':
+                this.summaryVisible = !this.summaryVisible;
+                break;
+            case 'details-tog':
+                this.detailsVisible = !this.detailsVisible;
+                break;
+            case 'bkgrnd-tog':
+                this.backgroundVisible = !this.backgroundVisible;
+                break;
+            default:
+                this.log.warn('Unhandled toolbar click', name);
+        }
+        // Send a message up to let TopologyComponent know of the event
+        this.buttonEvent.emit(name);
+    }
 }
diff --git a/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.theme.css b/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.theme.css
index fcd9157..7933ee6 100644
--- a/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.theme.css
+++ b/web/gui2/src/main/webapp/app/view/topology/panel/toolbar/toolbar.theme.css
@@ -15,9 +15,39 @@
  */
 
 
-/*
- ONOS GUI -- Topology Toolbar Panel -- Theme CSS file
+/**
+ * ONOS GUI -- Topology Toolbar Panel -- Theme CSS file
  */
+.tbar-arrow svg.embeddedIcon .icon rect {
+    stroke: none;
+}
+
+.tbar-arrow svg.embeddedIcon .icon .glyph {
+    fill: #838383;
+}
+
+.tbar-arrow svg.embeddedIcon .icon rect {
+    fill: none;
+}
+
+.separator {
+    border-color: #ddd;
+}
+
+/* ========== DARK Theme ========== */
+
+.dark .tbar-arrow svg.embeddedIcon .icon .glyph {
+    fill: #B2B2B2;
+}
+
+.dark .tbar-arrow svg.embeddedIcon .icon rect {
+    fill: none;
+}
+
+.dark .separator {
+    border-color: #454545;
+}
+
 .dark #toolbar-topo2-toolbar .tbar-row.right {
     color: #666;
 }
\ No newline at end of file
diff --git a/web/gui2/src/main/webapp/app/view/topology/topology.module.ts b/web/gui2/src/main/webapp/app/view/topology/topology.module.ts
index 3d9debc..e7fe739 100644
--- a/web/gui2/src/main/webapp/app/view/topology/topology.module.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/topology.module.ts
@@ -18,7 +18,6 @@
 import { TopologyRoutingModule } from './topology-routing.module';
 import { TopologyComponent } from './topology/topology.component';
 import { NoDeviceConnectedSvgComponent } from './layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component';
-import { LayoutComponent } from './layer/layout/layout.component';
 import { InstanceComponent } from './panel/instance/instance.component';
 import { SummaryComponent } from './panel/summary/summary.component';
 import { ToolbarComponent } from './panel/toolbar/toolbar.component';
@@ -39,6 +38,8 @@
 /**
  * ONOS GUI -- Topology View Module
  *
+ * The main entry point is the TopologyComponent
+ *
  * Note: This has been updated from onos-gui-1.0.0 where it was called 'topo2'
  * whereas here it is now called 'topology'. This also merges in the old 'topo'
  */
@@ -51,7 +52,6 @@
     declarations: [
         TopologyComponent,
         NoDeviceConnectedSvgComponent,
-        LayoutComponent,
         InstanceComponent,
         SummaryComponent,
         ToolbarComponent,
diff --git a/web/gui2/src/main/webapp/app/view/topology/topology.service.ts b/web/gui2/src/main/webapp/app/view/topology/topology.service.ts
index 9422a3f..2c5d777 100644
--- a/web/gui2/src/main/webapp/app/view/topology/topology.service.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/topology.service.ts
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-present Open Networking Foundation
+ * Copyright 2019-present Open Networking Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -49,12 +49,12 @@
     init(instance: InstanceComponent, background: BackgroundSvgComponent, force: ForceSvgComponent) {
         this.wss.bindHandlers(new Map<string, (data) => void>([
             ['topo2AllInstances', (data) => {
-                    this.log.warn('Add fn for topo2AllInstances callback', data);
+                    this.log.debug('Instances updated through WSS as topo2AllInstances', data);
                     instance.onosInstances = data.members;
                 }
             ],
             ['topo2CurrentLayout', (data) => {
-                    this.log.warn('Add fn for topo2CurrentLayout callback', data);
+                    this.log.debug('Background Data updated from WSS as topo2CurrentLayout', data);
                     if (background) {
                         background.layoutData = data;
                     }
@@ -65,19 +65,20 @@
                     force.ngOnChanges({
                         'regionData' : new SimpleChange(<Region>{}, data, true)
                     });
-                    this.log.warn('Add fn for topo2CurrentRegion callback', force.regionData);
+                    this.log.debug('Region Data replaced from WSS as topo2CurrentRegion', force.regionData);
                 }
             ],
             ['topo2PeerRegions', (data) => { this.log.warn('Add fn for topo2PeerRegions callback', data); } ],
             ['topo2UiModelEvent', (event) => {
                     // this.log.debug('Handling', event);
                     force.handleModelEvent(
-                        <ModelEventType><unknown>(ModelEventType[event.type]),
-                        <ModelEventMemo>(event.memo),
+                        <ModelEventType><unknown>(ModelEventType[event.type]), // Number based enum
+                        <ModelEventMemo>(event.memo), // String based enum
                         event.subject, event.data);
+                    this.log.debug('Region Data updated from WSS as topo2UiModelEvent', force.regionData);
                 }
             ],
-            // ['topo2Highlights', (data) => { this.log.warn('Add fn for topo2Highlights callback', data); } ],
+            // topo2Highlights is handled by TrafficService
         ]));
         this.handlers.push('topo2AllInstances');
         this.handlers.push('topo2CurrentLayout');
diff --git a/web/gui2/src/main/webapp/app/view/topology/topology/topology.component.html b/web/gui2/src/main/webapp/app/view/topology/topology/topology.component.html
index 2a654b7..6fe0cb1 100644
--- a/web/gui2/src/main/webapp/app/view/topology/topology/topology.component.html
+++ b/web/gui2/src/main/webapp/app/view/topology/topology/topology.component.html
@@ -1,5 +1,5 @@
 <!--
-~ Copyright 2018-present Open Networking Foundation
+~ Copyright 2019-present Open Networking Foundation
 ~
 ~ Licensed under the Apache License, Version 2.0 (the "License");
 ~ you may not use this file except in compliance with the License.
@@ -13,17 +13,42 @@
 ~ See the License for the specific language governing permissions and
 ~ limitations under the License.
 -->
+<!-- Template explaination - Add in the flash message component - and link it to
+the local variable - this is used to display messages when keyboard shortcuts are pressed
+-->
 <onos-flash id="topoMsgFlash" message="{{ flashMsg }}" (closed)="flashMsg = ''"></onos-flash>
 
+<!-- Template explanation - Add in the Panel components for the Topology view
+    These are referenced inside the typescript by @ViewChild and their label
+-->
 <onos-instance #instance [divTopPx]="80" (mastershipEvent)="force.onosInstMastership = $event"></onos-instance>
 <onos-summary #summary></onos-summary>
-<onos-toolbar #toolbar></onos-toolbar>
+<onos-toolbar #toolbar (buttonEvent)="toolbarButtonClicked($event)"></onos-toolbar>
 <onos-details #details></onos-details>
 
 <div id="ov-topo2">
+    <!-- Template explanation -
+    Line 0) This is the root of the whole SVG canvas of the Topology View - all
+        components beneath it are SVG components only (no HTML)
+    line 1) the No Devices Connected banner is shown if the force component
+        (from line 4) does not contain any devices
+    line 2) Create an SVG Grouping and apply the onosZoomableOf directive to it,
+        passing in the whole SVG canvas (#svgZoom)
+    line 3) Add in the Background Svg Component (if showBackground is true - toggled
+        by toolbar and by keyboard shortcut 'B'
+    line 4) Add in the layer of the Force Svg Component. If any item is selected on it, pass
+        to the details view and deselect all others. This is node and line graph
+        whose contents are supplied through the Topology Service, and whose positions
+        are driven by the d3.force engine
+    -->
     <svg:svg #svgZoom xmlns:svg="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000" id="topo2">
-        <svg:g *ngIf="force.regionData?.devices.length === 0" onos-nodeviceconnected />
+        <svg:desc>The main SVG canvas of the Topology View</svg:desc>
+        <svg:g *ngIf="force.regionData?.devices[0].length +
+                        force.regionData?.devices[1].length +
+                        force.regionData?.devices[2].length=== 0"
+               onos-nodeviceconnected />
         <svg:g id="topo-zoomlayer" onosZoomableOf [zoomableOf]="svgZoom">
+            <svg:desc>A logical layer that allows the main SVG canvas to be zoomed and panned</svg:desc>
             <svg:g *ngIf="showBackground" onos-backgroundsvg/>
             <svg:g #force onos-forcesvg (selectedNodeEvent)="nodeSelected($event)"/>
         </svg:g>
diff --git a/web/gui2/src/main/webapp/app/view/topology/topology/topology.component.spec.ts b/web/gui2/src/main/webapp/app/view/topology/topology/topology.component.spec.ts
index a9c6194..23fb257 100644
--- a/web/gui2/src/main/webapp/app/view/topology/topology/topology.component.spec.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/topology/topology.component.spec.ts
@@ -32,9 +32,11 @@
 import {
     FlashComponent,
     FnService,
-    LogService
+    LogService,
+    IconService, IconComponent
 } from 'gui2-fw-lib';
 import {ZoomableDirective} from '../layer/zoomable.directive';
+import {RouterTestingModule} from '@angular/router/testing';
 
 
 class MockActivatedRoute extends ActivatedRoute {
@@ -72,6 +74,10 @@
     destroy() {}
 }
 
+class MockIconService {
+    loadIconDef() { }
+}
+
 /**
  * ONOS GUI -- Topology View -- Unit Tests
  */
@@ -101,7 +107,7 @@
         fs = new FnService(ar, logSpy, windowMock);
 
         TestBed.configureTestingModule({
-            imports: [ BrowserAnimationsModule ],
+            imports: [ BrowserAnimationsModule, RouterTestingModule ],
             declarations: [
                 TopologyComponent,
                 InstanceComponent,
@@ -109,7 +115,8 @@
                 ToolbarComponent,
                 DetailsComponent,
                 FlashComponent,
-                ZoomableDirective
+                ZoomableDirective,
+                IconComponent
             ],
             providers: [
                 { provide: FnService, useValue: fs },
@@ -117,6 +124,7 @@
                 { provide: 'Window', useValue: windowMock },
                 { provide: HttpClient, useClass: MockHttpClient },
                 { provide: TopologyService, useClass: MockTopologyService },
+                { provide: IconService, useClass: MockIconService },
             ]
         }).compileComponents();
         logServiceSpy = TestBed.get(LogService);
diff --git a/web/gui2/src/main/webapp/app/view/topology/topology/topology.component.ts b/web/gui2/src/main/webapp/app/view/topology/topology/topology.component.ts
index 7365310..3e1e1a6 100644
--- a/web/gui2/src/main/webapp/app/view/topology/topology/topology.component.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/topology/topology.component.ts
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-present Open Networking Foundation
+ * Copyright 2019-present Open Networking Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the 'License');
  * you may not use this file except in compliance with the License.
@@ -21,9 +21,9 @@
 } from '@angular/core';
 import * as d3 from 'd3';
 import {
-    FnService,
+    FnService, IconService,
     KeysService,
-    KeysToken,
+    KeysToken, LionService,
     LogService,
     PrefsService,
     SvgUtilService,
@@ -36,9 +36,14 @@
 import {BackgroundSvgComponent} from '../layer/backgroundsvg/backgroundsvg.component';
 import {ForceSvgComponent} from '../layer/forcesvg/forcesvg.component';
 import {TopologyService} from '../topology.service';
-import {HostLabelToggle, LabelToggle, Node} from '../layer/forcesvg/models';
+import {
+    HostLabelToggle,
+    LabelToggle,
+    UiElement
+} from '../layer/forcesvg/models';
 import {ToolbarComponent} from '../panel/toolbar/toolbar.component';
 import {TrafficService} from '../traffic.service';
+import {ZoomableDirective} from '../layer/zoomable.directive';
 
 /**
  * ONOS GUI Topology View
@@ -77,11 +82,13 @@
     @ViewChild(ToolbarComponent) toolbar: ToolbarComponent;
     @ViewChild(BackgroundSvgComponent) background: BackgroundSvgComponent;
     @ViewChild(ForceSvgComponent) force: ForceSvgComponent;
+    @ViewChild(ZoomableDirective) zoomDirective: ZoomableDirective;
 
     flashMsg: string = '';
     prefsState = {};
     hostLabelIdx: number = 1;
     showBackground: boolean = false;
+    lionFn; // Function
 
     constructor(
         protected log: LogService,
@@ -92,29 +99,69 @@
         protected wss: WebSocketService,
         protected zs: ZoomService,
         protected ts: TopologyService,
-        protected trs: TrafficService
+        protected trs: TrafficService,
+        protected is: IconService,
+        private lion: LionService,
     ) {
+        if (this.lion.ubercache.length === 0) {
+            this.lionFn = this.dummyLion;
+            this.lion.loadCbs.set('topo-toolbar', () => this.doLion());
+        } else {
+            this.doLion();
+        }
 
+        this.is.loadIconDef('bird');
+        this.is.loadIconDef('active');
+        this.is.loadIconDef('uiAttached');
+        this.is.loadIconDef('m_switch');
+        this.is.loadIconDef('m_roadm');
+        this.is.loadIconDef('m_router');
+        this.is.loadIconDef('m_uiAttached');
+        this.is.loadIconDef('m_endstation');
+        this.is.loadIconDef('m_ports');
+        this.is.loadIconDef('m_summary');
+        this.is.loadIconDef('m_details');
+        this.is.loadIconDef('m_map');
+        this.is.loadIconDef('m_cycleLabels');
+        this.is.loadIconDef('m_resetZoom');
+        this.is.loadIconDef('m_eqMaster');
+        this.is.loadIconDef('m_unknown');
+        this.is.loadIconDef('m_allTraffic');
+        this.is.loadIconDef('deviceTable');
+        this.is.loadIconDef('flowTable');
+        this.is.loadIconDef('portTable');
+        this.is.loadIconDef('groupTable');
+        this.is.loadIconDef('meterTable');
+        this.is.loadIconDef('triangleUp');
         this.log.debug('Topology component constructed');
     }
 
+    /**
+     * Static functions must come before member variables
+     * @param index
+     */
     private static deviceLabelFlashMessage(index: number): string {
         switch (index) {
-            case 0: return 'Hide device labels';
-            case 1: return 'Show friendly device labels';
-            case 2: return 'Show device ID labels';
+            case 0: return 'fl_device_labels_hide';
+            case 1: return 'fl_device_labels_show_friendly';
+            case 2: return 'fl_device_labels_show_id';
         }
     }
 
     private static hostLabelFlashMessage(index: number): string {
         switch (index) {
-            case 0: return 'Hide host labels';
-            case 1: return 'Show friendly host labels';
-            case 2: return 'Show host IP labels';
-            case 3: return 'Show host MAC Address labels';
+            case 0: return 'fl_host_labels_hide';
+            case 1: return 'fl_host_labels_show_friendly';
+            case 2: return 'fl_host_labels_show_ip';
+            case 3: return 'fl_host_labels_show_mac';
         }
     }
 
+    /**
+     * Pass the list of Key Commands to the KeyService, and initialize the Topology
+     * Service - which communicates with through the WebSocket to the ONOS server
+     * to get the nodes and links.
+     */
     ngOnInit() {
         this.bindCommands();
         // The components from the template are handed over to TopologyService here
@@ -125,11 +172,72 @@
         this.log.debug('Topology component initialized');
     }
 
+    /**
+     * When this component is being stopped, disconnect the TopologyService from
+     * the WebSocket
+     */
     ngOnDestroy() {
         this.ts.destroy();
         this.log.debug('Topology component destroyed');
     }
 
+    /**
+     * When ever a toolbar button is clicked, an event is sent up from toolbar
+     * component which is caught and passed on to here.
+     * @param name The name of the button that was clicked
+     */
+    toolbarButtonClicked(name: string) {
+        switch (name) {
+            case 'instance-tog':
+                this.toggleInstancePanel();
+                break;
+            case 'summary-tog':
+                this.toggleSummary();
+                break;
+            case 'details-tog':
+                this.toggleDetails();
+                break;
+            case 'hosts-tog':
+                this.toggleHosts();
+                break;
+            case 'offline-tog':
+                this.toggleOfflineDevices();
+                break;
+            case 'ports-tog':
+                this.togglePorts();
+                break;
+            case 'bkgrnd-tog':
+                this.toggleBackground();
+                break;
+            case 'cycleLabels-btn':
+                this.cycleDeviceLabels();
+                break;
+            case 'cycleHostLabel-btn':
+                this.cycleHostLabels();
+                break;
+            case 'resetZoom-btn':
+                this.resetZoom();
+                break;
+            case 'eqMaster-btn':
+                this.equalizeMasters();
+                break;
+            case 'cancel-traffic':
+                this.cancelTraffic();
+                break;
+            case 'all-traffic':
+                this.monitorAllTraffic();
+                break;
+            default:
+                this.log.warn('Unhandled Toolbar action', name);
+        }
+    }
+
+    /**
+     * The list of key strokes that will be active in the Topology View.
+     *
+     * This action map is passed to the KeyService through the bindCommands()
+     * when this component is being initialized
+     */
     actionMap() {
         return {
             A: [() => {this.monitorAllTraffic(); }, 'Monitor all traffic'],
@@ -226,7 +334,7 @@
         const next = LabelToggle.next(old);
         this.force.ngOnChanges({'deviceLabelToggle':
                 new SimpleChange(old, next, false)});
-        this.flashMsg = TopologyComponent.deviceLabelFlashMessage(next);
+        this.flashMsg = this.lionFn(TopologyComponent.deviceLabelFlashMessage(next));
         this.log.debug('Cycling device labels', old, next);
     }
 
@@ -235,108 +343,112 @@
         const next = HostLabelToggle.next(old);
         this.force.ngOnChanges({'hostLabelToggle':
                 new SimpleChange(old, next, false)});
-        this.flashMsg = TopologyComponent.hostLabelFlashMessage(next);
+        this.flashMsg = this.lionFn(TopologyComponent.hostLabelFlashMessage(next));
         this.log.debug('Cycling host labels', old, next);
     }
 
-    protected toggleBackground(token: KeysToken) {
-        this.flashMsg = 'Toggling background';
+    protected toggleBackground(token?: KeysToken) {
         this.showBackground = !this.showBackground;
+        this.flashMsg = this.lionFn(this.showBackground ? 'show' : 'hide') +
+            ' ' + this.lionFn('fl_background_map');
+        this.toolbar.backgroundVisible = this.showBackground;
         this.log.debug('Toggling background', token);
-        // TODO: Reinstate with components
-        // t2bgs.toggle(x);
     }
 
-    protected toggleDetails(token: KeysToken) {
+    protected toggleDetails(token?: KeysToken) {
         if (this.details.selectedNode) {
-            this.flashMsg = 'Toggling details';
-            this.details.togglePanel(() => {
+            const on: boolean = this.details.togglePanel(() => {
             });
+            this.flashMsg = this.lionFn(on ? 'show' : 'hide') +
+                ' ' + this.lionFn('fl_panel_details');
+            this.toolbar.detailsVisible = on;
+
             this.log.debug('Toggling details', token);
         }
     }
 
-    protected toggleInstancePanel(token: KeysToken) {
-        this.flashMsg = 'Toggling instances';
-        this.instance.togglePanel(() => {});
-        this.log.debug('Toggling instances', token);
-        // TODO: Reinstate with components
-        // this.updatePrefsState('insts', t2is.toggle(x));
+    protected toggleInstancePanel(token?: KeysToken) {
+        const on: boolean = this.instance.togglePanel(() => {});
+        this.flashMsg = this.lionFn(on ? 'show' : 'hide') +
+            ' ' + this.lionFn('fl_panel_instances');
+        this.toolbar.instancesVisible = on;
+        this.log.debug('Toggling instances', token, on);
     }
 
     protected toggleSummary() {
-        this.flashMsg = 'Toggling summary';
-        this.summary.togglePanel(() => {});
+        const on: boolean = this.summary.togglePanel(() => {});
+        this.flashMsg = this.lionFn(on ? 'show' : 'hide') +
+            ' ' + this.lionFn('fl_panel_summary');
+        this.toolbar.summaryVisible = on;
     }
 
     protected resetZoom() {
-        // this.zoomer.reset();
-        this.log.debug('resetting zoom');
-        // TODO: Reinstate with components
-        // t2bgs.resetZoom();
-        // flash.flash('Pan and zoom reset');
+        this.zoomDirective.resetZoom();
+        this.flashMsg = this.lionFn('fl_pan_zoom_reset');
     }
 
-    protected togglePorts(token: KeysToken) {
-        this.log.debug('Toggling ports');
-        // TODO: Reinstate with components
-        // this.updatePrefsState('porthl', t2vs.togglePortHighlights(x));
-        // t2fs.updateLinks();
+    protected togglePorts(token?: KeysToken) {
+        const old: boolean = this.force.highlightPorts;
+        const current: boolean = !this.force.highlightPorts;
+        this.force.ngOnChanges({'highlightPorts': new SimpleChange(old, current, false)});
+        this.flashMsg = this.lionFn(current ? 'enable' : 'disable') +
+            ' ' + this.lionFn('fl_port_highlighting');
+        this.toolbar.portsVisible = current;
+        this.log.debug(current ? 'Enable' : 'Disable', 'port highlighting');
     }
 
     protected equalizeMasters() {
         this.wss.sendEvent('equalizeMasters', null);
-
+        this.flashMsg = this.lionFn('fl_eq_masters');
         this.log.debug('equalizing masters');
-        // TODO: Reinstate with components
-        // flash.flash('Equalizing master roles');
     }
 
     protected resetNodeLocation() {
+        // TODO: Implement reset locations
+        this.flashMsg = this.lionFn('fl_reset_node_locations');
         this.log.debug('resetting node location');
-        // TODO: Reinstate with components
-        // t2fs.resetNodeLocation();
-        // flash.flash('Reset node locations');
     }
 
     protected unpinNode() {
+        // TODO: Implement this
         this.log.debug('unpinning node');
-        // TODO: Reinstate with components
-        // t2fs.unpin();
-        // flash.flash('Unpin node');
     }
 
     protected toggleToolbar() {
         this.log.debug('toggling toolbar');
-        this.flashMsg = ('Toggle toolbar');
         this.toolbar.on = !this.toolbar.on;
     }
 
-    protected actionedFlashed(action, message) {
-        this.log.debug('action flashed');
-        // TODO: Reinstate with components
-        // this.flash.flash(action + ' ' + message);
-    }
-
     protected toggleHosts() {
         const old: boolean = this.force.showHosts;
         const current = !this.force.showHosts;
         this.force.ngOnChanges({'showHosts': new SimpleChange(old, current, false)});
-        this.flashMsg = (this.force.showHosts ? 'Show' : 'Hide') + ' Hosts';
+        this.flashMsg = this.lionFn('hosts') + ' ' +
+                        this.lionFn(this.force.showHosts ? 'visible' : 'hidden');
+        this.toolbar.hostsVisible = current;
         this.log.debug('toggling hosts: ', this.force.showHosts ? 'Show' : 'Hide');
     }
 
     protected toggleOfflineDevices() {
+        // TODO: Implement toggle offline visibility
+        const on: boolean = true;
+        this.flashMsg = this.lionFn(on ? 'show' : 'hide') +
+            ' ' + this.lionFn('fl_offline_devices');
         this.log.debug('toggling offline devices');
-        // TODO: Reinstate with components
-        // let on = t2rs.toggleOfflineDevices();
-        // this.actionedFlashed(on ? 'Show': 'Hide', 'offline devices');
     }
 
+    /**
+     * Check to see if this is needed anymore
+     * @param what
+     */
     protected notValid(what) {
         this.log.warn('topo.js getActionEntry(): Not a valid ' + what);
     }
 
+    /**
+     * Check to see if this is needed anymore
+     * @param what
+     */
     getActionEntry(key) {
         let entry;
 
@@ -354,15 +466,23 @@
         return this.fs.isA(entry) || [entry, ''];
     }
 
-    nodeSelected(node: Node) {
-        this.details.selectedNode = node;
-        this.details.on = Boolean(node);
+    /**
+     * An event handler that updates the details panel as items are
+     * selected in the forcesvg layer
+     * @param nodeOrLink the item to display details of
+     */
+    nodeSelected(nodeOrLink: UiElement) {
+        this.details.ngOnChanges({'selectedNode':
+            new SimpleChange(undefined, nodeOrLink, true)});
+        this.details.on = Boolean(nodeOrLink);
     }
 
     /**
      * Enable traffic monitoring
      */
     monitorAllTraffic() {
+        // TODO: Implement support for toggling between bits, packets and octets
+        this.flashMsg = this.lionFn('tr_fl_pstats_bits');
         this.trs.init(this.force);
     }
 
@@ -370,6 +490,22 @@
      * Cancel traffic monitoring
      */
     cancelTraffic() {
+        this.flashMsg = this.lionFn('fl_monitoring_canceled');
         this.trs.destroy();
     }
+
+    /**
+     * Read the LION bundle for Toolbar and set up the lionFn
+     */
+    doLion() {
+        this.lionFn = this.lion.bundle('core.view.Topo');
+    }
+
+    /**
+     * A dummy implementation of the lionFn until the response is received and the LION
+     * bundle is received from the WebSocket
+     */
+    dummyLion(key: string): string {
+        return '%' + key + '%';
+    }
 }