|
@@ -23,21 +23,17 @@ export default {
|
|
|
linking: false,
|
|
|
triggerLinking: false,
|
|
|
|
|
|
- pointerLink: {active: false, props: {}, src: {}},
|
|
|
- pointerTriggerLink: {active: false, props: {}, src: {}},
|
|
|
+ pointerLink: {active: false, from: null, to: null, pointer: null, src: {}},
|
|
|
+ pointerTriggerLink: {active: false, from: null, to: null, pointer: null, src: {}},
|
|
|
|
|
|
selector: null,
|
|
|
-
|
|
|
stickySockets: false,
|
|
|
stickyTriggers: false,
|
|
|
- nodeActivity: true,
|
|
|
- nodeProps: [],
|
|
|
- linkProps: []
|
|
|
- // cacheNodeProps: [],
|
|
|
+ nodeActivity: true
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
- ...mapGetters('flow', ['registry', 'activity', 'nodeData', 'nodeById', 'nodeSelection', 'nodeIdxCache']),
|
|
|
+ ...mapGetters('flow', ['registry', 'activity', 'nodeData', 'nodeById', 'nodeSelection']),
|
|
|
outputNode () {
|
|
|
const n = this.nodeData.nodes.find(n => n.src === 'Output')
|
|
|
return !!n
|
|
@@ -51,11 +47,24 @@ export default {
|
|
|
'selecting': !!this.selector
|
|
|
}
|
|
|
},
|
|
|
- /* nodeProps () {
|
|
|
- return (node) => {
|
|
|
- return this.nodePropsBuild(node)
|
|
|
+ matchHighlight () {
|
|
|
+ let highlight = {}
|
|
|
+ if (this.pointerLink) {
|
|
|
+ if (this.pointerLink.active) {
|
|
|
+ if (this.pointerLink.src.in !== undefined) {
|
|
|
+ highlight = {type: 'socket-out', dtype: this.pointerLink.src.type}
|
|
|
+ } else {
|
|
|
+ highlight = {type: 'socket-in', dtype: this.pointerLink.src.type}
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- }, */
|
|
|
+ if (this.pointerTriggerLink) {
|
|
|
+ if (this.pointerTriggerLink.active) {
|
|
|
+ highlight = {type: (this.pointerTriggerLink.src.dir === 'in') ? 'trigger-in' : 'trigger-out'}
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return highlight
|
|
|
+ },
|
|
|
triggerProps () {
|
|
|
return (trigger) => {
|
|
|
if (!this.$refs.nodes) return
|
|
@@ -89,26 +98,14 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
watch: {
|
|
|
- 'nodeData.nodes' (val, oldVal) {
|
|
|
- console.log('Nodes updated')
|
|
|
- this.nodePropsUpdate()
|
|
|
- },
|
|
|
- 'nodeData.links' () {
|
|
|
- console.log('Updating links')
|
|
|
- this.linkPropsUpdate()
|
|
|
- },
|
|
|
'activity' () {
|
|
|
- _debounce(this.activityUpdate, 1500)
|
|
|
+ this.activityUpdate()
|
|
|
}
|
|
|
},
|
|
|
- created () {
|
|
|
- this.nodePropsUpdate()
|
|
|
- },
|
|
|
mounted () {
|
|
|
console.log('Mounted')
|
|
|
this.$nextTick(() => {
|
|
|
this.$forceUpdate()
|
|
|
- this.$nextTick(() => { this.linkPropsUpdate() })
|
|
|
})
|
|
|
document.addEventListener('keydown', this.keyDown)
|
|
|
document.addEventListener('keyup', this.keyUp)
|
|
@@ -126,98 +123,9 @@ export default {
|
|
|
'LINK_ADD', 'LINK_REMOVE',
|
|
|
'TRIGGER_ADD', 'TRIGGER_REMOVE' ]),
|
|
|
|
|
|
- activityUpdate () {
|
|
|
+ activityUpdate: _debounce(function () {
|
|
|
console.log('Activity updated')
|
|
|
- this.linkPropsUpdate()
|
|
|
- },
|
|
|
- nodePropsBuild (node) {
|
|
|
- let highlight = {}
|
|
|
- if (this.pointerLink.active && this.pointerLink.src.nodeId !== node.id) {
|
|
|
- if (this.pointerLink.src.in !== undefined) {
|
|
|
- highlight = {type: 'socket-out', dtype: this.pointerLink.src.type}
|
|
|
- } else {
|
|
|
- highlight = {type: 'socket-in', dtype: this.pointerLink.src.type}
|
|
|
- }
|
|
|
- }
|
|
|
- if (this.pointerTriggerLink.active && this.pointerTriggerLink.src.nodeId !== node.id) {
|
|
|
- highlight = {type: (this.pointerTriggerLink.src.dir === 'in') ? 'trigger-in' : 'trigger-out'}
|
|
|
- }
|
|
|
-
|
|
|
- const nodeClass = this.registry[node.src]
|
|
|
- if (!nodeClass) {
|
|
|
- this.NODE_REMOVE([node])
|
|
|
- return
|
|
|
- }
|
|
|
- return {
|
|
|
- transform: `translate(${node.x} ${node.y})`,
|
|
|
- id: node.id,
|
|
|
- node: node,
|
|
|
- // Combine this into one
|
|
|
- match: highlight,
|
|
|
- selected: !!this.nodeSelection[node.id],
|
|
|
- dragging: this.dragging && !!this.dragging[node.id],
|
|
|
- activity: this.activity && this.activity.nodes && this.activity.nodes[node.id]
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- nodePropsUpdate (n) {
|
|
|
- // Find node ID and update it only
|
|
|
- if (n) {
|
|
|
- const idx = this.nodeIdxCache[n.id]
|
|
|
- this.$set(this.nodeProps, idx, this.nodePropsBuild(n))
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- const ret = []
|
|
|
- for (let node of this.nodeData.nodes) {
|
|
|
- ret.push(this.nodePropsBuild(node))
|
|
|
- }
|
|
|
- this.nodeProps = ret
|
|
|
- },
|
|
|
- // propCaches
|
|
|
- linkPropsUpdate (link, idx) {
|
|
|
- if (!this.$refs.nodes) {
|
|
|
- setTimeout(() => {
|
|
|
- this.linkPropsUpdate() // Retry until we have refs
|
|
|
- }, 200)
|
|
|
- return
|
|
|
- }
|
|
|
- const linkProps = (link) => {
|
|
|
- if (!this.$refs.nodes) return [] // empty we need $refs.nodes
|
|
|
- // For size .x .y
|
|
|
- const nodeFrom = this.nodeById(link.from)
|
|
|
- const nodeTo = this.nodeById(link.to)
|
|
|
-
|
|
|
- const refFrom = this.$refs.nodes.find(n => n.node.id === link.from)
|
|
|
- const refTo = this.$refs.nodes.find(n => n.node.id === link.to)
|
|
|
- if (!refFrom || !refTo) { // delete link
|
|
|
- // No ref yet
|
|
|
- return {}
|
|
|
- }
|
|
|
-
|
|
|
- const fromOutput = refFrom.outputPos(0) // only 1 output
|
|
|
- const toInput = refTo.inputPos(link.in)
|
|
|
-
|
|
|
- return {
|
|
|
- x1: nodeFrom.x + fromOutput.x,
|
|
|
- y1: nodeFrom.y + fromOutput.y,
|
|
|
- x2: nodeTo.x + toInput.x,
|
|
|
- y2: nodeTo.y + toInput.y,
|
|
|
- status: this.activity.nodes[nodeFrom.id] && this.activity.nodes[nodeFrom.id].status
|
|
|
- }
|
|
|
- }
|
|
|
- if (link) {
|
|
|
- if (idx === undefined)idx = this.linkProps.findIndex(l => l === link)
|
|
|
- this.$set(this.linkProps, idx, linkProps(link))
|
|
|
- return
|
|
|
- }
|
|
|
- const ret = []
|
|
|
- for (let link of this.nodeData.links) {
|
|
|
- const p = linkProps(link)
|
|
|
- ret.push(p)
|
|
|
- }
|
|
|
- this.linkProps = ret
|
|
|
- },
|
|
|
+ }, 1500),
|
|
|
|
|
|
keyDown (ev) {
|
|
|
if (document.activeElement && document.activeElement.matches('input,textarea')) { return }
|
|
@@ -259,19 +167,17 @@ export default {
|
|
|
// and create some LinkAdd method
|
|
|
socketPointerDown (nodeId, ev, socket) {
|
|
|
if (ev.button !== 0) return
|
|
|
- const nodeRef = this.$refs.nodes.find(n => n.node.id === nodeId)
|
|
|
const node = this.nodeById(nodeId)
|
|
|
const isInput = socket.in !== undefined
|
|
|
- const socketPos = isInput ? nodeRef.inputPos(socket.in) : nodeRef.outputPos(socket.out)
|
|
|
|
|
|
- // const p = this.transformedPoint(ev.clientX, ev.clientY)
|
|
|
- this.pointerLink.props = {
|
|
|
- x1: node.x + socketPos.x,
|
|
|
- y1: node.y + socketPos.y,
|
|
|
- x2: node.x + socketPos.x,
|
|
|
- y2: node.y + socketPos.y
|
|
|
+ const p = this.transformedPoint(ev.clientX, ev.clientY)
|
|
|
+ this.pointerLink.pointer = p
|
|
|
+ if (isInput) {
|
|
|
+ this.pointerLink.to = nodeId
|
|
|
+ this.pointerLink.in = socket.in
|
|
|
+ } else {
|
|
|
+ this.pointerLink.from = nodeId
|
|
|
}
|
|
|
-
|
|
|
if (isInput) {
|
|
|
this.pointerLink.src = {nodeId: nodeId, type: this.registry[node.src].inputs[socket.in].type, in: socket.in}
|
|
|
} else {
|
|
@@ -281,21 +187,13 @@ export default {
|
|
|
utils.createDrag({
|
|
|
dragStart: (ev) => {
|
|
|
this.pointerLink.active = true
|
|
|
- this.nodePropsUpdate()
|
|
|
},
|
|
|
drag: (ev) => {
|
|
|
const p = this.transformedPoint(ev.clientX, ev.clientY)
|
|
|
- if (isInput) {
|
|
|
- this.pointerLink.props.x1 = p.x
|
|
|
- this.pointerLink.props.y1 = p.y
|
|
|
- } else {
|
|
|
- this.pointerLink.props.x2 = p.x
|
|
|
- this.pointerLink.props.y2 = p.y
|
|
|
- }
|
|
|
+ this.pointerLink.pointer = p
|
|
|
},
|
|
|
drop: (ev) => {
|
|
|
this.pointerLink.active = false
|
|
|
- this.nodePropsUpdate()
|
|
|
if (ev.target.matches('.flow-pan-zoom__transformer')) {
|
|
|
if (isInput) {
|
|
|
console.error('LINK: Invalid target')
|
|
@@ -368,35 +266,20 @@ export default {
|
|
|
},
|
|
|
triggerPointerDown (nodeId, ev, dir) {
|
|
|
if (ev.button !== 0) return
|
|
|
-
|
|
|
- const nodeRef = this.$refs.nodes.find(n => n.id === nodeId)
|
|
|
- const node = this.nodeById(nodeId)
|
|
|
-
|
|
|
const isInput = (dir === 'in')
|
|
|
- const triggerPos = {
|
|
|
- x: 0,
|
|
|
- y: nodeRef.bodyProps.height / 2 * (isInput ? -1 : 1)
|
|
|
- }
|
|
|
- this.pointerTriggerLink.src = {nodeId: node.id, dir: dir}
|
|
|
|
|
|
- this.pointerTriggerLink.props = {
|
|
|
- x1: node.x + triggerPos.x,
|
|
|
- y1: node.y + triggerPos.y,
|
|
|
- x2: node.x + triggerPos.x,
|
|
|
- y2: node.y + triggerPos.y
|
|
|
+ if (isInput) {
|
|
|
+ this.pointerTriggerLink.to = nodeId
|
|
|
+ } else {
|
|
|
+ this.pointerTriggerLink.from = nodeId
|
|
|
}
|
|
|
-
|
|
|
+ this.pointerTriggerLink.src = {nodeId: nodeId, dir: dir}
|
|
|
+ this.pointerTriggerLink.pointer = this.transformedPoint(ev.clientX, ev.clientY)
|
|
|
this.pointerTriggerLink.active = true
|
|
|
+
|
|
|
utils.createDrag({
|
|
|
drag: (ev) => {
|
|
|
- const p = this.transformedPoint(ev.clientX, ev.clientY)
|
|
|
- if (isInput) {
|
|
|
- this.pointerTriggerLink.props.x1 = p.x
|
|
|
- this.pointerTriggerLink.props.y1 = p.y
|
|
|
- } else {
|
|
|
- this.pointerTriggerLink.props.x2 = p.x
|
|
|
- this.pointerTriggerLink.props.y2 = p.y
|
|
|
- }
|
|
|
+ this.pointerTriggerLink.pointer = this.transformedPoint(ev.clientX, ev.clientY)
|
|
|
},
|
|
|
drop: (ev) => {
|
|
|
this.pointerTriggerLink.active = false
|
|
@@ -414,11 +297,10 @@ export default {
|
|
|
}
|
|
|
const targetNodeId = curTarget.getAttribute('data-nodeid')
|
|
|
const targetDir = curTarget.getAttribute('data-dir')
|
|
|
- if (targetNodeId === node.id) {
|
|
|
+ if (targetNodeId === nodeId) {
|
|
|
console.error('TRIGGER: cannot link to self')
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
let trigger
|
|
|
// target is input
|
|
|
if (targetDir === 'in') {
|
|
@@ -489,7 +371,8 @@ export default {
|
|
|
for (let k in this.nodeSelection) {
|
|
|
const n = this.nodeById(k)
|
|
|
if (n.src === 'Output') { // Do not clone output
|
|
|
- continue
|
|
|
+ this.NOTIFICATION_ADD('cannot clone \'Output\' node')
|
|
|
+ return
|
|
|
}
|
|
|
const newNode = JSON.parse(JSON.stringify(n))
|
|
|
newNode.id = utils.guid()
|
|
@@ -500,7 +383,6 @@ export default {
|
|
|
// Clone links if inside the selection
|
|
|
for (let k in this.nodeSelection) {
|
|
|
const links = this.nodeData.links.filter(l => l.from === k)
|
|
|
- if (!links) break
|
|
|
for (let l of links) {
|
|
|
if (this.nodeSelection[l.to]) { // Link is inside
|
|
|
const link = {
|
|
@@ -511,6 +393,17 @@ export default {
|
|
|
this.LINK_ADD(link)
|
|
|
}
|
|
|
}
|
|
|
+ // Trigger too
|
|
|
+ const triggers = this.nodeData.triggers.filter(t => t.from === k)
|
|
|
+ for (let t of triggers) {
|
|
|
+ if (this.nodeSelection[t.to]) {
|
|
|
+ const trigger = {
|
|
|
+ from: nodeMap[k],
|
|
|
+ to: nodeMap[t.to]
|
|
|
+ }
|
|
|
+ this.TRIGGER_ADD(trigger)
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
// Check inner links
|
|
|
this.select(newNodes)
|
|
@@ -526,13 +419,6 @@ export default {
|
|
|
x: n.x + dragP.x - curP.x,
|
|
|
y: n.y + dragP.y - curP.y
|
|
|
}
|
|
|
- // XXX: temporary code
|
|
|
- this.nodePropsUpdate(cloneNode)
|
|
|
- // Find links too
|
|
|
- this.nodeData.links.forEach((link, idx) => {
|
|
|
- if (link.from !== k && link.to !== k) return true
|
|
|
- this.$nextTick(() => { this.linkPropsUpdate(link, idx) })
|
|
|
- })
|
|
|
|
|
|
nodeUpdate.push(cloneNode)
|
|
|
}
|
|
@@ -556,13 +442,6 @@ export default {
|
|
|
// x: Math.round((n.x + dragP.x - curP.x) / 10) * 10,
|
|
|
// y: Math.round((n.y + dragP.y - curP.y) / 10) * 10
|
|
|
}
|
|
|
- // XXX: temporary code
|
|
|
- this.nodePropsUpdate(cloneNode)
|
|
|
- // Place this in the nodeProps itself
|
|
|
- this.nodeData.links.forEach((link, idx) => {
|
|
|
- if (link.from !== k && link.to !== k) return true
|
|
|
- this.$nextTick(() => { this.linkPropsUpdate(link, idx) })
|
|
|
- })
|
|
|
|
|
|
nodeUpdate.push(cloneNode)
|
|
|
}
|
|
@@ -651,7 +530,6 @@ export default {
|
|
|
}
|
|
|
this.select(nodesToSelect, selectionAdd)
|
|
|
this.selector = null
|
|
|
- this.nodePropsUpdate()
|
|
|
},
|
|
|
noDrag: (ev) => {
|
|
|
if (!ev.shiftKey) this.select()
|
|
@@ -700,7 +578,6 @@ export default {
|
|
|
if (nodes) {
|
|
|
this.NODE_SELECTION_ADD(nodes)
|
|
|
}
|
|
|
- this.nodePropsUpdate()
|
|
|
},
|
|
|
// HELPERS depending on svg ref
|
|
|
createSVGPoint (x, y) {
|