Select Git revision
divtools.js
divtools.js 10.40 KiB
import * as BZ from './vbzt.js'
// I forsee genuine instantiation and state here ...
// or a roll into view
let port
function init(dom, prt) {
port = prt
console.log('DT INIT with dom', dom, 'and port', port)
BZ.init(dom)
}
/* --------------------------- ---------------------------- */
/* ------------------------- TRANSFORMS -------------------------- */
/* --------------------------- ---------------------------- */
function writeTransform(div, tf) {
div.style.transform = `scale(${tf.s})`
div.style.transformOrigin = '0px 0px'
div.style.left = `${tf.x}px`
div.style.top = `${tf.y}px`
}
function readTransform(div) {
// a string (there must be a better way)
let transform = div.style.transform
let index = transform.indexOf('scale')
let left = transform.indexOf('(', index)
let right = transform.indexOf(')', index)
let s = parseFloat(transform.slice(left + 1, right))
let x = parseFloat(div.style.left)
let y = parseFloat(div.style.top)
return ({
s: s,
x: x,
y: y
})
}
function reposition(div){
div.style.left = div.x + 'px'
div.style.top = div.y + 'px'
}
function readXY(div){
//console.log('READXY left', div.style.left, 'top', div.style.top)
return {x: div.style.left, y: div.style.top}
}
/* --------------------------- ---------------------------- */
/* -------------------- WRITING DOM ELEMENTS --------------------- */
/* --------------------------- ---------------------------- */
function writeDefDom(def, parentdom, debug) {
// debug
if (debug) console.log('writing for def', def)
// a div to locate it
let de = document.createElement('div')
$(de).addClass('block').attr('id', def.id)
// more html: the title
$(de).append($('<div>' + de.id + '</div>').addClass('blockid'))
let title = $(de).children('.blockid').get(0)
title.onmousedown = function(evt) {
evt.preventDefault()
evt.stopPropagation()
// stop the D3 sim
// halting ... we don't have access to that here
// we need to roll this into view
// save it for post-link world
//offsetX = evt.clientX - domElem.getBoundingClientRect().left
//offsetY = evt.clientY - domElem.getBoundingClientRect().top
function domElemMouseMove(evt) {
// TRANSFORMS here to move div about on drag
evt.preventDefault()
evt.stopPropagation()
let ct = readTransform(de)
ct.x += evt.movementX
ct.y += evt.movementY
writeTransform(de, ct)
drawLinks(parentdom)
// TODO rewrite redraw
//redrawLinks()
}
function rmOnMouseUp(evt) {
// would do save of position state here
// TODO /\
document.removeEventListener('mousemove', domElemMouseMove)
document.removeEventListener('mouseup', rmOnMouseUp)
}
document.addEventListener('mousemove', domElemMouseMove)
document.addEventListener('mouseup', rmOnMouseUp)
}
if (Object.keys(def.inputs).length > 0) {
let idom = $('<div>').addClass('inputs')
for (let key in def.inputs) {
if (debug) console.log('def.inputs[key]', def.inputs[key])
$(idom).append(writePortDom(def.inputs[key], def, 'input', parentdom, debug))
}
$(de).append(idom)
}
if (Object.keys(def.inputs).length > 0) {
let odom = $('<div>').addClass('outputs')
for (let key in def.outputs) {
if (debug) console.log('def.outputs[key]', def.outputs[key])
$(odom).append(writePortDom(def.outputs[key], def, 'output', parentdom, debug))
}
$(de).append(odom)
}
if (Object.keys(def.inputs).length > 0) {
let sdom = $('<div>').addClass('state')
for (let key in def.state) {
if (debug) console.log('state dom', sdom)
if (debug) console.log('def.state[key]', def.state[key])
$(sdom).append(writeStateDom(def.state[key], def, debug))
}
$(de).append(sdom)
}
return de
}
// PORTS (inputs and outputs) are <li> objects with unique IDs,
// outputs hold a list of the unique id's they are connected to, for drawing
// beziers with
// we're close, just
/*
- write message to manager
- receive newlink messages from manager
- something for deleting links ?
- f it all and get to the link link
*/
function writePortDom(port, parent, inout, bigdom, debug) {
if (false) console.log('port dom', port, parent.id, inout)
let dom = $('<li>' + port.name + '</li>').addClass(inout).get(0)
dom.id = parent.id + '_' + inout + '_' + port.name
// this goes in so that we can handily draw links
dom.connectedTo = new Array()
// let ... in is OK for zero-length arrays, but for ... of throws errors
for(let conn in port.connections){
let cn = port.connections[conn]
dom.connectedTo.push('#' + cn.parentid + '_' + 'input' + '_' + cn.input)
}
// messy global for the potential floater
let floater = {}
// the events
function evtDrag(drag) {
let cp = readTransform(floater)
cp.x += drag.movementX
cp.y += drag.movementY
writeTransform(floater, cp)
drawLinks(bigdom)
}
// startup the floater
dom.addEventListener('mousedown', (down) => {
console.log('MOUSEDOWN for', port.type, port.name, down)
// get the location to make the floater,
let cp = BZ.getRightHandle(dom, bigdom.subscale)
floater = $('<div>').attr('id', 'floater').append(port.type).get(0)
floater.style.zIndex = '1'
bigdom.appendChild(floater)
// 'hookup' our floater and its berth
dom.connectedTo.push('#floater')
// init out floater position, and put it in the dom
writeTransform(floater, {
s: bigdom.subscale,
x: cp.x - 80 * bigdom.subscale,
y: cp.y - (floater.clientHeight / 2) * bigdom.subscale
})
// do relative moves
bigdom.addEventListener('mousemove', evtDrag)
// and delete / act when mouse comes up
bigdom.addEventListener('mouseup', function evtUp(up) {
console.log('MOUSEUP ON', up.target.id)
// recall name and parent id from id
let str = up.target.id
let last = str.lastIndexOf('_')
let name = str.substring(last + 1)
console.log('with name', name)
let first = str.indexOf('_')
let next = str.indexOf('_', first + 1)
let id = str.substring(0, next)
console.log('and id', id)
let msg = {
header: 'add link',
content: [parent.id, port.name, id, name]
}
writeMsg(msg)
// do things to conn, then
// cleanup
bigdom.removeEventListener('mouseup', evtUp)
bigdom.removeEventListener('mousemove', evtDrag)
dom.connectedTo.splice(dom.connectedTo.indexOf('#floater'), 1)
$('#floater').remove()
drawLinks(bigdom)
})
})
if (debug) console.log('port', dom)
return dom
}
function writeStateDom(state, parent) {
let dom = $('<li>' + state.name + '</li>').get(0)
switch (typeof state.value) {
case 'string':
let strinput = $('<input>').attr('type', 'text').attr('size', 24).attr('value', state.value).get(0)
strinput.addEventListener('change', (evt) => {
// ask for a change,
writeStateChangeMessage(parent.id, state, strinput.value)
// but assert that we don't change the definition unless
strinput.value = state.value
})
state.dom = strinput
$(dom).append(strinput)
break
case 'number':
let ninput = $('<input>').attr('type', 'text').attr('size', 24).attr('value', state.value.toString()).get(0)
ninput.addEventListener('change', (evt) => {
// ask for a change,
writeStateChangeMessage(parent.id, state, parseFloat(ninput.value))
// but assert that we don't change the definition unless
ninput.value = state.value
})
state.dom = ninput
$(dom).append(ninput)
break
case 'boolean':
$(dom).append('<span style="float:right;">' + state.value.toString() + '</span>')
dom.addEventListener('click', (evt) => {
// ask for a change,
writeStateChangeMessage(parent.id, state, !state.value)
})
break
default:
// + note on nonrec type
break
}
return dom
}
function writeStateChangeMessage(parentid, state, value) {
let msg = {
header: 'state change',
content: {
id: parentid,
name: state.name,
value: value
}
}
writeMsg(msg)
}
function writeMsg(msg){
console.log('div msg down', msg)
console.log('port is', port)
port(msg)
}
/* --------------------------- ---------------------------- */
/* ----------------------- RENDERING LINKS ----------------------- */
/* --------------------------- ---------------------------- */
function drawLinks(dom) {
// from within the div
let outputs = $(dom).children('.block').children('.outputs').children('.output')
// clear all links
BZ.clear(dom)
// and draw new ones
for (let output of outputs) {
// finding the children to hookup to
for(let conn in output.connectedTo){
let hookup = $(dom).find(output.connectedTo[conn])
if(hookup.length !== 1){
// this can happen when a dependent is not loaded yet
console.log('missing connection')
} else {
let hk = hookup.get(0)
let head = BZ.getRightHandle(output, dom.subscale)
let tail
if(hk.id === 'floater'){
tail = BZ.getFloaterHandle(hk, dom.subscale)
} else {
tail = BZ.getLeftHandle(hk, dom.subscale)
}
BZ.writeBezier(head, tail, output.id + hk.id, dom)
}
}
}
}
export {
init,
readTransform,
readXY,
reposition,
writeTransform,
writeDefDom,
drawLinks
}