GUI -- Starting migration of topology view to the updated framework. WIP.
diff --git a/web/gui/src/main/webapp/topo2.js b/web/gui/src/main/webapp/topo2.js
index 8d1f9c1..fcc4bb4 100644
--- a/web/gui/src/main/webapp/topo2.js
+++ b/web/gui/src/main/webapp/topo2.js
@@ -15,7 +15,7 @@
  */
 
 /*
- ONOS network topology viewer - PoC version 1.0
+ ONOS network topology viewer - version 1.1
 
  @author Simon Hunt
  */
@@ -25,7 +25,7 @@
 
     // configuration data
     var config = {
-        useLiveData: true,
+        useLiveData: false,
         debugOn: false,
         debug: {
             showNodeXY: false,
@@ -34,7 +34,7 @@
         options: {
             layering: true,
             collisionPrevention: true,
-            loadBackground: true
+            showBackground: true
         },
         backgroundUrl: 'img/us-map.png',
         data: {
@@ -55,22 +55,7 @@
             pkt: 'img/pkt.png',
             opt: 'img/opt.png'
         },
-        mastHeight: 36,
         force: {
-            note: 'node.class or link.class is used to differentiate',
-            linkDistance: {
-                infra: 200,
-                host: 40
-            },
-            linkStrength: {
-                infra: 1.0,
-                host: 1.0
-            },
-            charge: {
-                device: -800,
-                host: -1000
-            },
-            ticksWithoutCollisions: 50,
             marginLR: 20,
             marginTB: 20,
             translate: function() {
@@ -78,39 +63,19 @@
                     config.force.marginLR + ',' +
                     config.force.marginTB + ')';
             }
-        },
-        labels: {
-            imgPad: 16,
-            padLR: 8,
-            padTB: 6,
-            marginLR: 3,
-            marginTB: 2,
-            port: {
-                gap: 3,
-                width: 18,
-                height: 14
-            }
-        },
-        icons: {
-            w: 32,
-            h: 32,
-            xoff: -12,
-            yoff: -8
-        },
-        constraints: {
-            ypos: {
-                host: 0.05,
-                switch: 0.3,
-                roadm: 0.7
-            }
-        },
-        hostLinkWidth: 1.0,
-        hostRadius: 7,
-        mouseOutTimerDelayMs: 120
+        }
     };
 
+    // radio buttons
+    var btnSet = [
+            { id: 'showAll', text: 'All Layers' },
+            { id: 'showPkt', text: 'Packet Only' },
+            { id: 'showOpt', text: 'Optical Only' }
+        ];
+
     // state variables
-    var view = {},
+    var svg,
+        bgImg,
         network = {},
         selected = {},
         highlighted = null,
@@ -119,84 +84,19 @@
         portLabelsOn = false;
 
 
-    function debug(what) {
-        return config.debugOn && config.debug[what];
-    }
+    // ==============================
+    // Private functions
 
