blob: fc3e5b739e52dfc91995fe162e6ca7849690bb8d [file] [log] [blame]
/*
* Copyright 2016-present 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 -- Topology Force Module.
Visualization of the topology in an SVG layer, using a D3 Force Layout.
*/
(function () {
'use strict';
// injected refs
var $log, $loc, wss;
var t2is, t2rs, t2ls, t2vs, t2bcs, t2ss, t2bgs;
var svg, forceG, uplink, dim, opts, zoomer;
// D3 Selections
var node;
// ========================== Helper Functions
function init(_svg_, _forceG_, _uplink_, _dim_, _zoomer_, _opts_) {
svg = _svg_;
uplink = _uplink_;
dim = _dim_;
zoomer = _zoomer_;
opts = _opts_;
t2bgs.init();
t2bgs.region = t2rs;
t2ls.init(svg, uplink, dim, zoomer, opts);
t2bcs.addLayout(t2ls);
t2ss.init(svg, zoomer);
t2ss.region = t2rs;
t2rs.layout = t2ls;
navToBookmarkedRegion($loc.search().regionId);
}
function destroy() {
$log.debug('Destroy topo force layout');
}
function navToBookmarkedRegion(regionId) {
$log.debug('navToBookmarkedRegion:', regionId);
if (regionId) {
wss.sendEvent('topo2navRegion', {
rid: regionId
});
t2ls.createForceElements();
t2ls.transitionDownRegion();
}
}
// ========================== Event Handlers
function allInstances(data) {
$log.debug('>> topo2AllInstances event:', data);
t2is.allInstances(data);
}
function currentLayout(data) {
$log.debug('>> topo2CurrentLayout event:', data);
t2rs.clear();
t2bcs.addBreadcrumb(data.crumbs);
t2bgs.addLayout(data);
}
function currentRegion(data) {
$log.debug('>> topo2CurrentRegion event:', data);
t2rs.loaded('regionData', data);
}
function topo2PeerRegions(data) {
$log.debug('>> topo2PeerRegions event:', data);
t2rs.loaded('peers', data.peers);
}
function modelEvent(data) {
$log.debug('>> topo2UiModelEvent event:', data);
// TODO: Interpret the event and update our topo model state (if needed)
// To Decide: Can we assume that the server will only send events
// related to objects that we are currently showing?
// (e.g. filtered by subregion contents?)
t2rs.update(data);
}
function showMastership(masterId) {
if (masterId) {
showMastershipFor(masterId);
} else {
restoreLayerState();
}
}
function restoreLayerState() {
// NOTE: this level of indirection required, for when we have
// the layer filter functionality re-implemented
suppressLayers(false);
}
// ========================== Main Service Definition
function showMastershipFor(id) {
suppressLayers(true);
node.each(function (n) {
if (n.master === id) {
n.el.classed('suppressedmax', false);
}
});
}
function supAmt(less) {
return less ? 'suppressed' : 'suppressedmax';
}
function suppressLayers(b, less) {
var cls = supAmt(less);
node.classed(cls, b);
// link.classed(cls, b);
}
function newDim(_dim_) {
dim = _dim_;
t2vs.newDim(dim);
}
// ========================== Main Service Definition
function update(elements) {
angular.forEach(elements, function (el) {
el.update();
});
}
function updateNodes() {
update(t2rs.regionNodes());
}
function updateLinks() {
update(t2rs.regionLinks());
}
function resetNodeLocation() {
var hovered = t2rs.filterRegionNodes(function (model) {
return model.get('hovered');
});
angular.forEach(hovered, function (model) {
model.resetPosition();
});
}
function unpin() {
var hovered = t2rs.filterRegionNodes(function (model) {
return model.get('hovered');
});
angular.forEach(hovered, function (model) {
model.fix(false);
});
t2ls.start();
}
angular.module('ovTopo2')
.factory('Topo2ForceService', [
'$log', '$location', 'WebSocketService', 'Topo2InstanceService',
'Topo2RegionService', 'Topo2LayoutService', 'Topo2ViewService',
'Topo2BreadcrumbService', 'Topo2ZoomService', 'Topo2SelectService',
'Topo2BackgroundService',
function (_$log_, _$loc_, _wss_, _t2is_, _t2rs_, _t2ls_,
_t2vs_, _t2bcs_, zoomService, _t2ss_, _t2bgs_) {
$log = _$log_;
$loc = _$loc_;
wss = _wss_;
t2is = _t2is_;
t2rs = _t2rs_;
t2ls = _t2ls_;
t2vs = _t2vs_;
t2bcs = _t2bcs_;
t2ss = _t2ss_;
t2bgs = _t2bgs_;
var onZoom = function () {
var nodes = [].concat(
t2rs.regionNodes(),
t2rs.regionLinks()
);
angular.forEach(nodes, function (node) {
node.setScale();
});
};
zoomService.addZoomEventListener(onZoom);
return {
init: init,
newDim: newDim,
destroy: destroy,
topo2AllInstances: allInstances,
topo2CurrentLayout: currentLayout,
topo2CurrentRegion: currentRegion,
topo2UiModelEvent: modelEvent,
showMastership: showMastership,
topo2PeerRegions: topo2PeerRegions,
updateNodes: updateNodes,
updateLinks: updateLinks,
resetNodeLocation: resetNodeLocation,
unpin: unpin
};
}]);
})();