Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

1423
LINES

< > BotCompany Repo | #1035021 // Gazelle Screen Cam / Gazelle 22 Module [backup]

JavaX source code (Dynamic Module) - run with: Stefan's OS

1  
!7
2  
3  
need latest area.
4  
5  
// We're banning db_mainConcepts() again to allow multiple databases loaded at once
6  
7  
// !transpileMainSnippet #1033860
8  
9  
!include once #1033998 // RSyntaxTextArea
10  
!include once #1013490 // sarxos webcam
11  
12  
!include early #1034876 // Gazelle 22 Flags [Include]
13  
14  
!include early #1033884 // Compact Module Include Gazelle V [dev version]
15  
16  
!include once #1034034 // Gazelle 22 Function Include for Scripts
17  
18  
rewrite Challenge to G22Challenge.
19  
rewrite Label to G22Label.
20  
rewrite GalleryImage to G22GalleryImage.
21  
22  
module GazelleScreenCam is G22ProjectActions {
23  
  !include early #1025212 // +Enabled without visualization
24  
  { enabled = false; }
25  
26  
  transient static bool autoRunSelfTests = true;
27  
  
28  
  int pixelRows = 128, colors = 8;
29  
  S script = "64p 8c gradientImage";
30  
  S newScript;
31  
  S screenCamScript;
32  
  S selectedTab;
33  
  S javaCode;
34  
  bool horizontalLayout; // flat layout
35  
  int fpsTarget = 20;
36  
  S webCamName;
37  
  bool webCamAccessEnabled = true;
38  
  
39  
  WatchTarget watchTarget;
40  
  
41  
  new G22_TestScreenPanel testScreen;
42  
43  
  // The following fields related to the screen cam panel
44  
  transient ImageSurface isPosterized;
45  
  transient new ScreenCamStream imageStream;
46  
47  
  transient Gazelle22_ImageToRegions imageToRegions_finished;
48  
  transient new DoubleFPSCounter fpsCounter;
49  
  transient int fps;
50  
  transient WatchTargetSelector watchTargetSelector;
51  
  transient new RollingAverage remainingMSPerFrame;
52  
  transient int remainingMS;
53  
  // End of fields for screen cam panel
54  
  
55  
  transient new FunctionTimings<S> functionTimings;
56  
  
57  
  transient ReliableSingleThread rstRunScript = dm_rst(me(), r _runScript);
58  
  
59  
  transient JGazelleVScriptRunner scriptRunner;
60  
  
61  
  transient UIURLSystem uiURLs;
62  
63  
  //transient L<Webcam> availableWebCams;
64  
  transient JComboBox<Webcam> cbWebCam;
65  
  transient SingleComponentPanel scpWebCamImage;
66  
  transient WebcamPanel webCamPanel;
67  
68  
  transient JLeftArrowScriptIDE screenCamScriptIDE;
69  
  transient GazelleV_LeftArrowScript.Script runningScreenCamScript;
70  
  
71  
  // set by host
72  
  transient Concepts concepts;
73  
  
74  
  S uiURL = "Main Tabs";
75  
  
76  
  transient FileWatchService fileWatcher;
77  
  
78  
  transient SimpleCRUD_v2<Label> labelCRUD;
79  
  transient SimpleCRUD_v2<GalleryImage> galleryCRUD;
80  
  transient JComponent galleryCRUDVis;
81  
82  
  transient SimpleCRUD_v2<Entity> entityCRUD;
83  
84  
  transient JGallery /*gallery,*/ paintToolGallery;
85  
  //transient ImageSurface galleryImageSurface;
86  
87  
  transient FlexibleRateTimer screenCamTimer;
88  
  transient SingleComponentPanel scpMain;
89  
  transient JTabbedPane mainTabs;
90  
  transient bool showRegionsAsOutline = true;
91  
  transient JComponent watchScreenPane;
92  
  transient S screenCamRecognitionOutput;
93  
94  
  transient gettable new G22Utils g22utils;
95  
  delegate stdImageSurface to g22utils.
96  
  delegate setupScriptCRUD to g22utils.
97  
  delegate dbDir to g22utils.
98  
99  
  delegate showUIURL to uiURLs.
100  
  delegate renderUIURL to uiURLs.
101  
102  
  
103  
  transient new BackgroundProcessesUI backgroundProcessesUI;
104  
  
105  
  transient BackgroundProcessesUI.Entry bgScreenCam = backgroundProcessesUI.new Entry("Screen Cam")
106  
    .menuItem(jMenuItem("Screen Cam", r showScreenCam));
107  
  transient BackgroundProcessesUI.Entry bgWebCam = backgroundProcessesUI.new Entry("Web Cam")
108  
    .menuItem(jMenuItem("Web Cam", r showWebCam));
109  
110  
  bool autoRunChallenge = true;
111  
112  
  transient G22ChallengesPanel challengesPanel;
113  
114  
  transient JComponent urlBar;
115  
116  
  transient JVideoLibDownloader videoLibDownloader;
117  
  transient JFFMPEGVideoPlayer videoPlayer;
118  
119  
  // it's now actually persistent
120  
  settableWithVar JPaintTool paintTool;
121  
122  
  // also persistent
123  
  G22AnalysisPanel paintAnalysisPanel;
124  
  
125  
  // to detect when the project is moved. not implemented yet
126  
  //settableWithVar File previousConceptsDir;
127  
128  
  transient G22SelfTests selfTests;
129  
130  
  settableWithVar bool paintToolGalleryExpanded;
131  
  
132  
  transient JComponent screenCamTab;
133  
134  
  // add fields here
135  
136  
  start {
137  
    g22utils.module(this);
138  
    
139  
    testScreen.onChange(l0 change);
140  
    
141  
    dm_onFieldChange horizontalLayout(
142  
      //r dm_revisualize // deh buggy
143  
      r dm_reload
144  
    );
145  
    
146  
    /*if (concepts == null) {
147  
      // non-standalone mode (doesn't work yet)
148  
      printWithMS("Starting DB");
149  
      db();
150  
      concepts = db_mainConcepts();
151  
    } else
152  
      assertSame(concepts, db_mainConcepts());*/
153  
      
154  
    concepts.quietSave = true;
155  
156  
    // make indexes
157  
    indexConceptField(concepts, GalleryImage, "path");
158  
    indexConceptField(concepts, Example, "item");
159  
    indexConceptFieldCI(concepts, G22Label, "name");
160  
    indexConceptField(concepts, G22Variable, "name");
161  
162  
    g22utils.concepts(concepts);
163  
    concepts.miscMapPut(G22Utils.class, g22utils);
164  
    g22utils.backgroundProcessesUI(backgroundProcessesUI);
165  
166  
    // fix legacy bug
167  
    for (c : list(concepts)) fixFieldValues(c);
168  
169  
    g22utils.onSettingUpParser(l1 modifyLeftArrowParser);
170  
    g22utils.projectActions(this);
171  
    g22utils.onSettingUpScriptIDE(ide -> {
172  
      if (!haveMuricaPassword()) ret;
173  
      
174  
      var scp = scp();
175  
      addInFront(ide.buttons(), scp);
176  
      
177  
      ide.varCompileResult().onChange(cr -> {
178  
        temp enter();
179  
180  
        // Offer to add standard function or class to Gazelle (if authorized)
181  
        var e = innerExceptionOfType(GazelleV_LeftArrowScriptParser.UnknownObject.class, cr?.compileError);
182  
        if (e != null) {
183  
          // An unknown object is referenced in the source. Let's hunt for it.
184  
          
185  
          if (isStandardFunction(e.name))
186  
            ret with scp.set(jbuttonWithDisable("Add function " + e.name, r {
187  
              infoBoxAndCompile(addFunctionNameToInclude(functionsIncludeID(), e.name));
188  
            }));
189  
            
190  
          if (isStandardClass(e.name))
191  
            ret with scp.set(jbuttonWithDisable("Add class " + e.name, r {
192  
              infoBoxAndCompile(addClassNameToInclude(functionsIncludeID(), e.name));
193  
            }));
194  
        }
195  
 
196  
        scp.clear();
197  
      });
198  
    });
199  
200  
    g22utils.autoStarter().init();
201  
202  
    //g22utils.basicParserTest();
203  
    
204  
    // update count in tab when tab isn't selected
205  
    onConceptChangeByClass(concepts, Label, -> {
206  
      labelCRUD?.updateEnclosingTabTitle();
207  
      //galleryCRUD?.updateEnclosingTabTitle();
208  
    });
209  
    
210  
    uiURLs = new UIURLSystem(me(), dm_fieldLiveValue uiURL());
211  
    uiURLs.addPreferredUIURL("Main Tabs");
212  
213  
    dm_watchFieldAndNow enabled(-> backgroundProcessesUI.addOrRemove(enabled, bgScreenCam));
214  
    
215  
    scriptRunner = new JGazelleVScriptRunner(dm_fieldLiveValue script(me()));
216  
217  
    printWithMS("Making image stream");
218  
219  
    imageStream.onNewElement(img -> {
220  
      fpsCounter.inc();
221  
      setField(fps := iround(fpsCounter!));
222  
223  
      // perform analysis on screen cam image
224  
225  
      // new G22_ImageAnalysis screenCamImageAnalysis;
226  
      
227  
      assertTrue("meta", getMetaSrc(img) instanceof ScreenShotMeta);
228  
      Gazelle22_ImageToRegions itr = new(functionTimings, img, new SnPSettings(pixelRows, colors));
229  
      itr.run();
230  
      imageToRegions_finished = itr;
231  
232  
      // run "linear" script on image if any
233  
      
234  
      if (shouldRunScript()) rstRunScript.go();
235  
236  
      // run left-arrow script
237  
238  
      if (screenCamScriptIDE != null 
239  
        && screenCamScriptIDE.visible()) try {
240  
          g22_runPostAnalysisLeftArrowScript(itr, runningScreenCamScript);
241  
        } catch e {
242  
          printStackTrace(e);
243  
          screenCamScriptIDE.showRuntimeError(e);
244  
        }
245  
246  
      // make textual result of analysis
247  
      
248  
      S text = nRegions(itr.regions.regionCount());
249  
      setField(screenCamRecognitionOutput := text);
250  
      
251  
      // display image after analysis so we can highlight a region
252  
253  
      g22_renderPosterizedHighlightedImage(isPosterized, itr, showRegionsAsOutline);
254  
    });
255  
256  
    watchTargetSelector = new WatchTargetSelector;
257  
258  
    /*if (webCamAccessEnabled) {
259  
      printWithMS("Detecting web cams");
260  
      watchTargetSelector.updateCamCount();
261  
      printWithMS("Found " + n2(availableWebCams, "web cam"));
262  
    }*/
263  
264  
    printWithMS("Starting screen cam");
265  
    
266  
    ownResource(screenCamTimer = new FlexibleRateTimer(fpsTarget, rEnter {
267  
      if (!enabled) ret;
268  
      watchTargetSelector?.updateScreenCount();
269  
      Timestamp deadline = tsNowPlusMS(1000/fpsTarget);
270  
      watchTarget?.mainWindow(getWindow(urlBar));
271  
      watchTarget?.configureScreenCamStream(imageStream);
272  
      imageStream.step();
273  
      long remaining = deadline.minus(tsNow());
274  
      remainingMSPerFrame.add(remaining);
275  
      setField(remainingMS := iround(remainingMSPerFrame!));
276  
    }));
277  
    screenCamTimer.start();
278  
    dm_onFieldChange fpsTarget(-> screenCamTimer.setFrequencyImmediately(fpsTarget));
279  
280  
    printWithMS("Gathering images from disk");
281  
    //addDirToGallery(galleryDir()));
282  
    addDirToGallery(conceptsDir(concepts));
283  
    printWithMS("Got dem images");
284  
285  
    transpileRaw_makeTranslator = -> hotwire(#7);
286  
287  
    // OSHI adds 4.5 MB to the jar...
288  
    //doAfter(5.0, r { print("Process size: ", toM_str(oshi_currentProcessResidentSize_noZGCFix())) });
289  
  } // end of start method
290  
291  
  void addDirToGallery(File dir) {
292  
    watchDirForGallery(dir);
293  
    for (f : allImageFiles(dir))
294  
      addToGallery(f);
295  
  }
296  
  
297  
  void watchDirForGallery(File dir) {
298  
    fileWatcher if null = new FileWatchService;
299  
    fileWatcher.addRecursiveListener(dir, file -> {
300  
      if (isImageFile(file))
301  
        addToGallery(file);
302  
    });
303  
  }
304  
305  
  // main window visualization
306  
  cachedVisualize {
307  
    isPosterized = stdImageSurface();
308  
309  
    // if screen cam is not enabled, highlight regions of last captured image
310  
    // on mouse hover
311  
    
312  
    imageSurfaceOnHover(isPosterized, pt -> {
313  
      if (!enabled && imageToRegions_finished != null)
314  
        g22_renderPosterizedHighlightedImage(isPosterized, imageToRegions_finished,
315  
          showRegionsAsOutline);
316  
    });
317  
        
318  
    labelCRUD = new SimpleCRUD_v2(concepts, Label);
319  
    labelCRUD.hideFields("globalID");
320  
    labelCRUD.addCountToEnclosingTab(true);
321  
    labelCRUD.itemToMap_inner2 = l
322  
      -> litorderedmap(
323  
        "Name" := l.name,
324  
        "# Examples" := n2(countConcepts(concepts, Example, label := l)));
325  
    
326  
    galleryCRUD = new SimpleCRUD_v2(concepts, GalleryImage);
327  
    galleryCRUD.addCountToEnclosingTab(true);
328  
    galleryCRUD.itemToMap_inner2 = img
329  
      -> litorderedmap(
330  
        "File" := fileName(img.path),
331  
        "Folder" := dirPath(img.path));
332  
    galleryCRUD.defaultAction(img -> { thread { showImage(img.path) }});
333  
    galleryCRUDVis = galleryCRUD.visualize();
334  
    galleryCRUD.addButton(jPopDownButton_noText(
335  
      "Forget missing images" := rThreadEnter forgetMissingImages
336  
    ));
337  
    galleryCRUD.addButton("Back to gallery", rThreadEnter { showUIURL("Gallery") });
338  
    galleryCRUD.newConcept = -> {
339  
      new JFileChooser fc;
340  
      fc.setDialogTitle("Add image to gallery");
341  
      fc.setCurrentDirectory(conceptsDir(concepts));
342  
      fc.setFileFilter(new ImageFileFilter().allowDirectories(true));
343  
      addToGallery(execFileChooser(fc));
344  
    };
345  
    
346  
    // main visual
347  
348  
    watchScreenPane = borderlessScrollPane(jHigherScrollPane(
349  
      jfullcenter(vstack(
350  
        withLeftAndRightMargin(hstack(
351  
          dm_rcheckBox enabled("Watch"),
352  
          watchTargetSelector.visualize(),
353  
          jlabel(" in "),
354  
          withLabelToTheRight("colors @ ", dm_spinner colors(2, 256)),
355  
          withLabelToTheRight("p", dm_powersOfTwoSpinner pixelRows(512)),
356  
        )),
357  
        verticalStrut(2),
358  
        withSideMargins(centerAndEastWithMargin(
359  
          dm_fieldLabel screenCamRecognitionOutput(),
360  
          dm_transientCalculatedToolTip speedInfo_long(rightAlignLabel(dm_transientCalculatedLabel speedInfo()))
361  
        )),
362  
      ))));
363  
364  
    initUIURLs();
365  
366  
    mainTabs = scrollingTabs(jTopOrLeftTabs(horizontalLayout));
367  
368  
    addUIURLToMainTabs("Screen Cam");
369  
    addUIURLToMainTabs("Project Overview");
370  
    addUIURLToMainTabs("Paint");
371  
    addUIURLToMainTabs("Analyzers");
372  
    addUIURLToMainTabs("Scripts");
373  
    addUIURLToMainTabs("Scratchpad");
374  
    addUIURLToMainTabs("Gallery");
375  
    addUIURLToMainTabs("Projects");
376  
377  
    // add tabs here
378  
379  
    // add main tabs to UI URLs (probably don't need this anymore)
380  
    for (S tab : tabNames(mainTabs)) {
381  
      reMutable tab = dropTrailingBracketedCount(tab);
382  
      uiURLs.put(tab, -> {
383  
        int i = indexOfTabNameWithoutTrailingCount(mainTabs, tab);
384  
        if (i < 0) ret jcenteredlabel("Hmm. Tab not found");
385  
        selectTab(mainTabs, i);
386  
        ret mainTabs;
387  
      });
388  
    }
389  
390  
    // Fix UI URL after tab was changed manually
391  
    // Hopefully doesn't brake stuff (seems it doesn't)
392  
    onTabSelected(mainTabs, -> {
393  
      if (!isShowing(mainTabs)) ret;
394  
      S tabName = dropTrailingBracketedCount(selectedTabName(mainTabs));
395  
      if (!eqicOneOf(uiURL, "Main Tabs", tabName))
396  
        uiURLs.showUIURL("Main Tabs");
397  
        //uiURLs.showUIURL(tabName);
398  
    });
399  
400  
    var cbEnabled = toolTip("Switch screen cam on or off", dm_checkBox enabled(""));
401  
    var lblScreenCam = setToolTip("Show scaled down and color-reduced screen image",
402  
      jlabel("Screen Cam"));
403  
    tabComponentClickFixer(lblScreenCam);
404  
    screenCamTab = hstackWithSpacing(cbEnabled, lblScreenCam);
405  
    addActionListener(cbEnabled, -> { if (enabled) selectTabComponent(mainTabs, screenCamTab); });
406  
    
407  
    replaceTabTitleComponent(mainTabs, "Screen Cam", screenCamTab);
408  
    
409  
    // for tab titles
410  
    challengesPanel?.updateCount();
411  
    labelCRUD?.update();
412  
    galleryCRUD?.update();
413  
    analyzersPanel().addCountToEnclosingTab(true);
414  
    analyzersPanel().updateCount();
415  
    scriptsPanel().addCountToEnclosingTab(true);
416  
    scriptsPanel().updateCount();
417  
    
418  
    persistSelectedTabAsLiveValue(mainTabs, dm_fieldLiveValue selectedTab());
419  
420  
    urlBar = uiURLs.urlBar();
421  
    focusOnFirstShow(urlBar);
422  
    setToolTip(uiURLs.comboBox, "UI navigation system");
423  
424  
    scpMain = singleComponentPanel();
425  
    uiURLs.scp(scpMain);
426  
427  
    showUIURL(uiURL);
428  
429  
    var lblDB = toolTip("Currently selected project (" + f2s(concepts.conceptsDir()) + ")",
430  
      jSimpleLabel(conceptsDirName(concepts)));
431  
    componentPopupMenuItems(lblDB,
432  
      "Manage or open projects...",
433  
        rThread { showUIURL("Projects")});
434  
    
435  
    var vis = northAndCenter(
436  
      withSideAndTopMargin(
437  
        westCenterAndEast(
438  
          //withLabelLeftAndRight("DB:", lblDB, "| "),
439  
          withLabelToTheRight(lblDB, "| "),
440  
          urlBar,
441  
          withLeftMargin(backgroundProcessesUI.shortLabel()))),
442  
      scpMain,
443  
    );
444  
445  
    g22utils.autoStarter().start();
446  
447  
    if (autoRunSelfTests) {
448  
      autoRunSelfTests = false;
449  
      onFirstShow(vis, l0 runSelfTests);
450  
    }
451  
452  
    ret vis;
453  
  }
454  
455  
  void runSelfTests {
456  
    thread "Self-Tests" {
457  
      selfTests = new G22SelfTests(g22utils);
458  
      selfTests.run();
459  
      selfTestsDone();
460  
    }
461  
  }
462  
463  
  event selfTestsDone;
464  
465  
  JComponent screenCamPanel() {
466  
    ret centerAndSouthOrEast(horizontalLayout,
467  
      withTools(isPosterized),
468  
      watchScreenPane);
469  
  }
470  
  
471  
  JComponent screenCamPlusScriptPanel() enter {
472  
    print("screenCamPlusScriptPanel");
473  
    //ret watchScreenPane;
474  
    try {
475  
      var ide = screenCamScriptIDE = leftArrowScriptIDE();
476  
      ide.runButtonShouldBeEnabled = ->
477  
         eq(getText(ide.btnRun), "Stop")
478  
          || ide.runButtonShouldBeEnabled_base();
479  
      
480  
      ide.runScript = -> {
481  
        if (eq(getText(ide.btnRun), "Stop"))
482  
          runningScreenCamScript = null;
483  
        else {
484  
          runningScreenCamScript = screenCamScriptIDE.parsedScript();
485  
          ide.showStatus("Running");
486  
        }
487  
        setText(ide.btnRun,
488  
          runningScreenCamScript == null ? "Run" : "Stop");
489  
      };
490  
      
491  
      ret centerAndSouthOrEast(horizontalLayout,
492  
        //withTools(
493  
          jhsplit(
494  
            jscroll_centered_borderless(isPosterized),
495  
            screenCamScriptIDE
496  
              .lvScript(dm_fieldLiveValue screenCamScript())
497  
              .visualize())
498  
        //, isPosterized)
499  
        , watchScreenPane);
500  
    } on fail e { print(e); }
501  
  }
502  
  
503  
  S speedInfo() {
504  
    ret "FPS " + fps + " idle " + remainingMS + " ms";
505  
  }
506  
  
507  
  S speedInfo_long() {
508  
    ret "Screen cam running at " + nFrames(fps) + "/second. " + n2(remainingMS) + " ms remaining per frame in first core"
509  
      + " (of targeted " + fpsTarget + " FPS)";
510  
  }
511  
  
512  
  bool useErrorHandling() { false; }
513  
  
514  
  S renderFunctionTimings() {
515  
    ret lines(ciSorted(map(functionTimings!, (f, avg) ->
516  
      firstToUpper(f) + ": " + n2(iround(nsToMicroseconds(avg!))) + " " + microSymbol() + "s (" + n2(iround(avg.n())) + ")")));
517  
  }
518  
  
519  
  transient long _runScript_idx;
520  
521  
  void _runScript() {
522  
    scriptRunner.parseAndRunOn(imageToRegions_finished.ii);
523  
  }
524  
  
525  
  bool shouldRunScript() {
526  
    ret isShowing(scriptRunner.scpScriptResult);
527  
  }
528  
  
529  
  JComponent testScreenPanel() {
530  
    ret withSideAndTopMargin(testScreen.visualize());
531  
  }
532  
  
533  
  L popDownItems() {
534  
    ret ll(jCheckBoxMenuItem_dyn("Horizontal Layout",
535  
      -> horizontalLayout,
536  
      b -> setField(horizontalLayout := b)));
537  
  }
538  
  
539  
  void unvisualize {} // don't zero transient component fields
540  
  
541  
  void resetTimings { functionTimings.reset(); }
542  
  
543  
  // add tool side bar to image surface
544  
  JComponent withTools(
545  
    JComponent component default jscroll_centered_borderless(is),
546  
    ImageSurface is) {
547  
    ret centerAndEastWithMargin(component,
548  
      vstack(
549  
        verticalStrut(5),
550  
        jimageButtonScaledToWidth(16, #1103054, "Save screenshot in gallery", rThread saveScreenshotToGallery),
551  
        /*jPopDownButton_noText(
552  
          jCheckBoxMenuItem_dyn("Live scripting", -> liveScripting, b -> setLiveScripting(b)
553  
        ),*/
554  
      )
555  
    );
556  
  }
557  
  
558  
  class WatchTargetSelector {
559  
    JComboBox<WatchTarget> cb = jComboBox();
560  
    int screenCount, camCount;
561  
    
562  
    visualize {
563  
      updateList();
564  
      //print("Selecting watchTarget: " + watchTarget);
565  
      selectItem(cb, watchTarget);
566  
      main onChange(cb, watchTarget -> {
567  
        setField(+watchTarget);
568  
        //print("Chose watchTarget: " + GazelleScreenCam.this.watchTarget);
569  
      });
570  
      ret cb;
571  
    }
572  
    
573  
    void updateScreenCount() {
574  
      if (screenCount != screenCount())
575  
        updateList();
576  
    }
577  
578  
    void updateList() swing {
579  
      setComboBoxItems(cb, makeWatchTargets());
580  
    }
581  
    
582  
    L<WatchTarget> makeWatchTargets() {
583  
      ret flattenToList(
584  
        countIteratorAsList_incl(1, screenCount = screenCount(),
585  
          i -> WatchScreen(i)),
586  
        new WatchMouse,
587  
        new WatchScreenWithMouse,
588  
        new WatchOtherScreen,
589  
      );
590  
    }
591  
  }
592  
593  
  JComponent wrapCRUD(S title, SimpleCRUD_v2 crud, JComponent vis default crud.visualize()) {
594  
    ret crud == null ?: withTopAndBottomMargin(jCenteredRaisedSection(title, withMargin(vis)));
595  
  }
596  
  
597  
  File galleryDir() {
598  
    ret picturesDir(gazelle22_imagesSubDirName());
599  
  }
600  
  
601  
  void saveScreenshotToGallery enter {
602  
    var img = imageStream!;
603  
    addToGallery(saveImageWithCounter(galleryDir(), "Screenshot", img));
604  
  }
605  
  
606  
  void saveWebCamImageToGallery enter {
607  
    var img = webCamPanel.getImage();
608  
    addToGallery(saveImageWithCounter(galleryDir(), "Webcam", img));
609  
  }
610  
  
611  
  GalleryImage addToGallery(File imgFile) {
612  
    if (!isImageFile(imgFile)) null;
613  
    var img = uniq(concepts, GalleryImage, path := imgFile);
614  
    printVars("addToGallery", +imgFile, +img);
615  
    ret img;
616  
  }
617  
618  
  class StudyPanel {
619  
    new G22SnPSelector snpSelector;
620  
    GalleryImage image;
621  
    BufferedImage originalImage;
622  
    //ImageSurface isOriginal = stdImageSurface();
623  
    ImageSurface isOriginalWithRegions = stdImageSurface();
624  
    ImageSurface isPosterized = stdImageSurface();
625  
    SingleComponentPanel scp = singleComponentPanel();
626  
    SingleComponentPanel analysisPanel = singleComponentPanel();
627  
    SingleComponentPanel scpExampleCRUD = singleComponentPanel();
628  
    ConceptsComboBox<GalleryImage> cbImage = swing(->
629  
      new ConceptsComboBox<GalleryImage>(concepts, GalleryImage));
630  
    Gazelle22_ImageToRegions itr;
631  
    int iSelectedRegion;
632  
    SimpleCRUD_v2<SavedRegion> regionCRUD;
633  
    SimpleCRUD_v2<Example> exampleCRUD;
634  
635  
    *() {
636  
      print("Making StudyPanel " + this);
637  
      //cbImage.sortTheList = l -> sortConceptsByIDDesc(l);
638  
      cbImage.sortTheList = l -> sortedByComparator(l, (a, b)
639  
        -> cmpAlphanumIC(fileName(a.path), fileName(b.path)));
640  
641  
      main onChangeAndNow(cbImage, img -> {
642  
        /*print("Image selected 1: " + img);
643  
        print("Me: " + me() + ", q thread: " + me().q().hasThread()
644  
          + ", q jobs done: " + me().q().nJobsDone());
645  
        print("Module queue current job: " + me().q().currentJob());*/
646  
        dm_q(me(), r {
647  
          print("Image selected: " + img);
648  
          image = img;
649  
          scp.setComponent(studyImagePanel());
650  
        });
651  
      });
652  
653  
      isPosterized.removeAllTools();
654  
      isPosterized.onMousePositionChanged(r_dm_q(me(), l0 regionUpdate));
655  
656  
      imageSurfaceOnLeftMouseDown(isPosterized, pt -> dm_q(me(), r { chooseRegionAt(pt) }));
657  
658  
      snpSelector.onChange(r_dm_q(me(), l0 runSnP));
659  
    }
660  
661  
    void chooseRegionAt(Pt p) {
662  
      if (itr == null) ret;
663  
      iSelectedRegion = itr.regions.regionAt(p);
664  
665  
      if (iSelectedRegion > 0) {
666  
        var savedRegion = uniq_returnIfNew(concepts, SavedRegion,
667  
          +image,
668  
          snpSettings := snpSelector.settings.cloneMe(),
669  
          regionIndex := iSelectedRegion);
670  
671  
        // it's new, add values
672  
        if (savedRegion != null) {
673  
          print("Saved new region!");
674  
          var bitMatrix = toScanlineBitMatrix(itr.regions.regionBitMatrix(iSelectedRegion));
675  
          cset(savedRegion, +bitMatrix);
676  
        }
677  
      }
678  
      
679  
      regionUpdate();
680  
    }
681  
682  
    // load new image
683  
    JComponent studyImagePanel() { 
684  
      if (image == null) null;
685  
      originalImage = loadImage2(image.path);
686  
      if (originalImage == null) ret jcenteredlabel("Image not found");
687  
688  
      //isOriginal.setImage(originalImage);
689  
      isOriginalWithRegions.setImage(originalImage);
690  
691  
      iSelectedRegion = 0;
692  
      itr = new Gazelle22_ImageToRegions(functionTimings, originalImage, snpSelector.settings);
693  
      runSnP();
694  
695  
      regionCRUD = new SimpleCRUD_v2<SavedRegion>(concepts, SavedRegion);
696  
      regionCRUD.addFilter(+image);
697  
      regionCRUD
698  
        .showSearchBar(false)
699  
        .showAddButton(false)
700  
        .showEditButton(false)
701  
        .iconButtons(true);
702  
        
703  
      regionCRUD.itemToMap_inner2 = region -> {
704  
        var examples = conceptsWhere(concepts, Example, item := region);
705  
        
706  
        ret litorderedmap(
707  
          "Pixels" := region.bitMatrix == null ? "-" : n2(region.bitMatrix.pixelCount()),
708  
          //"Shape" := "TODO",
709  
          "Labels" := joinWithComma(map(examples, e -> e.label)),
710  
711  
          // TODO: scale using snpsettings
712  
          "Position" := region.bitMatrix == null ? "-" : region.bitMatrix.boundingBoxOfTrueBits());
713  
      };
714  
715  
      var regionCRUDComponent = regionCRUD.visualize();
716  
      regionCRUD.onSelectionChanged(l0 updateExampleCRUD);
717  
718  
      ret hsplit(
719  
        jtabs(
720  
          //"Image" := jscroll_centered_borderless(isOriginal),
721  
          "Image + regions" := jscroll_centered_borderless(isOriginalWithRegions),
722  
          "Posterized" := jscroll_centered_borderless(isPosterized),
723  
        ),
724  
        northAndCenterWithMargin(
725  
          analysisPanel,
726  
          hsplit(
727  
            jCenteredSection("Saved regions", regionCRUDComponent),
728  
            scpExampleCRUD)
729  
          ));
730  
    }
731  
732  
    void runSnP {
733  
      if (itr == null) ret;
734  
      itr.run();
735  
      regionUpdate();
736  
    }
737  
738  
    void regionUpdate {
739  
      if (itr == null) ret;
740  
741  
      var pixels = itr.posterized.getRGBPixels();
742  
      
743  
      // hovering region marked green
744  
      g22_highlightRegion(pixels, isPosterized, itr, showRegionsAsOutline);
745  
746  
      // selected region marked blue
747  
      itr.regions.markRegionInPixelArray(pixels, iSelectedRegion, 0xFFADD8E6);
748  
749  
      var highlighted = bufferedImage(pixels, itr.posterized.getWidth(), itr.posterized.getHeight());
750  
751  
      isPosterized.setImage(highlighted);
752  
      isPosterized.performAutoZoom(); // seems to be necessary for some reason
753  
754  
      updateAnalysis();
755  
    }
756  
757  
    void updateAnalysis {
758  
      /*new LS lines;
759  
      lines.add(nRegions(itr.regions.regionCount()));
760  
      lines.add("Selected region: " + iSelectedRegion);
761  
      S text = lines_rtrim(lines);
762  
      analysisPanel.setComponent(jLabel(text)));*/
763  
    }
764  
765  
    void updateExampleCRUD {
766  
      var region = regionCRUD.selected();
767  
      if (region == null) ret with scpExampleCRUD.clear();
768  
      
769  
      exampleCRUD = new SimpleCRUD_v2<Example>(concepts, Example);
770  
      exampleCRUD.entityName = -> "label for region";
771  
      exampleCRUD.addFilter(item := region);
772  
      exampleCRUD.showSearchBar(false);
773  
      exampleCRUD.iconButtons(true);
774  
      scpExampleCRUD.set(jCenteredSection("Labels for region",
775  
        exampleCRUD.visualize()));
776  
    }
777  
778  
    void importImage {
779  
      new JFileChooser fc;
780  
      if (fc.showOpenDialog(cbImage) == JFileChooser.APPROVE_OPTION) {
781  
        File file = fc.getSelectedFile().getAbsoluteFile();
782  
        if (!isImageFile(file)) ret with infoMessage("Not an image file");
783  
        var img = addToGallery(file);
784  
        waitUntil(250, 5.0, -> comboBoxContainsItem(cbImage, img));
785  
        setSelectedItem(cbImage, img);
786  
      }
787  
    }
788  
789  
    visual
790  
      jRaisedSection(northAndCenterWithMargins(
791  
        centerAndEast(withLabel("Study", cbImage),
792  
          hstack(
793  
            jlabel(" in "),
794  
            snpSelector.visualize(),
795  
            horizontalStrut(10),
796  
            jPopDownButton_noText(
797  
              "Import image...", rThreadEnter importImage,
798  
            ),
799  
            )),
800  
        scp));
801  
  } // end of StudyPanel
802  
803  
  void initUIURLs {
804  
    uiURLs.put("Main Tabs", ->
805  
      horizontalLayout ? withMargin(mainTabs) : withSideMargin(mainTabs));
806  
      
807  
    uiURLs.put("Screen Cam FPS", -> jFullCenter(
808  
      vstackWithSpacing(
809  
        jCenteredLabel("FPS target (frames per second) for screen cam:"),
810  
        jFullCenter(dm_spinner fpsTarget(1, 60)),
811  
        jCenteredLabel("(You can lower this value if you have a slower computer)"))));
812  
813  
    uiURLs.put("Timings", -> {
814  
      JTextArea taTimings = jTextArea_noUndo();
815  
      awtEveryAndNow(taTimings, .5, r {
816  
        setText(taTimings, renderFunctionTimings())
817  
      });
818  
      ret withRightAlignedButtons(taTimings,
819  
        Reset := r resetTimings);
820  
    });
821  
822  
    uiURLs.put("Test Screen" := -> testScreenPanel());
823  
824  
    //uiURLs.put("Operators" := -> operatorsPanel());
825  
826  
    uiURLs.put("Settings" := -> settingsPanel());
827  
828  
    uiURLs.put("System Info" := -> systemInfoPanel());
829  
830  
    uiURLs.put("Web Cam" := -> webCamPanel());
831  
832  
    uiURLs.put("Labels" := -> wrapCRUD("Labels", labelCRUD));
833  
834  
    uiURLs.put(WithToolTip("Screen Cam + Linear Script", "Run a simple (linear) Gazelle V script")
835  
      := -> withBottomMargin(scriptRunner.scriptAndResultPanel()));
836  
      
837  
    uiURLs.put(WithToolTip("Scratchpad", "Write and run a \"left-arrow script\"")
838  
      := -> withBottomMargin(jOnDemand leftArrowScriptPanel()));
839  
      
840  
    uiURLs.put("Screen Cam + Script" := -> jOnDemand screenCamPlusScriptPanel());
841  
842  
    uiURLs.put(WithToolTip("Gallery CRUD", "Gallery view with more functions (delete etc)")
843  
      := -> wrapCRUD("Images", galleryCRUD, galleryCRUDVis));
844  
845  
    uiURLs.put(WithToolTip("Paint", "Paint a picture for Gazelle with your mouse!")
846  
      := -> withBottomMargin(paintPanel()));
847  
848  
    uiURLs.put(WithToolTip("Video", "A little video player (Note: no sound and doesn't handle some videos)")
849  
      := -> withBottomMargin(videoPanel()));
850  
    
851  
    uiURLs.put(WithToolTip("Analyzers", "Manage image analyzers here")
852  
      := -> withBottomMargin(analyzersPanel().visualize()));
853  
854  
    uiURLs.put(WithToolTip("Scripts", "Manage all left-arrow scripts here")
855  
      := -> withBottomMargin(scriptsPanel().visualize()));
856  
857  
    uiURLs.put("Screen Cam" := -> jOnDemand screenCamPanel())
858  
859  
      .put(WithToolTip("Study", "Here you can analyze gallery images")
860  
        := -> withTopAndBottomMargin(studyPanel().visualize()))
861  
      
862  
      .put(WithToolTip("Java", "Write & run actual Java code")
863  
        := -> withBottomMargin(jOnDemand javaPanel()))
864  
        
865  
      .put(WithToolTip("Gallery", "Gallery view with preview images")
866  
        := -> galleryPanel().visualize())
867  
          
868  
      .put(WithToolTip("Challenges", "Gazelle's self-tests")
869  
        := -> challengesPanel())
870  
871  
      .put(WithToolTip("Projects", "Manage/load Gazelle projects")
872  
        := -> databasesPanel())
873  
        
874  
      .put(WithToolTip("Entities", "Define entities (meta-level)")
875  
        := -> entitiesPanel())
876  
877  
      .put("Local Fonts" := -> localFontsPanel().visualize())
878  
879  
      .put("Scripts from all DBs" := -> new G22ScriptsFromAllDBsPanel(g22utils).visualize())
880  
881  
      .put("Files in project" := -> new G22DBFileBrowser(g22utils).visualize())
882  
883  
      .put("HTML Editor Test" := -> new G22HtmlEditor().visualize())
884  
885  
      .put("Project Overview" := -> new G22ProjectOverviewPanel(g22utils).visualize())
886  
887  
      .put("Story" := -> new G22ProjectStoryEditor(g22utils).visualize())
888  
889  
      .put("All objects by ID" := -> new G22AllConceptsPanel(g22utils).visualize())
890  
891  
      .put("Variables" := -> new G22VariablesPanel(g22utils).visualize())
892  
893  
      // add ui urls above this line
894  
    ;
895  
  }
896  
897  
  transient simplyCached G22LocalFontsPanel localFontsPanel() { ret new G22LocalFontsPanel(g22utils); }
898  
899  
  JComponent settingsPanel() {
900  
    var cbMinimizeToTray = jCheckBox(isTrue(getOpt(dm_stem(), "minimizeToTray")));
901  
    onUpdate(cbMinimizeToTray, -> dm_callStem(me(), "setMinimizeToTray", isChecked(cbMinimizeToTray)));
902  
    ret jscroll(makeForm3( 
903  
      "Minimize to tray", toolTip("Remove Gazelle from task bar when minimized (click Gazelle icon in system tray to reactivate)", cbMinimizeToTray),
904  
      "Access web cams", dm_checkBox webCamAccessEnabled(),
905  
    ));
906  
  }
907  
908  
  File gazelleJar() {
909  
    ret getBytecodePathForClass(this);
910  
  }
911  
912  
  JComponent systemInfoPanel() {
913  
    var gazelleJar = gazelleJar();
914  
    var cbMinimizeToTray = jCheckBox(isTrue(getOpt(dm_stem(), "minimizeToTray")));
915  
    onUpdate(cbMinimizeToTray, -> dm_callStem(me(), "setMinimizeToTray", isChecked(cbMinimizeToTray)));
916  
    // Sadly, even jScrollVertical causes a bug in formLayouter1 that
917  
    // makes the form grow horizontally without bounds
918  
    ret /*jscrollVertical*/(makeForm3( 
919  
      "Java Version", jlabel(javaVersion()),
920  
      "Gazelle Jar", JFilePathLabel(gazelleJar).visualize(),
921  
      "Gazelle Jar Size", str_toMB_oneDigit(fileSize(gazelleJar)),
922  
      "Memory use (objects)", jLabelShortCalcedEvery(1.0, -> str_toMB(usedMemory())),
923  
      "Using Custom Classloader", yesNoShort(usingStarter(mc())),
924  
      "Compilation Date", jlabel(or2(loadTextFileResource(classLoader(this), "compilation-date.txt"), "unknown")),
925  
      "Gazelle Count" := toolTip("How many Gazelles are running in the world",
926  
        jLiveValueLabel((LiveValue) dm_callOSOpt lvComputerCount())),
927  
      "Gazelle Database" := JFilePathLabel(concepts.conceptsFile()).visualize(),
928  
      "Gazelle Database Size" := str_toKB(fileSize(concepts.conceptsFile())),
929  
      "Self-Tests" := jlabel(selfTests == null ? "Not run" : selfTests.status()),
930  
    ));
931  
  }
932  
933  
  JComponent operatorsPanel() {
934  
    ret jcenteredlabel("TODO");
935  
  }
936  
937  
  JLeftArrowScriptIDE leftArrowScriptIDE() {
938  
    ret g22utils.leftArrowIDE();
939  
  }
940  
941  
  void modifyLeftArrowParser(GazelleV_LeftArrowScriptParser parser) {
942  
    parser.allowTheWorld(me(), mc(), utils.class, g22utils);
943  
  }
944  
945  
  JComponent leftArrowScriptPanel() {
946  
    var ide = leftArrowScriptIDE();
947  
948  
    var btnSave = jImageButton(#1103084, "Save script", rThreadEnter saveAsNewScript);
949  
    
950  
    // place to the right of hideable stuff
951  
    int idx = 0;
952  
    while (getComponentAtIndex(ide.buttons(), idx) instanceof SingleComponentPanel) idx++;
953  
    addComponentAtIndex(ide.buttons(), idx, btnSave);
954  
      
955  
    ide.sectionTitle("Left Arrow Script Scratchpad");
956  
    ide.lvScript(dm_fieldLiveValue newScript());
957  
    ret withTopMargin(ide.visualize());
958  
  }
959  
960  
  void saveAsNewScript {
961  
    S text = newScript;
962  
    inputText("Name for this script", description -> {
963  
      temp enter();
964  
      
965  
      // Note: This only works like this, i.e. when showUIURL is called
966  
      // first.
967  
      
968  
      showUIURL("Scripts");
969  
      var script = cnewUnlisted(G22LeftArrowScript, +description, +text);
970  
      scriptsPanel().selectAfterUpdate(script);
971  
      concepts.register(script);
972  
    });
973  
  }
974  
975  
  JComponent javaPanel() enter {
976  
    var scpResult = singleComponentPanel();
977  
    
978  
    new JMiniJavaIDE ide;
979  
    ide.stringifier(g22utils.stringifier);
980  
    ide.extraClassMembers = script -> {
981  
      LS tok = javaTok(script);
982  
983  
      if (contains(tok, "draw")) ret [[
984  
        import java.awt.*;
985  
        import java.awt.image.*;
986  
        
987  
        interface SimpleRenderable {
988  
          void renderOn(Graphics2D g);
989  
        }
990  
        
991  
        static BufferedImage draw(int w, int h, SimpleRenderable r) {
992  
          BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
993  
          Graphics2D g = img.createGraphics();
994  
          g.setColor(Color.white);
995  
          g.fillRect(0, 0, w, h);
996  
          g.setColor(Color.black);
997  
          r.renderOn(g);
998  
          return img;
999  
        }
1000  
      ]];
1001  
        
1002  
      ret "";
1003  
    };
1004  
1005  
    ide.callCompiledObject = o -> {
1006  
      O result = ide.callCompiledObject_base(o);
1007  
      if (result cast BufferedImage)
1008  
        scpResult.set(jscroll_centered_borderless(stdImageSurface(result)));
1009  
      ret result;
1010  
    };
1011  
    
1012  
    ide.lvScript(dm_fieldLiveValue javaCode());
1013  
    ret jhsplit(
1014  
      jCenteredSection("Image will show here", scpResult),
1015  
      ide.visualize());
1016  
  }
1017  
1018  
  JComponent webCamPanel() {
1019  
    if (cbWebCam == null) {
1020  
      fixContextClassLoader();
1021  
      var cams = listWebCams();
1022  
      cbWebCam = jTypedComboBox(cams,
1023  
        findWebCamByName(cams, webCamName));
1024  
    }
1025  
1026  
    if (scpWebCamImage == null) scpWebCamImage = singleComponentPanel();
1027  
    
1028  
    ret northAndCenterWithMargins(
1029  
      centerAndEastWithMargin(
1030  
        withLabel("Cam", cbWebCam),
1031  
        jline(
1032  
          jbutton("Start", rThreadEnter startWebCam),
1033  
          jbutton("Stop", rThreadEnter stopWebCam)
1034  
        )),
1035  
      scpWebCamImage);
1036  
  }
1037  
1038  
  void stopWebCam {
1039  
    if (webCamPanel != null) {
1040  
      webCamPanel.stop();
1041  
      webCamPanel = null;
1042  
      scpWebCamImage?.clear();
1043  
      backgroundProcessesUI.remove(bgWebCam);
1044  
    }
1045  
  }
1046  
1047  
  void startWebCam {
1048  
    temp tempInfoBox("Starting Web Cam");
1049  
    stopWebCam();
1050  
    var cam = getSelectedItem_typed(cbWebCam);
1051  
    setField(webCamName := cam?.getName());
1052  
    if (cam != null) {
1053  
      scpWebCamImage.set(
1054  
        northAndCenterWithMargin(
1055  
          rightAlignedLine(
1056  
            jimageButtonScaledToWidth(16, #1103054, "Save web cam image in gallery", rThread saveWebCamImageToGallery)
1057  
          ),
1058  
          webCamPanel = new WebcamPanel(cam, true)
1059  
      ));
1060  
      backgroundProcessesUI.add(bgWebCam);
1061  
    }
1062  
  }
1063  
  
1064  
  void forgetMissingImages {
1065  
    int n = l(deleteConcepts(GalleryImage, img -> !img.imageExists()));
1066  
    infoBox(n == 0 ? "Nothing to forget" : "Forgot " + nImages(n));
1067  
  }
1068  
1069  
  void addUIURLToMainTabs(S url) swing {
1070  
    if (containsTabNameWithoutTrailingCount(mainTabs, url)) ret;
1071  
    if (!uiURLs.hasURL(url)) ret with print("URL not found: " + url);
1072  
    
1073  
    addTab(mainTabs, WithToolTip(uiURLs.toolTipForURL(url), url),
1074  
      uiURLs.renderUIURL(url));
1075  
  }
1076  
1077  
  void showScreenCam() { showUIURL("Screen Cam"); }
1078  
  void showWebCam() { showUIURL("Web Cam"); }
1079  
1080  
  JComponent challengesPanel() { 
1081  
    if (challengesPanel == null)
1082  
      challengesPanel = new G22ChallengesPanel().g22utils(g22utils);
1083  
    ret challengesPanel.visualize();
1084  
  }
1085  
1086  
  class GalleryPanel is Swingable {
1087  
    transient JGallery gallery;
1088  
    
1089  
    void selectImage(GalleryImage img) {
1090  
      if (img != null) gallery.selectFile(img.path);
1091  
    }
1092  
      
1093  
    cachedVisualize {
1094  
      var galleryImageSurface = stdImageSurface()/*.verbose(true)*/;
1095  
      gallery = new JGallery;
1096  
      gallery.horizontal(false);
1097  
      gallery.imageLoader().imageHeight(50);
1098  
      gallery.onAdaptingButton((button, file) -> {
1099  
        if (!devMode()) ret;
1100  
        componentPopupMenuItem(button, "Upload image...",
1101  
          rThread { uploadImageFileDialog(file) });
1102  
      });
1103  
        
1104  
      new AWTOnConceptChangesByClass(concepts, GalleryImage, gallery.visualize(), -> {
1105  
        print("Updating gallery");
1106  
        var l = sortFilesAlphaNumIC(map(list(concepts, GalleryImage), i -> i.path));
1107  
        gallery.setImageFiles(l);
1108  
        updateEnclosingTabTitleWithCount(gallery.visualize(), l(l));
1109  
      }).install();
1110  
1111  
      var analysisPanel = new G22AnalysisPanel;
1112  
      analysisPanel.editAnalyzer = l1 editAnalyzer;
1113  
      analysisPanel.g22utils(g22utils).imageSurface(galleryImageSurface);
1114  
      ownResource(analysisPanel);
1115  
      main onChange(analysisPanel, me());
1116  
1117  
      gallery.openImage = img -> {
1118  
        galleryImageSurface.loadImage(img);
1119  
        analysisPanel.setImage(img);
1120  
      };
1121  
      
1122  
      ret withBottomMargin(
1123  
        jvsplit(0.75,
1124  
          jhsplit(0.25,
1125  
            jCenteredSection("All Images", gallery.visualize()),
1126  
            jRaisedCenteredSection("Selected Image",
1127  
              withRightAlignedButtons(galleryImageSurface.visualize(),
1128  
                "Gallery CRUD" := r { showUIURL("Gallery CRUD") }
1129  
              )
1130  
            )
1131  
          ),
1132  
          analysisPanel.visualize()
1133  
        ));
1134  
    }
1135  
  }
1136  
1137  
  transient simplyCached GalleryPanel galleryPanel() { ret new GalleryPanel; }
1138  
  
1139  
  JComponent entitiesPanel() { 
1140  
    if (entityCRUD == null)
1141  
      entityCRUD = new SimpleCRUD_v2(concepts, Entity);
1142  
    ret wrapCRUD("Entities", entityCRUD);
1143  
  }
1144  
  
1145  
  // for scripts
1146  
  Gazelle22_ImageToRegions imageToRegions(BufferedImage inputImage, SnPSettings snpSettings) {
1147  
    ret new Gazelle22_ImageToRegions(functionTimings, inputImage, snpSettings);
1148  
  }
1149  
1150  
  JComponent databasesPanel() {
1151  
    ret new G22DatabasesPanel(g22utils).visualize();
1152  
  }
1153  
1154  
  transient simplyCached JComponent paintPanel() {
1155  
    if (paintToolGallery == null) {
1156  
      paintToolGallery = JGallery().horizontal(false);
1157  
      paintToolGallery.openImage = img -> paintTool.loadImageProtected(img);
1158  
      paintToolGallery.imageLoader().imageHeight(50);
1159  
      
1160  
      new AWTOnConceptChangesByClass(concepts, GalleryImage, paintToolGallery.visualize(), -> {
1161  
        var images = galleryImagesIn(conceptsDir(concepts));
1162  
        print("Paint tool images: " + l(images));
1163  
        paintToolGallery.setImageFiles(sortFilesAlphaNumIC(images));
1164  
      }).install();
1165  
    }
1166  
    
1167  
    if (paintTool == null) paintTool(new JPaintTool);
1168  
    ownResource(paintTool);
1169  
    main onChange(paintTool, me());
1170  
1171  
    paintTool.createAutoPersistFile =
1172  
      -> makeFileNameUnique_beforeExtension_startWith1_noDot(conceptsDir(concepts, "Painting.png"));
1173  
    
1174  
    new JG22Labels labelsView;
1175  
    paintTool.bottomLeftControls = -> labelsView.visualize();
1176  
1177  
    var paintToolVis = paintTool.visualize();
1178  
1179  
    paintTool.imageSurface().defaultImageDir = -> g22utils.dbDir();
1180  
1181  
    // migrating between directories - just make a new file
1182  
    if (!isDeepContainedInDir_canonical(paintTool.autoPersistFile(), conceptsDir(concepts)))
1183  
      paintTool.newImage();
1184  
1185  
    paintTool.varAutoPersistFile().onChangeAndNow(imageFile -> {
1186  
      labelsView.setLabels(g22utils.labelsForFile(imageFile));
1187  
      paintToolGallery.selectFile(imageFile);
1188  
    });
1189  
    labelsView.addLabel = text -> {
1190  
      var imageFile = paintTool.autoPersistFile();
1191  
      var labels = g22utils.labelsForFile(imageFile);
1192  
      labels.add(g22utils.getLabel(text));
1193  
      print(+labels);
1194  
      g22utils.setLabelsForFile(imageFile, labels);
1195  
      labelsView.setLabels(labels);
1196  
    };
1197  
    
1198  
    labelsView.removeLabel = label -> {
1199  
      var imageFile = paintTool.autoPersistFile();
1200  
      var labels = g22utils.labelsForFile(imageFile);
1201  
      labels = listWithout(labels, label);
1202  
      g22utils.setLabelsForFile(imageFile, labels);
1203  
      labelsView.setLabels(labels);
1204  
    };
1205  
1206  
    paintAnalysisPanel if null = new G22AnalysisPanel;
1207  
    paintAnalysisPanel.editAnalyzer = l1 editAnalyzer;
1208  
    paintAnalysisPanel.g22utils(g22utils).imageSurface(paintTool.imageSurface());
1209  
    ownResource(paintAnalysisPanel);
1210  
    main onChange(paintAnalysisPanel, me());
1211  
1212  
    paintTool.onImageChanged(img -> paintAnalysisPanel.setImage(img));
1213  
    paintAnalysisPanel.setImage(paintTool.getImage());
1214  
1215  
    var collapsiblePanel = CollapsibleLeftPanel(false, "Paintings",
1216  
      paintToolGallery.visualize(), paintToolVis);
1217  
    linkVars(varPaintToolGalleryExpanded(), collapsiblePanel.varExpanded());
1218  
    paintToolGallery.varFiles().onChangeAndNow(files -> collapsiblePanel.sidePanelName(n2(files, "Painting")));
1219  
1220  
    ret jvsplit(0.75,
1221  
      collapsiblePanel.visualize(),
1222  
      jRaisedCenteredSection("Image Analysis", paintAnalysisPanel.visualize()));
1223  
  }
1224  
1225  
  JComponent videoPanel() {
1226  
    if (videoLibDownloader == null)
1227  
      videoLibDownloader = new JVideoLibDownloader()
1228  
        .forward(-> videoPlayer().visualize());
1229  
    ret videoLibDownloader.visualize();
1230  
  }
1231  
1232  
  JFFMPEGVideoPlayer videoPlayer() {
1233  
    if (videoPlayer == null)
1234  
      videoPlayer = new JFFMPEGVideoPlayer;
1235  
    ret videoPlayer;
1236  
  }
1237  
1238  
  transient simplyCached G22AnalyzersPanel analyzersPanel() {
1239  
    ret new G22AnalyzersPanel(g22utils);
1240  
  }
1241  
1242  
  transient simplyCached G22ScriptsPanel scriptsPanel() {
1243  
    ret new G22ScriptsPanel(g22utils);
1244  
  }
1245  
1246  
  Cl<File> galleryImagesIn(File dir) {
1247  
    ret mapNonNulls(list(concepts, GalleryImage),
1248  
      i -> isDeepContainedInDir_absolute(i.path, dir) ? i.path : null);
1249  
  }
1250  
1251  
  void editAnalyzer(G22Recognizer analyzer) {
1252  
    if (analyzer == null) ret;
1253  
    analyzersPanel().edit(analyzer);
1254  
    showUIURL("Analyzers");
1255  
  }
1256  
1257  
  O inlineScript(long scriptID, VarContext varContext) {
1258  
    var script = getConcept(concepts, G22LeftArrowScript, scriptID);
1259  
    if (script == null) fail("Script ID " + scriptID + " not found");
1260  
    GazelleV_LeftArrowScript.Script parsedScript = script.compileSaved().parsedScript;
1261  
    ret parsedScript.get(varContext);
1262  
  }
1263  
1264  
  transient simplyCached StudyPanel studyPanel() { ret new StudyPanel; }
1265  
1266  
  SingleComponentPanel jOnDemand(IF0<JComponent> makeComponent) {
1267  
    ret main jOnDemand(-> { temp enter(); ret makeComponent?!; });
1268  
  }
1269  
1270  
  // implementation of G22ProjectActions
1271  
1272  
  public void editScripts() {
1273  
    showUIURL("Scripts");
1274  
  }
1275  
1276  
  public void editProjectStory() {
1277  
    showUIURL("Story");
1278  
  }
1279  
1280  
  public void openObjectInProject(long id) {
1281  
    var c = getConcept(concepts, id);
1282  
    if (c == null)
1283  
      infoBox("Object ID not found in project: " + id);
1284  
    else
1285  
      openConcept(c);
1286  
  }
1287  
1288  
  public void openConcept(Concept c) {
1289  
    if (c cast G22Analyzer) {
1290  
      showUIURL("Analyzers");
1291  
      analyzersPanel().setSelected(c);
1292  
    } else if (c cast G22LeftArrowScript) {
1293  
      showUIURL("Scripts");
1294  
      scriptsPanel().setSelected(c);
1295  
    } else if (c cast G22GalleryImage) {
1296  
      showInGallery(c);
1297  
    } else
1298  
      infoBox("Don't know how to show " + c);
1299  
  }
1300  
  
1301  
  public void openPathInProject(S path) {
1302  
    path = trim(path);
1303  
    
1304  
    if (isInteger(path))
1305  
      ret with openObjectInProject(parseLong(path));
1306  
1307  
    if (uiURLs.hasURL(path))
1308  
      ret with uiURLs.showUIURL(path);
1309  
      
1310  
    File f = newFile(dbDir(), path);
1311  
    print(+f);
1312  
    if (isFile(f)) {
1313  
      if (isImageFile(f)) {
1314  
        showInGallery(addToGallery(f));
1315  
      } else
1316  
        infoBox("Unknown file type: " + fileName(f));
1317  
    } else
1318  
      infoBox("Not a UI URL, object ID or project file: " + path);
1319  
  }
1320  
1321  
  void showInGallery(G22GalleryImage img) {
1322  
    if (img == null) ret;
1323  
    showUIURL("Gallery");
1324  
    galleryPanel().selectImage(img);
1325  
  }
1326  
1327  
  BufferedImage getGalleryImage(long id) {
1328  
    var img = getConcept(concepts, G22GalleryImage, id);
1329  
    if (img == null) fail("Image not found: " + id);
1330  
    ret img.load();
1331  
  }
1332  
1333  
  void cleanMeUp_g22utils {
1334  
    g22utils.close();
1335  
  }
1336  
1337  
  public void waitUntilStarted aka waitForAutoStart() {
1338  
    g22utils.autoStarter().waitUntilDone();
1339  
  }
1340  
1341  
  S functionsIncludeID() { ret #1034034; }
1342  
1343  
  void infoBoxAndCompile(S msg) {
1344  
    //topLeftInfoBox(msg);
1345  
    infoBox(msg);
1346  
    if (cic(msg, "edited"))
1347  
      dm_callOS("compile");
1348  
  }
1349  
1350  
  JComponent visualizeJavaObject(O o) {
1351  
    ret wrap(G22JavaObjectVisualizer(g22utils, o));
1352  
  }
1353  
  
1354  
  bool devMode() { ret haveMuricaPassword(); }
1355  
} // end of module
1356  
1357  
concept SavedRegion {
1358  
  new Ref image; // e.g. a GalleryImage
1359  
  SnPSettings snpSettings;
1360  
  int regionIndex; // region number relative to snpSettings
1361  
  //Rect bounds; // get it from bitMatrix instead
1362  
  ScanlineBitMatrix bitMatrix;
1363  
  //new RefL<Label> labels;
1364  
}
1365  
1366  
concept Example {
1367  
  new Ref<Label> label;
1368  
  new Ref item; // e.g. a SavedRegion
1369  
  double confidence = 1;
1370  
}
1371  
1372  
concept IfThenTheory {
1373  
  new Ref if_;
1374  
  new Ref then;
1375  
}
1376  
1377  
asclass WatchTarget {
1378  
  void mainWindow(Window window) {}
1379  
  abstract void configureScreenCamStream(ScreenCamStream stream);
1380  
}
1381  
1382  
// screenNr: 1 = screen 1 etc
1383  
srecord WatchScreen(int screenNr) > WatchTarget {
1384  
  toString { ret "Screen " + screenNr; }
1385  
1386  
  void configureScreenCamStream(ScreenCamStream stream) {
1387  
    stream.useScreen(screenNr-1);
1388  
  }
1389  
}
1390  
1391  
srecord WatchMouse(int width, int height) > WatchTarget {
1392  
  WatchMouse() {
1393  
    height = 256;
1394  
    width = iround(height*16.0/9);
1395  
  }
1396  
  
1397  
  toString { ret "Mouse"; }
1398  
  
1399  
  void configureScreenCamStream(ScreenCamStream stream) {
1400  
    stream.area(mouseArea(width, height));
1401  
  }
1402  
}
1403  
1404  
srecord WatchScreenWithMouse > WatchTarget {
1405  
  toString { ret "Screen w/mouse"; }
1406  
1407  
  void configureScreenCamStream(ScreenCamStream stream) {
1408  
    stream.useScreen(screenNrContaining(mouseLocationPt()));
1409  
  }
1410  
}
1411  
1412  
// Screen where Gazelle window is not
1413  
srecord WatchOtherScreen > WatchTarget {
1414  
  toString { ret "Other Screen"; }
1415  
1416  
  transient void settable Window mainWindow;
1417  
1418  
  void configureScreenCamStream(ScreenCamStream stream) {
1419  
    stream.useScreen(mod(screenNrOfWindow(mainWindow)+1, numberOfScreens()));
1420  
  }
1421  
}
1422  
1423  
!include once #1034593 // Entity etc.

Author comment

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: 121 / 127
Referenced in: [show references]