GUI -- Added applications view.
Fixed table.js column width computation.
Fixed app.xml files to leave out ONOS from description.

Change-Id: Icfe323e63c7965dd8c3a268421ea58065c5c8236
diff --git a/web/gui/src/main/webapp/app/common.css b/web/gui/src/main/webapp/app/common.css
index 43755d3..5c7d2a1 100644
--- a/web/gui/src/main/webapp/app/common.css
+++ b/web/gui/src/main/webapp/app/common.css
@@ -43,10 +43,21 @@
     background-color: #444;
 }
 
-table.summary-list th {
-    padding: 10px;
-    letter-spacing: 0.02em;
+.light table.summary-list tr.selected {
+    background-color: deepskyblue;
+}
+
+.dark table.summary-list tr.selected {
+    background-color: #304860;
+}
+
+table.summary-list td,th {
+    padding: 6px 6px 6px 6px;
     text-align: left;
+}
+
+table.summary-list th {
+    letter-spacing: 0.02em;
     cursor: pointer;
 }
 table.summary-list th:first-child {
@@ -55,6 +66,7 @@
 table.summary-list th:last-child {
     border-radius: 0 8px 0 0;
 }
+
 .light table.summary-list th {
     background-color: #bbb;
 }
@@ -63,11 +75,6 @@
     color: #ccc;
 }
 
-table.summary-list td {
-    padding: 6px 10px 6px 10px;
-    text-align: left;
-}
-
 .dark table.summary-list td {
     color: #ccc;
 }
diff --git a/web/gui/src/main/webapp/app/fw/svg/icon.css b/web/gui/src/main/webapp/app/fw/svg/icon.css
index 7f3e8f4..6d83da2 100644
--- a/web/gui/src/main/webapp/app/fw/svg/icon.css
+++ b/web/gui/src/main/webapp/app/fw/svg/icon.css
@@ -28,6 +28,29 @@
     fill-rule: evenodd;
 }
 
+/*
+ FIXME: The following should be consolidated to result in much less CSS and
+ not to require entries for every icon.
+ */
+
+.light svg.embeddedIcon .icon.appActive,
+.light svg.embeddedIcon .icon.appInactive {
+    fill: none;
+}
+
+.dark svg.embeddedIcon .icon.appActive,
+.dark svg.embeddedIcon .icon.appInactive {
+    fill: none;
+}
+
+.light svg.embeddedIcon .icon.appActive .glyph {
+    fill: green;
+}
+.dark svg.embeddedIcon .icon.appActive .glyph {
+    fill: #266610;
+}
+
+
 .light svg.embeddedIcon .icon.deviceOnline,
 .light svg.embeddedIcon .icon.deviceOffline {
     fill: none;
@@ -73,6 +96,10 @@
     fill: #ccc;
 }
 
