diff --git a/LOG.md b/LOG.md index 6db4714bbe5e4bc12d06383db0a554e427a4f87f..f56fd6dcb719149e262228959298ce7f47b964e7 100644 --- a/LOG.md +++ b/LOG.md @@ -2,7 +2,11 @@ ### Dev Rebuilding 2019 12 10 -OK, kind of last day to pin this together. I think to start, I'll add that button back to the link, then try to run the 'expandlink' routine again. Then I can see about my two views, and how to assemble these layers. +OK, kind of last day to pin this together. I think to start, I'll add that button back to the link, then try to run the 'expandlink' routine again. Then I can see about my two views, and how to assemble these layers. + +Some progress here, I'm expanding links. To signal that ahn link has another-end, I have linkdef.contains ... + +Last question is how to recover the view -> links relationships, i.e. the link.contains is our hookup at the graph level, then the link.contains.plane's existence determines whether / not we are rendering it. To transition between rendering and not-rendering, we create and destroy this plane. ### Dev Rebuilding 2019 12 09 diff --git a/core/scope.js b/core/scope.js index f138f6944c41c7a420d18da9df3ce260b1c634a8..0dff360a3490bd3777b0aa428cea51f1a6b3c387 100644 --- a/core/scope.js +++ b/core/scope.js @@ -274,23 +274,16 @@ export default function Scope(wrapper, tlv) { this.check = () => { // check levels recursively, - checkView(tlv) - for(let def of tlv.defs){ - // def.contains is a hook to the view object that operates the MVC for the context - // on the other side of this link ... - if(def.contains){ - if(!def.contains.plane){ - def.contains.plane = $('<div>').addClass('subplane').attr('id', `${def.name}_plane`).get(0) - dt.writeTransform(def.contains.plane, { - x: -800, - y: 0 - }) - $(plane).append(def.contains.plane) - // add this, as a block, to that link-def ? + let recursor = (view) => { + checkView(view) + for(let def of view.defs){ + if(def.contains){ + if(!def.contains.plane) continue + recursor(def.contains) } - checkView(def.contains) } } + recursor(tlv) } // yeah ... so we redraw things now, yeah? how do what handles -> which handles? diff --git a/hunks/view.js b/hunks/view.js index 0803d3de95e3b1c3421e40e0c9490d714d581f29..036fb517d3731ef9c777e986e9ce7ccb099174f9 100644 --- a/hunks/view.js +++ b/hunks/view.js @@ -389,6 +389,7 @@ function View() { console.error('a bad time was had, with a new definition arriving w/ link topology out of order') console.error(err) } + return def } // end update let replaceDef = (spec) => { @@ -726,6 +727,7 @@ function View() { // wipes current state from remote, polls from zero this.refresh = () => { + console.log('REFRESH') // well, I won't say it's clean or beautiful, but we are interested in keeping the // positions of things intact, so I am here for this: let psns = [] @@ -742,6 +744,7 @@ function View() { // wipe ya docs, and ask yonder manager for a complete description // setting ahn JS array's length to zero effectively erases it, unless // there are other references to them someplace ... then GC will keepalive + defs.length = 0 // here we can set flag for complete redraw, as we've just tabula'd the table, setCompleteRedraw() // hello first, @@ -902,8 +905,6 @@ function View() { let mergeHunkList = (patch, debug) => { return new Promise(async (resolve, reject) => { - // ensure we are up-to-date w/ current state, - await this.refresh() // now wrip em out let loadedDefsList = [] let nh = patch.hunks.length @@ -997,7 +998,9 @@ function View() { }) } - this.reinstate = (system, debug) => { + this.reinstate = async (system, debug) => { + // ensure we are up-to-date w/ current state, + await this.refresh() return new Promise((resolve, reject) => { mergeHunkList(system, debug).then(() => { console.log('resolved hunk list, links now') @@ -1017,24 +1020,50 @@ function View() { /* ------------------------- PIPING -------------------------- */ /* --------------------------- ---------------------------- */ + // return inputdef-to-which connected, + // assume always 1d path, bail if not + this.trace = (opdef) => { + // for now we are 1d, cannot traverse links, + if(opdef.conn.length !== 1) return + return opdef.conn[0] + } + // for any link in any context, build some route up to // some view that exists in the browser level // and return ... ? this.routelink = (link) => { // oof async so nice return new Promise(async (resolve, reject) => { - // *and* need to do some intelligent work to trace our way up to - // the top level view, where we would be able to instate a view ... - // *should* check if trace up exists, but basically: - try { - let vdef = await this.requestAddHunk('view') - // almost definitely the easiest way to handle this is to give our local defs - // a .hunk, this way (1) we know they're local - the view will always be local - - await this.requestAddLink(vdef.outputs[0], link.inputs[1]) - await this.requestAddLink(link.inputs[1], vdef.outputs[0]) - resolve(vdef.hunk) - } catch (err) { - reject(err) + /* + ok, this thing either (1) finds the view that this link is connected to (write / use a trace fn) + or ! it builds that route, do this - + at the moment, your bug / curiosity is that the post-refresh messages aren't 'fresh' - they're registering + as updates - however, we should be able to assume that a view refresh really wipes the whole thing, + also! you're adding multiple views. add only one view, see if problem persists, continue + -> might have been that you were calling refresh on the new-view, it was messaging the old-view, due + to graph double-up coonnectivity + */ + // ok, + let tr = this.trace(link.outputs[1]) + if(tr){ + if(tr.parent.type == 'view'){ + resolve(tr.parent.hunk) + } else { + console.error('need to write case for this, likely that we are link->link here') + reject('no link traversing trace yet, pls write') + } + } else { + try { + let vdef = await window.tlv.requestAddHunk('view') + // almost definitely the easiest way to handle this is to give our local defs + // a .hunk, this way (1) we know they're local - the view will always be local - + // proceeding, these would be route-builders, + await this.requestAddLink(vdef.outputs[0], link.inputs[1]) + await this.requestAddLink(link.inputs[1], vdef.outputs[0]) + resolve(vdef.hunk) + } catch (err) { + reject(err) + } } }) } @@ -1164,7 +1193,6 @@ function View() { let spec = deserializeDef(msg, inc + 1, false) // so first we check for an existing hunk, let nd - console.log('HERE', defs[spec.ind]) if (defs[spec.ind] === undefined) { nd = newDef(spec) //console.log('the nd', nd) diff --git a/style.css b/style.css index 70fef0238a7d8faf89f92c682c1df466e72d742f..c634c9a1de9e8b8ecd9f2591255d1c0be66b4ed1 100644 --- a/style.css +++ b/style.css @@ -73,7 +73,7 @@ body { .subplane{ position: absolute; background-color: #c1c1c1;; - width: 800px; + width: 1200px; height: 800px; } diff --git a/view/blocks.js b/view/blocks.js index 8b20be89255fa5e3d7c10acf4cda383d28a57151..38004c51e6571bc97ef34470bef0e0cfe793db46 100644 --- a/view/blocks.js +++ b/view/blocks.js @@ -19,9 +19,122 @@ let makeBlockParent = (bl) => { bl.blockChildren.push(block) block.blockParent = bl } + bl.remove = (block) => { + let bi = bl.blockChildren.findIndex((cand) => { + return cand === block + }) + if (bi >= 0) { + bl.blockChildren.splice(bi, 1) + } else { + console.error('missing child block when trying to remove, shruggy') + } + } return bl } +let getBlockStackHeight = (blocks) => { + let y = 0 + for (let bl of blocks) { + if ($(bl).is('.state') || $(bl).is('.defcore')) y += bl.clientHeight + 5 + } + return y +} + +let getBlockStackWidth = (blocks) => { + let x = 0 + for (let bl of blocks) { + if ($(bl).is('.state') || $(bl).is('.defcore') || $(bl).is('.subplane')) { + if (x < bl.clientWidth) x = bl.clientWidth + } + } + return (x += 5) +} + +// oboy, +let makeLink = (ldef, titleblock) => { + // ok, we have a new link, + // if the def's context is within another link, chance we are the reciprocal, check: + if(ldef.context.within){ + // if this link's context is *within* some link-definition, are we the hookup? + if(ldef.states[1].value == ldef.context.within.ind){ + // if this link's 'otherlink' (indice of link-conn-to) value is the same as it's contexts' container's indice, + ldef.upstream = ldef.context.within + ldef.context.within.downstream = ldef + // so, I want to distinguish direction here because I have more or less given up on rendering / working with non-dag graphs, + // for the moment. + } + } + if(!ldef.upstream){ + let squid = $('<div>').addClass('loosebutton').addClass('block').get(0) + squid.position = () => { + return { x: 0, y: -squid.clientHeight - 5 } + } + squid.handle = ldef + titleblock.take(squid) + ldef.blocks.push(squid) + let open = (evt) => { + // returns the view that connects to this link, + ldef.context.routelink(ldef).then((view) => { + // the link (def) contains the view (hunk direct) + ldef.contains = view + // the hunk is 'within' the link ... ?? + view.within = ldef + // oh lawd + ldef.contains.plane = $('<div>').addClass('subplane').addClass('block').attr('id', `${ldef.name}_plane`).get(0) + ldef.contains.plane.position = () => { + return { x: 0, y: getBlockStackHeight(ldef.blocks) } + } + ldef.contains.plane.handle = ldef // this is a throwaway ... and maybe ah bugfarm + ldef.blocks.push(ldef.contains.plane) + titleblock.take(ldef.contains.plane) + $(window.tlv.plane).append(ldef.contains.plane) + // and, + repositionDef(ldef) + // toggle button state, + $(squid).html('<i class="em em-shell"></i> collapse link') + $(squid).one('click', close) + view.refresh().then(() => { + // ? + }).catch((err) => { + console.error(err) + }) + }).catch((err) => { + console.error(err) + }) + } + let close = (evt) => { + wipeContext(ldef.contains) + $(ldef.contains.plane).remove() + // arduous: rm from ldef, and from titleblock, + let bi = ldef.blocks.findIndex((cand) => { + return (cand === ldef.contains.plane) + }) + if (bi >= 0) { + ldef.blocks.splice(bi, 1) + } else { + console.error('lost plane block ... ') + } + titleblock.remove(ldef.contains.plane) + delete ldef.contains.plane + // . then-> + $(squid).html('<i class="em em-squid"></i> expand link') + $(squid).one('click', open) + repositionDef(ldef) + } + $(squid).html('<i class="em em-squid"></i> expand link') + $(squid).one('click', open) + } else { + // static title, + titleblock.position = () => { + let y = 0; + for(let ipd of ldef.inputs){ + y += ipd.block.clientHeight + 5 + } + return { x: 0, y: y } + } + } +} + // typed, awkward let makeState = (st, bl) => { // st is the state definition @@ -181,7 +294,6 @@ let wipeContext = (context) => { $(context.plane).find('.wire').remove() } - // this takes our raw-af defs and builds / rebuilds them into the objecst we want // to drop in the dom / use in the UI // two trees @@ -192,7 +304,7 @@ let rebuildDef = (def, position) => { // need to make sure we have some position information before we draw if (!def.position) { if (position) { - def.position = {x: position.x, y: position.y} + def.position = { x: position.x, y: position.y } } else { def.position = { x: 200, y: 200 } } @@ -218,7 +330,24 @@ let rebuildDef = (def, position) => { let inputblock = $(`<li>${inputdef.name} (${inputdef.type})</li>`).addClass('input').addClass('block').get(0) inputblock.handle = inputdef inputblock.position = () => { - return { x: -inputblock.clientWidth - 5, y: (inputblock.clientHeight + 5) * i } + // is this hella dollars? + if (def.contains && def.contains.plane) { + // I wonder if this is going to bog us down, + // ideally redrawing would be list-based, with longer trees of offsetparents ... + return { x: -inputblock.clientWidth - 5, y: getBlockStackHeight(def.blocks) + (inputblock.clientHeight + 5) * i } + } else if (def.upstream) { + // we have an upstream link, i.e. we are the unwrapped thing, + // inputs go right, + return { + x: def.context.plane.clientWidth - inputblock.clientWidth, + y: -titleblock.position().y + (inputblock.clientHeight + 5) * i + } + } else { + return { + x: -inputblock.clientWidth - 5, + y: (inputblock.clientHeight + 5) * i + } + } } inputdef.block = inputblock titleblock.take(inputblock) @@ -230,7 +359,20 @@ let rebuildDef = (def, position) => { let outdef = def.outputs[o] let outblock = $(`<li>(${outdef.type}) ${outdef.name}</li>`).addClass('output').addClass('block').get(0) outblock.position = () => { - return { x: titleblock.clientWidth + 5, y: (outblock.clientHeight + 5) * o } + if (def.contains && def.contains.plane) { + // I wonder if this is going to bog us down, + // ideally redrawing would be list-based, with longer trees of offsetparents ... + return { x: getBlockStackWidth(def.blocks), y: getBlockStackHeight(def.blocks) + (outblock.clientHeight + 5) * o } + } else if (def.upstream) { + // we have an upstream link, i.e. we are the unwrapped thing, + // inputs go right, + return { + x: 0, + y: -titleblock.position().y + (outblock.clientHeight + 5) * o + } + } else { + return { x: titleblock.clientWidth + 5, y: (outblock.clientHeight + 5) * o } + } } outblock.handle = outdef outdef.block = outblock @@ -259,9 +401,9 @@ let rebuildDef = (def, position) => { } // find yourself in t h e g l o b a l d o m a i n - if(def.context === window.tlv){ + if (def.context === window.tlv) { let hunk = window.hunks[def.ind] - if(!((hunk.name === def.name) && (hunk.type === def.type))) throw new Error('this should never be the case') + if (!((hunk.name === def.name) && (hunk.type === def.type))) throw new Error('this should never be the case') def.hunk = hunk // additionally, // claim dom elements, global search @@ -275,15 +417,7 @@ let rebuildDef = (def, position) => { // ok, I think I want to position this above everything else, native.position = () => { // this is more difficult, as we are looking @ the other blocks, - let y = 0 - for (let bl of def.blocks) { - if ($(bl).is('.input') || $(bl).is('.output') || $(bl).is('.hunk')){ - continue - } else { - y += bl.clientHeight + 5 - } - } - return { x: 0, y: y } + return { x: 0, y: getBlockStackHeight(def.blocks) } } // attach to title, titleblock.take(native) @@ -291,45 +425,8 @@ let rebuildDef = (def, position) => { } } - - // now the hairier work, - if(def.type == 'link'){ - let squid = $('<div>').addClass('loosebutton').addClass('block').get(0) - squid.position = () => { - return {x: 0, y: - squid.clientHeight - 5} - } - squid.handle = def - titleblock.take(squid) - def.blocks.push(squid) - let open = (evt) =>{ - // returns the view that connects to this link, - def.context.routelink(def).then((view) => { - console.log('route ok') - // oddly, - def.contains = view - // we *do* want to walk these, so we want a handle to - // the view element - not just its def ... - view.refresh().then(() => { - // toggle button state, - $(squid).html('<i class="em em-shell"></i> collapse link') - $(squid).one('click', close) - }).catch((err) => { - console.error(err) - }) - }).catch((err) => { - console.error(err) - }) - } - let close = (evt) => { - wipeContext(def.contains) - $(def.contains.plane).remove() - // . then-> - $(squid).html('<i class="em em-squid"></i> expand link') - $(squid).one('click', open) - } - $(squid).html('<i class="em em-squid"></i> expand link') - $(squid).one('click', open) - } + // messy ! + if (def.type == 'link') makeLink(def, titleblock) }