GUI2 fixed Quickhelp to use LionService

Change-Id: Id0799dd63de186ada17ec03380576d166947af19
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/ModelCache.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/ModelCache.java
index 4cb30e0..cfe3c7a 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/ModelCache.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/ModelCache.java
@@ -192,7 +192,11 @@
         //  or can we rely on looking it up live?
         // TODO: store the updated mastership information
         UiDevice uiDevice = uiTopology.findDevice(deviceId);
-        postEvent(DEVICE_ADDED_OR_UPDATED, uiDevice, MEMO_UPDATED);
+        if (uiDevice != null) {
+            postEvent(DEVICE_ADDED_OR_UPDATED, uiDevice, MEMO_UPDATED);
+        } else {
+            this.log.warn("DeviceID {} not found as a UiDevice", deviceId);
+        }
     }
 
     // === THE NULL REGION
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Ui.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Ui.properties
index a126bdc..d38da53 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Ui.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Ui.properties
@@ -27,6 +27,7 @@
 shift_click=shift-click
 drag=drag
 cmd_scroll=cmd-scroll
+scroll=scroll
 cmd_drag=cmd-drag
 
 # Common control button tooltips
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.css b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.css
index 26c1643..e6ef7b6 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.css
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.css
@@ -35,6 +35,7 @@
 
 #quickhelp div.help table {
     vertical-align: top;
+    width: 100%;
 }
 
 #quickhelp div.help p {
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.html b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.html
index d387284..5c1476a 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.html
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.html
@@ -20,140 +20,54 @@
         <table class="qhrow">
             <tr>
                 <td class="key">&#92;</td>
-                <td class="desc">Afficher/cacher l'aide rapide</td>
+                <td class="desc">{{lionFn("qh_hint_show_hide_qh")}}</td>
             </tr>
             <tr>
                 <td class="key">/</td>
-                <td class="desc">Afficher/cacher l'aide rapide</td>
+                <td class="desc">{{lionFn("qh_hint_show_hide_qh")}}</td>
             </tr>
             <tr>
                 <td class="key">Esc</td>
-                <td class="desc">ignorer la boîte de dialogue ou annuler les
-                    sélections
-                </td>
+                <td class="desc">{{lionFn("qh_hint_esc")}}</td>
             </tr>
             <tr>
                 <td class="key">T</td>
-                <td class="desc">basculer de thème</td>
+                <td class="desc">{{lionFn("qh_hint_t")}}</td>
             </tr>
         </table>
         <hr class="qhrowsep">
         <table class="qhrow">
