Newer
Older
// want one,
// altho, non-ideal ...
let dt = new DomTools(view)
// TODO:
/*
... think ... think ...
-> button to expand, and gather? div-related?
-> button drags as well ? titlematter does hover, not drag, two funcitons ?
-> !!!!!!!!!!!!! button for fixed ! fixed !!!!!!!!!!!!!!!
-> roll sim back, so that fixed / unfixed is meaningful
-> explosions afterwards
*/
// a floater is an individual that can be dragged, fixed/unfixed, etc
// it is exactly the thing we give to d3 to lay out
this.x = 0
this.y = 0
// these are handy,
this.bb = {}
this.bb.x1 = -50
this.bb.y1 = -50
this.bb.x2 = 51
this.bb.y2 = 51
// will have this to track within simulation links
this.simIndex = null
// every floater has *at least* this ...
// this is where we put the buttonz
this.ownElement = $(`<div>`).addClass('float').get(0)
$(this.ownElement).append(`<i class="em em-pushpin"></i>`)
this.free()
} else {
this.fix()
}
}).on('mouseover', (evt) => {
document.body.style.cursor = 'pointer'
}).on('mouseout', (evt) => [
document.body.style.cursor = 'auto'
])
$(view.plane).append(this.ownElement)
// fixed <i class="em em-round_pushpin"></i>
// open <i class="em em-pushpin"></i>
// this is a list of elements to carry about
this.bag = [] // gets {element, x, y}
// fuuu
let writeTitleMatter = (div, def) => {
let md = false
div.onmouseover = () => {
def.highlight()
}
div.onmousedown = (evt) => {
md = true
document.body.style.cursor = 'grabbing'
// pin to current position,
this.fix()
evt.preventDefault()
evt.stopPropagation()
let domElemMouseMove = (evt) => {
// TRANSFORMS here to move div about on drag
evt.preventDefault()
evt.stopPropagation()
// need to find that top-level view's scale transform
this.fx += evt.movementX / view.tls
this.fy += evt.movementY / view.tls
this.newFix()
this.tick()
}
function rmOnMouseUp(evt) {
md = false
document.body.style.cursor = 'auto'
document.removeEventListener('mousemove', domElemMouseMove)
document.removeEventListener('mouseup', rmOnMouseUp)
}
document.addEventListener('mousemove', domElemMouseMove)
document.addEventListener('mouseup', rmOnMouseUp)
}
}
// -------------------------------------------- TAKE
let type = ''
// cover view-containing ... ??
// if ($(div).is('.native') && $(div).children().contains('.view'))
let item = {
type: '',
de: div,
def: def,
offsetX: 0,
offsetY: 0
}
// always nice to do this first,
// defs -> the dom
$(view.plane).append(item.de)
} else if ($(div).is('.nativewrap')) {
item.type = 'native'
// at the gitgo, set this to our current width...
// this width thing is happening because you're rewriting the
if (this.w < 200) {
$(item.de).css('width', `200px`)
} else {
$(item.de).css('width', `${this.w}px`)
}
dt.makeResizeable(item.de, this.onElementResize, resize)
} else if ($(div).is('.defbutton')) {
console.error('no thx, no recognized type when taking div into floater')
}
// (also) write the drag content, if there's a header on board
this.fitNativeToFloater = () => {
this.calculateSizes(true)
// find it,
let nt = this.bag.find((cnd) => {
return cnd.type === 'native'
})
console.error('not finding a native element to resize here')
} else {
$(nt.de).css('width', `${this.w}px`)
// want also to reset the resizing handle ...
// kind of messy call, but
let w = nt.de.clientWidth
let h = nt.de.clientHeight
let handle = $(nt.de).children('.resizehandle').get(0)
// GROUP TYPES:
// 'edges' ... (core) with (outputs) and .edges || (inputs)
// 'unwrapped' ... (core) with (outputs) and .unwrapped || (inputs)
// 'wrapped' ... (core) with (inputs) and (outputs) and (native .view) and .wrapped
// 'std' ... (core) with some set of (inputs) and (outputs) and (native)
this.makeEdges = () => {
this.grouptype === 'edges'
this.onChange()
}
// -------------------------------------------- CHANGE
// don't want to do this all the time
// to 'open' ... put core with outputs,
// to 'unwrap' ... put core with inputs, it will go below
this.onChange = () => {
let core = this.bag.find((cnd) => {
return cnd.type === 'core'
})
let inputs = this.bag.find((cnd) => {
return cnd.type === 'inputs'
})
let outputs = this.bag.find((cnd) => {
return cnd.type === 'outputs'
})
let native = this.bag.find((cnd) => {
return cnd.type === 'native'
})
// possible to have many,
let buttons = []
for (let item of this.bag) {
if (item.type === 'button') buttons.push(item)
//console.log('FLT onchange, floater has', core ? '(core)' : '', inputs ? '(inputs)' : '', outputs ? '(outputs)' : '', native ? '(native)' : '')
if (this.grouptype === 'std') {
// 'std' ... (core) with some set of (inputs) and (outputs) and (native)
inputs.offsetX = core.offsetX - inputs.de.clientWidth - spaces - 2
if (native) {
// calc sizes, ignoring native
this.calculateSizes(true)
native.offsetX = this.bb.x1
native.offsetY = this.bb.y2 + spaces
// for resizing,
if (outputs) {
let gap = native.de.clientWidth - this.w
if (gap > 1) {
outputs.offsetX += gap
}
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
} else if (this.grouptype === 'unwrapped') {
// 'unwrapped' ... (core) with (outputs) and .unwrapped || (inputs)
if (core) {
// unwrapped, left side, core, outputs, etc
core.offsetX = -core.de.clientWidth
core.offsetY = 0
if (outputs) {
outputs.offsetX = spaces
outputs.offsetY = 0
}
if (native) {
this.calculateSizes(true)
native.offsetX = this.bb.x1
native.offsetY = this.bb.y2 + spaces
if (outputs) {
let gap = native.de.clientWidth - this.w
if (gap > 1) {
outputs.offsetX += gap
}
}
}
} else {
// unwrapped, right side, it's the lonely inputs
if (inputs) {
inputs.offsetX = -inputs.de.clientWidth
inputs.offsetY = 0
} else if (this.grouptype === 'wrapped') {
// should have 'em all let's just wyld out
// the view attached is king,
let ntw = native.de.clientWidth
let nth = native.de.clientHeight
// left ...
native.offsetX = -core.de.clientWidth
native.offsetY = core.de.clientHeight + spaces
core.offsetX = -core.de.clientWidth
core.offsetY = 0
inputs.offsetX = core.offsetX - inputs.de.clientWidth - spaces
inputs.offsetY = $(inputs.de).children('.header').get(0).clientHeight + spaces + native.offsetY
outputs.offsetX = ntw + spaces + core.offsetX
outputs.offsetY = inputs.offsetY
} else if (this.grouptype === 'edges') {
if(core && outputs){
this.edgetype = 'left'
// and on top of self,
core.offsetX = -core.de.clientWidth
core.offsetY = -core.de.clientHeight - 25
outputs.offsetX = core.offsetX
outputs.offsetY = core.offsetY - outputs.de.clientHeight - spaces
} else {
this.edgetype = 'right'
inputs.offsetX = -inputs.de.clientWidth
inputs.offsetY = -inputs.de.clientHeight - 25
// aaand
view.msgbox.setTopMargin( - inputs.offsetY + 20)
}
console.error(`this floater grouptype not written or recognized: '${this.grouptype}'`)
// now we can cover buttons, using core offsets
// cover buttons, if(buttons.length){
if (buttons.length > 0) {
if (!core) console.error('watch buttons not-on core?')
let inc = 0
for (let btn of buttons) {
btn.offsetX = core.offsetX + inc
btn.offsetY = -20 - core.offsetY
inc += 20
}
}
// ok,
let writePosition = (element, x, y) => {
$(element).css('left', `${x}px`).css('top', `${y}px`)
}
let readPosition = (element) => {
let it = $(element)
return {
x: parseInt(it.css('left')),
y: parseInt(it.css('top'))
}
}
let readSize = (element) => {
return {
w: element.clientWidth,
h: element.clientHeight
}
}
// will return this ...
let desire = {
x: 0,
y: 0
}
// check bounds,
if(!view.isTopLevel){
// bummer to do so many times !
let bounds = view.getCurrentBounds()
this.calculateSizes()
//
if(this.grouptype === 'edges'){
//console.log('bounds', bounds)
// x1, y1, x2, y2, w, h
if(this.edgetype === 'left'){
this.x = - this.bb.x1
this.y = - this.bb.y1 + 17 + 5
} else {
this.y = bounds.y1 - this.bb.y1 + 17 + 5
}
} else {
//console.log('place bounds', this.bb)
//console.log('bounds', bounds)
// x needs to contend with offset,
// this.bb.x1 probably -ve,
// this.bb.y1 probably -ve,
// want to track, but won't push things left or up,
this.x = Math.max(bounds.x1 - this.bb.x1, this.x) // lower bounds
this.y = Math.max(bounds.y1 - this.bb.y1, this.y)
// want-right term,
let rbnd = bounds.x2 - this.bb.x2
if(this.x > rbnd){
desire.x = this.x - rbnd
this.x = rbnd
// wants to go right
}
// want-down term,
let lbnd = bounds.y2 - this.bb.y2
if(this.y > lbnd){
desire.y = this.y - lbnd
this.y = lbnd
// wants to go down
}
// do work
writePosition(this.ownElement, x - 16.5, y - 20)
writePosition(item.de, this.x + item.offsetX, this.y + item.offsetY)
// aaaand tell em what we waaaaant
return desire
this.newFix = () => {
this.moveTo(this.fx, this.fy, true)
}
// as is tradition, we'll keep things local,
// and just make sure we re-calculate during relevant events... ?
// from core of xy, values like
//
// * -------------- (y1) -------- *
// | | |
// |(x1) --------- (x,y) ---- (x2)|
// | | |
// | | |
// * ------------ (y2) ---------- *
let x1 = 0
let y1 = 0
let x2 = 0
let y2 = 0
let wt = readSize(item.de)
// we know item offsets, so
if (item.offsetX < x1) x1 = item.offsetX
if (item.offsetY < y1) y1 = item.offsetY
if (item.offsetX + wt.w > x2) x2 = item.offsetX + wt.w
if (item.offsetY + wt.h > y2) y2 = item.offsetY + wt.h
this.bb.x1 = x1
this.bb.y1 = y1
this.bb.x2 = x2
this.bb.y2 = y2
// ok,
this.w = x2 - x1
this.h = y2 - y1
// also,
this.r = Math.max(this.w, this.h) / 2
// check,
let aspect = this.w / this.h
//console.error(`warning: deviously large aspect for 'circular' collisions: ${aspect}, logging floater`, this)
}
}
this.tick = () => {
// will use to bother the simulation
view.tick()
}
this.free = () => {
this.x = this.fx
this.y = this.fy
delete this.fx
delete this.fy
this.isFixed = false
$(this.ownElement).html(`<i class="em em-pushpin"></i>`)
$(this.ownElement).html(`<i class="em em-round_pushpin"></i>`)
this.fx = this.x
this.fy = this.y
this.moveTo(this.fx, this.fy, true)
}
this.fixTo = (x, y) => {
this.x = x
this.y = y
this.fix()
// RIP
this.cleanup = () => {
// js deletes things that are unreachable, so
// there are a few objects that are on the canvas we want to get rid of
$(this.ownElement).remove()
// also, any handle added to a native element
// not being able to search by js subset is kind of a bummer here, but
let native = this.bag.find((cnd) => {
return cnd.type === 'native'
})