import Service from '@ember/service'; import { action } from '@ember/object'; import { tracked } from '@glimmer/tracking'; import { schedule } from '@ember/runloop'; import { getBoxToBoxArrow } from 'curved-arrows'; function boxToArrow(ra, rb) { const bbA = ra; const bbB = rb; const [sx, sy, c1x, c1y, c2x, c2y, ex, ey, ae, as] = getBoxToBoxArrow( bbA.offsetLeft, bbA.offsetTop, bbA.offsetWidth, bbA.offsetHeight, bbB.offsetLeft, bbB.offsetTop, bbB.offsetWidth, bbB.offsetHeight ); return { sx, sy, c1x, c1y, c2x, c2y, ex, ey, ae, as, }; } export default class ActorRelationshipService extends Service { @tracked actors = []; get fns() { const { registerActor, deregisterActor, recalcCurves } = this; return { registerActor, deregisterActor, recalcCurves }; } get data() { const { actors, relationships } = this; return { actors, relationships }; } @action registerActor(actor) { schedule('actions', this, () => { this.actors = [...this.actors, actor]; }); } @action deregisterActor(actor) { schedule('actions', this, () => { this.actors = this.actors.filter((a) => a !== actor); }); } get rects() { const { actors } = this; return actors .filter((e) => e.previousEval) .map((e) => { const { previousEval: pid, id } = e; const eRectangle = document.querySelector(`[data-eval="${id}"]`); const prevRectangle = document.querySelector(`[data-eval="${pid}"]`); return [eRectangle, prevRectangle]; }); } get relationships() { const { rects } = this; return rects.map(([eRectangle, prevRectangle]) => { const { sx, sy, c1x, c1y, c2x, c2y, ex, ey } = boxToArrow( eRectangle, prevRectangle ); return { d: `M ${sx} ${sy} C ${c1x} ${c1y}, ${c2x} ${c2y}, ${ex} ${ey}`, sx, sy, ex, ey, }; }); } @action recalcCurves() { // retrigger the tracked getters by resetting dependent keys /* eslint-disable-next-line */ this.actors = this.actors; } }