-            <tr>
-                <td class="key">I</td>
-                <td class="desc">Basculer au panneau de instance
-                    ONOS
-                </td>
-                <td class="key">O</td>
-                <td class="desc">Baculer au panneau récapitulatif
-                    ONOS
-                </td>
-                <td class="key">D</td>
-                <td class="desc">Basculer le panneau de détails</td>
-            </tr>
-            <tr>
-                <td class="key">H</td>
-                <td class="desc">Basculer la visibilité de l'hôte
-                </td>
-                <td class="key">M</td>
-                <td class="desc">Basculer la visibilité hors-ligne
-                </td>
-                <td class="key">P</td>
-                <td class="desc">Basculer le port mis en évidence
-                </td>
-            </tr>
-            <tr>
-                <td class="key">Dash</td>
-                <td class="desc">Montrer les mauvais liens</td>
-                <td class="key">B</td>
-                <td class="desc">Basculer la carte géo de fond</td>
-                <td class="key">G</td>
-                <td class="desc">Sélectionner la carte géo de fond
-                </td>
-            </tr>
-            <tr>
-                <td class="key">S</td>
-                <td class="desc">Toggle sprite layer</td>
-                <td class="key" y="0">X</td>
-                <td class="desc" y="0" x="33.53125">réinitialiser la
-                    carte des noeuds
-                </td>
-                <td class="key">Z</td>
-                <td class="desc">Basculer la vue oblique
-                    (expérimental)
-                </td>
-            </tr>
-            <tr>
-                <td class="key">N</td>
-                <td class="desc">cycle couche de noeuds</td>
-                <td class="key">L</td>
-                <td class="desc">Parcourir étiquettes appareils</td>
-                <td class="key">Shift-l</td>
-                <td class="desc">Parcourir étiquettes hôte</td>
-            </tr>
-            <tr>
-                <td class="key">U</td>
-                <td class="desc">survoler avec la souris</td>
-                <td class="key">R</td>
-                <td class="desc">réinitialiser le zoom et le
-                    panoramique
-                </td>
-                <td class="key">E</td>
-                <td class="desc">Egaliser les rôles de maîtrises
-                </td>
-            </tr>
-            <tr>
-                <td class="key">Dot</td>
-                <td class="desc">Basculer a la barre d'outils</td>
-                <td class="key">0</td>
-                <td class="desc">Annuler la surveillance du trafic
-                </td>
-                <td class="key">A</td>
-                <td class="desc">Surveiller tout le trafic</td>
-            </tr>
-            <tr>
-                <td class="key">F</td>
-                <td class="desc">Afficher les flux de liaison de périphérique
-                </td>
-                <td class="key">V</td>
-                <td class="desc">Show all related intents</td>
-                <td class="key">L-arrow</td>
-                <td class="desc">Show previous related intent</td>
-            </tr>
-            <tr>
-                <td class="key">R-arrow</td>
-                <td class="desc">Show next related intent</td>
-                <td class="key">W</td>
-                <td class="desc">Monitor traffic of selected intent</td>
+            <tr *ngFor="let vk of viewKeys; i as index">
+                <ng-container *ngFor="let vkrow of vk">
+                    <td class="key">{{vkrow.keystroke}}</td>
+                    <td class="desc">{{vkrow.text}}</td>
+                </ng-container>
             </tr>
         </table>
-        <hr>
+        <hr class="qhrowsep">
         <div class="qhrow">
             <table class="qh-r4-c0">
                 <tr>
-                    <td class="key">cliquer</td>
+                    <td class="key">{{lionFn("click")}}</td>
                     <td class="desc">Sélectionner l'article et montrer les
                         détails
                     </td>
                 </tr>
                 <tr>
-                    <td class="key">Cliquer sur MAJ</td>
-                    <td class="desc">Basculer l'état de sélection</td>
+                    <td class="key">{{lionFn("shift-click")}}</td>
+                    <td class="desc">{{lionFn("qh_gest_shift_click")}}</td>
                 </tr>
                 <tr>
-                    <td class="key">Glisser</td>
-                    <td class="desc">Repositionner (et épingler) le périphérique
-                        / l'hôte
-                    </td>
+                    <td class="key">{{lionFn("drag")}}</td>
+                    <td class="desc">{{lionFn("qh_gest_drag")}}</td>
                 </tr>
                 <tr>
-                    <td class="key">cmd défiler</td>
-                    <td class="desc">Zoom avant/arrière</td>
+                    <td class="key">{{lionFn("drag")}}</td>
+                    <td class="desc">{{lionFn("qh_gest_cmd_scroll")}}</td>
                 </tr>
                 <tr>
