UNPKG

peepee

Version:

Visual Programming Language Where You Connect Ports Of One EventEmitter to Ports Of Another EventEmitter

257 lines (189 loc) 8.71 kB
import { Signal, combineLatest, fromEvent, fromBetweenEvents } from "signals"; import { Plugin } from "plugin"; export class PortManagerPlugin extends Plugin { app; subscriptions; portInstances; constructor() { super(); this.subscriptions = new Set(); this.portInstances = new Map(); } init(app) { this.app = app; this.svg = app.svg; this.stationManager = app.plugins.get("AgentManagerPlugin"); this.agentInstances = this.stationManager.agentInstances; this.agentManifests = this.stationManager.agentManifests; this.stationManager = app.plugins.get("StationManagerPlugin"); this.stationInstances = this.stationManager.stationInstances; this.recordsManager = app.plugins.get('RecordsManagerPlugin'); this.recordInstances = this.recordsManager.recordInstances; this.gadgetManagerPlugin = app.plugins.get("GadgetManagerPlugin"); this.gadgetRegistry = this.gadgetManagerPlugin.gadgetRegistry; this.widgetManagerPlugin = app.plugins.get("WidgetManagerPlugin"); this.widgets = this.widgetManagerPlugin.widgets; this.workbenchPlugin = app.plugins.get("WorkbenchPlugin"); this.engine = this.workbenchPlugin.engine; this.app.on("stationAgentAdded", (agent) => this.instantiatePorts(agent)); // this.app.on("gadgetAdded", (gadget) => this.instantiatePorts(gadget)); // 1. await stationAgentAdded // 2. await gadget with the station.agentTYpe // 3. call instantiatePorts // this.app.on("agentRemoved", (id) => this.destroyPorts(id)); this.app.on("stationRemoved", (id) => this.destroyPorts(id)); this.loadStyleSheet(new URL("./style.css", import.meta.url).href); } stop() { for (const unsubscribe of this.subscriptions) unsubscribe(); this.subscriptions.clear(); } createPort(station, kind, input) { const id = [station.id, kind, input.id].join(":"); // const name = [kind, input.id].join(":"); const name = [input.id].join(":"); const portComponent = this.widgets.registry.get(id); if (!portComponent) throw new Error(`Failed to locate component ${id} in component registry, does it have a valid id?`); const port = { id, name, stationId: station.id, portElement: portComponent.element, x: new Signal(0), y: new Signal(0), unsubscribe: [], }; // when station changes of moves, update port coordinates combineLatest(station.connect(), this.engine.scale, portComponent.attributes.portSocketX).subscribe(([[id, x1, y1, r, label, agentType], scale, portSocketX]) => { const { e: x, f: y } = portComponent.portSocket.getCTM(); const point = this.engine.clientToWorld(x, y); port.x.value = point.x + portSocketX; port.y.value = point.y + 8; // port.x.value = portComponent.attributes.portSocketXCTM.value; // port.y.value = portComponent.attributes.portSocketYCTM.valuealue = portComponent.attributes.portSocketYCTM.value; }); this.portInstances.set(port.id, port); this.eventDispatch("portAdded", port); } async instantiatePorts({id}) { console.log('instantiatePorts', id) const agent = this.agentInstances.get(id); const station = this.stationInstances.get(id); const manifest = this.agentManifests.get(station.agentType); let gadgetInstance = this.gadgetRegistry.get(id); if(!gadgetInstance){ await this.app.until('gadgetAdded', station.agentType); gadgetInstance = this.gadgetRegistry.get(station.agentType); } if(!gadgetInstance) throw new Error(`id ${id} required a gui gadget manifest of type ${station.agentType}`) // const gadgetInstance = this.gadgetRegistry.get(station.agentType); let record = this.recordInstances.get(id); if(!record){ await this.app.until('recordAdded', id); record = this.recordInstances.get(id); } let rootComponent; if(gadgetInstance){ console.log('gadgetInstance', gadgetInstance) let { content, properties } = gadgetInstance.content({ manifest, station }); rootComponent = this.widgets.append(content); record.subscribe((name, value)=>{ if (this.widgets.registry.has(properties[name])) this.widgets.registry.get(properties[name]).attributes[name].value = value; }); } // }else{ // const component = ` // <Panel caption="UI Not Found" left="500" top="500" width="200" height="200" horizontalCenter="0" verticalCenter="0"> // <Text content="No Gadget"></Text> // </Panel> // `; // // const component = ` // // <Panel caption="Basic Example" left="500" top="500" width="200" height="200" horizontalCenter="0" verticalCenter="0"> // // <Group left="10" top="10"> // // <VGroup gap="5"> // // ${manifest.node.inputs.map((port) => `<Port id="${[station.id, "input", port.id].join(":")}" group="${station.id}" type="input" caption="${port.id}" width="180"/>`).join()} // // ${manifest.node.outputs.map((port) => `<Port id="${[station.id, "output", port.id].join(":")}" group="${station.id}" type="output" caption="${port.id}" width="180"/>`).join()} // // </VGroup> // // </Group> // // </Panel> // // `; // rootComponent = this.widgets.append(component); // } rootComponent.element.setAttribute("data-station-id", station.id); rootComponent.element.addEventListener("click", () => this.eventDispatch("selectNode", station)); // PASS RECORD DATA TO ATTRIBUTES // this.tuneIn(record.get('color', 'green'), v=>path.style.stroke = this.primaryColorTransform(v) ) // for(const property of manifest.node.properties){ // } // INSTALL CONV TOOL ON PORTS for (const port of manifest.node.outputs) { const id = [station.id, "output", port.id].join(":"); const portComponent = this.widgets.registry.get(id); if(!portComponent) continue; let previousTool = this.app.selectedTool.value; let convenienceTool = "connect"; const pressingActivity = fromBetweenEvents(portComponent.portSocket, "mousedown", this.svg, "mouseup"); const unsubscribe = pressingActivity.subscribe((isPressing) => { if (isPressing) { previousTool = this.app.selectedTool.value; this.app.selectedTool.value = convenienceTool; } else { this.app.selectedTool.value = previousTool; } }); console.warn("unsubscribe", unsubscribe); } // let lastTool = this.app.selectedTool.value; // let overrideActive = false; // // fromEvent(rootComponent.element, 'mousedown').subscribe(()=>{ // // overrideActive=true; // // lastTool = this.app.selectedTool.value; // // this.app.selectedTool.value = 'move'; // // const currentTool = this.app.selectedTool.value // // console.log({lastTool, currentTool}) // // }); // // fromEvent(rootComponent.element, 'mouseup').subscribe(()=>{ // // console.log('mouseup', lastTool) // // if(!overrideActive) return; // // overrideActive = false; // // this.app.selectedTool.value = lastTool; // // }); let previousTool = this.app.selectedTool.value; let convenienceTool = "move"; const pressingActivity = fromBetweenEvents(rootComponent.dragHandle, "mousedown", this.svg, "mouseup"); pressingActivity.subscribe((isPressing) => { if (isPressing) { previousTool = this.app.selectedTool.value; this.app.selectedTool.value = convenienceTool; } else { this.app.selectedTool.value = previousTool; } }); // fromEvent(rootComponent.element, 'mousedown') // .switchMap(this.app.selectedTool) // .subscribe(tool=>{ // tool.value = 'move' // }) // fromEvent(document, 'mouseup') // .switchMap(this.app.selectedTool) // .subscribe(tool=>tool.value = 'move') // Station Position station.connect().subscribe(([id, x, y, r, label, agentType]) => { rootComponent.attributes.top.value = y; rootComponent.attributes.left.value = x; }); manifest.node.inputs.forEach((o) => this.createPort(station, "input", o)); manifest.node.outputs.forEach((o) => this.createPort(station, "output", o)); this.eventDispatch("portsAdded", agent); } destroyPorts(stationId) { // Remove ports matching the condition (it is safe to delete items being iterated via forEach) this.portInstances.forEach((port, key) => { if (port.stationId == stationId) { port.portElement.remove(); port.unsubscribe.forEach((stop) => stop()); this.portInstances.delete(key); } }); } }