Committed by
Gerrit Code Review
Topo2Link - Fixed width of rectangle and centered text
Topo2Layout/Link - Added port number on link hover Topo2Layout/Select - Added Drag functionality Topo2SubRegion - Added onClick event to node Topo2Device - Added Color Theme TopoForce - Removed console.log Change-Id: Icd85d92c8f3c5f96cb896068fe9375c250717f5f
Showing
7 changed files
with
327 additions
and
23 deletions
| ... | @@ -69,7 +69,7 @@ | ... | @@ -69,7 +69,7 @@ |
| 69 | ps.setPrefs('topo_zoom', {tx:tr[0], ty:tr[1], sc:sc}); | 69 | ps.setPrefs('topo_zoom', {tx:tr[0], ty:tr[1], sc:sc}); |
| 70 | 70 | ||
| 71 | // keep the map lines constant width while zooming | 71 | // keep the map lines constant width while zooming |
| 72 | -// mapG.style('stroke-width', (2.0 / sc) + 'px'); | 72 | + mapG.style('stroke-width', (2.0 / sc) + 'px'); |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | function setUpZoom() { | 75 | function setUpZoom() { |
| ... | @@ -108,8 +108,8 @@ | ... | @@ -108,8 +108,8 @@ |
| 108 | // provides function calls back into this space | 108 | // provides function calls back into this space |
| 109 | // showNoDevs: showNoDevs, | 109 | // showNoDevs: showNoDevs, |
| 110 | // projection: function () { return projection; }, | 110 | // projection: function () { return projection; }, |
| 111 | - // zoomLayer: function () { return zoomLayer; }, | 111 | + zoomLayer: function () { return zoomLayer; }, |
| 112 | - // zoomer: function () { return zoomer; }, | 112 | + zoomer: function () { return zoomer; }, |
| 113 | // opacifyMap: opacifyMap, | 113 | // opacifyMap: opacifyMap, |
| 114 | // topoStartDone: topoStartDone | 114 | // topoStartDone: topoStartDone |
| 115 | }; | 115 | }; | ... | ... |
| ... | @@ -30,6 +30,7 @@ | ... | @@ -30,6 +30,7 @@ |
| 30 | 30 | ||
| 31 | // configuration | 31 | // configuration |
| 32 | var devIconDim = 36, | 32 | var devIconDim = 36, |
| 33 | + labelPad = 10, | ||
| 33 | hostRadius = 14, | 34 | hostRadius = 14, |
| 34 | badgeConfig = { | 35 | badgeConfig = { |
| 35 | radius: 12, | 36 | radius: 12, |
| ... | @@ -43,7 +44,8 @@ | ... | @@ -43,7 +44,8 @@ |
| 43 | i: 'badgeInfo', | 44 | i: 'badgeInfo', |
| 44 | w: 'badgeWarn', | 45 | w: 'badgeWarn', |
| 45 | e: 'badgeError' | 46 | e: 'badgeError' |
| 46 | - }; | 47 | + }, |
| 48 | + deviceLabelIndex = 0; | ||
| 47 | 49 | ||
| 48 | function createDeviceCollection(data, region) { | 50 | function createDeviceCollection(data, region) { |
| 49 | 51 | ||
| ... | @@ -81,13 +83,25 @@ | ... | @@ -81,13 +83,25 @@ |
| 81 | } | 83 | } |
| 82 | } | 84 | } |
| 83 | 85 | ||
| 84 | - function deviceGlyphColor(d) { | 86 | + // note: these are the device icon colors without affinity (no master) |
| 87 | + var dColTheme = { | ||
| 88 | + light: { | ||
| 89 | + online: '#444444', | ||
| 90 | + offline: '#cccccc' | ||
| 91 | + }, | ||
| 92 | + dark: { | ||
| 93 | + // TODO: theme | ||
| 94 | + online: '#444444', | ||
| 95 | + offline: '#cccccc' | ||
| 96 | + } | ||
| 97 | + }; | ||
| 85 | 98 | ||
| 99 | + function deviceGlyphColor(d) { | ||
| 86 | var o = this.node.online, | 100 | var o = this.node.online, |
| 87 | id = this.node.master, // TODO: This should be from node.master | 101 | id = this.node.master, // TODO: This should be from node.master |
| 88 | otag = o ? 'online' : 'offline'; | 102 | otag = o ? 'online' : 'offline'; |
| 89 | return o ? sus.cat7().getColor(id, 0, ts.theme()) | 103 | return o ? sus.cat7().getColor(id, 0, ts.theme()) |
| 90 | - : '#ff0000'; | 104 | + : dColTheme[ts.theme()][otag]; |
| 91 | } | 105 | } |
| 92 | 106 | ||
| 93 | function setDeviceColor() { | 107 | function setDeviceColor() { | ... | ... |
| ... | @@ -22,12 +22,12 @@ | ... | @@ -22,12 +22,12 @@ |
| 22 | (function () { | 22 | (function () { |
| 23 | 'use strict'; | 23 | 'use strict'; |
| 24 | 24 | ||
| 25 | - var $log, sus, t2rs, t2d3, t2vs; | 25 | + var $log, sus, t2rs, t2d3, t2vs, t2ss; |
| 26 | 26 | ||
| 27 | - var linkG, linkLabelG, numLinkLabelsG, nodeG, portLabelG; | 27 | + var uplink, linkG, linkLabelG, numLinkLabelsG, nodeG, portLabelG; |
| 28 | var link, linkLabel, node; | 28 | var link, linkLabel, node; |
| 29 | 29 | ||
| 30 | - var nodes, links; | 30 | + var nodes, links, highlightedLink; |
| 31 | 31 | ||
| 32 | var force; | 32 | var force; |
| 33 | 33 | ||
| ... | @@ -124,7 +124,7 @@ | ... | @@ -124,7 +124,7 @@ |
| 124 | function init(_svg_, forceG, _uplink_, _dim_, opts) { | 124 | function init(_svg_, forceG, _uplink_, _dim_, opts) { |
| 125 | 125 | ||
| 126 | $log.debug("Initialising Topology Layout"); | 126 | $log.debug("Initialising Topology Layout"); |
| 127 | - | 127 | + uplink = _uplink_; |
| 128 | settings = angular.extend({}, defaultSettings, opts); | 128 | settings = angular.extend({}, defaultSettings, opts); |
| 129 | 129 | ||
| 130 | linkG = forceG.append('g').attr('id', 'topo-links'); | 130 | linkG = forceG.append('g').attr('id', 'topo-links'); |
| ... | @@ -147,6 +147,35 @@ | ... | @@ -147,6 +147,35 @@ |
| 147 | .linkDistance(settings.linkDistance._def_) | 147 | .linkDistance(settings.linkDistance._def_) |
| 148 | .linkStrength(settings.linkStrength._def_) | 148 | .linkStrength(settings.linkStrength._def_) |
| 149 | .on('tick', tick); | 149 | .on('tick', tick); |
| 150 | + | ||
| 151 | + drag = sus.createDragBehavior(force, | ||
| 152 | + t2ss.selectObject, atDragEnd, dragEnabled, clickEnabled); | ||
| 153 | + | ||
| 154 | + _svg_.on('mousemove', mouseMoveHandler) | ||
| 155 | + } | ||
| 156 | + | ||
| 157 | + function zoomingOrPanning(ev) { | ||
| 158 | + return ev.metaKey || ev.altKey; | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + function atDragEnd(d) { | ||
| 162 | + // once we've finished moving, pin the node in position | ||
| 163 | + d.fixed = true; | ||
| 164 | + d3.select(this).classed('fixed', true); | ||
| 165 | + // TODO: sendUpdateMeta(d); | ||
| 166 | + t2ss.clickConsumed(true); | ||
| 167 | + } | ||
| 168 | + | ||
| 169 | + // predicate that indicates when dragging is active | ||
| 170 | + function dragEnabled() { | ||
| 171 | + var ev = d3.event.sourceEvent; | ||
| 172 | + // nodeLock means we aren't allowing nodes to be dragged... | ||
| 173 | + return !nodeLock && !zoomingOrPanning(ev); | ||
| 174 | + } | ||
| 175 | + | ||
| 176 | + // predicate that indicates when clicking is active | ||
| 177 | + function clickEnabled() { | ||
| 178 | + return true; | ||
| 150 | } | 179 | } |
| 151 | 180 | ||
| 152 | function tick() { | 181 | function tick() { |
| ... | @@ -188,6 +217,7 @@ | ... | @@ -188,6 +217,7 @@ |
| 188 | }, | 217 | }, |
| 189 | opacity: 0 | 218 | opacity: 0 |
| 190 | }) | 219 | }) |
| 220 | + .call(drag) | ||
| 191 | // .on('mouseover', tss.nodeMouseOver) | 221 | // .on('mouseover', tss.nodeMouseOver) |
| 192 | // .on('mouseout', tss.nodeMouseOut) | 222 | // .on('mouseout', tss.nodeMouseOut) |
| 193 | .transition() | 223 | .transition() |
| ... | @@ -308,18 +338,140 @@ | ... | @@ -308,18 +338,140 @@ |
| 308 | force.start(); | 338 | force.start(); |
| 309 | } | 339 | } |
| 310 | 340 | ||
| 341 | + // Mouse Events | ||
| 342 | + function mouseMoveHandler() { | ||
| 343 | + var mp = getLogicalMousePosition(this), | ||
| 344 | + link = computeNearestLink(mp); | ||
| 345 | + | ||
| 346 | + | ||
| 347 | + if (highlightedLink) { | ||
| 348 | + highlightedLink.unenhance(); | ||
| 349 | + highlightedLink = null; | ||
| 350 | + } | ||
| 351 | + | ||
| 352 | + if (link) { | ||
| 353 | + link.enhance(); | ||
| 354 | + highlightedLink = link; | ||
| 355 | + } | ||
| 356 | + } | ||
| 357 | + | ||
| 358 | + // ======== ALGORITHM TO FIND LINK CLOSEST TO MOUSE ======== | ||
| 359 | + | ||
| 360 | + function getLogicalMousePosition(container) { | ||
| 361 | + var m = d3.mouse(container), | ||
| 362 | + sc = uplink.zoomer().scale(), | ||
| 363 | + tr = uplink.zoomer().translate(), | ||
| 364 | + mx = (m[0] - tr[0]) / sc, | ||
| 365 | + my = (m[1] - tr[1]) / sc; | ||
| 366 | + return {x: mx, y: my}; | ||
| 367 | + } | ||
| 368 | + | ||
| 369 | + | ||
| 370 | + function sq(x) { return x * x; } | ||
| 371 | + | ||
| 372 | + function mdist(p, m) { | ||
| 373 | + return Math.sqrt(sq(p.x - m.x) + sq(p.y - m.y)); | ||
| 374 | + } | ||
| 375 | + | ||
| 376 | + function prox(dist) { | ||
| 377 | + return dist / uplink.zoomer().scale(); | ||
| 378 | + } | ||
| 379 | + | ||
| 380 | + function computeNearestNode(mouse) { | ||
| 381 | + var proximity = prox(30), | ||
| 382 | + nearest = null, | ||
| 383 | + minDist, | ||
| 384 | + regionNodes = t2rs.regionNodes(); | ||
| 385 | + | ||
| 386 | + if (regionNodes.length) { | ||
| 387 | + minDist = proximity * 2; | ||
| 388 | + | ||
| 389 | + regionNodes.forEach(function (d) { | ||
| 390 | + var dist; | ||
| 391 | + | ||
| 392 | + if (!api.showHosts() && d.class === 'host') { | ||
| 393 | + return; // skip hidden hosts | ||
| 394 | + } | ||
| 395 | + | ||
| 396 | + dist = mdist({x: d.x, y: d.y}, mouse); | ||
| 397 | + if (dist < minDist && dist < proximity) { | ||
| 398 | + minDist = dist; | ||
| 399 | + nearest = d; | ||
| 400 | + } | ||
| 401 | + }); | ||
| 402 | + } | ||
| 403 | + return nearest; | ||
| 404 | + } | ||
| 405 | + | ||
| 406 | + | ||
| 407 | + function computeNearestLink(mouse) { | ||
| 408 | + var proximity = prox(30), | ||
| 409 | + nearest = null, | ||
| 410 | + minDist, | ||
| 411 | + regionLinks = t2rs.regionLinks(); | ||
| 412 | + | ||
| 413 | + function pdrop(line, mouse) { | ||
| 414 | + | ||
| 415 | + var x1 = line.x1, | ||
| 416 | + y1 = line.y1, | ||
| 417 | + x2 = line.x2, | ||
| 418 | + y2 = line.y2, | ||
| 419 | + x3 = mouse.x, | ||
| 420 | + y3 = mouse.y, | ||
| 421 | + k = ((y2-y1) * (x3-x1) - (x2-x1) * (y3-y1)) / | ||
| 422 | + (sq(y2-y1) + sq(x2-x1)), | ||
| 423 | + x4 = x3 - k * (y2-y1), | ||
| 424 | + y4 = y3 + k * (x2-x1); | ||
| 425 | + return {x:x4, y:y4}; | ||
| 426 | + } | ||
| 427 | + | ||
| 428 | + function lineHit(line, p, m) { | ||
| 429 | + if (p.x < line.x1 && p.x < line.x2) return false; | ||
| 430 | + if (p.x > line.x1 && p.x > line.x2) return false; | ||
| 431 | + if (p.y < line.y1 && p.y < line.y2) return false; | ||
| 432 | + if (p.y > line.y1 && p.y > line.y2) return false; | ||
| 433 | + // line intersects, but are we close enough? | ||
| 434 | + return mdist(p, m) <= proximity; | ||
| 435 | + } | ||
| 436 | + | ||
| 437 | + if (regionLinks.length) { | ||
| 438 | + minDist = proximity * 2; | ||
| 439 | + | ||
| 440 | + regionLinks.forEach(function (d) { | ||
| 441 | + // if (!api.showHosts() && d.type() === 'hostLink') { | ||
| 442 | + // return; // skip hidden host links | ||
| 443 | + // } | ||
| 444 | + | ||
| 445 | + var line = d.get('position'), | ||
| 446 | + point = pdrop(line, mouse), | ||
| 447 | + hit = lineHit(line, point, mouse), | ||
| 448 | + dist; | ||
| 449 | + | ||
| 450 | + if (hit) { | ||
| 451 | + dist = mdist(point, mouse); | ||
| 452 | + if (dist < minDist) { | ||
| 453 | + minDist = dist; | ||
| 454 | + nearest = d; | ||
| 455 | + } | ||
| 456 | + } | ||
| 457 | + }); | ||
| 458 | + } | ||
| 459 | + return nearest; | ||
| 460 | + } | ||
| 461 | + | ||
| 311 | angular.module('ovTopo2') | 462 | angular.module('ovTopo2') |
| 312 | .factory('Topo2LayoutService', | 463 | .factory('Topo2LayoutService', |
| 313 | [ | 464 | [ |
| 314 | '$log', 'SvgUtilService', 'Topo2RegionService', | 465 | '$log', 'SvgUtilService', 'Topo2RegionService', |
| 315 | - 'Topo2D3Service', 'Topo2ViewService', | 466 | + 'Topo2D3Service', 'Topo2ViewService', 'Topo2SelectService', |
| 316 | 467 | ||
| 317 | - function (_$log_, _sus_, _t2rs_, _t2d3_, _t2vs_) { | 468 | + function (_$log_, _sus_, _t2rs_, _t2d3_, _t2vs_, _t2ss_) { |
| 318 | 469 | ||
| 319 | $log = _$log_; | 470 | $log = _$log_; |
| 320 | t2rs = _t2rs_; | 471 | t2rs = _t2rs_; |
| 321 | t2d3 = _t2d3_; | 472 | t2d3 = _t2d3_; |
| 322 | t2vs = _t2vs_; | 473 | t2vs = _t2vs_; |
| 474 | + t2ss = _t2ss_; | ||
| 323 | sus = _sus_; | 475 | sus = _sus_; |
| 324 | 476 | ||
| 325 | return { | 477 | return { | ... | ... |
| ... | @@ -23,7 +23,9 @@ | ... | @@ -23,7 +23,9 @@ |
| 23 | 'use strict'; | 23 | 'use strict'; |
| 24 | 24 | ||
| 25 | var $log; | 25 | var $log; |
| 26 | - var Collection, Model, region, ts; | 26 | + var Collection, Model, region, ts, sus; |
| 27 | + | ||
| 28 | + var linkLabelOffset = '0.35em'; | ||
| 27 | 29 | ||
| 28 | var widthRatio = 1.4, | 30 | var widthRatio = 1.4, |
| 29 | linkScale = d3.scale.linear() | 31 | linkScale = d3.scale.linear() |
| ... | @@ -70,12 +72,26 @@ | ... | @@ -70,12 +72,26 @@ |
| 70 | y2: 0 | 72 | y2: 0 |
| 71 | } | 73 | } |
| 72 | // functions to aggregate dual link state | 74 | // functions to aggregate dual link state |
| 73 | -// extra: link.extra | 75 | + // extra: link.extra |
| 74 | }); | 76 | }); |
| 75 | 77 | ||
| 76 | this.set(attrs); | 78 | this.set(attrs); |
| 77 | } | 79 | } |
| 78 | 80 | ||
| 81 | + function rectAroundText(el) { | ||
| 82 | + var text = el.select('text'), | ||
| 83 | + box = text.node().getBBox(); | ||
| 84 | + | ||
| 85 | + // translate the bbox so that it is centered on [x,y] | ||
| 86 | + box.x = -box.width / 2; | ||
| 87 | + box.y = -box.height / 2; | ||
| 88 | + | ||
| 89 | + // add padding | ||
| 90 | + box.x -= 4; | ||
| 91 | + box.width += 8; | ||
| 92 | + return box; | ||
| 93 | + } | ||
| 94 | + | ||
| 79 | function linkEndPoints(srcId, dstId) { | 95 | function linkEndPoints(srcId, dstId) { |
| 80 | 96 | ||
| 81 | var sourceNode = this.region.findNodeById(srcId) | 97 | var sourceNode = this.region.findNodeById(srcId) |
| ... | @@ -106,13 +122,71 @@ | ... | @@ -106,13 +122,71 @@ |
| 106 | return this.get('type'); | 122 | return this.get('type'); |
| 107 | }, | 123 | }, |
| 108 | expected: function () { | 124 | expected: function () { |
| 109 | - //TODO: original code is: (s && s.expected) && (t && t.expected); | 125 | + // TODO: original code is: (s && s.expected) && (t && t.expected); |
| 110 | return true; | 126 | return true; |
| 111 | }, | 127 | }, |
| 112 | online: function () { | 128 | online: function () { |
| 129 | + // TODO: remove next line | ||
| 113 | return true; | 130 | return true; |
| 131 | + | ||
| 114 | return both && (s && s.online) && (t && t.online); | 132 | return both && (s && s.online) && (t && t.online); |
| 115 | }, | 133 | }, |
| 134 | + enhance: function () { | ||
| 135 | + var data = [], | ||
| 136 | + point; | ||
| 137 | + | ||
| 138 | + angular.forEach(this.collection.models, function (link) { | ||
| 139 | + link.unenhance(); | ||
| 140 | + }); | ||
| 141 | + | ||
| 142 | + this.el.classed('enhanced', true); | ||
| 143 | + point = this.locatePortLabel(); | ||
| 144 | + angular.extend(point, { | ||
| 145 | + id: 'topo-port-tgt', | ||
| 146 | + num: this.get('portB') | ||
| 147 | + }); | ||
| 148 | + data.push(point); | ||
| 149 | + | ||
| 150 | + var entering = d3.select('#topo-portLabels').selectAll('.portLabel') | ||
| 151 | + .data(data).enter().append('g') | ||
| 152 | + .classed('portLabel', true) | ||
| 153 | + .attr('id', function (d) { return d.id; }); | ||
| 154 | + | ||
| 155 | + entering.each(function (d) { | ||
| 156 | + var el = d3.select(this), | ||
| 157 | + rect = el.append('rect'), | ||
| 158 | + text = el.append('text').text(d.num); | ||
| 159 | + | ||
| 160 | + rect.attr(rectAroundText(el)) | ||
| 161 | + .attr('rx', 2) | ||
| 162 | + .attr('ry', 2); | ||
| 163 | + | ||
| 164 | + text.attr('dy', linkLabelOffset) | ||
| 165 | + .attr('text-anchor', 'middle'); | ||
| 166 | + | ||
| 167 | + el.attr('transform', sus.translate(d.x, d.y)); | ||
| 168 | + }); | ||
| 169 | + }, | ||
| 170 | + unenhance: function () { | ||
| 171 | + this.el.classed('enhanced', false); | ||
| 172 | + d3.select('#topo-portLabels').selectAll('.portLabel').remove(); | ||
| 173 | + }, | ||
| 174 | + locatePortLabel: function (link, src) { | ||
| 175 | + var offset = 32, | ||
| 176 | + pos = this.get('position'), | ||
| 177 | + nearX = src ? pos.x1 : pos.x2, | ||
| 178 | + nearY = src ? pos.y1 : pos.y2, | ||
| 179 | + farX = src ? pos.x2 : pos.x1, | ||
| 180 | + farY = src ? pos.y2 : pos.y1; | ||
| 181 | + | ||
| 182 | + function dist(x, y) { return Math.sqrt(x*x + y*y); } | ||
| 183 | + | ||
| 184 | + var dx = farX - nearX, | ||
| 185 | + dy = farY - nearY, | ||
| 186 | + k = offset / dist(dx, dy); | ||
| 187 | + | ||
| 188 | + return {x: k * dx + nearX, y: k * dy + nearY}; | ||
| 189 | + }, | ||
| 116 | restyleLinkElement: function (immediate) { | 190 | restyleLinkElement: function (immediate) { |
| 117 | // this fn's job is to look at raw links and decide what svg classes | 191 | // this fn's job is to look at raw links and decide what svg classes |
| 118 | // need to be applied to the line element in the DOM | 192 | // need to be applied to the line element in the DOM |
| ... | @@ -144,9 +218,10 @@ | ... | @@ -144,9 +218,10 @@ |
| 144 | .attr('stroke', linkConfig[th].baseColor); | 218 | .attr('stroke', linkConfig[th].baseColor); |
| 145 | } | 219 | } |
| 146 | }, | 220 | }, |
| 147 | - | ||
| 148 | onEnter: function (el) { | 221 | onEnter: function (el) { |
| 149 | - var link = d3.select(el); | 222 | + var _this = this, |
| 223 | + link = d3.select(el); | ||
| 224 | + | ||
| 150 | this.el = link; | 225 | this.el = link; |
| 151 | 226 | ||
| 152 | this.restyleLinkElement(); | 227 | this.restyleLinkElement(); |
| ... | @@ -166,12 +241,13 @@ | ... | @@ -166,12 +241,13 @@ |
| 166 | 241 | ||
| 167 | angular.module('ovTopo2') | 242 | angular.module('ovTopo2') |
| 168 | .factory('Topo2LinkService', | 243 | .factory('Topo2LinkService', |
| 169 | - ['$log', 'Topo2Collection', 'Topo2Model', 'ThemeService', | 244 | + ['$log', 'Topo2Collection', 'Topo2Model', 'ThemeService', 'SvgUtilService', |
| 170 | 245 | ||
| 171 | - function (_$log_, _Collection_, _Model_, _ts_) { | 246 | + function (_$log_, _Collection_, _Model_, _ts_, _sus_) { |
| 172 | 247 | ||
| 173 | $log = _$log_; | 248 | $log = _$log_; |
| 174 | ts = _ts_; | 249 | ts = _ts_; |
| 250 | + sus = _sus_; | ||
| 175 | Collection = _Collection_; | 251 | Collection = _Collection_; |
| 176 | Model = _Model_; | 252 | Model = _Model_; |
| 177 | 253 | ... | ... |
| 1 | +/* | ||
| 2 | + * Copyright 2016-present 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 | +/* | ||
| 18 | + ONOS GUI -- Topology Select Module. | ||
| 19 | + */ | ||
| 20 | + | ||
| 21 | +(function () { | ||
| 22 | + 'use strict'; | ||
| 23 | + | ||
| 24 | + // internal state | ||
| 25 | + var hovered, selections, selectOrder, consumeClick; | ||
| 26 | + | ||
| 27 | + function selectObject(obj) { | ||
| 28 | + var el = this, | ||
| 29 | + nodeEv = el && el.tagName === 'g', | ||
| 30 | + ev = d3.event.sourceEvent || {}, | ||
| 31 | + n; | ||
| 32 | + | ||
| 33 | + console.log(el, nodeEv, ev, n); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + function clickConsumed(x) { | ||
| 37 | + var cc = consumeClick; | ||
| 38 | + consumeClick = !!x; | ||
| 39 | + return cc; | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + angular.module('ovTopo2') | ||
| 43 | + .factory('Topo2SelectService', | ||
| 44 | + [ | ||
| 45 | + function () { | ||
| 46 | + | ||
| 47 | + return { | ||
| 48 | + selectObject: selectObject, | ||
| 49 | + clickConsumed: clickConsumed | ||
| 50 | + }; | ||
| 51 | + } | ||
| 52 | + ]); | ||
| 53 | + | ||
| 54 | +})(); | ... | ... |
| ... | @@ -22,7 +22,8 @@ | ... | @@ -22,7 +22,8 @@ |
| 22 | (function () { | 22 | (function () { |
| 23 | 'use strict'; | 23 | 'use strict'; |
| 24 | 24 | ||
| 25 | - var Collection, Model, is, sus, ts, t2vs; | 25 | + var wss, is, sus, ts, t2vs; |
| 26 | + var Collection, Model; | ||
| 26 | 27 | ||
| 27 | var remappedDeviceTypes = { | 28 | var remappedDeviceTypes = { |
| 28 | virtual: 'cord' | 29 | virtual: 'cord' |
| ... | @@ -71,11 +72,12 @@ | ... | @@ -71,11 +72,12 @@ |
| 71 | 72 | ||
| 72 | angular.module('ovTopo2') | 73 | angular.module('ovTopo2') |
| 73 | .factory('Topo2SubRegionService', | 74 | .factory('Topo2SubRegionService', |
| 74 | - ['Topo2Collection', 'Topo2NodeModel', 'IconService', 'SvgUtilService', | 75 | + ['WebSocketService', 'Topo2Collection', 'Topo2NodeModel', 'IconService', 'SvgUtilService', |
| 75 | 'ThemeService', 'Topo2ViewService', | 76 | 'ThemeService', 'Topo2ViewService', |
| 76 | 77 | ||
| 77 | - function (_Collection_, _NodeModel_, _is_, _sus_, _ts_, classnames, _t2vs_) { | 78 | + function (_wss_, _Collection_, _NodeModel_, _is_, _sus_, _ts_, classnames, _t2vs_) { |
| 78 | 79 | ||
| 80 | + wss = _wss_; | ||
| 79 | t2vs = _t2vs_; | 81 | t2vs = _t2vs_; |
| 80 | is = _is_; | 82 | is = _is_; |
| 81 | sus = _sus_; | 83 | sus = _sus_; |
| ... | @@ -89,6 +91,12 @@ | ... | @@ -89,6 +91,12 @@ |
| 89 | }, | 91 | }, |
| 90 | nodeType: 'sub-region', | 92 | nodeType: 'sub-region', |
| 91 | mapDeviceTypeToGlyph: mapDeviceTypeToGlyph, | 93 | mapDeviceTypeToGlyph: mapDeviceTypeToGlyph, |
| 94 | + onClick: function () { | ||
| 95 | + wss.sendEvent('topo2navRegion', { | ||
| 96 | + dir: 'down', | ||
| 97 | + rid: this.get('id') | ||
| 98 | + }); | ||
| 99 | + }, | ||
| 92 | onEnter: function (el) { | 100 | onEnter: function (el) { |
| 93 | 101 | ||
| 94 | var node = d3.select(el), | 102 | var node = d3.select(el), |
| ... | @@ -97,6 +105,7 @@ | ... | @@ -97,6 +105,7 @@ |
| 97 | glyph, labelWidth; | 105 | glyph, labelWidth; |
| 98 | 106 | ||
| 99 | this.el = node; | 107 | this.el = node; |
| 108 | + this.el.on('click', this.onClick.bind(this)); | ||
| 100 | 109 | ||
| 101 | // Label | 110 | // Label |
| 102 | var labelElements = this.addLabelElements(label); | 111 | var labelElements = this.addLabelElements(label); | ... | ... |
-
Please register or login to post a comment