From c2bb9d2a1d91e4569734a38f7c41bba48f975b63 Mon Sep 17 00:00:00 2001 From: Jaden Diefenbaugh <jaden.diefenbaugh@idiap.ch> Date: Mon, 22 Oct 2018 12:47:58 -0700 Subject: [PATCH] let user click on output/input to create conn, closes #79 --- .../components/toolchain/GraphicalEditor.jsx | 89 +++++++++++++------ 1 file changed, 62 insertions(+), 27 deletions(-) diff --git a/conda/js/src/components/toolchain/GraphicalEditor.jsx b/conda/js/src/components/toolchain/GraphicalEditor.jsx index dcbfedff..58b3cf81 100644 --- a/conda/js/src/components/toolchain/GraphicalEditor.jsx +++ b/conda/js/src/components/toolchain/GraphicalEditor.jsx @@ -510,7 +510,9 @@ export default class GraphicalEditor extends React.PureComponent<Props, State> { }, 50); }; - // d3 behaviour for dragging lines from an output to an input and creating a connection + // d3 behaviour for connecting an output and input and creating a connection + // allows users to drag from output to input, + // or click an output and click an input initD3Connections = () => { // creating connections setTimeout(() => { @@ -519,8 +521,17 @@ export default class GraphicalEditor extends React.PureComponent<Props, State> { const channelColors = this.props.repData.channel_colors; const {datasets, blocks} = this.props; let startBlock; - // the user has started dragging from an output block + let startX = 0; + let startY = 0; + // the user has started dragging from an output block, + // or it might be starting a click event! + // to see if the user is clicking or dragging, + // check in endDrag() if the distance travelled is small + // enough to be considered a click or not function startDrag(d) { + console.log('startDrag'); + startX = d3.event.x; + startY = d3.event.y; // find the block that the user started from const rawId = d3.select(this).attr('id'); const bName = rawId.split('-output-')[0]; @@ -533,37 +544,57 @@ export default class GraphicalEditor extends React.PureComponent<Props, State> { .append('line') .classed('tmp', true) .attr('stroke', 'black') - .attr('x1', d3.event.x) - .attr('y1', d3.event.y) - .attr('x2', d3.event.x) - .attr('y2', d3.event.y); + .attr('x1', startX) + .attr('y1', startY) + .attr('x2', startX) + .attr('y2', startY); } - // create a connection if the user ended the drag on an input block, - // else just remove the temp svg line - function endDrag() { - const {x, y} = d3.event; - d3.select('.tmp') - .remove(); + const processEndBlock = (endInput: HTMLElement) => { if(!startBlock) return; - // with the location of the end event, - // compare the location to the location & dims of all input blocks - // in the svg. - const endInput = Array.from(document.querySelectorAll('.iBlock')) - .find(n => { - const nx = n.x.baseVal.value; - const ny = n.y.baseVal.value; - const width = n.width.baseVal.value; - const height = n.height.baseVal.value; - return nx <= x && x <= nx + width && ny <= y && y <= ny + height; - }); - if(endInput === undefined) - return; + console.log(endInput); const endId = endInput.id.replace('-input-', '.'); - // create a new connection + // create a new connection assuming theres a given func that does it if(createConnection) createConnection(startId, endId, startBlock.synchronized_channel || startBlock.name); + + startBlock = undefined; + }; + + // create a connection if the user ended the drag on an input block, + // else just remove the temp svg line + function endDrag(d) { + //console.log('endDrag'); + const {x, y} = d3.event; + if(Math.abs(startX - x) < 10 && Math.abs(startY - y) < 10) { + // click event not drag + } else { + // probably not a click event + d3.select('.tmp').remove(); + // with the location of the end event, + // compare the location to the location & dims of all input blocks + // in the svg. + const endInput = Array.from(document.querySelectorAll('.iBlock')) + .find(n => { + const nx = n.x.baseVal.value; + const ny = n.y.baseVal.value; + const width = n.width.baseVal.value; + const height = n.height.baseVal.value; + return nx <= x && x <= nx + width && ny <= y && y <= ny + height; + }); + if(endInput === undefined){ + startBlock = undefined; + } else { + processEndBlock(endInput); + } + } + } + + // create a connection if the user clicked an input block, + // else just reset the startBlock + function endClick() { + processEndBlock(this); } // update the temp line @@ -573,12 +604,16 @@ export default class GraphicalEditor extends React.PureComponent<Props, State> { .attr('y2', d3.event.y); } - d3.selectAll('.oBlock').call( + d3.selectAll('.oBlock') + .call( d3.drag() .on('start', startDrag) .on('end', endDrag) .on('drag', dragged) ); + + d3.selectAll('.iBlock') + .on('click', endClick); }, 50); } -- GitLab