|
@@ -0,0 +1,542 @@
|
|
|
+import {mapGetters, mapActions} from 'vuex'
|
|
|
+import FlowNode from './node'
|
|
|
+import FlowLink from './link'
|
|
|
+import FlowTriggerLink from './link-trigger'
|
|
|
+
|
|
|
+import FlowPanZoom from './panzoom'
|
|
|
+import HxContextMenu from '@/components/shared/hx-contextmenu'
|
|
|
+import SvgDefs from './svgdefswrapper'
|
|
|
+import utils from '@/utils/utils'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'FlowManager',
|
|
|
+ components: {FlowNode, FlowLink, FlowTriggerLink, FlowPanZoom, HxContextMenu, SvgDefs},
|
|
|
+ props: {
|
|
|
+ 'width': {type: String, default: '800px'},
|
|
|
+ 'height': {type: String, default: '600px'}
|
|
|
+ },
|
|
|
+ data () {
|
|
|
+ // const cloned = JSON.parse(JSON.stringify(this.value)) // initial?
|
|
|
+ return {
|
|
|
+ panzoom: { x: 0, y: 0, zoom: 1 },
|
|
|
+
|
|
|
+ // Shared state
|
|
|
+ // nodeData: { nodes: [], links: [], triggers: [] },
|
|
|
+
|
|
|
+ dragging: null,
|
|
|
+ linking: false,
|
|
|
+ triggerLinking: false,
|
|
|
+
|
|
|
+ pointerLink: {active: false, props: {}, src: {}},
|
|
|
+ pointerTriggerLink: {active: false, props: {}, src: {}},
|
|
|
+
|
|
|
+ selector: null,
|
|
|
+ nodeSelection: {}, // map of true false
|
|
|
+
|
|
|
+ stickySockets: false,
|
|
|
+ stickyTriggers: false,
|
|
|
+ nodeActivity: true
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ ...mapGetters(['registry', 'activity', 'nodeData', 'nodeMap']),
|
|
|
+
|
|
|
+ nodeProps () {
|
|
|
+ return (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,
|
|
|
+ label: node.label,
|
|
|
+ inputs: nodeClass.inputs,
|
|
|
+ output: nodeClass.output,
|
|
|
+ // Combine this into one
|
|
|
+ match: highlight,
|
|
|
+ dragging: this.dragging && !!this.dragging[node.id],
|
|
|
+ activity: this.activity[node.id],
|
|
|
+ nodeStyle: nodeClass.style
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ linkProps () {
|
|
|
+ return (link) => {
|
|
|
+ if (!this.$refs.nodes) return
|
|
|
+ // For size .x .y
|
|
|
+ const nodeFrom = this.nodeMap(link.from)
|
|
|
+ const nodeTo = this.nodeMap(link.to)
|
|
|
+
|
|
|
+ const refFrom = this.$refs.nodes.find(n => n.id === link.from)
|
|
|
+ const refTo = this.$refs.nodes.find(n => n.id === link.to)
|
|
|
+ if (!refFrom || !refTo) { // delete link
|
|
|
+ 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[nodeFrom.id] && this.activity[nodeFrom.id].status
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ triggerProps () {
|
|
|
+ return (trigger) => {
|
|
|
+ if (!this.$refs.nodes) return
|
|
|
+ // For size .x .y
|
|
|
+ const nodeFrom = this.nodeMap(trigger.from)
|
|
|
+ const nodeTo = this.nodeMap(trigger.to)
|
|
|
+
|
|
|
+ const refFrom = this.$refs.nodes.find(n => n.id === trigger.from)
|
|
|
+ const refTo = this.$refs.nodes.find(n => n.id === trigger.to)
|
|
|
+ if (!refFrom || !refTo) { // delete trigger
|
|
|
+ return {}
|
|
|
+ }
|
|
|
+
|
|
|
+ const fromOutput = {
|
|
|
+ x: 0,
|
|
|
+ y: refFrom.bodyProps.height / 2
|
|
|
+ }
|
|
|
+ const toInput = {
|
|
|
+ x: 0,
|
|
|
+ y: -refTo.bodyProps.height / 2
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ x1: nodeFrom.x + fromOutput.x,
|
|
|
+ y1: nodeFrom.y + fromOutput.y,
|
|
|
+ x2: nodeTo.x + toInput.x,
|
|
|
+ y2: nodeTo.y + toInput.y,
|
|
|
+ status: this.activity[nodeFrom.id] && this.activity[nodeFrom.id].status
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+ mounted () {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.$forceUpdate()
|
|
|
+ })
|
|
|
+ document.addEventListener('keydown', this.keyDown)
|
|
|
+ document.addEventListener('keyup', this.keyUp)
|
|
|
+ },
|
|
|
+ beoreDestroy () {
|
|
|
+ document.removeEventListener('keydown', this.keyDown)
|
|
|
+ document.removeEventListener('keyup', this.keyUp)
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ ...mapActions([
|
|
|
+ 'DOCUMENT_SYNC',
|
|
|
+ 'NODE_RAISE', 'NODE_UPDATE', 'NODE_ADD', 'NODE_REMOVE', 'NODE_INSPECT',
|
|
|
+ 'LINK_ADD', 'LINK_REMOVE',
|
|
|
+ 'TRIGGER_ADD', 'TRIGGER_REMOVE' ]),
|
|
|
+
|
|
|
+ keyDown (ev) {
|
|
|
+ if (document.activeElement && document.activeElement.matches('input,textarea')) { return }
|
|
|
+ if (ev.shiftKey) {
|
|
|
+ this.linking = true
|
|
|
+ this.triggerLinking = true
|
|
|
+ }
|
|
|
+
|
|
|
+ let single = null
|
|
|
+ const selectionIds = Object.keys(this.nodeSelection)
|
|
|
+ if (selectionIds.length === 1) { single = this.nodeSelection[selectionIds[0]] }
|
|
|
+ switch (ev.key) {
|
|
|
+ case 'Enter':
|
|
|
+ if (!single) { return }
|
|
|
+ this.nodeInspect(single)
|
|
|
+ break
|
|
|
+ case 'Delete':
|
|
|
+ if (!this.nodeSelection) { return }
|
|
|
+ console.log('Removing nodes:', this.nodeSelection)
|
|
|
+ this.NODE_REMOVE(this.nodeSelection)
|
|
|
+ // for (let k in this.nodeSelection) {
|
|
|
+ // this.nodeRemove(this.nodeSelection[k])
|
|
|
+ // }
|
|
|
+ break
|
|
|
+ case 'a':
|
|
|
+ if (ev.ctrlKey) {
|
|
|
+ ev.preventDefault()
|
|
|
+ ev.stopPropagation()
|
|
|
+
|
|
|
+ this.nodeSelection = {}
|
|
|
+ for (let n of this.nodeData.nodes) {
|
|
|
+ this.nodeSelection[n.id] = n
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ break
|
|
|
+ }
|
|
|
+ },
|
|
|
+ keyUp (ev) {
|
|
|
+ if (!ev.shiftKey) {
|
|
|
+ this.linking = false
|
|
|
+ this.triggerLinking = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ panzoomReset () {
|
|
|
+ this.panzoom = {x: 0, y: 0, zoom: 1}
|
|
|
+ },
|
|
|
+ // XXX: Shrink this function
|
|
|
+ // and create some LinkAdd method
|
|
|
+ socketPointerDown (nodeId, ev, socket) {
|
|
|
+ if (ev.button !== 0) return
|
|
|
+
|
|
|
+ const nodeRef = this.$refs.nodes.find(n => n.id === nodeId)
|
|
|
+ const node = this.nodeMap(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
|
|
|
+ }
|
|
|
+
|
|
|
+ this.pointerLink.active = true
|
|
|
+ if (isInput) {
|
|
|
+ this.pointerLink.src = {nodeId: nodeId, type: this.registry[node.src].inputs[socket.in].type, in: socket.in}
|
|
|
+ } else {
|
|
|
+ this.pointerLink.src = {nodeId: nodeId, type: this.registry[node.src].output.type, out: 0}
|
|
|
+ }
|
|
|
+ utils.createDrag({
|
|
|
+ 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
|
|
|
+ }
|
|
|
+ },
|
|
|
+ drop: (ev) => {
|
|
|
+ this.pointerLink.active = false
|
|
|
+
|
|
|
+ // find Parent
|
|
|
+
|
|
|
+ var curTarget = ev.target
|
|
|
+ for (; curTarget.hasAttribute !== undefined && curTarget !== document.body; curTarget = curTarget.parentNode) {
|
|
|
+ if (curTarget.hasAttribute('data-nodeid')) {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!curTarget.hasAttribute || curTarget === document.body) {
|
|
|
+ console.error('LINK: target is not a socket')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const targetNodeId = curTarget.getAttribute('data-nodeid')
|
|
|
+ const targetIn = curTarget.getAttribute('data-in')
|
|
|
+ const targetOut = curTarget.getAttribute('data-out')
|
|
|
+
|
|
|
+ let link
|
|
|
+ // target is input
|
|
|
+ if (targetIn && !isInput) {
|
|
|
+ link = {
|
|
|
+ from: nodeId,
|
|
|
+ to: targetNodeId,
|
|
|
+ in: parseInt(targetIn)
|
|
|
+ }
|
|
|
+ } else if (targetOut && isInput) {
|
|
|
+ link = {
|
|
|
+ from: targetNodeId,
|
|
|
+ to: nodeId,
|
|
|
+ in: socket.in
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // No link
|
|
|
+ if (!link) {
|
|
|
+ console.error('LINK: input same direction (in->in/out->out)')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const nodeFrom = this.nodeMap(link.from)
|
|
|
+ const nodeTo = this.nodeMap(link.to)
|
|
|
+
|
|
|
+ const output = this.registry[nodeFrom.src].output.type
|
|
|
+ const input = this.registry[nodeTo.src].inputs[link.in].type
|
|
|
+ // Type checking
|
|
|
+ if (!(output === 'interface {}' || output === input || input === 'interface {}')) {
|
|
|
+ console.error('LINK: Invalid type')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // Input already exists, replace
|
|
|
+ const existingInputI = this.nodeData.links.findIndex(l => l.to === link.to && l.in === link.in)
|
|
|
+ if (existingInputI !== -1) {
|
|
|
+ this.nodeData.links.splice(existingInputI, 1)
|
|
|
+ }
|
|
|
+ this.LINK_ADD(link)
|
|
|
+ }})
|
|
|
+ },
|
|
|
+ triggerPointerDown (nodeId, ev, dir) {
|
|
|
+ if (ev.button !== 0) return
|
|
|
+
|
|
|
+ const nodeRef = this.$refs.nodes.find(n => n.id === nodeId)
|
|
|
+ const node = this.nodeMap(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
|
|
|
+ }
|
|
|
+
|
|
|
+ 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
|
|
|
+ }
|
|
|
+ },
|
|
|
+ drop: (ev) => {
|
|
|
+ this.pointerTriggerLink.active = false
|
|
|
+
|
|
|
+ // find Parent
|
|
|
+ var curTarget = ev.target
|
|
|
+ for (; curTarget.hasAttribute !== undefined && curTarget !== document.body; curTarget = curTarget.parentNode) {
|
|
|
+ if (curTarget.hasAttribute('data-nodeid')) {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!curTarget.hasAttribute || curTarget === document.body) {
|
|
|
+ console.error('TRIGGER: target is not a socket')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const targetNodeId = curTarget.getAttribute('data-nodeid')
|
|
|
+ const targetDir = curTarget.getAttribute('data-dir')
|
|
|
+ if (targetNodeId === node.id) {
|
|
|
+ console.error('TRIGGER: cannot link to self')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ let trigger
|
|
|
+ // target is input
|
|
|
+ if (targetDir === 'in') {
|
|
|
+ trigger = {
|
|
|
+ from: nodeId,
|
|
|
+ to: targetNodeId
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ trigger = {
|
|
|
+ from: targetNodeId,
|
|
|
+ to: nodeId
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.TRIGGER_ADD(trigger)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ nodeInspect (tnode, force) {
|
|
|
+ this.$emit('nodeInspect', tnode, force)
|
|
|
+ },
|
|
|
+
|
|
|
+ // HERE
|
|
|
+ nodePointerDown (ev, i) {
|
|
|
+ document.activeElement && document.activeElement.blur()
|
|
|
+ const tnode = this.nodeData.nodes[i]
|
|
|
+ if (ev.button === 1) {
|
|
|
+ this.NODE_REMOVE([tnode])
|
|
|
+ // this.nodeRemove(tnode)
|
|
|
+ // remove related links
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (ev.button !== 0) return // first button
|
|
|
+ if (ev.shiftKey) {
|
|
|
+ this.socketPointerDown(tnode.id, ev, {out: 0})
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // this.NODE_INSPECT(tnode.id)
|
|
|
+ this.nodeInspect(tnode)
|
|
|
+
|
|
|
+ // Switch selection
|
|
|
+ if (!this.nodeSelection[tnode.id] && !ev.ctrlKey) this.nodeSelection = {}
|
|
|
+ this.nodeSelection[tnode.id] = tnode
|
|
|
+ // we can handle with nodeId and a search
|
|
|
+
|
|
|
+ this.NODE_RAISE(this.nodeSelection)
|
|
|
+ // Raise node
|
|
|
+ // put the list of nodes in last
|
|
|
+ /* for (let nk in this.nodeSelection) {
|
|
|
+ // WRONG
|
|
|
+ let ni = this.nodeData.nodes.findIndex(n => n.id === this.nodeSelection[nk].id)
|
|
|
+ this.nodeData.nodes.splice(ni, 1)
|
|
|
+ this.nodeData.nodes.push(this.nodeSelection[nk]) // put in last
|
|
|
+ } */
|
|
|
+ let curP = this.transformedPoint(ev.x, ev.y)
|
|
|
+
|
|
|
+ this.dragging = this.nodeSelection
|
|
|
+ utils.createDrag({
|
|
|
+ drag: (ev) => {
|
|
|
+ if (this.nodeSelection === undefined) {
|
|
|
+ console.error('Well something went wrong')
|
|
|
+ }
|
|
|
+ const dragP = this.transformedPoint(ev.x, ev.y)
|
|
|
+ const nodeUpdate = []
|
|
|
+ for (let k in this.nodeSelection) {
|
|
|
+ // const n = this.nodeData.nodes.find(n => n.id === k)
|
|
|
+ const n = this.nodeMap(k)
|
|
|
+ // create new nodes
|
|
|
+ nodeUpdate.push({
|
|
|
+ ...n,
|
|
|
+ x: n.x + dragP.x - curP.x,
|
|
|
+ y: n.y + dragP.y - curP.y
|
|
|
+ })
|
|
|
+ }
|
|
|
+ this.NODE_UPDATE(nodeUpdate)
|
|
|
+ // this.sendFlowEvent('nodeUpdate', this.nodeSelection)
|
|
|
+ curP = dragP
|
|
|
+ },
|
|
|
+ drop: (ev) => {
|
|
|
+ this.dragging = null
|
|
|
+ this.DOCUMENT_SYNC()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /// ////////////
|
|
|
+ // NODE CREATOR FUNC
|
|
|
+ //
|
|
|
+ // STORE
|
|
|
+ nodeAdd (src, x = 100, y = 100) {
|
|
|
+ const newNode = {
|
|
|
+ id: utils.guid(),
|
|
|
+ x: x,
|
|
|
+ y: y,
|
|
|
+ defaultInputs: {},
|
|
|
+ label: src,
|
|
|
+ src: src
|
|
|
+ }
|
|
|
+ // Setup Props
|
|
|
+ if (this.registry[src].props) {
|
|
|
+ for (let k in this.registry[src].props) {
|
|
|
+ newNode.prop || (newNode.prop = {})
|
|
|
+ newNode.prop[k] = ''
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.NODE_ADD(newNode)
|
|
|
+ },
|
|
|
+ nodeProcess (node) {
|
|
|
+ // this.DOCUMENT_DYNC()
|
|
|
+ // console.log('Node process demand')
|
|
|
+ this.$emit('nodeProcess', node)
|
|
|
+ },
|
|
|
+ linkPointerClick (ev, link) {
|
|
|
+ ev.preventDefault()
|
|
|
+ this.LINK_REMOVE(link)
|
|
|
+ },
|
|
|
+
|
|
|
+ /* triggerRemove (trigger) {
|
|
|
+ const i = this.nodeData.triggers.findIndex(l => l === trigger)
|
|
|
+ if (i === -1) return
|
|
|
+ this.nodeData.triggers.splice(i, 1)
|
|
|
+ // this.sendFlowEvent('triggerRemove', trigger)
|
|
|
+ this.DOCUMENT_DYNC()
|
|
|
+ }, */
|
|
|
+
|
|
|
+ managerDrop (ev) {
|
|
|
+ ev.preventDefault()
|
|
|
+ const reg = ev.dataTransfer.getData('text')
|
|
|
+ if (this.registry[reg] === undefined) {
|
|
|
+ console.error('Registry: Drop src not found in registry')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const pt = this.transformedPoint(ev.x, ev.y)
|
|
|
+ this.nodeAdd(reg, pt.x, pt.y)
|
|
|
+ },
|
|
|
+ viewPointerDown (ev) {
|
|
|
+ if (ev.button !== 0) return
|
|
|
+ ev.preventDefault()
|
|
|
+ this.nodeSelection = {}
|
|
|
+ const p = this.transformedPoint(ev.x, ev.y)
|
|
|
+ this.selector = {x: p.x, y: p.y, width: 0, height: 0}
|
|
|
+ utils.createDrag({
|
|
|
+ drag: (evd) => {
|
|
|
+ // transform again in case we changed zoom/pan
|
|
|
+ const p = this.transformedPoint(ev.x, ev.y)
|
|
|
+ const p2 = this.transformedPoint(evd.x, evd.y)
|
|
|
+ const nwidth = p2.x - p.x
|
|
|
+ const nheight = p2.y - p.y
|
|
|
+ this.selector = {
|
|
|
+ x: nwidth < 0 ? p2.x : p.x,
|
|
|
+ y: nheight < 0 ? p2.y : p.y,
|
|
|
+ width: nwidth < 0 ? -nwidth : nwidth,
|
|
|
+ height: nheight < 0 ? -nheight : nheight
|
|
|
+ }
|
|
|
+ },
|
|
|
+ drop: (ev) => {
|
|
|
+ for (let n in this.nodeData.nodes) {
|
|
|
+ const node = this.nodeData.nodes[n]
|
|
|
+ if (node.x > this.selector.x && node.x < (this.selector.x + this.selector.width) &&
|
|
|
+ node.y > this.selector.y && node.y < (this.selector.y + this.selector.height)
|
|
|
+ ) {
|
|
|
+ this.nodeSelection[node.id] = node
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.selector = null
|
|
|
+ }})
|
|
|
+ },
|
|
|
+
|
|
|
+ // service events
|
|
|
+ /* sendFlowEvent (type, param) {
|
|
|
+ this.$flowService[type](param)
|
|
|
+ }, */
|
|
|
+
|
|
|
+ //
|
|
|
+ // DOCUMENT_DYNC () {
|
|
|
+ // this.DOCUMENT_SYNC()
|
|
|
+ // this.$flowService.documentUpdate(this.nodeData, this.$route.params.sessId)
|
|
|
+ // },
|
|
|
+ /* sendDocumentRun () {
|
|
|
+ console.log('Document running')
|
|
|
+ this.$flowService.documentRun(this.nodeData, this.$route.params.sessId)
|
|
|
+ }, */
|
|
|
+ // HELPERS depending on svg ref
|
|
|
+ createSVGPoint (x, y) {
|
|
|
+ const p = this.$refs.svg.createSVGPoint()
|
|
|
+ p.x = x; p.y = y
|
|
|
+ return p
|
|
|
+ },
|
|
|
+ transformedPoint (x, y, abs) {
|
|
|
+ const svgRect = this.$refs.svg.getBoundingClientRect()
|
|
|
+ if (!abs) {
|
|
|
+ x -= svgRect.left
|
|
|
+ y -= svgRect.top
|
|
|
+ }
|
|
|
+ return this.$refs.panzoom.transformedPoint(this.createSVGPoint(x, y))
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|