Commit a6d9e8ab authored by Jake Read's avatar Jake Read
Browse files

nearly hooking up again

parent 9572e704
......@@ -15,9 +15,34 @@ This project serves the developement environment / api we use to write and repre
## For MW
- GIFS
- load a program
- drag around
- zoom in and out
- add a module
- hook events up
- rm events
- rm modules
- change settings
- *don't forget*
- onload, load state...
- when hooking back to server, server.emitChange(key) ... from writeStateObject
- does state copy over successfully from loaded mod?
- this spiral
- entire programs read into UI
- hook sever-and-back
- for event hookup
- for module add
- for state push-down
- re-hook state push-down
- can req and add to program new modules
- can req to load new program
- can req to save this program
- next spiral
- programs come in chunk-wise and get placed
- programs are modules are heirarchical
- fundament
- the basic unit is a .js file having inputs, outputs, and state objects
......
// client side js for atkapi reconf
//
//
// new node controller / VIEW
//
// client.js
//
//
// Jake Read at the Center for Bits and Atoms
// (c) Massachusetts Institute of Technology 2018
//
// This work may be reproduced, modified, distributed, performed, and
// displayed for any purpose, but must acknowledge the mods
// project. Copyright is retained and must be preserved. The work is
// provided as is; no warranty is provided, and users accept all
// liability.
/*
// client globals
CLIENT GLOBALS ---------------------------------------------------
var reps = new Array()
*/
var sckt = {}
var lastPos = {}
var lastPos = { x: 10, y: 10 }
// drawing / div-ing
var wrapper = {}
// client fns
/*
STARTUP ---------------------------------------------------
*/
window.onload = function() {
svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
svg.style.position = 'absolute'
svg.style.left = 0
svg.style.top = 0
svg.style.zIndex = 0
svg.style.overflow = 'visible'
svg.setAttribute('width', 2)
svg.setAttribute('height', 2)
svg.setAttribute('id', 'svg')
svg.setAttribute('width', '100%')
svg.setAttribute('height', '100%')
document.body.appendChild(svg)
wrapper = document.createElement('div')
wrapper.id = 'wrapper'
document.body.append(wrapper)
const socket = new WebSocket('ws://localhost:8081')
socket.onopen = function(evt) {
// pass to global ref
sckt = this
// say hello
socketSend('console', 'hello server')
console.log('socket open')
// ask for the current program
socketSend('get current program', '')
// main socket entry point
this.onmessage = (evt) => {
socketRecv(evt)
}
// others
this.onerror = (err) => {
console.log('socket error', err)
}
this.onclose = (evt) => {
console.log('socket closed', evt)
sckt = null
}
}
}
/*
RECV / SEND PORTALS ---------------------------------------------------
*/
function socketSend(type, data) {
var msg = {
......@@ -22,21 +90,6 @@ function socketSend(type, data) {
sckt.send(JSON.stringify(msg))
}
// get json menu item and render
// and ask for module at /obj/key
oncontextmenu = function(evt) {
if (sckt) {
lastPos.X = evt.pageX
lastPos.Y = evt.pageY
socketSend('get menu', '')
} else {
// socket brkn
location.reload()
}
// prevents event bubbling
return false
}
function socketRecv(evt) {
var recv = JSON.parse(evt.data)
var type = recv.type
......@@ -47,39 +100,113 @@ function socketRecv(evt) {
case 'console':
console.log('RECV CONSOLE:', data)
break
case 'put menu':
buildMenu(data)
case 'put module menu':
console.log('RECV MENU')
heapSendsModuleMenu(data)
break
case 'add reps':
case 'put program':
console.log('RECV PROGRAM')
addReps(data)
break
case 'add rep':
addRep(data)
break
case 'change rep':
changeRep(data)
break
case 'change state':
changeState(data)
heapSendsNewProgram(data)
break
case 'put module':
console.log('RECV NEW MODULE')
heapSendsNewModule(data)
break
case 'put state':
console.log('RECV STATE CHANGE')
heapSendsNewState(data)
break
default:
console.log('ERR recv with non recognized type', recv)
break
}
}
/*
MISC ---------------------------------------------------
function addReps(reps) {
*/
// return ul element with name and alt and link?
function heapSendsModuleMenu(tree) {
var menuDom = document.createElement('div')
menuDom.id = 'menu'
menuDom.style.left = lastPos.x + 'px'
menuDom.style.top = lastPos.y + 'px'
for (key in tree) {
var ul = document.createElement('ul')
ul.innerHTML = key.toString()
for (subkey in tree[key]) {
var li = document.createElement('li')
var path = tree[key][subkey].path
li.innerHTML = subkey.toString()
li.id = path
li.addEventListener('click', function(evt) {
var data = this.id
socketSend('add module', data)
wrapper.removeChild(document.getElementById('menu'))
})
ul.appendChild(li)
}
menuDom.appendChild(ul)
}
wrapper.append(menuDom)
function rmListener(evt) {
var findMenu = document.getElementById('menu')
if (findMenu !== null && findMenu.id == 'menu') {
wrapper.removeChild(findMenu)
}
}
document.addEventListener('click', rmListener)
}
/*
HEAP -> SERVER ---------------------------------------------------
*/
// always a rep, tho
var program = {}
// re-writes the program, adds a description,
// and loads multiple representations of modules to the view
function heapSendsNewProgram(prgm) {
// whole hearted replace
// hello for bugs when we lay this on top of something else
program = prgm
// 1st we want to git rm old shit ...
// when adding links, we'll have to add all and then draw links
for (rep in reps) {
addRep(reps[rep])
console.log(program)
for (mdlName in program.modules) {
addRepToView(program.modules[mdlName])
}
redrawLinks()
}
function heapSendsNewModule(mdl){
if(program.description == null){
program.description.name = 'unnamed program'
}
if(program.modules == null){
program.modules = {}
}
addRepToView(mdl)
program.modules[mdl.description.id] = mdl
redrawLinks()
}
// write html from json representation
function addRep(rep) {
// writes DOM elements to represent the module, appends to the wrapper
// and appends to the rep object a .ui object
// containing references to those DOM objects
function addRepToView(rep) {
// a div to locate it
var domElem = document.createElement('div')
// dif. color for hardwares ?
......@@ -87,8 +214,8 @@ function addRep(rep) {
if (rep.description.isHardware) {
domElem.classList.add('hardware')
}
domElem.style.left = lastPos.X + 'px'
domElem.style.top = lastPos.Y + 'px'
domElem.style.left = lastPos.x + 'px'
domElem.style.top = lastPos.y + 'px'
// more html: the title
var title = document.createElement('div')
......@@ -97,8 +224,8 @@ function addRep(rep) {
title.alt = rep.description.alt
domElem.appendChild(title)
// make UI elements
// place in pos if info present
// the rep.ui object will store references to the module's related DOM elements
if (rep.ui != null) {
if (rep.ui.left != null) {
domElem.style.left = rep.ui.left + 'px'
......@@ -108,8 +235,8 @@ function addRep(rep) {
}
} else {
rep.ui = {}
rep.ui.left = lastPos.X
rep.ui.top = lastPos.Y
rep.ui.left = lastPos.x
rep.ui.top = lastPos.y
}
rep.ui.domElem = domElem
......@@ -164,7 +291,7 @@ function addRep(rep) {
document.addEventListener('mousemove', domElemMouseMove)
domElem.onmouseup = function() {
title.onmouseup = function() {
rep.ui.left = parseInt(domElem.style.left, 10)
rep.ui.top = parseInt(domElem.style.top, 10)
putUi(rep)
......@@ -173,55 +300,12 @@ function addRep(rep) {
}
}
console.log('REP AT ADD', rep)
// ADD TO LISTS, DOC
reps.push(rep)
wrapper.appendChild(rep.ui.domElem)
putUi(rep)
}
function redrawLinks() {
while (svg.firstChild) {
svg.removeChild(svg.firstChild)
}
// rm old links then redraw everything
//console.log('now drawing links')
for (var i = 0; i < reps.length; i++) {
var rep = reps[i]
for (key in rep.outputs) {
var output = rep.outputs[key]
var outputUi = rep.ui.outputs[key]
for (input in output.calls) {
var toId = output.calls[input].parentId
var toKey = output.calls[input].key
var inputUi = reps[toId].ui.inputs[toKey]
var outPos = getOutputArrow(outputUi)
var inPos = getInputArrow(inputUi)
var bz = newBezier(outPos.x, outPos.y, inPos.x, inPos.y)
}
}
}
}
function changeRep(data) {
console.log('CHANGE REP', data)
var rep = reps[data.id]
for (var key in data) {
if (key == 'outputs') {
rep.outputs = data.outputs
}
}
redrawLinks()
}
// update state from server to UI
function changeState(data) {
function heapSendsNewState(data) {
console.log('HEAP SENDS CHANGE STATE IN MODULE', data)
var rep = reps[data.id]
for (var key in data.state) {
if (data.state[key].isButton) {
......@@ -239,13 +323,11 @@ function changeState(data) {
}
}
function isStateKey(key) {
if (key.indexOf('_') == 0 || key == 'emitters' || key == 'onChange' || key == 'emitChange') {
return false
} else {
return true
}
}
/*
UI -> HEAP ---------------------------------------------------
*/
// push new state from UI to server
function putState(rep) {
......@@ -269,42 +351,45 @@ function putUi(rep) {
socketSend('put ui', data)
}
var clkState = false
var oClk = {}
var tmpBz = {}
/*
// input / output click handling
function evtConnectHandler(clk) {
if (!clkState) {
// first click
oClk = clk
clkState = true
UTILITIES? ---------------------------------------------------
*/
function isStateKey(key) {
if (key.indexOf('_') == 0 || key == 'emitters' || key == 'onChange' || key == 'emitChange') {
return false
} else {
// second click
var tClk = clk
console.log(oClk, tClk)
var x1 = parseInt(oClk.evt.target.offsetParent.style.left, 10) + oClk.evt.target.offsetLeft + oClk.evt.target.clientWidth
var y1 = parseInt(oClk.evt.target.offsetParent.style.top, 10) + oClk.evt.target.offsetTop + oClk.evt.target.clientHeight / 2
var x2 = parseInt(tClk.evt.target.offsetParent.style.left, 10) + tClk.evt.target.offsetLeft
var y2 = parseInt(tClk.evt.target.offsetParent.style.top, 10) + tClk.evt.target.offsetTop + tClk.evt.target.clientHeight / 2
var bz = newBezier(x1, y1, x2, y2)
clkState = false
return true
}
}
console.log('connect', oClk.rep.id, oClk.name, 'to', tClk.rep.id, tClk.name)
var data = {
from: {
id: oClk.rep.id,
output: oClk.name
},
to: {
id: tClk.rep.id,
input: tClk.name
function redrawLinks() {
// probably not a great way to do this, we're removing everything
// svg -rm -r
while (svg.firstChild) {
svg.removeChild(svg.firstChild)
}
// redraw thru all links, just look at reps
for(mdlName in program.modules){
var mdlRep = program.modules[mdlName]
for(key in mdlRep.outputs){
var output = mdlRep.outputs[key]
var outputUi = mdlRep.ui.outputs[key]
for (input in output.calls) {
var toId = output.calls[input].parentId
var toKey = output.calls[input].key
var inputUi = program.modules[toId].ui.inputs[toKey]
var outPos = getOutputArrow(outputUi)
var inPos = getInputArrow(inputUi)
var bz = newBezier(outPos.x, outPos.y, inPos.x, inPos.y)
}
}
socketSend('put link', data)
}
}
// need top level rep of program - nice to think of how to handle heirarchy later on? tl rep is internal rep ... is same ?
// how to handle movement of rep, incl. svg - goes with moving mouse after 1st click: svg lives 'in' rep ?
......@@ -315,99 +400,58 @@ function evtConnectHandler(clk) {
var svgns = 'http://www.w3.org/2000/svg'
var svg = {}
// 651
// 1554
/*
var crv = {}
document.addEventListener('mousemove', function(evt) {
modifyBezier(crv, 0, 0, evt.pageX, evt.pageY)
})
*/
UI EVENTS ---------------------------------------------------
// return ul element with name and alt and link?
function buildMenu(tree) {
var menuDom = document.createElement('div')
menuDom.id = 'menu'
menuDom.style.left = lastPos.X + 'px'
menuDom.style.top = lastPos.Y + 'px'
for (key in tree) {
var ul = document.createElement('ul')
ul.innerHTML = key.toString()
for (subkey in tree[key]) {
var li = document.createElement('li')
var path = tree[key][subkey].path
li.innerHTML = subkey.toString()
li.id = path
li.addEventListener('click', function(evt) {
var data = this.id
socketSend('add module', data)
wrapper.removeChild(document.getElementById('menu'))
})
ul.appendChild(li)
}
menuDom.appendChild(ul)
}
wrapper.append(menuDom)
*/
function rmListener(evt) {
var findMenu = document.getElementById('menu')
if (findMenu !== null && findMenu.id == 'menu') {
wrapper.removeChild(findMenu)
}
// get json menu item and render
// and ask for module at /obj/key
oncontextmenu = function(evt) {
if (sckt) {
lastPos.x = evt.pageX
lastPos.y = evt.pageY
socketSend('get module menu', '')
} else {
// socket brkn, reload page
location.reload()
}
document.addEventListener('click', rmListener)
// prevents event bubbling
return false
}
// init & hookup
window.onload = function() {
svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
svg.style.position = 'absolute'
svg.style.left = 0
svg.style.top = 0
svg.style.zIndex = 0
svg.style.overflow = 'visible'
svg.setAttribute('width', 2)
svg.setAttribute('height', 2)
svg.setAttribute('id', 'svg')
svg.setAttribute('width', '100%')
svg.setAttribute('height', '100%')
document.body.appendChild(svg)
wrapper = document.createElement('div')
wrapper.id = 'wrapper'
document.body.append(wrapper)
const socket = new WebSocket('ws://localhost:8081')
var clkState = false
var oClk = {}
var tmpBz = {}
socket.onopen = function(evt) {
// pass to global ref
sckt = this
// say hello
socketSend('console', 'hello server')
console.log('socket open')
// main socket entry point
this.onmessage = (evt) => {
socketRecv(evt)
}
// others
this.onerror = (err) => {
console.log('socket error', err)
}
this.onclose = (evt) => {
console.log('socket closed', evt)
sckt = null
// input / output click handling
function evtConnectHandler(clk) {
if (!clkState) {
// first click
oClk = clk
clkState = true
} else {
// second click
var tClk = clk
//console.log(oClk, tClk)
var x1 = parseInt(oClk.evt.target.offsetParent.style.left, 10) + oClk.evt.target.offsetLeft + oClk.evt.target.clientWidth
var y1 = parseInt(oClk.evt.target.offsetParent.style.top, 10) + oClk.evt.target.offsetTop + oClk.evt.target.clientHeight / 2
var x2 = parseInt(tClk.evt.target.offsetParent.style.left, 10) + tClk.evt.target.offsetLeft
var y2 = parseInt(tClk.evt.target.offsetParent.style.top, 10) + tClk.evt.target.offsetTop + tClk.evt.target.clientHeight / 2
//var bz = newBezier(x1, y1, x2, y2)
clkState = false
//console.log('connect', oClk.rep.description.id, oClk.name, 'to', tClk.rep.description.id, tClk.name)
var data = {
from: {
id: oClk.rep.description.id,
output: oClk.name
},
to: {
id: tClk.rep.description.id,
input: tClk.name
}
}
socketSend('put link', data)
}
}
/*
- add inputs and outputs
- ui for link inputs and outputs
- .. hold svg's in div of ui element rep.ui.domElement - also track endpts there, write tiny svg class ? then .onmove etc ties through to all elements ?
*/
\ No newline at end of file
}
\ No newline at end of file
......@@ -2,68 +2,56 @@
function writeStateRep(container, rep, key) {
var variable = rep.state[key]
if (variable.isButton) {
console.log('BUTTON!')
var li = document.