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

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