concept G22Network > ConceptWithChangeListeners { delegate Port to G22NetworkElement. settableWithVar S description; Cl elements = syncL(); settableWithVar int magneticDistance = 100; // Is the network safe to auto-calculate? settableWithVar bool autoCalculate = true; toString { ret or2(description, super.toString()); } // return new connections made Cl doMagneticConnections() { //deleteMagneticConnections(); new L newCables; new L inputPorts; new L outputPorts; for (element : elements) for (port : element.ports()) (port.isOutput() ? outputPorts : inputPorts).add(port); for (port1 : inputPorts) { if (port1.isConnected()) continue; Rect bounds1 = port1.bounds(); new Lowest best; for (port2 : outputPorts) { double distance = rectDistance(bounds1, port2.bounds()); // too far away? skip if (distance >= magneticDistance) continue; // wrong type? skip if (!isSubclassOf(port2.dataType(), port1.dataType())) continue; // candidate found - store with distance best.put(port2, distance); } var port2 = best!; if (port2 != null) { var cable = new G22NetworkCable().from(port2).to(port1); newCables.add(cable); cable.connect(); print("Made cable: " + cable); } } ret newCables; } void deleteMagneticConnections { for (cable : allCables()) if (cable.isAutomatic()) cable.remove(); } Set allCables() { new Set set; for (element : elements) for (port : element.ports()) addIfNotNull(set, port.cable); ret set; } }