Commit 327b496b authored by Jake Read's avatar Jake Read

working through state management

parent 70057d15
......@@ -26,9 +26,10 @@ This project serves the developement environment / api we use to write and repre
- change settings
- right now
- add module
- l for load
- s for save
- push state down & up
- note below :
- not actually setting, do node main, change ms, watch console
- some wholistic test ...
- *don't forget*
- onload, load state...
......@@ -84,15 +85,18 @@ Modules-that-represent-remote-computing also have
To assemble a representation of these, we want to have a kind of 'netlist' that, for convenience, we'll treat like a JSON object. We want heirarchy, so consider the representation having 'top-level' outputs / inputs / state as well ?
## Programming Notes
### 15 Minute Tasks
- @ views.js, uiRequestModuleMenu and uiRequestProgramMenu don't properly build trees from folder structure. similarly, reciprical fn's in client.js do the same
- @ these load / save functions could also reach into the modules' source to retrieve their proper names, as spec'd in description ...
## Programming Notes
- 's' for save program uses hack-asf DOM alert to ask for path
title bar
L for load prgmem
M for add module
- once we can plan gcode sequence, work towards more
- better hardware abstraction, i.e.
stepper.port = bridge.port('0,1')
......
......@@ -101,9 +101,13 @@ function socketRecv(evt) {
console.log('RECV CONSOLE:', data)
break
case 'put module menu':
console.log('RECV MENU')
console.log('RECV MODULE MENU')
heapSendsModuleMenu(data)
break
case 'put program menu':
console.log('RECV PRG MENU')
heapSendsProgramMenu(data)
break
case 'put program':
console.log('RECV PROGRAM')
heapSendsNewProgram(data)
......@@ -112,10 +116,16 @@ function socketRecv(evt) {
console.log('RECV NEW MODULE')
heapSendsNewModule(data)
break
case 'put state':
case 'put module change':
console.log('RECV MODULE CHANGE')
heapSendsModuleChange(data)
break
case 'put state change':
console.log('RECV STATE CHANGE')
heapSendsNewState(data)
heapSendsStateChange(data)
break
case 'restart':
location.reload()
default:
console.log('ERR recv with non recognized type', recv)
break
......@@ -129,9 +139,10 @@ MISC ---------------------------------------------------
*/
// return ul element with name and alt and link?
// TODO: not properly a tree, see note @ reciprocal fn in views.js
function heapSendsModuleMenu(tree) {
var menuDom = document.createElement('div')
menuDom.id = 'menu'
menuDom.id = 'moduleMenu'
menuDom.style.left = lastPos.x + 'px'
menuDom.style.top = lastPos.y + 'px'
for (key in tree) {
......@@ -145,7 +156,7 @@ function heapSendsModuleMenu(tree) {
li.addEventListener('click', function(evt) {
var data = this.id
socketSend('put module', data)
wrapper.removeChild(document.getElementById('menu'))
wrapper.removeChild(document.getElementById('moduleMenu'))
})
ul.appendChild(li)
}
......@@ -154,10 +165,42 @@ function heapSendsModuleMenu(tree) {
wrapper.append(menuDom)
function rmListener(evt) {
var findMenu = document.getElementById('menu')
if (findMenu !== null && findMenu.id == 'menu') {
var findMenu = document.getElementById('moduleMenu')
if (findMenu !== null && findMenu.id == 'moduleMenu') {
wrapper.removeChild(findMenu)
}
evt.target.removeEventListener(evt.type, arguments.callee)
}
document.addEventListener('click', rmListener)
}
function heapSendsProgramMenu(tree) {
var menuDom = document.createElement('div')
menuDom.id = 'programMenu'
menuDom.style.left = lastPos.x + 'px'
menuDom.style.top = lastPos.y + 'px'
for(key in tree){
var li = document.createElement('li')
var path = tree[key].path
li.innerHTML = key.toString()
li.id = path
li.addEventListener('click', function(evt){
var data = this.id
socketSend('load program', data)
wrapper.removeChild(document.getElementById('programMenu'))
})
menuDom.appendChild(li)
}
wrapper.append(menuDom)
function rmListener(evt){
var findMenu = document.getElementById('programMenu')
if(findMenu !== null && findMenu.id == 'programMenu'){
wrapper.removeChild(findMenu)
}
// rm this listner...
evt.target.removeEventListener(evt.type, arguments.callee)
}
document.addEventListener('click', rmListener)
......@@ -201,7 +244,6 @@ function heapSendsNewModule(mdl) {
redrawLinks()
}
// 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
......@@ -220,23 +262,19 @@ function addRepToView(rep) {
// more html: the title
var title = document.createElement('div')
title.className = 'modname'
title.innerHTML = rep.description.name + ' id: ' + rep.id
title.innerHTML = rep.description.id
title.alt = rep.description.alt
domElem.appendChild(title)
var uiSetFlag
// place in pos if info present
// the rep.ui object will store references to the module's related DOM elements
console.log(rep.description.position)
if (rep.description.position != null) {
console.log("FOUND POS")
uiSetFlag = false
if (rep.description.position.left != null) {
console.log("FOUND LEFT")
domElem.style.left = rep.description.position.left + 'px'
}
if (rep.description.position.top != null) {
console.log("FOUND TOP")
domElem.style.top = rep.description.position.top + 'px'
}
} else {
......@@ -317,24 +355,35 @@ function addRepToView(rep) {
}
}
// update state from server to UI
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].type == 'button') {
console.log('BUTTON UPDATE')
} else if (data.state[key].type == 'multiline') {
console.log('MULTILINE UPDATE')
rep.ui.state[key].value = data.state[key].value
} else {
// two ?
rep.state[key] = data.state[key]
if (rep.ui.state[key] != null) {
rep.ui.state[key].value = rep.state[key]
}
function heapSendsModuleChange(data){
console.log(data)
// data should be rep of changed module
var rep = program.modules[data.description.id]
// we want a general case, but for now we know we're looking for
// new event hookups or new state items
for(key in rep.outputs){
var output = rep.outputs[key]
if(output.calls.length !== data.outputs[key].calls.length){
rep.outputs = data.outputs
}
}
// ok
for(key in rep.state){
var stateItem = rep.state[key]
if(stateItem != data.state[key]){
stateItem = data.state[key]
rep.ui.state[key].value = data.state[key]
}
}
// wreckless or wonderful?
//clear(rep)
redrawLinks()
}
// update state from server to UI
function heapSendsStateChange(data) {
console.log('HEAP SENDS CHANGE STATE IN MODULE', data)
heapSendsModuleChange(data)
}
/*
......@@ -344,11 +393,16 @@ UI -> HEAP ---------------------------------------------------
*/
// push new state from UI to server
function putState(rep) {
function putState(rep, key) {
// ship it all home: not perfect, but hey
var data = {
id: rep.id,
state: rep.state
description: {
id: rep.description.id
},
state: {
key: key,
val: rep.state[key]
}
}
socketSend('put state', data)
}
......@@ -419,7 +473,7 @@ var svg = {}
/*
UI EVENTS ---------------------------------------------------
UI EVENTS ---------------------------------------------------------------------
*/
......@@ -455,7 +509,7 @@ document.onkeydown = function(evt){
socketSend('save program', path)
break
case 'l':
console.log('LOADID')
socketSend('get program menu', '')
break
case 'm':
socketSend('get module menu', '')
......
......@@ -14,7 +14,7 @@ function writeStateRep(container, rep, key) {
} else {
rep.state[key].isPressed = true
}
putState(rep)
putState(rep, key)
})
container.appendChild(li)
return li
......@@ -30,7 +30,7 @@ function writeStateRep(container, rep, key) {
txtArea.value = variable.value
txtArea.addEventListener('change', function() {
rep.state[key].value = txtArea.value
putState(rep)
putState(rep, key)
})
li.appendChild(txtArea)
container.appendChild(li)
......@@ -46,7 +46,7 @@ function writeStateRep(container, rep, key) {
input.value = variable
input.addEventListener('change', function() {
rep.state[key] = input.value
putState(rep)
putState(rep, key)
})
li.appendChild(input)
container.appendChild(li)
......@@ -60,7 +60,7 @@ function writeStateRep(container, rep, key) {
input.value = variable.toString()
input.addEventListener('change', function() {
rep.state[key] = parseFloat(input.value)
putState(rep)
putState(rep, key)
})
li.appendChild(input)
container.appendChild(li)
......@@ -79,7 +79,7 @@ function writeStateRep(container, rep, key) {
array[index] = parseFloat(element)
})
rep.state[key] = arr
putState(rep)
putState(rep, key)
})
li.appendChild(input)
container.appendChild(li)
......
......@@ -98,9 +98,16 @@ li:active{
background-color: #d1d1d1;
}
#menu {
#moduleMenu {
position: absolute;
width: 245px;
padding: 10px;
background-color: #303030;
}
#programMenu {
position: absolute;
width: 245px;
padding: 10px;
background-color: #303030;
}
\ No newline at end of file
......@@ -79,11 +79,11 @@ function isStateKey(key) {
}
// a coupl'a fancy UI state hooks
function Button(label) {
function Button(label, onClick) {
var button = {
type: 'button',
isPressed: false,
label: label
label: label,
onClick: onClick
}
return button
......
{
"description": {
"name": "tstprgmem",
"counter": 4
},
"modules": {
"gate-1": {
"description": {
"id": "gate-1",
"name": "gate",
"alt": "in ... out",
"path": "./src/util/gate.js",
"position": {
"left": 10,
"top": 10
}
},
"inputs": {
"thru": {
"accepts": "any"
}
},
"outputs": {
"out": {
"emits": "any",
"calls": [
{
"parentId": "delay-2",
"key": "thru"
},
{
"parentId": "logger-3",
"key": "thru"
},
{
"parentId": "delay-4",
"key": "thru"
}
]
}
},
"state": {
"toggle": {
"type": "button",
"isPressed": false,
"label": "Open / Close"
},
"message": "closed"
}
},
"delay-2": {
"description": {
"id": "delay-2",
"name": "delay",
"alt": "in ... out",
"path": "./src/util/delay.js",
"position": {
"left": 132,
"top": 225
}
},
"inputs": {
"thru": {
"accepts": "any"
}
},
"outputs": {
"out": {
"emits": "any",
"calls": [
{
"parentId": "logger-3",
"key": "thru"
}
]
}
},
"state": {
"ms": 100
}
},
"logger-3": {
"description": {
"id": "logger-3",
"name": "logger",
"alt": "in ... out to console",
"path": "./src/util/log.js",
"position": {
"left": 123,
"top": 367
}
},
"inputs": {
"thru": {
"accepts": "any"
}
},
"outputs": {
"throughput": {
"emits": "any",
"calls": []
}
},
"state": {
"prefix": "LOGGER:",
"message": "---"
}
},
"delay-4": {
"description": {
"id": "delay-4",
"name": "delay",
"alt": "in ... out",
"path": "./src/util/delay.js",
"position": {
"left": 721,
"top": 309
}
},
"inputs": {
"thru": {
"accepts": "any"
}
},
"outputs": {
"out": {
"emits": "any",
"calls": []
}
},
"state": {
"ms": 100
}
}
}
}
\ No newline at end of file
......@@ -87,12 +87,15 @@ function socketRecv(evt) {
case 'get module menu':
uiRequestModuleMenu()
break
case 'get program menu':
uiRequestProgramMenu()
break
case 'load program':
uiRequestLoadProgram(data)
break
case 'save program':
uiRequestSaveProgram(data)
break
break
case 'put module':
uiRequestNewModule(data)
break
......@@ -148,6 +151,9 @@ function uiRequestCurrentProgram() {
socketSend('put program', prgRep)
}
// TODO: proper heirarchy, with both of these ...
function uiRequestModuleMenu() {
var availableSourceRep = {}
var dir = fs.readdirSync('./src')
......@@ -166,24 +172,48 @@ function uiRequestModuleMenu() {
socketSend('put module menu', availableSourceRep)
}
function uiRequestProgramMenu() {
var availableProgramRep = {}
var paths = fs.readdirSync('./programs')
for (i in paths) {
if (paths[i].slice(-5) === '.json') {
var name = paths[i].slice(0, -5)
var path = './programs/' + paths[i]
availableProgramRep[paths[i]] = {
name: name,
path: path
}
}
}
socketSend('put program menu', availableProgramRep)
}
/*
UI -> HEAP HANDLES ---------------------------------------------------
*/
function uiRequestLoadProgram(data){
function uiRequestLoadProgram(data) {
console.log('UI REQUEST TO OPEN NEW PROGRAM', data)
// gonna tear it doooown, maybe just kick page afterwards to restart it?
program = null
program = Programs.open(data)
socketSend('restart', '')
}
function uiRequestSaveProgram(data){
function uiRequestSaveProgram(data) {
console.log('UI REQUEST TO SAVE PROGRAM', data)
// is data a path? add .json ?
if(!data.includes('.json')){
data = data + '.json'
if (data) {
if (!data.includes('.json')) {
data = data + '.json'
}
path = 'programs/' + data
Programs.save(program, path)
socketSend('console', ('saved program at' + path))
}
path = 'programs/' + data
Programs.save(program, path)
}
function uiRequestNewModule(data) {
......@@ -196,11 +226,54 @@ function uiRequestNewModule(data) {
function uiRequestStateChange(data) {
console.log('UI REQUEST CHANGE STATE IN MODULE', data)
// and don't forget state.obj.emit
// there should only be one !
var id = data.description.id
var key = data.state.key
var val = data.state.val
var mdlState = program.modules[id].state
console.log('mdlState', mdlState)
var mdlStateItem = program.modules[id].state[key]
console.log('mdlStateItem', mdlStateItem)
if (mdlStateItem) {
switch (mdlState.type) {
case 'button':
mdlStateItem.onClick()
break
case 'multiline':
mdlStateItem.value = val
mdlState.emitChange(key)
break
default:
mdlStateItem = val
mdlState.emitChange(key)
break
}
} else {
console.log("ERR no state key,", key, "found here", data)
}
console.log('mdlStateItem', mdlStateItem)
console.log(program.modules[id])
}
function uiRequestLinkChange(data) {
console.log('UI REQUEST ADD EVENT LINK', data)
var fromId = data.from.id
var outputName = data.from.output
var toId = data.to.id
var inputName = data.to.input
// HERE: check if hooked already
var fromMdl = program.modules[fromId]
var toMdl = program.modules[toId]
fromMdl.outputs[outputName].attach(toMdl.inputs[inputName])
var nRep = Reps.makeFromModule(fromMdl)
socketSend('put module change', nRep)
}
function uiRequestUiChange(data) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment