From b5062ab6d4aaed4e127efc70352757ccf4d85db3 Mon Sep 17 00:00:00 2001 From: Jess Date: Tue, 7 Jun 2016 15:38:48 -0400 Subject: [PATCH 1/6] Made things very broken, commiting before going back to point A --- app/components/Graph.jsx | 56 ++++++++++++++++++++++++++++++-- app/components/Node.jsx | 70 ++++++++++++++++++++++++++-------------- 2 files changed, 98 insertions(+), 28 deletions(-) diff --git a/app/components/Graph.jsx b/app/components/Graph.jsx index b61a4f3..91a1d0b 100644 --- a/app/components/Graph.jsx +++ b/app/components/Graph.jsx @@ -10,21 +10,23 @@ import values from 'lodash/object/values'; import min from 'lodash/collection/min'; import max from 'lodash/collection/max'; import includes from 'lodash/collection/includes'; +import filter from 'lodash/collection/filter'; + export default class Graph extends BaseComponent { constructor(props) { super(props); - this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop'); + this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop', '_handleNodeDragStart', '_handleNodeDrag', '_handleNodeDragStop'); this.nodes = {}; this.edges = {}; this.mounted = false; let viewBox = this._computeViewbox(props.graph, props.zoom, props.viewOnlyHighlighted); this.state = { x: 0, y: 0, viewBox, height: props.height }; + } render() { let { x, y, prevGraph, viewBox, height } = this.state; - return ( ); + isLocked={this.props.isLocked} + onGroupStart={this._handleNodeDragStart} + onGroupDrag={this._handleNodeDrag} + onGroupStop={this._handleNodeDragStop} />); } _renderCaptions() { @@ -214,6 +219,51 @@ export default class Graph extends BaseComponent { return { x, y }; } + //NODE DRAGGING + + // keep initial position for comparison with drag position + _handleNodeDragStart(e, ui, that) { + console.log(e); + that._startDrag = ui.position; + that._startPosition = { + x: that.state.x, + y: that.state.y + }; + } + + // while dragging node and its edges are updated only in state, not store + _handleNodeDrag(e, ui, that) { + if (this.props.isLocked) return; + + that._dragging = true; // so that _handleClick knows it's not just a click + + let n = that.props.node; + let deltaX = (ui.position.clientX - that._startDrag.clientX) / that.graph.state.actualZoom; + let deltaY = (ui.position.clientY - that._startDrag.clientY) / that.graph.state.actualZoom; + let x = that._startPosition.x + deltaX; + let y = that._startPosition.y + deltaY; + + that.setState({ x, y }); + + + // update state of connecting edges + let edges = GraphModel.edgesConnectedToNode(that.props.graph, n.id); + + edges.forEach(edge => { + let thisNodeNum = edge.node1_id == n.id ? 1 : 2; + let newEdge = GraphModel.moveEdgeNode(edge, thisNodeNum, x, y); + that.graph.edges[edge.id].setState(newEdge.display); + }); + } + + // store updated once dragging is done + _handleNodeDragStop(e, ui, that) { + // event fires every mouseup so we check for actual drag before updating store + if (that._dragging) { + that.props.moveNode(that.props.node.id, that.state.x, that.state.y); + } + } + // TRANSITION ANIMATION _animateTransition(oldViewBox, viewBox, duration) { diff --git a/app/components/Node.jsx b/app/components/Node.jsx index e56d0ec..89da40c 100644 --- a/app/components/Node.jsx +++ b/app/components/Node.jsx @@ -21,14 +21,17 @@ export default class Node extends BaseComponent { const { x, y, name } = this.state; const groupId = `node-${n.id}`; const transform = `translate(${x}, ${y})`; - return ( + onStop={this._handleDragStop} + > { - let thisNodeNum = edge.node1_id == n.id ? 1 : 2; - let newEdge = Graph.moveEdgeNode(edge, thisNodeNum, x, y); - this.graph.edges[edge.id].setState(newEdge.display); - }); + edges.forEach(edge => { + let thisNodeNum = edge.node1_id == n.id ? 1 : 2; + let newEdge = Graph.moveEdgeNode(edge, thisNodeNum, x, y); + this.graph.edges[edge.id].setState(newEdge.display); + }); + } else { + this.props.onGroupDrag(e, ui, this); + console.log(this); + + } } // store updated once dragging is done _handleDragStop(e, ui) { - // event fires every mouseup so we check for actual drag before updating store - if (this._dragging) { - this.props.moveNode(this.props.node.id, this.state.x, this.state.y); + if (!this.graph.props.showEditTools){ + // event fires every mouseup so we check for actual drag before updating store + if (this._dragging) { + this.props.moveNode(this.props.node.id, this.state.x, this.state.y); + } + } else { + this.props.onGroupStart(e, ui, this); + console.log(this); + } } From c6c9b5232447d6dd6b59f525593813f3ad764113 Mon Sep 17 00:00:00 2001 From: Jess Date: Tue, 7 Jun 2016 16:37:42 -0400 Subject: [PATCH 2/6] committing before revisiting previous approach --- app/components/Graph.jsx | 51 +----------------------- app/components/Node.jsx | 83 +++++++++++++++++++--------------------- 2 files changed, 42 insertions(+), 92 deletions(-) diff --git a/app/components/Graph.jsx b/app/components/Graph.jsx index 91a1d0b..a140d7f 100644 --- a/app/components/Graph.jsx +++ b/app/components/Graph.jsx @@ -16,7 +16,7 @@ import filter from 'lodash/collection/filter'; export default class Graph extends BaseComponent { constructor(props) { super(props); - this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop', '_handleNodeDragStart', '_handleNodeDrag', '_handleNodeDragStop'); + this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop'); this.nodes = {}; this.edges = {}; this.mounted = false; @@ -85,10 +85,7 @@ export default class Graph extends BaseComponent { selected={this.props.selection && includes(this.props.selection.nodeIds, n.id)} clickNode={this.props.clickNode} moveNode={this.props.moveNode} - isLocked={this.props.isLocked} - onGroupStart={this._handleNodeDragStart} - onGroupDrag={this._handleNodeDrag} - onGroupStop={this._handleNodeDragStop} />); + isLocked={this.props.isLocked} />); } _renderCaptions() { @@ -219,50 +216,6 @@ export default class Graph extends BaseComponent { return { x, y }; } - //NODE DRAGGING - - // keep initial position for comparison with drag position - _handleNodeDragStart(e, ui, that) { - console.log(e); - that._startDrag = ui.position; - that._startPosition = { - x: that.state.x, - y: that.state.y - }; - } - - // while dragging node and its edges are updated only in state, not store - _handleNodeDrag(e, ui, that) { - if (this.props.isLocked) return; - - that._dragging = true; // so that _handleClick knows it's not just a click - - let n = that.props.node; - let deltaX = (ui.position.clientX - that._startDrag.clientX) / that.graph.state.actualZoom; - let deltaY = (ui.position.clientY - that._startDrag.clientY) / that.graph.state.actualZoom; - let x = that._startPosition.x + deltaX; - let y = that._startPosition.y + deltaY; - - that.setState({ x, y }); - - - // update state of connecting edges - let edges = GraphModel.edgesConnectedToNode(that.props.graph, n.id); - - edges.forEach(edge => { - let thisNodeNum = edge.node1_id == n.id ? 1 : 2; - let newEdge = GraphModel.moveEdgeNode(edge, thisNodeNum, x, y); - that.graph.edges[edge.id].setState(newEdge.display); - }); - } - - // store updated once dragging is done - _handleNodeDragStop(e, ui, that) { - // event fires every mouseup so we check for actual drag before updating store - if (that._dragging) { - that.props.moveNode(that.props.node.id, that.state.x, that.state.y); - } - } // TRANSITION ANIMATION diff --git a/app/components/Node.jsx b/app/components/Node.jsx index 89da40c..dfca78e 100644 --- a/app/components/Node.jsx +++ b/app/components/Node.jsx @@ -12,7 +12,7 @@ import Helpers from '../models/Helpers'; export default class Node extends BaseComponent { constructor(props) { super(props); - this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop', '_handleClick'); + this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop', '_handleClick', '_doDragStart'); this.state = props.node.display; } @@ -21,17 +21,14 @@ export default class Node extends BaseComponent { const { x, y, name } = this.state; const groupId = `node-${n.id}`; const transform = `translate(${x}, ${y})`; + return ( + onStop={this._handleDragStop}> { - let thisNodeNum = edge.node1_id == n.id ? 1 : 2; - let newEdge = Graph.moveEdgeNode(edge, thisNodeNum, x, y); - this.graph.edges[edge.id].setState(newEdge.display); - }); - } else { - this.props.onGroupDrag(e, ui, this); - console.log(this); - - } + this.setState({ x, y }); + + // update state of connecting edges + let edges = Graph.edgesConnectedToNode(this.props.graph, n.id); + + edges.forEach(edge => { + let thisNodeNum = edge.node1_id == n.id ? 1 : 2; + let newEdge = Graph.moveEdgeNode(edge, thisNodeNum, x, y); + this.graph.edges[edge.id].setState(newEdge.display); + }); } // store updated once dragging is done _handleDragStop(e, ui) { - if (!this.graph.props.showEditTools){ - // event fires every mouseup so we check for actual drag before updating store - if (this._dragging) { - this.props.moveNode(this.props.node.id, this.state.x, this.state.y); - } - } else { - this.props.onGroupStart(e, ui, this); - console.log(this); - + // event fires every mouseup so we check for actual drag before updating store + if (this._dragging) { + this.props.moveNode(this.props.node.id, this.state.x, this.state.y); } } From 703527c302e23dc4482cbd2567c3dc2e3691aaef Mon Sep 17 00:00:00 2001 From: Jess Date: Tue, 7 Jun 2016 19:27:37 -0400 Subject: [PATCH 3/6] dragging multiple nodes seems to be working --- app/components/Edge.jsx | 1 + app/components/Graph.jsx | 43 ++++++++++++++++++- app/components/Node.jsx | 90 +++++++++++++++++++++++----------------- 3 files changed, 95 insertions(+), 39 deletions(-) diff --git a/app/components/Edge.jsx b/app/components/Edge.jsx index d472fe7..85fe03d 100644 --- a/app/components/Edge.jsx +++ b/app/components/Edge.jsx @@ -105,6 +105,7 @@ export default class Edge extends BaseComponent { let cy = this._startPosition.y + deltaY; this.setState({ cx, cy }); + } _handleDragStop(e, ui) { diff --git a/app/components/Graph.jsx b/app/components/Graph.jsx index a140d7f..dcc47d7 100644 --- a/app/components/Graph.jsx +++ b/app/components/Graph.jsx @@ -16,7 +16,7 @@ import filter from 'lodash/collection/filter'; export default class Graph extends BaseComponent { constructor(props) { super(props); - this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop'); + this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop', '_handleDragGroupStart', '_handleDragGroup', '_handleDragGroupStop'); this.nodes = {}; this.edges = {}; this.mounted = false; @@ -85,7 +85,10 @@ export default class Graph extends BaseComponent { selected={this.props.selection && includes(this.props.selection.nodeIds, n.id)} clickNode={this.props.clickNode} moveNode={this.props.moveNode} - isLocked={this.props.isLocked} />); + isLocked={this.props.isLocked} + onStart={this._handleDragGroupStart} + onDrag={this._handleDragGroup} + onStop={this._handleDragGroupStop} />); } _renderCaptions() { @@ -216,6 +219,42 @@ export default class Graph extends BaseComponent { return { x, y }; } + //GROUP DRAGGING + // keep initial position for comparison with drag position + _handleDragGroupStart(e, ui, that) { + var theSelection = this.props.selection; + var nodes = theSelection["nodeIds"]; + var selectedNodes = _.filter(this.nodes, function(d){ + return _.indexOf(nodes, d.props.node["id"]) != -1; + }) + _.forEach(selectedNodes, function(d){ + d._doDragStart(e, ui); + }) + } + + _handleDragGroup(e, ui, that) { + var theSelection = this.props.selection; + var nodes = theSelection["nodeIds"]; + var selectedNodes = _.filter(this.nodes, function(d){ + return _.indexOf(nodes, d.props.node["id"]) != -1; + }) + _.forEach(selectedNodes, function(d){ + d._doDrag(e, ui, true); + }) + } + + _handleDragGroupStop(e, ui, that) { + var theSelection = this.props.selection; + var nodes = theSelection["nodeIds"]; + var selectedNodes = _.filter(this.nodes, function(d){ + return _.indexOf(nodes, d.props.node["id"]) != -1; + }) + _.forEach(selectedNodes, function(d){ + d._doDragStop(e, ui); + }) + } + + // TRANSITION ANIMATION diff --git a/app/components/Node.jsx b/app/components/Node.jsx index dfca78e..d712889 100644 --- a/app/components/Node.jsx +++ b/app/components/Node.jsx @@ -12,7 +12,7 @@ import Helpers from '../models/Helpers'; export default class Node extends BaseComponent { constructor(props) { super(props); - this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop', '_handleClick', '_doDragStart'); + this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop', '_doDragStart', '_doDrag', '_doDragStop', '_handleClick'); this.state = props.node.display; } @@ -47,68 +47,84 @@ export default class Node extends BaseComponent { } shouldComponentUpdate(nextProps, nextState) { + // return true; return nextProps.selected !== this.props.selected || JSON.stringify(nextState) !== JSON.stringify(this.state); } // keep initial position for comparison with drag position _handleDragStart(e, ui) { - var theSelection = this.graph.props.selection.nodeIds; - if (!this.graph.props.showEditTools){ - this._doDragStart(e, ui); + if (!this.graph.props.showEditTools || !this.props.selected) { + this._doDragStart(e, ui); } else { - var selectedNodes = _.filter(this.graph.nodes, function(node){ - return _.indexOf(theSelection, node.props.node.id) != -1; - }) - _.forEach(selectedNodes, function(node){ - node._doDragStart(e, ui); - }) + this.props.onStart(e, ui, this); } } _doDragStart(e, ui) { - this._startDrag = ui.position; - this._startPosition = { - x: this.state.x, - y: this.state.y - }; + this._startDrag = ui.position; + this._startPosition = { + x: this.state.x, + y: this.state.y + }; } // while dragging node and its edges are updated only in state, not store _handleDrag(e, ui) { - console.log(this.props.node) if (this.props.isLocked) return; + if (!this.graph.props.showEditTools || !this.props.selected) { + this._doDrag(e, ui, false); + } else { + this.props.onDrag(e, ui, this); + } + } - this._dragging = true; // so that _handleClick knows it's not just a click - - let n = this.props.node; - - let deltaX = (ui.position.clientX - this._startDrag.clientX) / this.graph.state.actualZoom; - let deltaY = (ui.position.clientY - this._startDrag.clientY) / this.graph.state.actualZoom; - let x = this._startPosition.x + deltaX; - let y = this._startPosition.y + deltaY; - - this.setState({ x, y }); - - // update state of connecting edges - let edges = Graph.edgesConnectedToNode(this.props.graph, n.id); - - edges.forEach(edge => { - let thisNodeNum = edge.node1_id == n.id ? 1 : 2; - let newEdge = Graph.moveEdgeNode(edge, thisNodeNum, x, y); - this.graph.edges[edge.id].setState(newEdge.display); - }); + _doDrag(e, ui, isMultiple) { + this._dragging = true; // so that _handleClick knows it's not just a click + + let n = this.props.node; + let deltaX = (ui.position.clientX - this._startDrag.clientX) / this.graph.state.actualZoom; + let deltaY = (ui.position.clientY - this._startDrag.clientY) / this.graph.state.actualZoom; + let x = this._startPosition.x + deltaX; + let y = this._startPosition.y + deltaY; + + this.setState({ x, y }); + + // update state of connecting edges + let edges = Graph.edgesConnectedToNode(this.props.graph, n.id); + + edges.forEach(edge => { + let thisNodeNum = edge.node1_id == n.id ? 1 : 2; + let newEdge = Graph.moveEdgeNode(edge, thisNodeNum, x, y); + this.graph.edges[edge.id].setState(newEdge.display); + }); + + //update throughout drag so nodes know their siblings' positions when + //multiple nodes are dragged simultaneously + if (isMultiple){ + if (this._dragging) { + this.props.moveNode(this.props.node.id, this.state.x, this.state.y); + } + } } // store updated once dragging is done _handleDragStop(e, ui) { // event fires every mouseup so we check for actual drag before updating store - if (this._dragging) { - this.props.moveNode(this.props.node.id, this.state.x, this.state.y); + if (!this.graph.props.showEditTools || !this.props.selected) { + this._doDragStop(e, ui); + } else { + this.props.onStop(e, ui, this); } } + _doDragStop(e, ui){ + if (this._dragging) { + this.props.moveNode(this.props.node.id, this.state.x, this.state.y); + } + } + _handleClick() { if (this._dragging) { this._dragging = false; From b5b5b656f8511174a17e4199a40eb5f14be74c11 Mon Sep 17 00:00:00 2001 From: Jess Date: Tue, 7 Jun 2016 22:03:18 -0400 Subject: [PATCH 4/6] can drag captions as well, working on making edges draggable in groups too --- app/components/Caption.jsx | 39 +++++++++++++++++++++++++++++++++++++- app/components/Edge.jsx | 35 ++++++++++++++++++++++++++++------ app/components/Graph.jsx | 36 +++++++++++++++++++++++++++++++++-- 3 files changed, 101 insertions(+), 9 deletions(-) diff --git a/app/components/Caption.jsx b/app/components/Caption.jsx index efd9025..ad88629 100644 --- a/app/components/Caption.jsx +++ b/app/components/Caption.jsx @@ -8,7 +8,7 @@ import merge from 'lodash/object/merge'; export default class Caption extends BaseComponent { constructor(props) { super(props); - this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop', '_handleClick'); + this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop', '_doDragStart', '_doDrag', '_doDragStop', '_handleClick'); this.state = props.caption.display; } @@ -78,7 +78,17 @@ export default class Caption extends BaseComponent { } } + + // keep initial position for comparison with drag position _handleDragStart(e, ui) { + if (!this.graph.props.showEditTools || !this.props.selected) { + this._doDragStart(e, ui); + } else { + this.props.onStart(e, ui, this); + } + } + + _doDragStart(e, ui) { this._startDrag = ui.position; this._startPosition = { x: this.state.x, @@ -86,9 +96,18 @@ export default class Caption extends BaseComponent { }; } + // while dragging node and its edges are updated only in state, not store _handleDrag(e, ui) { + if (this.props.isLocked) return; + if (!this.graph.props.showEditTools || !this.props.selected) { + this._doDrag(e, ui, false); + } else { + this.props.onDrag(e, ui, this); + } + } + _doDrag(e, ui, isMultiple) { this._dragging = true; let deltaX = (ui.position.clientX - this._startDrag.clientX) / this.graph.state.actualZoom; @@ -97,10 +116,28 @@ export default class Caption extends BaseComponent { let y = this._startPosition.y + deltaY; this.setState({ x, y }); + + //update throughout drag so nodes know their siblings' positions when + //multiple nodes are dragged simultaneously + if (isMultiple){ + if (this._dragging) { + this.props.moveCaption(this.props.caption.id, this.state.x, this.state.y); + } + } } + // store updated once dragging is done _handleDragStop(e, ui) { // event fires every mouseup so we check for actual drag before updating store + if (!this.graph.props.showEditTools || !this.props.selected) { + this._doDragStop(e, ui); + } else { + this.props.onStop(e, ui, this); + } + } + + _doDragStop(e, ui){ + // event fires every mouseup so we check for actual drag before updating store if (this._dragging) { this.props.moveCaption(this.props.caption.id, this.state.x, this.state.y); } diff --git a/app/components/Edge.jsx b/app/components/Edge.jsx index 85fe03d..4452eaa 100644 --- a/app/components/Edge.jsx +++ b/app/components/Edge.jsx @@ -9,7 +9,7 @@ import classNames from 'classnames'; export default class Edge extends BaseComponent { constructor(props) { super(props); - this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop', '_handleClick', '_handleTextClick'); + this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop', '_doDragStart', '_doDrag', '_doDragStop', '_handleClick', '_handleTextClick'); // need control point immediately for dragging let { cx, cy } = this._calculateGeometry(props.edge.display); this.state = merge({}, props.edge.display, { cx, cy }); @@ -85,7 +85,7 @@ export default class Edge extends BaseComponent { JSON.stringify(nextState) !== JSON.stringify(this.state); } - _handleDragStart(event, ui) { + _doDragStart(event, ui) { this._startDrag = ui.position; this._startPosition = { x: this.state.cx, @@ -93,7 +93,7 @@ export default class Edge extends BaseComponent { } } - _handleDrag(event, ui) { + _doDrag(event, ui) { if (this.props.isLocked) return; this._dragging = true; // so that _handleClick knows it's not just a click @@ -105,16 +105,39 @@ export default class Edge extends BaseComponent { let cy = this._startPosition.y + deltaY; this.setState({ cx, cy }); - } - _handleDragStop(e, ui) { - // event fires every mouseup so we check for actual drag before updating store + _doDragStop(event, ui) { if (this._dragging) { this.props.moveEdge(this.props.edge.id, this.state.cx, this.state.cy); } } + _handleDragStart(event, ui) { + if (!this.graph.props.showEditTools || !this.props.selected) { + this._doDragStart(e, ui); + } else { + console.log("hiii"); + } + } + + _handleDrag(event, ui) { + if (!this.graph.props.showEditTools || !this.props.selected) { + this._doDrag(e, ui); + } else { + console.log("hiii"); + } + } + + _handleDragStop(e, ui) { + // event fires every mouseup so we check for actual drag before updating store + if (!this.graph.props.showEditTools || !this.props.selected) { + this._doDragStop(e, ui); + } else { + console.log("hiii"); + } + } + _handleClick() { if (this._dragging) { this._dragging = false; diff --git a/app/components/Graph.jsx b/app/components/Graph.jsx index dcc47d7..671737e 100644 --- a/app/components/Graph.jsx +++ b/app/components/Graph.jsx @@ -19,6 +19,7 @@ export default class Graph extends BaseComponent { this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop', '_handleDragGroupStart', '_handleDragGroup', '_handleDragGroupStop'); this.nodes = {}; this.edges = {}; + this.captions = {}; this.mounted = false; let viewBox = this._computeViewbox(props.graph, props.zoom, props.viewOnlyHighlighted); this.state = { x: 0, y: 0, viewBox, height: props.height }; @@ -94,14 +95,17 @@ export default class Graph extends BaseComponent { _renderCaptions() { return values(this.props.graph.captions).map((c, i) => { if (c) { c.graph = this; } }} + ref={(a) => { this.captions[c.id] = a; if (a) { a.graph = this; }} } key={c.id} caption={c} graphId={this.props.graph.id} selected={this.props.selection && includes(this.props.selection.captionIds, c.id)} moveCaption={this.props.moveCaption} clickCaption={this.props.clickCaption} - isLocked={this.props.isLocked} />); + isLocked={this.props.isLocked} + onStart={this._handleDragGroupStart} + onDrag={this._handleDragGroup} + onStop={this._handleDragGroupStop} />); } _renderMarkers() { @@ -230,6 +234,14 @@ export default class Graph extends BaseComponent { _.forEach(selectedNodes, function(d){ d._doDragStart(e, ui); }) + + var captions = theSelection["captionIds"]; + var selectedCaptions = _.filter(this.captions, function(d){ + return _.indexOf(captions, d.props.caption["id"]) != -1; + }) + _.forEach(selectedCaptions, function(d){ + d._doDragStart(e, ui); + }) } _handleDragGroup(e, ui, that) { @@ -241,6 +253,16 @@ export default class Graph extends BaseComponent { _.forEach(selectedNodes, function(d){ d._doDrag(e, ui, true); }) + + var captions = theSelection["captionIds"]; + var selectedCaptions = _.filter(this.captions, function(d){ + return _.indexOf(captions, d.props.caption["id"]) != -1; + }) + _.forEach(selectedCaptions, function(d){ + d._doDrag(e, ui, true); + }) + + } _handleDragGroupStop(e, ui, that) { @@ -252,6 +274,16 @@ export default class Graph extends BaseComponent { _.forEach(selectedNodes, function(d){ d._doDragStop(e, ui); }) + + var captions = theSelection["captionIds"]; + var selectedCaptions = _.filter(this.captions, function(d){ + return _.indexOf(captions, d.props.caption["id"]) != -1; + }) + _.forEach(selectedCaptions, function(d){ + d._doDragStop(e, ui); + }) + + } From 7983fa3bb6d820b6f0b59b8d85e3a091710f5f5d Mon Sep 17 00:00:00 2001 From: Jess Date: Wed, 8 Jun 2016 13:10:25 -0400 Subject: [PATCH 5/6] multiselect possible with any combination of nodes, edges and captions --- app/components/Edge.jsx | 20 +++++++++++++------- app/components/Graph.jsx | 29 +++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/app/components/Edge.jsx b/app/components/Edge.jsx index 4452eaa..14d257f 100644 --- a/app/components/Edge.jsx +++ b/app/components/Edge.jsx @@ -93,7 +93,7 @@ export default class Edge extends BaseComponent { } } - _doDrag(event, ui) { + _doDrag(event, ui, isMultiple) { if (this.props.isLocked) return; this._dragging = true; // so that _handleClick knows it's not just a click @@ -105,6 +105,12 @@ export default class Edge extends BaseComponent { let cy = this._startPosition.y + deltaY; this.setState({ cx, cy }); + + if (isMultiple){ + if (this._dragging) { + this.props.moveEdge(this.props.edge.id, this.state.cx, this.state.cy); + } + } } _doDragStop(event, ui) { @@ -115,26 +121,26 @@ export default class Edge extends BaseComponent { _handleDragStart(event, ui) { if (!this.graph.props.showEditTools || !this.props.selected) { - this._doDragStart(e, ui); + this._doDragStart(event, ui, false); } else { - console.log("hiii"); + this.props.onStart(event, ui, this); } } _handleDrag(event, ui) { if (!this.graph.props.showEditTools || !this.props.selected) { - this._doDrag(e, ui); + this._doDrag(event, ui); } else { - console.log("hiii"); + this.props.onDrag(event, ui, this); } } _handleDragStop(e, ui) { // event fires every mouseup so we check for actual drag before updating store if (!this.graph.props.showEditTools || !this.props.selected) { - this._doDragStop(e, ui); + this._doDragStop(event, ui); } else { - console.log("hiii"); + this.props.onStop(event, ui, this); } } diff --git a/app/components/Graph.jsx b/app/components/Graph.jsx index 671737e..a90cb10 100644 --- a/app/components/Graph.jsx +++ b/app/components/Graph.jsx @@ -72,7 +72,10 @@ export default class Graph extends BaseComponent { selected={this.props.selection && includes(this.props.selection.edgeIds, e.id)} clickEdge={this.props.clickEdge} moveEdge={this.props.moveEdge} - isLocked={this.props.isLocked} />); + isLocked={this.props.isLocked} + onStart={this._handleDragGroupStart} + onDrag={this._handleDragGroup} + onStop={this._handleDragGroupStop} />); } _renderNodes() { @@ -242,6 +245,14 @@ export default class Graph extends BaseComponent { _.forEach(selectedCaptions, function(d){ d._doDragStart(e, ui); }) + + var edges = theSelection["edgeIds"]; + var selectedEdges = _.filter(this.edges, function(d){ + return _.indexOf(edges, d.props.edge["id"]) != -1; + }) + _.forEach(selectedEdges, function(d){ + d._doDragStart(e, ui); + }) } _handleDragGroup(e, ui, that) { @@ -261,8 +272,14 @@ export default class Graph extends BaseComponent { _.forEach(selectedCaptions, function(d){ d._doDrag(e, ui, true); }) - + var edges = theSelection["edgeIds"]; + var selectedEdges = _.filter(this.edges, function(d){ + return _.indexOf(edges, d.props.edge["id"]) != -1; + }) + _.forEach(selectedEdges, function(d){ + d._doDrag(e, ui, true); + }) } _handleDragGroupStop(e, ui, that) { @@ -283,6 +300,14 @@ export default class Graph extends BaseComponent { d._doDragStop(e, ui); }) + var edges = theSelection["edgeIds"]; + var selectedEdges = _.filter(this.edges, function(d){ + return _.indexOf(edges, d.props.edge["id"]) != -1; + }) + _.forEach(selectedEdges, function(d){ + d._doDragStop(e, ui); + }) + } From 58fa382bc698946b9b14bc30169e594d1fc8dd95 Mon Sep 17 00:00:00 2001 From: Jess Date: Wed, 8 Jun 2016 13:46:50 -0400 Subject: [PATCH 6/6] slightly less code --- app/components/Caption.jsx | 21 ++++---- app/components/Graph.jsx | 104 +++++++++++-------------------------- app/components/Node.jsx | 20 ++++--- 3 files changed, 53 insertions(+), 92 deletions(-) diff --git a/app/components/Caption.jsx b/app/components/Caption.jsx index ad88629..bec96ae 100644 --- a/app/components/Caption.jsx +++ b/app/components/Caption.jsx @@ -81,7 +81,8 @@ export default class Caption extends BaseComponent { // keep initial position for comparison with drag position _handleDragStart(e, ui) { - if (!this.graph.props.showEditTools || !this.props.selected) { + var isOnlyOne = (this.graph.props.selection["nodeIds"].length + this.graph.props.selection["captionIds"].length + this.graph.props.selection["edgeIds"].length) < 2; + if (!this.graph.props.showEditTools || !this.props.selected || isOnlyOne) { this._doDragStart(e, ui); } else { this.props.onStart(e, ui, this); @@ -100,7 +101,8 @@ export default class Caption extends BaseComponent { _handleDrag(e, ui) { if (this.props.isLocked) return; - if (!this.graph.props.showEditTools || !this.props.selected) { + var isOnlyOne = (this.graph.props.selection["nodeIds"].length + this.graph.props.selection["captionIds"].length + this.graph.props.selection["edgeIds"].length) < 2; + if (!this.graph.props.showEditTools || !this.props.selected || isOnlyOne) { this._doDrag(e, ui, false); } else { this.props.onDrag(e, ui, this); @@ -117,19 +119,20 @@ export default class Caption extends BaseComponent { this.setState({ x, y }); - //update throughout drag so nodes know their siblings' positions when - //multiple nodes are dragged simultaneously - if (isMultiple){ - if (this._dragging) { - this.props.moveCaption(this.props.caption.id, this.state.x, this.state.y); - } + //update throughout drag so nodes know their siblings' positions when + //multiple nodes are dragged simultaneously + if (isMultiple){ + if (this._dragging) { + this.props.moveCaption(this.props.caption.id, this.state.x, this.state.y); } + } } // store updated once dragging is done _handleDragStop(e, ui) { // event fires every mouseup so we check for actual drag before updating store - if (!this.graph.props.showEditTools || !this.props.selected) { + var isOnlyOne = (this.graph.props.selection["nodeIds"].length + this.graph.props.selection["captionIds"].length + this.graph.props.selection["edgeIds"].length) < 2; + if (!this.graph.props.showEditTools || !this.props.selected || isOnlyOne) { this._doDragStop(e, ui); } else { this.props.onStop(e, ui, this); diff --git a/app/components/Graph.jsx b/app/components/Graph.jsx index a90cb10..df1af92 100644 --- a/app/components/Graph.jsx +++ b/app/components/Graph.jsx @@ -16,7 +16,7 @@ import filter from 'lodash/collection/filter'; export default class Graph extends BaseComponent { constructor(props) { super(props); - this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop', '_handleDragGroupStart', '_handleDragGroup', '_handleDragGroupStop'); + this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop', '_handleDragGroupStart', '_handleDragGroup', '_handleDragGroupStop', '_manageDragStage'); this.nodes = {}; this.edges = {}; this.captions = {}; @@ -229,88 +229,42 @@ export default class Graph extends BaseComponent { //GROUP DRAGGING // keep initial position for comparison with drag position _handleDragGroupStart(e, ui, that) { - var theSelection = this.props.selection; - var nodes = theSelection["nodeIds"]; - var selectedNodes = _.filter(this.nodes, function(d){ - return _.indexOf(nodes, d.props.node["id"]) != -1; - }) - _.forEach(selectedNodes, function(d){ - d._doDragStart(e, ui); - }) - - var captions = theSelection["captionIds"]; - var selectedCaptions = _.filter(this.captions, function(d){ - return _.indexOf(captions, d.props.caption["id"]) != -1; - }) - _.forEach(selectedCaptions, function(d){ - d._doDragStart(e, ui); - }) - - var edges = theSelection["edgeIds"]; - var selectedEdges = _.filter(this.edges, function(d){ - return _.indexOf(edges, d.props.edge["id"]) != -1; - }) - _.forEach(selectedEdges, function(d){ - d._doDragStart(e, ui); - }) + this._manageDragStage(e, ui, that, "start"); } _handleDragGroup(e, ui, that) { - var theSelection = this.props.selection; - var nodes = theSelection["nodeIds"]; - var selectedNodes = _.filter(this.nodes, function(d){ - return _.indexOf(nodes, d.props.node["id"]) != -1; - }) - _.forEach(selectedNodes, function(d){ - d._doDrag(e, ui, true); - }) - - var captions = theSelection["captionIds"]; - var selectedCaptions = _.filter(this.captions, function(d){ - return _.indexOf(captions, d.props.caption["id"]) != -1; - }) - _.forEach(selectedCaptions, function(d){ - d._doDrag(e, ui, true); - }) - - var edges = theSelection["edgeIds"]; - var selectedEdges = _.filter(this.edges, function(d){ - return _.indexOf(edges, d.props.edge["id"]) != -1; - }) - _.forEach(selectedEdges, function(d){ - d._doDrag(e, ui, true); - }) + this._manageDragStage(e, ui, that, "drag"); } _handleDragGroupStop(e, ui, that) { - var theSelection = this.props.selection; - var nodes = theSelection["nodeIds"]; - var selectedNodes = _.filter(this.nodes, function(d){ - return _.indexOf(nodes, d.props.node["id"]) != -1; - }) - _.forEach(selectedNodes, function(d){ - d._doDragStop(e, ui); - }) - - var captions = theSelection["captionIds"]; - var selectedCaptions = _.filter(this.captions, function(d){ - return _.indexOf(captions, d.props.caption["id"]) != -1; - }) - _.forEach(selectedCaptions, function(d){ - d._doDragStop(e, ui); - }) - - var edges = theSelection["edgeIds"]; - var selectedEdges = _.filter(this.edges, function(d){ - return _.indexOf(edges, d.props.edge["id"]) != -1; - }) - _.forEach(selectedEdges, function(d){ - d._doDragStop(e, ui); - }) - - + this._manageDragStage(e, ui, that, "stop"); } + _manageDragStage(e, ui, that, stage){ + var theSelection = this.props.selection; + var elements = ["node", "caption", "edge"]; + //cycle through elements and move selected elements + for (var i = 0; i < elements.length; i++){ + var thisElement = theSelection[elements[i] + "Ids"]; + var selectedElements = _.filter(this[elements[i] + "s"], function(d){ + return _.indexOf(thisElement, d.props[elements[i]]["id"]) != -1; + }) + + if (stage == "start"){ + _.forEach(selectedElements, function(d){ + d._doDragStart(e, ui); + }) + } else if (stage == "drag"){ + _.forEach(selectedElements, function(d){ + d._doDrag(e, ui, true); + }) + } else { + _.forEach(selectedElements, function(d){ + d._doDragStop(e, ui); + }) + } + } + } // TRANSITION ANIMATION diff --git a/app/components/Node.jsx b/app/components/Node.jsx index d712889..5531370 100644 --- a/app/components/Node.jsx +++ b/app/components/Node.jsx @@ -54,7 +54,8 @@ export default class Node extends BaseComponent { // keep initial position for comparison with drag position _handleDragStart(e, ui) { - if (!this.graph.props.showEditTools || !this.props.selected) { + var isOnlyOne = (this.graph.props.selection["nodeIds"].length + this.graph.props.selection["captionIds"].length + this.graph.props.selection["edgeIds"].length) < 2; + if (!this.graph.props.showEditTools || !this.props.selected || isOnlyOne) { this._doDragStart(e, ui); } else { this.props.onStart(e, ui, this); @@ -62,18 +63,20 @@ export default class Node extends BaseComponent { } _doDragStart(e, ui) { - this._startDrag = ui.position; - this._startPosition = { - x: this.state.x, - y: this.state.y - }; + this._startDrag = ui.position; + this._startPosition = { + x: this.state.x, + y: this.state.y + }; } // while dragging node and its edges are updated only in state, not store _handleDrag(e, ui) { if (this.props.isLocked) return; - if (!this.graph.props.showEditTools || !this.props.selected) { + + var isOnlyOne = (this.graph.props.selection["nodeIds"].length + this.graph.props.selection["captionIds"].length + this.graph.props.selection["edgeIds"].length) < 2; + if (!this.graph.props.showEditTools || !this.props.selected || isOnlyOne) { this._doDrag(e, ui, false); } else { this.props.onDrag(e, ui, this); @@ -112,7 +115,8 @@ export default class Node extends BaseComponent { // store updated once dragging is done _handleDragStop(e, ui) { // event fires every mouseup so we check for actual drag before updating store - if (!this.graph.props.showEditTools || !this.props.selected) { + var isOnlyOne = (this.graph.props.selection["nodeIds"].length + this.graph.props.selection["captionIds"].length + this.graph.props.selection["edgeIds"].length) < 2; + if (!this.graph.props.showEditTools || !this.props.selected || isOnlyOne) { this._doDragStop(e, ui); } else { this.props.onStop(e, ui, this);