sclass G22AnalysisPanel > MetaWithChangeListeners is Swingable, AutoCloseable { // This is actually persistable // TODO: use Ref pointer so it's cleaned when target is deleted settableWithVar G22Recognizer 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; // 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(), G22Recognizer).allowNull(true)) )), jimageButton(#1101440, "Re-run analyzer", l0 remakeAnalyzerPanel) ), 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(); if (result cast Rect) imageSurface.addOverlay(new RenderRecognizedBox(RectAsRecognizedBox(result))); }); analyzerPanel.onAnalyzerError((analyzer, error) -> imageSurface.clearOverlays()); scp.set(analyzerPanel); } } void remakeAnalyzerPanel { thread { _startAnalysis(); } } close {} }