NIFI-347:

- Fixing threshold for self loops.
- Drawing preview of self loops while dragging the new connection.
- Addressing all cases when we want to prevent new connection attempts.
This commit is contained in:
Matt Gilman 2015-02-12 14:17:36 -05:00
parent a7eb1b7644
commit 851fe298b8
2 changed files with 47 additions and 36 deletions

View File

@ -409,10 +409,10 @@ nf.Canvas = (function () {
// update the selection box // update the selection box
selectionBox.attr(d); selectionBox.attr(d);
}
// prevent further propagation (to parents) // prevent further propagation (to parents)
d3.event.stopPropagation(); d3.event.stopPropagation();
}
} }
}) })
.on('mouseup.selection', function () { .on('mouseup.selection', function () {

View File

@ -20,6 +20,21 @@ nf.Connectable = (function () {
var canvas; var canvas;
var origin; var origin;
/**
* Determines if we want to allow adding connections in the current state:
*
* 1) When shift is down, we could be adding components to the current selection.
* 2) When the selection box is visible, we are in the process of moving all the
* components currently selected.
* 3) When the drag selection box is visible, we are in the process or selecting components
* using the selection box.
*
* @returns {boolean}
*/
var allowConnection = function () {
return !d3.event.shiftKey && d3.select('rect.drag-selection').empty() && d3.select('rect.selection').empty();
};
return { return {
init: function () { init: function () {
canvas = d3.select('#canvas'); canvas = d3.select('#canvas');
@ -103,16 +118,26 @@ nf.Connectable = (function () {
if (!destination.empty() && destination.classed('connectable-destination')) { if (!destination.empty() && destination.classed('connectable-destination')) {
var destinationData = destination.datum(); var destinationData = destination.datum();
// get the position on the destination perimeter // show the line preview as appropriate
var end = nf.CanvasUtils.getPerimeterPoint(pathDatum, { if (pathDatum.sourceId === destinationData.component.id) {
'x': destinationData.component.position.x, var x = pathDatum.x;
'y': destinationData.component.position.y, var y = pathDatum.y;
'width': destinationData.dimensions.width, var componentOffset = pathDatum.sourceWidth / 2;
'height': destinationData.dimensions.height var xOffset = nf.Connection.config.selfLoopXOffset;
}); var yOffset = nf.Connection.config.selfLoopYOffset;
return 'M' + x + ' ' + y + 'L' + (x + componentOffset + xOffset) + ' ' + (y - yOffset) + 'L' + (x + componentOffset + xOffset) + ' ' + (y + yOffset) + 'Z';
} else {
// get the position on the destination perimeter
var end = nf.CanvasUtils.getPerimeterPoint(pathDatum, {
'x': destinationData.component.position.x,
'y': destinationData.component.position.y,
'width': destinationData.dimensions.width,
'height': destinationData.dimensions.height
});
// direct line between components to provide a 'snap feel' // direct line between components to provide a 'snap feel'
return 'M' + pathDatum.x + ' ' + pathDatum.y + 'L' + end.x + ' ' + end.y; return 'M' + pathDatum.x + ' ' + pathDatum.y + 'L' + end.x + ' ' + end.y;
}
} else { } else {
return 'M' + pathDatum.x + ' ' + pathDatum.y + 'L' + d3.event.x + ' ' + d3.event.y; return 'M' + pathDatum.x + ' ' + pathDatum.y + 'L' + d3.event.x + ' ' + d3.event.y;
} }
@ -157,24 +182,11 @@ nf.Connectable = (function () {
// remove the connector // remove the connector
connector.remove(); connector.remove();
} else { } else {
var destinationData = destination.datum();
// if this is a self loop we need to insert some bend points
if (connectorData.sourceId === destinationData.component.id) {
connector.attr('d', function (pathDatum) {
var x = pathDatum.x;
var y = pathDatum.y;
var componentOffset = pathDatum.sourceWidth / 2;
var xOffset = nf.Connection.config.selfLoopXOffset;
var yOffset = nf.Connection.config.selfLoopYOffset;
return 'M' + x + ' ' + y + 'L' + (x + componentOffset + xOffset) + ' ' + (y - yOffset) + 'L' + (x + componentOffset + xOffset) + ' ' + (y + yOffset) + 'Z';
});
}
// remove the add connect img // remove the add connect img
addConnect.remove(); addConnect.remove();
// create the connection // create the connection
var destinationData = destination.datum();
nf.ConnectionConfiguration.createConnection(connectorData.sourceId, destinationData.component.id); nf.ConnectionConfiguration.createConnection(connectorData.sourceId, destinationData.component.id);
} }
}); });
@ -183,14 +195,14 @@ nf.Connectable = (function () {
activate: function (components) { activate: function (components) {
components components
.on('mouseenter.connectable', function (d) { .on('mouseenter.connectable', function (d) {
if (!d3.event.shiftKey && d3.select('rect.drag-selection').empty()) { if (allowConnection()) {
var selection = d3.select(this); var selection = d3.select(this);
// ensure the current component supports connection source // ensure the current component supports connection source
if (nf.CanvasUtils.isValidConnectionSource(selection)) { if (nf.CanvasUtils.isValidConnectionSource(selection)) {
// see if theres already a connector rendered // see if theres already a connector rendered
var anyConnector = d3.select('image.add-connect'); var addConnect = d3.select('image.add-connect');
if (anyConnector.empty()) { if (addConnect.empty()) {
var x = (d.dimensions.width / 2) - 14; var x = (d.dimensions.width / 2) - 14;
var y = (d.dimensions.height / 2) - 14; var y = (d.dimensions.height / 2) - 14;
@ -214,17 +226,16 @@ nf.Connectable = (function () {
}) })
.on('mouseleave.connectable', function () { .on('mouseleave.connectable', function () {
// conditionally remove the connector // conditionally remove the connector
var connector = d3.select(this).select('image.add-connect'); var addConnect = d3.select(this).select('image.add-connect');
if (!connector.empty() && !connector.classed('dragging')) { if (!addConnect.empty() && !addConnect.classed('dragging')) {
connector.remove(); addConnect.remove();
} }
}) })
// Using mouseover/out to workaround chrome issue #122746 // Using mouseover/out to workaround chrome issue #122746
.on('mouseover.connectable', function () { .on('mouseover.connectable', function () {
// mark that we are hovering when appropriate // mark that we are hovering when appropriate
var selection = d3.select(this); d3.select(this).classed('hover', function () {
selection.classed('hover', function () { return allowConnection();
return !d3.event.shiftKey && !selection.classed('hover') && d3.select('rect.drag-selection').empty();
}); });
}) })
.on('mouseout.connection', function () { .on('mouseout.connection', function () {