persistable sclass G22NetworkElement > MetaWithChangeListeners { // network element belongs to settable G22Network network; // position in visual representation settable Rect bounds; // identifier in network (optional) settableWithVar S identifier; // script code to adapt element and to create instance settableWithVar S code; // general properties map depending on element type Map properties = syncMap(); { onChange(-> { network?.change(); }); } class Port extends MetaWithChangeListeners { // position on element's border (0 to 1, 0 to 1) settableWithVar DoublePt position; // name of port within element settableWithVar S name; // cable attached to this port (optional) settableWithVar G22NetworkCable cable; // is it output or input? settableWithVar bool isOutput; // type of object sent through port settableWithVar Class dataType; G22NetworkElement element() { ret G22NetworkElement.this; } toString { ret (isOutput ? "Output" : "Input") + " port" + " " + quote(name) + " of type " + shortClassName(dataType); } Rect bounds() { int size = 10; Rect r = element().bounds; if (r == null) null; r = growRectTopAndLeft(r, size); ret rect(r.x+iround(position.x*r.w), r.y+iround(position.y*r.h), size, size); } void delete() { cable?.remove(); ports.remove(this); change(); } } L ports = syncL(); LASCompileResult newCompileResult() { ret new LASCompileResult; } transient LASCompileResult compileResult; LASCompileResult compile(G22Utils g22utils) { S code = this.code; if (code == null) null; var cr = compileResult; if (cr != null && eq(cr.script, code)) ret cr; cr = newCompileResult(); var parser = g22utils.leftArrowParser(); configureParser(parser); cr.script(code).parser(parser).compile(); ret compileResult = cr; } void configureParser(GazelleV_LeftArrowScriptParser parser) { parser.addVar("blueprint"); parser.addVar("instance"); } GazelleV_LeftArrowScript.Script compileScript(G22Utils g22utils) null on exception { var compiled = compile(g22utils); if (compiled == null) null; if (!compiled.runnable()) null; ret compiled!; } void configureBlueprint(G22Utils g22utils) { var script = compileScript(g22utils); if (script == null) ret; new FlexibleVarContext ctx; var f = script.getFunction("configure"); if (f != null) f.call(ctx, this); } O makeInstance(G22Utils g22utils, G22NetworkInstance networkInstance) null on exception { var script = compileScript(g22utils); if (script == null) null; new FlexibleVarContext ctx; for (port : ports) if (!port.isOutput() && port.cable != null) { var outputPort = port.cable.from; if (outputPort != null) ctx.set(port.name, networkInstance.getObjectForBlueprint(outputPort.element())); } ret script.get(ctx); } // Nodes that we directly depend on Set upstreamNodes() { new Set set; for (port : ports) if (!port.isOutput() && port.cable != null) { var outputPort = port.cable.from; if (outputPort != null) set.add(outputPort.element()); } ret set; } // Nodes that directly depend on this one Set downstreamNodes() { new Set set; for (port : ports) if (port.isOutput() && port.cable != null) { var outputPort = port.cable.to; if (outputPort != null) set.add(outputPort.element()); } ret set; } toString { ret or2(identifier(), "Unnamed element"); } Port getPort(S name) { ret firstThat(ports, p -> eq(p.name, name)); } void addPort aka addSlot(S name, DoublePt etc position) { printFunctionCall("addPort", +name, +position); Port p = getPort(name); if (p != null) ret; ports.add(new Port().name(name).position(position)); change(); } void addInputPort(S name, DoublePt etc position, Class type) { Port p = getPort(name); if (p != null) ret; ports.add(new Port().name(name).position(position) .isOutput(false).dataType(type)); change(); } void addOutputPort(S name, DoublePt etc position, Class type) { Port p = getPort(name); if (p != null) ret; p = new Port().name(name).position(position) .isOutput(true).dataType(type); ports.add(p); print("Made port " + p); change(); } void removePorts aka deletePorts aka removeSlots aka deleteSlots() { while (nempty(ports)) last(port).delete(); change(); } L ports() { ret cloneList(ports); } // key and value must be persistable! void setProperty(O key, O value) { properties.put(key, value); change(); } O getProperty(O key) { ret properties.get(key); } }