Transpiled version (69799L) is out of date.
1 | // Some of the functions are dependent on the concepts field, |
2 | // others are global. |
3 | |
4 | !include once #1035461 // Gazelle 22 Class synonyms Include |
5 | |
6 | sclass G22Utils_Base { |
7 | // event that is triggered every time a file or directory inside the |
8 | // project changes. Starts the fileWatcher automatically when the |
9 | // first listener is added. |
10 | event projectFileChanged(File file); |
11 | } |
12 | |
13 | sclass G22Utils > G22Utils_Base is AutoCloseable, TransientObject { |
14 | delegate FunctionDef to GazelleV_LeftArrowScript. |
15 | |
16 | settable IBackgroundProcesses backgroundProcessesUI; |
17 | settable Enterable module; |
18 | settable G22MasterStuff masterStuff; |
19 | settable Concepts concepts; |
20 | settable G22ProjectActions projectActions; |
21 | gettable G22AutoStarter autoStarter = new(this); |
22 | settable new FunctionTimings<S> functionTimings; |
23 | gettable Map<S, FunctionDef> projectWideFunctionDefs = syncMap(); |
24 | gettable Map<S, Class> projectWideClassDefs = syncMap(); |
25 | |
26 | Timestamp recompileDate; |
27 | |
28 | gettable Set<AutoCloseable> autoClosingResources = syncLinkedHashSet(); |
29 | |
30 | // TODO: set this to a few seconds if your variables are expensive to render |
31 | // settable Seconds variableUpdateIntervalInUI; |
32 | |
33 | FileWatchService fileWatcher; // general file watch service |
34 | bool projectFileListenerInitiated; |
35 | |
36 | gettable CombinedStringifier stringifier = new( |
37 | o -> o cast BufferedImage ? "Image (" + o.getWidth() + "*" + o.getHeight() + " px)" : null |
38 | ); |
39 | |
40 | ILASClassLoader lasClassLoader() { ret masterStuff?.lasClassLoader(); } |
41 | |
42 | settable bool confirmProjectReplacements; |
43 | |
44 | // add fields here |
45 | |
46 | ImageSurface stdImageSurface_noToolTip(ImageSurface is default imageSurface()) { |
47 | imageSurface_pixelated(is); |
48 | is.setAutoZoomToDisplay(true).repaintInThread(false); |
49 | is.defaultImageDir = -> dbDir(); |
50 | is.specialPurposed = true; |
51 | ret is; |
52 | } |
53 | |
54 | ImageSurface stdImageSurface(ImageSurface is default imageSurface()) { |
55 | stdImageSurface_noToolTip(is); |
56 | new ImageSurface_PositionToolTip(is); |
57 | ret is; |
58 | } |
59 | |
60 | L<ImageSurface> stdImageSurfaces(Cl images) { |
61 | ret map stdImageSurface(toBufferedImages(images)); |
62 | } |
63 | |
64 | ImageSurface stdImageSurface(BufferedImage etc img) { |
65 | var is = stdImageSurface(); |
66 | is.setImage(img); |
67 | ret is; |
68 | } |
69 | |
70 | ImageSurface stdImageSurface(File file) { |
71 | var is = stdImageSurface(); |
72 | is.setImage(file); |
73 | ret is; |
74 | } |
75 | |
76 | ImageSurface stdImageSurface(G22GalleryImage img) { |
77 | ret stdImageSurface(img?.path); |
78 | } |
79 | |
80 | ImageSurface stdImageSurfaceWithSelection(BufferedImage etc img, Rect selection) { |
81 | var is = stdImageSurface(img); |
82 | is.setSelection(selection); |
83 | ret is; |
84 | } |
85 | |
86 | S stringify(O o) { ret stringifier.toString(o); } |
87 | |
88 | event bigVariableLoaded(G22Variable var); |
89 | |
90 | event settingUpParser(GazelleV_LeftArrowScriptParser parser); |
91 | event settingUpScriptIDE(JLeftArrowScriptIDE ide); |
92 | |
93 | GazelleV_LeftArrowScriptParser leftArrowParser() { |
94 | new GazelleV_LeftArrowScriptParser parser; |
95 | parser.classNameResolver(classNameResolver()); |
96 | parser.lasClassLoader(lasClassLoader()); |
97 | |
98 | settingUpParser(parser); |
99 | parser.addClassAlias("Bool", "Boolean"); |
100 | parser.addClassAlias("BollingerBands", "LiveBollingerBands"); |
101 | parser.addClassAlias("Freq", "Frequency"); |
102 | parser.addClassAlias("PriceDigitizer", "PriceDigitizer2"); |
103 | parser.addClassAlias("MRUAndAllTimeTop", "MRUAndAllTimeTop_optimized"); |
104 | parser.findExternalObject2 = name -> { |
105 | try object projectWideClassDefs.get(name); |
106 | ret parser.findExternalObject2_base(name); |
107 | }; |
108 | |
109 | parser.addFunctionDefs(projectWideFunctionDefs); |
110 | |
111 | ret parser; |
112 | } |
113 | |
114 | O leftArrow(S script) { |
115 | ret leftArrowParse(script)!; |
116 | } |
117 | |
118 | GazelleV_LeftArrowScript.Script leftArrowParse(S script) { |
119 | ret leftArrowParser().parse(script); |
120 | } |
121 | |
122 | O leftArrowWithVars(S script, O... vars) { |
123 | var parser = leftArrowParser(); |
124 | for (int i = 0; i < l(vars); i += 2) |
125 | parser.addVar((S) vars[i], or(_getClass(vars[i+1]), O), true); |
126 | |
127 | var parsed = parser.parse(script); |
128 | FlexibleVarContext varContext = flexibleVarContextFromParams(vars); |
129 | ret parsed.get(varContext); |
130 | } |
131 | |
132 | void basicParserTest() { |
133 | var parser = leftArrowParser(); |
134 | print(classContainerPrefixes := parser.classContainerPrefixes()); |
135 | assertEquals(pair(1, 2), parser.parse("new Pair 1 2")!); |
136 | } |
137 | |
138 | ifclass JLeftArrowScriptIDE |
139 | JLeftArrowScriptIDE leftArrowIDE aka leftArrowScriptIDE() { |
140 | new JLeftArrowScriptIDE ide; |
141 | ide.g22utils(this); |
142 | ide.scriptTimeout(projectWideScriptTimeout()); |
143 | settingUpScriptIDE(ide); |
144 | ret ide; |
145 | } |
146 | endif |
147 | |
148 | File byteCodePath() { |
149 | ret assertNotNull(getBytecodePathForClass(this)); |
150 | } |
151 | |
152 | simplyCached ClassNameResolver classNameResolver() { |
153 | ret new ClassNameResolver().byteCodePath(byteCodePath()).init(); |
154 | } |
155 | |
156 | File databasesMotherDir() { |
157 | ret masterStuff.databasesMotherDir(); |
158 | } |
159 | |
160 | File dirOfProjectNamed(S name) { |
161 | assertNempty(name); |
162 | ret newFile(databasesMotherDir(), name); |
163 | } |
164 | |
165 | AutoCloseable enter() { ret module?.enter(); } |
166 | |
167 | S defaultDBName() { ret "Default"; } |
168 | |
169 | File lastOpenedDBsFile() { |
170 | ret newFile(databasesMotherDir(), "Last Opened"); |
171 | } |
172 | |
173 | File recentlyOpenedDBsFile() { |
174 | ret newFile(databasesMotherDir(), "Recently Opened"); |
175 | } |
176 | |
177 | File autoUpdateFile() { |
178 | ret newFile(databasesMotherDir(), "Auto-Update"); |
179 | } |
180 | |
181 | bool autoUpdateEnabled() { |
182 | ret fileExists(autoUpdateFile()); |
183 | } |
184 | |
185 | void setAutoUpdate(bool b) { |
186 | createOrRemoveFile(autoUpdateFile(), b); |
187 | } |
188 | |
189 | LS dbsToOpen() { |
190 | ret loadRecentProjectsFile(lastOpenedDBsFile()); |
191 | } |
192 | |
193 | LS dbNamesRecentlyOpened() { |
194 | ret loadRecentProjectsFile(recentlyOpenedDBsFile()); |
195 | } |
196 | |
197 | void addToRecentDBNames(S dbName, bool hidden) { |
198 | LS list = dbNamesRecentlyOpened(); |
199 | LS list2 = cloneList(list); |
200 | removeAll(list2, dbName, "*" + dbName); |
201 | list2.add(0, hidden ? "*" + dbName : dbName); |
202 | truncateList(list2, 100); |
203 | if (!eq(list, list2)) |
204 | saveTextFile(recentlyOpenedDBsFile(), lines(list2)); |
205 | } |
206 | |
207 | // returns project names with optional "*" prefix for hidden projects |
208 | LS loadRecentProjectsFile(File file) { |
209 | new LS dbNames; |
210 | for (S name : tlft(loadTextFile(file))) { |
211 | S name2 = dropPrefix("*", name); |
212 | if (fileExists(newFile(databasesMotherDir(), name2))) |
213 | dbNames.add(name); |
214 | } |
215 | |
216 | if (empty(dbNames)) dbNames.add(defaultDBName()); |
217 | ret dbNames; |
218 | } |
219 | |
220 | void setOpenDBs(Cl<? extends IG22LoadedDB> dbs) { |
221 | new LS dbNames; |
222 | for (db : dbs) { |
223 | var dbDir = conceptsDir(db.concepts()); |
224 | if (sameFile(databasesMotherDir(), dirOfFile(dbDir))) |
225 | dbNames.add((db.hidden() ? "*" : "") + fileName(dbDir)); |
226 | } |
227 | |
228 | saveTextFile(lastOpenedDBsFile(), lines(dbNames)); |
229 | } |
230 | |
231 | ifclass SimpleCRUD_v2 |
232 | <A extends G22LeftArrowScript> void setupScriptCRUD(SimpleCRUD_v2<A> crud, bool allowRunOnProjectOpen default false) { |
233 | crud.useNewChangeHandler(true); |
234 | crud.editableFieldsForItem = x -> llNonNulls("description", |
235 | allowRunOnProjectOpen ? "runOnProjectOpen" : null, |
236 | allowRunOnProjectOpen ? "runOrder" : null); |
237 | //G22LeftArrowScript.f_description().getName()); |
238 | crud.multiLineField("text"); |
239 | crud.multiLineField("editingText"); |
240 | crud.makeTextArea = text -> jMinHeight(200, crud.makeTextArea_base(text)); |
241 | crud.humanizeFieldNames = false; |
242 | crud.iconButtons(true); |
243 | crud.itemToMap_inner2 = c -> scriptToMap(c, allowRunOnProjectOpen); |
244 | crud.dontDuplicateFields = litset("runOnProjectOpen", /*"runOrder",*/ "runCount", "lastResultByMode"); |
245 | |
246 | } |
247 | endif |
248 | |
249 | MapSO scriptToMap(G22LeftArrowScript c, bool allowRunOnProjectOpen default false) { |
250 | ret litorderedmap( |
251 | "Description" := c.description(), |
252 | "Status" := renderScriptStatus(c), |
253 | "LoC" := renderScriptLoC(c), |
254 | "Import note" := c.importNote, |
255 | "Run on project open" := c.renderRunOnProjectOpenStatus()); |
256 | } |
257 | |
258 | S renderScriptStatus(G22LeftArrowScript c) { |
259 | ret or2_rev("Empty", joinNemptiesWithSpacedPlus( |
260 | c.isClearForAutoRun() ? "Clear for auto-run" : null, |
261 | c.isSavedDistinctFromAutoRunVersion() ? "Saved" /*"Saved (not cleared)"*/ : null, |
262 | c.isEditing() ? "Editing" : null |
263 | )); |
264 | } |
265 | |
266 | S renderScriptLoC(G22LeftArrowScript c) { |
267 | ret n2(intMax(mapLL linesOfCode_javaTok( |
268 | c.editingText, |
269 | c.text, |
270 | c.codeForAutoRun()))); |
271 | } |
272 | |
273 | // e.g. for an image file |
274 | L<G22Label> labelsForFile(File file) { |
275 | if (file == null) null; |
276 | File labelsFile = appendToFileName(file, ".labels"); |
277 | LS labels = tlft(loadTextFile(labelsFile)); |
278 | ret map getLabel(labels); |
279 | } |
280 | |
281 | File labelsFile(File file) { |
282 | if (file == null) null; |
283 | ret appendToFileName(file, ".labels"); |
284 | } |
285 | |
286 | void setLabelsForFile(File file, L<G22Label> labels) { |
287 | LS list = map(labels, label -> label.name); |
288 | File f = labelsFile(file); |
289 | saveTextFile(f, lines(list)); |
290 | print("Saved " + nLabels(list) + " (" + joinWithComma(list) + ") to " + f); |
291 | } |
292 | |
293 | G22Label getLabel(S name) { |
294 | if (empty(name)) null; |
295 | if (containsNewLine(name)) fail("No newlines in label names allowed: " + name); |
296 | ret uniqCI(concepts, G22Label, +name); |
297 | } |
298 | |
299 | File dbDir aka projectDir() { ret conceptsDir(concepts); } |
300 | |
301 | File fileInDbDir aka projectFile aka projectDir(S name) { ret newFile(dbDir(), name); } |
302 | |
303 | record GazelleDB(S name, File dir) { |
304 | S name() { ret name; } |
305 | File dir() { ret dir; } |
306 | |
307 | bool loaded() { |
308 | ret loadedDB() != null; |
309 | } |
310 | |
311 | simplyCached IG22LoadedDB loadedDB() { |
312 | ret masterStuff.getLoadedDBForConceptDir(dir); |
313 | } |
314 | |
315 | File conceptsFile() { ret conceptsFileIn(dir); } |
316 | } |
317 | |
318 | L<GazelleDB> gazelleDBs() { |
319 | new L<GazelleDB> dbs; |
320 | for (File dir : listDirsContainingFileNamed(databasesMotherDir(), |
321 | "concepts.structure.gz")) |
322 | dbs.add(new GazelleDB(fileName(dir), dir)); |
323 | ret dbs; |
324 | } |
325 | |
326 | ItIt<Concepts> peekAllProjectsConcepts() { |
327 | var classFinder = masterStuff.makeClassFinder(); |
328 | ret mapI_pcall(gazelleDBs(), db -> { |
329 | var cc = newConceptsWithClassFinder(db.conceptsFile(), classFinder); |
330 | cc.loadFromDisk(); |
331 | ret cc; |
332 | }); |
333 | } |
334 | |
335 | ifclass RSyntaxTextAreaWithSearch |
336 | RSyntaxTextAreaWithSearch newSyntaxTextArea(IF1<JComponent> wrapStatusLabel default (IF1) null) { |
337 | RSyntaxTextAreaWithSearch ta = new(wrapStatusLabel); |
338 | ta.textArea().setHighlightCurrentLine(false); |
339 | ta.menuLessOperation(); |
340 | ret ta; |
341 | } |
342 | |
343 | RSyntaxTextAreaWithSearch newSyntaxTextArea(S text) { |
344 | var ta = newSyntaxTextArea(); |
345 | ta.setText(text); |
346 | ret ta; |
347 | } |
348 | endif |
349 | |
350 | File projectStoryTextFile() { ret newFile(dbDir(), "story.txt"); } |
351 | |
352 | S projectName() { ret fileName(dbDir()); } |
353 | |
354 | close { |
355 | autoStarter.close(); |
356 | closeAndClear(autoClosingResources); |
357 | dispose fileWatcher; |
358 | } |
359 | |
360 | // solve shadowing problem in LAS |
361 | void close(AutoCloseable c) { |
362 | main close(c); |
363 | } |
364 | |
365 | // project vars |
366 | |
367 | G22Variable findProjectVar(S name) { |
368 | ret conceptWhereCI(concepts, G22Variable, +name); |
369 | } |
370 | |
371 | Cl<S> projectVarNames() { |
372 | ret collect name(list(concepts, G22Variable)); |
373 | } |
374 | |
375 | O getProjectVar(S name) { |
376 | G22Variable var = findProjectVar(name); |
377 | ret var?.value(); |
378 | } |
379 | |
380 | // If it's a big variable, load it just now and then forget |
381 | // it again |
382 | O getBigProjectVarOnce(S name) { |
383 | G22Variable var = findProjectVar(name); |
384 | ret var?.getOnce(); |
385 | } |
386 | |
387 | // fail if var doesn't exist or value is null |
388 | O getMandatoryProjectVar(S name) { |
389 | ret assertNotNull(name, getProjectVar(name)); |
390 | } |
391 | |
392 | O getOrSetTransientProjectVar(S name, IF0 f) { |
393 | try object getProjectVar(name); |
394 | ret setTransientProjectVarAndReturn(name, f!); |
395 | } |
396 | |
397 | O getProjectVarOrCallScript(S name, long scriptID) { |
398 | try object getProjectVar(name); |
399 | ret callScript(scriptID); |
400 | } |
401 | |
402 | O getProjectVarSetByScript(S name, long scriptID) { |
403 | try object getProjectVar(name); |
404 | callScript(scriptID); |
405 | ret getProjectVar(name); |
406 | } |
407 | |
408 | // gets first non-null value of project variable named "name" |
409 | // in any open project (order not defined) |
410 | O getProjectVarFromAnyProject(S name) { |
411 | for (project : masterStuff().openProjects()) |
412 | try object project.g22utils().getProjectVar(name); |
413 | null; |
414 | } |
415 | |
416 | // gets all non-null values from project variable named "name" |
417 | // in any open project |
418 | L getProjectVarFromAllProjects aka getVarFromAnyProject(S name) { |
419 | ret nonNulls(masterStuff().openProjects(), |
420 | project -> project.g22utils().getProjectVar(name)); |
421 | } |
422 | |
423 | // Creates the variable if it's not there, otherwise |
424 | // returns existing variable. |
425 | G22Variable projectVarConcept(S name) { |
426 | ret optimizedUniqCI(concepts, G22Variable, +name); |
427 | } |
428 | |
429 | O waitForProjectVar(double timeoutSeconds default infinity(), S name) { |
430 | G22Variable var = projectVarConcept(name); |
431 | ret waitForCalculatedValueUsingChangeListener(timeoutSeconds, -> var.value(), var); |
432 | } |
433 | |
434 | void setBigProjectVar(bool persistent, S name, O value) { |
435 | if (persistent) |
436 | setBigProjectVar(name, value); |
437 | else |
438 | setTransientProjectVar(name, value); |
439 | } |
440 | |
441 | G22Variable setProjectVar(bool persistent, S name, O value) { |
442 | G22Variable var = projectVarConcept(name); |
443 | |
444 | // defensive order |
445 | if (!persistent) var.persistent(persistent); |
446 | var.value(value); |
447 | if (persistent) var.persistent(persistent); |
448 | |
449 | ret var; |
450 | } |
451 | |
452 | // uncache a big project variable. Does not change the value |
453 | void unloadProjectVar(S name) { |
454 | var var = findProjectVar(name); |
455 | var?.unload(); |
456 | } |
457 | |
458 | <A> A setBigProjectVar(S name, A value) { |
459 | setPersistentProjectVar(name, value); |
460 | G22Variable var = projectVarConcept(name); |
461 | var.makeBig(); |
462 | ret value; |
463 | } |
464 | |
465 | O getCachedProjectVar(S name) { |
466 | var var = findProjectVar(name); |
467 | ret var?.cachedValue(); |
468 | } |
469 | |
470 | bool isBigProjectVar(S name) { |
471 | var v = findProjectVar(name); |
472 | ret v != null && v.big(); |
473 | } |
474 | |
475 | <A> A setPersistentProjectVar(S name, A value) { |
476 | setProjectVar(true, name, value); |
477 | ret value; |
478 | } |
479 | |
480 | G22Variable setTransientProjectVar(S name, O value) { |
481 | ret setProjectVar(false, name, value); |
482 | } |
483 | |
484 | <A> A setTransientProjectVarAndReturn(S name, A value) { |
485 | setProjectVar(false, name, value); |
486 | ret value; |
487 | } |
488 | |
489 | void setAutoClosingProjectVar(S name, O value) { |
490 | setTransientProjectVar(name, value).autoClose(true); |
491 | } |
492 | |
493 | void clearProjectVar(S name) { |
494 | var v = findProjectVar(name); |
495 | v?.clear(); |
496 | } |
497 | |
498 | void deleteProjectVar(S name) { |
499 | deleteConcept(findProjectVar(name)); |
500 | } |
501 | |
502 | // Note: unsynced. Wild west baby! |
503 | O getOrCreateProjectVar aka getOrCreateTransientProjectVar(S name, IF0 maker) { |
504 | ret getOrCreateProjectVar(projectVarConcept(name), maker); |
505 | } |
506 | |
507 | O getOrCreatePersistentProjectVar(S name, IF0 maker) { |
508 | var var = projectVarConcept(name); |
509 | O value = getOrCreateProjectVar(var, maker); |
510 | var.persistent(true); |
511 | ret value; |
512 | } |
513 | |
514 | O getOrCreateBigProjectVar(S name, IF0 maker) { |
515 | var var = projectVarConcept(name); |
516 | O value = getOrCreateProjectVar(var, maker); |
517 | var.makeBig(); |
518 | ret value; |
519 | } |
520 | |
521 | O getOrCreateAutoClosingProjectVar(S name, IF0 maker) { |
522 | var var = projectVarConcept(name); |
523 | O value = getOrCreateProjectVar(var, maker); |
524 | var.autoClose(true); |
525 | ret value; |
526 | } |
527 | |
528 | G22Variable getOrCreateAutoClosingProjectVar_returnVar(S name, IF0 maker) { |
529 | var var = projectVarConcept(name); |
530 | getOrCreateProjectVar(var, maker); |
531 | ret var.autoClose(true); |
532 | } |
533 | |
534 | bool projectVarIsNotNull(S name) { |
535 | var var = findProjectVar(name); |
536 | ret var != null && var.has(); |
537 | } |
538 | |
539 | O getOrCreateProjectVar(G22Variable var, IF0 maker) { |
540 | if (!var.has()) { |
541 | O value = maker!; |
542 | if (value != null) |
543 | var.setValueIfNull(value); |
544 | } |
545 | ret var!; |
546 | } |
547 | |
548 | // variable is made persistent |
549 | IVarWithNotify liveProjectVar(S name, O defaultValue default null) { |
550 | G22Variable var = projectVarConcept(name); |
551 | var.persistent(true); |
552 | var.setValueIfNull(defaultValue); |
553 | ret var.varValue(); |
554 | } |
555 | |
556 | IVarWithNotify liveTransientProjectVar(S name, O defaultValue default null) { |
557 | G22Variable var = projectVarConcept(name); |
558 | var.persistent(false); |
559 | var.setValueIfNull(defaultValue); |
560 | ret var.varValue(); |
561 | } |
562 | |
563 | void replaceCloseableProjectVar(S name, IF0<? extends AutoCloseable> calc) { |
564 | O value = getProjectVar(name); |
565 | if (value cast AutoCloseable) { |
566 | main close(value); |
567 | deleteProjectVar(name); |
568 | } |
569 | setTransientProjectVar(name, calc?!); |
570 | } |
571 | |
572 | // notify of internal changes in the variable |
573 | // even though the value pointer may have stayed the same. |
574 | void projectVarChanged aka saveProjectVar(S name) { |
575 | var var = findProjectVar(name); |
576 | var?.changeInsideOfValue(); |
577 | } |
578 | |
579 | // search by value |
580 | Cl<G22Variable> projectVarChanged aka saveProjectVar(O value) { |
581 | var vars = conceptsWhere(concepts, G22Variable, +value); |
582 | for (var : vars) |
583 | var.change(); |
584 | ret vars; |
585 | } |
586 | |
587 | // timeouts |
588 | |
589 | double defaultScriptTimeout() { ret 10.0; } |
590 | double projectWideScriptTimeout() { |
591 | ret or(toDoubleOrNull(getProjectVar("!Script Timeout")), |
592 | defaultScriptTimeout()); |
593 | } |
594 | |
595 | // getting objects |
596 | |
597 | G22Analyzer getAnalyzer(long id) { |
598 | var a = getConcept(concepts, G22Analyzer, id); |
599 | if (a == null) fail("Analyzer not found: " + id); |
600 | ret a; |
601 | } |
602 | |
603 | G22LeftArrowScript getScript(long id) { |
604 | var a = getConcept(concepts, G22LeftArrowScript, id); |
605 | if (a == null) fail("Script not found: " + id); |
606 | ret a; |
607 | } |
608 | |
609 | S textOfScript(long id) { |
610 | ret getScript(id).latestText(); |
611 | } |
612 | |
613 | // calling scripts |
614 | |
615 | // This is meant to be called from within another script. |
616 | // No timeout (timeout is handled by calling script) |
617 | // Uses "safest" version available (auto-run or saved) |
618 | O callScript(long id) { |
619 | var script = getScript(id); |
620 | ret script.evaluateWithoutTimeout(); |
621 | } |
622 | |
623 | // Like callScript, but only uses auto-run version |
624 | O callAutoRunnableScript(long id) { |
625 | var script = getScript(id); |
626 | ret script.evaluateAutoRunWithoutTimeout(); |
627 | } |
628 | |
629 | O callScriptWithParams(long id, O... params) { |
630 | ret callScriptWithParams(getScript(id), params); |
631 | } |
632 | |
633 | O callScriptWithParams(G22LeftArrowScript script, O... params) { |
634 | var compiledScript = script.compileSaved()!; |
635 | ret compiledScript.get(flexibleVarContextFromParams(params)); |
636 | } |
637 | |
638 | // no timeout by default |
639 | double defaultTimeout() { ret infinity(); } |
640 | |
641 | // evaluate |
642 | // -with timeout |
643 | // -registered in background processes |
644 | // -with module entered |
645 | <A> A evalRegisteredCode(double timeoutSeconds default defaultTimeout(), S processName, IF0<A> code) { |
646 | if (code == null) null; |
647 | ret evalWithTimeoutOrTypedException(timeoutSeconds, -> |
648 | useThisThreadAsBackgroundProcess(processName, code) |
649 | ); |
650 | } |
651 | |
652 | Thread startAsRegisteredThread(S processName default str_shorten(r), Runnable r) { |
653 | if (r == null) null; |
654 | ret startThread(processName, -> useThisThreadAsBackgroundProcess(processName, toIF0(r))); |
655 | } |
656 | |
657 | <A> A useThisThreadAsBackgroundProcess(S processName, IF0<A> code) { |
658 | temp enter(); |
659 | temp var process = backgroundProcessesUI.tempAdd(processName); |
660 | Thread myThread = currentThread(); |
661 | process.setInterruptAction(r { cancelThread(myThread) }); |
662 | ret code!; |
663 | } |
664 | |
665 | virtual GazelleHost host() { |
666 | temp enter(); |
667 | ret dm_os(); |
668 | } |
669 | |
670 | <A> A timeFunction(S name, IF0<A> f) { |
671 | ret functionTimings.get(name, f); |
672 | } |
673 | |
674 | bool isConceptsDir(File dir) { |
675 | ret isSameFile(conceptsDir(concepts), dir); |
676 | } |
677 | |
678 | synchronized FileWatchService fileWatcher() { |
679 | ret fileWatcher if null = new FileWatchService; |
680 | } |
681 | |
682 | synchronized selfType onProjectFileChanged(IVF1<File> listener) { |
683 | super.onProjectFileChanged(listener); |
684 | if (!projectFileListenerInitiated) { |
685 | set projectFileListenerInitiated; |
686 | fileWatcher().addRecursiveListener(dbDir(), l1 projectFileChanged); |
687 | } |
688 | this; |
689 | } |
690 | |
691 | simplyCached G22ProjectInfo projectInfo() { |
692 | ret optimizedUniq(concepts, G22ProjectInfo); |
693 | } |
694 | |
695 | RunnablesReferenceQueue runnablesReferenceQueue() { |
696 | ret masterStuff.runnablesReferenceQueue(); |
697 | } |
698 | |
699 | EphemeralObjectIDs ephemeralObjectIDs() { |
700 | ret masterStuff.ephemeralObjectIDs(); |
701 | } |
702 | |
703 | // get a remember ephemeral object by ID |
704 | O eph(long id) { ret ephemeralObjectIDs().get(id); } |
705 | |
706 | void openInBrowser(S url) { |
707 | main openPlatformBrowser(url); |
708 | /*if (Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) |
709 | main openInBrowser(url); |
710 | else { |
711 | S cmd; |
712 | if (projectInfo().useFirefox() && isOnPATH("firefox")) |
713 | cmd = "firefox"; |
714 | else { |
715 | cmd = chromeCmd(); |
716 | if (isRoot()) |
717 | cmd += " -no-sandbox"; |
718 | } |
719 | cmd += " " + platformQuote(url); |
720 | nohup(cmd); |
721 | }*/ |
722 | } |
723 | |
724 | S compilationDate() { |
725 | ret or2(compilationDateFromClassPath(this), "unknown"); |
726 | } |
727 | |
728 | // Global ID for project |
729 | S projectID() { |
730 | ret projectInfo().projectID(); |
731 | } |
732 | |
733 | IG22LoadedDB getLoadedDB() { |
734 | ret masterStuff.getLoadedDB(concepts); |
735 | } |
736 | |
737 | ConceptsComboBox<GalleryImage> galleryImagesComboBox() { |
738 | ret swing(-> |
739 | new ConceptsComboBox<GalleryImage>(concepts, GalleryImage)); |
740 | } |
741 | |
742 | IBackgroundProcess tempAddBackgroundProcess(S name) { |
743 | ret backgroundProcessesUI?.tempAdd(name); |
744 | } |
745 | |
746 | IF1<S, Class> classFinder() { |
747 | var master = masterStuff.makeClassFinder(); |
748 | ret name -> { |
749 | try object projectWideClassDefs().get(dropPrefix("main$", name)); |
750 | ret master.get(name); |
751 | }; |
752 | } |
753 | |
754 | O restructure(O o) { |
755 | ret unstructure(structure(o), false, concepts.classFinder); |
756 | } |
757 | |
758 | G22ProjectActions project() { ret projectActions(); } |
759 | |
760 | bool openPathInProject(S path) { |
761 | ret projectActions().openPathInProject(path); |
762 | } |
763 | |
764 | void openUIURL aka showUIURL aka goToURIURL(S url) { |
765 | projectActions().openUIURL(url); |
766 | } |
767 | |
768 | BufferedImage loadProjectImage(S fileName) { |
769 | ret loadImage2(projectFile(fileName)); |
770 | } |
771 | |
772 | IG22LoadedDB openDB(S name, bool hidden default false) { |
773 | ret masterStuff().openDB(name, hidden); |
774 | } |
775 | |
776 | // Hides project if it is opened by this call |
777 | G22Utils getProject(S name) { |
778 | ret openDB(name, true).g22utils(); |
779 | } |
780 | |
781 | G22Utils getProjectIfExists(S name) { |
782 | ret !masterStuff().projectExists(name) ? null |
783 | : getProject(name); |
784 | } |
785 | |
786 | G22Utils getProjectIfOpen(S name) { |
787 | var db = first(openProjects(), p -> eqic(p.g22utils().projectName(), name)); |
788 | ret db?.g22utils(); |
789 | } |
790 | |
791 | G22JavaObjectVisualizer visualizeObject aka visualizeJavaObject(O o) { |
792 | ret new G22JavaObjectVisualizer(this, o); |
793 | } |
794 | |
795 | G22JavaObjectVisualizer visualizeObjectWithoutType aka visualizeJavaObjectWithoutType(O o) { |
796 | ret visualizeObject(o).withTypeAndTime(false); |
797 | } |
798 | |
799 | swappable G22VariablesPanel makeVariablesPanel() { |
800 | ret new G22VariablesPanel().g22utils(this); |
801 | } |
802 | |
803 | swappable JComponent jGazelleLogo() { |
804 | ret main jGazelleLogo(); |
805 | } |
806 | |
807 | bool devMode() { |
808 | ret masterStuff().devMode(); |
809 | } |
810 | |
811 | // specialize list() for our concepts |
812 | |
813 | <A extends Concept> L<A> nuLike list(Class<A> type, Concepts cc default concepts()) { |
814 | ret main list(cc, type); |
815 | } |
816 | |
817 | <A extends Concept> L<A> list(Concepts concepts, Class<A> type) { |
818 | ret main list(type, concepts); |
819 | } |
820 | |
821 | G22GalleryImage galleryImageForMD5(S md5) { |
822 | ret firstThat(list(concepts, G22GalleryImage), |
823 | img -> cic(fileName(img.path), md5)); |
824 | } |
825 | |
826 | // add the right kind of scrollpane to an image surface |
827 | JComponent wrapImageSurface(ImageSurface is) { |
828 | ret is == null ?: jscroll_centered_borderless(is); |
829 | } |
830 | |
831 | JComponent wrap(O o) { |
832 | var c = main wrap(o); |
833 | if (c cast ImageSurface) |
834 | ret wrapImageSurface(c); |
835 | ret c; |
836 | } |
837 | |
838 | swappable S byUser() { |
839 | ret ""; |
840 | } |
841 | |
842 | Cl<? extends IG22LoadedDB> getLoadedDBs aka openProjects() { |
843 | ret masterStuff().openProjects(); |
844 | } |
845 | |
846 | <A extends Concept> L<A> nuLike listInOpenProjects(Class<A> type) { |
847 | ret concatMap(openProjects(), db -> db.g22utils().list(type)); |
848 | } |
849 | |
850 | transient simplyCached PicturesByMD5 picturesByMD5() { |
851 | ret new PicturesByMD5(projectFile("Images")) |
852 | .extension(".qoi"); |
853 | } |
854 | |
855 | JButton reloadButton(S toolTip, Runnable action) { |
856 | ret jimageButton(#1101440, toolTip, action); |
857 | } |
858 | |
859 | void registerConcept(Concept c) { |
860 | main registerConcept(concepts, c); |
861 | } |
862 | |
863 | void registerConcept(Concepts cc, Concept c) { |
864 | main registerConcept(cc, c); |
865 | } |
866 | |
867 | void addingAdditionalAutoCompletes(LeftArrowScriptAutoCompleter autoCompleter) { |
868 | // projectVar magic |
869 | S token = autoCompleter.prevToken(); |
870 | if (isIdentifier(token) && cic(token, "ProjectVar")) |
871 | autoCompleter.addToSearcher(quoteAll(projectVarNames())); |
872 | |
873 | // project-wide class defs |
874 | autoCompleter.addToSearcher(keys(projectWideClassDefs())); |
875 | } |
876 | |
877 | meta-for Lib as S, File { |
878 | bool addLibrary(Lib library) { |
879 | if (!main addLibrary(library)) false; |
880 | print("Loaded library: " + library); |
881 | masterStuff().newClassesDefined(); |
882 | true; |
883 | } |
884 | } |
885 | |
886 | // add an auto-closing resource to the project |
887 | <A extends AutoCloseable> WrappedCloseable<A> addResource(A resource) { |
888 | if (resource == null) null; |
889 | autoClosingResources.add(resource); |
890 | ret new WrappedCloseable<A>(resource) { |
891 | @Override void beforeClose { |
892 | autoClosingResources.remove(resource); |
893 | } |
894 | }; |
895 | } |
896 | |
897 | // TODO: Improve LAS to not need this anymore |
898 | O callFunctionFromScript(int scriptID, S functionName, O... args) { |
899 | ret callFunctionFromScript((long) scriptID, functionName, args); |
900 | } |
901 | |
902 | // This even returns the version being edited - very aggressive |
903 | O callLatestFunctionFromScript(int scriptID, S functionName, O... args) { |
904 | var function = getScript(scriptID).latestCompileResult().get().getFunction(functionName); |
905 | ret function.callFromOutside(args); |
906 | } |
907 | |
908 | // Uses "saved" version, not "cleared for auto-run" |
909 | O callSavedFunctionFromScript(int scriptID, S functionName, O... args) { |
910 | var function = getScript(scriptID).compileSaved().get().getFunction(functionName); |
911 | ret function.callFromOutside(args); |
912 | } |
913 | |
914 | O callFunctionFromScript(long scriptID, S functionName, O... args) { |
915 | var function = getScript(scriptID).safestCompileResult().get().getFunction(functionName); |
916 | ret function.callFromOutside(args); |
917 | } |
918 | |
919 | O callProjectFunction(S functionName, O... args) { |
920 | var function = projectWideFunctionDefs.get(functionName); |
921 | if (function == null) fail("Function " + functionName + " not found in project " + projectName()); |
922 | ret function.callFromOutside(args); |
923 | } |
924 | |
925 | JComponent visualizeAutoRunnableScript(long scriptID) { |
926 | ret visualizeAutoRunnableScript(getScript(scriptID)); |
927 | } |
928 | |
929 | JComponent visualizeAutoRunnableScript(G22LeftArrowScript script) { |
930 | if (script == null) null; |
931 | |
932 | if (!script.isClearForAutoRun()) |
933 | ret jcenteredlabel("Script not clear for auto-run"); |
934 | |
935 | try { |
936 | O result = script.evaluateAutoRunWithoutTimeout(); |
937 | var objVisualizer = G22JavaObjectVisualizer(this, result).withType(false); |
938 | ret objVisualizer.visualize(); |
939 | } catch print e { |
940 | ret jErrorView(e); |
941 | } |
942 | } |
943 | |
944 | JComponent visualizeSavedScript(long scriptID) { |
945 | ret visualizeSavedScript(getScript(scriptID)); |
946 | } |
947 | |
948 | JComponent visualizeSavedScript(G22LeftArrowScript script) { |
949 | if (script == null) null; |
950 | |
951 | if (!script.isSaved()) |
952 | ret jcenteredlabel("Script not saved"); |
953 | |
954 | try { |
955 | O result = script.evaluateWithoutTimeout(); |
956 | var objVisualizer = G22JavaObjectVisualizer(this, result).withType(false); |
957 | ret objVisualizer.visualize(); |
958 | } catch print e { |
959 | ret jErrorView(e); |
960 | } |
961 | } |
962 | |
963 | // projectName must match base dir in zip |
964 | void importProjectFromZip(File zipFile, S baseDirInZip, S projectName) { |
965 | File dir = dirOfProjectNamed(projectName); |
966 | if (isConceptsDir(dir)) { |
967 | if (eqic(projectName(), "Default")) |
968 | ret with infoMessage("Sorry dude"); |
969 | |
970 | IG22LoadedDB defaultDB = masterStuff().getLoadedDBForConceptDir(dirOfProjectNamed("Default")); |
971 | IG22LoadedDB preloadedDefaultDB = defaultDB; |
972 | if (defaultDB == null) |
973 | defaultDB = openDB("Default"); |
974 | |
975 | project().closeProject(); |
976 | defaultDB.g22utils().importProjectFromZip(zipFile, baseDirInZip, projectName); |
977 | |
978 | // Close default project again if only opened for this purpose |
979 | if (preloadedDefaultDB == null) |
980 | defaultDB.projectActions().closeProject(); |
981 | |
982 | ret; |
983 | } |
984 | |
985 | if (!directoryIsEmpty(dir)) { |
986 | if (confirmProjectReplacements && !swingConfirm("Archive and overwrite existing project " + projectName + "?")) |
987 | ret; |
988 | |
989 | File archiveDir = javaxBackupDir("Gazelle/" + projectName + "-" + computerID() + "-" + ymdMinusHMS()); |
990 | moveFile(dir, archiveDir); |
991 | infoMessage("Archived project to: " + archiveDir); |
992 | } |
993 | |
994 | zip2dir(zipFile, empty(baseDirInZip) ? dir : dir.getParentFile()); |
995 | infoBox("Imported project " + projectName); |
996 | |
997 | masterStuff().openDB(projectName); |
998 | } |
999 | |
1000 | void importProjectFromZip(File zipFile) { |
1001 | S baseDir = baseDirInZip(zipFile); |
1002 | S projectName = takeFirst(baseDir, smartIndexOf(baseDir, '/')); |
1003 | if (empty(projectName)) { |
1004 | ret with inputText("Please enter name for imported project", |
1005 | name -> { |
1006 | if (!validFileName(name)) { |
1007 | infoBox("Invalid name, use simpler characters"); |
1008 | importProjectFromZip(zipFile); |
1009 | ret; |
1010 | } |
1011 | importProjectFromZip(zipFile, "", name); |
1012 | }); |
1013 | } |
1014 | |
1015 | assertValidFileName(projectName); |
1016 | importProjectFromZip(zipFile, baseDir, projectName); |
1017 | } |
1018 | |
1019 | Class export(Class c) { |
1020 | if (c != null) { |
1021 | projectWideClassDefs.put(dropHashFromClassName(shortClassName(c)), c); |
1022 | newFunctionsDefined(); |
1023 | } |
1024 | ret c; |
1025 | } |
1026 | |
1027 | FunctionDef exportFunction aka export(FunctionDef def) { |
1028 | ret def == null ?: exportFunction(def.name, def); |
1029 | } |
1030 | |
1031 | FunctionDef exportFunction aka export(S name, FunctionDef def) { |
1032 | projectWideFunctionDefs.put(name, def); |
1033 | //print("Defined function " + name); |
1034 | |
1035 | // Make sure all compiled scripts are forgotten |
1036 | newFunctionsDefined(); |
1037 | |
1038 | ret def; |
1039 | } |
1040 | |
1041 | // return previous definition |
1042 | FunctionDef unexportFunction aka unexport(S name) { |
1043 | FunctionDef f = projectWideFunctionDefs.remove(name); |
1044 | if (f != null) { |
1045 | print("Undefined function " + name); |
1046 | newFunctionsDefined(); |
1047 | } |
1048 | ret f; |
1049 | } |
1050 | |
1051 | void newFunctionsDefined { |
1052 | masterStuff().newClassesDefined(); |
1053 | recompileDate = tsNow(); |
1054 | } |
1055 | |
1056 | bool shouldRecompile(LASCompileResult cr) { |
1057 | ret recompileDate != null && cr.compilationStart() != null |
1058 | && cr.compilationStart().compareTo(recompileDate) < 0; |
1059 | } |
1060 | |
1061 | bool compileResultValid(LASCompileResult cr, S code) { |
1062 | ret cr != null && eq(cr.script, code) && !shouldRecompile(cr); |
1063 | } |
1064 | |
1065 | toString { |
1066 | ret "G22Utils(" + quote(projectName()) + ")"; |
1067 | } |
1068 | |
1069 | void editScript(G22LeftArrowScript script) { |
1070 | projectActions().editScript(script); |
1071 | } |
1072 | |
1073 | JButton editButton(S toolTip, Runnable action) { |
1074 | ret jimageButtonScaledToWidth(16, #1103068, toolTip, action); |
1075 | } |
1076 | |
1077 | JButton editScriptButton(G22LeftArrowScript script) { |
1078 | ret editButton("Edit script", |
1079 | -> projectActions().editScript(script)); |
1080 | } |
1081 | |
1082 | G22ScriptView savedScriptView(long scriptID) { |
1083 | ret new G22ScriptView(getScript(scriptID)).mustBeAutoRunnable(false); |
1084 | } |
1085 | |
1086 | G22ScriptView scriptView(long scriptID) { |
1087 | ret new G22ScriptView(getScript(scriptID)); |
1088 | } |
1089 | |
1090 | File gazelleJar() { |
1091 | ret getBytecodePathForClass(this); |
1092 | } |
1093 | |
1094 | L<PersistableThrowable> projectErrors() { |
1095 | ret projectActions().projectErrors(); |
1096 | } |
1097 | |
1098 | JComponent jErrorView(Throwable e) { |
1099 | var view = main jErrorView(e); |
1100 | var scriptErrors = instancesOf(GazelleV_LeftArrowScript.ScriptError.class, allCausesIncludingSelf(e)); |
1101 | var sources = mapNotNulls(scriptErrors, -> .tokenRangeWithSrc()); |
1102 | if (empty(sources)) ret view; |
1103 | sources = uniquifySources(sources); |
1104 | ret centerAndEastWithMargin(view, |
1105 | jline(map(sources, src -> |
1106 | jThreadedButton( |
1107 | str_shorten(src, 40), |
1108 | -> projectActions().goToSource(src))))); |
1109 | } |
1110 | |
1111 | L<TokenRangeWithSrc> uniquifySources(L<TokenRangeWithSrc> sources) { |
1112 | ret uniquifyWith(sources, src -> pair(src.sourceInfo, src.renderRange())); |
1113 | } |
1114 | |
1115 | structure_Data makeStructureData() { |
1116 | ret concepts().makeStructureData(); |
1117 | } |
1118 | |
1119 | S g22struct(O o) { |
1120 | ret struct(o, makeStructureData()); |
1121 | } |
1122 | |
1123 | O g22unstruct(S struct) { |
1124 | ret unstructure(struct, classFinder()); |
1125 | } |
1126 | |
1127 | O stem() { |
1128 | ret dm_stem(module()); |
1129 | } |
1130 | |
1131 | void reloadProject { |
1132 | masterStuff().reopenDB(getLoadedDB()); |
1133 | } |
1134 | |
1135 | File downloadProjectFromGazAI(GazAICredentials credentials, S projectName) ctex { |
1136 | var cred = credentials.asParams(); |
1137 | var params = cloneMap(cred); |
1138 | params.put("asZip", 1); |
1139 | |
1140 | var url = "https://" + gazAIHost() + "/dl-authed/gazelle/" + spaceToPercent20(projectName) + "/"; |
1141 | var conn = urlConnection(url); |
1142 | |
1143 | var file = javaxBackupDir(concat(projectName + " Downloaded ", ymdMinusHMS(), ".zip")); |
1144 | doPostBinaryToFile(makePostData(params), conn, file); |
1145 | |
1146 | if (!isZip(file)) |
1147 | fail("Download failed, not authenticated for " + gazAIHost() + "?"); |
1148 | |
1149 | fileSavedInfoBox(file); |
1150 | ret file; |
1151 | } |
1152 | |
1153 | public void waitForAutoStart() { |
1154 | autoStarter().waitUntilDone(); |
1155 | } |
1156 | |
1157 | void adaptTextEditor(JSyntaxTextFileEditor editor) { |
1158 | editor.adaptSyntaxTextArea = textArea -> |
1159 | g22_adaptSyntaxTextAreaForHashRefs(textArea, this); |
1160 | } |
1161 | |
1162 | Window projectWindow() { |
1163 | ret (Window) call(stem(), "window"); |
1164 | } |
1165 | } // 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/393 |
Text MD5: | 974c4d889c207f200442450b507d81c2 |
Author: | stefan |
Category: | javax / gazelle 22 |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2024-08-27 15:04:39 |
Source code size: | 34895 bytes / 1165 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 1094 / 3582 |
Version history: | 392 change(s) |
Referenced in: | [show references] |