GUI -- Topo Panels now dynamically adjust their height to fit in the whole windo…
…w. Topo panel structure changed to have api for dynamic content to be added later. Change-Id: I70b272ca740efdf5392d8896271baef4a7cf97b5
Showing
2 changed files
with
164 additions
and
62 deletions
| ... | @@ -82,7 +82,7 @@ | ... | @@ -82,7 +82,7 @@ |
| 82 | 82 | ||
| 83 | #topo-p-detail { | 83 | #topo-p-detail { |
| 84 | /* Base css from panel.css */ | 84 | /* Base css from panel.css */ |
| 85 | - top: 320px; | 85 | + top: 310px; |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | #topo-p-detail .actionBtns .actionBtn { | 88 | #topo-p-detail .actionBtns .actionBtn { |
| ... | @@ -95,6 +95,10 @@ | ... | @@ -95,6 +95,10 @@ |
| 95 | 95 | ||
| 96 | /* --- general topo-panel styling --- */ | 96 | /* --- general topo-panel styling --- */ |
| 97 | 97 | ||
| 98 | +.topo-p div.body { | ||
| 99 | + overflow-y: scroll; | ||
| 100 | +} | ||
| 101 | + | ||
| 98 | .topo-p svg { | 102 | .topo-p svg { |
| 99 | display: inline-block; | 103 | display: inline-block; |
| 100 | width: 42px; | 104 | width: 42px; |
| ... | @@ -119,7 +123,9 @@ | ... | @@ -119,7 +123,9 @@ |
| 119 | 123 | ||
| 120 | .topo-p h2 { | 124 | .topo-p h2 { |
| 121 | position: absolute; | 125 | position: absolute; |
| 122 | - margin: 0 4px; | 126 | + padding: 0 4px; |
| 127 | + margin: 0; | ||
| 128 | + word-wrap: break-word; | ||
| 123 | top: 20px; | 129 | top: 20px; |
| 124 | left: 50px; | 130 | left: 50px; |
| 125 | } | 131 | } |
| ... | @@ -131,7 +137,9 @@ | ... | @@ -131,7 +137,9 @@ |
| 131 | } | 137 | } |
| 132 | 138 | ||
| 133 | .topo-p h3 { | 139 | .topo-p h3 { |
| 134 | - margin: 0 4px; | 140 | + padding: 0 4px; |
| 141 | + margin: 0; | ||
| 142 | + word-wrap: break-word; | ||
| 135 | top: 20px; | 143 | top: 20px; |
| 136 | left: 50px; | 144 | left: 50px; |
| 137 | } | 145 | } |
| ... | @@ -143,16 +151,19 @@ | ... | @@ -143,16 +151,19 @@ |
| 143 | } | 151 | } |
| 144 | 152 | ||
| 145 | .topo-p p, table { | 153 | .topo-p p, table { |
| 146 | - margin: 4px 4px; | 154 | + padding: 4px; |
| 155 | + margin: 0; | ||
| 147 | } | 156 | } |
| 148 | 157 | ||
| 158 | +.topo-p td { | ||
| 159 | + word-wrap: break-word; | ||
| 160 | +} | ||
| 149 | .topo-p td.label { | 161 | .topo-p td.label { |
| 150 | font-style: italic; | 162 | font-style: italic; |
| 151 | padding-right: 12px; | 163 | padding-right: 12px; |
| 152 | /* works for both light and dark themes ... */ | 164 | /* works for both light and dark themes ... */ |
| 153 | color: #777; | 165 | color: #777; |
| 154 | } | 166 | } |
| 155 | - | ||
| 156 | .topo-p td.value { | 167 | .topo-p td.value { |
| 157 | } | 168 | } |
| 158 | 169 | ... | ... |
| ... | @@ -33,14 +33,101 @@ | ... | @@ -33,14 +33,101 @@ |
| 33 | width: 260 | 33 | width: 260 |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | - // panels | ||
| 37 | - var summaryPanel, | ||
| 38 | - detailPanel; | ||
| 39 | - | ||
| 40 | // internal state | 36 | // internal state |
| 41 | var useDetails = true, // should we show details if we have 'em? | 37 | var useDetails = true, // should we show details if we have 'em? |
| 42 | haveDetails = false; // do we have details that we could show? | 38 | haveDetails = false; // do we have details that we could show? |
| 43 | 39 | ||
| 40 | + // panels | ||
| 41 | + var summary, detail; | ||
| 42 | + | ||
| 43 | + // === ----------------------------------------------------- | ||
| 44 | + // Panel API | ||
| 45 | + function createTopoPanel(id, opts) { | ||
| 46 | + var p = ps.createPanel(id, opts), | ||
| 47 | + header, body, footer; | ||
| 48 | + p.classed(pCls, true); | ||
| 49 | + | ||
| 50 | + function hAppend(x) { | ||
| 51 | + return header.append(x); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + function bAppend(x) { | ||
| 55 | + return body.append(x); | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + function fAppend(x) { | ||
| 59 | + return footer.append(x); | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + function setup() { | ||
| 63 | + p.empty(); | ||
| 64 | + | ||
| 65 | + p.append('div').classed('header', true); | ||
| 66 | + p.append('div').classed('body', true); | ||
| 67 | + p.append('div').classed('footer', true); | ||
| 68 | + | ||
| 69 | + header = p.el().select('.header'); | ||
| 70 | + body = p.el().select('.body'); | ||
| 71 | + footer = p.el().select('.footer'); | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + // fromTop is how many pixels from the top of the page the panel is | ||
| 75 | + // max is the max height of the panel in pixels | ||
| 76 | + // only adjusts if the body content would be 10px or larger | ||
| 77 | + function adjustHeight(fromTop, max) { | ||
| 78 | + var totalPHeight, avSpace, | ||
| 79 | + overflow = 0, | ||
| 80 | + pdg = 30; | ||
| 81 | + | ||
| 82 | + if (!fromTop) { | ||
| 83 | + $log.warn('adjustHeight: height from top of page not given'); | ||
| 84 | + return null; | ||
| 85 | + } else if (!body || !p) { | ||
| 86 | + // if we have reached this function without setting a panel | ||
| 87 | + // sometimes the d3 tick function calls detail panel's 'up' | ||
| 88 | + // on reload when body isn't defined yet. | ||
| 89 | + $log.warn('adjustHeight: panel is not defined'); | ||
| 90 | + return null; | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + p.el().style('height', null); | ||
| 94 | + body.style('height', null); | ||
| 95 | + | ||
| 96 | + totalPHeight = fromTop + p.height(); | ||
| 97 | + avSpace = fs.windowSize(pdg).height; | ||
| 98 | + | ||
| 99 | + if (totalPHeight >= avSpace) { | ||
| 100 | + overflow = totalPHeight - avSpace; | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + function _adjustBody(height) { | ||
| 104 | + if (height < 10) { | ||
| 105 | + return false; | ||
| 106 | + } else { | ||
| 107 | + body.style('height', height + 'px'); | ||
| 108 | + } | ||
| 109 | + return true; | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + if (!_adjustBody(fs.noPxStyle(body, 'height') - overflow)) { | ||
| 113 | + return; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + if (max && p.height() > max) { | ||
| 117 | + _adjustBody(fs.noPxStyle(body, 'height') - (p.height() - max)); | ||
| 118 | + } | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + return { | ||
| 122 | + panel: p, | ||
| 123 | + setup: setup, | ||
| 124 | + appendHeader: hAppend, | ||
| 125 | + appendBody: bAppend, | ||
| 126 | + appendFooter: fAppend, | ||
| 127 | + adjustHeight: adjustHeight | ||
| 128 | + }; | ||
| 129 | + } | ||
| 130 | + | ||
| 44 | // === ----------------------------------------------------- | 131 | // === ----------------------------------------------------- |
| 45 | // Utility functions | 132 | // Utility functions |
| 46 | 133 | ||
| ... | @@ -48,6 +135,11 @@ | ... | @@ -48,6 +135,11 @@ |
| 48 | tbody.append('tr').append('td').attr('colspan', 2).append('hr'); | 135 | tbody.append('tr').append('td').attr('colspan', 2).append('hr'); |
| 49 | } | 136 | } |
| 50 | 137 | ||
| 138 | + function addBtnFooter() { | ||
| 139 | + detail.appendFooter('hr'); | ||
| 140 | + detail.appendFooter('div').classed('actionBtns', true); | ||
| 141 | + } | ||
| 142 | + | ||
| 51 | function addProp(tbody, label, value) { | 143 | function addProp(tbody, label, value) { |
| 52 | var tr = tbody.append('tr'), | 144 | var tr = tbody.append('tr'), |
| 53 | lab; | 145 | lab; |
| ... | @@ -65,7 +157,7 @@ | ... | @@ -65,7 +157,7 @@ |
| 65 | } | 157 | } |
| 66 | 158 | ||
| 67 | function listProps(tbody, data) { | 159 | function listProps(tbody, data) { |
| 68 | - data.propOrder.forEach(function(p) { | 160 | + data.propOrder.forEach(function (p) { |
| 69 | if (p === '-') { | 161 | if (p === '-') { |
| 70 | addSep(tbody); | 162 | addSep(tbody); |
| 71 | } else { | 163 | } else { |
| ... | @@ -74,23 +166,15 @@ | ... | @@ -74,23 +166,15 @@ |
| 74 | }); | 166 | }); |
| 75 | } | 167 | } |
| 76 | 168 | ||
| 77 | - function dpa(x) { | ||
| 78 | - return detailPanel.append(x); | ||
| 79 | - } | ||
| 80 | - | ||
| 81 | - function spa(x) { | ||
| 82 | - return summaryPanel.append(x); | ||
| 83 | - } | ||
| 84 | - | ||
| 85 | // === ----------------------------------------------------- | 169 | // === ----------------------------------------------------- |
| 86 | // Functions for populating the summary panel | 170 | // Functions for populating the summary panel |
| 87 | 171 | ||
| 88 | function populateSummary(data) { | 172 | function populateSummary(data) { |
| 89 | - summaryPanel.empty(); | 173 | + summary.setup(); |
| 90 | 174 | ||
| 91 | - var svg = spa('svg'), | 175 | + var svg = summary.appendHeader('svg'), |
| 92 | - title = spa('h2'), | 176 | + title = summary.appendHeader('h2'), |
| 93 | - table = spa('table'), | 177 | + table = summary.appendBody('table'), |
| 94 | tbody = table.append('tbody'); | 178 | tbody = table.append('tbody'); |
| 95 | 179 | ||
| 96 | gs.addGlyph(svg, 'node', 40); | 180 | gs.addGlyph(svg, 'node', 40); |
| ... | @@ -104,33 +188,31 @@ | ... | @@ -104,33 +188,31 @@ |
| 104 | // Functions for populating the detail panel | 188 | // Functions for populating the detail panel |
| 105 | 189 | ||
| 106 | function displaySingle(data) { | 190 | function displaySingle(data) { |
| 107 | - detailPanel.empty(); | 191 | + detail.setup(); |
| 108 | 192 | ||
| 109 | - var svg = dpa('svg'), | 193 | + var svg = detail.appendHeader('svg'), |
| 110 | - title = dpa('h2'), | 194 | + title = detail.appendHeader('h2'), |
| 111 | - table = dpa('table'), | 195 | + table = detail.appendBody('table'), |
| 112 | tbody = table.append('tbody'); | 196 | tbody = table.append('tbody'); |
| 113 | 197 | ||
| 114 | gs.addGlyph(svg, (data.type || 'unknown'), 40); | 198 | gs.addGlyph(svg, (data.type || 'unknown'), 40); |
| 115 | title.text(data.id); | 199 | title.text(data.id); |
| 116 | listProps(tbody, data); | 200 | listProps(tbody, data); |
| 117 | - dpa('hr'); | 201 | + addBtnFooter(); |
| 118 | - dpa('div').classed('actionBtns', true); | ||
| 119 | } | 202 | } |
| 120 | 203 | ||
| 121 | function displayMulti(ids) { | 204 | function displayMulti(ids) { |
| 122 | - detailPanel.empty(); | 205 | + detail.setup(); |
| 123 | 206 | ||
| 124 | - var title = dpa('h3'), | 207 | + var title = detail.appendHeader('h3'), |
| 125 | - table = dpa('table'), | 208 | + table = detail.appendBody('table'), |
| 126 | tbody = table.append('tbody'); | 209 | tbody = table.append('tbody'); |
| 127 | 210 | ||
| 128 | title.text('Selected Nodes'); | 211 | title.text('Selected Nodes'); |
| 129 | ids.forEach(function (d, i) { | 212 | ids.forEach(function (d, i) { |
| 130 | addProp(tbody, i+1, d); | 213 | addProp(tbody, i+1, d); |
| 131 | }); | 214 | }); |
| 132 | - dpa('hr'); | 215 | + addBtnFooter(); |
| 133 | - dpa('div').classed('actionBtns', true); | ||
| 134 | } | 216 | } |
| 135 | 217 | ||
| 136 | function addAction(o) { | 218 | function addAction(o) { |
| ... | @@ -177,11 +259,11 @@ | ... | @@ -177,11 +259,11 @@ |
| 177 | ]; | 259 | ]; |
| 178 | 260 | ||
| 179 | function displayLink(data) { | 261 | function displayLink(data) { |
| 180 | - detailPanel.empty(); | 262 | + detail.setup(); |
| 181 | 263 | ||
| 182 | - var svg = dpa('svg'), | 264 | + var svg = detail.appendHeader('svg'), |
| 183 | - title = dpa('h2'), | 265 | + title = detail.appendHeader('h2'), |
| 184 | - table = dpa('table'), | 266 | + table = detail.appendBody('table'), |
| 185 | tbody = table.append('tbody'), | 267 | tbody = table.append('tbody'), |
| 186 | edgeLink = data.type() === 'hostLink', | 268 | edgeLink = data.type() === 'hostLink', |
| 187 | order = edgeLink ? edgeOrder : coreOrder; | 269 | order = edgeLink ? edgeOrder : coreOrder; |
| ... | @@ -235,7 +317,7 @@ | ... | @@ -235,7 +317,7 @@ |
| 235 | 317 | ||
| 236 | function toggleSummary(x) { | 318 | function toggleSummary(x) { |
| 237 | var kev = (x === 'keyev'), | 319 | var kev = (x === 'keyev'), |
| 238 | - on = kev ? !summaryPanel.isVisible() : !!x, | 320 | + on = kev ? !summary.panel.isVisible() : !!x, |
| 239 | verb = on ? 'Show' : 'Hide'; | 321 | verb = on ? 'Show' : 'Hide'; |
| 240 | 322 | ||
| 241 | if (on) { | 323 | if (on) { |
| ... | @@ -253,29 +335,33 @@ | ... | @@ -253,29 +335,33 @@ |
| 253 | // === LOGIC For showing/hiding summary and detail panels... | 335 | // === LOGIC For showing/hiding summary and detail panels... |
| 254 | 336 | ||
| 255 | function showSummaryPanel() { | 337 | function showSummaryPanel() { |
| 256 | - if (detailPanel.isVisible()) { | 338 | + function _show() { |
| 257 | - detailPanel.down(summaryPanel.show); | 339 | + summary.panel.show(); |
| 340 | + summary.adjustHeight(64, 226); | ||
| 341 | + } | ||
| 342 | + if (detail.panel.isVisible()) { | ||
| 343 | + detail.down(_show); | ||
| 258 | } else { | 344 | } else { |
| 259 | - summaryPanel.show(); | 345 | + _show(); |
| 260 | } | 346 | } |
| 261 | } | 347 | } |
| 262 | 348 | ||
| 263 | function hideSummaryPanel() { | 349 | function hideSummaryPanel() { |
| 264 | // instruct server to stop sending summary data | 350 | // instruct server to stop sending summary data |
| 265 | wss.sendEvent("cancelSummary"); | 351 | wss.sendEvent("cancelSummary"); |
| 266 | - summaryPanel.hide(detailPanel.up); | 352 | + summary.panel.hide(detail.up); |
| 267 | } | 353 | } |
| 268 | 354 | ||
| 269 | function showDetailPanel() { | 355 | function showDetailPanel() { |
| 270 | - if (summaryPanel.isVisible()) { | 356 | + if (summary.panel.isVisible()) { |
| 271 | - detailPanel.down(detailPanel.show); | 357 | + detail.down(detail.panel.show); |
| 272 | } else { | 358 | } else { |
| 273 | - detailPanel.up(detailPanel.show); | 359 | + detail.up(detail.panel.show); |
| 274 | } | 360 | } |
| 275 | } | 361 | } |
| 276 | 362 | ||
| 277 | function hideDetailPanel() { | 363 | function hideDetailPanel() { |
| 278 | - detailPanel.hide(); | 364 | + detail.panel.hide(); |
| 279 | } | 365 | } |
| 280 | 366 | ||
| 281 | // ========================== | 367 | // ========================== |
| ... | @@ -283,15 +369,15 @@ | ... | @@ -283,15 +369,15 @@ |
| 283 | function noop () {} | 369 | function noop () {} |
| 284 | 370 | ||
| 285 | function augmentDetailPanel() { | 371 | function augmentDetailPanel() { |
| 286 | - var dp = detailPanel; | 372 | + var d = detail; |
| 287 | - dp.ypos = { up: 64, down: 320, current: 320}; | 373 | + d.ypos = { up: 64, down: 310, current: 310}; |
| 288 | 374 | ||
| 289 | - dp._move = function (y, cb) { | 375 | + d._move = function (y, cb) { |
| 290 | var endCb = fs.isF(cb) || noop, | 376 | var endCb = fs.isF(cb) || noop, |
| 291 | - yp = dp.ypos; | 377 | + yp = d.ypos; |
| 292 | if (yp.current !== y) { | 378 | if (yp.current !== y) { |
| 293 | yp.current = y; | 379 | yp.current = y; |
| 294 | - dp.el().transition().duration(300) | 380 | + d.panel.el().transition().duration(300) |
| 295 | .each('end', endCb) | 381 | .each('end', endCb) |
| 296 | .style('top', yp.current + 'px'); | 382 | .style('top', yp.current + 'px'); |
| 297 | } else { | 383 | } else { |
| ... | @@ -299,8 +385,15 @@ | ... | @@ -299,8 +385,15 @@ |
| 299 | } | 385 | } |
| 300 | }; | 386 | }; |
| 301 | 387 | ||
| 302 | - dp.down = function (cb) { dp._move(dp.ypos.down, cb); }; | 388 | + // d.up is being called on the tick function for some reason |
| 303 | - dp.up = function (cb) { dp._move(dp.ypos.up, cb); }; | 389 | + d.down = function (cb) { |
| 390 | + d._move(d.ypos.down, cb); | ||
| 391 | + detail.adjustHeight(d.ypos.current); | ||
| 392 | + }; | ||
| 393 | + d.up = function (cb) { | ||
| 394 | + d._move(d.ypos.up, cb); | ||
| 395 | + detail.adjustHeight(d.ypos.current); | ||
| 396 | + }; | ||
| 304 | } | 397 | } |
| 305 | 398 | ||
| 306 | function toggleUseDetailsFlag(x) { | 399 | function toggleUseDetailsFlag(x) { |
| ... | @@ -324,11 +417,8 @@ | ... | @@ -324,11 +417,8 @@ |
| 324 | // ========================== | 417 | // ========================== |
| 325 | 418 | ||
| 326 | function initPanels() { | 419 | function initPanels() { |
| 327 | - summaryPanel = ps.createPanel(idSum, panelOpts); | 420 | + summary = createTopoPanel(idSum, panelOpts); |
| 328 | - detailPanel = ps.createPanel(idDet, panelOpts); | 421 | + detail = createTopoPanel(idDet, panelOpts); |
| 329 | - | ||
| 330 | - summaryPanel.classed(pCls, true); | ||
| 331 | - detailPanel.classed(pCls, true); | ||
| 332 | 422 | ||
| 333 | augmentDetailPanel(); | 423 | augmentDetailPanel(); |
| 334 | } | 424 | } |
| ... | @@ -336,7 +426,7 @@ | ... | @@ -336,7 +426,7 @@ |
| 336 | function destroyPanels() { | 426 | function destroyPanels() { |
| 337 | ps.destroyPanel(idSum); | 427 | ps.destroyPanel(idSum); |
| 338 | ps.destroyPanel(idDet); | 428 | ps.destroyPanel(idDet); |
| 339 | - summaryPanel = detailPanel = null; | 429 | + summary.panel = detail.panel = null; |
| 340 | haveDetails = false; | 430 | haveDetails = false; |
| 341 | } | 431 | } |
| 342 | 432 | ||
| ... | @@ -359,6 +449,7 @@ | ... | @@ -359,6 +449,7 @@ |
| 359 | return { | 449 | return { |
| 360 | initPanels: initPanels, | 450 | initPanels: initPanels, |
| 361 | destroyPanels: destroyPanels, | 451 | destroyPanels: destroyPanels, |
| 452 | + createTopoPanel: createTopoPanel, | ||
| 362 | 453 | ||
| 363 | showSummary: showSummary, | 454 | showSummary: showSummary, |
| 364 | toggleSummary: toggleSummary, | 455 | toggleSummary: toggleSummary, |
| ... | @@ -366,15 +457,15 @@ | ... | @@ -366,15 +457,15 @@ |
| 366 | toggleUseDetailsFlag: toggleUseDetailsFlag, | 457 | toggleUseDetailsFlag: toggleUseDetailsFlag, |
| 367 | displaySingle: displaySingle, | 458 | displaySingle: displaySingle, |
| 368 | displayMulti: displayMulti, | 459 | displayMulti: displayMulti, |
| 369 | - addAction: addAction, | ||
| 370 | displayLink: displayLink, | 460 | displayLink: displayLink, |
| 371 | displayNothing: displayNothing, | 461 | displayNothing: displayNothing, |
| 372 | displaySomething: displaySomething, | 462 | displaySomething: displaySomething, |
| 463 | + addAction: addAction, | ||
| 373 | 464 | ||
| 374 | hideSummaryPanel: hideSummaryPanel, | 465 | hideSummaryPanel: hideSummaryPanel, |
| 375 | 466 | ||
| 376 | - detailVisible: function () { return detailPanel.isVisible(); }, | 467 | + detailVisible: function () { return detail.panel.isVisible(); }, |
| 377 | - summaryVisible: function () { return summaryPanel.isVisible(); } | 468 | + summaryVisible: function () { return summary.panel.isVisible(); } |
| 378 | }; | 469 | }; |
| 379 | }]); | 470 | }]); |
| 380 | }()); | 471 | }()); | ... | ... |
-
Please register or login to post a comment