-                    <td class="key" y="48">cmd-glisser</td>
-                    <td class="desc" y="48" x="74.84375">Pan
-                </tr>
+                    <td class="key" y="48">{{lionFn("scroll")}}</td>
+                    <td class="desc" y="48" x="74.84375">{{lionFn("qh_gest_cmd_drag")}}</tr>
             </table>
         </div>
     </div>
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.spec.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.spec.ts
index da60a1b..5dfb73c 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.spec.ts
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.spec.ts
@@ -26,7 +26,19 @@
 class MockFnService {}
 
 class MockKeysService {
+    keyHandler: {
+        viewKeys: any[],
+        globalKeys: any[]
+    };
 
+    mockViewKeys: Object[];
+    constructor() {
+        this.mockViewKeys = [];
+        this.keyHandler = {
+            viewKeys: this.mockViewKeys,
+            globalKeys: this.mockViewKeys
+        };
+    }
 }
 
 /**
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.ts
index 6789e14..261f49c 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.ts
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.ts
@@ -13,13 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import {Component} from '@angular/core';
+import {Component, OnInit} from '@angular/core';
 import {animate, state, style, transition, trigger} from '@angular/animations';
 import {LogService} from '../../log.service';
 import {FnService} from '../../util/fn.service';
 import {KeysService} from '../../util/keys.service';
 import {LionService} from '../../util/lion.service';
 
+export interface KeyEntry {
+    keystroke: string;
+    text: string;
+}
 
 @Component({
     selector: 'onos-quickhelp',
@@ -38,9 +42,23 @@
         ])
     ]
 })
-export class QuickhelpComponent {
+export class QuickhelpComponent implements OnInit {
     lionFn; // Function
 
+    dialogKeys: Object;
+    globalKeys: Object[];
+    maskedKeys: Object;
+    viewGestures: Object;
+    viewKeys: KeyEntry[][];
+
+    private static extractKeyEntry(viewKeyObj: Object, log: LogService): KeyEntry {
+        const subParts = Object.values(viewKeyObj[1]);
+        return <KeyEntry>{
+            keystroke: <string>viewKeyObj[0],
+            text: <string>subParts[1]
+        };
+    }
+
     constructor(
         private log: LogService,
         private fs: FnService,
@@ -53,10 +71,24 @@
         } else {
             this.doLion();
         }
+        this.globalKeys = [];
+        this.viewKeys = [[], [], [], [], [], [], [], [], []];
 
-        this.log.debug('Quickhelp component constructed');
+        this.log.debug('QuickhelpComponent constructed');
     }
 
+    ngOnInit(): void {
+        Object.entries(this.ks.keyHandler.viewKeys)
+            .filter((vk) => vk[0] !== '_helpFormat' && vk[0] !== '9')
+            .forEach((vk, idx) => {
+                const ke = QuickhelpComponent.extractKeyEntry(vk, this.log);
+                this.viewKeys[Math.floor(idx / 3)][idx % 3] = ke;
+            });
+        this.log.debug('QuickhelpComponent initialized');
+        this.log.debug('view keys retrieved', this.ks.keyHandler.globalKeys);
+    }
+
+
     /**
      * Read the LION bundle for Toolbar and set up the lionFn
      */
diff --git a/web/gui2-fw-lib/src/app/app.component.html b/web/gui2-fw-lib/src/app/app.component.html
index 2cc727e..9d66610 100644
--- a/web/gui2-fw-lib/src/app/app.component.html
+++ b/web/gui2-fw-lib/src/app/app.component.html
@@ -44,6 +44,5 @@
   If you change anything in the library, you will have to build it again before
   it is picked up in this app.
 </p>
-<onos-quickhelp></onos-quickhelp>
-<onos-loading [running]="loadingRunning"></onos-loading>
-<button (click)="toggleLoadingRunning()">Toggle loading image</button>
+<onos-quickhelp #qh></onos-quickhelp>
+<button (click)="qh.ks.quickHelpShown = true">Toggle quick help shown</button>
diff --git a/web/gui2-fw-lib/src/app/app.component.ts b/web/gui2-fw-lib/src/app/app.component.ts
index a5a5450..5e934d4 100644
--- a/web/gui2-fw-lib/src/app/app.component.ts
+++ b/web/gui2-fw-lib/src/app/app.component.ts
@@ -15,7 +15,7 @@
  */
 
 import {Component} from '@angular/core';
