From 78a0d483b8ccbc13dbecfb7cdec0ec7b3fb1822f Mon Sep 17 00:00:00 2001 From: Jake <jake.read@cba.mit.edu> Date: Fri, 24 May 2019 16:31:25 -0400 Subject: [PATCH] this for inputs and outputs, and now update vs. replace for link swapping --- README.md | 13 ++++-- hunks/input/string.js | 4 +- hunks/interface/button.js | 8 ++-- hunks/interface/logger.js | 2 +- hunks/link.js | 9 ++-- hunks/manager.js | 13 ++++-- hunks/template.js | 4 +- hunks/view.js | 96 +++++++++++++++++++++++---------------- typeset.js | 19 ++++---- view/vdef.js | 31 ++++++++++--- 10 files changed, 126 insertions(+), 73 deletions(-) diff --git a/README.md b/README.md index 5e5a0e5..ae7a048 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,17 @@ Native Cuttlefish 'Hunks' are given access to a DOM/div element, making them nic - towards a patch loading recipe, you need to consider the link update, that's next ... see if you can just complete the promise 'last' with the og state request, - needs a policy, -- check all hunks can load, - - do load-patch-by-promises -- do open-up-a-link-to-a-view recipe, + - load link, websocket, and change link to have new outputs and inputs + - replacedef / evaluatehunk / link, ok, we have to face this + - then you can save, then you can load + +ok, my thoughts on links adding inputs and outputs +- go atomic or build complexity: + instead of monolithic link, each link io is a hunk, and you can connect them each to the same data port +- would still like to + +- do open-up-a-link-to-a-view recipe, (req. leap of faith into new drawings, new view) - do refresh afterwards, find bootstrap nautilus ... - merge on nautilus a serial program ... the link updates, oy oy - ponyo diff --git a/hunks/input/string.js b/hunks/input/string.js index 93dc474..92238a3 100644 --- a/hunks/input/string.js +++ b/hunks/input/string.js @@ -11,10 +11,10 @@ function Strang() { this.description = 'click pow pow' - let thruput = new Input('string', 'thru') + let thruput = new Input('string', 'thru', this) this.inputs.push(thruput) - let stringOutput = new Output('string', 'string') + let stringOutput = new Output('string', 'string', this) this.outputs.push(stringOutput) // this.states.prefix = new State('string', 'prefix', 'LOG:') diff --git a/hunks/interface/button.js b/hunks/interface/button.js index 5f03464..b281895 100644 --- a/hunks/interface/button.js +++ b/hunks/interface/button.js @@ -9,14 +9,14 @@ import { Hunkify, Input, Output, State } from '../hunks.js' function Button() { Hunkify(this, 'Button') - let trigger = new Input('any', 'trigger') + let trigger = new Input('any', 'trigger', this) this.inputs.push(trigger) - let onclk = new Output('any', 'onclick') + let onclk = new Output('any', 'onclick', this) this.outputs.push(onclk) /* aspirationally - this.outputs.mousedown = new Output('event', 'mousedown') - this.outputs.mouseup = new Output('event', 'mouseup') + this.outputs.mousedown + this.outputs.mouseup */ let strang = new State('string', 'strng', 'start value') diff --git a/hunks/interface/logger.js b/hunks/interface/logger.js index 391084d..8fdac88 100644 --- a/hunks/interface/logger.js +++ b/hunks/interface/logger.js @@ -9,7 +9,7 @@ import { Hunkify, Input, Output, State } from '../hunks.js' function Logger() { Hunkify(this, 'Logger') - let tolog = new Input('any', 'tolog') + let tolog = new Input('any', 'tolog', this) this.inputs.push(tolog) let prefix = new State('string', 'prefix', 'LOG:') diff --git a/hunks/link.js b/hunks/link.js index f282a14..0bb5ae9 100644 --- a/hunks/link.js +++ b/hunks/link.js @@ -104,16 +104,19 @@ function Link() { inputList.onChange = (value) => { // OK: back up to this ... swapLists(value, true) - // if OK - inputList.set(value) // we have to report this ... this.mgr.evaluateHunk(this) + // if OK + inputList.set(value) } outputList.onChange = (value) => { swapLists(value, false) - outputList.set(value) this.mgr.evaluateHunk(this) + // this has to follow on, to complete the promise ? + // this necessitates that we write a manager-message-buffer on embedded, + // and breaks one-program-item-at-a-time rules + outputList.set(value) } /* --------------------------- ---------------------------- */ diff --git a/hunks/manager.js b/hunks/manager.js index 6ea08ee..b41deb4 100644 --- a/hunks/manager.js +++ b/hunks/manager.js @@ -89,6 +89,7 @@ function Manager() { let slat = bytes.length bytes.push(HK.CONNECTIONS) for(let cn of op.connections){ + console.log('conn', cn) bytes.push(HK.CONNECTION) bytes.push(cn.parent.ind) bytes.push(cn.findOwnIndex()) @@ -283,8 +284,13 @@ function Manager() { // this is a utility that hunks can use when they modify themsleves, - this.serializeAndSendHunk = (hunk) => { - let msg = [MK.HUNKALIVE] + this.serializeAndSendHunk = (hunk, replace) => { + let msg = [] + if(replace) { + msg.push(MK.HUNKREPLACE) + } else { + msg.push(MK.HUNKALIVE) + } serializeHunk(hunk, msg) writeMessage(msg) } @@ -302,11 +308,10 @@ function Manager() { } // one for updating hunks, - this.evaluateHunk = (hunk) => { // input and output lists have probably changed, so there's some work to do. // first, we reply with a new definition, - this.serializeAndSendHunk(hunk) + this.serializeAndSendHunk(hunk, true) // on a renewed definition, the view will remove all links associated. // now we need to walk inputs and outputs, and message about the links // that still exist diff --git a/hunks/template.js b/hunks/template.js index a4f55e5..dc0a41d 100644 --- a/hunks/template.js +++ b/hunks/template.js @@ -13,10 +13,10 @@ let State = Hunk.State function Name() { Hunkify(this, 'Name') - let inA = new Input('type', 'name') + let inA = new Input('type', 'name', this) this.inputs.push(inA) - let outB = new Output('type', 'name') + let outB = new Output('type', 'name', this) this.outputs.push(outB) let stateItem = new State('type', 'name') diff --git a/hunks/view.js b/hunks/view.js index 17f0a54..1e84df8 100644 --- a/hunks/view.js +++ b/hunks/view.js @@ -214,7 +214,7 @@ function View() { $(evt.target).append(' > requested ... ') msgbox.write(`requested one new ${item}`) this.requestAddHunk(item).then((def) => { - console.log('one hunk as promised', def) + //console.log('one hunk as promised', def) }).catch((err) => { this.changeContextTitle('error, see consoles') setTimeout(() => { @@ -474,49 +474,55 @@ function View() { return def } + let updateDef = (spec) => { + // update should change names, values, but not types or orders + // with an update, we maintain link topology + // with a replace, we wipe link topology, + // and manager is responsible for updating us with new links + console.log('updateDef with this spec:', spec) + let cdef = defs[spec.ind] + // check name, + if (spec.name !== cdef.name) { + cdef.updateName(spec.name) + } + // check states, + for (let st in spec.states) { + if (spec.states[st].value !== cdef.states[st].value) { + cdef.states[st].set(spec.states[st].value) + } + } + } // end update + let replaceDef = (spec) => { - // the old boy, - console.error('watch out, replacing definitions is pretty well untested') let od = defs[spec.ind] + // as a rule, when we replace defs, we unhook everything. + // the manager (in its wisdom) is responsible for following up by sending us + // links that are still alive, + // console.log('the od', od) + // so first rm those links (this won't properly be tested until program loading, i'd bet) + for (let ip in od.inputs) { + od.inputs[ip].disconnectAll() + } + for (let op in od.outputs) { + od.outputs[op].disconnectAll() + } + // that was considerate of the others, but this whole thing is just going to get rm'd, so outputs don't matter let mt = dt.readTransform(od.de) - // remove, and add new + // now we can *eliminate it* $(od.de).remove() - defs[spec.ind] = null - // new baybieee + delete defs[spec.ind] + // and replace it, let nd = new HunkDefinition(spec, this, dt, false) + // write-over and cut all connections, we'll receive new ones + // ok, ready to place and append, dt.writeTransform(nd.de, mt) + // add the def's domelement to the view, $(this.plane).append(nd.de) - // shoebox return + // and replace it in the list, defs[spec.ind] = nd - // delete, and then rekindle outputs (by our new spec) - for (let op of od.outputs) { - op.disconnectAll() - } - for(let op of nd.outputs){ - if (op.specConnections) { - for (let sc of op.specConnections) { - try { - op.connect(defs[sc[0]].inputs[sc[1]]) - } catch (err) { - console.err('cannot reconnect from spec', err) - msgbox.write(`err while trying to make links from spec`) - } - } - delete op.specConnections - } - } - // connect (by memory) and then eliminate old refs - for (let ip of od.inputs){ - for(let cn of ip.connections){ - // connections is an array of outputs, we can connect them by respective index - cn.connect(nd.inputs[ip.ind]) - } - } - // now we let them go, - for(let ip of od.inputs){ - ip.disconnectAll() - } + // and re-render this.drawLinks() + // occasionally useful, return nd } @@ -694,7 +700,7 @@ function View() { msgbox.write('err serializing state change request, see console for that type err') } promiseThis(msg, (stdef) => { - //console.log('promise returns for state change for def', stdef) + console.log('promise returns for state change for def', stdef) resolve(stdef) }, (errmsg) => { //console.log('promise rejects for state change bc error', errmsg) @@ -945,11 +951,25 @@ function View() { msgbox.write(`added a new hunk: ${spec.name}`) } else { if (verbose) console.log('replacing hunk at', spec.ind) - nd = replaceDef(spec) - msgbox.write(`replaced ${spec.name}_${spec.ind} with a new definition`) + nd = updateDef(spec) + msgbox.write(`updated ${spec.name}_${spec.ind} with a new definition`) } if (cbd) cbd.callback(nd) break + case MK.HUNKREPLACE: + // to add inputs or outputs, this is sent, all links are eliminated, + // and they are sent again by the manager + if (msgverbose) console.log('VIEW MSG is a hunk replacement') + let repSpec = specBySerial(msg, inc + 1, false) + if (defs[repSpec.ind] === undefined) { + console.error('received hunk replace for non existent hunk') + console.error('ere is the spec:', repSpec) + } else { + replaceDef(repSpec) + msgbox.write(`replaced ${repSpec.name}_${repSpec.ind} with a new definition`) + if (cbd) cbd.callback(nd) + } + break case MK.HUNKSTATECHANGE: if (msgverbose) console.log('VIEW MSG is a state change') let stchHnkInd = MSGS.readFrom(msg, inc + 1, 'uint16').item diff --git a/typeset.js b/typeset.js index b8de570..34626cc 100644 --- a/typeset.js +++ b/typeset.js @@ -375,16 +375,17 @@ const MK = { REQADDHUNK: 247, // (str) name REQNAMECHANGE: 246, HUNKALIVE: 245, // (hunkdescription): name, id, inputlist, outputlist, statelist - REQSTATECHANGE: 244, - HUNKSTATECHANGE: 243, - REQRMHUNK: 242, // (str) id - HUNKREMOVED: 241, // (str) id - REQADDLINK: 240, // (str) id, (str) outname, (str) id, (str) inname - LINKALIVE: 239, // (str) id, (str) outname, (str) id, (str) inname - REQRMLINK: 238, // (str) id, (str) outname, (str) id, (str) inname - LINKREMOVED: 237, // (str) id, (str) outname, (str) id, (str) inname + HUNKREPLACE: 244, + REQSTATECHANGE: 243, + HUNKSTATECHANGE: 242, + REQRMHUNK: 241, // (str) id + HUNKREMOVED: 240, // (str) id + REQADDLINK: 239, // (str) id, (str) outname, (str) id, (str) inname + LINKALIVE: 238, // (str) id, (str) outname, (str) id, (str) inname + REQRMLINK: 237, // (str) id, (str) outname, (str) id, (str) inname + LINKREMOVED: 236, // (str) id, (str) outname, (str) id, (str) inname // to id, - MSGID: 236 + MSGID: 235 } // hunk description keys, diff --git a/view/vdef.js b/view/vdef.js index 7f9816c..60888c1 100644 --- a/view/vdef.js +++ b/view/vdef.js @@ -109,7 +109,7 @@ function HunkDefinition(spec, view, dt, debug) { } $(this.de).append(odom) } - + // and states, if (spec.states.length > 0) { let sdom = $('<div>').addClass('states') for (let st in spec.states) { @@ -120,19 +120,36 @@ function HunkDefinition(spec, view, dt, debug) { $(this.de).append(sdom) } + // UPDATE Index this.newInd = (ind) => { this.ind = ind // and those titles, and ids ... $(this.de).attr('id', `${this.name}_${this.ind}`) $(title).text(`${this.name}`) for (let ip of this.inputs) { - ip.newParentInd() + ip.onNewParentInfo() + } + for (let op of this.outputs) { + op.onNewParentInfo() + } + for (let st of this.states) { + st.onNewParentInfo() + } + } + + // UPDATE Name + this.updateName = (newName) => { + this.name = newName + $(this.de).attr('id', `${this.name}_${this.ind}`) + $(title).text(`${this.name}`) + for (let ip of this.inputs) { + ip.onNewParentInfo() } for (let op of this.outputs) { - op.newParentInd() + op.onNewParentInfo() } for (let st of this.states) { - st.newParentInd() + st.onNewParentInfo() } } @@ -148,7 +165,7 @@ function InputDefinition(ipspec, ind, def, debug) { // a dom element this.de = $(`<li>${this.name} (${this.type})</li>`).addClass('input').get(0) this.de.id = `${this.parent.name}_${this.parent.ind}_input_${this.name}` - this.newParentInd = () => { + this.onNewParentInfo = () => { this.de.id = `${this.parent.name}_${this.parent.ind}_input_${this.name}` } // we also keep a list, @@ -179,7 +196,7 @@ function OutputDefinition(opspec, ind, def, view, dt, debug) { // a dom element this.de = $(`<li>(${this.type}) ${this.name}</li>`).addClass('output').get(0) this.de.id = `${this.parent.name}_${this.parent.ind}_output_${this.name}` - this.newParentInd = () => { + this.onNewParentInfo = () => { this.de.id = `${this.parent.name}_${this.parent.ind}_output_${this.name}` } // outputs handle all of the dragging-etc @@ -287,7 +304,7 @@ function StateDefinition(stspec, ind, def, view, debug) { // ok, this.de = $('<div>' + this.name + " (" + this.type + ")" + '</div>').addClass('stateItem').get(0) this.de.id = `${this.parent.name}_${this.parent.ind}_state_${this.name}` - this.newParentInd = () => { + this.onNewParentInfo = () => { this.de.id = `${this.parent.name}_${this.parent.ind}_state_${this.name}` } // ui for these ... we can just cover the basics of js types because yonder serializations -- GitLab