// 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 functionTimings; gettable Map projectWideFunctionDefs = syncMap(); gettable Map projectWideClassDefs = syncMap(); Timestamp recompileDate; gettable Set 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 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("Bool", "Boolean"); parser.addClassAlias("BollingerBands", "LiveBollingerBands"); 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); FlexibleVarContext varContext = flexibleVarContextFromParams(vars); 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 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 void setupScriptCRUD(SimpleCRUD_v2 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" /*"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 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 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 aka projectDir(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 gazelleDBs() { new L dbs; for (File dir : listDirsContainingFileNamed(databasesMotherDir(), "concepts.structure.gz")) dbs.add(new GazelleDB(fileName(dir), dir)); ret dbs; } ItIt 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 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 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 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 setPersistentProjectVar(S name, A value) { setProjectVar(true, name, value); ret value; } G22Variable setTransientProjectVar(S name, O value) { ret setProjectVar(false, name, value); } A setTransientProjectVarAndReturn(S name, A value) { setProjectVar(false, name, value); ret value; } void setAutoClosingProjectVar(S name, O value) { setTransientProjectVar(name, value).autoClose(true); } void clearProjectVar(S name) { var v = findProjectVar(name); v?.clear(); } 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; } G22Variable getOrCreateAutoClosingProjectVar_returnVar(S name, IF0 maker) { var var = projectVarConcept(name); getOrCreateProjectVar(var, maker); ret var.autoClose(true); } 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 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 aka saveProjectVar(S name) { var var = findProjectVar(name); var?.changeInsideOfValue(); } // search by value Cl projectVarChanged aka saveProjectVar(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; } S textOfScript(long id) { ret getScript(id).latestText(); } // 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(); } O callScriptWithParams(long id, O... params) { ret callScriptWithParams(getScript(id), params); } O callScriptWithParams(G22LeftArrowScript script, O... params) { var compiledScript = script.compileSaved()!; ret compiledScript.get(flexibleVarContextFromParams(params)); } // no timeout by default double defaultTimeout() { ret infinity(); } // evaluate // -with timeout // -registered in background processes // -with module entered A evalRegisteredCode(double timeoutSeconds default defaultTimeout(), S processName, IF0 code) { if (code == null) null; ret evalWithTimeoutOrTypedException(timeoutSeconds, -> useThisThreadAsBackgroundProcess(processName, code) ); } Thread startAsRegisteredThread(S processName default str_shorten(r), Runnable r) { if (r == null) null; ret startThread(processName, -> useThisThreadAsBackgroundProcess(processName, toIF0(r))); } A useThisThreadAsBackgroundProcess(S processName, IF0 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 timeFunction(S name, IF0 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 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 galleryImagesComboBox() { ret swing(-> new ConceptsComboBox(concepts, GalleryImage)); } IBackgroundProcess tempAddBackgroundProcess(S name) { ret backgroundProcessesUI?.tempAdd(name); } IF1 classFinder() { var master = masterStuff.makeClassFinder(); ret name -> { try object projectWideClassDefs().get(dropPrefix("main$", name)); ret master.get(name); }; } O restructure(O o) { ret unstructure(structure(o), false, concepts.classFinder); } G22ProjectActions project() { ret projectActions(); } bool openPathInProject(S path) { ret projectActions().openPathInProject(path); } void openUIURL aka showUIURL aka goToURIURL(S url) { projectActions().openUIURL(url); } BufferedImage loadProjectImage(S fileName) { ret loadImage2(projectFile(fileName)); } IG22LoadedDB openDB(S name, bool hidden default false) { ret masterStuff().openDB(name, hidden); } // Hides project if it is opened by this call G22Utils getProject(S name) { ret openDB(name, true).g22utils(); } G22Utils getProjectIfExists(S name) { ret !masterStuff().projectExists(name) ? null : getProject(name); } G22Utils getProjectIfOpen(S name) { var db = first(openProjects(), p -> eqic(p.g22utils().projectName(), name)); ret db?.g22utils(); } G22JavaObjectVisualizer visualizeObject aka visualizeJavaObject(O o) { ret new G22JavaObjectVisualizer(this, o); } G22JavaObjectVisualizer visualizeObjectWithoutType aka visualizeJavaObjectWithoutType(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 L nuLike list(Class type, Concepts cc default concepts()) { ret main list(cc, type); } L list(Concepts concepts, Class 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 getLoadedDBs aka openProjects() { ret masterStuff().openProjects(); } L nuLike listInOpenProjects(Class 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) { // projectVar magic S token = autoCompleter.prevToken(); if (isIdentifier(token) && cic(token, "ProjectVar")) autoCompleter.addToSearcher(quoteAll(projectVarNames())); // project-wide class defs autoCompleter.addToSearcher(keys(projectWideClassDefs())); } 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 WrappedCloseable 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); } O callProjectFunction(S functionName, O... args) { var function = projectWideFunctionDefs.get(functionName); if (function == null) fail("Function " + functionName + " not found in project " + projectName()); 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); } } JComponent visualizeSavedScript(long scriptID) { ret visualizeSavedScript(getScript(scriptID)); } JComponent visualizeSavedScript(G22LeftArrowScript script) { if (script == null) null; if (!script.isSaved()) ret jcenteredlabel("Script not saved"); try { O result = script.evaluateWithoutTimeout(); 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(" + quote(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 savedScriptView(long scriptID) { ret new G22ScriptView(getScript(scriptID)).mustBeAutoRunnable(false); } G22ScriptView scriptView(long scriptID) { ret new G22ScriptView(getScript(scriptID)); } File gazelleJar() { ret getBytecodePathForClass(this); } L projectErrors() { ret projectActions().projectErrors(); } JComponent jErrorView(Throwable e) { var view = main jErrorView(e); var scriptErrors = instancesOf(GazelleV_LeftArrowScript.ScriptError.class, allCausesIncludingSelf(e)); var sources = mapNotNulls(scriptErrors, -> .tokenRangeWithSrc()); if (empty(sources)) ret view; sources = uniquifySources(sources); ret centerAndEastWithMargin(view, jline(map(sources, src -> jThreadedButton( str_shorten(src, 40), -> projectActions().goToSource(src))))); } L uniquifySources(L sources) { ret uniquifyWith(sources, src -> pair(src.sourceInfo, src.renderRange())); } structure_Data makeStructureData() { ret concepts().makeStructureData(); } S g22struct(O o) { ret struct(o, makeStructureData()); } O g22unstruct(S struct) { ret unstructure(struct, classFinder()); } O stem() { ret dm_stem(module()); } void reloadProject { masterStuff().reopenDB(getLoadedDB()); } File downloadProjectFromGazAI(GazAICredentials credentials, S projectName) ctex { var cred = credentials.asParams(); var params = cloneMap(cred); params.put("asZip", 1); var url = "https://" + gazAIHost() + "/dl-authed/gazelle/" + spaceToPercent20(projectName) + "/"; var conn = urlConnection(url); var file = javaxBackupDir(concat(projectName + " Downloaded ", ymdMinusHMS(), ".zip")); doPostBinaryToFile(makePostData(params), conn, file); if (!isZip(file)) fail("Download failed, not authenticated for " + gazAIHost() + "?"); fileSavedInfoBox(file); ret file; } public void waitForAutoStart() { autoStarter().waitUntilDone(); } void adaptTextEditor(JSyntaxTextFileEditor editor) { editor.adaptSyntaxTextArea = textArea -> g22_adaptSyntaxTextAreaForHashRefs(textArea, this); } } // end of G22Utils