sclass G22AnalysisPanel > MetaWithChangeListeners is Swingable, AutoCloseable { // This is actually persistable // TODO: use Ref pointer so it's cleaned when target is deleted settableWithVar G22Analyzer analyzer; transient settable G22Utils g22utils; // where to show recognized boxes transient settable ImageSurface imageSurface; transient SingleComponentPanel scp; transient ReliableSingleThread rstStartAnalysis = new(r _startAnalysis); transient gettable BufferedImage image; transient G22RunSingleAnalyzerPanel analyzerPanel; public void setImage(File image) { setImage(loadImage2(image)); } // we may be getting the same instance again but it still means // there was a change in the image public void setImage(BufferedImage image) { this.image = image; analyzerPanel?.setImage(image); } cachedVisualize { scp = singleComponentPanel(); varAnalyzer().onChangeAndNow(rstStartAnalysis); ret northAndCenterWithMargins( centerAndEastWithMargin( withLabel("Analyzer", bindComboBoxToVar(varAnalyzer(), swing(-> new ConceptsComboBox(g22utils.concepts(), G22Analyzer).allowNull(true)) )), jline( jimageButton(#1101440, "Re-run analyzer", l0 remakeAnalyzerPanel), jimageButtonScaledToWidth(16, #1103068, "Edit analyzer", -> editAnalyzer(analyzer)) ) ), scp ); } void _startAnalysis { var panel = optCast G22RunSingleAnalyzerPanel(analyzerPanel); if (panel == null || panel.analyzer != analyzer) { analyzerPanel = new G22RunSingleAnalyzerPanel(g22utils, image, analyzer); if (imageSurface != null) { analyzerPanel.onAnalyzerResult((analyzer, result) -> { imageSurface.clearOverlays(); analyzerResultToOverlays(result); }); analyzerPanel.onAnalyzerError((analyzer, error) -> imageSurface.clearOverlays()); } scp.set(analyzerPanel); } } void analyzerResultToOverlays(O result) { if (result cast Rect) { imageSurface.addOverlay(new RenderRecognizedBox(RectAsRecognizedBox(result))); } else if (result cast IImageRegion) { imageSurface.addOverlay(new RenderRecognizedBox/*Region*/(RecognizedRegion(result))); } } void remakeAnalyzerPanel { analyzerPanel = null; thread { _startAnalysis(); } } close {} swappable void editAnalyzer(G22Analyzer analyzer) {} }