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

1648
LINES

< > BotCompany Repo | #1033862 // GazelleScreenCam [implementation of G22ProjectActions, Gazelle 22 main module]

JavaX source code (Dynamic Module) [tags: use-pretranspiled] - run with: Stefan's OS

Transpiled version (54188L) is out of date.

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

Author comment

Began life as a copy of #1033683

download  show line numbers  debug dex  old transpilations   

Travelled to 4 computer(s): bhatertpkbcr, mowyntqkapby, mqqgnosmbjvj, wnsclhtenguj

No comments. add comment

Snippet ID: #1033862
Snippet name: GazelleScreenCam [implementation of G22ProjectActions, Gazelle 22 main module]
Eternal ID of this version: #1033862/1113
Text MD5: 3b313a27c6e91b213243709959681b3f
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: 2023-01-07 21:21:03
Source code size: 54431 bytes / 1648 lines
Pitched / IR pitched: No / No
Views / Downloads: 702 / 6356
Version history: 1112 change(s)
Referenced in: [show references]