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