Select Git revision
clusterpi.js
-
Neil Gershenfeld authoredNeil Gershenfeld authored
divtools.js 11.96 KiB
// writing representations
function addRepToView(rep) {
// a div to locate it
var domElem = document.createElement('div')
// dif. color for hardwares ?
domElem.className = 'block'
if (rep.description.isHardware) {
domElem.classList.add('hardware')
}
domElem.style.left = lastPos.x + 'px'
domElem.style.top = lastPos.y + 'px'
// more html: the title
var title = document.createElement('div')
title.className = 'modname'
title.innerHTML = rep.description.id
title.alt = rep.description.alt
// MOVEABOUT CODE
title.onmousedown = function(evt) {
evt.preventDefault()
evt.stopPropagation()
offsetX = evt.clientX - domElem.getBoundingClientRect().left
offsetY = evt.clientY - domElem.getBoundingClientRect().top
function domElemMouseMove(evt) {
evt.preventDefault()
evt.stopPropagation()
var cT = getCurrentTransform()
domElem.style.left = parseFloat(domElem.style.left) + evt.movementX / cT.s + 'px'
domElem.style.top = parseFloat(domElem.style.top) + evt.movementY / cT.s + 'px'
redrawLinks()
}
function rmOnMouseUp(evt) {
rep.description.position.left = parseInt(domElem.style.left, 10)
rep.description.position.top = parseInt(domElem.style.top, 10)
putPosition(rep)
document.removeEventListener('mousemove', domElemMouseMove)
document.removeEventListener('mouseup', rmOnMouseUp)
}
document.addEventListener('mousemove', domElemMouseMove)
document.addEventListener('mouseup', rmOnMouseUp)
}
domElem.appendChild(title)
var uiSetFlag
// place in pos if info present
// the rep.dom object will store references to the module's related DOM elements
if (rep.description.position != null) {
uiSetFlag = false
if (rep.description.position.left != null) {
domElem.style.left = rep.description.position.left + 'px'
}
if (rep.description.position.top != null) {
domElem.style.top = rep.description.position.top + 'px'
}
} else {
uiSetFlag = true
rep.description.position = {}
rep.description.position.left = lastPos.x
rep.description.position.top = lastPos.y
}
if (rep.dom == null) {
rep.dom = {}
}
rep.dom.domElem = domElem
// WRITE STATE ELEMENTS
var stateElem = document.createElement('div')
stateElem.className = 'state'
rep.dom.state = {}
for (st in rep.state) {
var inputItem = writeStateRep(stateElem, rep, st)
rep.dom.state[st] = inputItem
}
// WRITE INPUTS
var inElem = document.createElement('div')
inElem.className = 'inputs'
rep.dom.inputs = {}
for (ip in rep.inputs) {
var li = writeEventRep(rep, 'input', ip)
inElem.appendChild(li)
rep.dom.inputs[ip] = li
}
// WRITE OUTPUTS
var outElem = document.createElement('div')
outElem.className = 'outputs'
rep.dom.outputs = {}
for (op in rep.outputs) {
var li = writeEventRep(rep, 'output', op)
outElem.appendChild(li)
rep.dom.outputs[op] = li
}
// HANDLE UNIQUE UIS
if (rep.ui != null) {
var uiElem = document.createElement('div')
uiElem.className = 'uidiv'
rep.dom.ui = {}
for (ui in rep.ui) {
writeUiElement(uiElem, rep, ui)
}
}
// APPEND TO CONTAINER
domElem.appendChild(inElem)
domElem.appendChild(outElem)
domElem.appendChild(stateElem)
domElem.appendChild(uiElem)
var clearElem = document.createElement('div')
clearElem.className = 'clear'
domElem.appendChild(clearElem)
wrapper.appendChild(rep.dom.domElem)
if (uiSetFlag) {
putPosition(rep)
}
}
function writeEventRep(rep, type, key) {
var li = document.createElement('li')
li.innerHTML = key.toString()
li.id = rep.id + ' ' + type + ' ' + key
li.addEventListener('click', (evt) => {
var ipclk = {
rep: rep,
type: type,
name: key,
evt: evt
}
if (verbose) console.log('EVENT HOOKUP CLK: ', key)
evtConnectHandler(ipclk)
})
li.addEventListener('mouseover', (evt) => {
if (type == 'input') {
rep.dom.inputs[key].isHovering = true
} else if (type == 'output') {
rep.dom.outputs[key].isHovering = true
}
redrawLinks()
li.addEventListener('mouseout', (evt) => {
if (type == 'input') {
rep.dom.inputs[key].isHovering = false
} else if (type == 'output') {
rep.dom.outputs[key].isHovering = false
}
redrawLinks()
})
})
return li
}
function writeStateRep(container, rep, key) {
var variable = rep.state[key]
switch (typeof variable) {
case 'string':
var li = document.createElement('li')
li.appendChild(document.createTextNode(key))
var input = document.createElement('input')
input.type = 'text'
input.size = 24
input.value = variable
input.addEventListener('change', function() {
rep.state[key] = input.value
putState(rep, key)
})
li.appendChild(input)
container.appendChild(li)
return input
break
case 'number':
var li = document.createElement('li')
li.appendChild(document.createTextNode(key))
var input = document.createElement('input')
input.type = 'text'
input.size = 24
input.value = variable.toString()
input.addEventListener('change', function(evt) {
rep.state[key] = parseFloat(input.value)
putState(rep, key)
})
li.appendChild(input)
container.appendChild(li)
return input
break
case 'boolean':
var li = document.createElement('li')
li.innerHTML = key + ':\t\t' + variable.toString()
// TODO: tag align-right?
li.addEventListener('click', function() {
if (rep.state[key]) {
rep.state[key] = false
} else {
rep.state[key] = true
}
putState(rep, key)
})
container.appendChild(li)
return li
// TODO : return what ?
break
case 'object':
// first, handle arrays
if (Array.isArray(variable)) {
var li = document.createElement('li')
li.appendChild(document.createTextNode(key))
var input = document.createElement('input')
input.type = 'text'
input.size = 24
if (typeof variable[0] == 'number') {
input.value = variable.toString()
input.addEventListener('change', function() {
var arr = input.value.split(',')
arr.forEach(function(element, index, array) {
array[index] = parseFloat(element)
})
rep.state[key] = arr
putState(rep, key)
})
li.appendChild(input)
container.appendChild(li)
return input
} else if (typeof variable[0] == 'string') {
input.value = variable.toString()
input.addEventListener('change', function() {
var arr = input.value.split(',')
arr.forEach(function(element, index, array) {
array[index] = element
})
rep.state[key] = arr
putState(rep, key)
})
li.appendChild(input)
container.appendChild(li)
return input
} else if (typeof variable[0] == 'object') {
throw 'ERR not going to handle object arrays'
}
} else {
throw 'ERR not going to handle objects in state'
}
break
default:
console.log("ERR: state walked and no reciprocal code")
}
}
function writeUiElement(container, rep, key) {
// pull the representation object from what we were sent
var ui = rep.ui[key]
console.log('write ui', ui)
console.log('at rep', rep)
//import script from ui.clientPath
// load this thing,
ui.script = document.createElement('script')
container.appendChild(ui.script)
// it loads and executes when this is set
ui.script.src = ui.clientPath
// events
ui.script.onerror = function(err){
console.log('ERR from ui script', err)
}
ui.script.onload = function(msg){
console.log('UI script loaded')
// each ui script writes this function to
// window. (global scope) on load,
// so we can use it now to get hooks
registerNewModule(rep.description.id, key)
// that function will be used to append to
console.log('UI script hooked, having lump at', program.modules[rep.description.id].ui[key].lump)
container.appendChild(program.modules[rep.description.id].ui[key].lump.domElem)
}
}
// bezier utilities
var svgns = 'http://www.w3.org/2000/svg'
var svg = {}
function newBezier(x1, y1, x2, y2, highlight) {
var bz = {}
bz.elem = document.createElementNS(svgns, 'path')
if (highlight) {
bz.elem.style.stroke = '#fcd17b'
} else {
bz.elem.style.stroke = '#1a1a1a'
}
bz.elem.style.fill = 'none'
bz.elem.style.strokeWidth = '7px'
bz.x1 = x1
bz.y1 = y1
bz.x2 = x2
bz.y2 = y2
redrawBezier(bz)
svg.appendChild(bz.elem)
return bz
}
function redrawBezier(bz) {
var bl = Math.sqrt(Math.pow((bz.x1 - bz.x2), 2) + Math.pow((bz.y1 - bz.y2), 2)) * 0.6
var ps = 'M ' + bz.x1 + ' ' + bz.y1 + ' C ' + (bz.x1 + bl) + ' ' + bz.y1
var pe = ' ' + (bz.x2 - bl) + ' ' + bz.y2 + ' ' + bz.x2 + ' ' + bz.y2
bz.elem.setAttribute('d', ps + pe)
}
function modifyBezierHead(bz, x1, y1) {
bz.x1 = x1
bz.y1 = y1
redrawBezier(bz)
}
function modifyBezierTail(bz, x2, y2) {
bz.x2 = x2
bz.y2 = y2
redrawBezier(bz)
}
function getOutputArrow(div) {
var x = div.offsetParent.offsetLeft + div.offsetLeft + div.clientWidth
var y = div.offsetParent.offsetTop + div.offsetTop + div.clientHeight / 2
var pos = {
x: x,
y: y
}
return pos
}
function getInputArrow(div) {
var x = div.offsetParent.offsetLeft
var y = div.offsetParent.offsetTop + div.offsetTop + div.clientHeight / 2
var pos = {
x: x,
y: y
}
return pos
}
function newLine(x1, y1, x2, y2, stroke, dashed) {
var ln = {}
ln.elem = document.createElementNS(svgns, 'line')
ln.elem.style.stroke = '#1a1a1a'
if (dashed) {
ln.elem.setAttribute('stroke-dasharray', '21, 7, 7, 7')
}
ln.elem.style.fill = 'none'
if (stroke) {
ln.elem.style.strokeWidth = stroke + 'px'
} else {
ln.elem.style.strokeWidth = '6px'
}
ln.x1 = x1
ln.y1 = y1
ln.x2 = x2
ln.y2 = y2
redrawLine(ln)
svg.appendChild(ln.elem)
return ln
}
function redrawLine(ln) {
ln.elem.setAttribute('x1', ln.x1)
ln.elem.setAttribute('y1', ln.y1)
ln.elem.setAttribute('x2', ln.x2)
ln.elem.setAttribute('y2', ln.y2)
}
function getLeftWall(div) {
var x = div.offsetLeft + 25
var y = div.offsetTop + 25
var pt = {
x: x,
y: y
}
return pt
}
function getRightWall(div) {
var x = div.offsetLeft + div.clientWidth - 25
var y = div.offsetTop + div.clientHeight - 25
var pt = {
x: x,
y: y
}
return pt
}