GUI -- Completed icon directive definition, and wired up device view.

Change-Id: Ia3cf0655fb17d47adc54f9f4540bb25eacbaaa62
diff --git a/web/gui/src/main/webapp/app/directives.js b/web/gui/src/main/webapp/app/directives.js
index 7d574d5..9cbcf6d 100644
--- a/web/gui/src/main/webapp/app/directives.js
+++ b/web/gui/src/main/webapp/app/directives.js
@@ -59,20 +59,16 @@
 
         // create icon directive, so that we can inject icons into
         // HTML tables etc.
-        .directive('icon', ['GlyphService', function (gs) {
+        .directive('icon', ['IconService', function (is) {
             return {
-                templateUrl: 'toBeDecided-iconContext.html',
                 restrict: 'A',
+                scope: {
+                    iconId: '@'
+                },
                 link: function (scope, element, attrs) {
-                    // TODO: implement this
-                    // needs to pull out the parameters for the icon
-                    // from the attributes of the element, and use those
-                    // as arguments to the IconService.addIcon(...) call.
-
-
+                    is.loadEmbeddedIcon(d3.select(element[0]), scope.iconId);
                 }
             };
 
-
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/fw/remote/rest.js b/web/gui/src/main/webapp/app/fw/remote/rest.js
index b397aa7..920d07e 100644
--- a/web/gui/src/main/webapp/app/fw/remote/rest.js
+++ b/web/gui/src/main/webapp/app/fw/remote/rest.js
@@ -35,6 +35,7 @@
             "devices": [{
                 "id": "of:0000000000000001",
                 "available": true,
+                "_iconid_available": "deviceOnline",
                 "role": "MASTER",
                 "mfr": "Nicira, Inc.",
                 "hw": "Open vSwitch",
@@ -44,23 +45,38 @@
                     "protocol": "OF_10"
                 }
             },
-                {
-                    "id": "of:0000000000000004",
-                    "available": true,
-                    "role": "MASTER",
-                    "mfr": "Nicira, Inc.",
-                    "hw": "Open vSwitch",
-                    "sw": "2.0.1",
-                    "serial": "None",
-                    "annotations": {
-                        "protocol": "OF_10"
-                    }
-                }]
+            {
+                "id": "of:0000000000000004",
+                "available": false,
+                "_iconid_available": "deviceOffline",
+                "role": "MASTER",
+                "mfr": "Nicira, Inc.",
+                "hw": "Open vSwitch",
+                "sw": "2.0.1",
+                "serial": "None",
+                "annotations": {
+                    "protocol": "OF_10"
+                }
+            },
+            {
+                "id": "of:0000000000000092",
+                "available": false,
+                "_iconid_available": "deviceOffline",
+                "role": "MASTER",
+                "mfr": "Nicira, Inc.",
+                "hw": "Open vSwitch",
+                "sw": "2.0.1",
+                "serial": "None",
+                "annotations": {
+                    "protocol": "OF_10"
+                }
+            }]
         },
         '2': {
             "devices": [{
                 "id": "of:0000000000000002",
                 "available": true,
+                "_iconid_available": "deviceOnline",
                 "role": "MASTER",
                 "mfr": "Nicira, Inc.",
                 "hw": "Open vSwitch",
@@ -70,18 +86,19 @@
                     "protocol": "OF_10"
                 }
             },
-                {
-                    "id": "of:0000000000000006",
-                    "available": true,
-                    "role": "MASTER",
-                    "mfr": "Nicira, Inc.",
-                    "hw": "Open vSwitch",
-                    "sw": "2.1.1",
-                    "serial": "None",
-                    "annotations": {
-                        "protocol": "OF_10"
-                    }
-                }]
+            {
+                "id": "of:0000000000000006",
+                "available": true,
+                "_iconid_available": "deviceOnline",
+                "role": "MASTER",
+                "mfr": "Nicira, Inc.",
+                "hw": "Open vSwitch",
+                "sw": "2.1.1",
+                "serial": "None",
+                "annotations": {
+                    "protocol": "OF_10"
+                }
+            }]
         },
         'empty': {
             devices: []
diff --git a/web/gui/src/main/webapp/app/fw/svg/glyph.js b/web/gui/src/main/webapp/app/fw/svg/glyph.js
index ef017e0..b2afea3 100644
--- a/web/gui/src/main/webapp/app/fw/svg/glyph.js
+++ b/web/gui/src/main/webapp/app/fw/svg/glyph.js
@@ -168,16 +168,25 @@
             }
 
             // Note: defs should be a D3 selection of a single <defs> element
-            function loadDefs(defs, glyphIds) {
-                var list = fs.isA(glyphIds) || ids();
+            function loadDefs(defs, glyphIds, noClear) {
+                var list = fs.isA(glyphIds) || ids(),
+                    clearCache = !noClear;
 
-                // remove all existing content
-                defs.html(null);
+                if (clearCache) {
+                    // remove all existing content
+                    defs.html(null);
+                }
 
                 // load up the requested glyphs
                 list.forEach(function (id) {
                     var g = glyph(id);
                     if (g) {
+                        if (noClear) {
+                            // quick exit if symbol is already present
+                            if (defs.select('symbol#' + g.id).size() > 0) {
+                                return;
+                            }
+                        }
                         defs.append('symbol')
                             .attr({ id: g.id, viewBox: g.vb })
                             .append('path').attr('d', g.d);
diff --git a/web/gui/src/main/webapp/app/fw/svg/icon.css b/web/gui/src/main/webapp/app/fw/svg/icon.css
new file mode 100644
index 0000000..bd431c7
--- /dev/null
+++ b/web/gui/src/main/webapp/app/fw/svg/icon.css
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2014,2015 Open Networking Laboratory
+ *
+ * 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 -- Icon Service -- CSS file
+ */
+
+svg.embeddedIcon .icon .glyph {
+ stroke: none;
+ fill: white;
+ fill-rule: evenodd;
+}
+
+svg.embeddedIcon .icon.deviceOnline {
+ fill: green;
+}
+
+svg.embeddedIcon .icon.deviceOffline {
+ fill: darkred;
+}
+
+svg.embeddedIcon .icon rect {
+ stroke: black;
+ stroke-width: 1px;
+}
diff --git a/web/gui/src/main/webapp/app/fw/svg/icon.js b/web/gui/src/main/webapp/app/fw/svg/icon.js
index 2013a63..deb1522 100644
--- a/web/gui/src/main/webapp/app/fw/svg/icon.js
+++ b/web/gui/src/main/webapp/app/fw/svg/icon.js
@@ -22,53 +22,89 @@
 (function () {
     'use strict';
 
-    var $log, fs;
+    var $log, fs, gs;
 
-    var viewBoxDim = 50,
-        viewBox = '0 0 ' + viewBoxDim + ' ' + viewBoxDim;
+    var vboxSize = 50,
+        cornerSize = vboxSize / 10,
+        viewBox = '0 0 ' + vboxSize + ' ' + vboxSize;
 
     // maps icon id to the glyph id it uses.
     // note: icon id maps to a CSS class for styling that icon
     var glyphMapping = {
-            deviceOnline: 'checkMark',
-            deviceOffline: 'xMark'
+            deviceOnline: 'crown',
+            deviceOffline: 'chain'
+            //deviceOnline: 'checkMark',
+            //deviceOffline: 'xMark'
         };
 
+    function ensureIconLibDefs() {
+        var body = d3.select('body'),
+            svg = body.select('svg#IconLibDefs'),
+            defs;
+
+        if (svg.empty()) {
+            svg = body.append('svg').attr('id', 'IconLibDefs');
+            defs = svg.append('defs');
+        }
+        return svg.select('defs');
+    }
+
     angular.module('onosSvg')
-        .factory('IconService', ['$log', 'FnService', function (_$log_, _fs_) {
+        .factory('IconService', ['$log', 'FnService', 'GlyphService',
+        function (_$log_, _fs_, _gs_) {
             $log = _$log_;
             fs = _fs_;
+            gs = _gs_;
 
             // div is a D3 selection of the <DIV> element into which icon should load
             // iconCls is the CSS class used to identify the icon
             // size is dimension of icon in pixels. Defaults to 20.
-            function loadIcon(div, iconCls, size) {
+            // installGlyph, if truthy, will cause the glyph to be added to
+            //      well-known defs element. Defaults to false.
+            // svgClass is the CSS class used to identify the SVG layer.
+            //      Defaults to 'embeddedIcon'.
+            function loadIcon(div, iconCls, size, installGlyph, svgClass) {
                 var dim = size || 20,
-                    gid = glyphMapping[iconCls] || 'unknown';
+                    svgCls = svgClass || 'embeddedIcon',
+                    gid = glyphMapping[iconCls] || 'unknown',
+                    svg, g;
 
-                var svg = div.append('svg').attr({
+                if (installGlyph) {
+                    gs.loadDefs(ensureIconLibDefs(), [gid], true);
+                }
+
+                svg = div.append('svg').attr({
+                        'class': svgCls,
                         width: dim,
                         height: dim,
                         viewBox: viewBox
                     });
-                var g = svg.append('g').attr({
+
+                g = svg.append('g').attr({
                     'class': 'icon ' + iconCls
                 });
+
                 g.append('rect').attr({
-                    width: viewBoxDim,
-                    height: viewBoxDim,
-                    rx: 4
+                    width: vboxSize,
+                    height: vboxSize,
+                    rx: cornerSize
                 });
+
                 g.append('use').attr({
-                    width: viewBoxDim,
-                    height: viewBoxDim,
+                    width: vboxSize,
+                    height: vboxSize,
                     'class': 'glyph',
                     'xlink:href': '#' + gid
                 });
             }
 
+            function loadEmbeddedIcon(div, iconCls, size) {
+                loadIcon(div, iconCls, size, true);
+            }
+
             return {
-                loadIcon: loadIcon
+                loadIcon: loadIcon,
+                loadEmbeddedIcon: loadEmbeddedIcon
             };
         }]);
 
diff --git a/web/gui/src/main/webapp/app/index.html b/web/gui/src/main/webapp/app/index.html
index aa9c1de..f455406 100644
--- a/web/gui/src/main/webapp/app/index.html
+++ b/web/gui/src/main/webapp/app/index.html
@@ -58,6 +58,7 @@
     <link rel="stylesheet" href="onos.css">
     <link rel="stylesheet" href="common.css">
     <link rel="stylesheet" href="fw/mast/mast.css">
+    <link rel="stylesheet" href="fw/svg/icon.css">
     <link rel="stylesheet" href="fw/nav/nav.css">
 
     <!-- This is where contributed javascript will get injected -->
diff --git a/web/gui/src/main/webapp/app/view/device/device.html b/web/gui/src/main/webapp/app/view/device/device.html
index 451dd03..a6fd640 100644
--- a/web/gui/src/main/webapp/app/view/device/device.html
+++ b/web/gui/src/main/webapp/app/view/device/device.html
@@ -4,17 +4,19 @@
 
     <table class="summary-list">
         <tr>
+            <th></th>
             <th>ID</th>
             <th>Manufacturer</th>
             <th>Hardware Version</th>
             <th>Software Version</th>
         </tr>
         <tr ng-repeat="dev in ctrl.deviceData">
-            <!-- add more property fields for table from device data -->
+            <td><div icon icon-id="{{dev._iconid_available}}"></div></td>
             <td>{{dev.id}}</td>
             <td>{{dev.mfr}}</td>
             <td>{{dev.hw}}</td>
             <td>{{dev.sw}}</td>
+            <!-- add more property fields for table from device data -->
         </tr>
     </table>