!7 need latest area. // We're banning db_mainConcepts() again to allow multiple databases loaded at once // !transpileMainSnippet #1033860 !include once #1033998 // RSyntaxTextArea !include once #1013490 // sarxos webcam !include early #1034876 // Gazelle 22 Flags [Include] !include early #1033884 // Compact Module Include Gazelle V [dev version] !include once #1034034 // Gazelle 22 Function Include for Scripts rewrite Challenge to G22Challenge. rewrite Label to G22Label. rewrite GalleryImage to G22GalleryImage. module GazelleScreenCam is G22ProjectActions { !include early #1025212 // +Enabled without visualization { enabled = false; } transient static bool autoRunSelfTests = true; int pixelRows = 128, colors = 8; S script = "64p 8c gradientImage"; S newScript; S screenCamScript; S selectedTab; S javaCode; bool horizontalLayout; // flat layout int fpsTarget = 20; S webCamName; bool webCamAccessEnabled = true; WatchTarget watchTarget; new G22_TestScreenPanel testScreen; // The following fields related to the screen cam panel transient ImageSurface isPosterized; transient new ScreenCamStream imageStream; transient Gazelle22_ImageToRegions imageToRegions_finished; transient new DoubleFPSCounter fpsCounter; transient int fps; transient WatchTargetSelector watchTargetSelector; transient new RollingAverage remainingMSPerFrame; transient int remainingMS; // End of fields for screen cam panel transient new FunctionTimings<S> functionTimings; transient ReliableSingleThread rstRunScript = dm_rst(me(), r _runScript); transient JGazelleVScriptRunner scriptRunner; transient UIURLSystem uiURLs; //transient L<Webcam> availableWebCams; transient JComboBox<Webcam> cbWebCam; transient SingleComponentPanel scpWebCamImage; transient WebcamPanel webCamPanel; transient JLeftArrowScriptIDE screenCamScriptIDE; transient GazelleV_LeftArrowScript.Script runningScreenCamScript; // set by host transient Concepts concepts; S uiURL = "Main Tabs"; transient FileWatchService fileWatcher; transient SimpleCRUD_v2<Label> labelCRUD; transient SimpleCRUD_v2<GalleryImage> galleryCRUD; transient JComponent galleryCRUDVis; transient SimpleCRUD_v2<Entity> entityCRUD; transient JGallery /*gallery,*/ paintToolGallery; //transient ImageSurface galleryImageSurface; transient FlexibleRateTimer screenCamTimer; transient SingleComponentPanel scpMain; transient JTabbedPane mainTabs; transient bool showRegionsAsOutline = true; transient JComponent watchScreenPane; transient S screenCamRecognitionOutput; transient gettable new G22Utils g22utils; delegate stdImageSurface to g22utils. delegate setupScriptCRUD to g22utils. delegate dbDir to g22utils. delegate showUIURL to uiURLs. delegate renderUIURL to uiURLs. transient new BackgroundProcessesUI backgroundProcessesUI; transient BackgroundProcessesUI.Entry bgScreenCam = backgroundProcessesUI.new Entry("Screen Cam") .menuItem(jMenuItem("Screen Cam", r showScreenCam)); transient BackgroundProcessesUI.Entry bgWebCam = backgroundProcessesUI.new Entry("Web Cam") .menuItem(jMenuItem("Web Cam", r showWebCam)); bool autoRunChallenge = true; transient G22ChallengesPanel challengesPanel; transient JComponent urlBar; transient JVideoLibDownloader videoLibDownloader; transient JFFMPEGVideoPlayer videoPlayer; // it's now actually persistent settableWithVar JPaintTool paintTool; // also persistent G22AnalysisPanel paintAnalysisPanel; // to detect when the project is moved. not implemented yet //settableWithVar File previousConceptsDir; transient G22SelfTests selfTests; settableWithVar bool paintToolGalleryExpanded; transient JComponent screenCamTab; // add fields here start { g22utils.module(this); testScreen.onChange(l0 change); dm_onFieldChange horizontalLayout( //r dm_revisualize // deh buggy r dm_reload ); /*if (concepts == null) { // non-standalone mode (doesn't work yet) printWithMS("Starting DB"); db(); concepts = db_mainConcepts(); } else assertSame(concepts, db_mainConcepts());*/ concepts.quietSave = true; // make indexes indexConceptField(concepts, GalleryImage, "path"); indexConceptField(concepts, Example, "item"); indexConceptFieldCI(concepts, G22Label, "name"); indexConceptField(concepts, G22Variable, "name"); g22utils.concepts(concepts); concepts.miscMapPut(G22Utils.class, g22utils); g22utils.backgroundProcessesUI(backgroundProcessesUI); // fix legacy bug for (c : list(concepts)) fixFieldValues(c); g22utils.onSettingUpParser(l1 modifyLeftArrowParser); g22utils.projectActions(this); g22utils.onSettingUpScriptIDE(ide -> { if (!haveMuricaPassword()) ret; var scp = scp(); addInFront(ide.buttons(), scp); ide.varCompileResult().onChange(cr -> { temp enter(); // Offer to add standard function or class to Gazelle (if authorized) var e = innerExceptionOfType(GazelleV_LeftArrowScriptParser.UnknownObject.class, cr?.compileError); if (e != null) { // An unknown object is referenced in the source. Let's hunt for it. if (isStandardFunction(e.name)) ret with scp.set(jbuttonWithDisable("Add function " + e.name, r { infoBoxAndCompile(addFunctionNameToInclude(functionsIncludeID(), e.name)); })); if (isStandardClass(e.name)) ret with scp.set(jbuttonWithDisable("Add class " + e.name, r { infoBoxAndCompile(addClassNameToInclude(functionsIncludeID(), e.name)); })); } scp.clear(); }); }); g22utils.autoStarter().init(); //g22utils.basicParserTest(); // update count in tab when tab isn't selected onConceptChangeByClass(concepts, Label, -> { labelCRUD?.updateEnclosingTabTitle(); //galleryCRUD?.updateEnclosingTabTitle(); }); uiURLs = new UIURLSystem(me(), dm_fieldLiveValue uiURL()); uiURLs.addPreferredUIURL("Main Tabs"); dm_watchFieldAndNow enabled(-> backgroundProcessesUI.addOrRemove(enabled, bgScreenCam)); scriptRunner = new JGazelleVScriptRunner(dm_fieldLiveValue script(me())); printWithMS("Making image stream"); imageStream.onNewElement(img -> { fpsCounter.inc(); setField(fps := iround(fpsCounter!)); // perform analysis on screen cam image // new G22_ImageAnalysis screenCamImageAnalysis; assertTrue("meta", getMetaSrc(img) instanceof ScreenShotMeta); Gazelle22_ImageToRegions itr = new(functionTimings, img, new SnPSettings(pixelRows, colors)); itr.run(); imageToRegions_finished = itr; // run "linear" script on image if any if (shouldRunScript()) rstRunScript.go(); // run left-arrow script if (screenCamScriptIDE != null && screenCamScriptIDE.visible()) try { g22_runPostAnalysisLeftArrowScript(itr, runningScreenCamScript); } catch e { printStackTrace(e); screenCamScriptIDE.showRuntimeError(e); } // make textual result of analysis S text = nRegions(itr.regions.regionCount()); setField(screenCamRecognitionOutput := text); // display image after analysis so we can highlight a region g22_renderPosterizedHighlightedImage(isPosterized, itr, showRegionsAsOutline); }); watchTargetSelector = new WatchTargetSelector; /*if (webCamAccessEnabled) { printWithMS("Detecting web cams"); watchTargetSelector.updateCamCount(); printWithMS("Found " + n2(availableWebCams, "web cam")); }*/ printWithMS("Starting screen cam"); ownResource(screenCamTimer = new FlexibleRateTimer(fpsTarget, rEnter { if (!enabled) ret; watchTargetSelector?.updateScreenCount(); Timestamp deadline = tsNowPlusMS(1000/fpsTarget); watchTarget?.mainWindow(getWindow(urlBar)); watchTarget?.configureScreenCamStream(imageStream); imageStream.step(); long remaining = deadline.minus(tsNow()); remainingMSPerFrame.add(remaining); setField(remainingMS := iround(remainingMSPerFrame!)); })); screenCamTimer.start(); dm_onFieldChange fpsTarget(-> screenCamTimer.setFrequencyImmediately(fpsTarget)); printWithMS("Gathering images from disk"); //addDirToGallery(galleryDir())); addDirToGallery(conceptsDir(concepts)); printWithMS("Got dem images"); transpileRaw_makeTranslator = -> hotwire(#7); // OSHI adds 4.5 MB to the jar... //doAfter(5.0, r { print("Process size: ", toM_str(oshi_currentProcessResidentSize_noZGCFix())) }); } // end of start method void addDirToGallery(File dir) { watchDirForGallery(dir); for (f : allImageFiles(dir)) addToGallery(f); } void watchDirForGallery(File dir) { fileWatcher if null = new FileWatchService; fileWatcher.addRecursiveListener(dir, file -> { if (isImageFile(file)) addToGallery(file); }); } // main window visualization cachedVisualize { isPosterized = stdImageSurface(); // if screen cam is not enabled, highlight regions of last captured image // on mouse hover imageSurfaceOnHover(isPosterized, pt -> { if (!enabled && imageToRegions_finished != null) g22_renderPosterizedHighlightedImage(isPosterized, imageToRegions_finished, showRegionsAsOutline); }); labelCRUD = new SimpleCRUD_v2(concepts, Label); labelCRUD.hideFields("globalID"); labelCRUD.addCountToEnclosingTab(true); labelCRUD.itemToMap_inner2 = l -> litorderedmap( "Name" := l.name, "# Examples" := n2(countConcepts(concepts, Example, label := l))); galleryCRUD = new SimpleCRUD_v2(concepts, GalleryImage); galleryCRUD.addCountToEnclosingTab(true); galleryCRUD.itemToMap_inner2 = img -> litorderedmap( "File" := fileName(img.path), "Folder" := dirPath(img.path)); galleryCRUD.defaultAction(img -> { thread { showImage(img.path) }}); galleryCRUDVis = galleryCRUD.visualize(); galleryCRUD.addButton(jPopDownButton_noText( "Forget missing images" := rThreadEnter forgetMissingImages )); galleryCRUD.addButton("Back to gallery", rThreadEnter { showUIURL("Gallery") }); galleryCRUD.newConcept = -> { new JFileChooser fc; fc.setDialogTitle("Add image to gallery"); fc.setCurrentDirectory(conceptsDir(concepts)); fc.setFileFilter(new ImageFileFilter().allowDirectories(true)); addToGallery(execFileChooser(fc)); }; // main visual watchScreenPane = borderlessScrollPane(jHigherScrollPane( jfullcenter(vstack( withLeftAndRightMargin(hstack( dm_rcheckBox enabled("Watch"), watchTargetSelector.visualize(), jlabel(" in "), withLabelToTheRight("colors @ ", dm_spinner colors(2, 256)), withLabelToTheRight("p", dm_powersOfTwoSpinner pixelRows(512)), )), verticalStrut(2), withSideMargins(centerAndEastWithMargin( dm_fieldLabel screenCamRecognitionOutput(), dm_transientCalculatedToolTip speedInfo_long(rightAlignLabel(dm_transientCalculatedLabel speedInfo())) )), )))); initUIURLs(); mainTabs = scrollingTabs(jTopOrLeftTabs(horizontalLayout)); addUIURLToMainTabs("Screen Cam"); addUIURLToMainTabs("Project Overview"); addUIURLToMainTabs("Paint"); addUIURLToMainTabs("Analyzers"); addUIURLToMainTabs("Scripts"); addUIURLToMainTabs("Scratchpad"); addUIURLToMainTabs("Gallery"); addUIURLToMainTabs("Projects"); // add tabs here // add main tabs to UI URLs (probably don't need this anymore) for (S tab : tabNames(mainTabs)) { reMutable tab = dropTrailingBracketedCount(tab); uiURLs.put(tab, -> { int i = indexOfTabNameWithoutTrailingCount(mainTabs, tab); if (i < 0) ret jcenteredlabel("Hmm. Tab not found"); selectTab(mainTabs, i); ret mainTabs; }); } // Fix UI URL after tab was changed manually // Hopefully doesn't brake stuff (seems it doesn't) onTabSelected(mainTabs, -> { if (!isShowing(mainTabs)) ret; S tabName = dropTrailingBracketedCount(selectedTabName(mainTabs)); if (!eqicOneOf(uiURL, "Main Tabs", tabName)) uiURLs.showUIURL("Main Tabs"); //uiURLs.showUIURL(tabName); }); var cbEnabled = toolTip("Switch screen cam on or off", dm_checkBox enabled("")); var lblScreenCam = setToolTip("Show scaled down and color-reduced screen image", jlabel("Screen Cam")); tabComponentClickFixer(lblScreenCam); screenCamTab = hstackWithSpacing(cbEnabled, lblScreenCam); addActionListener(cbEnabled, -> { if (enabled) selectTabComponent(mainTabs, screenCamTab); }); replaceTabTitleComponent(mainTabs, "Screen Cam", screenCamTab); // for tab titles challengesPanel?.updateCount(); labelCRUD?.update(); galleryCRUD?.update(); analyzersPanel().addCountToEnclosingTab(true); analyzersPanel().updateCount(); scriptsPanel().addCountToEnclosingTab(true); scriptsPanel().updateCount(); persistSelectedTabAsLiveValue(mainTabs, dm_fieldLiveValue selectedTab()); urlBar = uiURLs.urlBar(); focusOnFirstShow(urlBar); setToolTip(uiURLs.comboBox, "UI navigation system"); scpMain = singleComponentPanel(); uiURLs.scp(scpMain); showUIURL(uiURL); var lblDB = toolTip("Currently selected project (" + f2s(concepts.conceptsDir()) + ")", jSimpleLabel(conceptsDirName(concepts))); componentPopupMenuItems(lblDB, "Manage or open projects...", rThread { showUIURL("Projects")}); var vis = northAndCenter( withSideAndTopMargin( westCenterAndEast( //withLabelLeftAndRight("DB:", lblDB, "| "), withLabelToTheRight(lblDB, "| "), urlBar, withLeftMargin(backgroundProcessesUI.shortLabel()))), scpMain, ); g22utils.autoStarter().start(); if (autoRunSelfTests) { autoRunSelfTests = false; onFirstShow(vis, l0 runSelfTests); } ret vis; } void runSelfTests { thread "Self-Tests" { selfTests = new G22SelfTests(g22utils); selfTests.run(); selfTestsDone(); } } event selfTestsDone; JComponent screenCamPanel() { ret centerAndSouthOrEast(horizontalLayout, withTools(isPosterized), watchScreenPane); } JComponent screenCamPlusScriptPanel() enter { print("screenCamPlusScriptPanel"); //ret watchScreenPane; try { var ide = screenCamScriptIDE = leftArrowScriptIDE(); ide.runButtonShouldBeEnabled = -> eq(getText(ide.btnRun), "Stop") || ide.runButtonShouldBeEnabled_base(); ide.runScript = -> { if (eq(getText(ide.btnRun), "Stop")) runningScreenCamScript = null; else { runningScreenCamScript = screenCamScriptIDE.parsedScript(); ide.showStatus("Running"); } setText(ide.btnRun, runningScreenCamScript == null ? "Run" : "Stop"); }; ret centerAndSouthOrEast(horizontalLayout, //withTools( jhsplit( jscroll_centered_borderless(isPosterized), screenCamScriptIDE .lvScript(dm_fieldLiveValue screenCamScript()) .visualize()) //, isPosterized) , watchScreenPane); } on fail e { print(e); } } S speedInfo() { ret "FPS " + fps + " idle " + remainingMS + " ms"; } S speedInfo_long() { ret "Screen cam running at " + nFrames(fps) + "/second. " + n2(remainingMS) + " ms remaining per frame in first core" + " (of targeted " + fpsTarget + " FPS)"; } bool useErrorHandling() { false; } S renderFunctionTimings() { ret lines(ciSorted(map(functionTimings!, (f, avg) -> firstToUpper(f) + ": " + n2(iround(nsToMicroseconds(avg!))) + " " + microSymbol() + "s (" + n2(iround(avg.n())) + ")"))); } transient long _runScript_idx; void _runScript() { scriptRunner.parseAndRunOn(imageToRegions_finished.ii); } bool shouldRunScript() { ret isShowing(scriptRunner.scpScriptResult); } JComponent testScreenPanel() { ret withSideAndTopMargin(testScreen.visualize()); } L popDownItems() { ret ll(jCheckBoxMenuItem_dyn("Horizontal Layout", -> horizontalLayout, b -> setField(horizontalLayout := b))); } void unvisualize {} // don't zero transient component fields void resetTimings { functionTimings.reset(); } // add tool side bar to image surface JComponent withTools( JComponent component default jscroll_centered_borderless(is), ImageSurface is) { ret centerAndEastWithMargin(component, vstack( verticalStrut(5), jimageButtonScaledToWidth(16, #1103054, "Save screenshot in gallery", rThread saveScreenshotToGallery), /*jPopDownButton_noText( jCheckBoxMenuItem_dyn("Live scripting", -> liveScripting, b -> setLiveScripting(b) ),*/ ) ); } class WatchTargetSelector { JComboBox<WatchTarget> cb = jComboBox(); int screenCount, camCount; visualize { updateList(); //print("Selecting watchTarget: " + watchTarget); selectItem(cb, watchTarget); main onChange(cb, watchTarget -> { setField(+watchTarget); //print("Chose watchTarget: " + GazelleScreenCam.this.watchTarget); }); ret cb; } void updateScreenCount() { if (screenCount != screenCount()) updateList(); } void updateList() swing { setComboBoxItems(cb, makeWatchTargets()); } L<WatchTarget> makeWatchTargets() { ret flattenToList( countIteratorAsList_incl(1, screenCount = screenCount(), i -> WatchScreen(i)), new WatchMouse, new WatchScreenWithMouse, new WatchOtherScreen, ); } } JComponent wrapCRUD(S title, SimpleCRUD_v2 crud, JComponent vis default crud.visualize()) { ret crud == null ?: withTopAndBottomMargin(jCenteredRaisedSection(title, withMargin(vis))); } File galleryDir() { ret picturesDir(gazelle22_imagesSubDirName()); } void saveScreenshotToGallery enter { var img = imageStream!; addToGallery(saveImageWithCounter(galleryDir(), "Screenshot", img)); } void saveWebCamImageToGallery enter { var img = webCamPanel.getImage(); addToGallery(saveImageWithCounter(galleryDir(), "Webcam", img)); } GalleryImage addToGallery(File imgFile) { if (!isImageFile(imgFile)) null; var img = uniq(concepts, GalleryImage, path := imgFile); printVars("addToGallery", +imgFile, +img); ret img; } class StudyPanel { new G22SnPSelector snpSelector; GalleryImage image; BufferedImage originalImage; //ImageSurface isOriginal = stdImageSurface(); ImageSurface isOriginalWithRegions = stdImageSurface(); ImageSurface isPosterized = stdImageSurface(); SingleComponentPanel scp = singleComponentPanel(); SingleComponentPanel analysisPanel = singleComponentPanel(); SingleComponentPanel scpExampleCRUD = singleComponentPanel(); ConceptsComboBox<GalleryImage> cbImage = swing(-> new ConceptsComboBox<GalleryImage>(concepts, GalleryImage)); Gazelle22_ImageToRegions itr; int iSelectedRegion; SimpleCRUD_v2<SavedRegion> regionCRUD; SimpleCRUD_v2<Example> exampleCRUD; *() { print("Making StudyPanel " + this); //cbImage.sortTheList = l -> sortConceptsByIDDesc(l); cbImage.sortTheList = l -> sortedByComparator(l, (a, b) -> cmpAlphanumIC(fileName(a.path), fileName(b.path))); main onChangeAndNow(cbImage, img -> { /*print("Image selected 1: " + img); print("Me: " + me() + ", q thread: " + me().q().hasThread() + ", q jobs done: " + me().q().nJobsDone()); print("Module queue current job: " + me().q().currentJob());*/ dm_q(me(), r { print("Image selected: " + img); image = img; scp.setComponent(studyImagePanel()); }); }); isPosterized.removeAllTools(); isPosterized.onMousePositionChanged(r_dm_q(me(), l0 regionUpdate)); imageSurfaceOnLeftMouseDown(isPosterized, pt -> dm_q(me(), r { chooseRegionAt(pt) })); snpSelector.onChange(r_dm_q(me(), l0 runSnP)); } void chooseRegionAt(Pt p) { if (itr == null) ret; iSelectedRegion = itr.regions.regionAt(p); if (iSelectedRegion > 0) { var savedRegion = uniq_returnIfNew(concepts, SavedRegion, +image, snpSettings := snpSelector.settings.cloneMe(), regionIndex := iSelectedRegion); // it's new, add values if (savedRegion != null) { print("Saved new region!"); var bitMatrix = toScanlineBitMatrix(itr.regions.regionBitMatrix(iSelectedRegion)); cset(savedRegion, +bitMatrix); } } regionUpdate(); } // load new image JComponent studyImagePanel() { if (image == null) null; originalImage = loadImage2(image.path); if (originalImage == null) ret jcenteredlabel("Image not found"); //isOriginal.setImage(originalImage); isOriginalWithRegions.setImage(originalImage); iSelectedRegion = 0; itr = new Gazelle22_ImageToRegions(functionTimings, originalImage, snpSelector.settings); runSnP(); regionCRUD = new SimpleCRUD_v2<SavedRegion>(concepts, SavedRegion); regionCRUD.addFilter(+image); regionCRUD .showSearchBar(false) .showAddButton(false) .showEditButton(false) .iconButtons(true); regionCRUD.itemToMap_inner2 = region -> { var examples = conceptsWhere(concepts, Example, item := region); ret litorderedmap( "Pixels" := region.bitMatrix == null ? "-" : n2(region.bitMatrix.pixelCount()), //"Shape" := "TODO", "Labels" := joinWithComma(map(examples, e -> e.label)), // TODO: scale using snpsettings "Position" := region.bitMatrix == null ? "-" : region.bitMatrix.boundingBoxOfTrueBits()); }; var regionCRUDComponent = regionCRUD.visualize(); regionCRUD.onSelectionChanged(l0 updateExampleCRUD); ret hsplit( jtabs( //"Image" := jscroll_centered_borderless(isOriginal), "Image + regions" := jscroll_centered_borderless(isOriginalWithRegions), "Posterized" := jscroll_centered_borderless(isPosterized), ), northAndCenterWithMargin( analysisPanel, hsplit( jCenteredSection("Saved regions", regionCRUDComponent), scpExampleCRUD) )); } void runSnP { if (itr == null) ret; itr.run(); regionUpdate(); } void regionUpdate { if (itr == null) ret; var pixels = itr.posterized.getRGBPixels(); // hovering region marked green g22_highlightRegion(pixels, isPosterized, itr, showRegionsAsOutline); // selected region marked blue itr.regions.markRegionInPixelArray(pixels, iSelectedRegion, 0xFFADD8E6); var highlighted = bufferedImage(pixels, itr.posterized.getWidth(), itr.posterized.getHeight()); isPosterized.setImage(highlighted); isPosterized.performAutoZoom(); // seems to be necessary for some reason updateAnalysis(); } void updateAnalysis { /*new LS lines; lines.add(nRegions(itr.regions.regionCount())); lines.add("Selected region: " + iSelectedRegion); S text = lines_rtrim(lines); analysisPanel.setComponent(jLabel(text)));*/ } void updateExampleCRUD { var region = regionCRUD.selected(); if (region == null) ret with scpExampleCRUD.clear(); exampleCRUD = new SimpleCRUD_v2<Example>(concepts, Example); exampleCRUD.entityName = -> "label for region"; exampleCRUD.addFilter(item := region); exampleCRUD.showSearchBar(false); exampleCRUD.iconButtons(true); scpExampleCRUD.set(jCenteredSection("Labels for region", exampleCRUD.visualize())); } void importImage { new JFileChooser fc; if (fc.showOpenDialog(cbImage) == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile().getAbsoluteFile(); if (!isImageFile(file)) ret with infoMessage("Not an image file"); var img = addToGallery(file); waitUntil(250, 5.0, -> comboBoxContainsItem(cbImage, img)); setSelectedItem(cbImage, img); } } visual jRaisedSection(northAndCenterWithMargins( centerAndEast(withLabel("Study", cbImage), hstack( jlabel(" in "), snpSelector.visualize(), horizontalStrut(10), jPopDownButton_noText( "Import image...", rThreadEnter importImage, ), )), scp)); } // end of StudyPanel void initUIURLs { uiURLs.put("Main Tabs", -> horizontalLayout ? withMargin(mainTabs) : withSideMargin(mainTabs)); uiURLs.put("Screen Cam FPS", -> jFullCenter( vstackWithSpacing( jCenteredLabel("FPS target (frames per second) for screen cam:"), jFullCenter(dm_spinner fpsTarget(1, 60)), jCenteredLabel("(You can lower this value if you have a slower computer)")))); uiURLs.put("Timings", -> { JTextArea taTimings = jTextArea_noUndo(); awtEveryAndNow(taTimings, .5, r { setText(taTimings, renderFunctionTimings()) }); ret withRightAlignedButtons(taTimings, Reset := r resetTimings); }); uiURLs.put("Test Screen" := -> testScreenPanel()); //uiURLs.put("Operators" := -> operatorsPanel()); uiURLs.put("Settings" := -> settingsPanel()); uiURLs.put("System Info" := -> systemInfoPanel()); uiURLs.put("Web Cam" := -> webCamPanel()); uiURLs.put("Labels" := -> wrapCRUD("Labels", labelCRUD)); uiURLs.put(WithToolTip("Screen Cam + Linear Script", "Run a simple (linear) Gazelle V script") := -> withBottomMargin(scriptRunner.scriptAndResultPanel())); uiURLs.put(WithToolTip("Scratchpad", "Write and run a \"left-arrow script\"") := -> withBottomMargin(jOnDemand leftArrowScriptPanel())); uiURLs.put("Screen Cam + Script" := -> jOnDemand screenCamPlusScriptPanel()); uiURLs.put(WithToolTip("Gallery CRUD", "Gallery view with more functions (delete etc)") := -> wrapCRUD("Images", galleryCRUD, galleryCRUDVis)); uiURLs.put(WithToolTip("Paint", "Paint a picture for Gazelle with your mouse!") := -> withBottomMargin(paintPanel())); uiURLs.put(WithToolTip("Video", "A little video player (Note: no sound and doesn't handle some videos)") := -> withBottomMargin(videoPanel())); uiURLs.put(WithToolTip("Analyzers", "Manage image analyzers here") := -> withBottomMargin(analyzersPanel().visualize())); uiURLs.put(WithToolTip("Scripts", "Manage all left-arrow scripts here") := -> withBottomMargin(scriptsPanel().visualize())); uiURLs.put("Screen Cam" := -> jOnDemand screenCamPanel()) .put(WithToolTip("Study", "Here you can analyze gallery images") := -> withTopAndBottomMargin(studyPanel().visualize())) .put(WithToolTip("Java", "Write & run actual Java code") := -> withBottomMargin(jOnDemand javaPanel())) .put(WithToolTip("Gallery", "Gallery view with preview images") := -> galleryPanel().visualize()) .put(WithToolTip("Challenges", "Gazelle's self-tests") := -> challengesPanel()) .put(WithToolTip("Projects", "Manage/load Gazelle projects") := -> databasesPanel()) .put(WithToolTip("Entities", "Define entities (meta-level)") := -> entitiesPanel()) .put("Local Fonts" := -> localFontsPanel().visualize()) .put("Scripts from all DBs" := -> new G22ScriptsFromAllDBsPanel(g22utils).visualize()) .put("Files in project" := -> new G22DBFileBrowser(g22utils).visualize()) .put("HTML Editor Test" := -> new G22HtmlEditor().visualize()) .put("Project Overview" := -> new G22ProjectOverviewPanel(g22utils).visualize()) .put("Story" := -> new G22ProjectStoryEditor(g22utils).visualize()) .put("All objects by ID" := -> new G22AllConceptsPanel(g22utils).visualize()) .put("Variables" := -> new G22VariablesPanel(g22utils).visualize()) // add ui urls above this line ; } transient simplyCached G22LocalFontsPanel localFontsPanel() { ret new G22LocalFontsPanel(g22utils); } JComponent settingsPanel() { var cbMinimizeToTray = jCheckBox(isTrue(getOpt(dm_stem(), "minimizeToTray"))); onUpdate(cbMinimizeToTray, -> dm_callStem(me(), "setMinimizeToTray", isChecked(cbMinimizeToTray))); ret jscroll(makeForm3( "Minimize to tray", toolTip("Remove Gazelle from task bar when minimized (click Gazelle icon in system tray to reactivate)", cbMinimizeToTray), "Access web cams", dm_checkBox webCamAccessEnabled(), )); } File gazelleJar() { ret getBytecodePathForClass(this); } JComponent systemInfoPanel() { var gazelleJar = gazelleJar(); var cbMinimizeToTray = jCheckBox(isTrue(getOpt(dm_stem(), "minimizeToTray"))); onUpdate(cbMinimizeToTray, -> dm_callStem(me(), "setMinimizeToTray", isChecked(cbMinimizeToTray))); // Sadly, even jScrollVertical causes a bug in formLayouter1 that // makes the form grow horizontally without bounds ret /*jscrollVertical*/(makeForm3( "Java Version", jlabel(javaVersion()), "Gazelle Jar", JFilePathLabel(gazelleJar).visualize(), "Gazelle Jar Size", str_toMB_oneDigit(fileSize(gazelleJar)), "Memory use (objects)", jLabelShortCalcedEvery(1.0, -> str_toMB(usedMemory())), "Using Custom Classloader", yesNoShort(usingStarter(mc())), "Compilation Date", jlabel(or2(loadTextFileResource(classLoader(this), "compilation-date.txt"), "unknown")), "Gazelle Count" := toolTip("How many Gazelles are running in the world", jLiveValueLabel((LiveValue) dm_callOSOpt lvComputerCount())), "Gazelle Database" := JFilePathLabel(concepts.conceptsFile()).visualize(), "Gazelle Database Size" := str_toKB(fileSize(concepts.conceptsFile())), "Self-Tests" := jlabel(selfTests == null ? "Not run" : selfTests.status()), )); } JComponent operatorsPanel() { ret jcenteredlabel("TODO"); } JLeftArrowScriptIDE leftArrowScriptIDE() { ret g22utils.leftArrowIDE(); } void modifyLeftArrowParser(GazelleV_LeftArrowScriptParser parser) { parser.allowTheWorld(me(), mc(), utils.class, g22utils); } JComponent leftArrowScriptPanel() { var ide = leftArrowScriptIDE(); var btnSave = jImageButton(#1103084, "Save script", rThreadEnter saveAsNewScript); // place to the right of hideable stuff int idx = 0; while (getComponentAtIndex(ide.buttons(), idx) instanceof SingleComponentPanel) idx++; addComponentAtIndex(ide.buttons(), idx, btnSave); ide.sectionTitle("Left Arrow Script Scratchpad"); ide.lvScript(dm_fieldLiveValue newScript()); ret withTopMargin(ide.visualize()); } void saveAsNewScript { S text = newScript; inputText("Name for this script", description -> { temp enter(); // Note: This only works like this, i.e. when showUIURL is called // first. showUIURL("Scripts"); var script = cnewUnlisted(G22LeftArrowScript, +description, +text); scriptsPanel().selectAfterUpdate(script); concepts.register(script); }); } JComponent javaPanel() enter { var scpResult = singleComponentPanel(); new JMiniJavaIDE ide; ide.stringifier(g22utils.stringifier); ide.extraClassMembers = script -> { LS tok = javaTok(script); if (contains(tok, "draw")) ret [[ import java.awt.*; import java.awt.image.*; interface SimpleRenderable { void renderOn(Graphics2D g); } static BufferedImage draw(int w, int h, SimpleRenderable r) { BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics2D g = img.createGraphics(); g.setColor(Color.white); g.fillRect(0, 0, w, h); g.setColor(Color.black); r.renderOn(g); return img; } ]]; ret ""; }; ide.callCompiledObject = o -> { O result = ide.callCompiledObject_base(o); if (result cast BufferedImage) scpResult.set(jscroll_centered_borderless(stdImageSurface(result))); ret result; }; ide.lvScript(dm_fieldLiveValue javaCode()); ret jhsplit( jCenteredSection("Image will show here", scpResult), ide.visualize()); } JComponent webCamPanel() { if (cbWebCam == null) { fixContextClassLoader(); var cams = listWebCams(); cbWebCam = jTypedComboBox(cams, findWebCamByName(cams, webCamName)); } if (scpWebCamImage == null) scpWebCamImage = singleComponentPanel(); ret northAndCenterWithMargins( centerAndEastWithMargin( withLabel("Cam", cbWebCam), jline( jbutton("Start", rThreadEnter startWebCam), jbutton("Stop", rThreadEnter stopWebCam) )), scpWebCamImage); } void stopWebCam { if (webCamPanel != null) { webCamPanel.stop(); webCamPanel = null; scpWebCamImage?.clear(); backgroundProcessesUI.remove(bgWebCam); } } void startWebCam { temp tempInfoBox("Starting Web Cam"); stopWebCam(); var cam = getSelectedItem_typed(cbWebCam); setField(webCamName := cam?.getName()); if (cam != null) { scpWebCamImage.set( northAndCenterWithMargin( rightAlignedLine( jimageButtonScaledToWidth(16, #1103054, "Save web cam image in gallery", rThread saveWebCamImageToGallery) ), webCamPanel = new WebcamPanel(cam, true) )); backgroundProcessesUI.add(bgWebCam); } } void forgetMissingImages { int n = l(deleteConcepts(GalleryImage, img -> !img.imageExists())); infoBox(n == 0 ? "Nothing to forget" : "Forgot " + nImages(n)); } void addUIURLToMainTabs(S url) swing { if (containsTabNameWithoutTrailingCount(mainTabs, url)) ret; if (!uiURLs.hasURL(url)) ret with print("URL not found: " + url); addTab(mainTabs, WithToolTip(uiURLs.toolTipForURL(url), url), uiURLs.renderUIURL(url)); } void showScreenCam() { showUIURL("Screen Cam"); } void showWebCam() { showUIURL("Web Cam"); } JComponent challengesPanel() { if (challengesPanel == null) challengesPanel = new G22ChallengesPanel().g22utils(g22utils); ret challengesPanel.visualize(); } class GalleryPanel is Swingable { transient JGallery gallery; void selectImage(GalleryImage img) { if (img != null) gallery.selectFile(img.path); } cachedVisualize { var galleryImageSurface = stdImageSurface()/*.verbose(true)*/; gallery = new JGallery; gallery.horizontal(false); gallery.imageLoader().imageHeight(50); gallery.onAdaptingButton((button, file) -> { if (!devMode()) ret; componentPopupMenuItem(button, "Upload image...", rThread { uploadImageFileDialog(file) }); }); new AWTOnConceptChangesByClass(concepts, GalleryImage, gallery.visualize(), -> { print("Updating gallery"); var l = sortFilesAlphaNumIC(map(list(concepts, GalleryImage), i -> i.path)); gallery.setImageFiles(l); updateEnclosingTabTitleWithCount(gallery.visualize(), l(l)); }).install(); var analysisPanel = new G22AnalysisPanel; analysisPanel.editAnalyzer = l1 editAnalyzer; analysisPanel.g22utils(g22utils).imageSurface(galleryImageSurface); ownResource(analysisPanel); main onChange(analysisPanel, me()); gallery.openImage = img -> { galleryImageSurface.loadImage(img); analysisPanel.setImage(img); }; ret withBottomMargin( jvsplit(0.75, jhsplit(0.25, jCenteredSection("All Images", gallery.visualize()), jRaisedCenteredSection("Selected Image", withRightAlignedButtons(galleryImageSurface.visualize(), "Gallery CRUD" := r { showUIURL("Gallery CRUD") } ) ) ), analysisPanel.visualize() )); } } transient simplyCached GalleryPanel galleryPanel() { ret new GalleryPanel; } JComponent entitiesPanel() { if (entityCRUD == null) entityCRUD = new SimpleCRUD_v2(concepts, Entity); ret wrapCRUD("Entities", entityCRUD); } // for scripts Gazelle22_ImageToRegions imageToRegions(BufferedImage inputImage, SnPSettings snpSettings) { ret new Gazelle22_ImageToRegions(functionTimings, inputImage, snpSettings); } JComponent databasesPanel() { ret new G22DatabasesPanel(g22utils).visualize(); } transient simplyCached JComponent paintPanel() { if (paintToolGallery == null) { paintToolGallery = JGallery().horizontal(false); paintToolGallery.openImage = img -> paintTool.loadImageProtected(img); paintToolGallery.imageLoader().imageHeight(50); new AWTOnConceptChangesByClass(concepts, GalleryImage, paintToolGallery.visualize(), -> { var images = galleryImagesIn(conceptsDir(concepts)); print("Paint tool images: " + l(images)); paintToolGallery.setImageFiles(sortFilesAlphaNumIC(images)); }).install(); } if (paintTool == null) paintTool(new JPaintTool); ownResource(paintTool); main onChange(paintTool, me()); paintTool.createAutoPersistFile = -> makeFileNameUnique_beforeExtension_startWith1_noDot(conceptsDir(concepts, "Painting.png")); new JG22Labels labelsView; paintTool.bottomLeftControls = -> labelsView.visualize(); var paintToolVis = paintTool.visualize(); paintTool.imageSurface().defaultImageDir = -> g22utils.dbDir(); // migrating between directories - just make a new file if (!isDeepContainedInDir_canonical(paintTool.autoPersistFile(), conceptsDir(concepts))) paintTool.newImage(); paintTool.varAutoPersistFile().onChangeAndNow(imageFile -> { labelsView.setLabels(g22utils.labelsForFile(imageFile)); paintToolGallery.selectFile(imageFile); }); labelsView.addLabel = text -> { var imageFile = paintTool.autoPersistFile(); var labels = g22utils.labelsForFile(imageFile); labels.add(g22utils.getLabel(text)); print(+labels); g22utils.setLabelsForFile(imageFile, labels); labelsView.setLabels(labels); }; labelsView.removeLabel = label -> { var imageFile = paintTool.autoPersistFile(); var labels = g22utils.labelsForFile(imageFile); labels = listWithout(labels, label); g22utils.setLabelsForFile(imageFile, labels); labelsView.setLabels(labels); }; paintAnalysisPanel if null = new G22AnalysisPanel; paintAnalysisPanel.editAnalyzer = l1 editAnalyzer; paintAnalysisPanel.g22utils(g22utils).imageSurface(paintTool.imageSurface()); ownResource(paintAnalysisPanel); main onChange(paintAnalysisPanel, me()); paintTool.onImageChanged(img -> paintAnalysisPanel.setImage(img)); paintAnalysisPanel.setImage(paintTool.getImage()); var collapsiblePanel = CollapsibleLeftPanel(false, "Paintings", paintToolGallery.visualize(), paintToolVis); linkVars(varPaintToolGalleryExpanded(), collapsiblePanel.varExpanded()); paintToolGallery.varFiles().onChangeAndNow(files -> collapsiblePanel.sidePanelName(n2(files, "Painting"))); ret jvsplit(0.75, collapsiblePanel.visualize(), jRaisedCenteredSection("Image Analysis", paintAnalysisPanel.visualize())); } JComponent videoPanel() { if (videoLibDownloader == null) videoLibDownloader = new JVideoLibDownloader() .forward(-> videoPlayer().visualize()); ret videoLibDownloader.visualize(); } JFFMPEGVideoPlayer videoPlayer() { if (videoPlayer == null) videoPlayer = new JFFMPEGVideoPlayer; ret videoPlayer; } transient simplyCached G22AnalyzersPanel analyzersPanel() { ret new G22AnalyzersPanel(g22utils); } transient simplyCached G22ScriptsPanel scriptsPanel() { ret new G22ScriptsPanel(g22utils); } Cl<File> galleryImagesIn(File dir) { ret mapNonNulls(list(concepts, GalleryImage), i -> isDeepContainedInDir_absolute(i.path, dir) ? i.path : null); } void editAnalyzer(G22Recognizer analyzer) { if (analyzer == null) ret; analyzersPanel().edit(analyzer); showUIURL("Analyzers"); } O inlineScript(long scriptID, VarContext varContext) { var script = getConcept(concepts, G22LeftArrowScript, scriptID); if (script == null) fail("Script ID " + scriptID + " not found"); GazelleV_LeftArrowScript.Script parsedScript = script.compileSaved().parsedScript; ret parsedScript.get(varContext); } transient simplyCached StudyPanel studyPanel() { ret new StudyPanel; } SingleComponentPanel jOnDemand(IF0<JComponent> makeComponent) { ret main jOnDemand(-> { temp enter(); ret makeComponent?!; }); } // implementation of G22ProjectActions public void editScripts() { showUIURL("Scripts"); } public void editProjectStory() { showUIURL("Story"); } public void openObjectInProject(long id) { var c = getConcept(concepts, id); if (c == null) infoBox("Object ID not found in project: " + id); else openConcept(c); } public void openConcept(Concept c) { if (c cast G22Analyzer) { showUIURL("Analyzers"); analyzersPanel().setSelected(c); } else if (c cast G22LeftArrowScript) { showUIURL("Scripts"); scriptsPanel().setSelected(c); } else if (c cast G22GalleryImage) { showInGallery(c); } else infoBox("Don't know how to show " + c); } public void openPathInProject(S path) { path = trim(path); if (isInteger(path)) ret with openObjectInProject(parseLong(path)); if (uiURLs.hasURL(path)) ret with uiURLs.showUIURL(path); File f = newFile(dbDir(), path); print(+f); if (isFile(f)) { if (isImageFile(f)) { showInGallery(addToGallery(f)); } else infoBox("Unknown file type: " + fileName(f)); } else infoBox("Not a UI URL, object ID or project file: " + path); } void showInGallery(G22GalleryImage img) { if (img == null) ret; showUIURL("Gallery"); galleryPanel().selectImage(img); } BufferedImage getGalleryImage(long id) { var img = getConcept(concepts, G22GalleryImage, id); if (img == null) fail("Image not found: " + id); ret img.load(); } void cleanMeUp_g22utils { g22utils.close(); } public void waitUntilStarted aka waitForAutoStart() { g22utils.autoStarter().waitUntilDone(); } S functionsIncludeID() { ret #1034034; } void infoBoxAndCompile(S msg) { //topLeftInfoBox(msg); infoBox(msg); if (cic(msg, "edited")) dm_callOS("compile"); } JComponent visualizeJavaObject(O o) { ret wrap(G22JavaObjectVisualizer(g22utils, o)); } bool devMode() { ret haveMuricaPassword(); } } // end of module concept SavedRegion { new Ref image; // e.g. a GalleryImage SnPSettings snpSettings; int regionIndex; // region number relative to snpSettings //Rect bounds; // get it from bitMatrix instead ScanlineBitMatrix bitMatrix; //new RefL<Label> labels; } concept Example { new Ref<Label> label; new Ref item; // e.g. a SavedRegion double confidence = 1; } concept IfThenTheory { new Ref if_; new Ref then; } asclass WatchTarget { void mainWindow(Window window) {} abstract void configureScreenCamStream(ScreenCamStream stream); } // screenNr: 1 = screen 1 etc srecord WatchScreen(int screenNr) > WatchTarget { toString { ret "Screen " + screenNr; } void configureScreenCamStream(ScreenCamStream stream) { stream.useScreen(screenNr-1); } } srecord WatchMouse(int width, int height) > WatchTarget { WatchMouse() { height = 256; width = iround(height*16.0/9); } toString { ret "Mouse"; } void configureScreenCamStream(ScreenCamStream stream) { stream.area(mouseArea(width, height)); } } srecord WatchScreenWithMouse > WatchTarget { toString { ret "Screen w/mouse"; } void configureScreenCamStream(ScreenCamStream stream) { stream.useScreen(screenNrContaining(mouseLocationPt())); } } // Screen where Gazelle window is not srecord WatchOtherScreen > WatchTarget { toString { ret "Other Screen"; } transient void settable Window mainWindow; void configureScreenCamStream(ScreenCamStream stream) { stream.useScreen(mod(screenNrOfWindow(mainWindow)+1, numberOfScreens())); } } !include once #1034593 // Entity etc.
Began life as a copy of #1033862
download show line numbers debug dex old transpilations
Travelled to 2 computer(s): bhatertpkbcr, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1035021 |
Snippet name: | Gazelle Screen Cam / Gazelle 22 Module [backup] |
Eternal ID of this version: | #1035021/1 |
Text MD5: | 6722f1afd4244dd76520dd9a4943d8b2 |
Author: | stefan |
Category: | javax / gazelle v |
Type: | JavaX source code (Dynamic Module) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2022-03-23 01:33:04 |
Source code size: | 46978 bytes / 1423 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 122 / 128 |
Referenced in: | -