!7 sS background = #1009931; sS mainIconID = #1101272; static double minLoadScreenShowingTime = 4.0; static JDesktopPane desktop; static ReliableSingleThread rst = new(f updateModules); static volatile long updateCycles; static int systemErrorsToKeep = 10; static L systemErrors = synchroList(new CircularArrayList); static new Flag stopRequested; static SimpleLiveValue systemStatus = stringLiveValue("loading"); static Map ghostModules = weakHashMap(); p { _handleException_addHandler(voidfunc(Throwable e) { addToListWithMaxSize(systemErrors, e, systemErrorsToKeep); infoBox("Error: " + exceptionToStringShort(e)); LastErrors lastErrors = first(staticModulesOfType(LastErrors)); if (lastErrors != null) lastErrors.addError(e); }); if (swic(activateFramesOf(programID()), "OK")) cleanKill(); framesBot(); //substance(); stefansOS_loadingAnimation_fullScreen = startInFullScreen(); final Component loadingAnim = stefansOS_loadingAnimation(r { stopRequested.raise() }); try { long start = sysNow(); useDBOf(#1015871); db(); background = or2(trim(loadTextFile(javaxDataDir("os-background.txt"))), background); desktop = jDesktopPaneWithSkyPicture_autoUnload(background, Color.black); autoFixDesktopPane(desktop); waitUntilSysTime(start+toMS(minLoadScreenShowingTime)); } catch e { _handleException(e); stopRequested.raise(); } try { bool flag = stopRequested.isUp(); // get before closing animation if (flag) ret with showFrame("Stop screen", centerAndSouthWithMargins( jcenteredlabel("Troubleshooting options will go here."), jcenteredbuttons( "Start Stefan's OS normally", r restart, "Delete session", disableButtonWhileCalcing(func -> bool { if (!fileExists(conceptsFile())) ret false with infoBox("Session already empty."); if (!confirmOKCancel("Really delete your current session?")) false; renameFileToSomeBackupName(conceptsFile()); infoBox("Session deleted. Starting again."); disableAllButtonsInWindow(heldInstance(JButton)); sleepSeconds(3); restart(); false; })))); autoRestart(); substance(); showDesktop(); } finally { disposeWindow(loadingAnim); } initAfterDBLoad(); hideConsole(); } sbool startInFullScreen() { ret eq("1", trim(loadTextFile(javaxDataDir("start-os-in-full-screen.txt")))); } sbool showDesktop_first = true; svoid showDesktop { if (showDesktop_first && startInFullScreen()) showFullScreen(desktop); else { showMaximizedFrame(desktop); titlePopupMenu_top(desktop, voidfunc(JPopupMenu menu) { addMenuItems(menu, "Update One Cycle", rst, "New Session", rThreadPcallMessageBox(r deleteAllModules), "Restore Initial Modules", r initialModules, ); }); } doNothingOnClose(getFrame(desktop)); frameIcon(mainIconID, desktop); showDesktop_first = false; cleanExitOnFrameClose_ifStillInSameFrame(desktop); } svoid initAfterDBLoad { doEvery(30000, r swing_clearLightWeightPopupCache); initialModules(); UpdateCycles uc = conceptWhere(UpdateCycles); if (uc != null) updateCycles = uc.value; for (Module m : onModules()) startModule(m); addConceptIndex(simpleConceptIndex(rst)); rst.trigger(); systemStatus.set("running"); } svoid initialModules { if (empty(onModules())) showModule(new DynamicModule(#1016067, 'main$WelcomeScreen)); makeOrShowStaticModuleOfType(ModuleClasses); } svoid triggerUpdate { rst.trigger(); } svoid updateModules { ++updateCycles; for (Module m : onModules()) updateModule(m); } svoid updateModule(Module m) { if (m == null) ret; temp m.enter(); pcall { m.update(); } } svoid cleanMeUp { systemStatus.set("shutting down"); for (Module m) if (m.vis != null) pcall { m.unvisualize(); } for (Module m) cleanUp(m); } static L onModules() { ret conceptsWhere(Module, on := true); } sbool hasModuleWithFields(Class c, O... params) { ret hasConcept(c, concatArrays(new O[] {on := true}, params)); } svoid startModule(Module m) { ping(); pcall { //addIfNotThere(modules, m); lock m.lock; if (m.started) ret; m.started = true; print("Starting module " + m); try { m.start(); } catch e { m.setError(e); _handleException(e); } rst.trigger(); if (m.visible) showModule(m); }} static Module showModule(final Module m) { if (m == null) ret m; startModule(m); lock m.lock; if (m.vis != null) { if (!isLoading()) activateInternalFrame(m.vis); ret m; } cset(m, visible := true); visualizeModule(m); if (m.vis != null) swing { Rect r = m.frameRect; if (r == null) r = randomRect(desktop.getWidth(), desktop.getHeight(), 10, 150, 100); if (r == null) r = Rect(10, 10, 200, 100); print("Showing frame at " + r); S frameTitle = m.moduleName(); final JInternalFrame f; { temp tempSetThreadLocal(addInternalFrame_dontSelect, isLoading()); f = showInternalFrame(desktop, frameTitle, r.x, r.y, r.w, r.h, m.vis); } f.setDefaultCloseOperation(JInternalFrame.DO_NOTHING_ON_CLOSE); final WeakReference fRef = new(f); final WeakReference mRef = new(m); internalFrameTitlePopupMenuItem(f, "Module source", r-thread { pcall { S src = mRef->sourceCode(); if (src != null) showText(internalFrameTitle(fRef!) + " [Source]", src); else infoBox("No source code found"); }}); onInternalFrameIconified(f, r { hideModule(m) }); onInternalFrameClosing(f, r { deleteModule(m) }); internalFrameIcon(f, m.iconID); m.enhanceFrame(f); } ret m; } svoid showModules(L l) { for (Module m : unnull(l)) showModule(m); } sbool deleteModule(Module m) { pcall { bool warn = isTrue(callOpt(resolveModule(m), 'warnOnDelete)); if (warn && !confirmOKCancel("Really delete module " + m + "?")) false; } O m2 = unwrapDynamicModule(m); ghostModules.put(m2.getClass(), nu(GhostModule, name := m.moduleName(), created := m.created, deleted := now(), instance := new WeakReference(m2)); pcall { m.unvisualize(); } removeConcept(m); triggerUpdate(); true; } svoid visualizeModule(Module m) { pcall { if (m.vis == null) m.vis = m.visualize(); if (m.vis == null) m.vis = defaultVisualize(m); } } svoid hideModule(final Module m) { if (m == null) ret; lock m.lock; cset(m, visible := false); pcall { m.unvisualize(); } } svoid revisualizeModule(Module m) { pcall { if (m == null) ret; lock m.lock; JInternalFrame frame = getInternalFrame(m.vis); if (frame == null) ret; m.unvisualize1b(); m.unvisualize2(); visualizeModule(m); setInternalFrameContents(frame, m.vis); } } abstract concept Module { transient JComponent vis; transient bool started; transient Lock lock = lock(); bool on = true, visible; Rect frameRect; S iconID; PersistableThrowable error; //transient Set timers; JComponent visualize() { null; } void unvisualize() { unvisualize1(); unvisualize2(); } void enhanceFrame(JInternalFrame frame) {} void start() {} void unvisualize1() { disposeInternalFrame(getInternalFrame(vis)); unvisualize1b(); } void unvisualize1b() { grabFrameRect(); vis = null; } void unvisualize2() {} void update() {} void grabFrameRect() { JInternalFrame f = getInternalFrame(vis); if (f != null) cset(this, frameRect := toRect(getBounds(f))); } void cleanMeUp_started() { started = false; } void delete() { unvisualize(); cleanUp(this); super.delete(); } S sourceCode() { ret javaxSourceOfMyClass1(shortClassName(this)); } // for all modules void triggerUpdate { rst.trigger(); } void setModuleIcon(S iconID) { if (eq(iconID, this.iconID)) ret; this.iconID = iconID; internalFrameIcon(vis, iconID); } O resolve() { ret this; } O getError() { ret error; } S moduleID() { ret str(id); } void setError(Throwable e) { cset(this, error := persistableThrowable(e)); } AutoCloseable enter() { null; } JComponent vis() { ret vis; } static bool needsParameters() { false; } S moduleName() { ret humanizeFormLabel(shortClassName(this)); } } // END CONCEPT MODULE static JComponent defaultVisualize(Module m) { ret jCenteredMultiLineLabel(renderConcept(m)); } static A findModule(Class c) { ret findConcept(c, on := true); } // returns module ID static S findDynModuleOfType(S type) { DynamicModule m = findConcept(DynamicModule, on := true, _className := "main$" + type); ret m == null ? null : m.moduleID(); } sbool moduleTypeIs(Module m, S type) { if (m == null) false; ret eq(moduleResolvedClassName(m), "main$" + type); } sS moduleResolvedClassName(Module m) { if (m == null) null; if (m instanceof DynamicModule) ret m/DynamicModule._className; ret className(m); } // returns module ID sS findClosestModuleTo(O searcher, S type) { JInternalFrame f = getInternalFrame(dm_getVisualization(searcher)); if (f == null) null; Pt p = centerOfRect(toRect(getBounds(f))); new Lowest best; for (Module m : onModules()) { JInternalFrame f2 = getInternalFrame(m.vis); if (f2 == null || f2 == f) continue; if (type != null && !moduleTypeIs(m, type)) continue; Rect r2 = toRect(getBounds(f2)); best.put(m.moduleID(), rectPointDistance(r2, p)); } ret best!; } static L staticModulesOfType(Class type) { ret conceptsWhere(type, on := true); } static L staticModulesOfExactType(Class type) { ret filterByExactType(type, staticModulesOfType(type)); } static L listModules() { ret map unwrapDynamicModule(onModules()); } static L visibleModules() { ret map unwrapDynamicModule(objectsWhere(onModules(), visible := true)); } static O unwrapDynamicModule(Module m) { ret m instanceof DynamicModule ? or(m/DynamicModule.o, m) : m; } sbool moduleStillThere(O o) { Module m = o instanceof Module ? o/Module : (Module) get(o, '_host); ret isConceptRegistered(mainConcepts, m); } static O getDynModuleByID(S moduleID) { if (moduleID == null) null; ret resolveModule(getConcept(Module, parseLong(moduleID))); } static Module getModuleByID(S moduleID) { if (moduleID == null) null; ret getConcept(Module, parseLong(moduleID)); } sS getInterestingString { InterestingString m = findModule(InterestingString); ret m == null ? null : m.theString; } sS modulesSessionGrab() { grabFrameRects(); ret struct(ll(programID(), localDateWithMilliseconds())) + "\n" + mainConcepts.xfullgrab(); } svoid autoSaveModulesSession() { infoBox("Auto-saving session."); S grab; logQuoted(javaxBackupDir(fsI(programID()) + "/auto-saved-sessions.txt"), grab = modulesSessionGrab()); infoBox("Auto-save done (" + l(grab) + " chars)"); } svoid deleteAllModules() { autoSaveModulesSession(); deleteConcepts(Module); initialModules(); } svoid restoreModulesSession(S text) { autoSaveModulesSession(); systemStatus.set("shutting down"); infoBox("Releasing session"); cleanMeUp(); cleanUp(mainConcepts); mainConcepts = null; //sleepSeconds(1); infoBox("Loading session"); systemStatus.set("loading"); mainConcepts = new Concepts().load(dropFirstLine(text)); initAfterDBLoad(); infoBox("Session restore done"); } svoid grabFrameRects { for (Module m : onModules()) m.grabFrameRect(); } sclass DynamicModule extends Module { S moduleID, _className; // "className" is taken by DynamicObject; _className == null for old-style dyn module S oStruct; // serialized dynamic object transient Class c; transient O o; *() {} *(S *moduleID, S *_className) {} *(S *moduleID, S *_className, Class *c) {} static bool needsParameters() { true; } AutoCloseable enter() { ret castForTemp(callOpt(o, 'enter)); } JComponent visualize() { temp enter(); ret (JComponent) callOpt(o, 'visualize); } void enhanceFrame(final JInternalFrame f) { internalFrameTitlePopupMenuItem(f, "Reload", rThread(r reload)); { temp enter(); pcallOpt(o, 'enhanceFrame, f); } internalFrameTitle(f, moduleName()); } S moduleName() { S name = (S) callOpt(o, 'moduleName); if (nempty(name)) ret name; ret dropSuffixICTrimOneOf(snippetTitle_cached(moduleID), "[Dyn Module]", "[Dyn Module, OK]"); } void start() { if (moduleID == null) ret; if (c == null) c = hotwireModule(moduleID); if (oStruct != null) pcall { o = unstructureInRealm(oStruct, c); } if (o == null) if (_className == null) o = c; else o = nu(_getClass(c, _className)); setOptAll(o, _host := this, lock := lock); if (o instanceof Class) callMain(o); else callOpt(o, 'start); } void unvisualize2() { callOpt(o, 'unvisualize); } void update() { callOpt(o, 'update); } void cleanMeUp() { oStruct = null; pcall { if (o != null && !o instanceof Class) oStruct = struct(o); } cleanUpObjectAndItsMainClass(o); o = null; c = null; } void reload() { JInternalFrame frame = getInternalFrame(vis); unvisualize1b(); unvisualize2(); cleanUp(this); // also sets started to false if (frame != null) setInternalFrameContents(frame, jcenteredlabel("Reloading...")); visible = false; startModule(this); if (frame != null) { cset(this, visible := true); visualizeModule(this); //print("New content: " + vis); setInternalFrameContents(frame, vis); } rst.trigger(); } S sourceCode() { ret loadSnippet(moduleID); } O resolve() { ret o; } O getError() { if (o != null) { O error = callOpt(o, 'getError); if (error != null) ret error; } ret super.getError(); } toString { ret "DynModule " + moduleID + "/" + className; } void setError(Throwable e) { if (o != null && isTrue(callOpt(o, 'setError, e))) ret; super.setError(e); } } /*static L resolvedModules() { new L l; for (Module m : onModules()) l.add(m.resolve()); ret l; }*/ static S moduleID(Module m) { ret m == null ? null : m.moduleID(); } static O resolveModule(Module m) { ret m == null ? null : m.resolve(); } static S makeModule(Class moduleClass) { ret makeModule(shortClassName(moduleClass)); } static S makeModule(S moduleLibID) { ret makeOrShowModule(moduleLibID, false); } static S makeOrShowModule(S moduleLibID) { ret makeOrShowModule(moduleLibID, true); } static S makeOrShowModule(S moduleLibID, bool orShow) { // makes dynamic & static modules if (isIdentifier(moduleLibID)) ret moduleID(makeOrShowStaticModuleOfType(moduleLibID), orShow); L l = splitAtSlash(moduleLibID); if (!isSnippetID(first(l))) fail("Unknown module lib ID: " + moduleLibID); S snippetID = first(l), className = second(l); className = className == null ? null : "main$" + className; DynamicModule m = findConcept(DynamicModule, on := true, moduleID := snippetID, _className := className); if (m == null) { Class c = hotwireModule(snippetID); m = DynamicModule(snippetID, className, c); } if (orShow) showModule(m); else startModule(m); ret moduleID(m); } static Module makeOrShowStaticModuleOfType(S s) { ret makeOrShowStaticModuleOfType(s, true); } static Module makeOrShowStaticModuleOfType(S s, bool orShow) { ret makeOrShowStaticModuleOfType(classForName("main$" + s), orShow); } static Module makeOrShowStaticModuleOfType(Class c) { ret makeOrShowStaticModuleOfType(c, true); } static Module makeOrShowStaticModuleOfType(Class c, bool orShow) { final L l = staticModulesOfExactType(c); Module m = empty(l) ? nu(c) : first(l); if (orShow) showModule(m); else startModule(m); ret m; } !include once #1016217 // Sticky Libs static Class hotwireModule(S snippetID) { hotwire_autoStickyLibs(); ret hotwire(snippetID); // give each their own local_log } sbool isLoading() { ret eq(systemStatus!, "loading"); } !include once #1015842 // SavedSessions !include once #1015885 // Standard Modules !include once #1015959 // More Standard Modules please include function renderConcept. please include function restart.