blob: 9c40c361c8c7639fefc0c14531968cd3ad23e7b4 [file] [log] [blame]
Simon Hunt988c6fc2014-11-20 17:43:03 -08001/*
2 * Copyright 2014 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
Simon Hunt5cef9062014-11-24 15:24:35 -080018 ONOS GUI -- Quick Help Layer
Simon Hunt988c6fc2014-11-20 17:43:03 -080019
20 Defines the key-map layer for the UI. Used to give user a list of
21 key bindings; both global, and for the current view.
22
23 @author Simon Hunt
24 */
25
26(function (onos){
27 'use strict';
28
29 // API's
30 var api = onos.api;
31
32 // Config variables
33 var w = '100%',
34 h = '80%',
Simon Hunt209155e2014-11-21 12:16:09 -080035 fade = 500,
Simon Hunt5cef9062014-11-24 15:24:35 -080036 vb = '-200 0 400 400';
Simon Hunt988c6fc2014-11-20 17:43:03 -080037
38 // State variables
39 var data = [];
40
41 // DOM elements and the like
Simon Hunt5cef9062014-11-24 15:24:35 -080042 var qhdiv = d3.select('#quickhelp'),
43 svg = qhdiv.select('svg'),
44 pane,
45 rect,
46 items;
Simon Hunt988c6fc2014-11-20 17:43:03 -080047
Simon Hunt5cef9062014-11-24 15:24:35 -080048 // General functions
Simon Hunt56ef0fe2014-11-21 08:24:43 -080049 function isA(a) {
50 return $.isArray(a) ? a : null;
Simon Hunt988c6fc2014-11-20 17:43:03 -080051 }
52
Simon Hunt5cef9062014-11-24 15:24:35 -080053 var keyDisp = {
54 equals: '=',
55 dash: '-',
56 slash: '/',
57 leftArrow: 'L-arrow',
58 upArrow: 'U-arrow',
59 rightArrow: 'R-arrow',
60 downArrow: 'D-arrow'
61 };
Simon Hunt56ef0fe2014-11-21 08:24:43 -080062
Simon Hunt5cef9062014-11-24 15:24:35 -080063 function cap(s) {
64 return s.replace(/^[a-z]/, function (m) { return m.toUpperCase(); });
65 }
Simon Hunt56ef0fe2014-11-21 08:24:43 -080066
Simon Hunt5cef9062014-11-24 15:24:35 -080067 function mkKeyDisp(id) {
68 var v = keyDisp[id] || id;
69 return cap(v);
70 }
71
72 // layout configuration
73 var pad = 8,
74 offy = 45,
75 dy = 14,
76 offDesc = 40;
77
78 // D3 magic
Simon Hunt56ef0fe2014-11-21 08:24:43 -080079 function updateKeyItems() {
Simon Hunt5cef9062014-11-24 15:24:35 -080080 var keyItems = items.selectAll('.keyItem')
Simon Hunt988c6fc2014-11-20 17:43:03 -080081 .data(data);
82
Simon Hunt5cef9062014-11-24 15:24:35 -080083 var entering = keyItems.enter()
Simon Hunt988c6fc2014-11-20 17:43:03 -080084 .append('g')
85 .attr({
Simon Hunt56ef0fe2014-11-21 08:24:43 -080086 id: function (d) { return d.id; },
87 class: 'keyItem'
88 });
Simon Hunt988c6fc2014-11-20 17:43:03 -080089
Simon Hunt56ef0fe2014-11-21 08:24:43 -080090 entering.each(function (d, i) {
Simon Hunt988c6fc2014-11-20 17:43:03 -080091 var el = d3.select(this),
Simon Hunt56ef0fe2014-11-21 08:24:43 -080092 y = offy + dy * i;
Simon Hunt988c6fc2014-11-20 17:43:03 -080093
Simon Hunt56ef0fe2014-11-21 08:24:43 -080094 if (d.id === '_') {
95 el.append('line')
Simon Hunt5cef9062014-11-24 15:24:35 -080096 .attr({ x1: 0, y1: y, x2: 1, y2: y});
Simon Hunt56ef0fe2014-11-21 08:24:43 -080097 } else {
98 el.append('text')
99 .text(d.key)
100 .attr({
101 class: 'key',
Simon Hunt5cef9062014-11-24 15:24:35 -0800102 x: 0,
Simon Hunt56ef0fe2014-11-21 08:24:43 -0800103 y: y
104 });
105
106 el.append('text')
107 .text(d.desc)
108 .attr({
109 class: 'desc',
110 x: offDesc,
111 y: y
112 });
113 }
114 });
Simon Hunt5cef9062014-11-24 15:24:35 -0800115
116 var box = items.node().getBBox(),
117 paneW = box.width + pad * 2,
118 paneH = box.height + offy;
119
120 items.select('line').attr('x2', box.width);
121 items.attr('transform', translate(-paneW/2, -pad));
122 rect.attr({
123 width: paneW,
124 height: paneH,
125 transform: translate(-paneW/2-pad, 0)
126 });
127 }
128
129 function translate(x, y) {
130 return 'translate(' + x + ',' + y + ')';
Simon Hunt56ef0fe2014-11-21 08:24:43 -0800131 }
132
133 function aggregateData(bindings) {
134 var gmap = d3.map(bindings.globalKeys),
135 vmap = d3.map(bindings.viewKeys),
136 gkeys = gmap.keys(),
137 vkeys = vmap.keys();
138
139 gkeys.sort();
140 vkeys.sort();
141
142 data = [];
143 gkeys.forEach(function (k) {
144 addItem('global', k, gmap.get(k));
145 });
146 addItem('separator');
147 vkeys.forEach(function (k) {
148 addItem('view', k, vmap.get(k));
Simon Hunt988c6fc2014-11-20 17:43:03 -0800149 });
150
Simon Hunt56ef0fe2014-11-21 08:24:43 -0800151 function addItem(type, k, d) {
152 var id = type + '-' + k,
153 a = isA(d),
154 desc = a && a[1];
155 if (desc) {
156 data.push(
157 {
158 id: id,
159 type: type,
Simon Hunt5cef9062014-11-24 15:24:35 -0800160 key: mkKeyDisp(k),
Simon Hunt56ef0fe2014-11-21 08:24:43 -0800161 desc: desc
162 }
163 );
164 } else if (type === 'separator') {
165 data.push({
166 id: '_',
167 type: type
168 });
169 }
Simon Hunt988c6fc2014-11-20 17:43:03 -0800170 }
Simon Hunt988c6fc2014-11-20 17:43:03 -0800171 }
172
Simon Hunt5cef9062014-11-24 15:24:35 -0800173 function popBind(bindings) {
174 pane = svg.append('g')
Simon Hunt988c6fc2014-11-20 17:43:03 -0800175 .attr({
Simon Hunt5cef9062014-11-24 15:24:35 -0800176 class: 'help',
Simon Hunt988c6fc2014-11-20 17:43:03 -0800177 opacity: 0
Simon Hunt988c6fc2014-11-20 17:43:03 -0800178 });
179
Simon Hunt5cef9062014-11-24 15:24:35 -0800180 rect = pane.append('rect')
181 .attr('rx', 8);
182
Simon Hunt56ef0fe2014-11-21 08:24:43 -0800183 pane.append('text')
Simon Hunt5cef9062014-11-24 15:24:35 -0800184 .text('Quick Help')
Simon Hunt988c6fc2014-11-20 17:43:03 -0800185 .attr({
Simon Hunt5cef9062014-11-24 15:24:35 -0800186 class: 'title',
187 dy: '1.2em',
188 transform: translate(-pad,0)
Simon Hunt988c6fc2014-11-20 17:43:03 -0800189 });
190
Simon Hunt5cef9062014-11-24 15:24:35 -0800191 items = pane.append('g');
192
Simon Hunt56ef0fe2014-11-21 08:24:43 -0800193 aggregateData(bindings);
194 updateKeyItems();
Simon Hunt5cef9062014-11-24 15:24:35 -0800195
196 _fade(1);
Simon Hunt988c6fc2014-11-20 17:43:03 -0800197 }
198
199 function fadeBindings() {
Simon Hunt5cef9062014-11-24 15:24:35 -0800200 _fade(0);
201 }
202
203 function _fade(o) {
204 svg.selectAll('g.help')
Simon Hunt988c6fc2014-11-20 17:43:03 -0800205 .transition()
206 .duration(fade)
Simon Hunt5cef9062014-11-24 15:24:35 -0800207 .attr('opacity', o);
Simon Hunt988c6fc2014-11-20 17:43:03 -0800208 }
209
210 function addSvg() {
Simon Hunt5cef9062014-11-24 15:24:35 -0800211 svg = qhdiv.append('svg')
Simon Hunt988c6fc2014-11-20 17:43:03 -0800212 .attr({
213 width: w,
214 height: h,
215 viewBox: vb
216 });
217 }
218
219 function removeSvg() {
220 svg.transition()
221 .delay(fade + 20)
222 .remove();
223 }
224
Simon Hunt5cef9062014-11-24 15:24:35 -0800225 function showQuickHelp(bindings) {
226 svg = qhdiv.select('svg');
Simon Hunt988c6fc2014-11-20 17:43:03 -0800227 if (svg.empty()) {
228 addSvg();
Simon Hunt5cef9062014-11-24 15:24:35 -0800229 popBind(bindings);
Simon Hunt56ef0fe2014-11-21 08:24:43 -0800230 } else {
Simon Hunt5cef9062014-11-24 15:24:35 -0800231 hideQuickHelp();
Simon Hunt988c6fc2014-11-20 17:43:03 -0800232 }
233 }
234
Simon Hunt5cef9062014-11-24 15:24:35 -0800235 function hideQuickHelp() {
236 svg = qhdiv.select('svg');
Simon Hunt988c6fc2014-11-20 17:43:03 -0800237 if (!svg.empty()) {
238 fadeBindings();
239 removeSvg();
Simon Hunt988c6fc2014-11-20 17:43:03 -0800240 return true;
241 }
242 return false;
243 }
244
Simon Hunt5cef9062014-11-24 15:24:35 -0800245 onos.ui.addLib('quickHelp', {
246 show: showQuickHelp,
247 hide: hideQuickHelp
Simon Hunt988c6fc2014-11-20 17:43:03 -0800248 });
249}(ONOS));