sclass G22Utils { settable BackgroundProcessesUI backgroundProcessesUI; settable Enterable module; settable G22MasterStuff masterStuff; gettable CombinedStringifier stringifier = new( o -> o cast BufferedImage ? "Image (" + o.getWidth() + "*" + o.getHeight() + " px)" : null ); ImageSurface stdImageSurface() { var is = pixelatedImageSurface().setAutoZoomToDisplay(true).repaintInThread(false); is.specialPurposed = true; new ImageSurface_PositionToolTip(is); ret is; } ImageSurface stdImageSurface(BufferedImage etc img) { var is = stdImageSurface(); is.setImage(img); ret is; } S stringify(O o) { ret stringifier.toString(o); } swappable void modifyLeftArrowParser(GazelleV_LeftArrowScriptParser parser) {} GazelleV_LeftArrowScriptParser leftArrowParser() { new GazelleV_LeftArrowScriptParser parser; parser.g22utils(this); modifyLeftArrowParser(parser); ret parser; } void basicParserTest() { var parser = leftArrowParser(); print(classContainerPrefixes := parser.classContainerPrefixes()); assertEquals(pair(1, 2), parser.parse("new Pair 1 2")!); } ifclass JLeftArrowScriptIDE JLeftArrowScriptIDE leftArrowIDE() { new JLeftArrowScriptIDE ide; ide.g22utils(this); ide.modifyParser = modifyLeftArrowParser; ret ide; } endif File byteCodePath() { ret assertNotNull(getBytecodePathForClass(this)); } simplyCached ClassNameResolver classNameResolver() { ret new ClassNameResolver().byteCodePath(byteCodePath()).init(); } File databasesMotherDir() { ret javaxDataDir("Gazelle-22"); } AutoCloseable enter() { ret module?.enter(); } S defaultDBName() { ret "Default"; } File lastOpenedDBFile() { ret newFile(databasesMotherDir(), "Last-Opened")); } S dbToOpen() { S name = loadTextFile(lastOpenedDBFile()); if (nempty(name) && fileExists(newFile(databasesMotherDir(), name))) ret name; ret defaultDBName()); } void openedDB(File dbDir) { if (sameFile(databasesMotherDir(), dirOfFile(dbDir))) saveTextFile(lastOpenedDBFile(), fileName(dbDir)); } }