Download Jar. Uses 1177K of libraries. Click here for Pure Java version (43793L/303K).
1 | !7 |
2 | |
3 | set flag print_rst. // speed up printing a lot |
4 | |
5 | set flag jCheckBoxMenuItem_dyn_debug. |
6 | |
7 | set flag InOSCore. |
8 | set flag NotifyingPrintLog. |
9 | |
10 | sS defaultBackground = #1101488; //#1101303; //#1101465; //#1101438; //#1101355; // #1009931; |
11 | sS background = defaultBackground; |
12 | sS mainIconID = #1102666, moduleDefaultIconID = #1101337; |
13 | sS laf; |
14 | static double minLoadScreenShowingTime = 2; |
15 | sbool loadBackgroundLater = true; |
16 | static double backgroundLoadDelay = 2.0; |
17 | sbool showLoadingScreen = false; |
18 | static JDesktopPane desktop; |
19 | sbool useCodeSharing = true; // share code between identical modules |
20 | |
21 | static int autoSaveInterval = -10000; // 10 seconds plus slowdown logic |
22 | static int persistenceDelayPerModule = 10000; // 10 seconds |
23 | |
24 | static int systemErrorsToKeep = 10; |
25 | |
26 | // OUTDATED |
27 | static ReliableSingleThread rstUpdateModules = new(r { systemQ.add(r updateModules) }); |
28 | sS lastTopInput; |
29 | static ReliableSingleThread rstTopInputChanged = rstWithDelay(250, r { |
30 | S s = getText(tfTopInput); |
31 | if (neq(lastTopInput, s)) |
32 | vmBus_send('topInputChanged, lastTopInput = s); |
33 | }); |
34 | |
35 | static volatile long updateCycles; |
36 | static L systemErrors = synchroList(); |
37 | static int systemErrors_pointer; |
38 | static new Flag stopRequested; |
39 | static SimpleLiveValue<S> systemStatus = stringLiveValue("loading"); |
40 | static bool firstModuleShown; |
41 | static Map<O, GhostModule> ghostModules = weakHashMap(); // key is main class (if dynamic module) or instance (if static module) |
42 | static Q systemQ; |
43 | static AccessControlContext globalACC; |
44 | static volatile Module activeModule; |
45 | static JTextField tfTopInput; // the input field in the OS menu bar |
46 | static long tfTopInput_dontSelectAll; // sysNow timestamp |
47 | static StefansOS_ConnectToServer connector; |
48 | static Map generalMap = synchroMap(); |
49 | static L<Component> trayAreaComponents = synchroList(); |
50 | sbool printOnPersistContents, verboseCleanUp; |
51 | static JMenuBar menuBar; |
52 | sbool katze_send = true, katze_sendTyped; |
53 | sO makeReloadingComponent; // F1<Module, Component> |
54 | static long startTime; |
55 | static NotTooOften backgroundGCFrequency = everyTenMinutes(); |
56 | static Set<S> hideFeatures; |
57 | static LS standardModules; |
58 | sS botName = "Stefan's OS."; |
59 | sS osName; |
60 | sbool showTopInput = true; |
61 | static Runnable shutdownConsole; // instead of showConsole() |
62 | sbool verboseModuleDeletes, cacheTranspilationsDuringBoot = true; |
63 | sO confirmOSExit; // func -> bool or null |
64 | sO gc_subcondition; // disable GC by module; func -> bool or null |
65 | sbool showTimeInPrintLog = true; |
66 | static JCheckBoxMenuItem miEnableQuickSearches; |
67 | sbool debugFrameSizes; |
68 | |
69 | // if you want other initial modules |
70 | sO initialModules_override; // VF1<OS reference> |
71 | |
72 | static Runnable restarter_override; |
73 | static O onStart; |
74 | |
75 | static S[] mainArgs; |
76 | |
77 | static Set<S> disabledModuleIDs; |
78 | static Set<DynamicModule> modulesBeingReloaded = syncSet(); |
79 | |
80 | p { |
81 | startTime = sysNow(); |
82 | |
83 | // Just load all my classes so we are not dependent on jar or |
84 | // classes files on disk. |
85 | time "loadAllClasses" { |
86 | loadAllClasses(); |
87 | } |
88 | |
89 | mainArgs = args; |
90 | vm_generalMap_put(stefansOS := mc()); |
91 | callF(onStart, mc()); |
92 | |
93 | //set getServerTranspiled_printStackTrace; |
94 | |
95 | print(headless() ? "We are headless." : "Starting GUI."); |
96 | |
97 | if (!headless()) showControls(jbutton("TROUBLESHOOTING", r { stopRequested.raise() })); |
98 | noRegularGC(); // not while we're loading |
99 | |
100 | /*if (onLocallyInferiorJavaX()) { |
101 | print("Restarting to use standard JavaX"); |
102 | restart(); |
103 | }*/ |
104 | |
105 | checkMaxWindowBoundsBug(); |
106 | |
107 | if (!eq("0", trim(loadTextFile(javaxDataDir("compile-on-server"))))) |
108 | set hotwire_compileOnServer; |
109 | |
110 | /*if (isLinux() && isRoot()) |
111 | addToDefaultVMArgs("-XX:ThreadPriorityPolicy");*/ |
112 | |
113 | /*if (java10OrHigher()) { |
114 | addStandardAddOpensFlags(); |
115 | addPermitIllegalAccessesFlag(); |
116 | // needed for URLClassLoader and Swing stuff |
117 | if (!hasStandardAddOpensFlagsInCurrentVM()) { |
118 | print("RESTARTING with proper JDK 11+ arguments"); |
119 | restart(); |
120 | } |
121 | }*/ |
122 | |
123 | if (java8OrHigher() && !containsOneOf(defaultVMArgs(), "+UseZGC", "+ShenandoahGC")) |
124 | addToDefaultVMArgs(smallHeapArgs()); |
125 | |
126 | //laf = 'webLAF; // Let's not generally use it, is sluggish on my machine |
127 | //laf = 'nimbus; |
128 | laf = 'platform; |
129 | |
130 | //if (isMac()) laf = 'platform; // because https://github.com/michael-hagen/JTattoo/issues/1 |
131 | if (isMac()) vmGeneralMap_set('iconifyBroken, true); |
132 | if (isLinux()) laf = 'jtattoo; |
133 | |
134 | /*if (vmArgs().contains("-XX:+PrintAssembly")) pcall { |
135 | teeSystemOutAndErrToFile(programFile("os.log")); |
136 | }*/ |
137 | |
138 | if (!hasClass("x30_pkg.x30_util")) { |
139 | if (!zipFileContains_falseOnError(pathToJavaxJar(), "x30_pkg/x30_util.class")) |
140 | upgradeJavaXAndRestart(); |
141 | else |
142 | restart(); |
143 | } |
144 | |
145 | _handleException_addHandler(voidfunc(Throwable e) { |
146 | try { |
147 | synchronized(systemErrors) { |
148 | listSet(systemErrors, systemErrors_pointer, e); |
149 | systemErrors_pointer = (systemErrors_pointer+1) % systemErrorsToKeep; |
150 | } |
151 | } catch e2 { |
152 | printStackTrace(e2); |
153 | } |
154 | infoBox("Error: " + exceptionToStringShort(e)); |
155 | LastErrors lastErrors = first(staticModulesOfType(LastErrors)); |
156 | if (lastErrors != null) lastErrors.addError(e); |
157 | }); |
158 | |
159 | timeJumpDetector(); |
160 | |
161 | vm_generalMap_put('consoleInUse, true); // bots made by modules should not handle console |
162 | |
163 | monitorThreadAllocatedMemory(); |
164 | |
165 | // Solve deadlocks every 10 to be sure |
166 | doEvery(10000, r printDeadlocksAndSolve); |
167 | |
168 | print("Data dir: " + javaxDataDir()); |
169 | vm_setGlobalACC(globalACC = acc_current()); |
170 | |
171 | // TODO: FIX, not working |
172 | if (swic(activateFramesOf(programIDPlusHome()), "OK")) { |
173 | print("OS already running!"); |
174 | cleanKill(); |
175 | } |
176 | |
177 | framesBot(); |
178 | if (nempty(botName)) makeBot(botName); |
179 | |
180 | S printLogSize = trim(loadTextFile(javaxDataDir("os-print-log-size.txt"))); |
181 | if (isInteger(printLogSize)) printLogMaxChars(parseInt(printLogSize)); |
182 | |
183 | please include function allAWTComponents. |
184 | |
185 | vm_generalMap_put('newSwingComponentRegistry, voidfunc(Component c) { |
186 | allAWTComponents_extraList.add(c) |
187 | }); |
188 | |
189 | connector = new StefansOS_ConnectToServer; |
190 | connector.start(); |
191 | |
192 | // in case we sub to it later |
193 | connector.onLine = voidfunc(S line) { |
194 | new Matches m; |
195 | if (startsWith(line, "snippetUpdates:", m)) { |
196 | S msg = m.rest(); |
197 | printWithIndent("<< ", msg); |
198 | logQuoted(programLogFile(#1019239), msg); // using this file for hysterical reasons |
199 | vmBus_send snippetUpdate(safeUnstruct(msg)); |
200 | } |
201 | }; |
202 | |
203 | //substance(); |
204 | final SimpleLiveValue<S> lvDetails = stringLiveValue(); |
205 | lvDetails.onChange(r { print(lvDetails!) }); |
206 | stefansOS_loadingAnimation_fullScreen = startInFullScreen() && !isWindows() /* bug */; |
207 | final Component loadingAnim = showLoadingScreen ? stefansOS_loadingAnimation(r { |
208 | stopRequested.raise() |
209 | }, lvDetails) : null; |
210 | |
211 | try { |
212 | long start = sysNow(); |
213 | systemQ = startQ("System Q"); |
214 | useDBOf(#1015871); |
215 | lvDetails.set("Loading database"); |
216 | db(autoSaveInterval); |
217 | db_mainConcepts().quietSave = true; |
218 | if (!headless()) { |
219 | // if you use Processing |
220 | JPopupMenu.setDefaultLightWeightPopupEnabled(false); |
221 | |
222 | lvDetails.set("Loading background"); |
223 | background = or2(trim(loadTextFile(javaxDataDir("os-background.txt"))), background); |
224 | if (!isSnippetID(background)) |
225 | background = fileToURI(new File(background)); |
226 | try { |
227 | if (eq(settings().backgroundMode, "fit")) |
228 | desktop = loadBackgroundLater |
229 | ? jDesktopPaneWithFitPicture_smooth_cacheScaled_loadLater(background, delay := backgroundLoadDelay) |
230 | : jDesktopPaneWithFitPicture_smooth_cacheScaled(background); |
231 | else if (eq(settings().backgroundMode, "center")) |
232 | desktop = setBackground(settings().backgroundColor, |
233 | jDesktopPaneWithCenteredPicture(background)); |
234 | else |
235 | desktop = jDesktopPaneWithSkyPicture/*_autoUnload*/(background, settings().backgroundColor); |
236 | } catch print e { |
237 | try { |
238 | desktop = jDesktopPaneWithFitPicture_smooth(defaultBackground); |
239 | } catch print e2 { |
240 | desktop = jDesktopPane(); |
241 | } |
242 | } |
243 | setMainDesktopPane(desktop); |
244 | autoFixDesktopPane(desktop); |
245 | |
246 | // Allow frame switching from AI bar & similar components |
247 | installInternalFrameSwitcher_v3(desktop).shouldSwitch = |
248 | func -> bool { sameComponentOrDeepChildOf(getFocusOwner(), menuBar) }; |
249 | } |
250 | |
251 | long ms = consoleShowing() ? toMS(minLoadScreenShowingTime) : 0; |
252 | long remaining = start+ms-sysNow(); |
253 | if (remaining <= 0) |
254 | lvDetails.set("Done loading"); |
255 | else { |
256 | S seconds = formatDouble(toSeconds(remaining), 1); |
257 | lvDetails.set("Done loading, but will wait if you hit the troubleshooting button for " + seconds + " more second" + (eq(seconds, "1") ? "" : "s")); |
258 | } |
259 | //if (loadingAnim != null) |
260 | waitUntilSysTimeOrFlag(start+ms, stopRequested); |
261 | } catch e { |
262 | _handleException(e); |
263 | stopRequested.raise(); |
264 | } |
265 | |
266 | try { |
267 | bool flag = stopRequested.isUp(); // get before closing animation |
268 | if (flag) |
269 | ret with showFrame("Stop screen", |
270 | centerAndSouthWithMargins( |
271 | jcenteredlabel("More troubleshooting options will go here."), |
272 | jcenteredbuttons( |
273 | "Start " + osName() + " normally", r restart, |
274 | //"Switch to " + otherVersionName(), r startOtherVersion, |
275 | eq(programID(), #1016478) ? null: "Switch to v6", r { nohupJavax(#1016478) }, |
276 | eq(programID(), #1024932) ? null: "Switch to v7", r { nohupJavax(#1024932) }, |
277 | "Use last session backup", rThread useLastSessionBackup, |
278 | jPopDownButton_noText( |
279 | "Delete session", disableButtonWhileCalcing(func -> bool { |
280 | if (!fileExists(conceptsFile())) |
281 | ret false with infoBox("Session already empty."); |
282 | if (!confirmOKCancel("Really delete your current session?")) false; |
283 | cleanMeUp_concepts(); |
284 | renameFileToSomeBackupName(conceptsFile()); |
285 | infoBox("Session deleted. Starting again."); |
286 | disableAllButtonsInWindow(heldInstance(JButton)); |
287 | sleepSeconds(3); |
288 | restart(); |
289 | false; |
290 | }))))); |
291 | |
292 | //autoRestart(); |
293 | thread { serverAutoRestartMD5(); } // just a short ping |
294 | |
295 | pcall { setLookAndFeel(); } |
296 | |
297 | showDesktop(); |
298 | } finally { |
299 | disposeWindow(loadingAnim); |
300 | } |
301 | |
302 | initAfterDBLoad(); |
303 | setOpt(javax(), regularGC_firstDelay := 60000); |
304 | call(javax(), 'regularGC); |
305 | if (!headless()) { |
306 | setOpt(javax(), regularGC_condition := func -> bool { |
307 | if (isFalse(callF(gc_subcondition))) false; |
308 | if (backgroundGCFrequency! || vmHasActiveFrame()) |
309 | ret true /*with print("GC")*/; |
310 | else |
311 | ret false /* with print("Skipping GC (not in foreground)") */; |
312 | }); |
313 | } |
314 | hideConsole(); |
315 | manualConsole(); |
316 | //clearConsole(); |
317 | if (headless()) sleep(); |
318 | } |
319 | |
320 | sbool startInFullScreen() { |
321 | ret eq("1", trim(loadTextFile(javaxDataDir("start-os-in-full-screen.txt")))); |
322 | } |
323 | |
324 | svoid setStartInFullScreen(bool b) { |
325 | saveTextFile(javaxDataDir("start-os-in-full-screen.txt"), b ? "1" : "0"); |
326 | } |
327 | sbool showDesktop_first = true; |
328 | |
329 | svoid showDesktop { |
330 | if (headless()) ret; |
331 | bool done = false; |
332 | |
333 | S title; |
334 | if (nempty(osName)) title = osName; |
335 | else { |
336 | title = osName(); //programName(); |
337 | S subDir = javaxVirtualSpaceName(); |
338 | if (subDir != null) title = "[" + subDir + "] " + title; |
339 | } |
340 | |
341 | if (showDesktop_first && startInFullScreen()) pcall { |
342 | showFullScreen(title, desktop); |
343 | done = true; |
344 | } |
345 | |
346 | if (!done) { |
347 | showMaximizedFrame(title, desktop); |
348 | titlePopupMenu_top(desktop, voidfunc(JPopupMenu menu) { |
349 | addMenuItems(menu, |
350 | "New Session", rThreadPcallMessageBox(r deleteAllModules), |
351 | "Restore Initial Modules", r initialModules, |
352 | ); |
353 | }); |
354 | } |
355 | |
356 | if (showTopInput) |
357 | registerFunctionKey(getFrame(desktop), 1, r { requestFocus(tfTopInput) }); |
358 | |
359 | fillMenuBar(); |
360 | doNothingOnClose(getFrame(desktop)); |
361 | frameIcon(mainIconID, desktop); |
362 | showDesktop_first = false; |
363 | cleanExitOnFrameClose_ifStillInSameFrame(desktop, |
364 | () -> (Bool) callF(confirmOSExit)); |
365 | } |
366 | |
367 | sbool inFullScreen() { |
368 | ret isFullScreen(desktop); |
369 | } |
370 | |
371 | svoid fullScreenOff() { |
372 | if (inFullScreen()) fullScreenOnOff(); |
373 | } |
374 | |
375 | svoid fullScreenOnOff { |
376 | // Don't screw up window positions while adjusting from/to fullscreen |
377 | autoFixDesktopPane_exclude.add(desktop); |
378 | temp tempAfterwards(r { autoFixDesktopPane_exclude.remove(desktop) }); |
379 | |
380 | Window w = getWindow(desktop); |
381 | if (!inFullScreen()) { |
382 | showFullScreen(frameTitle(desktop), desktop); |
383 | pcall { frameIcon(mainIconID, desktop); } |
384 | cleanExitOnFrameClose_ifStillInSameFrame(desktop); |
385 | fillMenuBar(); |
386 | setStartInFullScreen(true); |
387 | } else { |
388 | removeFromParent(desktop); |
389 | showDesktop(); |
390 | setStartInFullScreen(false); |
391 | } |
392 | |
393 | // Allow closing empty "zombie" windows (why do we have these?) |
394 | final JFrame f = getFrame(desktop); |
395 | onFrameClosing(f, r { if (isEmptyFrame(f)) { |
396 | removeListener(); |
397 | disposeWindow(f); |
398 | }}); |
399 | |
400 | disposeWindow(w); |
401 | fixDesktopPane(desktop); |
402 | } |
403 | |
404 | svoid updateMenuBar() swing { |
405 | //temp tempRememberFocusedComponent(); |
406 | JMenuBar mb = getMenuBar(desktop); |
407 | if (mb == null) { |
408 | mb = addMenuBar(desktop); |
409 | mb.setLayout(new javax.swing.plaf.basic.DefaultMenuLayout(menuBar, BoxLayout.X_AXIS)); |
410 | } |
411 | keepComponentsByPred(mb, func(Component c) -> bool { |
412 | c instanceof JMenu || c == tfTopInput |
413 | }); |
414 | //clearMenuBar(); |
415 | fillMenuBar(); |
416 | } |
417 | |
418 | svoid fillMenuBar() swing { |
419 | menuBar = addMenuBar(desktop); |
420 | set jmenuItem_newThreads; |
421 | S version = version(); |
422 | S name = osName(); |
423 | //S subDir = userHomeSubDirName(); |
424 | //if (subDir != null) name += " [" + subDir + "]"; |
425 | addMenuIfNempty(desktop, empty(osName) ? "OS" : trim(name), |
426 | featureMenuItem("Screenshot"), r stefansOS_screenshot, |
427 | featureMenuItem("Full screen on/off"), r fullScreenOnOff, |
428 | featureMenuItem("Switch OS version", "Switch to " + otherVersionName()), r { |
429 | innerCleanUp(); |
430 | startOtherVersion(); |
431 | cleanKill(); |
432 | }, |
433 | "---", |
434 | featureMenuItem("Restart OS", "Restart " + or2(osName, "Stefan's OS")), r { showConsole(); restart(); }, |
435 | featureMenuItem("Exit"), r cleanKill |
436 | ); |
437 | |
438 | L moduleMenu = ll( |
439 | featureMenuItem("Other Module..."), r stefansOS_addDynamicModuleDialog, |
440 | "Show selected module's menu", r showCurrentModuleMenu |
441 | ); |
442 | |
443 | for (int i = 0; i+1 < l(standardModules); i += 2) { |
444 | moduleMenu.add(standardModules.get(i)); |
445 | S id = standardModules.get(i+1); |
446 | moduleMenu.add(r { makeOrShowModule(id) }); |
447 | } |
448 | |
449 | moduleMenu.addAll(ll( |
450 | featureMenuItem("Welcome Screen"), r { makeOrShowModule("#1016067/WelcomeScreen") }, |
451 | featureMenuItem("Quick Module Search"), r addQuickModuleSearch, |
452 | //"Hello (input field for everything)", r { makeOrShowModule("Hello") }, |
453 | featureMenuItem("Auto Module Upgrade"), r { makeOrShowModule("#1021905/AutoReloadButtons") }, |
454 | featureMenuItem("Task Bar"), r { makeOrShowModule("#1019954/TaskBar_dev") }, |
455 | featureMenuItem("System Print Log"), r { makeOrShowModule("#1018866/SystemPrintLog") }, |
456 | hideFeature("Internal Types") ? null : jmenu("Internal Types", map(myNonAbstractClassesImplementing(Module), func(final Class c) -> JMenuItem { |
457 | jMenuItem(shortClassName(c), rThread { makeOrShowStaticModuleOfType(c) }) |
458 | })), |
459 | featureMenuItem("Module Classes"), r { makeOrShowStaticModuleOfType(ModuleClasses) }, |
460 | "---", |
461 | jDynamicScrollingMenu("Loaded Modules", voidfunc(JPopupMenu menu) { |
462 | for (final Module m : sortedByMethodIC('moduleName, onModules())) |
463 | addMenuItem(menu, m.moduleName(), rThread { showModule(m) }); |
464 | }) |
465 | )); |
466 | |
467 | addMenu(desktop, "Modules", asObjectArray(moduleMenu)); |
468 | |
469 | // TODO - need to generate menu items differently in enhanceFrame |
470 | //addFullyDynamicMenu(desktop, "Current module", |
471 | |
472 | addMenu(desktop, "More", |
473 | featureMenuItem("Start External JavaX Program..."), r stefansOS_startExternalJavaXProgram, |
474 | "---", |
475 | featureMenuItem("Run 10 Second Profiler"), r tenSecondProfileAndShowInFrame, |
476 | featureMenuItem("Find memory leaks", "Find memory leaks (PID: " + getPID() + ")"), r stefansOS_findMemoryLeaks, |
477 | "Computer ID: " + computerID(), r { copyTextToClipboard_infoBox(computerID()) }, |
478 | featureMenuItem("Show console"), rThread showConsole, |
479 | featureMenuItem("System Version"), r { makeOrShowModule_early("#1016442/SystemVersion") }, |
480 | featureMenuItem("Remove moduleless frames"), rThread dm_closeModuleLessFrames, |
481 | featureMenuItem("Clean disk caches"), rThread stefansOS_cleanDiskCaches, |
482 | hideFeature("Enable quick searches") ? null : (miEnableQuickSearches = menuItem_enableQuickSearches()), |
483 | featureMenuItem("Hard exit"), rHardExit(), |
484 | ); |
485 | |
486 | // Add the fancy stuff |
487 | |
488 | JMenuBar menuBar = cast call(getFrame(desktop), 'getJMenuBar); |
489 | |
490 | if (tfTopInput == null && showTopInput) { |
491 | tfTopInput = jcenteredtextfield(uniq(TopInput).text); |
492 | setFontSize(tfTopInput, 16); |
493 | selectAllOnFocusIf(tfTopInput, func -> bool { |
494 | elapsedTime(tfTopInput_dontSelectAll) >= 2000 |
495 | }); |
496 | onChange(tfTopInput, r { |
497 | cset(uniq(TopInput), text := getText(tfTopInput)); |
498 | rstTopInputChanged.trigger(); |
499 | }); |
500 | onEnter(tfTopInput, r { |
501 | S info = cast generalMap.get('topInputInfo); |
502 | temp dm_generalMap_tempPut(topInputInfo := or2(info, "typed")); |
503 | S text = getText(tfTopInput); |
504 | vmBus_send('topInput, text); |
505 | logQuotedWithDate(topInputsLogFile(), text); |
506 | if (katze_send) |
507 | if (nempty(info)) |
508 | katze_userSaid(info, text); |
509 | else if (katze_sendTyped) |
510 | katze_userTyped(text); |
511 | }); |
512 | componentPopupMenu(tfTopInput, voidfunc(JPopupMenu menu) { |
513 | menu.add(menuItem_enableQuickSearches()); |
514 | }); |
515 | } |
516 | |
517 | if (showTopInput && getParent(tfTopInput) == null) { |
518 | menuBar.add(Box.createHorizontalStrut(20)); |
519 | menuBar.add(tfTopInput); |
520 | } |
521 | |
522 | if (!containsChildOfType(menuBar, JLabel.class)) { // look for clock label |
523 | if (!showTopInput) |
524 | menuBar.add(Box.createHorizontalGlue()); |
525 | else { |
526 | menuBar.add(Box.createHorizontalStrut(5)); |
527 | menuBar.add(onClick(setToolTip([[Simulate pressing Enter key in input field to the left ("AI bar")]], jimage(#1101426)), r { simulateEnter(tfTopInput) })); |
528 | } |
529 | //menuBar.add(jhgrid(null, tfTopInput)); |
530 | //menuBar.add(jhgrid(tfTopInput, null)); |
531 | menuBar.add(Box.createHorizontalStrut(20)); |
532 | for i over trayAreaComponents: { |
533 | Component c = trayAreaComponents.get(i); |
534 | continue if c == null; |
535 | menuBar.add(c); |
536 | menuBar.add(Box.createHorizontalStrut(i == l(trayAreaComponents)-1 ? 20 : 6)); |
537 | } |
538 | menuBar.add(jLiveValueLabel(clockTimeLiveValue())); |
539 | menuBar.add(Box.createHorizontalStrut(6)); |
540 | } |
541 | } |
542 | |
543 | svoid addQuickModuleSearch { |
544 | makeOrShowModule("#1016702/LoadedModuleSearch"); |
545 | makeOrShowModule("#1016932/ServerModuleSearch"); |
546 | } |
547 | |
548 | static JCheckBoxMenuItem menuItem_enableQuickSearches() { |
549 | ret jCheckBoxMenuItem("Enable quick searches", quickSearchesEnabled(), voidfunc(bool b) { |
550 | cset(uniq(TopInput), quickSearchesEnabled := b); |
551 | setChecked(miEnableQuickSearches, b); |
552 | }); |
553 | } |
554 | |
555 | static tempDisposeInternalFrame_obj<JLabel> tempBusyAnimation(fS text) { |
556 | ret vmExiting() ? null : tempBusyAnimation(stringLiveValue(text)); |
557 | } |
558 | |
559 | static tempDisposeInternalFrame_obj<JLabel> tempBusyAnimation(LiveValue<S> text) { |
560 | if (headless()) null; |
561 | final JLabel anim = jBackground(Color.white, jAnimation_liveValueText(#1101316, text)); |
562 | swing { |
563 | addInternalFrame_dontSelect.set(true); |
564 | addInternalFrame_layer.set(JLayeredPane.POPUP_LAYER); |
565 | addInternalFrame(desktop, "", null, anim); |
566 | packInternalFrameInTopRightCorner(anim); |
567 | JInternalFrame f = getInternalFrame(anim); |
568 | //print("Have busy animation: " + f + " in " + getParent(f)); |
569 | } |
570 | ret tempDisposeInternalFrame(anim); |
571 | } |
572 | |
573 | svoid allRegularFixes { |
574 | applyStandardSwingFixes(); |
575 | cleanDefunctACCsInAllThreads(); |
576 | cleanDefunctACCsInAllSwingComponents(); |
577 | } |
578 | |
579 | svoid gcWithFixes { |
580 | allRegularFixes(); |
581 | gc(); |
582 | allRegularFixes(); |
583 | } |
584 | |
585 | svoid initAfterDBLoad { |
586 | doEvery(30000, r allRegularFixes); |
587 | doEvery(600000, r clearSnippetTitleCacheIfOnline); |
588 | set cleanUp_interruptThreads; |
589 | |
590 | // for Java Chrome |
591 | classForNameOpt("java.util.prefs.FileSystemPreferences"); |
592 | |
593 | SimpleLiveValue<S> lvText = stringLiveValue(jlabel_textAsHTML_center("Restoring Session")); |
594 | temp final tempDisposeInternalFrame_obj<JLabel> anim = tempBusyAnimation(lvText); |
595 | JLabel animComponent = anim == null ? null : anim.component; |
596 | if (anim != null) { |
597 | onResizeAndNow(animComponent, r { |
598 | setVerticalAlignment( |
599 | animComponent.getHeight() >= 150 ? JLabel.CENTER : JLabel.TOP, |
600 | animComponent) |
601 | }); |
602 | growInternalFrameLeft(animComponent, 50); |
603 | growInternalFrameSouth(animComponent, 50); |
604 | } |
605 | |
606 | disabledModuleIDs = asSet(tlft(loadTextFile(javaxDataDir("stefans-os/disabled-modules.txt")))); |
607 | |
608 | initialModules(); |
609 | |
610 | UpdateCycles uc = conceptWhere(UpdateCycles); |
611 | if (uc != null) updateCycles = uc.value; |
612 | |
613 | stefansOS_installQuickSearchHelper(); |
614 | |
615 | // START ALL MODULES |
616 | |
617 | L<Module> modules = startOrder(onModules()); |
618 | |
619 | AutoCloseable disposeTempCache2 = cacheTranspilationsDuringBoot ? tempSetMCOpt(getServerTranspiled2_tempCache := syncMap()) : null; |
620 | |
621 | if (cacheTranspilationsDuringBoot) thread { |
622 | for (Module m : modules) pcall { |
623 | if (m cast DynamicModule) { |
624 | print("Preloading " + m.moduleID); |
625 | getServerTranspiled2(m.moduleID); |
626 | } |
627 | } |
628 | print("Preloading done"); |
629 | } |
630 | |
631 | AutoCloseable disposeTempCache = tempSetTL(loadLibraryOrSrcLib_tempCache, new Map); |
632 | |
633 | int i = 0; |
634 | for (Module m : modules) { |
635 | ++i; |
636 | int _i = i; |
637 | systemQ.add(new Runnable { |
638 | run { |
639 | if (isShuttingDown()) ret; |
640 | lvText.set(jlabel_textAsHTML_center( |
641 | "Starting module " + _i + "/" + l(modules) + ":\n" |
642 | + m.moduleName())); |
643 | startModule(m); |
644 | } |
645 | |
646 | toString { ret "Start module " + m.id; } |
647 | }); |
648 | } |
649 | |
650 | if (anim != null) anim.disableAutoDisposal(); |
651 | systemQ.add(r { |
652 | close(disposeTempCache); |
653 | close(disposeTempCache2); |
654 | disposeInternalFrame(animComponent); |
655 | if (isShuttingDown()) ret; |
656 | systemStatus.set("running"); |
657 | print("== STARTED IN " + iceil(elapsedSeconds(/*vmStartTime_sys()*/startTime)) + " SECONDS =="); |
658 | }); |
659 | } |
660 | |
661 | static L<Module> startOrder(L<Module> modules) { |
662 | ret sortedByComparator( |
663 | combineComparators( |
664 | main.<Module> fieldComparator('loadOrder), |
665 | main.<Module> descFieldComparator('visible), |
666 | main.<Module> fieldComparator('zOrder)), |
667 | modules); |
668 | } |
669 | |
670 | svoid initialModules { |
671 | if (initialModules_override != null) |
672 | ret with pcallF(initialModules_override, mc()); |
673 | initialModules_base(); |
674 | } |
675 | |
676 | svoid initialModules_base { |
677 | if (headless()) { |
678 | makeOrShowModule("#1016576/ConnectToServer"); |
679 | ret; |
680 | } |
681 | |
682 | if (empty(onModules())) { |
683 | //makeOrShowModule(#1016081/WelcomeScreen"); |
684 | showModule_noFocus(getModuleByID(makeModule("#1018866/SystemPrintLog"))); |
685 | showModule_noFocus(getModuleByID(makeModule("#1019954/TaskBar_dev"))); |
686 | //makeModule("#1016872/SnippetsDB"); |
687 | makeModule("#1016932/ServerModuleSearch"); |
688 | makeModule("#1016702/LoadedModuleSearch"); |
689 | //makeModule("#1018602/QuickAudioRecord"); |
690 | makeModule("#1019326/WitAILastRecording"); |
691 | makeModule("#1019400/SpeechRecogConfirmation"); |
692 | makeModule("#1021905/AutoReloadButtons"); |
693 | } |
694 | } |
695 | |
696 | svoid triggerUpdate { rstUpdateModules.trigger(); } |
697 | |
698 | // not done anymore |
699 | svoid updateModules { |
700 | /*++updateCycles; |
701 | for (Module m : onModules()) |
702 | updateModule(m);*/ |
703 | } |
704 | |
705 | svoid updateModule(Module m) { |
706 | if (m == null) ret; |
707 | temp m.enter(); |
708 | pcall { m.update(); } |
709 | } |
710 | |
711 | svoid updateModules(final Collection<Module> l) { |
712 | systemQ.add(r { |
713 | for (Module m : unnull(l)) updateModule(m); |
714 | }); |
715 | } |
716 | |
717 | svoid saveZOrder { |
718 | for (Module m) |
719 | cset(m, zOrder := getComponentZOrder(getInternalFrame(m.vis))); |
720 | } |
721 | |
722 | svoid cleanMeUp { |
723 | saveZOrder(); |
724 | autoConsole(); |
725 | if (shutdownConsole == null) showConsole(); else pcallF(shutdownConsole); |
726 | killProgram(#1019683); // stop watch dog |
727 | systemStatus.set("shutting down"); |
728 | temp tempBusyAnimation("Shutting Down"); |
729 | |
730 | print("PRE-CLEAN UP"); |
731 | preCleanUp(list(Module)); |
732 | for (Module m) { |
733 | if (m.vis != null) pcall { |
734 | print("UNVISUALIZING " + moduleIDAndName(m)); |
735 | m.unvisualize(); |
736 | print("UNVISUALIZED " + moduleIDAndName(m)); |
737 | } |
738 | print("CLEANING UP " + moduleIDAndName(m)); |
739 | cleanUp(m); |
740 | print("CLEANED UP " + moduleIDAndName(m)); |
741 | } |
742 | print("CLEAN UP DONE"); |
743 | cleanedUp = true; |
744 | } |
745 | |
746 | static L<Module> onModules() { ret asList(conceptsWhere(Module, on := true)); } |
747 | |
748 | sbool hasModuleWithFields(Class<? extends Module> c, O... params) { |
749 | ret hasConcept(c, concatArrays(new O[] {on := true}, params)); |
750 | } |
751 | |
752 | sbool startModule_reloading, startModule_doShare; |
753 | sO startModule_beforeStart; |
754 | |
755 | svoid startModule(Module m) { |
756 | runInSystemQAndWait(r-pcall { |
757 | //addIfNotThere(modules, m); |
758 | //print("startModule " + m); |
759 | temp m.enter(); |
760 | if (m.started) ret; |
761 | if (m.startedWithError) print("Module " + m + " started with error"); |
762 | |
763 | temp tempSet(m, starting := true); |
764 | print("Starting module " + m.moduleName()); |
765 | try { |
766 | if (m cast DynamicModule) |
767 | if (contains(disabledModuleIDs, m.moduleID)) |
768 | failWithInfoBox("Not starting disabled module " + m); |
769 | m.start(); |
770 | m.started = true; |
771 | } catch e { |
772 | m.startedWithError = true; |
773 | m.setError(e); |
774 | _handleException(e); |
775 | } |
776 | vmBus_send('moduleStarted, m.moduleID()); |
777 | //rstUpdateModules.trigger(); |
778 | if (m.visible) { |
779 | showModule(m); |
780 | if (m.poppedOut) stefansOS_popOutModule(m); |
781 | } |
782 | }); |
783 | } |
784 | |
785 | static Module showModule(final Module m) { |
786 | ret showModule(m, true); |
787 | } |
788 | |
789 | static Module showModule_noFocus(final Module m) { |
790 | ret showModule(m, false); |
791 | } |
792 | |
793 | svoid runInSystemQAndWait(Runnable r) { |
794 | if (isAWTThread()) ret with callF(r); |
795 | runInQAndWait(systemQ, r); |
796 | } |
797 | |
798 | sO evalInSystemQ_gen(O f) { |
799 | ret evalInSystemQ(toF0(f)); |
800 | } |
801 | |
802 | static <A> A evalInSystemQ(F0<A> f) { |
803 | if (isAWTThread()) ret callF(f); |
804 | ret evalInQ(systemQ, f); |
805 | } |
806 | |
807 | static Module showModule(final Module m, final bool focus) { |
808 | if (m == null) ret m; |
809 | runInSystemQAndWait(r { |
810 | startModule(m); |
811 | if (headless()) ret; |
812 | temp m.enter(); |
813 | if (m.vis != null) { |
814 | if (focus && !isLoading()) |
815 | if (stefansOS_moduleIsPoppedOut(m)) |
816 | activateFrame(m.vis); |
817 | else |
818 | activateInternalFrame(m.vis); |
819 | ret; |
820 | } |
821 | csetAndStatusChange(m, visible := true); |
822 | visualizeModule(m); |
823 | if (m.vis != null) swing { |
824 | Rect r = m.frameRect; |
825 | /*if (r == null) r = randomRect(desktop.getWidth(), desktop.getHeight(), 10, 150, 100); |
826 | if (r == null) r = makeDefaultRectForModule(m); |
827 | print("Showing frame at " + r);*/ |
828 | S frameTitle = m.moduleName(); |
829 | final JInternalFrame f; |
830 | bool toBack = isLoading() && firstModuleShown; |
831 | bool activate = focus && !toBack; |
832 | { |
833 | temp tempSetThreadLocal(addInternalFrame_toBack, toBack); |
834 | temp tempSetThreadLocal(addInternalFrame_dontSelect, !activate); |
835 | f = showInternalFrame(desktop, frameTitle, r, m.vis); |
836 | set firstModuleShown; |
837 | } |
838 | if (r == null) { |
839 | if (debugFrameSizes) print("Setting initial size for module " + m); |
840 | Pt p = m.getMinSize(); |
841 | if (debugFrameSizes) print("Minimum size: " + p); |
842 | if (isTrue(callOpt(resolveModule(m), "_usePreferredSizeInitially"))) { |
843 | p = toPt(getPreferredSize(m.vis)); |
844 | if (debugFrameSizes) print("Using preferred size: " + p); |
845 | } |
846 | |
847 | centerPackInternalFrameWithMinSize(f, p); |
848 | } |
849 | f.setDefaultCloseOperation(JInternalFrame.DO_NOTHING_ON_CLOSE); |
850 | |
851 | onInternalFrameIconified(f, r { hideModule(m) }); |
852 | onInternalFrameClosing(f, rThread { deleteModule(m) }); |
853 | onInternalFrameActivated(f, r { setActiveModule(m) }); |
854 | onInternalFrameDeactivated(f, r { if (activeModule == m) setActiveModule(null) }); |
855 | onBoundsChange(f, r { m.grabFrameRect() }); |
856 | internalFrameIcon(f, or2(m.iconID, moduleDefaultIconID)); |
857 | m.enhanceFrame(f); |
858 | if (activate) setActiveModule(m); |
859 | } |
860 | }); |
861 | ret m; |
862 | } |
863 | |
864 | static Rect makeDefaultRectForModule(Module m) { |
865 | ret Rect(10, 10, 200, 100); |
866 | } |
867 | |
868 | svoid showModules(L<? extends Module> l) { |
869 | for (Module m : unnull(l)) showModule(m); |
870 | } |
871 | |
872 | sbool deleteModule(Module m) { |
873 | pcall { |
874 | bool warn = isTrue(callOpt(resolveModule(m), 'warnOnDelete)); |
875 | if (warn && !confirmOKCancel("Really delete module " + m + "?")) |
876 | false; |
877 | } |
878 | deleteModule_noConfirm(m); |
879 | true; |
880 | } |
881 | |
882 | svoid deleteModule_noConfirm(Module m) { |
883 | runInSystemQAndWait(r { |
884 | if (verboseModuleDeletes) print("delete phase 1"); |
885 | O m2 = unwrapDynamicModule(m); |
886 | vmBus_send('deletingModule, m2); |
887 | ghostModules.put(m == m2 ? m : m2.getClass(), nu(GhostModule, |
888 | name := m.moduleName(), |
889 | created := m.created, |
890 | deleted := now(), |
891 | instance := new WeakReference(m2))); |
892 | if (verboseModuleDeletes) print("delete phase 2"); |
893 | pcall { m.unvisualize(); } |
894 | if (verboseModuleDeletes) print("delete phase 3"); |
895 | removeConcept(m); // generates oStruct |
896 | vmBus_send('moduleDeleted, m); |
897 | if (verboseModuleDeletes) print("delete phase 4"); |
898 | pcall { |
899 | S snippetID = m instanceof DynamicModule ? m/DynamicModule.moduleID : "internal_" + shortClassName(m); |
900 | logStructure(deletedModulesLogFile(snippetID), litmap( |
901 | globalID := aGlobalID(), |
902 | deleted := now(), |
903 | module := m)); |
904 | } |
905 | //triggerUpdate(); |
906 | }); |
907 | } |
908 | |
909 | svoid visualizeModule(Module m) { |
910 | pcall { |
911 | if (m.vis == null) m.vis = m.visualize(); |
912 | } |
913 | pcall { |
914 | if (m.vis == null) m.vis = defaultVisualize(m); |
915 | } |
916 | vmBus_send('moduleVisualized, m); |
917 | } |
918 | |
919 | svoid hideModule(final Module m) { |
920 | if (m == null) ret; |
921 | runInSystemQAndWait(r { |
922 | temp m.enter(); |
923 | csetAndStatusChange(m, visible := false); |
924 | pcall { m.unvisualize(); } |
925 | }); |
926 | } |
927 | |
928 | svoid csetAndStatusChange(Module m, O... params) { |
929 | if (cset(m, params) > 0) |
930 | vmBus_send('moduleStatusChange, m, params); |
931 | } |
932 | |
933 | svoid revisualizeModule(Module m) { |
934 | pcall { |
935 | if (m == null) ret; |
936 | temp m.enter(); |
937 | JInternalFrame frame = getInternalFrame(m.vis); |
938 | if (frame == null) ret; |
939 | m.unvisualize1b(); |
940 | m.unvisualize2(); |
941 | visualizeModule(m); |
942 | setInternalFrameContents(frame, m.vis); |
943 | } |
944 | } |
945 | |
946 | abstract concept Module { |
947 | transient JComponent vis; |
948 | transient bool starting, started, startedWithError; |
949 | transient Lock lock = lock(); |
950 | |
951 | static int ALWAYSONTOPWHENPOPPEDOUT = 1; |
952 | |
953 | bool on = true, visible, poppedOut; |
954 | int flags; |
955 | Rect frameRect; |
956 | int zOrder; |
957 | S iconID; |
958 | PersistableThrowable error; |
959 | int loadOrder; |
960 | |
961 | //transient Set timers; |
962 | |
963 | JComponent visualize() { null; } |
964 | void unvisualize() { |
965 | pcall { unvisualize1(); } |
966 | pcall { unvisualize2(); } |
967 | vmBus_send('moduleUnvisualized, this); |
968 | } |
969 | void enhanceFrame(JInternalFrame frame) {} |
970 | void start() {} |
971 | void unvisualize1() { |
972 | disposeInternalFrame(getInternalFrame(vis)); |
973 | unvisualize1b(); |
974 | } |
975 | |
976 | void unvisualize1b() { |
977 | grabFrameRect(); |
978 | vis = null; |
979 | } |
980 | void unvisualize2() {} |
981 | void update() {} |
982 | |
983 | void grabFrameRect() { |
984 | JInternalFrame f = getInternalFrame(vis); |
985 | if (f != null) |
986 | cset(this, frameRect := toRect(getBounds(f))); |
987 | } |
988 | |
989 | Rect getFrameRect() { |
990 | grabFrameRect(); |
991 | ret frameRect; |
992 | } |
993 | |
994 | void cleanMeUp_started() { started = startedWithError = false; } |
995 | |
996 | void delete() { |
997 | unvisualize(); |
998 | cleanUp(this); |
999 | super.delete(); |
1000 | } |
1001 | |
1002 | S sourceCode() { |
1003 | ret javaxSourceOfMyClass1(shortClassName(this)); |
1004 | } |
1005 | |
1006 | // for all modules |
1007 | void triggerUpdate { rstUpdateModules.trigger(); } |
1008 | |
1009 | void setModuleIcon(S iconID) { |
1010 | if (eq(iconID, this.iconID)) ret; |
1011 | this.iconID = iconID; |
1012 | internalFrameIcon(vis, iconID); |
1013 | } |
1014 | |
1015 | O resolve() { ret this; } |
1016 | O getError() { ret error; } |
1017 | S moduleID() { ret str(id); } |
1018 | |
1019 | void setError(Throwable e) { |
1020 | cset(this, error := persistableThrowable(e)); |
1021 | } |
1022 | |
1023 | AutoCloseable enter() { null; } |
1024 | |
1025 | JComponent vis() { ret vis; } |
1026 | |
1027 | static bool needsParameters() { false; } |
1028 | |
1029 | S moduleName() { |
1030 | ret humanizeFormLabel(shortClassName(this)); |
1031 | } |
1032 | |
1033 | bool hasFlag(int flag) { ret anyCommonBits(flags, flag); } |
1034 | void setFlag(int flag) { _setField(flags := flags | flag); } |
1035 | void clearFlag(int flag) { _setField(flags := flags & ~flag); } |
1036 | |
1037 | // minimum size of JInternalFrame |
1038 | Pt getMinSize() { null; } |
1039 | } // END CONCEPT MODULE |
1040 | |
1041 | static JComponent defaultVisualize(Module m) { |
1042 | ret jCenteredMultiLineLabel(renderConcept(m)); |
1043 | } |
1044 | |
1045 | static <A extends Module> A findModule(Class<A> c) { |
1046 | ret findConcept(c, on := true); |
1047 | } |
1048 | |
1049 | // ignores snippet ID, just checks for module (inner) class name |
1050 | // returns module ID |
1051 | sS findDynModuleOfType(S type) { |
1052 | S suffix = "$" + type; |
1053 | DynamicModule m = firstThat(conceptsWhere DynamicModule(on := true), mod -> endsWith(mod._className, suffix)); |
1054 | ret m?.moduleID(); |
1055 | } |
1056 | |
1057 | sbool moduleTypeIs(Module m, S type) { |
1058 | if (m == null) false; |
1059 | ret endsWith(moduleResolvedClassName(m), "$" + type); |
1060 | } |
1061 | |
1062 | sS moduleResolvedClassName(Module m) { |
1063 | if (m == null) null; |
1064 | if (m instanceof DynamicModule) |
1065 | ret m/DynamicModule._className; |
1066 | ret className(m); |
1067 | } |
1068 | |
1069 | // returns module ID |
1070 | sS findClosestModuleTo(O searcher, S type) { |
1071 | JInternalFrame f = getInternalFrame(dm_getVisualization(searcher)); |
1072 | if (f == null) null; |
1073 | Pt p = centerOfRect(toRect(getBounds(f))); |
1074 | new Lowest<S> best; |
1075 | for (Module m : onModules()) { |
1076 | JInternalFrame f2 = getInternalFrame(m.vis); |
1077 | if (f2 == null || f2 == f) continue; |
1078 | if (type != null && !moduleTypeIs(m, type)) continue; |
1079 | Rect r2 = toRect(getBounds(f2)); |
1080 | best.put(m.moduleID(), rectPointDistance(r2, p)); |
1081 | } |
1082 | ret best!; |
1083 | } |
1084 | |
1085 | static <A extends Module> L<A> staticModulesOfType(Class<A> type) { |
1086 | ret asList(conceptsWhere(type, on := true)); |
1087 | } |
1088 | |
1089 | static <A extends Module> L<A> staticModulesOfExactType(Class<A> type) { |
1090 | ret filterByExactType(type, staticModulesOfType(type)); |
1091 | } |
1092 | |
1093 | static L listModules() { |
1094 | ret map unwrapDynamicModule(onModules()); |
1095 | } |
1096 | |
1097 | static int moduleCount() { |
1098 | ret l(onModules()); |
1099 | } |
1100 | |
1101 | static L visibleModules() { |
1102 | ret map unwrapDynamicModule(objectsWhere(onModules(), visible := true)); |
1103 | } |
1104 | |
1105 | static O unwrapDynamicModule(Module m) { |
1106 | ret m instanceof DynamicModule ? or(m/DynamicModule.o, m) : m; |
1107 | } |
1108 | |
1109 | sbool moduleStillThere(O o) { |
1110 | Module m = o instanceof Module ? o/Module : (Module) get(o, '_host); |
1111 | ret isConceptRegistered(mainConcepts, m); |
1112 | } |
1113 | |
1114 | static O getDynModuleByID(S moduleID) { |
1115 | if (moduleID == null) null; |
1116 | ret resolveModule(getConcept(Module, parseLong(moduleID))); |
1117 | } |
1118 | |
1119 | static Module getModuleByID(S moduleID) { |
1120 | if (moduleID == null) null; |
1121 | ret getConcept(Module, parseLong(moduleID)); |
1122 | } |
1123 | |
1124 | sS getInterestingString { |
1125 | InterestingString m = findModule(InterestingString); |
1126 | ret m == null ? getText(tfTopInput) : m.theString; |
1127 | } |
1128 | |
1129 | sS modulesSessionGrab() { |
1130 | grabFrameRects(); |
1131 | ret struct(ll(programID(), localDateWithMilliseconds())) + "\n" |
1132 | + mainConcepts.xfullgrab(); |
1133 | } |
1134 | |
1135 | svoid autoSaveModulesSession() { |
1136 | infoBox("Auto-saving session."); |
1137 | S grab; |
1138 | logQuoted(javaxBackupDir(fsI(programID()) + "/auto-saved-sessions.txt"), grab = modulesSessionGrab()); |
1139 | infoBox("Auto-save done (" + l(grab) + " chars)"); |
1140 | } |
1141 | |
1142 | svoid deleteAllModules() { |
1143 | autoSaveModulesSession(); |
1144 | deleteConcepts(Module); |
1145 | initialModules(); |
1146 | } |
1147 | |
1148 | svoid restoreModulesSession(S text) { |
1149 | autoSaveModulesSession(); |
1150 | systemStatus.set("shutting down"); |
1151 | infoBox("Releasing session"); |
1152 | cleanMeUp(); |
1153 | cleanUp(mainConcepts); |
1154 | mainConcepts = null; |
1155 | //sleepSeconds(1); |
1156 | infoBox("Loading session"); |
1157 | systemStatus.set("loading"); |
1158 | mainConcepts = new Concepts().load(dropFirstLine(text)); |
1159 | initAfterDBLoad(); |
1160 | infoBox("Session restore done"); |
1161 | } |
1162 | |
1163 | svoid grabFrameRects { |
1164 | for (Module m : onModules()) m.grabFrameRect(); |
1165 | } |
1166 | |
1167 | concept DynamicModule extends Module { |
1168 | // moduleID is the snippet ID |
1169 | // "className" is taken by DynamicObject; _className == null for old-style dyn module |
1170 | S moduleID, _className; |
1171 | |
1172 | S oStruct; // serialized dynamic object |
1173 | sbool reload_replaceFrame = true; |
1174 | |
1175 | transient Class c; |
1176 | transient O o; |
1177 | transient bool contentsDirty = true; |
1178 | transient ReliableSingleThread rstPersist = rstWithDelay(persistenceDelayPerModule, r persistContents); |
1179 | transient O reloadData; // data held for module during reload |
1180 | |
1181 | *() {} |
1182 | *(S *moduleID, S *_className) {} |
1183 | *(S *moduleID, S *_className, Class *c) {} |
1184 | |
1185 | static bool needsParameters() { true; } |
1186 | |
1187 | AutoCloseable enter() { |
1188 | ret castForTemp(callOpt(o, 'enter)); |
1189 | } |
1190 | |
1191 | JComponent visualize() { |
1192 | temp enter(); |
1193 | ret (JComponent) callOpt(o, 'visualize); |
1194 | } |
1195 | |
1196 | void enhanceFrame(final JInternalFrame f) { |
1197 | final WeakReference<JInternalFrame> fRef = new(f); |
1198 | final WeakReference<DynamicModule> mRef = new(this); |
1199 | S idText = str(id); |
1200 | |
1201 | if (isTrue(vmGeneralMap_get('iconifyBroken))) |
1202 | internalFrameTitlePopupMenuItem(f, "Hide/Minimize", r { hideModule(mRef!) }); |
1203 | |
1204 | idText += "/" + moduleLibID(); |
1205 | if (!hideFeature("Show source code")) |
1206 | internalFrameTitlePopupMenuItem(f, "Source code [Module ID: " + idText + "]", r-thread { pcall { |
1207 | if (empty(mRef->moduleID)) ret with infoBox("No source code found"); |
1208 | dm_openSnippetInEditor(mRef->moduleID); |
1209 | }}); |
1210 | |
1211 | internalFrameTitlePopupMenuItem(f, "Reload", r reload); |
1212 | internalFrameTitlePopupMenuItem(f, "Duplicate", rThread { duplicateModule(DynamicModule.this) }); |
1213 | if (!hideFeature("Retranspile")) |
1214 | internalFrameTitlePopupMenuItem(f, "Medium Retranspile", rThread { transpileOnServerWithErrorWindow(moduleID, true, r reload) }); |
1215 | if (!hideFeature("Pop Out")) internalFrameTitlePopupMenuItem(f, "Pop Out", r { |
1216 | clearFlag(ALWAYSONTOPWHENPOPPEDOUT); |
1217 | stefansOS_popOutModule(DynamicModule.this); |
1218 | }); |
1219 | if (!hideFeature("Pop Out + Always On Top")) internalFrameTitlePopupMenuItem(f, "Pop Out + Always On Top", r { |
1220 | setFlag(ALWAYSONTOPWHENPOPPEDOUT); |
1221 | stefansOS_popOutModule(DynamicModule.this); |
1222 | }); |
1223 | |
1224 | internalFrameTitlePopupMenu(f, (IVF1<JPopupMenu>) menu -> { |
1225 | LS sisterModules = dm_sisterModules(this); |
1226 | if (empty(sisterModules)) ret; |
1227 | JMenu subMenu = jmenu("Sister modules"); |
1228 | for (S mod : sisterModules) |
1229 | addMenuItem(subMenu, dm_moduleName(mod), rThread { dm_showModule(mod) }); |
1230 | menu.add(subMenu); |
1231 | }); |
1232 | |
1233 | { |
1234 | temp enter(); |
1235 | pcallOpt(o, 'enhanceFrame, f); |
1236 | } |
1237 | internalFrameTitle(f, moduleName()); |
1238 | } |
1239 | |
1240 | S moduleLibID() { |
1241 | ret moduleID + "/" + afterLastDollar(_className); |
1242 | } |
1243 | |
1244 | S moduleName() { |
1245 | S name = (S) callOpt(o, 'moduleName); |
1246 | if (nempty(name)) ret name; |
1247 | ret originalModuleName(); |
1248 | } |
1249 | |
1250 | S originalModuleName() { |
1251 | S title = snippetTitle_cached(moduleID); |
1252 | //ret dropSuffixICTrimOneOf(title, "[Dyn Module]", "[Dyn Module, OK]", "[Dyn Module, shortened]"); |
1253 | ret stefansOS_cleanModuleName(title); |
1254 | } |
1255 | |
1256 | void start() { |
1257 | try { |
1258 | start_impl(); |
1259 | } catch e { |
1260 | setError(e); |
1261 | _handleException(e); |
1262 | } |
1263 | } |
1264 | |
1265 | void start_impl { |
1266 | if (moduleID == null) ret; |
1267 | if (c == null) |
1268 | c = startModule_reloading && !startModule_doShare |
1269 | ? hotwireModule(moduleID) |
1270 | : hotwireModule_withSharing(moduleID); |
1271 | replaceACCInClassLoader(c, globalACC); |
1272 | if (oStruct != null) pcall { |
1273 | Map<S, O> renames = cast getOpt(c, '_renameClasses); |
1274 | //print("Class renames: " + sfu(renames)); |
1275 | S renamed = migrateClassesInStructureText(oStruct, renames); |
1276 | //print("Renamed: " + renamed); |
1277 | |
1278 | // notify module that we are loading (dev.) |
1279 | /*ThreadLocal tlLoading = cast getOpt(getClass(c, "loadableUtils.utils"), 'dynamicObjectIsLoading); |
1280 | temp tempSetTL(tlLoading, true);*/ |
1281 | |
1282 | // load |
1283 | o = unstructureInRealm(renamed, c); |
1284 | S className = shortClassName(o); |
1285 | if (eq(className, "DynamicObject")) |
1286 | print("Warning: Module didn't unstructure to target class"); |
1287 | else |
1288 | // Update module lib ID after module class rename |
1289 | setField(_className := className(o)); |
1290 | } |
1291 | if (o == null) |
1292 | if (_className == null) |
1293 | o = c; // old-style - just a class |
1294 | else { |
1295 | o = nu(getClass_vmName(c, _className)); // new-style (module is an object) |
1296 | if (!stefansOS_checkModuleInstance(o)) { // TODO: doesn't seem to trigger for modules with wrong class name |
1297 | o = null; |
1298 | S msg = this + " failed to load - " + className(o) + " not an instance of DynModule"; |
1299 | infoBox(msg); |
1300 | error = persistableThrowable(new RuntimeException(msg)); |
1301 | ret; |
1302 | } |
1303 | } |
1304 | setOptAll(o, _host := this, lock := lock); |
1305 | |
1306 | // call module's start() method |
1307 | |
1308 | temp enter(); |
1309 | |
1310 | // this is set when making a module with params |
1311 | callF(startModule_beforeStart, this); |
1312 | |
1313 | // some modules need the reload data before starting |
1314 | if (reloadData != null) |
1315 | callOpt(o, '_setReloadData_early, reloadData); |
1316 | |
1317 | if (o instanceof Class) |
1318 | callMain(o); |
1319 | else |
1320 | callOpt(o, 'start); |
1321 | } |
1322 | |
1323 | void unvisualize2() { callOpt(o, 'unvisualize); } |
1324 | |
1325 | void update() { callOpt(o, 'update); } |
1326 | |
1327 | // TODO - only when called from DynModule |
1328 | // (works for now, but should be renamed) |
1329 | public void change :: after { |
1330 | vmBus_send moduleChanged(this); |
1331 | contentsDirty = true; |
1332 | if (rstPersist != null) |
1333 | rstPersist.trigger(); |
1334 | } |
1335 | |
1336 | void persistContents() enter { |
1337 | if (_concepts != null && contentsDirty) { |
1338 | vmBus_send persistingModuleContents(this); |
1339 | contentsDirty = false; |
1340 | //oStruct = null; |
1341 | pcall { |
1342 | if (o != null && !o instanceof Class) { |
1343 | cset(this, oStruct := struct(o)); |
1344 | if (printOnPersistContents) |
1345 | print("Persisted contents: " + moduleID + " - " + l(oStruct) + " chars"); |
1346 | callOpt(o, 'onPersisted); |
1347 | } |
1348 | } |
1349 | } |
1350 | } |
1351 | |
1352 | void cleanMeUp() { |
1353 | persistContents(); |
1354 | if (verboseCleanUp) |
1355 | print("o: " + className(o) + ". Cleaning up main class: " + mainClass(o)); |
1356 | if (mainClass(o) == mc()) // anomalous object |
1357 | cleanUp(o); |
1358 | else enter { |
1359 | if (classLoadedInOtherModule(mainClass(o), this)) { |
1360 | print("KEEPING code (loaded in other module)"); |
1361 | cleanUp(o); |
1362 | } else |
1363 | cleanUpObjectAndItsMainClass(o); |
1364 | } |
1365 | o = null; |
1366 | c = null; |
1367 | } |
1368 | |
1369 | void reload() { |
1370 | reloadModuleInBackground(this); |
1371 | } |
1372 | |
1373 | // don't call directly - runs in system queue |
1374 | void reload_impl() { |
1375 | temp tempAddToCollection(modulesBeingReloaded, this); |
1376 | |
1377 | if (reloadData == null) { |
1378 | temp enter(); |
1379 | reloadData = callOpt(o, '_getReloadData); |
1380 | } |
1381 | |
1382 | if (poppedOut) stefansOS_popInModule(this); |
1383 | JInternalFrame frame = getInternalFrame(vis); |
1384 | unvisualize1b(); |
1385 | unvisualize2(); |
1386 | |
1387 | if (o != null) |
1388 | ghostModules.put(o.getClass(), nu(GhostModule, |
1389 | name := moduleName(), |
1390 | created := created, |
1391 | deleted := now(), |
1392 | instance := new WeakReference(o))); |
1393 | |
1394 | cleanUp(this); // also sets started to false |
1395 | |
1396 | if (frame != null) |
1397 | setInternalFrameContents(frame, |
1398 | makeReloadingComponent != null |
1399 | ? callF(makeReloadingComponent, this) |
1400 | : makeStandardReloadingComponent(this)); |
1401 | |
1402 | visible = false; |
1403 | |
1404 | { |
1405 | temp tempSetMC(startModule_reloading := true); |
1406 | startModule(this); |
1407 | } |
1408 | |
1409 | if (reloadData != null) { |
1410 | temp enter(); |
1411 | callOpt(o, '_setReloadData, reloadData); |
1412 | reloadData = null; |
1413 | } |
1414 | |
1415 | if (frame != null) { |
1416 | if (reload_replaceFrame) { // avoids some bugs |
1417 | cset(this, frameRect := toRect(getBounds(frame))); |
1418 | disposeInternalFrame(frame); |
1419 | showModule(this); |
1420 | } else { |
1421 | csetAndStatusChange(this, visible := true); |
1422 | visualizeModule(this); |
1423 | //print("New content: " + vis); |
1424 | setInternalFrameContents(frame, vis); |
1425 | } |
1426 | } |
1427 | |
1428 | if (poppedOut) stefansOS_popOutModule(this); |
1429 | |
1430 | vmBus_send moduleReloaded(this); |
1431 | } |
1432 | |
1433 | S sourceCode() { |
1434 | ret loadSnippet(moduleID); |
1435 | } |
1436 | |
1437 | O resolve() { ret o; } |
1438 | O getError() { |
1439 | if (o != null) { |
1440 | O error = callOpt(o, 'getError); |
1441 | if (error != null) ret error; |
1442 | } |
1443 | ret super.getError(); |
1444 | } |
1445 | |
1446 | toString { |
1447 | ret "DynModule " + moduleID + "/" + shortenClassName(_className); |
1448 | } |
1449 | |
1450 | void setError(Throwable e) { |
1451 | if (o != null && isTrue(callOpt(o, 'setError, e))) ret; |
1452 | super.setError(e); |
1453 | } |
1454 | |
1455 | Pt getMinSize() { |
1456 | ret shallowCloneToClass Pt(callOpt(o, 'minimumSize)); |
1457 | } |
1458 | } // END CONCEPT DYNAMICMODULE |
1459 | |
1460 | /*static L resolvedModules() { |
1461 | new L l; |
1462 | for (Module m : onModules()) |
1463 | l.add(m.resolve()); |
1464 | ret l; |
1465 | }*/ |
1466 | |
1467 | static S moduleID(Module m) { |
1468 | ret m == null ? null : m.moduleID(); |
1469 | } |
1470 | |
1471 | static O resolveModule(O m) { |
1472 | ret m instanceof Module ? m/Module.resolve() : m; |
1473 | } |
1474 | |
1475 | static S makeModule(Class<? extends Module> moduleClass) { |
1476 | ret makeModule(shortClassName(moduleClass)); |
1477 | } |
1478 | |
1479 | static S makeModule(S moduleLibID) { |
1480 | ret makeOrShowModule(moduleLibID, false); |
1481 | } |
1482 | |
1483 | static S makeOrShowModule(S moduleLibID) { |
1484 | ret makeOrShowModule(moduleLibID, true); |
1485 | } |
1486 | |
1487 | sS makeOrShowModule_early(S moduleLibID) { |
1488 | ret makeOrShowModule_early(moduleLibID, true); |
1489 | } |
1490 | |
1491 | sS makeOrShowModule(fS moduleLibID, final bool orShow) { |
1492 | ret evalInQ(systemQ, func -> S { // XXX - changed 2019/07/10 |
1493 | makeOrShowModule_impl(moduleLibID, orShow) |
1494 | }); |
1495 | } |
1496 | |
1497 | // add to beginning of system queue |
1498 | sS makeOrShowModule_early(fS moduleLibID, bool orShow) { |
1499 | ret evalInQ_first(systemQ, func -> S { |
1500 | makeOrShowModule_impl(moduleLibID, orShow) |
1501 | }); |
1502 | } |
1503 | |
1504 | sS makeOrShowModule_impl(fS moduleLibID, final bool orShow) { |
1505 | // makes dynamic & static modules |
1506 | |
1507 | if (isIdentifier(moduleLibID)) |
1508 | ret moduleID(makeOrShowStaticModuleOfType(moduleLibID, orShow)); |
1509 | |
1510 | L<S> l = splitAtSlash(moduleLibID); |
1511 | if (!isSnippetID(first(l))) |
1512 | fail("Unknown module lib ID: " + moduleLibID); |
1513 | |
1514 | |
1515 | // TODO: handle dm_require cycles |
1516 | //if (makingModuleLibIDs.contains(moduleLibID)) |
1517 | //temp tempAdd(makingModuleLibIDs, moduleLibID); |
1518 | |
1519 | S snippetID = fsI(first(l)), className = second(l); |
1520 | S classNameSuffix = className == null ? null : "$" + className; |
1521 | DynamicModule m = firstThat(conceptsWhere DynamicModule(on := true, moduleID := snippetID), |
1522 | mod -> className == null ? mod._className == null : endsWith(mod._className, classNameSuffix)); |
1523 | if (m == null) { |
1524 | Class c = hotwireModule_withSharing(snippetID); |
1525 | S fullClassName = c.getName() + classNameSuffix; |
1526 | printVars(+snippetID, +fullClassName, +classNameSuffix, +c); |
1527 | m = cregister(DynamicModule(snippetID, fullClassName, c)); |
1528 | print("Made module: " + m.id); |
1529 | vmBus_send('moduleLoaded, m); |
1530 | } |
1531 | if (orShow) showModule(m); else startModule(m); |
1532 | ret moduleID(m); |
1533 | } |
1534 | |
1535 | // beforeStart: voidfunc(DynamicModule) |
1536 | sS makeNewModule(fS moduleLibID, final bool show, O... _) { |
1537 | temp tempSetMC(startModule_beforeStart := optPar beforeStart(_)); |
1538 | ret evalInSystemQ(func -> S { |
1539 | print("Loading module " + moduleLibID); |
1540 | |
1541 | if (isIdentifier(moduleLibID)) |
1542 | ret moduleID(makeNewStaticModuleOfType(moduleLibID, show)); |
1543 | |
1544 | L<S> l = splitAtSlash(moduleLibID); |
1545 | if (!isSnippetID(first(l))) |
1546 | fail("Unknown module lib ID: " + moduleLibID); |
1547 | |
1548 | S snippetID = first(l), className = second(l); |
1549 | |
1550 | Class c = hotwireModule_withSharing(snippetID); |
1551 | className = className == null ? null : c.getName() + "$" + className; |
1552 | print(+className); |
1553 | Module m = cregister(DynamicModule(snippetID, className, c)); |
1554 | print("Made module: " + m.id); |
1555 | startModule(m); |
1556 | if (show && !stefansOS_shouldStartMinimized(m)) |
1557 | showModule(m); |
1558 | ret moduleID(m); |
1559 | }); |
1560 | } |
1561 | |
1562 | // dynamic only |
1563 | sS findModuleByLibID(S moduleLibID) { |
1564 | LS l = splitAtSlash(moduleLibID); |
1565 | if (!isSnippetID(first(l))) |
1566 | fail("Unknown module lib ID: " + moduleLibID); |
1567 | |
1568 | S snippetID = first(l), className = second(l); |
1569 | |
1570 | Cl<DynamicModule> list = findConcepts(DynamicModule, on := true, moduleID := snippetID); |
1571 | S classNameSuffix = className == null ? null : "$" + className; |
1572 | DynamicModule m = firstThat(list, mod -> className == null ? mod._className == null : endsWith(mod._className, classNameSuffix)); |
1573 | if (m != null) ret moduleID(m); |
1574 | if (className != null) null; |
1575 | ret moduleID(first(list)); |
1576 | } |
1577 | |
1578 | static Module makeOrShowStaticModuleOfType(S s) { |
1579 | ret makeOrShowStaticModuleOfType(s, true); |
1580 | } |
1581 | |
1582 | static Module makeOrShowStaticModuleOfType(S s, bool orShow) { |
1583 | ret makeOrShowStaticModuleOfType(classForName("main$" + s), orShow); |
1584 | } |
1585 | |
1586 | static Module makeOrShowStaticModuleOfType(Class<? extends Module> c) { |
1587 | ret makeOrShowStaticModuleOfType(c, true); |
1588 | } |
1589 | |
1590 | static Module makeOrShowStaticModuleOfType(Class<? extends Module> c, bool orShow) { |
1591 | final L<? extends Module> l = staticModulesOfExactType(c); |
1592 | Module m = empty(l) ? nu(c) : first(l); |
1593 | if (orShow) showModule(m); else startModule(m); |
1594 | ret m; |
1595 | } |
1596 | |
1597 | static Module makeNewStaticModuleOfType(S type, bool show) { |
1598 | Class c = classForName("main$" + type); |
1599 | Module m = cast nu(c); |
1600 | if (show) showModule(m); else startModule(m); |
1601 | ret m; |
1602 | } |
1603 | |
1604 | //!include once #1016217 // Sticky Libs |
1605 | !include once #1020744 // Sticky Libs & Src Libs |
1606 | |
1607 | static Class hotwireModule(S snippetID) { |
1608 | hotwire_autoStickyLibs(); |
1609 | ret hotwire(snippetID, lambda1 mainClassNameForClassLoader); |
1610 | } |
1611 | |
1612 | static Class hotwireModule_withSharing(S snippetID) { |
1613 | Class c = null; |
1614 | if (useCodeSharing) { |
1615 | c = findLoadedCodeBySnippetID(snippetID); |
1616 | if (c != null) |
1617 | print("SHARING code for " + snippetID); |
1618 | } |
1619 | if (c == null) |
1620 | c = hotwireModule(snippetID); |
1621 | ret c; |
1622 | } |
1623 | |
1624 | // Make modules print with their module ID |
1625 | |
1626 | set flag hotwire_copyOver_extend. |
1627 | svoid hotwire_copyOver_extend(Class c) { |
1628 | S progID = getProgramID(c); |
1629 | if (nempty(progID) && fieldType(c, 'print_log) == Appendable.class) |
1630 | setOpt(c, 'print_log, makeSubModulePrint(c, progID)); |
1631 | } |
1632 | |
1633 | static swappable _SubModulePrint makeSubModulePrint(Class c, S progID) { |
1634 | _SubModulePrint p = new("[" + progID + "] "); |
1635 | p.makePrefix = () -> |
1636 | showTimeInPrintLog ? "[" + progID + " " + timeWithMilliseconds() + "] " : p.prefix; |
1637 | ret p; |
1638 | } |
1639 | |
1640 | sbool isLoading() { |
1641 | ret eq(systemStatus!, "loading"); |
1642 | } |
1643 | |
1644 | sbool isShuttingDown() { |
1645 | ret eq(systemStatus!, "shutting down"); |
1646 | } |
1647 | |
1648 | svoid doInGlobalContext(final Runnable r) { |
1649 | final new Flag flag; |
1650 | systemQ.add(r { |
1651 | callF(r); |
1652 | flag.raise(); |
1653 | }); |
1654 | flag.waitUntilUp(); |
1655 | } |
1656 | |
1657 | !include once #1015842 // SavedSessions |
1658 | !include once #1015885 // Standard Modules |
1659 | !include once #1015959 // More Standard Modules |
1660 | |
1661 | please include function renderConcept. |
1662 | please include function restart. |
1663 | |
1664 | svoid setLookAndFeel() { |
1665 | if (cic(mainArgs, "-nolaf")) ret; |
1666 | new Matches m; |
1667 | S laf = or2(getLAF(), main.laf); |
1668 | if (isSnippetID(laf)) |
1669 | runDependent(laf); |
1670 | else if (eq(laf, 'webLAF)) |
1671 | installWebLAF(); |
1672 | else if (eq(laf, 'nimbus)) |
1673 | nimbus(); |
1674 | else if (eq(laf, 'jtattoo)) |
1675 | jtattoo_mcWin(); |
1676 | else if (eq(laf, 'platform)) |
1677 | systemLAF(); |
1678 | else if (eq(laf, 'substance)) |
1679 | call(hotwire(#1025722), 'substance); |
1680 | else if (startsWith_trim(laf, "substance ", m)) |
1681 | call(hotwire(#1025722), 'substance, $1); |
1682 | else |
1683 | print("Unknown LAF: " + laf); |
1684 | |
1685 | pcall { |
1686 | S scale = trim(loadTextFile(javaxDataDir("os-font-scale.txt"))); |
1687 | if (nempty(scale)) |
1688 | swingFontScale(parseDouble(scale)); |
1689 | } |
1690 | } |
1691 | |
1692 | please include function myTranspilationDate. |
1693 | |
1694 | // should happen in swing thread |
1695 | svoid setActiveModule(Module m) { |
1696 | if (activeModule != m) { |
1697 | activeModule = m; |
1698 | vmBus_send('newActiveModule, m); |
1699 | } |
1700 | } |
1701 | |
1702 | static O unwrappedActiveModule() { |
1703 | ret unwrapDynamicModule(activeModule); |
1704 | } |
1705 | |
1706 | concept TopInput { |
1707 | S text; |
1708 | bool quickSearchesEnabled = true; |
1709 | } |
1710 | |
1711 | concept LAF { |
1712 | S laf; // 'platform etc. or module ID |
1713 | } |
1714 | |
1715 | svoid nohupJavax(S javaxArgs) { |
1716 | nohupJavax(javaxArgs, javaxDefaultVMArgs()); |
1717 | } |
1718 | |
1719 | sbool cleanedUp; |
1720 | |
1721 | svoid nohupJavax(S javaxArgs, S vmArgs) { |
1722 | if (desktop != null && !cleanedUp) pcall { fullScreenOff(); } |
1723 | directNohupJavax(javaxArgs, vmArgs); |
1724 | } |
1725 | |
1726 | sbool isDevVersion() { |
1727 | ret neq(programID(), #1016478); |
1728 | } |
1729 | |
1730 | svoid startOtherVersion { |
1731 | nohupJavax(isDevVersion() ? #1016478 : #1024932); |
1732 | } |
1733 | |
1734 | sS otherVersionName() { |
1735 | ret isDevVersion() ? "v6" : "v7"; |
1736 | } |
1737 | |
1738 | sS restoreModule(S structure) { |
1739 | if (structure == null) null; |
1740 | |
1741 | print(shorten(500, structure)); |
1742 | |
1743 | O mod = safeUnstructure(structure); |
1744 | if (mod instanceof Map) |
1745 | mod = get((Map) mod, 'module); |
1746 | |
1747 | S shortName = dynShortName(mod); |
1748 | if (!eq(shortName, "DynamicModule")) |
1749 | fail("Can't restore static modules yet [" + shortName + "]"); |
1750 | |
1751 | S snippetID = getString(mod, "moduleID"); |
1752 | S className = getString(mod, "_className"); |
1753 | |
1754 | print("Restoring " + snippetID + "/" + className); |
1755 | |
1756 | Class c = hotwireModule_withSharing(snippetID); |
1757 | DynamicModule m = cregister(DynamicModule(snippetID, className, c)); |
1758 | copyFields(mod, m, 'iconID); |
1759 | m.frameRect = (Rect) restruct(getOpt(m, 'frameRect)); |
1760 | m.oStruct = getString(mod, "oStruct"); |
1761 | showModule(m); |
1762 | ret moduleID(m); |
1763 | } |
1764 | |
1765 | sS moduleStructForDuplication(DynamicModule m) { |
1766 | if (m == null) null; |
1767 | m.persistContents(); |
1768 | S struct = struct(m); |
1769 | fO resolved = resolveModule(m); |
1770 | |
1771 | if (hasMethod(resolved, '_modifyStructForDuplication, struct)) |
1772 | struct = jreplace_first_dyn(struct, "oStruct=*", func(LS tok, int i) -> S { |
1773 | S s = unquote(tok.get(i+4)); |
1774 | s = (S) callOpt(resolved, '_modifyStructForDuplication, s); |
1775 | if (s == null) fail("Module does not want to be duplicated"); |
1776 | ret "oStruct=" + quote(s); |
1777 | }); |
1778 | |
1779 | ret struct; |
1780 | } |
1781 | |
1782 | sS duplicateModule(DynamicModule m) { |
1783 | ret restoreModule(moduleStructForDuplication(m)); |
1784 | } |
1785 | |
1786 | static O dm_current_mandatory() { fail(); } |
1787 | |
1788 | // for modules |
1789 | please include function mechList_opt_raw. |
1790 | please include function mechList_clearCache. |
1791 | please include function mechLists_clearCache. |
1792 | |
1793 | // This is only answered from localhost |
1794 | answer { |
1795 | if "is stefan's os" ret "yes"; |
1796 | |
1797 | if "show module * with params *" { |
1798 | ret dm_showModuleWithParams(unstructString($1), unstructObjectArray($2)); |
1799 | } |
1800 | |
1801 | if (swic(s, "restore module:", m)) |
1802 | ret ok2(restoreModule(m.rest())); |
1803 | |
1804 | if "swing latency" { ret str(swingLatency()); } |
1805 | |
1806 | if "activate frames" { |
1807 | awt { activateMyFrames(); } |
1808 | ret "OK"; |
1809 | } |
1810 | |
1811 | if "program id" ret programID(); |
1812 | if "main program id" ret mainProgramID(); |
1813 | |
1814 | if "enable remote control from *" { |
1815 | O mod = getDynModuleByID(makeOrShowModule("#1017127/RemoteControlled")); |
1816 | call(mod, 'setFields, new O[] {new O[] {controllingComputers := $1, enabled := true}}); |
1817 | ret "OK"; |
1818 | } |
1819 | |
1820 | if "stack traces" |
1821 | ret renderAllThreadsWithStackTraces(); |
1822 | } |
1823 | |
1824 | srecord Service(O module, O worker) {} |
1825 | |
1826 | static new MultiMap<S, Service> registeredServices; |
1827 | |
1828 | static bool callService(S name, O... args) { |
1829 | for (Service service : cloneList(registeredServices.get(name))) |
1830 | if (isTrue(pcallF(service.worker, name, args))) true; |
1831 | false; |
1832 | } |
1833 | |
1834 | static void registerService(O module, S name, O service) { |
1835 | registeredServices.put(name, Service(module, service)); |
1836 | } |
1837 | |
1838 | static void unregisterService(O module, S name, O service) { |
1839 | registeredServices.remove(name, Service(module, service)); |
1840 | } |
1841 | |
1842 | static O dm_os() { ret main.class; } |
1843 | |
1844 | please include function robot_keyPress. |
1845 | please include function robot_keyRelease. |
1846 | please include function robot_safetyKeyReleaser. |
1847 | |
1848 | svoid showCurrentModuleMenu { |
1849 | swing { |
1850 | showInternalFramePopupMenu(desktop.getSelectedFrame()); |
1851 | } |
1852 | } |
1853 | |
1854 | svoid inSystemQ(Runnable r) { |
1855 | systemQ.add(r); |
1856 | } |
1857 | |
1858 | svoid reloadModuleInBackground(final DynamicModule m) { |
1859 | if (m == null) ret; |
1860 | vmBus_send reloadingModule(m); |
1861 | inSystemQ(r { m.reload_impl() }); |
1862 | } |
1863 | |
1864 | svoid deleteModuleInBackground(final DynamicModule m) { |
1865 | if (m == null) ret; |
1866 | inSystemQ(r { deleteModule(m) }); |
1867 | } |
1868 | |
1869 | svoid restart { |
1870 | if (restarter_override != null) |
1871 | ret with callF(restarter_override); |
1872 | restartWithDefaultVMArgs(); |
1873 | sleep(); |
1874 | } |
1875 | |
1876 | static Component makeStandardReloadingComponent(Module m) { |
1877 | ret jcenteredlabel("Reloading..."); |
1878 | } |
1879 | |
1880 | sbool classLoadedInOtherModule(Class mainClass, Module mod) { |
1881 | for (DynamicModule m) |
1882 | if (m != mod && mainClass(m.o) == mainClass) |
1883 | true; |
1884 | false; |
1885 | } |
1886 | |
1887 | static Class findLoadedCodeBySnippetID(S snippetID) { |
1888 | for (Module m : onModules()) |
1889 | if (m cast DynamicModule) |
1890 | if (sameSnippetID(m.moduleID, snippetID) && m.c != null) |
1891 | ret m.c; |
1892 | null; |
1893 | } |
1894 | |
1895 | svoid cleanKill { |
1896 | setOpt(javax(), cleanKill_verbose := true); |
1897 | cleanKillVM(); |
1898 | } |
1899 | |
1900 | sS moduleIDAndName(Module m) { |
1901 | ret m == null ? "-" : m.id + " - " + rcall_pcall moduleName(m); |
1902 | } |
1903 | |
1904 | sbool hideFeature(S name) { |
1905 | ret contains(hideFeatures, name); |
1906 | } |
1907 | |
1908 | sS featureMenuItem(S name) { |
1909 | ret featureMenuItem(name, name); |
1910 | } |
1911 | |
1912 | sS featureMenuItem(S feature, S name) { |
1913 | ret hideFeature(feature) ? null : name; |
1914 | } |
1915 | |
1916 | sS osName() { ret or2(osName, "Stefan's OS " + version()); } |
1917 | |
1918 | sS version() { ret ai_versionFromName(programName()); } |
1919 | |
1920 | static IF0<Bool> standardOSExitConfirm() { |
1921 | ret () -> confirmOKCancel("Really exit " + osName() + "?"); |
1922 | } |
1923 | |
1924 | svoid setLAF(S laf) { |
1925 | cset(uniq(LAF), +laf); |
1926 | } |
1927 | |
1928 | sS getLAF() { |
1929 | ret getString laf(conceptWhere(LAF)); |
1930 | } |
1931 | |
1932 | static TopInput topInputConcept() { |
1933 | ret uniq(TopInput); |
1934 | } |
1935 | |
1936 | sbool quickSearchesEnabled() { |
1937 | ret topInputConcept().quickSearchesEnabled; |
1938 | } |
1939 | |
1940 | svoid useLastSessionBackup { |
1941 | restoreNextToLastConceptsBackup(dbProgramID()); |
1942 | restart(); |
1943 | } |
1944 | |
1945 | static Settings settings() { ret uniq(Settings); } |
1946 | |
1947 | concept Settings { |
1948 | S backgroundMode = "fit"; |
1949 | Color backgroundColor = Color.white; |
1950 | } |
1951 | |
1952 | svoid setBackgroundMode(S backgroundMode) { cset(settings(), +backgroundMode); } |
1953 | svoid setBackgroundColor(Color backgroundColor) { cset(settings(), +backgroundColor); } |
1954 | |
1955 | svoid subConnectorToChannel(S channel) { |
1956 | connector.sub(channel); |
1957 | } |
Began life as a copy of #1016005
download show line numbers debug dex old transpilations
Travelled to 96 computer(s): abfyfbgggack, aexrvlgyxxhu, aijbjpqedjjc, aoiabmzegqzx, axwnutwaxmlh, ayivmpnvhhik, bhatertpkbcr, bngzkrcgfjus, btvdylkaqoum, cbybwowwnfue, cecjewutwwoy, cfunsshuasjs, cnewtswnjcpl, dbzfplsxganw, djztyncnmsck, dmudagwnpltw, eiwvkucnqnjw, ekrmjmnbrukm, elvireockksu, fpbaligaclcw, fwldxygvxlem, gfcwnmfwchyu, gwrvuhgaqvyk, hhusmcjygydo, hpgrupgrauku, ilgbwaciyqrp, inmhkjdpuplp, irmadwmeruwu, ishqpsrjomds, iveijnkanddl, ixlofvyxkrco, jatrsapfxtty, jchfcwwgaovw, jcllbfdqhrgy, jozkyjcghlvl, jsbwwwyklurv, jtubtzbbkimh, kanivhkedcyu, keakywteguii, ktbwgngfmivo, kwdqxmbuyord, lastaxpxduqo, lhhfttygyvev, lpdgvwnxivlt, lqnftawlhpir, mowyntqkapby, mplzucoataeu, mqqgnosmbjvj, nazvggbglmsf, nnlgzsuogrvb, nphwexcmpunv, nrkwhpbvqrop, odhhsrjjbcgr, ofpaelxlmzfo, omdjrrnzbjjv, onxytkatvevr, pcsjzfqafodr, poggnhebuplf, pyentgdyhuwx, pzhvpgtvlbxg, qebrsmobutff, qgvkllrfbgaw, qmtsvidgarql, qnjxhkjyztuv, qqauijjrzgml, qsqiayxyrbia, rjpzpeejafvs, skddmizpvtmy, snaazhdonpnp, svlzptffahhm, tosptxptpfyt, tslmcundralx, tvejysmllsmz, twycvekltchr, ubadkicnhrcp, uhjabitqdyqv, umsdtmbpyecw, unoaxrwscvea, uwohonbpqrts, vdksuejmluqn, veepotesqksf, voixwhikvanr, vouqrxazstgt, vtoaovihiybt, vtpnfdczhzww, vzdtmrzilvqm, wdffvflfhhdx, whxojlpjdney, wpzdwgqboxjy, xjedlqssgqex, xktzprzutyxr, xrpafgyirdlv, xvimeffiorjm, zkbeyrirjpvi, zmkyvqxnmjhp, zpmdaxwphzuy
No comments. add comment
Snippet ID: | #1016478 |
Snippet name: | Stefan's OS v6 |
Eternal ID of this version: | #1016478/528 |
Text MD5: | c57745a0ec98ffbd8dd3e5cc07e58aea |
Transpilation MD5: | 13b3c2fa147171618590e3bfd510f516 |
Author: | stefan |
Category: | javax / stefan's os |
Type: | JavaX source code (desktop) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2022-03-11 01:24:01 |
Source code size: | 59680 bytes / 1957 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 2547 / 22241 |
Version history: | 527 change(s) |
Referenced in: | [show references] |