Commit 546bc22f by kevalbhatt

ATLAS-3060 : UI: Allow to drag node and place it accordingly

Signed-off-by: 's avatarkevalbhatt <kbhatt@apache.org>
parent d030b525
...@@ -22,6 +22,7 @@ define(['require', ...@@ -22,6 +22,7 @@ define(['require',
'collection/VLineageList', 'collection/VLineageList',
'models/VEntity', 'models/VEntity',
'utils/Utils', 'utils/Utils',
'views/graph/LineageUtils',
'dagreD3', 'dagreD3',
'd3-tip', 'd3-tip',
'utils/Enums', 'utils/Enums',
...@@ -29,7 +30,7 @@ define(['require', ...@@ -29,7 +30,7 @@ define(['require',
'utils/Globals', 'utils/Globals',
'platform', 'platform',
'jquery-ui' 'jquery-ui'
], function(require, Backbone, LineageLayoutViewtmpl, VLineageList, VEntity, Utils, dagreD3, d3Tip, Enums, UrlLinks, Globals, platform) { ], function(require, Backbone, LineageLayoutViewtmpl, VLineageList, VEntity, Utils, LineageUtils, dagreD3, d3Tip, Enums, UrlLinks, Globals, platform) {
'use strict'; 'use strict';
var LineageLayoutView = Backbone.Marionette.LayoutView.extend( var LineageLayoutView = Backbone.Marionette.LayoutView.extend(
...@@ -469,39 +470,7 @@ define(['require', ...@@ -469,39 +470,7 @@ define(['require',
this.$('.lineage-edge-details').removeClass('open'); this.$('.lineage-edge-details').removeClass('open');
} }
}, },
centerNode: function(nodeID) {
var zoom = function() {
svgGroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
};
var selectedNode = this.$('svg').find("g.nodes").find('>g#' + nodeID);
if (selectedNode.length > 0) {
selectedNode = selectedNode;
var matrix = selectedNode.attr('transform').replace(/[^0-9\-.,]/g, '').split(','),
x = matrix[0],
y = matrix[1];
} else {
selectedNode = this.$('svg').find("g.nodes").find('g').eq(1);
var x = this.g.graph().width / 2,
y = this.g.graph().height / 2;
}
var viewerWidth = this.$('svg').width(),
viewerHeight = this.$('svg').height(),
gBBox = d3.select('g').node().getBBox(),
zoomListener = d3.behavior.zoom().scaleExtent([0.01, 50]).on("zoom", zoom),
scale = 1.2,
xa = -((x * scale) - (viewerWidth / 2)),
ya = -((y * scale) - (viewerHeight / 2));
this.zoom.translate([xa, ya]);
d3.select('g').transition()
.duration(350)
.attr("transform", "translate(" + xa + "," + ya + ")scale(" + scale + ")");
zoomListener.scale(scale);
zoomListener.translate([xa, ya]);
this.zoom.scale(scale);
},
zoomed: function(that) { zoomed: function(that) {
this.$('svg').find('>g').attr("transform", this.$('svg').find('>g').attr("transform",
"translate(" + this.zoom.translate() + ")" + "translate(" + this.zoom.translate() + ")" +
...@@ -654,36 +623,6 @@ define(['require', ...@@ -654,36 +623,6 @@ define(['require',
svg.on("dblclick.zoom", null) svg.on("dblclick.zoom", null)
// .on("wheel.zoom", null); // .on("wheel.zoom", null);
//change text postion //change text postion
function isConnected(a, b, o) {
//console.log(a, b, o);
if (a === o || (b && b.length && b.indexOf(o) != -1)) {
return true;
}
}
function fade(opacity, d, nodesToHighlight) {
var node = svg.selectAll('.node');
var path = svg.selectAll('.edgePath');
node.classed("hover-active", function(selectedNode, i, nodes) {
if (isConnected(d, nodesToHighlight, selectedNode)) {
return true;
} else {
return false;
}
});
path.classed('hover-active-node', function(c) {
var _thisOpacity = c.v === d || c.w === d ? 1 : 0;
if (_thisOpacity) {
return true;
} else {
return false;
}
});
}
//Highlight on click
svgGroup.selectAll("g.nodes g.label") svgGroup.selectAll("g.nodes g.label")
.attr("transform", "translate(2,-35)"); .attr("transform", "translate(2,-35)");
var waitForDoubleClick = null; var waitForDoubleClick = null;
...@@ -723,7 +662,12 @@ define(['require', ...@@ -723,7 +662,12 @@ define(['require',
var nextNode = that.g.successors(d), var nextNode = that.g.successors(d),
previousNode = that.g.predecessors(d), previousNode = that.g.predecessors(d),
nodesToHighlight = nextNode.concat(previousNode); nodesToHighlight = nextNode.concat(previousNode);
fade(0.3, d, nodesToHighlight); LineageUtils.onHoverFade({
opacity: 0.3,
selectedNode: d,
highlight: nodesToHighlight,
svg: that.svg
}).init();
}) })
.on('mouseleave', function(d) { .on('mouseleave', function(d) {
that.activeNode = false; that.activeNode = false;
...@@ -735,12 +679,16 @@ define(['require', ...@@ -735,12 +679,16 @@ define(['require',
tooltip.hide(d); tooltip.hide(d);
} }
} }
}, 400); }, 150);
if (!that.ui.showOnlyHoverPath.prop('checked')) { if (!that.ui.showOnlyHoverPath.prop('checked')) {
return; return;
} }
that.$('svg').removeClass('hover'); that.$('svg').removeClass('hover');
fade(1, d); LineageUtils.onHoverFade({
opacity: 1,
selectedNode: d,
svg: that.svg
}).init();
}) })
.on('click', function(d) { .on('click', function(d) {
if (d3.event.defaultPrevented) return; // ignore drag if (d3.event.defaultPrevented) return; // ignore drag
...@@ -797,7 +745,17 @@ define(['require', ...@@ -797,7 +745,17 @@ define(['require',
}); });
// Center the graph // Center the graph
this.centerNode(that.guid); LineageUtils.centerNode({
guid: that.guid,
svg: that.$('svg'),
g: this.g,
afterCenterZoomed: function(options) {
var newScale = options.newScale,
newTranslate = options.newTranslate;
that.zoom.scale(newScale);
that.zoom.translate(newTranslate);
}
}).init();
zoom.event(svg); zoom.event(svg);
//svg.attr('height', this.g.graph().height * initialScale + 40); //svg.attr('height', this.g.graph().height * initialScale + 40);
if (platform.name === "IE") { if (platform.name === "IE") {
...@@ -817,6 +775,11 @@ define(['require', ...@@ -817,6 +775,11 @@ define(['require',
}, 1000); }, 1000);
}); });
} }
LineageUtils.DragNode({
svg: this.svg,
g: this.g,
guid: this.guid
}).init();
}, },
renderLineageTypeSearch: function() { renderLineageTypeSearch: function() {
var that = this; var that = this;
...@@ -842,9 +805,18 @@ define(['require', ...@@ -842,9 +805,18 @@ define(['require',
e.stopImmediatePropagation(); e.stopImmediatePropagation();
d3.selectAll(".serach-rect").remove(); d3.selectAll(".serach-rect").remove();
var selectedNode = $('[data-id="typeSearch"]').val(); var selectedNode = $('[data-id="typeSearch"]').val();
that.searchNodeObj.selectedNode = $('[data-id="typeSearch"]').val(); that.searchNodeObj.selectedNode = selectedNode;
that.centerNode(selectedNode); LineageUtils.centerNode({
guid: selectedNode,
svg: $(that.svg[0]),
g: that.g,
afterCenterZoomed: function(options) {
var newScale = options.newScale,
newTranslate = options.newTranslate;
that.zoom.scale(newScale);
that.zoom.translate(newTranslate);
}
}).init();
that.svg.selectAll('.nodes g.label').attr('stroke', function(c, d) { that.svg.selectAll('.nodes g.label').attr('stroke', function(c, d) {
if (c == selectedNode) { if (c == selectedNode) {
return "#316132"; return "#316132";
......
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
define(['require', ''], function(require) {
'use strict';
var LinegaeUtils = {};
LinegaeUtils.DragNode = function(options) {
var that = this,
g = options.g,
svg = options.svg,
guid = options.guid;
return {
init: function() {
var that = this;
//give IDs to each of the nodes so that they can be accessed
svg.selectAll("g.node rect")
.attr("id", function(d) {
return "node" + d;
});
svg.selectAll("g.edgePath path")
.attr("id", function(e) {
return e.v + "-" + e.w;
});
svg.selectAll("g.edgeLabel g")
.attr("id", function(e) {
return 'label_' + e.v + "-" + e.w;
});
g.nodes().forEach(function(v) {
var node = g.node(v);
node.customId = "node" + v;
})
g.edges().forEach(function(e) {
var edge = g.edge(e.v, e.w);
edge.customId = e.v + "-" + e.w
});
var nodeDrag = d3.behavior.drag()
.on("dragstart", this.dragstart)
.on("drag", function(d) { that.dragmove(this, d) });
var edgeDrag = d3.behavior.drag()
.on("dragstart", this.dragstart)
.on('drag', function(d) {
that.translateEdge(g.edge(d.v, d.w), d3.event.dx, d3.event.dy);
$('#' + g.edge(d.v, d.w).customId).attr('d', that.calcPoints(d));
});
nodeDrag.call(svg.selectAll("g.node"));
edgeDrag.call(svg.selectAll("g.edgePath"));
},
dragstart: function(d) {
d3.event.sourceEvent.stopPropagation();
},
dragmove: function(elem, d) {
var that = this,
node = d3.select(elem),
selectedNode = g.node(d),
prevX = selectedNode.x,
prevY = selectedNode.y;
selectedNode.x += d3.event.dx;
selectedNode.y += d3.event.dy;
node.attr('transform', 'translate(' + selectedNode.x + ',' + selectedNode.y + ')');
var dx = selectedNode.x - prevX,
dy = selectedNode.y - prevY;
g.edges().forEach(function(e) {
if (e.v == d || e.w == d) {
var edge = g.edge(e.v, e.w);
that.translateEdge(g.edge(e.v, e.w), dx, dy);
$('#' + edge.customId).attr('d', that.calcPoints(e));
var label = $('#label_' + edge.customId);
var xforms = label.attr('transform');
if (xforms != "") {
var parts = /translate\(\s*([^\s,)]+)[ ,]?([^\s,)]+)?/.exec(xforms),
X = parseInt(parts[1]) + dx,
Y = parseInt(parts[2]) + dy;
// console.log(X, Y);
if (isNaN(Y)) {
Y = dy;
}
label.attr('transform', 'translate(' + X + ',' + Y + ')');
}
}
})
},
translateEdge: function(e, dx, dy) {
e.points.forEach(function(p) {
p.x = p.x + dx;
p.y = p.y + dy;
});
},
calcPoints: function(e) {
var edge = g.edge(e.v, e.w),
tail = g.node(e.v),
head = g.node(e.w),
points = edge.points.slice(1, edge.points.length - 1),
afterslice = edge.points.slice(1, edge.points.length - 1);
points.unshift(this.intersectRect(tail, points[0]));
points.push(this.intersectRect(head, points[points.length - 1]));
return d3.svg.line()
.x(function(d) {
return d.x;
})
.y(function(d) {
return d.y;
})
.interpolate("basis")
(points);
},
intersectRect: function(node, point) {
var that = this,
x = node.x,
y = node.y,
dx = point.x - x,
dy = point.y - y,
w = node.id == guid ? 24 : 21,
h = node.id == guid ? 24 : 21,
sx = 0,
sy = 0;
if (Math.abs(dy) * w > Math.abs(dx) * h) {
// Intersection is top or bottom of rect.
if (dy < 0) {
h = -h;
}
sx = dy === 0 ? 0 : h * dx / dy;
sy = h;
} else {
// Intersection is left or right of rect.
if (dx < 0) {
w = -w;
}
sx = w;
sy = dx === 0 ? 0 : w * dy / dx;
}
return {
x: x + sx,
y: y + sy
};
}
}
}
LinegaeUtils.centerNode = function(options) {
var nodeID = options.guid,
svg = options.svg,
g = options.g,
afterCenterZoomed = options.afterCenterZoomed,
zoom = d3.behavior.zoom(),
svgGroup = svg.find("g"),
zoomBind = function() {
svgGroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
},
selectedNode = $(svg).find("g.nodes").find('>g#' + nodeID);
return {
init: function() {
if (selectedNode.length > 0) {
selectedNode = selectedNode;
var matrix = selectedNode.attr('transform').replace(/[^0-9\-.,]/g, '').split(','),
x = matrix[0],
y = matrix[1];
} else {
selectedNode = $(svg).find("g.nodes").find('g').eq(1);
var x = g.graph().width / 2,
y = g.graph().height / 2;
}
var viewerWidth = $(svg).width(),
viewerHeight = $(svg).height(),
gBBox = d3.select('g').node().getBBox(),
zoomListener = zoom.scaleExtent([0.01, 50]).on("zoom", zoomBind),
scale = 1.2,
xa = -((x * scale) - (viewerWidth / 2)),
ya = -((y * scale) - (viewerHeight / 2));
zoom.translate([xa, ya]);
d3.select('g').transition()
.duration(350)
.attr("transform", "translate(" + xa + "," + ya + ")scale(" + scale + ")");
zoomListener.scale(scale);
zoomListener.translate([xa, ya]);
zoom.scale(scale);
afterCenterZoomed({ newScale: scale, newTranslate: [xa, ya] });
}
}
}
LinegaeUtils.onHoverFade = function(options) {
var opacity = options.opacity,
d = options.selectedNode,
nodesToHighlight = options.highlight,
svg = options.svg,
isConnected = function(a, b, o) {
if (a === o || (b && b.length && b.indexOf(o) != -1)) {
return true;
}
},
node = svg.selectAll('.node'),
path = svg.selectAll('.edgePath');
return {
init: function() {
node.classed("hover-active", function(selectedNode, i, nodes) {
if (isConnected(d, nodesToHighlight, selectedNode)) {
return true;
} else {
return false;
}
});
path.classed('hover-active-node', function(c) {
var _thisOpacity = c.v === d || c.w === d ? 1 : 0;
if (_thisOpacity) {
return true;
} else {
return false;
}
});
}
}
}
return LinegaeUtils;
});
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment