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

1046
LINES

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

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

Uses 4324K of libraries. Click here for Pure Java version (31276L/171K).

!7

// Note: It's ok again to use db_mainConcepts()

!include early #1033884 // Compact Module Include Gazelle V [dev version]

need latest onEnter.

rewrite Challenge to G22Challenge.

module GazelleScreenCam {
  !include early #1025212 // +Enabled without visualization
  
  int pixelRows = 128, colors = 8;
  S script = "64p 8c gradientImage";
  S newScript;
  S screenCamScript;
  S selectedTab;
  S javaCode;
  S recognizerScript;
  bool horizontalLayout; // flat layout
  int fpsTarget = 20;
  S webCamName;
  bool webCamAccessEnabled = true;
  
  WatchTarget watchTarget;
  
  new G22_TestScreenPanel testScreen;

  transient ImageSurface isPosterized;
  transient new ScreenCamStream imageStream;
  
  transient Gazelle22_ImageToRegions imageToRegions_finished;
  transient new DoubleFPSCounter fpsCounter;
  transient int fps;
  transient WatchTargetSelector watchTargetSelector;
  transient new RollingAverage remainingMSPerFrame;
  transient int remainingMS;
  
  transient new FunctionTimings<S> functionTimings;
  
  transient ReliableSingleThread rstRunScript = dm_rst(me(), r _runScript);
  
  transient JGazelleVScriptRunner scriptRunner;
  
  transient UIURLSystem uiURLs;

  //transient L<Webcam> availableWebCams;
  transient JComboBox<Webcam> cbWebCam;
  transient SingleComponentPanel scpWebCamImage;
  transient WebcamPanel webCamPanel;

  transient JLeftArrowScriptIDE screenCamScriptIDE;
  transient GazelleV_LeftArrowScript.Script runningScreenCamScript;
  
  // set by host
  transient Concepts concepts;
  
  S uiURL = "Main Tabs";
  
  transient FileWatchService fileWatcher;
  
  transient SimpleCRUD_v2<Label> labelCRUD;
  transient SimpleCRUD_v2<GalleryImage> imageCRUD;
  transient JComponent imageCRUDVis;

  transient JGallery gallery;
  transient JComponent galleryComponent;

  transient SimpleCRUD_v2<Challenge> challengeCRUD;
  transient SingleComponentPanel scpChallengePanel, scpChallengeCode;

  transient SimpleCRUD_v2<G22RecognizerScript> recognizerCRUD;
  
  transient FlexibleRateTimer screenCamTimer;
  transient SingleComponentPanel scpMain;
  transient JTabbedPane mainTabs;
  transient bool showRegionsAsOutline = true;
  transient JComponent watchScreenPane;
  transient S screenCamRecognitionOutput;

  transient new G22Utils g22utils;
  delegate stdImageSurface to g22utils.
  
  delegate showUIURL to uiURLs.
  delegate renderUIURL to uiURLs.

  transient BackgroundProcessesUI backgroundProcessesUI;
  
  transient BackgroundProcessesUI.Entry bgScreenCam = new("Screen Cam")
    .menuItem(jMenuItem("Screen Cam", r showScreenCam));
  transient BackgroundProcessesUI.Entry bgWebCam = new("Web Cam")
    .menuItem(jMenuItem("Web Cam", r showWebCam));

  // add fields here

