// 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 }