diff --git a/src/components/App.js b/src/components/App.js index d2f2891..3a32f15 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -254,7 +254,8 @@ export default class App extends Component { return this.moveInHistory(1) } - handleDataChange = evt => { + handleDataChange = (evt, overwriteLastHistory = false) => { + if (overwriteLastHistory) this.historyPointer-- let edgeAdded = this.state.diagram.edges.length + 1 === evt.data.edges.length let historyEntry = {diagram: evt.data, time: Date.now()} diff --git a/src/components/Grid.js b/src/components/Grid.js index f7748db..ddfa3de 100644 --- a/src/components/Grid.js +++ b/src/components/Grid.js @@ -12,7 +12,8 @@ export default class Grid extends Component { width: 0, height: 0, phantomArrow: null, - cellTypesetSizes: {} + cellTypesetSizes: {}, + nodesToJoin: null } } @@ -24,8 +25,7 @@ export default class Grid extends Component { document.addEventListener('mouseup', () => { this.mouseDown = null - let {phantomArrow} = this.state - + let {phantomArrow, nodesToJoin} = this.state if (phantomArrow != null) { if (!arrEquals(phantomArrow.from, phantomArrow.to)) { // Add edge @@ -71,6 +71,40 @@ export default class Grid extends Component { this.setState({phantomArrow: null}) } + if (nodesToJoin != null) { + let {textNode, emptyNode} = nodesToJoin + let {onDataChange = () => {}} = this.props + onDataChange( + { + data: { + nodes: this.props.data.nodes + .filter(node => node.id !== textNode.id) + .map(node => + node.id === emptyNode.id + ? { + ...emptyNode, + value: textNode.value + } + : node + ), + edges: this.props.data.edges.map(edge => { + edge = {...edge} + if (edge.from === textNode.id) edge.from = emptyNode.id + if (edge.to === textNode.id) edge.to = emptyNode.id + if (edge.to === edge.from) + edge = { + ...edge, + loop: edge.loop || [0, false], + labelPosition: 'right' + } + return edge + }) + } + }, + true + ) + this.setState({nodesToJoin: null}) + } }) document.addEventListener('mousemove', evt => { @@ -91,16 +125,38 @@ export default class Grid extends Component { cameraPosition: arrSubtract(this.mouseDown.cameraPosition, movement) }) } else if (this.mouseDown.mode === 'move') { - let {nodeIndex} = this.mouseDown + let {nodeIndex, node: draggedNode} = this.mouseDown if (nodeIndex < 0) return - let existingNode = this.props.data.nodes.find(n => - arrEquals(n.position, newPosition) + let existingNode = this.props.data.nodes.find( + n => arrEquals(n.position, newPosition) && n.id !== draggedNode.id ) - if (existingNode != null) return - let {onDataChange = () => {}} = this.props + if ( + this.props.data.nodes.some( + n => arrEquals(n.position, newPosition) && n.id === draggedNode.id + ) + ) + return + + let nodesToJoin = null + if (existingNode != null) { + if (existingNode.value.length > 0 && draggedNode.value.length > 0) + return + if (!arrEquals(newPosition, draggedNode.position)) { + let [textNode, emptyNode] = + draggedNode.value.length > 0 + ? [draggedNode, existingNode] + : [existingNode, draggedNode] + nodesToJoin = { + textNode: {...textNode, position: newPosition}, + emptyNode: {...emptyNode, position: newPosition} + } + } + } + this.setState({nodesToJoin}) + let {onDataChange = () => {}} = this.props onDataChange({ selectedCell: newPosition, data: { @@ -395,9 +451,22 @@ export default class Grid extends Component { this.props.selectedCell != null && arrEquals(position, this.props.selectedCell) - let node = this.props.data.nodes.find(n => - arrEquals(n.position, position) - ) + let node + + let {nodesToJoin} = this.state + if ( + nodesToJoin != null && + arrEquals(nodesToJoin.textNode.position, position) + ) { + node = { + ...nodesToJoin.emptyNode, + value: nodesToJoin.textNode.value, + position: position + } + } else + node = this.props.data.nodes.find(n => + arrEquals(n.position, position) + ) return (