-    function urlData() {
-        return config.data[config.useLiveData ? 'live' : 'fake'];
-    }
-
-    function networkJsonUrl() {
-        return urlData().jsonUrl;
-    }
-
-    function safeId(id) {
-        return id.replace(/[^a-z0-9]/gi, '_');
-    }
-
-    function detailJsonUrl(id) {
-        var u = urlData(),
-            encId = config.useLiveData ? encodeURIComponent(id) : safeId(id);
-        return u.detailPrefix + encId + u.detailSuffix;
-    }
-
-
-    // load the topology view of the network
-    function loadNetworkView() {
-        // Hey, here I am, calling something on the ONOS api:
-        api.printTime();
-
-        resize();
-
-        // go get our network data from the server...
-        var url = networkJsonUrl();
-        d3.json(url , function (err, data) {
-            if (err) {
-                alert('Oops! Error reading JSON...\n\n' +
-                    'URL: ' + url + '\n\n' +
-                    'Error: ' + err.message);
-                return;
-            }
-//            console.log("here is the JSON data...");
-//            console.log(data);
-
-            network.data = data;
-            drawNetwork();
-        });
-
-        // while we wait for the data, set up the handlers...
-        setUpClickHandler();
-        setUpRadioButtonHandler();
-        setUpKeyHandler();
-        $(window).on('resize', resize);
-    }
-
-    function setUpClickHandler() {
-        // click handler for "selectable" objects
-        $(document).on('click', '.select-object', function () {
-            // when any object of class "select-object" is clicked...
-            var obj = network.lookup[$(this).data('id')];
-            if (obj) {
-                selectObject(obj);
-            }
-            // stop propagation of event (I think) ...
-            return false;
+    // set the size of the SVG layer (or other element) to that of the view
+    function setSize(view, el) {
+        var thing = el || svg;
+        thing.attr({
+            width: view.width(),
+            height: view.height()
         });
     }
 
-    function setUpRadioButtonHandler() {
-        d3.selectAll('#displayModes .radio').on('click', function () {
-            var id = d3.select(this).attr('id');
-            if (id !== viewMode) {
-                radioButton('displayModes', id);
-                viewMode = id;
-                doRadioAction(id);
-            }
-        });
-    }
-
-    function doRadioAction(id) {
+    function doRadio(view, id) {
         showAllLayers();
         if (id === 'showPkt') {
             showPacketLayer();
@@ -206,1014 +106,68 @@
     }
 
     function showAllLayers() {
-        network.node.classed('inactive', false);
-        network.link.classed('inactive', false);
-        d3.selectAll('svg .port').classed('inactive', false)
-        d3.selectAll('svg .portText').classed('inactive', false)
+//        network.node.classed('inactive', false);
+//        network.link.classed('inactive', false);
+//        d3.selectAll('svg .port').classed('inactive', false);
+//        d3.selectAll('svg .portText').classed('inactive', false);
+        alert('show all layers');
     }
 
     function showPacketLayer() {
-        network.node.each(function(d) {
-            // deactivate nodes that are not hosts or switches
-            if (d.class === 'device' && d.type !== 'switch') {
-                d3.select(this).classed('inactive', true);
-            }
-        });
-
-        network.link.each(function(lnk) {
-            // deactivate infrastructure links that have opt's as endpoints
-            if (lnk.source.type === 'roadm' || lnk.target.type === 'roadm') {
-                d3.select(this).classed('inactive', true);
-            }
-        });
-
-        // deactivate non-packet ports
-        d3.selectAll('svg .optPort').classed('inactive', true)
+        alert('show packet layer');
     }
 
     function showOpticalLayer() {
-        network.node.each(function(d) {
-            // deactivate nodes that are not optical devices
-            if (d.type !== 'roadm') {
-                d3.select(this).classed('inactive', true);
-            }
-        });
-
-        network.link.each(function(lnk) {
-            // deactivate infrastructure links that have opt's as endpoints
-            if (lnk.source.type !== 'roadm' || lnk.target.type !== 'roadm') {
-                d3.select(this).classed('inactive', true);
-            }
-        });
-
-        // deactivate non-packet ports
-        d3.selectAll('svg .pktPort').classed('inactive', true)
+        alert('show optical layer');
     }
 
-    function setUpKeyHandler() {
-        d3.select('body')
-            .on('keydown', function () {
-                processKeyEvent();
-                if (debug('showKeyHandler')) {
-                    network.svg.append('text')
-                        .attr('x', 5)
-                        .attr('y', 15)
-                        .style('font-size', '20pt')
-                        .text('keyCode: ' + d3.event.keyCode +
-                            ' applied to : ' + contextLabel())
-                        .transition().duration(2000)
-                        .style('font-size', '2pt')
-                        .style('fill-opacity', 0.01)
-                        .remove();
-                }
-            });
-    }
+    // ==============================
+    // View life-cycle callbacks
 
-    function contextLabel() {
-        return hovered === null ? "(nothing)" : hovered.id;
-    }
+    function preload(view, ctx) {
+        var w = view.width(),
+            h = view.height(),
+            idBg = view.uid('bg'),
+            showBg = config.options.showBackground ? 'visible' : 'hidden';
 
-    function radioButton(group, id) {
-        d3.selectAll("#" + group + " .radio").classed("active", false);
-        d3.select("#" + group + " #" + id).classed("active", true);
-    }
-
-    function processKeyEvent() {
-        var code = d3.event.keyCode;
-        switch (code) {
-            case 66:    // B
-                toggleBackground();
-                break;
-            case 71:    // G
-                cycleLayout();
-                break;
-            case 76:    // L
-                cycleLabels();
-                break;
-            case 80:    // P
-                togglePorts();
-                break;
-            case 85:    // U
-                unpin();
-                break;
-        }
-
-    }
-
-    function toggleBackground() {
-        var bg = d3.select('#bg'),
-            vis = bg.style('visibility'),
-            newvis = (vis === 'hidden') ? 'visible' : 'hidden';
-        bg.style('visibility', newvis);
-    }
-
-    function cycleLayout() {
-        config.options.layering = !config.options.layering;
-        network.force.resume();
-    }
-
-    function cycleLabels() {
-        console.log('Cycle Labels - context = ' + contextLabel());
-    }
-
-    function togglePorts() {
-        portLabelsOn = !portLabelsOn;
-        var portVis = portLabelsOn ? 'visible' : 'hidden';
-        d3.selectAll('.port').style('visibility', portVis);
-        d3.selectAll('.portText').style('visibility', portVis);
-    }
-
-    function unpin() {
-        if (hovered) {
-            hovered.fixed = false;
-            findNodeFromData(hovered).classed('fixed', false);
-            network.force.resume();
-        }
-        console.log('Unpin - context = ' + contextLabel());
-    }
-
-
-    // ========================================================
-
-    function drawNetwork() {
-        $('#view').empty();
-
-        prepareNodesAndLinks();
-        createLayout();
-        console.log("\n\nHere is the augmented network object...");
-        console.log(network);
-    }
-
-    function prepareNodesAndLinks() {
-        network.lookup = {};
-        network.nodes = [];
-        network.links = [];
-
-        var nw = network.forceWidth,
-            nh = network.forceHeight;
-
-        function yPosConstraintForNode(n) {
-            return config.constraints.ypos[n.type || 'host'];
-        }
-
-        // Note that both 'devices' and 'hosts' get mapped into the nodes array
-
-        // first, the devices...
-        network.data.devices.forEach(function(n) {
-            var ypc = yPosConstraintForNode(n),
-                ix = Math.random() * 0.6 * nw + 0.2 * nw,
-                iy = ypc * nh,
-                node = {
-                    id: n.id,
-                    labels: n.labels,
-                    class: 'device',
-                    icon: 'device',
-                    type: n.type,
-                    x: ix,
-                    y: iy,
-                    constraint: {
-                        weight: 0.7,
-                        y: iy
-                    }
-                };
-            network.lookup[n.id] = node;
-            network.nodes.push(node);
-        });
-
-        // then, the hosts...
-        network.data.hosts.forEach(function(n) {
-            var ypc = yPosConstraintForNode(n),
-                ix = Math.random() * 0.6 * nw + 0.2 * nw,
-                iy = ypc * nh,
-                node = {
-                    id: n.id,
-                    labels: n.labels,
-                    class: 'host',
-                    icon: 'host',
-                    type: n.type,
-                    x: ix,
-                    y: iy,
-                    constraint: {
-                        weight: 0.7,
-                        y: iy
-                    }
-                };
-            network.lookup[n.id] = node;
-            network.nodes.push(node);
-        });
-
-
-        // now, process the explicit links...
-        network.data.links.forEach(function(lnk) {
-            var src = network.lookup[lnk.src],
-                dst = network.lookup[lnk.dst],
-                id = src.id + "-" + dst.id;
-
-            var link = {
-                class: 'infra',
-                id: id,
-                type: lnk.type,
-                width: lnk.linkWidth,
-                source: src,
-                srcPort: lnk.srcPort,
-                target: dst,
-                tgtPort: lnk.dstPort,
-                strength: config.force.linkStrength.infra
-            };
-            network.links.push(link);
-        });
-
-        // finally, infer host links...
-        network.data.hosts.forEach(function(n) {
-            var src = network.lookup[n.id],
-                dst = network.lookup[n.cp.device],
-                id = src.id + "-" + dst.id;
-
-            var link = {
-                class: 'host',
-                id: id,
-                type: 'hostLink',
-                width: config.hostLinkWidth,
-                source: src,
-                target: dst,
-                strength: config.force.linkStrength.host
-            };
-            network.links.push(link);
-        });
-    }
-
-    function createLayout() {
-
-        var cfg = config.force;
-
-        network.force = d3.layout.force()
-            .size([network.forceWidth, network.forceHeight])
-            .nodes(network.nodes)
-            .links(network.links)
-            .linkStrength(function(d) { return cfg.linkStrength[d.class]; })
-            .linkDistance(function(d) { return cfg.linkDistance[d.class]; })
-            .charge(function(d) { return cfg.charge[d.class]; })
-            .on('tick', tick);
-
-        network.svg = d3.select('#view').append('svg')
-            .attr('width', view.width)
-            .attr('height', view.height)
-            .append('g')
+        // NOTE: view.$div is a D3 selection of the view's div
+        svg = view.$div.append('svg');
+        setSize(view);
+        svg.append('g')
             .attr('transform', config.force.translate());
-//            .attr('id', 'zoomable')
-//            .call(d3.behavior.zoom().on("zoom", zoomRedraw));
 
-        network.svg.append('svg:image')
+        // load the background image
+        bgImg = svg.append('svg:image')
             .attr({
-                id: 'bg',
-                width: view.width,
-                height: view.height,
+                id: idBg,
+                width: w,
+                height: h,
                 'xlink:href': config.backgroundUrl
             })
-            .style('visibility',
-                    config.options.loadBackground ? 'visible' : 'hidden');
-
-//        function zoomRedraw() {
-//            d3.select("#zoomable").attr("transform",
-//                    "translate(" + d3.event.translate + ")"
-//                    + " scale(" + d3.event.scale + ")");
-//        }
-
-        // TODO: move glow/blur stuff to util script
-        var glow = network.svg.append('filter')
-            .attr('x', '-50%')
-            .attr('y', '-50%')
-            .attr('width', '200%')
-            .attr('height', '200%')
-            .attr('id', 'blue-glow');
-
-        glow.append('feColorMatrix')
-            .attr('type', 'matrix')
-            .attr('values', '0 0 0 0  0 ' +
-                '0 0 0 0  0 ' +
-                '0 0 0 0  .7 ' +
-                '0 0 0 1  0 ');
-
-        glow.append('feGaussianBlur')
-            .attr('stdDeviation', 3)
-            .attr('result', 'coloredBlur');
-
-        glow.append('feMerge').selectAll('feMergeNode')
-            .data(['coloredBlur', 'SourceGraphic'])
-            .enter().append('feMergeNode')
-            .attr('in', String);
-
-        // TODO: legend (and auto adjust on scroll)
-//        $('#view').on('scroll', function() {
-//
-//        });
-
-
-        // TODO: move drag behavior into separate method.
-        // == define node drag behavior...
-        network.draggedThreshold = d3.scale.linear()
-            .domain([0, 0.1])
-            .range([5, 20])
-            .clamp(true);
-
-        function dragged(d) {
-            var threshold = network.draggedThreshold(network.force.alpha()),
-                dx = d.oldX - d.px,
-                dy = d.oldY - d.py;
-            if (Math.abs(dx) >= threshold || Math.abs(dy) >= threshold) {
-                d.dragged = true;
-            }
-            return d.dragged;
-        }
-
-        network.drag = d3.behavior.drag()
-            .origin(function(d) { return d; })
-            .on('dragstart', function(d) {
-                d.oldX = d.x;
-                d.oldY = d.y;
-                d.dragged = false;
-                d.fixed |= 2;
-            })
-            .on('drag', function(d) {
-                d.px = d3.event.x;
-                d.py = d3.event.y;
-                if (dragged(d)) {
-                    if (!network.force.alpha()) {
-                        network.force.alpha(.025);
-                    }
-                }
-            })
-            .on('dragend', function(d) {
-                if (!dragged(d)) {
-                    selectObject(d, this);
-                }
-                d.fixed &= ~6;
-
-                // once we've finished moving, pin the node in position,
-                // if it is a device (not a host)
-                if (d.class === 'device') {
-                    d.fixed = true;
-                    d3.select(this).classed('fixed', true)
-                }
+            .style({
+                visibility: showBg
             });
-
-        $('#view').on('click', function(e) {
-            if (!$(e.target).closest('.node').length) {
-                deselectObject();
-            }
-        });
-
-        // ...............................................................
-
-        // add links to the display
-        network.link = network.svg.append('g').attr('id', 'links')
-            .selectAll('.link')
-            .data(network.force.links(), function(d) {return d.id})
-            .enter().append('line')
-            .attr('class', function(d) {return 'link ' + d.class});
-
-        network.linkSrcPort = network.svg.append('g')
-            .attr({
-                id: 'srcPorts',
-                class: 'portLayer'
-            });
-        network.linkTgtPort = network.svg.append('g')
-            .attr({
-                id: 'tgtPorts',
-                class: 'portLayer'
-            });
-
-        var portVis = portLabelsOn ? 'visible' : 'hidden',
-            pw = config.labels.port.width,
-            ph = config.labels.port.height;
-
-        network.link.filter('.infra').each(function(d) {
-            var srcType = d.source.type === 'roadm' ? 'optPort' : 'pktPort',
-                tgtType = d.target.type === 'roadm' ? 'optPort' : 'pktPort';
-
-            if (d.source.type)
-
-            network.linkSrcPort.append('rect').attr({
-                id: 'srcPort-' + safeId(d.id),
-                class: 'port ' + srcType,
-                width: pw,
-                height: ph,
-                rx: 4,
-                ry: 4
-            }).style('visibility', portVis);
-
-            network.linkTgtPort.append('rect').attr({
-                id: 'tgtPort-' + safeId(d.id),
-                class: 'port ' + tgtType,
-                width: pw,
-                height: ph,
-                rx: 4,
-                ry: 4
-            }).style('visibility', portVis);
-
-            network.linkSrcPort.append('text').attr({
-                id: 'srcText-' + safeId(d.id),
-                class: 'portText ' + srcType
-            }).text(d.srcPort)
-                .style('visibility', portVis);
-
-            network.linkTgtPort.append('text').attr({
-                id: 'tgtText-' + safeId(d.id),
-                class: 'portText ' + tgtType
-            }).text(d.tgtPort)
-                .style('visibility', portVis);
-        });
-
-        // ...............................................................
-
-        // add nodes to the display
-        network.node = network.svg.selectAll('.node')
-            .data(network.force.nodes(), function(d) {return d.id})
-            .enter().append('g')
-            .attr('class', function(d) {
-                var cls = 'node ' + d.class;
-                if (d.type) {
-                    cls += ' ' + d.type;
-                }
-                return cls;
-            })
-            .attr('transform', function(d) {
-                return translate(d.x, d.y);
-            })
-            .call(network.drag)
-            .on('mouseover', function(d) {
-                // TODO: show tooltip
-                if (network.mouseoutTimeout) {
-                    clearTimeout(network.mouseoutTimeout);
-                    network.mouseoutTimeout = null;
-                }
-                hoverObject(d);
-            })
-            .on('mouseout', function(d) {
-                // TODO: hide tooltip
-                if (network.mouseoutTimeout) {
-                    clearTimeout(network.mouseoutTimeout);
-                    network.mouseoutTimeout = null;
-                }
-                network.mouseoutTimeout = setTimeout(function() {
-                    hoverObject(null);
-                }, config.mouseOutTimerDelayMs);
-            });
-
-
-        // deal with device nodes first
-        network.nodeRect = network.node.filter('.device')
-            .append('rect')
-            .attr({
-                rx: 5,
-                ry: 5,
-                width: 100,
-                height: 12
-            });
-            // note that width/height are adjusted to fit the label text
-            // then padded, and space made for the icon.
-
-        network.node.filter('.device').each(function(d) {
-            var node = d3.select(this),
-                icon = iconUrl(d);
-
-            node.append('text')
-            // TODO: add label cycle behavior
-                .text(d.id)
-                .attr('dy', '1.1em');
-
-            if (icon) {
-                var cfg = config.icons;
-                node.append('svg:image')
-                    .attr({
-                        width: cfg.w,
-                        height: cfg.h,
-                        'xlink:href': icon
-                    });
-                // note, icon relative positioning (x,y) is done after we have
-                // adjusted the bounds of the rectangle...
-            }
-
-            // debug function to show the modelled x,y coordinates of nodes...
-            if (debug('showNodeXY')) {
-                node.select('rect').attr('fill-opacity', 0.5);
-                node.append('circle')
-                    .attr({
-                        class: 'debug',
-                        cx: 0,
-                        cy: 0,
-                        r: '3px'
-                    });
-            }
-        });
-
-        // now process host nodes
-        network.nodeCircle = network.node.filter('.host')
-            .append('circle')
-            .attr({
-                r: config.hostRadius
-            });
-
-        network.node.filter('.host').each(function(d) {
-            var node = d3.select(this),
-                icon = iconUrl(d);
-
-            // debug function to show the modelled x,y coordinates of nodes...
-            if (debug('showNodeXY')) {
-                node.select('circle').attr('fill-opacity', 0.5);
-                node.append('circle')
-                    .attr({
-                        class: 'debug',
-                        cx: 0,
-                        cy: 0,
-                        r: '3px'
-                    });
-            }
-        });
-
-        // this function is scheduled to happen soon after the given thread ends
-        setTimeout(function() {
-            var lab = config.labels,
-                portGap = lab.port.gap,
-                midW = portGap + lab.port.width/ 2,
-                midH = portGap + lab.port.height / 2;
-
-            // post process the device nodes, to pad their size to fit the
-            // label text and attach the icon to the right location.
-            network.node.filter('.device').each(function(d) {
-                // for every node, recompute size, padding, etc. so text fits
-                var node = d3.select(this),
-                    text = node.select('text'),
-                    box = adjustRectToFitText(node);
-
-                // now make the computed adjustment
-                node.select('rect')
-                    .attr(box);
-
-                node.select('image')
-                    .attr('x', box.x + config.icons.xoff)
-                    .attr('y', box.y + config.icons.yoff);
-
-                var bounds = boundsFromBox(box),
-                    portBounds = {
-                        x1: bounds.x1 - midW,
-                        x2: bounds.x2 + midW,
-                        y1: bounds.y1 - midH,
-                        y2: bounds.y2 + midH
-                    };
-
-                // todo: clean up extent and edge work..
-                d.extent = {
-                    left: bounds.x1 - lab.marginLR,
-                    right: bounds.x2 + lab.marginLR,
-                    top: bounds.y1 - lab.marginTB,
-                    bottom: bounds.y2 + lab.marginTB
-                };
-
-                d.edge = {
-                    left   : new geo.LineSegment(bounds.x1, bounds.y1, bounds.x1, bounds.y2),
-                    right  : new geo.LineSegment(bounds.x2, bounds.y1, bounds.x2, bounds.y2),
-                    top    : new geo.LineSegment(bounds.x1, bounds.y1, bounds.x2, bounds.y1),
-                    bottom : new geo.LineSegment(bounds.x1, bounds.y2, bounds.x2, bounds.y2)
-                };
-
-                d.portEdge = {
-                    left   : new geo.LineSegment(
-                        portBounds.x1, portBounds.y1, portBounds.x1, portBounds.y2
-                    ),
-                    right  : new geo.LineSegment(
-                        portBounds.x2, portBounds.y1, portBounds.x2, portBounds.y2
-                    ),
-                    top    : new geo.LineSegment(
-                        portBounds.x1, portBounds.y1, portBounds.x2, portBounds.y1
-                    ),
-                    bottom : new geo.LineSegment(
-                        portBounds.x1, portBounds.y2, portBounds.x2, portBounds.y2
-                    )
-                };
-
-            });
-
-            network.numTicks = 0;
-            network.preventCollisions = false;
-            network.force.start();
-            for (var i = 0; i < config.force.ticksWithoutCollisions; i++) {
-                network.force.tick();
-            }
-            network.preventCollisions = true;
-            $('#view').css('visibility', 'visible');
-        });
-
-
-        // returns the newly computed bounding box of the rectangle
-        function adjustRectToFitText(n) {
-            var text = n.select('text'),
-                box = text.node().getBBox(),
-                lab = config.labels;
-
-            // not sure why n.data() returns an array of 1 element...
-            var data = n.data()[0];
-
-            text.attr('text-anchor', 'middle')
-                .attr('y', '-0.8em')
-                .attr('x', lab.imgPad/2)
-            ;
-
-            // translate the bbox so that it is centered on [x,y]
-            box.x = -box.width / 2;
-            box.y = -box.height / 2;
-
-            // add padding
-            box.x -= (lab.padLR + lab.imgPad/2);
-            box.width += lab.padLR * 2 + lab.imgPad;
-            box.y -= lab.padTB;
-            box.height += lab.padTB * 2;
-
-            return box;
-        }
-
-        function boundsFromBox(box) {
-            return {
-                x1: box.x,
-                y1: box.y,
-                x2: box.x + box.width,
-                y2: box.y + box.height
-            };
-        }
-
-    }
-
-    function iconUrl(d) {
-        return 'img/' + d.type + '.png';
-//        return config.iconUrl[d.icon];
-    }
-
-    function translate(x, y) {
-        return 'translate(' + x + ',' + y + ')';
-    }
-
-    // prevents collisions amongst device nodes
-    function preventCollisions() {
-        var quadtree = d3.geom.quadtree(network.nodes),
-            hrad = config.hostRadius;
-
-        network.nodes.forEach(function(n) {
-            var nx1, nx2, ny1, ny2;
-
-            if (n.class === 'device') {
-                nx1 = n.x + n.extent.left;
-                nx2 = n.x + n.extent.right;
-                ny1 = n.y + n.extent.top;
-                ny2 = n.y + n.extent.bottom;
-
-            } else {
-                nx1 = n.x - hrad;
-                nx2 = n.x + hrad;
-                ny1 = n.y - hrad;
-                ny2 = n.y + hrad;
-            }
-
-            quadtree.visit(function(quad, x1, y1, x2, y2) {
-                if (quad.point && quad.point !== n) {
-                    // check if the rectangles/circles intersect
-                    var p = quad.point,
-                        px1, px2, py1, py2, ix;
-
-                    if (p.class === 'device') {
-                        px1 = p.x + p.extent.left;
-                        px2 = p.x + p.extent.right;
-                        py1 = p.y + p.extent.top;
-                        py2 = p.y + p.extent.bottom;
-
-                    } else {
-                        px1 = p.x - hrad;
-                        px2 = p.x + hrad;
-                        py1 = p.y - hrad;
-                        py2 = p.y + hrad;
-                    }
-
-                    ix = (px1 <= nx2 && nx1 <= px2 && py1 <= ny2 && ny1 <= py2);
-
-                    if (ix) {
-                        var xa1 = nx2 - px1, // shift n left , p right
-                            xa2 = px2 - nx1, // shift n right, p left
-                            ya1 = ny2 - py1, // shift n up   , p down
-                            ya2 = py2 - ny1, // shift n down , p up
-                            adj = Math.min(xa1, xa2, ya1, ya2);
-
-                        if (adj == xa1) {
-                            n.x -= adj / 2;
-                            p.x += adj / 2;
-                        } else if (adj == xa2) {
-                            n.x += adj / 2;
-                            p.x -= adj / 2;
-                        } else if (adj == ya1) {
-                            n.y -= adj / 2;
-                            p.y += adj / 2;
-                        } else if (adj == ya2) {
-                            n.y += adj / 2;
-                            p.y -= adj / 2;
-                        }
-                    }
-                    return ix;
-                }
-            });
-
-        });
-    }
-
-    function tick(e) {
-        network.numTicks++;
-
-        if (config.options.layering) {
-            // adjust the y-coord of each node, based on y-pos constraints
-            network.nodes.forEach(function (n) {
-                var z = e.alpha * n.constraint.weight;
-                if (!isNaN(n.constraint.y)) {
-                    n.y = (n.constraint.y * z + n.y * (1 - z));
-                }
-            });
-        }
-
-        if (config.options.collisionPrevention && network.preventCollisions) {
-            preventCollisions();
-        }
-
-        var portHalfW = config.labels.port.width / 2,
-            portHalfH = config.labels.port.height / 2;
-
-        // clip visualization of links at bounds of nodes...
-        network.link.each(function(d) {
-            var xs = d.source.x,
-                ys = d.source.y,
-                xt = d.target.x,
-                yt = d.target.y,
-                line = new geo.LineSegment(xs, ys, xt, yt),
-                e, ix,
-                exs, eys, ext, eyt,
-                pxs, pys, pxt, pyt;
-
-            if (d.class === 'host') {
-                // no adjustment for source end of link, since hosts are dots
-                exs = xs;
-                eys = ys;
-
-            } else {
-                for (e in d.source.edge) {
-                    ix = line.intersect(d.source.edge[e].offset(xs, ys));
-                    if (ix.in1 && ix.in2) {
-                        exs = ix.x;
-                        eys = ix.y;
-
-                        // also pick off the port label intersection
-                        ix = line.intersect(d.source.portEdge[e].offset(xs, ys));
-                        pxs = ix.x;
-                        pys = ix.y;
-                        break;
-                    }
-                }
-            }
-
-            for (e in d.target.edge) {
-                ix = line.intersect(d.target.edge[e].offset(xt, yt));
-                if (ix.in1 && ix.in2) {
-                    ext = ix.x;
-                    eyt = ix.y;
-
-                    // also pick off the port label intersection
-                    ix = line.intersect(d.target.portEdge[e].offset(xt, yt));
-                    pxt = ix.x;
-                    pyt = ix.y;
-                    break;
-                }
-            }
-
-            // adjust the endpoints of the link's line to match rectangles
-            var sid = safeId(d.id);
-            d3.select(this)
-                .attr('x1', exs)
-                .attr('y1', eys)
-                .attr('x2', ext)
-                .attr('y2', eyt);
-
-            d3.select('#srcPort-' + sid)
-                .attr('x', pxs - portHalfW)
-                .attr('y', pys - portHalfH);
-
-            d3.select('#tgtPort-' + sid)
-                .attr('x', pxt - portHalfW)
-                .attr('y', pyt - portHalfH);
-
-            // TODO: fit label rect to size of port number.
-            d3.select('#srcText-' + sid)
-                .attr('x', pxs - 5)
-                .attr('y', pys + 3);
-
-            d3.select('#tgtText-' + sid)
-                .attr('x', pxt - 5)
-                .attr('y', pyt + 3);
-
-        });
-
-        // position each node by translating the node (group) by x,y
-        network.node
-            .attr('transform', function(d) {
-                return translate(d.x, d.y);
-            });
-
-    }
-
-    //    $('#docs-close').on('click', function() {
-    //        deselectObject();
-    //        return false;
-    //    });
-
-    //    $(document).on('click', '.select-object', function() {
-    //        var obj = graph.data[$(this).data('name')];
-    //        if (obj) {
-    //            selectObject(obj);
-    //        }
-    //        return false;
-    //    });
-
-    function findNodeFromData(d) {
-        var el = null;
-        network.node.filter('.' + d.class).each(function(n) {
-            if (n.id === d.id) {
-                el = d3.select(this);
-            }
-        });
-        return el;
-    }
-
-    function selectObject(obj, el) {
-        var node;
-        if (el) {
-            node = d3.select(el);
-        } else {
-            network.node.each(function(d) {
-                if (d == obj) {
-                    node = d3.select(el = this);
-                }
-            });
-        }
-        if (!node) return;
-
-        if (node.classed('selected')) {
-            deselectObject();
-            flyinPane(null);
-            return;
-        }
-        deselectObject(false);
-
-        selected = {
-            obj : obj,
-            el  : el
-        };
-
-        node.classed('selected', true);
-        flyinPane(obj);
-    }
-
-    function deselectObject(doResize) {
-        // Review: logic of 'resize(...)' function.
-        if (doResize || typeof doResize == 'undefined') {
-            resize(false);
-        }
-
-        // deselect all nodes in the network...
-        network.node.classed('selected', false);
-        selected = {};
-        flyinPane(null);
-    }
-
-    function flyinPane(obj) {
-        var pane = d3.select('#flyout'),
-            url;
-
-        if (obj) {
-            // go get details of the selected object from the server...
-            url = detailJsonUrl(obj.id);
-            d3.json(url, function (err, data) {
-                if (err) {
-                    alert('Oops! Error reading JSON...\n\n' +
-                        'URL: ' + url + '\n\n' +
-                        'Error: ' + err.message);
-                    return;
-                }
-//                console.log("JSON data... " + url);
-//                console.log(data);
-
-                displayDetails(data, pane);
-            });
-
-        } else {
-            // hide pane
-            pane.transition().duration(750)
-                .style('right', '-320px')
-                .style('opacity', 0.0);
-        }
-    }
-
-    function displayDetails(data, pane) {
-        $('#flyout').empty();
-
-        var title = pane.append("h2"),
-            table = pane.append("table"),
-            tbody = table.append("tbody");
-
-        $('<img src="img/' + data.type + '.png">').appendTo(title);
-        $('<span>').attr('class', 'icon').text(data.id).appendTo(title);
-
-
-        // TODO: consider using d3 data bind to TR/TD
-
-        data.propOrder.forEach(function(p) {
-            if (p === '-') {
-                addSep(tbody);
-            } else {
-                addProp(tbody, p, data.props[p]);
-            }
-        });
-
-        function addSep(tbody) {
-            var tr = tbody.append('tr');
-            $('<hr>').appendTo(tr.append('td').attr('colspan', 2));
-        }
-
-        function addProp(tbody, label, value) {
-            var tr = tbody.append('tr');
-
-            tr.append('td')
-                .attr('class', 'label')
-                .text(label + ' :');
-
-            tr.append('td')
-                .attr('class', 'value')
-                .text(value);
-        }
-
-        // show pane
-        pane.transition().duration(750)
-            .style('right', '20px')
-            .style('opacity', 1.0);
-    }
-
-    function highlightObject(obj) {
-        if (obj) {
-            if (obj != highlighted) {
-                // TODO set or clear "inactive" class on nodes, based on criteria
-                network.node.classed('inactive', function(d) {
-                    //                return (obj !== d &&
-                    //                    d.relation(obj.id));
-                    return (obj !== d);
-                });
-                // TODO: same with links
-                network.link.classed('inactive', function(d) {
-                    return (obj !== d.source && obj !== d.target);
-                });
-            }
-            highlighted = obj;
-        } else {
-            if (highlighted) {
-                // clear the inactive flag (no longer suppressed visually)
-                network.node.classed('inactive', false);
-                network.link.classed('inactive', false);
-            }
-            highlighted = null;
-
-        }
-    }
-
-    function hoverObject(obj) {
-        if (obj) {
-            hovered = obj;
-        } else {
-            if (hovered) {
-                hovered = null;
-            }
-        }
     }
 
 
-    function resize() {
-        view.height = window.innerHeight - config.mastHeight;
-        view.width = window.innerWidth;
-        $('#view')
-            .css('height', view.height + 'px')
-            .css('width', view.width + 'px');
+    function load(view, ctx) {
+        view.setRadio(btnSet, doRadio);
 
-        network.forceWidth = view.width - config.force.marginLR;
-        network.forceHeight = view.height - config.force.marginTB;
     }
 
-    // ======================================================================
-    // register with the UI framework
+    function resize(view, ctx) {
+        setSize(view);
+        setSize(view, bgImg);
+    }
+
+
+    // ==============================
+    // View registration
 
     onos.ui.addView('topo', {
-        load: loadNetworkView
+        preload: preload,
+        load: load,
+        resize: resize
     });
 
-
 }(ONOS));
-