// please include #1005686 [PIF Classes v2] sclass SingleObjectFinder { S obj = "start button"; *() {} *(S *obj) {} int maxTotal = 10; bool fullSearch = true; JComponent form; JLabel lFound, lSearchTime, lScreenshots; volatile L found; void showGUI() { form = showForm( "Number of \*obj*/ pictures stored:", jConceptCountLabel(Clip), "Number of screenshots stored:", lScreenshots = jConceptDependentLabel(func { int n = countConcepts(Screenshot); int t = countConcepts(TransientScreenshot); ret n + " (" + (n-t) + " with image)"; }), "Currently found:", lFound = jlabel(), "Search time:", lSearchTime = jlabel(), "", jbutton("Show pictures", r { showClips() }), "", jbutton("Grab picture of \*obj*/", r { addClip(false) }), "", jbutton("Grab picture with delay", r { addClip(true) }) ); onDoubleClick(lFound, r { Found f = first(found); if (f == null) ret; moveMouseTo(centerOfRect(f.fi.r)); }); componentPopupMenu(lFound, voidfunc(JPopupMenu menu) { menu.add(jmenuItem("Show all", r { for (Found f: unnull(found)) pointArrowsToArea(f.fi.r); })); }); componentPopupMenu(lScreenshots, voidfunc(JPopupMenu menu) { menu.add(jmenuItem("Delete older screenshots", r { deleteOlderScreenshots() })); }); final new MonoThread thread; installTimer(form, 5000, 0, r { thread.runIfNotRunning(r { BufferedImage img = shootScreen2(); long start = now(); found = continuousFind_step(goodClips(), img, maxTotal, fullSearch); final long time = now()-start; awt { lSearchTime.setText(time + " ms"); S s = "no"; if (nempty(found)) s = "at " + first(found).fi.r + " [clip " + first(found).clip->id + "]"; if (l(found) > 1) s += " +" + (l(found)-1); lFound.setText(s); } }); }); } void addClip(bool delay) { letUserMarkScreenArea(delay ? null : shootScreen2(), voidfunc(final Rectangle r, BufferedImage img) { if (r == null) print("Cancelled!"); else { Screenshot screenshot = new Screenshot(img); showAnimation("#1005611", "You marked " + r, 3); uniq(MarkedClip, +screenshot, positionInScreenshot := new Rect(r), description := obj, img := new BWImage(img).clip(r)); darkenScreenArea(r, 5); swingLater(250, r { pointArrowsToArea(r, 5-0.25); }); } }); } void showClips { new L data; for (MarkedClip clip) pcall { data.add(ll(clip.id, clip.img == null ? null : clip.img.getBufferedImage(), clip.description)); } final JTable table = showTableWithImages("Clips", splitAtSpace("ID Picture Description"), data); tablePopupMenu(table, voidfunc(JPopupMenu menu, int row) { L line = getTableLine(table, row); long id = parseLong(line.get(0)); final Clip clip = cast getConcept(id); if (neq(clip.description, "bad")) menu.add(jmenuItem("Mark bad", r { cset(clip, description := "bad"); disposeFrame(table); showClips(); })); }); } L goodClips() { ret [Clip c in list(Clip) | swic(c.description, obj)]; } void deleteOlderScreenshots() { for (Screenshot s : dropLast(list(Screenshot))) { if (hasBackRef(s, Clip)) continue; print("Backrefs to screenshot:"); L backRefs = findBackRefs(s, Concept); printIndent(renderConcepts(backRefs)); deleteConcepts(backRefs); s.delete(); } } }