  start {
    testScreen.onChange(l0 change);
    
    dm_onFieldChange horizontalLayout(
      //r dm_revisualize // deh buggy
      r dm_reload
    );
    
    if (concepts == null) {
      // non-standalone mode (doesn't work yet)
      printWithMS("Starting DB");
      db();
      concepts = db_mainConcepts();
    } else
      assertSame(concepts, db_mainConcepts());
      
    concepts.quietSave = true;

    // make indexes
    indexConceptField(concepts, GalleryImage, "path");
    indexConceptField(concepts, Example, "item");

    g22utils.modifyLeftArrowParser = l1 modifyLeftArrowParser;

    g22utils.basicParserTest();
    
    // update count in tab when tab isn't selected
    onConceptChanges(concepts, -> {
      labelCRUD?.updateEnclosingTabTitle();
      //imageCRUD?.updateEnclosingTabTitle();
      updateEnclosingTabTitleWithCount(galleryComponent, countConcepts(GalleryImage));
    });
    
    uiURLs = new UIURLSystem(me(), dm_fieldLiveValue uiURL());
    uiURLs.addPreferredUIURL("Main Tabs");

    backgroundProcessesUI = new BackgroundProcessesUI;

    dm_watchFieldAndNow enabled(-> backgroundProcessesUI.addOrRemove(enabled, bgScreenCam));
    
    scriptRunner = new JGazelleVScriptRunner(dm_fieldLiveValue script(me()));

    printWithMS("Making image stream");

    imageStream.onNewElement(img -> {
      fpsCounter.inc();
      setField(fps := iround(fpsCounter!));

      // perform analysis on screen cam image

      // new G22_ImageAnalysis screenCamImageAnalysis;
      
      assertTrue("meta", getMetaSrc(img) instanceof ScreenShotMeta);
      Gazelle22_ImageToRegions itr = new(functionTimings, img, new SnPSettings(pixelRows, colors));
      itr.run();
      imageToRegions_finished = itr;

      // run "linear" script on image if any
      
      if (shouldRunScript()) rstRunScript.go();

      // run left-arrow script

      if (screenCamScriptIDE != null 
        && screenCamScriptIDE.visible()) try {
          g22_runPostAnalysisLeftArrowScript(itr, runningScreenCamScript);
        } catch e {
          printStackTrace(e);
          screenCamScriptIDE.showRuntimeError(e);
        }

      // make textual result of analysis
      
      S text = nRegions(itr.regions.regionCount());
      setField(screenCamRecognitionOutput := text);
      
      // display image after analysis so we can highlight a region

      g22_renderPosterizedHighlightedImage(isPosterized, itr, showRegionsAsOutline);
    });

    watchTargetSelector = new WatchTargetSelector;

    /*if (webCamAccessEnabled) {
      printWithMS("Detecting web cams");
      watchTargetSelector.updateCamCount();
      printWithMS("Found " + n2(availableWebCams, "web cam"));
    }*/
    
    printWithMS("Starting screen cam");
    
    ownResource(screenCamTimer = new FlexibleRateTimer(fpsTarget, rEnter {
      if (!enabled) ret;
      watchTargetSelector?.updateScreenCount();
      Timestamp deadline = tsNowPlusMS(1000/fpsTarget);
      watchTarget?.configureScreenCamStream(imageStream);
      imageStream.step();
      long remaining = deadline.minus(tsNow());
      remainingMSPerFrame.add(remaining);
      setField(remainingMS := iround(remainingMSPerFrame!));
    }));
    screenCamTimer.start();
    dm_onFieldChange fpsTarget(-> screenCamTimer.setFrequencyImmediately(fpsTarget));

    printWithMS("Starting dir watcher");
    
    startDirWatcher();
    
    printWithMS("Gathering images from disk");
    for (f : allImageFiles(galleryDir()))
      addToGallery(f);
    printWithMS("Got dem images");

    transpileRaw_makeTranslator = -> hotwire(#7);

    // OSHI adds 4.5 MB to the jar...
    //doAfter(5.0, r { print("Process size: ", toM_str(oshi_currentProcessResidentSize_noZGCFix())) });
  }
  
  void startDirWatcher {
    fileWatcher = new FileWatchService;
    fileWatcher.addRecursiveListener(picturesDir(), file -> {
      if (!isImageFile(file)) ret;
      addToGallery(file);
    });
  }
  
  visualize {
    gallery = new JGallery;
    galleryComponent = gallery.visualize();

    new AWTOnConceptChanges(concepts, galleryComponent, -> {
      gallery.setImageFiles(map(list(GalleryImage), i -> i.path));
    }).install();
    
    isPosterized = stdImageSurface();
        
    labelCRUD = new SimpleCRUD_v2(concepts, Label);
    labelCRUD.hideFields("globalID");
    labelCRUD.addCountToEnclosingTab(true);
    labelCRUD.itemToMap_inner2 = l
      -> litorderedmap(
        "Name" := l.name,
        "# Examples" := n2(countConcepts(concepts, Example, label := l)));
    
    imageCRUD = new SimpleCRUD_v2(concepts, GalleryImage);
    imageCRUD.addCountToEnclosingTab(true);
    imageCRUD.itemToMap_inner2 = img
      -> litorderedmap(
        "File" := fileName(img.path),
        "Folder" := dirPath(img.path));
    imageCRUDVis = imageCRUD.visualize();
    imageCRUD.addButton(jPopDownButton_noText(
      "Forget missing images" := rThreadEnter forgetMissingImages
    ));
    
    // main visual

    var studyPanel = new StudyPanel;

    watchScreenPane = borderlessScrollPane(jHigherScrollPane(
      jfullcenter(vstack(
        withLeftAndRightMargin(hstack(
          dm_rcheckBox enabled("Watch"),
          watchTargetSelector.visualize(),
          jlabel(" in "),
          withLabelToTheRight("colors @ ", dm_spinner colors(2, 256)),
          withLabelToTheRight("p", dm_powersOfTwoSpinner pixelRows(512)),
        )),
        verticalStrut(2),
        withSideMargins(centerAndEastWithMargin(
          dm_fieldLabel screenCamRecognitionOutput(),
          dm_transientCalculatedToolTip speedInfo_long(rightAlignLabel(dm_transientCalculatedLabel speedInfo()))
        )),
      ))));

    initUIURLs();

    mainTabs = scrollingTabs(jTopOrLeftTabs(horizontalLayout,
      "Screen Cam" := jOnDemand screenCamPanel(),
      WithToolTip("Study", "Here you can analyze gallery images")
        := withTopAndBottomMargin(studyPanel.visualize()),
      WithToolTip("Java", "Write & run actual Java code")
        := withBottomMargin(jOnDemand javaPanel()),
      WithToolTip("Gallery", "Gallery view with preview images")
        := withBottomMargin(withRightAlignedButtons(galleryComponent,
          "Gallery CRUD" := r { showUIURL("Gallery CRUD") })),
      WithToolTip("Challenges", "Gazelle's self-tests")
        := challengesPanel(),
    ));

    // update tab count
    challengeCRUD.update();

    addUIURLToMainTabs("Left Arrow Script");

    addTabs(mainTabs,
      WithToolTip("Databases", "Choose the Gazelle database to use")
        := databasesPanel(),
    );

    // add main tabs to UI URLs
    for (S tab : tabNames(mainTabs)) {
      reMutable tab = dropTrailingBracketedCount(tab);
      uiURLs.put(tab, -> {
        int i = indexOfTabNameWithoutTrailingCount(mainTabs, tab);
        if (i < 0) ret jcenteredlabel("Hmm. Tab not found");
        selectTab(mainTabs, i);
        ret mainTabs;
      });
    }

    var cbEnabled = toolTip("Switch screen cam on or off", dm_checkBox enabled(""));
    var lblScreenCam = setToolTip("Show scaled down and color-reduced screen image",
      jlabel("Screen Cam"));
    tabComponentClickFixer(lblScreenCam);
    var screenCamTab = hstackWithSpacing(cbEnabled, lblScreenCam);
    
    replaceTabTitleComponent(mainTabs, "Screen Cam", screenCamTab);
    
    // for tab titles
    labelCRUD.update();
    imageCRUD.update();
    
    persistSelectedTabAsLiveValue(mainTabs, dm_fieldLiveValue selectedTab());

    var urlBar = uiURLs.urlBar();
    focusOnFirstShow(urlBar);
    setToolTip(uiURLs.comboBox, "UI navigation system (partially populated)");

    scpMain = singleComponentPanel();
    uiURLs.scp(scpMain);

    showUIURL(uiURL);

    var lblDB = toolTip("Currently selected database (" + f2s(concepts.conceptsDir()) + ")",
      jSimpleLabel(conceptsDirName()));
    componentPopupMenuItems(lblDB,
      "Manage or switch databases...",
        rThread { showUIURL("Databases")});
    
    var vis = northAndCenter(
      withSideAndTopMargin(
        westCenterAndEast(
          //withLabelLeftAndRight("DB:", lblDB, "| "),
          withLabelToTheRight(lblDB, "| "),
          urlBar,
          withLeftMargin(backgroundProcessesUI.shortLabel()))),
      scpMain,
    );

    ret vis;
  }

  JComponent screenCamPanel() {
    ret centerAndSouthOrEast(horizontalLayout,
      withTools(isPosterized),
      watchScreenPane);
  }
  
  JComponent screenCamPlusScriptPanel() enter {
    print("screenCamPlusScriptPanel");
    //ret watchScreenPane;
    try {
      var ide = screenCamScriptIDE = leftArrowScriptIDE();
      ide.runButtonShouldBeEnabled = ->
         eq(getText(ide.btnRun), "Stop")
          || ide.runButtonShouldBeEnabled_base();
      
      ide.runScript = -> {
        if (eq(getText(ide.btnRun), "Stop"))
          runningScreenCamScript = null;
        else {
          runningScreenCamScript = screenCamScriptIDE.parsedScript();
          ide.showStatus("Running");
        }
        setText(ide.btnRun,
          runningScreenCamScript == null ? "Run" : "Stop");
      };
      
      ret centerAndSouthOrEast(horizontalLayout,
        //withTools(
          jhsplit(
            jscroll_centered_borderless(isPosterized),
            screenCamScriptIDE
              .lvScript(dm_fieldLiveValue screenCamScript())
              .visualize())
        //, isPosterized)
        , watchScreenPane);
    } on fail e { print(e); }
  }
  
  S speedInfo() {
    ret "FPS " + fps + " idle " + remainingMS + " ms";
  }
  
  S speedInfo_long() {
    ret "Screen cam running at " + nFrames(fps) + "/second. " + n2(remainingMS) + " ms remaining per frame in first core"
      + " (of targeted " + fpsTarget + " FPS)";
  }
  
  bool useErrorHandling() { false; }
  
  S renderFunctionTimings() {
    ret lines(ciSorted(map(functionTimings!, (f, avg) ->
      firstToUpper(f) + ": " + n2(iround(nsToMicroseconds(avg!))) + " " + microSymbol() + "s (" + n2(iround(avg.n())) + ")")));
  }
  
  transient long _runScript_idx;

  void _runScript() {
    scriptRunner.parseAndRunOn(imageToRegions_finished.ii);
  }
  
  bool shouldRunScript() {
    ret isShowing(scriptRunner.scpScriptResult);
  }
  
  JComponent testScreenPanel() {
    ret withSideAndTopMargin(testScreen.visualize());
  }
  
  L popDownItems() {
    ret ll(jCheckBoxMenuItem_dyn("Horizontal Layout",
      -> horizontalLayout,
      b -> setField(horizontalLayout := b)));
  }
  
  void unvisualize {} // don't zero transient component fields
  
  void resetTimings { functionTimings.reset(); }
  
  // add tool side bar to image surface
  JComponent withTools(
    JComponent component default jscroll_centered_borderless(is),
    ImageSurface is) {
    ret centerAndEastWithMargin(component,
      vstack(
        verticalStrut(5),
        jimageButtonScaledToWidth(16, #1103054, "Save screenshot in gallery", rThread saveScreenshotToGallery),
        /*jPopDownButton_noText(
          jCheckBoxMenuItem_dyn("Live scripting", -> liveScripting, b -> setLiveScripting(b)
        ),*/
      )
    );
  }
  
  class WatchTargetSelector {
    JComboBox<WatchTarget> cb = jComboBox();
    int screenCount, camCount;
    
    visualize {
      updateList();
      //print("Selecting watchTarget: " + watchTarget);
      selectItem(cb, watchTarget);
      main onChange(cb, watchTarget -> {
        setField(+watchTarget);
        //print("Chose watchTarget: " + GazelleScreenCam.this.watchTarget);
      });
      ret cb;
    }
    
    void updateScreenCount() {
      if (screenCount != screenCount())
        updateList();
    }

    /*void updateCamCount() pcall {
      availableWebCams = listWebCams();
      updateList();
    }*/
    
    void updateList() swing {
      setComboBoxItems(cb, makeWatchTargets());
    }
    
    L<WatchTarget> makeWatchTargets() {
      ret flattenToList(
        countIteratorAsList_incl(1, screenCount = screenCount(),
          i -> WatchScreen(i)),
        new WatchMouse,
        new WatchScreenWithMouse,
        /*countIteratorAsList_incl(1, l(availableWebCams),
          i -> new WatchWebCam(i))*/
      );
    }
  }

  class SnPSelector {
    settable new SnPSettings settings;
    
    event change;

    visualize {
      var colors = jspinner(settings.colors, 2, 256);
      main onChange(colors, -> {
        settings.colors = intFromSpinner(colors);
        change();
      });
      
      var pixelRows = jPowersOfTwoSpinner(512, settings.pixelRows);
      main onChange(pixelRows, -> {
        settings.pixelRows = intFromSpinner(pixelRows);
        change();
      });
      
      ret hstack(
        colors,
        jlabel(" colors @ "),
        pixelRows,
        jlabel(" p"));
    }
  }
  
  JComponent wrapCRUD(SimpleCRUD_v2 crud, JComponent vis default crud.visualize()) {
    ret crud == null ?: withTopAndBottomMargin(jRaisedSection(withMargin(vis)));
  }
  
  File galleryDir() {
    ret picturesDir(gazelle22_imagesSubDirName());
  }
  
  void saveScreenshotToGallery enter {
    var img = imageStream!;
    saveImageWithCounter(galleryDir(), "Screenshot", img);
  }
  
  GalleryImage addToGallery(File imgFile) {
    if (!isImageFile(imgFile)) null;
    var img = uniq(concepts, GalleryImage, path := imgFile);
    //printVars("addToGallery", +imgFile, +img);
    ret img;
  }

  class StudyPanel {
    new SnPSelector snpSelector;
    GalleryImage image;
    BufferedImage originalImage;
    //ImageSurface isOriginal = stdImageSurface();
    ImageSurface isOriginalWithRegions = stdImageSurface();
    ImageSurface isPosterized = stdImageSurface();
    SingleComponentPanel scp = singleComponentPanel();
    SingleComponentPanel analysisPanel = singleComponentPanel();
    SingleComponentPanel scpExampleCRUD = singleComponentPanel();
    ConceptsComboBox<GalleryImage> cbImage = new(concepts, GalleryImage);
    Gazelle22_ImageToRegions itr;
    int iSelectedRegion;
    SimpleCRUD_v2<SavedRegion> regionCRUD;
    SimpleCRUD_v2<Example> exampleCRUD;

    *() {
      //cbImage.sortTheList = l -> sortConceptsByIDDesc(l);
      cbImage.sortTheList = l -> sortedByComparator(l, (a, b)
        -> cmpAlphanumIC(fileName(a.path), fileName(b.path)));

      main onChangeAndNow(cbImage, img -> dm_q(me(), r {
        image = img;
        scp.setComponent(studyImagePanel());
      }));

      isPosterized.removeAllTools();
      isPosterized.onMousePositionChanged(r_dm_q(me(), l0 regionUpdate));

      imageSurfaceOnLeftMouseDown(isPosterized, pt -> dm_q(me(), r { chooseRegionAt(pt) }));

      snpSelector.onChange(r_dm_q(me(), l0 runSnP));
    }

    void chooseRegionAt(Pt p) {
      if (itr == null) ret;
      iSelectedRegion = itr.regions.regionAt(p);

      if (iSelectedRegion > 0) {
        var savedRegion = uniq_returnIfNew(concepts, SavedRegion,
          +image,
          snpSettings := snpSelector.settings.cloneMe(),
          regionIndex := iSelectedRegion);

        // it's new, add values
        if (savedRegion != null) {
          print("Saved new region!");
          var bitMatrix = toScanlineBitMatrix(itr.regions.regionBitMatrix(iSelectedRegion));
          cset(savedRegion, +bitMatrix);
        }
      }
      
      regionUpdate();
    }

    // load new image
    JComponent studyImagePanel() { 
      if (image == null) null;
      originalImage = loadImage2(image.path);
      if (originalImage == null) ret jcenteredlabel("Image not found");

      //isOriginal.setImage(originalImage);
      isOriginalWithRegions.setImage(originalImage);

      iSelectedRegion = 0;
      itr = new Gazelle22_ImageToRegions(functionTimings, originalImage, snpSelector.settings);
      runSnP();

      regionCRUD = new SimpleCRUD_v2<SavedRegion>(concepts, SavedRegion);
      regionCRUD.addFilter(+image);
      regionCRUD
        .showSearchBar(false)
        .showAddButton(false)
        .showEditButton(false)
        .iconButtons(true);
        
      regionCRUD.itemToMap_inner2 = region -> {
        var examples = conceptsWhere(concepts, Example, item := region);
        
        ret litorderedmap(
          "Pixels" := region.bitMatrix == null ? "-" : n2(region.bitMatrix.pixelCount()),
          //"Shape" := "TODO",
          "Labels" := joinWithComma(map(examples, e -> e.label)),

          // TODO: scale using snpsettings
          "Position" := region.bitMatrix == null ? "-" : region.bitMatrix.boundingBoxOfTrueBits());
      };

      var regionCRUDComponent = regionCRUD.visualize();
      regionCRUD.onSelectionChanged(l0 updateExampleCRUD);

      ret hsplit(
        jtabs(
          //"Image" := jscroll_centered_borderless(isOriginal),
          "Image + regions" := jscroll_centered_borderless(isOriginalWithRegions),
          "Posterized" := jscroll_centered_borderless(isPosterized),
        ),
        northAndCenterWithMargin(
          analysisPanel,
          hsplit(
            jCenteredSection("Saved regions", regionCRUDComponent),
            scpExampleCRUD)
          ));
    }

    void runSnP {
      if (itr == null) ret;
      itr.run();
      regionUpdate();
    }

    void regionUpdate {
      if (itr == null) ret;

      var pixels = itr.posterized.getRGBPixels();
      
      // hovering region marked green
      g22_highlightRegion(pixels, isPosterized, itr, showRegionsAsOutline);

      // selected region marked blue
      itr.regions.markRegionInPixelArray(pixels, iSelectedRegion, 0xFFADD8E6);

      var highlighted = bufferedImage(pixels, itr.posterized.getWidth(), itr.posterized.getHeight());

      isPosterized.setImage(highlighted);
      isPosterized.performAutoZoom(); // seems to be necessary for some reason

      updateAnalysis();
    }

    void updateAnalysis {
      /*new LS lines;
      lines.add(nRegions(itr.regions.regionCount()));
      lines.add("Selected region: " + iSelectedRegion);
      S text = lines_rtrim(lines);
      analysisPanel.setComponent(jLabel(text)));*/
    }

    void updateExampleCRUD {
      var region = regionCRUD.selected();
      if (region == null) ret with scpExampleCRUD.clear();
      
      exampleCRUD = new SimpleCRUD_v2<Example>(concepts, Example);
      exampleCRUD.entityName = -> "label for region";
      exampleCRUD.addFilter(item := region);
      exampleCRUD.showSearchBar(false);
      exampleCRUD.iconButtons(true);
      scpExampleCRUD.set(jCenteredSection("Labels for region",
        exampleCRUD.visualize()));
    }

    void importImage {
      new JFileChooser fc;
      if (fc.showOpenDialog(cbImage) == JFileChooser.APPROVE_OPTION) {
        File file = fc.getSelectedFile().getAbsoluteFile();
        if (!isImageFile(file)) ret with infoMessage("Not an image file");
        var img = addToGallery(file);
        waitUntil(250, 5.0, -> comboBoxContainsItem(cbImage, img));
        setSelectedItem(cbImage, img);
      }
    }

    visual
      jRaisedSection(northAndCenterWithMargins(
        centerAndEast(withLabel("Study", cbImage),
          hstack(
            jlabel(" in "),
            snpSelector.visualize(),
            horizontalStrut(10),
            jPopDownButton_noText(
              "Import image...", rThreadEnter importImage,
            ),
            )),
        scp));
  } // end of StudyPanel

  void initUIURLs {
    uiURLs.put("Main Tabs", ->
      horizontalLayout ? withMargin(mainTabs) : withSideMargin(mainTabs));
      
    uiURLs.put("Screen Cam FPS", -> jFullCenter(
      vstackWithSpacing(
        jCenteredLabel("FPS target (frames per second) for screen cam:"),
        jFullCenter(dm_spinner fpsTarget(1, 60)),
        jCenteredLabel("(You can lower this value if you have a slower computer)"))));

    uiURLs.put("Timings", -> {
      JTextArea taTimings = jTextArea_noUndo();
      awtEveryAndNow(taTimings, .5, r {
        setText(taTimings, renderFunctionTimings())
      });
      ret withRightAlignedButtons(taTimings,
        Reset := r resetTimings);
    });

    uiURLs.put("Test Screen" := -> testScreenPanel());

    //uiURLs.put("Operators" := -> operatorsPanel());

    uiURLs.put("Left Arrow Script" := -> leftArrowScriptPanel());

    uiURLs.put("Settings" := -> settingsPanel());

    uiURLs.put("System Info" := -> systemInfoPanel());

    uiURLs.put("Web Cam" := -> webCamPanel());

    uiURLs.put("Labels" := -> wrapCRUD(labelCRUD));

    uiURLs.put(WithToolTip("Screen Cam + Linear Script", "Run a simple (linear) Gazelle V script")
      := -> withBottomMargin(scriptRunner.scriptAndResultPanel()));
      
    uiURLs.put(WithToolTip("Left Arrow Script", "Run a \"left-arrow script\"")
      := -> withBottomMargin(leftArrowScriptPanel()));
      
    uiURLs.put("Screen Cam + Script" := -> jOnDemand screenCamPlusScriptPanel());

    uiURLs.put(WithToolTip("Gallery CRUD", "Gallery view with more functions (delete etc)")
      := -> wrapCRUD(imageCRUD, imageCRUDVis));
    
    // add ui urls above this line
  }

  JComponent settingsPanel() {
    var cbMinimizeToTray = jCheckBox(isTrue(getOpt(dm_stem(), "minimizeToTray")));
    onUpdate(cbMinimizeToTray, -> dm_callStem(me(), "setMinimizeToTray", isChecked(cbMinimizeToTray)));
    ret jscroll(makeForm3( 
      "Minimize to tray", toolTip("Remove Gazelle from task bar when minimized (click Gazelle icon in system tray to reactivate)", cbMinimizeToTray),
      "Access web cams", dm_checkBox webCamAccessEnabled(),
    ));
  }

  File gazelleJar() {
    ret getBytecodePathForClass(this);
  }

  JComponent systemInfoPanel() {
    var gazelleJar = gazelleJar();
    var cbMinimizeToTray = jCheckBox(isTrue(getOpt(dm_stem(), "minimizeToTray")));
    onUpdate(cbMinimizeToTray, -> dm_callStem(me(), "setMinimizeToTray", isChecked(cbMinimizeToTray)));
    // Sadly, even jScrollVertical causes a bug in formLayouter1 that
    // makes the form grow horizontally without bounds
    ret /*jscrollVertical*/(makeForm3( 
      "Java Version", jlabel(javaVersion()),
      "Gazelle Jar", JFilePathLabel(gazelleJar).visualize(),
      "Gazelle Jar Size", str_toMB_oneDigit(fileSize(gazelleJar)),
      "Compilation Date", jlabel(or2(loadTextFileResource(classLoader(this), "compilation-date.txt"), "unknown")),
      "Gazelle Count" := toolTip("How many Gazelles are running in the world",
        jLiveValueLabel((LiveValue) dm_callOSOpt lvComputerCount())),
      "Gazelle Database" := JFilePathLabel(concepts.conceptsFile()).visualize(),
      "Gazelle Database Size" := str_toKB(fileSize(concepts.conceptsFile())),
    ));
  }

  JComponent operatorsPanel() {
    ret jcenteredlabel("TODO");
  }

  JLeftArrowScriptIDE leftArrowScriptIDE() {
    var ide = g22utils.leftArrowIDE();
    ide.withResultPanel();
    ret ide;    
  }

  void modifyLeftArrowParser(GazelleV_LeftArrowScriptParser parser) {
    parser.allowTheWorld(me(), mc(), utils.class);
  }

  JComponent leftArrowScriptPanel() {
    var ide = leftArrowScriptIDE();
    ide.lvScript(dm_fieldLiveValue newScript());
    ret ide.visualize();
  }

  JComponent javaPanel() enter {
    var scpResult = singleComponentPanel();
    
    new JMiniJavaIDE ide;
    ide.stringifier(g22utils.stringifier);
    ide.extraClassMembers = script -> {
      LS tok = javaTok(script);

      if (contains(tok, "draw")) ret [[
        import java.awt.*;
        import java.awt.image.*;
        
        interface SimpleRenderable {
          void renderOn(Graphics2D g);
        }
        
        static BufferedImage draw(int w, int h, SimpleRenderable r) {
          BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
          Graphics2D g = img.createGraphics();
          g.setColor(Color.white);
          g.fillRect(0, 0, w, h);
          g.setColor(Color.black);
          r.renderOn(g);
          return img;
        }
      ]];
        
      ret "";
    };

    ide.callCompiledObject = o -> {
      O result = ide.callCompiledObject_base(o);
      if (result cast BufferedImage)
        scpResult.set(jscroll_centered_borderless(stdImageSurface(result)));
      ret result;
    };
    
    ide.lvScript(dm_fieldLiveValue javaCode());
    ret jhsplit(
      jCenteredSection("Image will show here", scpResult),
      ide.visualize());
  }

  JComponent webCamPanel() {
    if (cbWebCam == null) {
      var cams = listWebCams();
      cbWebCam = jTypedComboBox(cams,
        findWebCamByName(cams, webCamName));
    }

    if (scpWebCamImage == null) scpWebCamImage = singleComponentPanel();
    
    ret northAndCenterWithMargins(
      centerAndEastWithMargin(
        withLabel("Cam", cbWebCam),
        jline(
          jbutton("Start", rThreadEnter startWebCam),
          jbutton("Stop", rThreadEnter stopWebCam)
        )),
      scpWebCamImage);
  }

  void stopWebCam {
    if (webCamPanel != null) {
      webCamPanel.stop();
      webCamPanel = null;
      scpWebCamImage?.clear();
      backgroundProcessesUI.remove(bgWebCam);
    }
  }

  void startWebCam {
    temp tempInfoBox("Starting Web Cam");
    stopWebCam();
    var cam = getSelectedItem_typed(cbWebCam);
    setField(webCamName := cam?.getName());
    if (cam != null) {
      scpWebCamImage.set(webCamPanel = new WebcamPanel(cam, true));
      backgroundProcessesUI.add(bgWebCam);
    }
  }
  
  void forgetMissingImages {
    int n = l(deleteConcepts(GalleryImage, img -> !img.imageExists()));
    infoBox(n == 0 ? "Nothing to forget" : "Forgot " + nImages(n));
  }

  void addUIURLToMainTabs(S url) swing {
    if (containsTabNameWithoutTrailingCount(mainTabs, url)) ret;
    if (!uiURLs.hasURL(url)) ret with print("URL not found: " + url);
    addTab(mainTabs, url, uiURLs.renderUIURL(url));
  }

  void showScreenCam() { showUIURL("Screen Cam"); }
  void showWebCam() { showUIURL("Web Cam"); }

  <A extends G22LeftArrowScript> void setupScriptCRUD(SimpleCRUD_v2<A> crud) {
    crud.updateInterval = 2000;
    crud.useNewChangeHandler(true);
    crud.multiLineField("code");
    crud.makeTextArea = text -> jMinHeight(200, crud.makeTextArea_base(text));
    crud.humanizeFieldNames = false;
    crud.iconButtons(true);
    crud.itemToMap_inner2 = c
      -> litorderedmap(
        "Description" := str(c),
        "LoC" := n2(linesOfCode_javaTok(c.code)));
  }

  JComponent challengesPanel() {
    challengeCRUD = new SimpleCRUD_v2<>(concepts, Challenge);
    setupScriptCRUD(challengeCRUD);
    challengeCRUD.addCountToEnclosingTab(true);
    challengeCRUD.entityName = -> "Challenge";

    recognizerCRUD = new SimpleCRUD_v2<>(concepts, G22RecognizerScript);
    recognizerCRUD.entityName = -> "Recognizer";
    setupScriptCRUD(recognizerCRUD);
    
    var challengeCRUDVis = challengeCRUD.visualize();
    var recognizerCRUDVis = recognizerCRUD.visualize();
    
    scpChallengePanel = singleComponentPanel();
    scpChallengeCode = singleComponentPanel();

    challengeCRUD.onSelectionChangedAndNow(r_dm_q(l0 makeChallengePanel));

    ret jhsplit(
      withTopRightAndBottomMargin(jCenteredRaisedSection("Challenges", 
        withSideAndBottomMargin(
          jvsplit(
            jvsplit(
              withBottomMargin(challengeCRUDVis),
              scpChallengeCode
            ),
            jCenteredRaisedSection("Recognizers", recognizerCRUDVis)
          )
        ))),
        withSideMargins(scpChallengePanel));
  }

  void makeChallengePanel {
    var challenge = challengeCRUD.selected();
    if (challenge == null) {
      scpChallengePanel.clear();
      scpChallengeCode.set(jcenteredlabel("Please select a challenge above to start"));
      ret;
    }

    scpChallengeCode.set(jCenteredSection(
      //"Code for " + challenge,
      "Code for challenge",
      liveValueRSyntaxTextArea_bothWays(
        conceptFieldLiveValue code(challenge))));
      
    var panel = G22ChallengePanel(challenge);
    panel.g22utils(g22utils);
    panel.init();
    panel.recognizerIDE.lvScript(dm_liveValue recognizerScript());
    scpChallengePanel.set(withTopAndBottomMargin(12, 6, panel.visualize()));
  }

  // for scripts
  Gazelle22_ImageToRegions imageToRegions(BufferedImage inputImage, SnPSettings snpSettings) {
    ret new Gazelle22_ImageToRegions(functionTimings, inputImage, snpSettings);
  }

  JComponent databasesPanel() {
    ret new G22DatabasesPanel(g22utils, concepts).visualize();
  }
} // end of module

concept Label > ConceptWithGlobalID {
  S name;
  //new RefL examples;
  
  toString { ret /*"Label " +*/ name; }
}

concept GalleryImage {
  File path;

  toString { ret /*"[" + id + "] " +*/ fileName(path); }

  bool imageExists() { ret fileExists(path); }
}

concept SavedRegion {
  new Ref image; // e.g. a GalleryImage
  SnPSettings snpSettings;
  int regionIndex; // region number relative to snpSettings
  //Rect bounds; // get it from bitMatrix instead
  ScanlineBitMatrix bitMatrix;
  //new RefL<Label> labels;
}

concept Example {
  new Ref<Label> label;
  new Ref item; // e.g. a SavedRegion
  double confidence = 1;
}

concept IfThenTheory {
  new Ref if_;
  new Ref then;
}

asclass WatchTarget {
  abstract void configureScreenCamStream(ScreenCamStream stream);
}

// screenNr: 1 = screen 1 etc
srecord WatchScreen(int screenNr) > WatchTarget {
  toString { ret "Screen " + screenNr; }

  void configureScreenCamStream(ScreenCamStream stream) {
    stream.useScreen(screenNr-1);
  }
}

srecord WatchMouse(int width, int height) > WatchTarget {
  WatchMouse() {
    height = 256;
    width = iround(height*16.0/9);
  }
  
  toString { ret "Mouse"; }
  
  void configureScreenCamStream(ScreenCamStream stream) {
    stream.area(mouseArea(width, height));
  }
}

srecord WatchScreenWithMouse > WatchTarget {
  toString { ret "Screen w/mouse"; }

  void configureScreenCamStream(ScreenCamStream stream) {
    stream.useScreen(screenNrContaining(mouseLocationPt()));
  }
}

!include once #1034034 // Gazelle 22 Function Include for Scripts

Author comment

Began life as a copy of #1033862

download  show line numbers  debug dex  old transpilations   

Travelled to 3 computer(s): bhatertpkbcr, mowyntqkapby, mqqgnosmbjvj

No comments. add comment

Snippet ID: #1034316
Snippet name: Gazelle Screen Cam / Gazelle 22 Module [backup]
Eternal ID of this version: #1034316/1
Text MD5: 4efddfa15a929567a92d9156a4ee5669
Transpilation MD5: 87de8611e98d3a315440d5d42be9ef10
Author: stefan
Category: javax / gazelle v
Type: JavaX source code (Dynamic Module)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-02-02 00:15:22
Source code size: 33472 bytes / 1046 lines
Pitched / IR pitched: No / No
Views / Downloads: 63 / 167
Referenced in: [show references]