sclass JG22Network is Swingable { G22Utils g22utils; new MainPanel mainPanel; new G22Network network; Map elementToComponent = syncMap(); ReliableSingleThread rstUpdate = rstWithPreDelay(0.25, l0 updateImpl); // example instance of the network so we can test it immediately settable volatile G22NetworkInstance networkInstance; // margin on bottom/right transient int margin = 50; class MainPanel extends JPanel { *() { super(null); } // no layout manager // to allow overlapping components public bool isOptimizedDrawingEnabled() { false; } public Dimension getPreferredSize() { Rect r = combinedChildBounds(this); if (r == null) r = rect(0, 0, 0, 0); //_print("JG22Network.getPreferredSize = " + r); ret new Dimension(r.x2()+margin, r.y2()+margin); } void revalidateMe() { //_print("JG22Network.revalidateMe"); //awtLater(0.5, -> { revalidateIncludingFullCenterContainer(this); repaint(); //}); } } *(G22Utils *g22utils, G22Network *network) { network.onChangeAndNow(l0 networkChanged); for (element : network.elements) visualizeElement(element); } void networkChanged { rstUpdate.trigger(); } void updateImpl { if (networkInstance == null) makeInstance(); visualizePorts(); } void visualizePorts { awt { // Remove old visualizations for (ports : directChildrenOfType(mainPanel, JG22NetworkPort)) removeFromParent(ports); // Create new ones for (e : network.elements) { var c = elementToComponent.get(e); if (c == null) print("No component for " + e); else for (port : e.ports) { print("Visualizing port " + port); var p = new JG22NetworkPort(g22utils, c, port); p.init(); mainPanel.add(p); } } mainPanel.repaint(); }} void makeInstance { var networkInstance = new G22NetworkInstance(network); networkInstance.init(g22utils); networkInstance(networkInstance); print("Network instance made"); } void visualizeElement(G22NetworkElement element) swing { var c = new JG22NetworkElement(g22utils, this, element); elementToComponent.put(element, c); mainPanel.add(c.visualize()); mainPanel.revalidateMe(); } void newInstance { networkInstance = null; rstUpdate.trigger(); } void newElement { new G22NetworkElement element; element.network(network); network.elements.add(element); network.change(); visualizeElement(element); } void deleteElement(JG22NetworkElement element) { network.elements.remove(element.element); network.change(); mainPanel.remove(element.visualize()); mainPanel.repaint(); } cachedVisualize { var magneticDistanceSlider = jLiveValueSlider_int_bothWays(0, 500, network.varMagneticDistance()); ret withRightAlignedButtons(/*jscroll_center_borderless*/jscroll(mainPanel), withLabel("Magnetic auto-connect distance:", magneticDistanceSlider), "New instance", rThread newInstance, "New element", rThread newElement); } }