-import {FnService, LogService} from 'gui2-fw-lib';
+import {FnService, KeysService, LogService} from 'gui2-fw-lib';
 
 @Component({
   selector: 'app-root',
@@ -23,16 +23,78 @@
   styleUrls: ['./app.component.css']
 })
 export class AppComponent {
-  title = 'Test app for GUI Framework Library';
-  loadingRunning: boolean = false;
+    title = 'Test app for GUI Framework Library';
+    loadingRunning: boolean = false;
 
-  constructor(
-    protected fs: FnService
-  ) {
-    this.title = this.fs.cap(this.title);
-  }
+    constructor(
+        protected fs: FnService,
+        protected ks: KeysService,
+        protected log: LogService
+    ) {
+        this.title = this.fs.cap(this.title);
+        this.bindCommands();
+        this.log.debug('AppComponent constructed');
+    }
 
-    toggleLoadingRunning() {
-        this.loadingRunning = !this.loadingRunning;
+    bindCommands(additional?: any) {
+
+        const am = this.actionMap();
+        const add = this.fs.isO(additional);
+
+        this.ks.keyBindings(am);
+
+        this.ks.gestureNotes([
+            ['click', 'Select the item and show details'],
+            ['shift-click', 'Toggle selection state'],
+            ['drag', 'Reposition (and pin) device / host'],
+            ['cmd-scroll', 'Zoom in / out'],
+            ['cmd-drag', 'Pan'],
+        ]);
+    }
+
+
+    showKeyStroke(letter: string, token?: string) {
+        this.log.debug('Key pressed', letter);
+    }
+
+    actionMap() {
+        return {
+            A: [() => {this.showKeyStroke('A'); }, 'Monitor all traffic'],
+            B: [(token) => {this.showKeyStroke('B', token); }, 'Toggle background'],
+            D: [(token) => {this.showKeyStroke('D', token); }, 'Toggle details panel'],
+            E: [() => {this.showKeyStroke('E'); }, 'Equalize mastership roles'],
+            H: [() => {this.showKeyStroke('H'); }, 'Toggle host visibility'],
+            I: [(token) => {this.showKeyStroke('I', token); }, 'Toggle ONOS Instance Panel'],
+            G: [() => {this.showKeyStroke('G'); }, 'Show map selection dialog'],
+            L: [() => {this.showKeyStroke('L'); }, 'Cycle device labels'],
+            M: [() => {this.showKeyStroke('M'); }, 'Toggle offline visibility'],
+            O: [() => {this.showKeyStroke('O'); }, 'Toggle the Summary Panel'],
+            P: [(token) => {this.showKeyStroke('P', token); }, 'Toggle Port Highlighting'],
+            Q: [() => {this.showKeyStroke('Q'); }, 'Cycle grid display'],
+            R: [() => {this.showKeyStroke('R'); }, 'Reset pan / zoom'],
+            U: [() => {this.showKeyStroke('U'); }, 'Unpin or freeze nodes'],
+            X: [() => {this.showKeyStroke('X'); }, 'Reset Node Location'],
+            dot: [() => {this.showKeyStroke('.'); }, 'Toggle Toolbar'],
+            0: [() => {this.showKeyStroke('0'); }, 'Cancel traffic monitoring'],
+            'shift-L': [() => {this.showKeyStroke('shift-L'); }, 'Cycle host labels'],
+
+            esc: [() => {this.showKeyStroke('Esc'); }, 'Cancel commands'],
+
+            // TODO update after adding in Background Service
+            // topology overlay selections
+            // F1: function () { t2tbs.fnKey(0); },
+            // F2: function () { t2tbs.fnKey(1); },
+            // F3: function () { t2tbs.fnKey(2); },
+            // F4: function () { t2tbs.fnKey(3); },
+            // F5: function () { t2tbs.fnKey(4); },
+            //
+            // _keyListener: t2tbs.keyListener.bind(t2tbs),
+
+            _helpFormat: [
+                ['I', 'O', 'D', 'H', 'M', 'P', 'dash', 'B'],
+                ['X', 'Z', 'N', 'L', 'shift-L', 'U', 'R', 'E', 'dot'],
+                [], // this column reserved for overlay actions
+            ],
+        };
     }
 }
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.spec.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.spec.ts
index f38604f..0492858 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.spec.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.spec.ts
@@ -95,6 +95,20 @@
 class MockKeysService {
     quickHelpShown: boolean = true;
 
+    keyHandler: {
+        viewKeys: any[],
+        globalKeys: any[]
+    };
+
+    mockViewKeys: Object[];
+    constructor() {
+        this.mockViewKeys = [];
+        this.keyHandler = {
+            viewKeys: this.mockViewKeys,
+            globalKeys: this.mockViewKeys
+        };
+    }
+
     keyBindings(x) {
         return {};
     }
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.ts
index d8e0a0f..8c6b953 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.ts
@@ -408,34 +408,37 @@
      *
      * This action map is passed to the KeyService through the bindCommands()
      * when this component is being initialized
+     *
+     * TODO - Replace this doggy doo doo (copied over from GUI-1)
+     * with something more structured
      */
     actionMap() {
         return {
-            A: [() => {this.cycleTrafficTypeDisplay(); }, 'Monitor all traffic'],
-            B: [(token) => {this.toggleBackground(token); }, 'Toggle background'],
-            D: [(token) => {this.toggleDetails(token); }, 'Toggle details panel'],
-            E: [() => {this.equalizeMasters(); }, 'Equalize mastership roles'],
-            H: [() => {this.toggleHosts(); }, 'Toggle host visibility'],
-            I: [(token) => {this.toggleInstancePanel(token); }, 'Toggle ONOS Instance Panel'],
-            G: [() => {this.mapSelShown = !this.mapSelShown; }, 'Show map selection dialog'],
-            L: [() => {this.cycleDeviceLabels(); }, 'Cycle device labels'],
-            M: [() => {this.toggleOfflineDevices(); }, 'Toggle offline visibility'],
-            O: [() => {this.toggleSummary(); }, 'Toggle the Summary Panel'],
-            P: [(token) => {this.togglePorts(token); }, 'Toggle Port Highlighting'],
-            Q: [() => {this.cycleGridDisplay(); }, 'Cycle grid display'],
-            R: [() => {this.resetZoom(); }, 'Reset pan / zoom'],
-            U: [() => {this.unpinOrFreezeNodes(); }, 'Unpin or freeze nodes'],
-            X: [() => {this.resetNodeLocation(); }, 'Reset Node Location'],
-            dot: [() => {this.toggleToolbar(); }, 'Toggle Toolbar'],
-            0: [() => {this.cancelTraffic(); }, 'Cancel traffic monitoring'],
-            'shift-L': [() => {this.cycleHostLabels(); }, 'Cycle host labels'],
+            A: [() => {this.cycleTrafficTypeDisplay(); }, this.lionFn('tr_btn_monitor_all')],
+            B: [(token) => {this.toggleBackground(token); }, this.lionFn('tbtt_tog_map')],
+            D: [(token) => {this.toggleDetails(token); }, this.lionFn('tbtt_tog_use_detail')],
+            E: [() => {this.equalizeMasters(); }, this.lionFn('tbtt_eq_master')],
+            H: [() => {this.toggleHosts(); }, this.lionFn('tbtt_tog_host')],
+            I: [(token) => {this.toggleInstancePanel(token); }, this.lionFn('tbtt_tog_instances')],
+            G: [() => {this.mapSelShown = !this.mapSelShown; }, this.lionFn('tbtt_sel_map')],
+            L: [() => {this.cycleDeviceLabels(); }, this.lionFn('tbtt_cyc_dev_labs')],
+            M: [() => {this.toggleOfflineDevices(); }, this.lionFn('tbtt_tog_offline')],
+            O: [() => {this.toggleSummary(); }, this.lionFn('tbtt_tog_summary')],
+            P: [(token) => {this.togglePorts(token); }, this.lionFn('tbtt_tog_porthi')],
+            Q: [() => {this.cycleGridDisplay(); }, this.lionFn('tbtt_cyc_grid_display')],
+            R: [() => {this.resetZoom(); }, this.lionFn('tbtt_reset_zoom')],
+            U: [() => {this.unpinOrFreezeNodes(); }, this.lionFn('tbtt_unpin_node')],
+            X: [() => {this.resetNodeLocation(); }, this.lionFn('tbtt_reset_loc')],
+            dot: [() => {this.toggleToolbar(); }, this.lionFn('tbtt_tog_toolbar')],
+            0: [() => {this.cancelTraffic(); }, this.lionFn('tr_btn_cancel_monitoring')],
+            'shift-L': [() => {this.cycleHostLabels(); }, this.lionFn('tbtt_cyc_host_labs')],
 
             // -- instance color palette debug
             9: () => {
                 this.sus.cat7().testCard(d3.select('svg#topo2'));
             },
 
-            esc: [() => {this.handleEscape(); }, 'Cancel commands'],
+            esc: [() => {this.handleEscape(); }, this.lionFn('qh_hint_esc')],
 
             // TODO update after adding in Background Service
             // topology overlay selections