+.light svg.embeddedIcon .icon.appActive rect,
+.light svg.embeddedIcon .icon.appInactive rect,
+.dark svg.embeddedIcon .icon.appActive rect,
+.dark svg.embeddedIcon .icon.appInactive rect,
 .light svg.embeddedIcon .icon.deviceOnline rect,
 .light svg.embeddedIcon .icon.deviceOffline rect,
 .dark svg.embeddedIcon .icon.deviceOnline rect,
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 400b7aa..8a8b35f 100644
--- a/web/gui/src/main/webapp/app/fw/svg/icon.js
+++ b/web/gui/src/main/webapp/app/fw/svg/icon.js
@@ -29,6 +29,9 @@
     // Maps icon ID to the glyph ID it uses.
     // NOTE: icon ID maps to a CSS class for styling that icon
     var glyphMapping = {
+        appActive: 'checkMark',
+        appInactive: 'unknown',
+
         deviceOnline: 'checkMark',
         deviceOffline: 'xMark',
         devIcon_SWITCH: 'switch',
diff --git a/web/gui/src/main/webapp/app/fw/widget/table.js b/web/gui/src/main/webapp/app/fw/widget/table.js
index 2fc3277..285d21d 100644
--- a/web/gui/src/main/webapp/app/fw/widget/table.js
+++ b/web/gui/src/main/webapp/app/fw/widget/table.js
@@ -29,19 +29,31 @@
     // Functions for creating a fixed header on a table (Angular Directive)
 
     function setTableWidth(t) {
-        var tHeaders, tdElement, colWidth, numCols,
+        var tHeaders, tdElement, colWidth, numIcons, numNonIcons,
             winWidth = fs.windowSize().width;
 
         tHeaders = t.selectAll('th');
-        numCols = tHeaders[0].length;
-        colWidth = Math.floor(winWidth / numCols);
+        numIcons = 0;
+        numNonIcons = 0;
+
+        // FIXME: This should observe custom-set width from the HTML
 
         tHeaders.each(function(thElement, index) {
             thElement = d3.select(this);
+            if (thElement.classed('table-icon')) {
+                numIcons = numIcons + 1;
+            } else {
+                numNonIcons = numNonIcons + 1;
+            }
+        });
 
+        colWidth = Math.floor((winWidth - (numIcons * tableIconTdSize)) / numNonIcons);
+
+        tHeaders.each(function(thElement, index) {
+            thElement = d3.select(this);
             tdElement = t.select('td:nth-of-type(' + (index + 1) + ')');
 
-            if (tdElement.classed('table-icon')) {
+            if (thElement.classed('table-icon')) {
                 thElement.style('width', tableIconTdSize + 'px');
                 tdElement.style('width', tableIconTdSize + 'px');
             } else {
diff --git a/web/gui/src/main/webapp/app/view/app/app.css b/web/gui/src/main/webapp/app/view/app/app.css
new file mode 100644
index 0000000..b30f488
--- /dev/null
+++ b/web/gui/src/main/webapp/app/view/app/app.css
@@ -0,0 +1,22 @@
+/*
+ * Copyright 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 -- Host View -- CSS file
+ */
+
+#ov-app td {
+}
diff --git a/web/gui/src/main/webapp/app/view/app/app.html b/web/gui/src/main/webapp/app/view/app/app.html
new file mode 100644
index 0000000..c219eb8
--- /dev/null
+++ b/web/gui/src/main/webapp/app/view/app/app.html
@@ -0,0 +1,34 @@
+<!-- app partial HTML -->
+<div id="ov-app">
+    <h2>Applications ({{ctrl.appData.length}} total)</h2>
+    <table class="summary-list"
+           onos-fixed-header
+           onos-sortable-header
+           sort-callback="sortCallback(requestParams)">
+        <thead>
+            <tr>
+                <th colId="state" class="table-icon" sortable></th>
+                <th colId="id" sortable>App ID </th>
+                <th colId="version" sortable>Version</th>
+                <th colId="origin" sortable>Origin </th>
+                <th colId="desc">Description </th>
+            </tr>
+        </thead>
+
+        <tbody>
+        <tr ng-repeat="app in ctrl.appData"
+            ng-click="setSelected(app.id)"
+            ng-class="{selected: app.id === selectedAppId}"
+            ng-repeat-done>
+            <td class="table-icon">
+                <div icon icon-id="{{app._iconid_state}}"></div>
+            </td>
+            <td>{{app.id}}</td>
+            <td>{{app.version}}</td>
+            <td>{{app.origin}}</td>
+            <td>{{app.desc}}</td>
+        </tr>
+        </tbody>
+    </table>
+
+</div>
diff --git a/web/gui/src/main/webapp/app/view/app/app.js b/web/gui/src/main/webapp/app/view/app/app.js
new file mode 100644
index 0000000..d2bab39
--- /dev/null
+++ b/web/gui/src/main/webapp/app/view/app/app.js
@@ -0,0 +1,60 @@
+/*
+ * Copyright 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 -- App View Module
+ */
+
+(function () {
+    'use strict';
+
+    angular.module('ovApp', [])
+    .controller('OvAppCtrl',
+        ['$log', '$scope', '$location', 'FnService', 'WebSocketService',
+
+        function ($log, $scope, $location, fs, wss) {
+            var self = this;
+            self.appData = [];
+
+            $scope.responseCallback = function(data) {
+                self.appData = data.applications;
+                $scope.$apply();
+            };
+
+            $scope.sortCallback = function (requestParams) {
+                wss.sendEvent('appDataRequest', requestParams);
+            };
+
+            $scope.selectedAppId = null;
+            $scope.setSelected = function (appId) {
+                $scope.selectedAppId = appId;
+            };
+
+            var handlers = {
+                appDataResponse: $scope.responseCallback
+            };
+            wss.bindHandlers(handlers);
+
+            // Cleanup on destroyed scope
+            $scope.$on('$destroy', function () {
+                wss.unbindHandlers(handlers);
+            });
+
+            $scope.sortCallback();
+
+            $log.log('OvAppCtrl has been created');
+        }]);
+}());
diff --git a/web/gui/src/main/webapp/app/view/device/device.css b/web/gui/src/main/webapp/app/view/device/device.css
index bfc1ebc..53cdabe 100644
--- a/web/gui/src/main/webapp/app/view/device/device.css
+++ b/web/gui/src/main/webapp/app/view/device/device.css
@@ -18,6 +18,5 @@
  ONOS GUI -- Device View -- CSS file
  */
 
-#ov-device {
-    /* placeholder */
-}
\ No newline at end of file
+#ov-device td {
+}
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 c37f295..1db7900 100644
--- a/web/gui/src/main/webapp/app/view/device/device.html
+++ b/web/gui/src/main/webapp/app/view/device/device.html
@@ -7,8 +7,8 @@
            sort-callback="sortCallback(requestParams)">
         <thead>
             <tr>
-                <th colId="available"></th>
-                <th colId="type"></th>
+                <th colId="available" class="table-icon" sortable></th>
+                <th colId="type" class="table-icon" sortable></th>
                 <th colId="id" sortable>Device ID </th>
                 <th colId="mfr" sortable>Vendor </th>
                 <th colId="hw" sortable>H/W Version </th>
diff --git a/web/gui/src/main/webapp/app/view/host/host.css b/web/gui/src/main/webapp/app/view/host/host.css
index 708dc23..94815f5 100644
--- a/web/gui/src/main/webapp/app/view/host/host.css
+++ b/web/gui/src/main/webapp/app/view/host/host.css
@@ -19,5 +19,5 @@
  */
 
 #ov-host td {
-    padding: 12px 10px;
+    height: 20px;
 }
\ No newline at end of file
diff --git a/web/gui/src/main/webapp/index.html b/web/gui/src/main/webapp/index.html
index 89c5aff..ef45356 100644
--- a/web/gui/src/main/webapp/index.html
+++ b/web/gui/src/main/webapp/index.html
@@ -101,6 +101,7 @@
     <script src="app/view/topo/topoToolbar.js"></script>
     <script src="app/view/device/device.js"></script>
     <script src="app/view/host/host.js"></script>
+    <script src="app/view/app/app.js"></script>
     <script src="app/view/sample/sample.js"></script>
     <!-- {INJECTED-JAVASCRIPT-END} -->
 
@@ -110,6 +111,7 @@
     <link rel="stylesheet" href="app/view/topo/topo.css">
     <link rel="stylesheet" href="app/view/device/device.css">
     <link rel="stylesheet" href="app/view/host/host.css">
+    <link rel="stylesheet" href="app/view/app/app.css">
     <link rel="stylesheet" href="app/view/sample/sample.css">
     <!-- {INJECTED-STYLESHEETS-END} -->
 
diff --git a/web/gui/src/main/webapp/onos.js b/web/gui/src/main/webapp/onos.js
index d63d6d9..2822cf6 100644
--- a/web/gui/src/main/webapp/onos.js
+++ b/web/gui/src/main/webapp/onos.js
@@ -39,6 +39,7 @@
         'topo',
         'device',
         'host',
+        'app',
         'sample',
         // {INJECTED-VIEW-IDS-END}