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

1026
LINES

< > BotCompany Repo | #1034148 // G22Utils

JavaX fragment (include) [tags: use-pretranspiled]

Transpiled version (63878L) is out of date.

// Some of the functions are dependent on the concepts field,
// others are global.

!include once #1035461 // Gazelle 22 Class synonyms Include

sclass G22Utils_Base {
  // event that is triggered every time a file or directory inside the
  // project changes. Starts the fileWatcher automatically when the
  // first listener is added.
  event projectFileChanged(File file);
}

sclass G22Utils > G22Utils_Base is AutoCloseable, TransientObject {
  delegate FunctionDef to GazelleV_LeftArrowScript.
  
  settable IBackgroundProcesses backgroundProcessesUI;
  settable Enterable module;
  settable G22MasterStuff masterStuff;
  settable Concepts concepts;
  settable G22ProjectActions projectActions;
  gettable G22AutoStarter autoStarter = new(this);
  settable new FunctionTimings<S> functionTimings;
  Map<S, FunctionDef> projectWideFunctionDefs = syncMap();
  Map<S, Class> projectWideClassDefs = syncMap();
  
  Timestamp recompileDate;
  
  gettable Set<AutoCloseable> autoClosingResources = syncLinkedHashSet();
  
  // TODO: set this to a few seconds if your variables are expensive to render
  // settable Seconds variableUpdateIntervalInUI;
  
  FileWatchService fileWatcher; // general file watch service
  bool projectFileListenerInitiated;

  gettable CombinedStringifier stringifier = new(
    o -> o cast BufferedImage ? "Image (" + o.getWidth() + "*" + o.getHeight() + " px)" : null
  );
  
  ILASClassLoader lasClassLoader() { ret masterStuff?.lasClassLoader(); }
  
  settable bool confirmProjectReplacements;
  
  // add fields here
  
  ImageSurface stdImageSurface_noToolTip(ImageSurface is default imageSurface()) {
    imageSurface_pixelated(is);
    is.setAutoZoomToDisplay(true).repaintInThread(false);
    is.defaultImageDir = -> dbDir();
    is.specialPurposed = true;
    ret is;
  }
    
  ImageSurface stdImageSurface(ImageSurface is default imageSurface()) {
    stdImageSurface_noToolTip(is);
    new ImageSurface_PositionToolTip(is);
    ret is;
  }
  
  L<ImageSurface> stdImageSurfaces(Cl images) {
    ret map stdImageSurface(toBufferedImages(images));
  }

  ImageSurface stdImageSurface(BufferedImage etc img) {
    var is = stdImageSurface();
    is.setImage(img);
    ret is;
  }
  
  ImageSurface stdImageSurface(File file) {
    var is = stdImageSurface();
    is.setImage(file);
    ret is;
  }
  
  ImageSurface stdImageSurface(G22GalleryImage img) {
    ret stdImageSurface(img?.path);
  }
  
  ImageSurface stdImageSurfaceWithSelection(BufferedImage etc img, Rect selection) {
    var is = stdImageSurface(img);
    is.setSelection(selection);
    ret is;
  }
  
  S stringify(O o) { ret stringifier.toString(o); }
  
  event bigVariableLoaded(G22Variable var);

  event settingUpParser(GazelleV_LeftArrowScriptParser parser);
  event settingUpScriptIDE(JLeftArrowScriptIDE ide);
  
  GazelleV_LeftArrowScriptParser leftArrowParser() {
    new GazelleV_LeftArrowScriptParser parser;
    parser.classNameResolver(classNameResolver());
    parser.lasClassLoader(lasClassLoader());
    settingUpParser(parser);
    parser.addClassAlias("Freq", "Frequency");
    parser.addClassAlias("PriceDigitizer", "PriceDigitizer2");
    parser.addClassAlias("MRUAndAllTimeTop", "MRUAndAllTimeTop_optimized");
    parser.findExternalObject2 = name -> {
      try object projectWideClassDefs.get(name);
      ret parser.findExternalObject2_base(name);
    };
    
    parser.addFunctionDefs(projectWideFunctionDefs);
    
    ret parser;
  }
  
  O leftArrow(S script) {
    ret leftArrowParse(script)!;
  }
  
  GazelleV_LeftArrowScript.Script leftArrowParse(S script) {
    ret leftArrowParser().parse(script);
  }
  
  O leftArrowWithVars(S script, O... vars) {
    var parser = leftArrowParser();
    for (int i = 0; i < l(vars); i += 2)
      parser.addVar((S) vars[i], or(_getClass(vars[i+1]), O), true);
      
    var parsed = parser.parse(script);
    new FlexibleVarContext varContext;
    for (int i = 0; i < l(vars); i += 2)
      varContext.set((S) vars[i], vars[i+1]);
    ret parsed.get(varContext);
  }
  
  void basicParserTest() {
    var parser = leftArrowParser();
    print(classContainerPrefixes := parser.classContainerPrefixes());
    assertEquals(pair(1, 2), parser.parse("new Pair 1 2")!);
  }

  ifclass JLeftArrowScriptIDE
  JLeftArrowScriptIDE leftArrowIDE aka leftArrowScriptIDE() {
    new JLeftArrowScriptIDE ide;
    ide.g22utils(this);
    ide.scriptTimeout(projectWideScriptTimeout());
    settingUpScriptIDE(ide);
    ret ide;
  }
  endif
  
  File byteCodePath() {
    ret assertNotNull(getBytecodePathForClass(this));
  }

  simplyCached ClassNameResolver classNameResolver() {
    ret new ClassNameResolver().byteCodePath(byteCodePath()).init();
  }
  
  File databasesMotherDir() {
    ret masterStuff.databasesMotherDir();
  }
  
  File dirOfProjectNamed(S name) {
    assertNempty(name);
    ret newFile(databasesMotherDir(), name);
  }
  
  AutoCloseable enter() { ret module?.enter(); }
  
  S defaultDBName() { ret "Default"; }
  
  File lastOpenedDBsFile() {
    ret newFile(databasesMotherDir(), "Last Opened");
  }
  
  File recentlyOpenedDBsFile() {
    ret newFile(databasesMotherDir(), "Recently Opened");
  }
  
  File autoUpdateFile() {
    ret newFile(databasesMotherDir(), "Auto-Update");
  }
  
  bool autoUpdateEnabled() {
    ret fileExists(autoUpdateFile());
  }
  
  void setAutoUpdate(bool b) {
    createOrRemoveFile(autoUpdateFile(), b);
  }
  
  LS dbsToOpen() {
    ret loadRecentProjectsFile(lastOpenedDBsFile());
  }
  
  LS dbNamesRecentlyOpened() {
    ret loadRecentProjectsFile(recentlyOpenedDBsFile());
  }
  
  void addToRecentDBNames(S dbName, bool hidden) {
    LS list = dbNamesRecentlyOpened();
    LS list2 = cloneList(list);
    removeAll(list2, dbName, "*" + dbName);
    list2.add(0, hidden ? "*" + dbName : dbName);
    truncateList(list2, 100);
    if (!eq(list, list2))
      saveTextFile(recentlyOpenedDBsFile(), lines(list2));
  }
  
  // returns project names with optional "*" prefix for hidden projects
  LS loadRecentProjectsFile(File file) {
    new LS dbNames;
    for (S name : tlft(loadTextFile(file))) {
      S name2 = dropPrefix("*", name);
      if (fileExists(newFile(databasesMotherDir(), name2)))
        dbNames.add(name);
    }
        
    if (empty(dbNames)) dbNames.add(defaultDBName());
    ret dbNames;
  }
  
  void setOpenDBs(Cl<? extends IG22LoadedDB> dbs) {
    new LS dbNames;
    for (db : dbs) {
      var dbDir = conceptsDir(db.concepts());
      if (sameFile(databasesMotherDir(), dirOfFile(dbDir)))
        dbNames.add((db.hidden() ? "*" : "") + fileName(dbDir));
    }
      
    saveTextFile(lastOpenedDBsFile(), lines(dbNames));
  }
  
  ifclass SimpleCRUD_v2
  <A extends G22LeftArrowScript> void setupScriptCRUD(SimpleCRUD_v2<A> crud, bool allowRunOnProjectOpen default false) {
    crud.useNewChangeHandler(true);
    crud.editableFieldsForItem = x -> llNonNulls("description",
      allowRunOnProjectOpen ? "runOnProjectOpen" : null,
      allowRunOnProjectOpen ? "runOrder" : null);
    //G22LeftArrowScript.f_description().getName());
    crud.multiLineField("text");
    crud.multiLineField("editingText");
    crud.makeTextArea = text -> jMinHeight(200, crud.makeTextArea_base(text));
    crud.humanizeFieldNames = false;
    crud.iconButtons(true);
    crud.itemToMap_inner2 = c -> scriptToMap(c, allowRunOnProjectOpen);
    crud.dontDuplicateFields = litset("runOnProjectOpen", "runOrder", "runCount", "lastResultByMode");

  }
  endif

  MapSO scriptToMap(G22LeftArrowScript c, bool allowRunOnProjectOpen default false) {  
    ret litorderedmap(
      "Description" := c.description(),
      "Status" := renderScriptStatus(c),
      "LoC" := renderScriptLoC(c),
      "Import note" := c.importNote,
      "Run on project open" := c.renderRunOnProjectOpenStatus());
  }
  
  S renderScriptStatus(G22LeftArrowScript c) {
    ret or2_rev("Empty", joinNemptiesWithSpacedPlus(
      c.isClearForAutoRun() ? "Clear for auto-run" : null,
      c.isSavedDistinctFromAutoRunVersion() ? "Saved (not cleared)" : null,
      c.isEditing() ? "Editing" : null
    ));
  }
  
  S renderScriptLoC(G22LeftArrowScript c) {
    ret n2(intMax(mapLL linesOfCode_javaTok(
      c.editingText,
      c.text,
      c.codeForAutoRun())));
  }
  
  // e.g. for an image file
  L<G22Label> labelsForFile(File file) {
    if (file == null) null;
    File labelsFile = appendToFileName(file, ".labels");
    LS labels = tlft(loadTextFile(labelsFile));
    ret map getLabel(labels);
  }

  File labelsFile(File file) {  
    if (file == null) null;
    ret appendToFileName(file, ".labels");
  }
  
  void setLabelsForFile(File file, L<G22Label> labels) {
    LS list = map(labels, label -> label.name);
    File f = labelsFile(file);
    saveTextFile(f, lines(list));
    print("Saved " + nLabels(list) + " (" + joinWithComma(list) + ") to " + f);
  }
  
  G22Label getLabel(S name) {
    if (empty(name)) null;
    if (containsNewLine(name)) fail("No newlines in label names allowed: " + name);
    ret uniqCI(concepts, G22Label, +name);
  }
  
  File dbDir aka projectDir() { ret conceptsDir(concepts); }
  
  File fileInDbDir aka projectFile(S name) { ret newFile(dbDir(), name); }
  
  record GazelleDB(S name, File dir) {
    S name() { ret name; }
    File dir() { ret dir; }
    
    bool loaded() {
      ret loadedDB() != null;
    }
    
    simplyCached IG22LoadedDB loadedDB() {
      ret masterStuff.getLoadedDBForConceptDir(dir);
    }
    
    File conceptsFile() { ret conceptsFileIn(dir); }
  }
  
  L<GazelleDB> gazelleDBs() {
    new L<GazelleDB> dbs;
    for (File dir : listDirsContainingFileNamed(databasesMotherDir(),
      "concepts.structure.gz"))
      dbs.add(new GazelleDB(fileName(dir), dir));
    ret dbs;
  }
  
  ItIt<Concepts> peekAllProjectsConcepts() {
    var classFinder = masterStuff.makeClassFinder();
    ret mapI_pcall(gazelleDBs(), db -> {
      var cc = newConceptsWithClassFinder(db.conceptsFile(), classFinder);
      cc.loadFromDisk();
      ret cc;
    });
  }
  
  ifclass RSyntaxTextAreaWithSearch
    RSyntaxTextAreaWithSearch newSyntaxTextArea(IF1<JComponent> wrapStatusLabel default (IF1) null) {
      RSyntaxTextAreaWithSearch ta = new(wrapStatusLabel);
      ta.textArea().setHighlightCurrentLine(false);
      ta.menuLessOperation();
      ret ta;
    }
    
    RSyntaxTextAreaWithSearch newSyntaxTextArea(S text) {
      var ta = newSyntaxTextArea();
      ta.setText(text);
      ret ta;
    }
  endif
  
  File projectStoryTextFile() { ret newFile(dbDir(), "story.txt"); }
  
  S projectName() { ret fileName(dbDir()); }
  
  close {
    autoStarter.close();
    closeAndClear(autoClosingResources);
    dispose fileWatcher;
  }
  
  // solve shadowing problem in LAS
  void close(AutoCloseable c) {
    main close(c);
  }
  
  // project vars
  
  G22Variable findProjectVar(S name) {
    ret conceptWhereCI(concepts, G22Variable, +name);
  }
  
  Cl<S> projectVarNames() {
    ret collect name(list(concepts, G22Variable));
  }
  
  O getProjectVar(S name) {
    G22Variable var = findProjectVar(name);
    ret var?.value();
  }
  
  // If it's a big variable, load it just now and then forget
  // it again
  O getBigProjectVarOnce(S name) {
    G22Variable var = findProjectVar(name);
    ret var?.getOnce();
  }
  
  // fail if var doesn't exist or value is null
  O getMandatoryProjectVar(S name) {
    ret assertNotNull(name, getProjectVar(name));
  }
  
  O getOrSetTransientProjectVar(S name, IF0 f) {
    try object getProjectVar(name);
    ret setTransientProjectVarAndReturn(name, f!);
  }
  
  O getProjectVarOrCallScript(S name, long scriptID) {
    try object getProjectVar(name);
    ret callScript(scriptID);
  }
  
  O getProjectVarSetByScript(S name, long scriptID) {
    try object getProjectVar(name);
    callScript(scriptID);
    ret getProjectVar(name);
  }
  
  // gets first non-null value of project variable named "name"
  // in any open project (order not defined)
  O getProjectVarFromAnyProject(S name) {
    for (project : masterStuff().openProjects())
      try object project.g22utils().getProjectVar(name);
    null;
  }
  
  // gets all non-null values from project variable named "name"
  // in any open project
  L getProjectVarFromAllProjects aka getVarFromAnyProject(S name) {
    ret nonNulls(masterStuff().openProjects(),
      project -> project.g22utils().getProjectVar(name));
  }
  
  // Creates the variable if it's not there, otherwise
  // returns existing variable.
  G22Variable projectVarConcept(S name) {
    ret optimizedUniqCI(concepts, G22Variable, +name);
  }
  
  O waitForProjectVar(double timeoutSeconds default infinity(), S name) {
    G22Variable var = projectVarConcept(name);
    ret waitForCalculatedValueUsingChangeListener(timeoutSeconds, -> var.value(), var);
  }
  
  void setBigProjectVar(bool persistent, S name, O value) {
    if (persistent)
      setBigProjectVar(name, value);
    else
      setTransientProjectVar(name, value);
  }
  
  G22Variable setProjectVar(bool persistent, S name, O value) {
    G22Variable var = projectVarConcept(name);
    
    // defensive order
    if (!persistent) var.persistent(persistent);
    var.value(value);
    if (persistent) var.persistent(persistent);
    
    ret var;
  }
  
  // uncache a big project variable. Does not change the value
  void unloadProjectVar(S name) {
    var var = findProjectVar(name);
    var?.unload();
  }

  <A> A setBigProjectVar(S name, A value) {
    setPersistentProjectVar(name, value);
    G22Variable var = projectVarConcept(name);
    var.makeBig();
    ret value;
  }
  
  O getCachedProjectVar(S name) {
    var var = findProjectVar(name);
    ret var?.cachedValue();
  }
  
  bool isBigProjectVar(S name) {
    var v = findProjectVar(name);
    ret v != null && v.big();
  }
  
  <A> A setPersistentProjectVar(S name, A value) {
    setProjectVar(true, name, value);
    ret value;
  }
  
  G22Variable setTransientProjectVar(S name, O value) {
    ret setProjectVar(false, name, value);
  }
  
  <A> A setTransientProjectVarAndReturn(S name, A value) {
    setProjectVar(false, name, value);
    ret value;
  }
  
  void setAutoClosingProjectVar(S name, O value) {
    setTransientProjectVar(name, value).autoClose(true);
  }
  
  void deleteProjectVar(S name) {
    deleteConcept(findProjectVar(name));
  }
  
  // Note: unsynced. Wild west baby!
  O getOrCreateProjectVar aka getOrCreateTransientProjectVar(S name, IF0 maker) {
    ret getOrCreateProjectVar(projectVarConcept(name), maker);
  }
  
  O getOrCreatePersistentProjectVar(S name, IF0 maker) {
    var var = projectVarConcept(name);
    O value = getOrCreateProjectVar(var, maker);
    var.persistent(true);
    ret value;
  }
  
  O getOrCreateBigProjectVar(S name, IF0 maker) {
    var var = projectVarConcept(name);
    O value = getOrCreateProjectVar(var, maker);
    var.makeBig();
    ret value;
  }
  
  O getOrCreateAutoClosingProjectVar(S name, IF0 maker) {
    var var = projectVarConcept(name);
    O value = getOrCreateProjectVar(var, maker);
    var.autoClose(true);
    ret value;
  }
  
  bool projectVarIsNotNull(S name) {
    var var = findProjectVar(name);
    ret var != null && var.has();
  }
  
  O getOrCreateProjectVar(G22Variable var, IF0 maker) {
    if (!var.has()) {
      O value = maker!;
      if (value != null)
        var.setValueIfNull(value);
    }
    ret var!;
  }
  
  // variable is made persistent
  IVarWithNotify liveProjectVar(S name, O defaultValue default null) {
    G22Variable var = projectVarConcept(name);
    var.persistent(true);
    var.setValueIfNull(defaultValue);
    ret var.varValue();
  }
  
  IVarWithNotify liveTransientProjectVar(S name, O defaultValue default null) {
    G22Variable var = projectVarConcept(name);
    var.persistent(false);
    var.setValueIfNull(defaultValue);
    ret var.varValue();
  }
  
  void replaceCloseableProjectVar(S name, IF0<? extends AutoCloseable> calc) {
    O value = getProjectVar(name);
    if (value cast AutoCloseable) {
      main close(value);
      deleteProjectVar(name);
    }
    setTransientProjectVar(name, calc?!);
  }
  
  // notify of internal changes in the variable
  // even though the value pointer may have stayed the same.
  void projectVarChanged(S name) {
    var var = findProjectVar(name);
    var?.changeInsideOfValue();
  }

  // search by value
  Cl<G22Variable> projectVarChanged(O value) {
    var vars = conceptsWhere(concepts, G22Variable, +value);
    for (var : vars)
      var.change();
    ret vars;
  }
  
  // timeouts
  
  double defaultScriptTimeout() { ret 10.0; }
  double projectWideScriptTimeout() {
    ret or(toDoubleOrNull(getProjectVar("!Script Timeout")),
      defaultScriptTimeout());
  }
  
  // getting objects
  
  G22Analyzer getAnalyzer(long id) {
    var a = getConcept(concepts, G22Analyzer, id);
    if (a == null) fail("Analyzer not found: " + id);
    ret a;
  }

  G22LeftArrowScript getScript(long id) {
    var a = getConcept(concepts, G22LeftArrowScript, id);
    if (a == null) fail("Script not found: " + id);
    ret a;
  }

  // calling scripts
  
  // This is meant to be called from within another script.
  // No timeout (timeout is handled by calling script)
  // Uses "safest" version available (auto-run or saved)
  O callScript(long id) {
    var script = getScript(id);
    ret script.evaluateWithoutTimeout();
  }
  
  // Like callScript, but only uses auto-run version
  O callAutoRunnableScript(long id) {
    var script = getScript(id);
    ret script.evaluateAutoRunWithoutTimeout();
  }
  
  // no timeout by default
  double defaultTimeout() { ret infinity(); }
  
  // evaluate
  // -with timeout
  // -registered in background processes
  // -with module entered
  <A> A evalRegisteredCode(double timeoutSeconds default defaultTimeout(), S processName, IF0<A> code) {
    if (code == null) null;
    ret evalWithTimeoutOrTypedException(timeoutSeconds, ->
      useThisThreadAsBackgroundProcess(processName, code)
    );
  }
  
  Thread startAsRegisteredThread(S processName, Runnable r) {
    if (r == null) null;
    ret startThread(processName, -> useThisThreadAsBackgroundProcess(processName, toIF0(r)));
  }

  <A> A useThisThreadAsBackgroundProcess(S processName, IF0<A> code) {
    temp enter();
    temp var process = backgroundProcessesUI.tempAdd(processName);
    Thread myThread = currentThread();
    process.setInterruptAction(r { cancelThread(myThread) });
    ret code!;
  }
  
  virtual GazelleHost host() {
    temp enter();
    ret dm_os();
  }
  
  <A> A timeFunction(S name, IF0<A> f) {
    ret functionTimings.get(name, f);
  }
  
  bool isConceptsDir(File dir) {
    ret isSameFile(conceptsDir(concepts), dir);
  }
  
  synchronized FileWatchService fileWatcher() {
    ret fileWatcher if null = new FileWatchService;
  }
  
  synchronized selfType onProjectFileChanged(IVF1<File> listener) {
    super.onProjectFileChanged(listener);
    if (!projectFileListenerInitiated) {
      set projectFileListenerInitiated;
      fileWatcher().addRecursiveListener(dbDir(), l1 projectFileChanged);
    }
    this;
  }
  
  simplyCached G22ProjectInfo projectInfo() {
    ret optimizedUniq(concepts, G22ProjectInfo);
  }
  
  RunnablesReferenceQueue runnablesReferenceQueue() {
    ret masterStuff.runnablesReferenceQueue();
  }
  
  EphemeralObjectIDs ephemeralObjectIDs() {
    ret masterStuff.ephemeralObjectIDs();
  }
  
  // get a remember ephemeral object by ID
  O eph(long id) { ret ephemeralObjectIDs().get(id); }
  
  void openInBrowser(S url) {
    main openPlatformBrowser(url);
    /*if (Desktop.getDesktop().isSupported(Desktop.Action.BROWSE))
      main openInBrowser(url);
    else {
      S cmd;
      if (projectInfo().useFirefox() && isOnPATH("firefox")) 
        cmd = "firefox";
      else {
        cmd = chromeCmd();
        if (isRoot())
          cmd += " -no-sandbox";
      }
      cmd += " " + platformQuote(url);
      nohup(cmd);
    }*/
  }
  
  S compilationDate() {
    ret or2(compilationDateFromClassPath(this), "unknown");
  }
  
  // Global ID for project
  S projectID() {
    ret projectInfo().projectID();
  }
  
  IG22LoadedDB getLoadedDB() {
    ret masterStuff.getLoadedDB(concepts);
  }
  
  ConceptsComboBox<GalleryImage> galleryImagesComboBox() {
    ret swing(->
      new ConceptsComboBox<GalleryImage>(concepts, GalleryImage));
  }
  
  IBackgroundProcess tempAddBackgroundProcess(S name) {
    ret backgroundProcessesUI?.tempAdd(name);
  }
  
  IF1<S, Class> classFinder() {
    ret masterStuff.makeClassFinder();
  }
  
  O restructure(O o) {
    ret unstructure(structure(o), false, concepts.classFinder);
  }
  
  G22ProjectActions project() { ret projectActions(); }
  
  bool openPathInProject(S path) {
    ret projectActions().openPathInProject(path);
  }
  
  bool openUIURL aka showUIURL(S url) {
    ret projectActions().openUIURL(url);
  }
  
  BufferedImage loadProjectImage(S fileName) {
    ret loadImage2(projectFile(fileName));
  }
  
  IG22LoadedDB openDB(S name, bool hidden default false) {
    ret masterStuff().openDB(name, hidden);
  }
  
  G22Utils getProject(S name) {
    ret openDB(name, true).g22utils();
  }
  
  G22Utils getProjectIfOpen(S name) {
    var db = first(openProjects(), p -> eqic(p.g22utils().projectName(), name));
    ret db?.g22utils();
  }
  
  G22JavaObjectVisualizer visualizeObject(O o) {
    ret new G22JavaObjectVisualizer(this, o);
  }
  
  G22JavaObjectVisualizer visualizeObjectWithoutType(O o) {
    ret visualizeObject(o).withTypeAndTime(false);
  }
  
  swappable G22VariablesPanel makeVariablesPanel() {
    ret new G22VariablesPanel().g22utils(this);
  }
  
  swappable JComponent jGazelleLogo() {
    ret main jGazelleLogo();
  }
  
  bool devMode() {
    ret masterStuff().devMode();
  }
  
  // specialize list() for our concepts
  
  <A extends Concept> L<A> nuLike list(Class<A> type, Concepts cc default concepts()) {
    ret main list(cc, type);
  }
  
  <A extends Concept> L<A> list(Concepts concepts, Class<A> type) {
  ret main list(type, concepts);
  }
  
  G22GalleryImage galleryImageForMD5(S md5) {
    ret firstThat(list(concepts, G22GalleryImage),
      img -> cic(fileName(img.path), md5));
  }
  
  // add the right kind of scrollpane to an image surface
  JComponent wrapImageSurface(ImageSurface is) {
    ret is == null ?: jscroll_centered_borderless(is);
  }
  
  JComponent wrap(O o) {
    var c = main wrap(o);
    if (c cast ImageSurface)
      ret wrapImageSurface(c);
    ret c;
  }
  
  swappable S byUser() {
    ret "";
  }
  
  Cl<? extends IG22LoadedDB> getLoadedDBs aka openProjects() {
    ret masterStuff().openProjects();
  }
  
  <A extends Concept> L<A> nuLike listInOpenProjects(Class<A> type) {
    ret concatMap(openProjects(), db -> db.g22utils().list(type));
  }
  
  transient simplyCached PicturesByMD5 picturesByMD5() {
    ret new PicturesByMD5(projectFile("Images"))
      .extension(".qoi");
  }
  
  JButton reloadButton(S toolTip, Runnable action) {
    ret jimageButton(#1101440, toolTip, action);
  }
  
  void registerConcept(Concept c) {
    main registerConcept(concepts, c);
  }
  
  void registerConcept(Concepts cc, Concept c) {
    main registerConcept(cc, c);
  }
  
  void addingAdditionalAutoCompletes(LeftArrowScriptAutoCompleter autoCompleter) {
    S token = autoCompleter.prevToken();
    if (isIdentifier(token) && contains(token, "ProjectVar"))
      autoCompleter.addToSearcher(quoteAll(projectVarNames()));
  }
  
  meta-for Lib as S, File {  
    bool addLibrary(Lib library) {
      if (!main addLibrary(library)) false;
      print("Loaded library: " + library);
      masterStuff().newClassesDefined();
      true;
    }
  }
  
  // add an auto-closing resource to the project
  <A extends AutoCloseable> WrappedCloseable<A> addResource(A resource) {
    if (resource == null) null; 
    autoClosingResources.add(resource);
    ret new WrappedCloseable<>(resource) {
      @Override void beforeClose {
        autoClosingResources.remove(resource);
      }
    };
  }

  // TODO: Improve LAS to not need this anymore  
  O callFunctionFromScript(int scriptID, S functionName, O... args) {
    ret callFunctionFromScript((long) scriptID, functionName, args);
  }
    
  // This even returns the version being edited - very aggressive
  O callLatestFunctionFromScript(int scriptID, S functionName, O... args) {
    var function = getScript(scriptID).latestCompileResult().get().getFunction(functionName);
    ret function.callFromOutside(args);
  }
  
  // Uses "saved" version, not "cleared for auto-run"
  O callSavedFunctionFromScript(int scriptID, S functionName, O... args) {
    var function = getScript(scriptID).compileSaved().get().getFunction(functionName);
    ret function.callFromOutside(args);
  }
  
  O callFunctionFromScript(long scriptID, S functionName, O... args) {
    var function = getScript(scriptID).safestCompileResult().get().getFunction(functionName);
    ret function.callFromOutside(args);
  }
  
  JComponent visualizeAutoRunnableScript(long scriptID) {
    ret visualizeAutoRunnableScript(getScript(scriptID));
  }
  
  JComponent visualizeAutoRunnableScript(G22LeftArrowScript script) {
    if (script == null) null;

    if (!script.isClearForAutoRun())
      ret jcenteredlabel("Script not clear for auto-run");
      
    try {
      O result = script.evaluateAutoRunWithoutTimeout();
      var objVisualizer = G22JavaObjectVisualizer(this, result).withType(false);
      ret objVisualizer.visualize();
    } catch print e {
      ret jErrorView(e);
    }
  }
  
  // projectName must match base dir in zip
  void importProjectFromZip(File zipFile, S baseDirInZip, S projectName) {
    File dir = dirOfProjectNamed(projectName);
    if (isConceptsDir(dir)) {
      if (eqic(projectName(), "Default"))
        ret with infoMessage("Sorry dude");

      IG22LoadedDB defaultDB = masterStuff().getLoadedDBForConceptDir(dirOfProjectNamed("Default"));
      IG22LoadedDB preloadedDefaultDB = defaultDB;
      if (defaultDB == null)
        defaultDB = openDB("Default");
        
      project().closeProject();
      defaultDB.g22utils().importProjectFromZip(zipFile, baseDirInZip, projectName);
      
      // Close default project again if only opened for this purpose
      if (preloadedDefaultDB == null)
        defaultDB.projectActions().closeProject();
        
      ret;
    }
    
    if (!directoryIsEmpty(dir)) {
      if (confirmProjectReplacements && !swingConfirm("Archive and overwrite existing project " + projectName + "?"))
        ret;
      
      File archiveDir = javaxBackupDir("Gazelle/" + projectName + "-" + computerID() + "-" + ymdMinusHMS());
      moveFile(dir, archiveDir);
      infoMessage("Archived project to: " + archiveDir);
    }
      
    zip2dir(zipFile, empty(baseDirInZip) ? dir : dir.getParentFile());
    infoBox("Imported project " + projectName);
    
    masterStuff().openDB(projectName);
  }
  
  void importProjectFromZip(File zipFile) {
    S baseDir = baseDirInZip(zipFile);
    S projectName = takeFirst(baseDir, smartIndexOf(baseDir, '/'));
    if (empty(projectName)) {
      ret with inputText("Please enter name for imported project",
        name -> {
          if (!validFileName(name)) {
            infoBox("Invalid name, use simpler characters");
            importProjectFromZip(zipFile);
            ret;
          }
          importProjectFromZip(zipFile, "", name);
        });
    }
        
    assertValidFileName(projectName);
    importProjectFromZip(zipFile, baseDir, projectName);
  }
  
  Class export(Class c) {
    if (c != null) {
      projectWideClassDefs.put(dropHashFromClassName(shortClassName(c)), c);
      newFunctionsDefined();
    }
    ret c;
  }
  
  FunctionDef exportFunction aka export(FunctionDef def) {
    ret def == null ?: exportFunction(def.name, def);
  }
  
  FunctionDef exportFunction aka export(S name, FunctionDef def) {
    projectWideFunctionDefs.put(name, def);
    //print("Defined function " + name);
    
    // Make sure all compiled scripts are forgotten
    newFunctionsDefined();
    
    ret def;
  }
  
  // return previous definition
  FunctionDef unexportFunction aka unexport(S name) {
    FunctionDef f = projectWideFunctionDefs.remove(name);
    if (f != null) {
      print("Undefined function " + name);
      newFunctionsDefined();
    }
    ret f;
  }
  
  void newFunctionsDefined {
    masterStuff().newClassesDefined();
    recompileDate = tsNow();
  }

  bool shouldRecompile(LASCompileResult cr) {  
    ret recompileDate != null && cr.compilationStart() != null
      && cr.compilationStart().compareTo(recompileDate) < 0;
  }
  
  bool compileResultValid(LASCompileResult cr, S code) {
    ret cr != null && eq(cr.script, code) && !shouldRecompile(cr);
  }
  
  toString {
    ret "G22Utils for " + projectName();
  }
  
  void editScript(G22LeftArrowScript script) {
    projectActions().editScript(script);
  }
  
  JButton editButton(S toolTip, Runnable action) {
    ret jimageButtonScaledToWidth(16, #1103068, toolTip, action);
  }
  
  JButton editScriptButton(G22LeftArrowScript script) {
    ret editButton("Edit script",
      -> projectActions().editScript(script));
  }
  
  G22ScriptView scriptView(long scriptID) {
    ret new G22ScriptView(getScript(scriptID));
  }
  
  File gazelleJar() {
    ret getBytecodePathForClass(this);
  }

} // end of G22Utils

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #1034148
Snippet name: G22Utils
Eternal ID of this version: #1034148/327
Text MD5: 63a7cad45b56bd22df9a9f7b0a7fd155
Author: stefan
Category: javax / gazelle 22
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-11-30 17:28:59
Source code size: 30454 bytes / 1026 lines
Pitched / IR pitched: No / No
Views / Downloads: 740 / 2816
Version history: 326 change(s)
Referenced in: [show references]