!7 sS background = #1009931; static JDesktopPane desktop; static ReliableSingleThread rst = new(f updateModules); static volatile long updateCycles; static int systemErrorsToKeep = 10; static L systemErrors = synchroList(new CircularArrayList); p-subst { _handleException_addHandler(voidfunc(Throwable e) { addToListWithMaxSize(systemErrors, e, systemErrorsToKeep); infoBox("Error: " + exceptionToStringShort(e)); LastErrors lastErrors = first(staticModulesOfType(LastErrors)); if (lastErrors != null) lastErrors.addError(e); }); autoRestart(); db(); desktop = jDesktopPaneWithSkyPicture_autoUnload(background, Color.black); autoFixDesktopPane(desktop); cleanExitOnFrameClose(frameIcon(#1101272, showMaximizedFrame(desktop))); titlePopupMenu_top(desktop, voidfunc(JPopupMenu menu) { addMenuItems(menu, "Update One Cycle", rst, "New Session", rThreadPcallMessageBox(r deleteAllModules), ); }); initAfterDBLoad(); } svoid initAfterDBLoad { initialModules(); UpdateCycles uc = conceptWhere(UpdateCycles); if (uc != null) updateCycles = uc.value; for (Module m : onModules()) startModule(m); addConceptIndex(simpleConceptIndex(rst)); rst.trigger(); } svoid initialModules { if (!hasConcept(ModuleClasses)) showModule(uniq(ModuleClasses)); } svoid triggerUpdate { rst.trigger(); } svoid updateModules { ++updateCycles; for (Module m : onModules()) pcall { m.update(); } } svoid cleanMeUp { 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) { 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); }} svoid showModule(final Module m) { if (m == null) ret; startModule(m); lock m.lock; if (m.vis != null) { activateInternalFrame(m.vis); ret; } 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 = humanizeFormLabel(shortClassName(m)); final JInternalFrame f = showInternalFrame(desktop, frameTitle, r.x, r.y, r.w, r.h, m.vis); internalFrameTitlePopupMenuItem(f, "Module source", r-thread { pcall { S src = m.sourceCode(); if (src != null) showText(internalFrameTitle(f) + " [Source]", src); else infoBox("No source code found"); }}); onInternalFrameIconified(f, r { hideModule(m) }); onInternalFrameClosing(f, r { deleteModule(m) /* really? */ }); internalFrameIcon(f, m.iconID); m.enhanceFrame(f); } } svoid showModules(L l) { for (Module m : unnull(l)) showModule(m); } svoid deleteModule(Module m) { removeConcept(m); triggerUpdate(); } 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); m.unvisualize1b(); m.unvisualize2(); visualizeModule(m); setInternalFrameContents(frame, m.vis); } } abstract concept Module { transient Component vis; transient bool started; transient Lock lock = lock(); bool on = true, visible; Rect frameRect; S iconID; PersistableThrowable error; 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)); } } // 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(); } static L staticModulesOfType(Class type) { ret conceptsWhere(type, on := true); } static L listModules() { ret map unwrapDynamicModule(onModules()); } 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; DynamicModule m = cast getConcept(parseLong(moduleID)); ret m == null ? null : m.o; } 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(); infoBox("Releasing session"); cleanMeUp(); cleanUp(mainConcepts); mainConcepts = null; //sleepSeconds(1); infoBox("Loading session"); 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) {} 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)); S title = internalFrameTitle(f); { temp enter(); pcallOpt(o, 'enhanceFrame, f); } if (eq(internalFrameTitle(f), title)) // not changed by dynamic module thread { internalFrameTitle(f, dropSuffixICTrimOneOf(snippetTitle(moduleID), "[Dyn Module]", "[Dyn Module, OK]")); } } void start() { if (moduleID == null) ret; if (c == null) c = hotwireDependent(moduleID); if (oStruct != null) pcall { o = unstructureInRealm(oStruct, c); } if (o == null) if (_className == null) o = c; else o = nu(_getClass(c, _className)); setOpt(o, _host := this); if (o instanceof Class) callMain(o); else callOpt(o, 'start); } void unvisualize2() { callOpt(o, 'unvisualize2); } void update() { callOpt(o, 'update); } void cleanMeUp() { oStruct = null; pcall { if (o != null && !o instanceof Class) oStruct = struct(o); } cleanUp(o); if (!o instanceof Class) cleanUp(_getClass(o, "main")); 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 or(o, this); } 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; } !include once #1015842 // SavedSessions !include once #1015885 // Standard Modules !include once #1015959 // More Standard Modules