Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

1231
LINES

< > TinyBrain | #1016005 - Stefan's OS v5 [OK]

JavaX source code (desktop) [tags: use-pretranspiled] - run with: x30.jar

Uses 0K of libraries. Click here for Pure Java version (22858L/179K).

!7

sS background = #1101355; // #1009931;
sS backgroundMode = 'fit;
sS mainIconID = #1101346, moduleDefaultIconID = #1101337;
sS laf;
static double minLoadScreenShowingTime = 0;
static JDesktopPane desktop;

static int autoSaveInterval = -10000; // 10 seconds plus slowdown logic
static int persistenceDelayPerModule = 10000; // 10 seconds

static int systemErrorsToKeep = 10;

static ReliableSingleThread rstUpdateModules = new(r { systemQ.add(r updateModules) });

static volatile long updateCycles;
static L systemErrors = synchroList();
static int systemErrors_pointer;
static new Flag stopRequested;
static SimpleLiveValue<S> systemStatus = stringLiveValue("loading");
static Map<O, GhostModule> ghostModules = weakHashMap(); // key is main class (if dynamic module) or instance (if static module)
static Q systemQ;
static AccessControlContext globalACC;
static volatile Module activeModule;
static Set<Module> onActiveModuleChange = synchroHashSet();
static JTextField tfTopInput; // the input field in the OS menu bar
static long tfTopInput_dontSelectAll; // sysNow timestamp
static StefansOS_ConnectToServer connector;
static Map generalMap = synchroMap();

p {
  //laf = 'webLAF; // Let's not generally use it, is sluggish on my machine
  //laf = 'nimbus;
  laf = 'platform;
  
  if (isMac()) laf = 'platform; // because https://github.com/michael-hagen/JTattoo/issues/1
  if (isLinux()) laf = 'jtattoo;
  
  /*if (vmArgs().contains("-XX:+PrintAssembly")) pcall {
    teeSystemOutAndErrToFile(programFile("os.log"));
  }*/
  
  if (!hasClass("x30_pkg.x30_util")) {
    if (!zipFileContains_falseOnError(pathToJavaxJar(), "x30_pkg/x30_util.class"))
      upgradeJavaXAndRestart();
    else
      restart();
  }
  
  _handleException_addHandler(voidfunc(Throwable e) {
    try {
      synchronized(systemErrors) {
        listSet(systemErrors, systemErrors_pointer, e);
        systemErrors_pointer = (systemErrors_pointer+1) % systemErrorsToKeep;
      }
    } catch e2 {
      printStackTrace(e2);
    }
    infoBox("Error: " + exceptionToStringShort(e));
    LastErrors lastErrors = first(staticModulesOfType(LastErrors));
    if (lastErrors != null) lastErrors.addError(e);
  });
  
  timeJumpDetector();
  
  vm_generalMap_put('consoleInUse, true); // bots made by modules should not handle console

  monitorThreadAllocatedMemory();
  
  // Solve deadlocks every 10 to be sure
  doEvery(10000, r printDeadlocksAndSolve);
  
  print("Data dir: " + javaxDataDir());
  vm_setGlobalACC(globalACC = acc_current());
  
  if (swic(activateFramesOf(programIDPlusHome()), "OK")) {
    print("OS already running!");
    cleanKill();
  }
  
  framesBot();
  
  makeBot("Stefan's OS.");
  
  S printLogSize = trim(loadTextFile(javaxDataDir("os-print-log-size.txt")));
  if (isInteger(printLogSize)) printLogMaxChars(parseInt(printLogSize));
  
  vm_generalMap_put('newSwingComponentRegistry, voidfunc(Component c) {
    allAWTComponents_extraList.add(c)
  });
  
  connector = new StefansOS_ConnectToServer;
  connector.start();
  
  //substance();
  final SimpleLiveValue<S> lvDetails = stringLiveValue();
  lvDetails.onChange(r { print(lvDetails!) });
  stefansOS_loadingAnimation_fullScreen = startInFullScreen() && !isWindows() /* bug */;
  final Component loadingAnim = stefansOS_loadingAnimation(r {
    stopRequested.raise()
  }, lvDetails);
  
  try {
    long start = sysNow();
    systemQ = startQ("System Q");
    useDBOf(#1015871);
    lvDetails.set("Loading database");
    db(autoSaveInterval);
    if (!headless()) {
      lvDetails.set("Loading background");
      background = or2(trim(loadTextFile(javaxDataDir("os-background.txt"))), background);
      if (eq(backgroundMode, 'fit))
        desktop = jDesktopPaneWithFitPicture(background);
      else
        desktop = jDesktopPaneWithSkyPicture/*_autoUnload*/(background, Color.black);
      setMainDesktopPane(desktop);
      autoFixDesktopPane(desktop);
      
      installInternalFrameSwitcher_v2(desktop);
    }
    
    long ms = toMS(minLoadScreenShowingTime);
    long remaining = start+ms-sysNow();
    if (remaining <= 0)
      lvDetails.set("Done loading");
    else {
      S seconds = formatDouble(toSeconds(remaining), 1);
      lvDetails.set("Done loading, just showing you the nice animation for " + seconds + " more second" + (eq(seconds, "1") ? "" : "s"));
    }
    if (loadingAnim != null)
      waitUntilSysTimeOrFlag(start+ms, stopRequested);
  } catch e {
    _handleException(e);
    stopRequested.raise();
  }
  
  try {
    bool flag = stopRequested.isUp(); // get before closing animation
    if (flag)
      ret with showFrame("Stop screen",
        centerAndSouthWithMargins(
          jcenteredlabel("Troubleshooting options will go here."),
          jcenteredbuttons(
            "Start Stefan's OS normally", r restart,
            "Switch to " + otherVersionName(), r startOtherVersion,
            "Delete session", disableButtonWhileCalcing(func -> bool {
              if (!fileExists(conceptsFile()))
                ret false with infoBox("Session already empty.");
              if (!confirmOKCancel("Really delete your current session?")) false;
              renameFileToSomeBackupName(conceptsFile());
              infoBox("Session deleted. Starting again.");
              disableAllButtonsInWindow(heldInstance(JButton));
              sleepSeconds(3);
              restart();
              false;
            }))));
  
    //autoRestart();
    thread { serverAutoRestartMD5(); } // just a short ping
    
    pcall { setLookAndFeel(); }
    
    showDesktop();
  } finally {
    disposeWindow(loadingAnim);
  }
    
  initAfterDBLoad();
  hideConsole();
  manualConsole();
  clearConsole();
  if (headless()) sleep();
}

sbool startInFullScreen() {
  ret eq("1", trim(loadTextFile(javaxDataDir("start-os-in-full-screen.txt"))));
}

svoid setStartInFullScreen(bool b) {
  saveTextFile(javaxDataDir("start-os-in-full-screen.txt"), b ? "1" : "0");
}
sbool showDesktop_first = true;

svoid showDesktop {
  if (headless()) ret;
  bool done = false;
  if (showDesktop_first && startInFullScreen()) pcall {
    showFullScreen(desktop);
    done = true;
  }

  if (!done) {
    showMaximizedFrame(desktop);
    titlePopupMenu_top(desktop, voidfunc(JPopupMenu menu) {
      addMenuItems(menu,
        "Update One Cycle", rstUpdateModules,
        "New Session", rThreadPcallMessageBox(r deleteAllModules),
        "Restore Initial Modules", r initialModules,
      );
    });
  }
  
  registerFunctionKey(getFrame(desktop), 1, r { requestFocus(tfTopInput) });
  
  fillMenuBar();
  doNothingOnClose(getFrame(desktop));
  frameIcon(mainIconID, desktop);
  showDesktop_first = false;
  cleanExitOnFrameClose_ifStillInSameFrame(desktop);
}

sbool inFullScreen() {
  ret isFullScreen(desktop);
}

svoid fullScreenOff() {
  if (inFullScreen()) fullScreenOnOff();
}

svoid fullScreenOnOff {
  // Don't screw up window positions while adjusting from/to fullscreen
  autoFixDesktopPane_exclude.add(desktop);
  temp tempAfterwards(r { autoFixDesktopPane_exclude.remove(desktop) });
  
  Window w = getWindow(desktop);
  if (!inFullScreen()) {
    showFullScreen(frameTitle(desktop), desktop);
    pcall { frameIcon(mainIconID, desktop); }
    cleanExitOnFrameClose_ifStillInSameFrame(desktop);
    fillMenuBar();
    setStartInFullScreen(true);
  } else {
    removeFromParent(desktop);
    showDesktop();
    setStartInFullScreen(false);
  }
  
  // Allow closing empty "zombie" windows (why do we have these?)
  final JFrame f = getFrame(desktop);
  onFrameClosing(f, r { if (isEmptyFrame(f)) {
    removeListener();
    disposeWindow(f);
  }});
  
  disposeWindow(w);
  fixDesktopPane(desktop);
}

svoid fillMenuBar() swing {
  // if you use Processing
  JPopupMenu.setDefaultLightWeightPopupEnabled(false);
  
  JMenuBar menuBar = addMenuBar(desktop);
  menuBar.setLayout(new javax.swing.plaf.basic.DefaultMenuLayout(menuBar, BoxLayout.X_AXIS));
  set jmenuItem_newThreads;
  S version = ai_versionFromName(programName());
  final bool dev = isDevVersion();
  S name = "Stefan's OS " + version;
  S home = userHomeIfNotActual();
  S actual = actualUserHome();
  S prefix = addFileSep(actualUserHome());
  print("home: " + home + ", actual: " + actual);
  if (home != null) name += " [" + dropPrefix(prefix, home) + "]";
  addMenu(desktop, trim(name),
    "Screenshot", r stefansOS_screenshot,
    "Full screen on/off", r fullScreenOnOff,
    "Switch to " + otherVersionName(), r {
      innerCleanUp();
      startOtherVersion();
      cleanKill();
    },
    "---",
    "Restart Stefan's OS", r { showConsole(); restart(); },
    "Exit", r cleanKill
  );
  
  addMenu(desktop, "Modules",
    "Other Module...", r stefansOS_addDynamicModuleDialog,
    "---",
    "Welcome Screen", r { makeOrShowModule("#1016067/WelcomeScreen") },
    "Quick Module Search", r addQuickModuleSearch,
    //"Hello (input field for everything)", r { makeOrShowModule("Hello") },
    "Task Bar", r { makeOrShowModule("#1018410/TaskBar") },
    "System Print Log", r { makeOrShowModule("#1016189/SystemPrintLog") },
    jmenu("Internal Types", map(myNonAbstractClassesImplementing(Module), func(final Class c) -> JMenuItem {
      jMenuItem(shortClassName(c), rThread { makeOrShowStaticModuleOfType(c) })
    })),
    "Module Classes", r {  makeOrShowStaticModuleOfType(ModuleClasses) },
  );
  
  addMenu(desktop, "More",
    "Start External JavaX Program...", r stefansOS_startExternalJavaXProgram,
    "---",
    "Find memory leaks (PID: " + getPID() + ")", r stefansOS_findMemoryLeaks,
    "Show console", rThread showConsole);
    
  // Add the fancy stuff
  
  swing {
    JMenuBar menuBar = cast call(getFrame(desktop), 'getJMenuBar);
    if (!containsChildOfType(menuBar, JLabel.class)) {
      //menuBar.add(Box.createHorizontalGlue());
      menuBar.add(Box.createHorizontalStrut(20));
      tfTopInput = jcenteredtextfield(uniq(TopInput).text);
      selectAllOnFocusIf(tfTopInput, func -> bool {
        elapsedTime(tfTopInput_dontSelectAll) >= 2000
      });
      onChange(tfTopInput, r {
        cset(uniq(TopInput), text := getText(tfTopInput))
      });
      onEnter(tfTopInput, r {
        S text = getText(tfTopInput);
        vmBus_send('topInput, text);
        katze_userTyped(text);
      });
      //menuBar.add(jMinWidth(100, tfTopInput));
      menuBar.add(tfTopInput);
      //menuBar.add(jhgrid(null, tfTopInput));
      //menuBar.add(jhgrid(tfTopInput, null));
      menuBar.add(Box.createHorizontalStrut(20));
      menuBar.add(jLiveValueLabel(clockTimeLiveValue()));
      menuBar.add(Box.createHorizontalStrut(6));
    }
  }
}

svoid addQuickModuleSearch {
  makeOrShowModule("#1016702/LoadedModuleSearch");
  makeOrShowModule("#1016932/ServerModuleSearch");
}

static tempDisposeInternalFrame_obj<JLabel> tempBusyAnimation(fS text) {
  ret vmExiting() ? null : tempBusyAnimation(stringLiveValue(text));
}

static tempDisposeInternalFrame_obj<JLabel> tempBusyAnimation(LiveValue<S> text) {
  if (headless()) null;
  final JLabel anim = jBackground(Color.white, jAnimation_liveValueText(#1101316, text));
  swing {
    addInternalFrame_dontSelect.set(true);
    addInternalFrame_layer.set(JLayeredPane.POPUP_LAYER);
    addInternalFrame(desktop, "", null, anim);
    packInternalFrameInTopRightCorner(anim);
    JInternalFrame f = getInternalFrame(anim);
    //print("Have busy animation: " + f + " in " + getParent(f));
  }
  ret tempDisposeInternalFrame(anim);
}

svoid allRegularFixes {
  applyStandardSwingFixes();
  cleanDefunctACCsInAllThreads();
  cleanDefunctACCsInAllSwingComponents();
}

svoid gcWithFixes {
  allRegularFixes();
  gc();
  allRegularFixes();
}

svoid initAfterDBLoad {
  doEvery(30000, r allRegularFixes);
  doEvery(600000, r clearSnippetTitleCacheIfOnline);
  set cleanUp_interruptThreads; 
  
  // for Java Chrome
  classForNameOpt("java.util.prefs.FileSystemPreferences");
  
  SimpleLiveValue<S> lvText = stringLiveValue(jlabel_textAsHTML_center("Restoring Session"));
  temp tempDisposeInternalFrame_obj<JLabel> anim = tempBusyAnimation(lvText);
  setVerticalAlignment(JLabel.TOP, anim.component);
  growInternalFrameLeft(anim.component, 50);
  growInternalFrameSouth(anim.component, 50);
  
  initialModules();
  
  UpdateCycles uc = conceptWhere(UpdateCycles);
  if (uc != null) updateCycles = uc.value;
  
  L<Module> modules = onModules();
  int i = 0;
  for (Module m : modules) {
    ++i;
    lvText.set(jlabel_textAsHTML_center(
      "Starting module " + i + "/" + l(modules) + ":\n"
      + m.moduleName()));
    startModule(m);
  }
  
  addConceptIndex(simpleConceptIndex(rstUpdateModules));
  rstUpdateModules.trigger();

  systemStatus.set("running");
}

svoid initialModules {
  if (empty(onModules()))
    showModule(new DynamicModule(#1016067, 'main$WelcomeScreen));
    
  //makeOrShowStaticModuleOfType(ModuleClasses);
  //makeOrShowStaticModuleOfType(Hello);
  
  if (headless())
    makeOrShowModule("#1016576/ConnectToServer");
  /*else
    makeOrShowModule("#1016123/TaskBar");*/
}

svoid triggerUpdate { rstUpdateModules.trigger(); }

svoid updateModules {
  ++updateCycles;
  for (Module m : onModules())
    updateModule(m);
}

svoid updateModule(Module m) {
  if (m == null) ret;
  temp m.enter();
  pcall { m.update(); }
}

svoid updateModules(final Collection<Module> l) {
  systemQ.add(r {
    for (Module m : unnull(l)) updateModule(m);
  });
}

svoid cleanMeUp {
  autoConsole();
  showConsole();
  systemStatus.set("shutting down");
  temp tempBusyAnimation("Shutting Down");
  for (Module m) if (m.vis != null) pcall {
    m.unvisualize();
  }
  
  for (Module m) cleanUp(m);
  cleanedUp = true;
}

static L<Module> onModules() { ret conceptsWhere(Module, on := true); }

sbool hasModuleWithFields(Class<? extends Module> c, O... params) {
  ret hasConcept(c, concatArrays(new O[] {on := true}, params));
}

svoid startModule(Module m) { ping(); pcall {
  //addIfNotThere(modules, m);
  temp m.enter();
  if (m.started) ret;
  m.started = true;
  print("Starting module " + m.moduleName());
  try {
    m.start();
  } catch e {
    m.setError(e);
    _handleException(e);
  }
  rstUpdateModules.trigger();
  if (m.visible) showModule(m);
}}

static Module showModule(final Module m) {
  ret showModule(m, true);
}

static Module showModule_noFocus(final Module m) {
  ret showModule(m, false);
}

static Module showModule(final Module m, final bool focus) {
if (m == null) ret m;
  startModule(m);
  if (headless()) ret m;
  temp m.enter();
  if (m.vis != null) {
    if (focus && !isLoading())
      activateInternalFrame(m.vis);
    ret m;
  }
  cset(m, visible := true);
  visualizeModule(m);
  if (m.vis != null) swing {
    Rect r = m.frameRect;
    /*if (r == null) r = randomRect(desktop.getWidth(), desktop.getHeight(), 10, 150, 100);
    if (r == null) r = Rect(10, 10, 200, 100);
    print("Showing frame at " + r);*/
    S frameTitle = m.moduleName();
    final JInternalFrame f;
    {
      temp tempSetThreadLocal(addInternalFrame_dontSelect, !focus || isLoading());
      f = showInternalFrame(desktop, frameTitle, r, m.vis);
    }
    if (r == null) centerPackInternalFrame(f);
    f.setDefaultCloseOperation(JInternalFrame.DO_NOTHING_ON_CLOSE);
    
    final WeakReference<JInternalFrame> fRef = new(f);
    final WeakReference<Module> mRef = new(m);
    S idText = str(m.id);
    if (m cast DynamicModule)
      idText += "/" + m.moduleLibID();
    internalFrameTitlePopupMenuItem(f, "Source code [Module ID: " + idText + "]", r-thread { pcall {
      S src = mRef->sourceCode();
      if (src != null) showText(internalFrameTitle(fRef!) + " [Source]", src); else infoBox("No source code found");
    }});
    onInternalFrameIconified(f, r { hideModule(m) });
    onInternalFrameClosing(f, r { deleteModule(m) });
    onInternalFrameActivated(f, r { setActiveModule(m) });
    onInternalFrameDeactivated(f, r { if (activeModule == m) setActiveModule(null) });
    internalFrameIcon(f, or2(m.iconID, moduleDefaultIconID));
    m.enhanceFrame(f);
  }
  ret m;
}

svoid showModules(L<? extends Module> l) {
  for (Module m : unnull(l)) showModule(m);
}

sbool deleteModule(Module m) {
  pcall {
    bool warn = isTrue(callOpt(resolveModule(m), 'warnOnDelete));
    if (warn && !confirmOKCancel("Really delete module " + m + "?"))
      false;
  }
  onActiveModuleChange.remove(m);
  O m2 = unwrapDynamicModule(m);
  ghostModules.put(m == m2 ? m : m2.getClass(), nu(GhostModule,
    name := m.moduleName(),
    created := m.created,
    deleted := now(),
    instance := new WeakReference(m2)));
  pcall { m.unvisualize(); }
  removeConcept(m); // generates oStruct
  pcall {
    S snippetID = m instanceof DynamicModule ? m/DynamicModule.moduleID : "internal_" + shortClassName(m);
    logStructure(deletedModulesLogFile(snippetID), litmap(
      globalID := aGlobalID(),
      deleted := now(),
      module := m));
  }
  triggerUpdate();
  true;
}

svoid visualizeModule(Module m) {
  pcall {
    if (m.vis == null) m.vis = m.visualize();
  }
  pcall {
    if (m.vis == null) m.vis = defaultVisualize(m);
  }
}

svoid hideModule(final Module m) {
  if (m == null) ret;
  temp m.enter();
  cset(m, visible := false);
  pcall { m.unvisualize(); }
}

svoid revisualizeModule(Module m) {
  pcall {
    if (m == null) ret;
    temp m.enter();
    JInternalFrame frame = getInternalFrame(m.vis);
    if (frame == null) ret;
    m.unvisualize1b();
    m.unvisualize2();
    visualizeModule(m);
    setInternalFrameContents(frame, m.vis);
  }
}

abstract concept Module {
  transient JComponent vis;
  transient bool started;
  transient Lock lock = lock();

  bool on = true, visible;
  Rect frameRect;
  S iconID;
  PersistableThrowable error;
  
  //transient Set timers;
  
  JComponent visualize() { null; }
  void unvisualize() {
    pcall { unvisualize1(); }
    pcall { unvisualize2(); }
  }
  void enhanceFrame(JInternalFrame frame) {}
  void start() {}
  void unvisualize1() {
    disposeInternalFrame(getInternalFrame(vis));
    unvisualize1b();
  }
  
  void unvisualize1b() {
    grabFrameRect();
    vis = null;
  }
  void unvisualize2() {}
  void update() {}
  
  void grabFrameRect() {
    JInternalFrame f = getInternalFrame(vis);
    if (f != null)
      cset(this, frameRect := toRect(getBounds(f)));
  }
  
  Rect getFrameRect() {
    grabFrameRect();
    ret frameRect;
  }
  
  void cleanMeUp_started() { started = false; }

  void delete() {
    unvisualize();
    cleanUp(this);
    super.delete();
  }

  S sourceCode() {  
    ret javaxSourceOfMyClass1(shortClassName(this));
  }
  
  // for all modules
  void triggerUpdate { rstUpdateModules.trigger(); }
  
  void setModuleIcon(S iconID) {
    if (eq(iconID, this.iconID)) ret;
    this.iconID = iconID;
    internalFrameIcon(vis, iconID);
  }
  
  O resolve() { ret this; }
  O getError() { ret error; }
  S moduleID() { ret str(id); }
  
  void setError(Throwable e) {
    cset(this, error := persistableThrowable(e));
  }
  
  AutoCloseable enter() { null; }
  
  JComponent vis() { ret vis; }
  
  static bool needsParameters() { false; }
  
  S moduleName() {
    ret humanizeFormLabel(shortClassName(this));
  }
} // END CONCEPT MODULE

static JComponent defaultVisualize(Module m) {
  ret jCenteredMultiLineLabel(renderConcept(m)); 
}

static <A extends Module> A findModule(Class<A> c) {
  ret findConcept(c, on := true);
}

// returns module ID
static S findDynModuleOfType(S type) {
  DynamicModule m = findConcept(DynamicModule, on := true, _className := "main$" + type);
  ret m == null ? null : m.moduleID();
}

sbool moduleTypeIs(Module m, S type) {
  if (m == null) false;
  ret eq(moduleResolvedClassName(m), "main$" + type);
}

sS moduleResolvedClassName(Module m) {
  if (m == null) null;
  if (m instanceof DynamicModule)
    ret m/DynamicModule._className;
  ret className(m);
}

// returns module ID
sS findClosestModuleTo(O searcher, S type) {
  JInternalFrame f = getInternalFrame(dm_getVisualization(searcher));
  if (f == null) null;
  Pt p = centerOfRect(toRect(getBounds(f)));
  new Lowest<S> best;
  for (Module m : onModules()) {
    JInternalFrame f2 = getInternalFrame(m.vis);
    if (f2 == null || f2 == f) continue;
    if (type != null && !moduleTypeIs(m, type)) continue;
    Rect r2 = toRect(getBounds(f2));
    best.put(m.moduleID(), rectPointDistance(r2, p));
  }
  ret best!;
}

static <A extends Module> L<A> staticModulesOfType(Class<A> type) {
  ret conceptsWhere(type, on := true);
}

static <A extends Module> L<A> staticModulesOfExactType(Class<A> type) {
  ret filterByExactType(type, staticModulesOfType(type));
}

static L listModules() {
  ret map unwrapDynamicModule(onModules());
}

static int moduleCount() {
  ret l(onModules());
}

static L visibleModules() {
  ret map unwrapDynamicModule(objectsWhere(onModules(), visible := true));
}

static O unwrapDynamicModule(Module m) {
  ret m instanceof DynamicModule ? or(m/DynamicModule.o, m) : m;
}

sbool moduleStillThere(O o) {
  Module m = o instanceof Module ? o/Module : (Module) get(o, '_host);
  ret isConceptRegistered(mainConcepts, m);
}

static O getDynModuleByID(S moduleID) {
  if (moduleID == null) null;
  ret resolveModule(getConcept(Module, parseLong(moduleID)));
}
  
static Module getModuleByID(S moduleID) {
  if (moduleID == null) null;
  ret getConcept(Module, parseLong(moduleID));
}
  
sS getInterestingString {
  InterestingString m = findModule(InterestingString);
  ret m == null ? getText(tfTopInput) : m.theString;
}

sS modulesSessionGrab() {
  grabFrameRects();
  ret struct(ll(programID(), localDateWithMilliseconds())) + "\n"
    + mainConcepts.xfullgrab();
}

svoid autoSaveModulesSession() {
  infoBox("Auto-saving session.");
  S grab;
  logQuoted(javaxBackupDir(fsI(programID()) + "/auto-saved-sessions.txt"), grab = modulesSessionGrab());
  infoBox("Auto-save done (" + l(grab) + " chars)");
}

svoid deleteAllModules() {
  autoSaveModulesSession();
  deleteConcepts(Module);
  initialModules();
}

svoid restoreModulesSession(S text) {
  autoSaveModulesSession();
  systemStatus.set("shutting down");
  infoBox("Releasing session");
  cleanMeUp();
  cleanUp(mainConcepts);
  mainConcepts = null;
  //sleepSeconds(1);
  infoBox("Loading session");
  systemStatus.set("loading");
  mainConcepts = new Concepts().load(dropFirstLine(text));
  initAfterDBLoad();
  infoBox("Session restore done");
}

svoid grabFrameRects {
  for (Module m : onModules()) m.grabFrameRect();
}

sclass DynamicModule extends Module {
  // moduleID is the snippet ID
  // "className" is taken by DynamicObject; _className == null for old-style dyn module
  S moduleID, _className;
  S oStruct; // serialized dynamic object
  sbool reload_replaceFrame = true;
  
  transient Class c;
  transient O o;
  transient bool contentsDirty = true;
  transient ReliableSingleThread rstPersist = rstWithDelay(persistenceDelayPerModule, r persistContents);
  transient O reloadData; // data held for module during reload

  *() {}
  *(S *moduleID, S *_className) {}
  *(S *moduleID, S *_className, Class *c) {}
  
  static bool needsParameters() { true; }
    
  AutoCloseable enter() {
    ret castForTemp(callOpt(o, 'enter));
  }

  JComponent visualize() {
    temp enter();
    ret (JComponent) callOpt(o, 'visualize);
  }
  
  void enhanceFrame(final JInternalFrame f) {
    internalFrameTitlePopupMenuItem(f, "Reload", rThread(r reload));
    internalFrameTitlePopupMenuItem(f, "Duplicate", rThread { duplicateModule(DynamicModule.this) });
    if (isDevVersion())
      internalFrameTitlePopupMenuItem(f, "Medium Retranspile", rThread { transpileOnServerWithErrorWindow(moduleID, true, r reload) });
    
    {
      temp enter();
      pcallOpt(o, 'enhanceFrame, f);
    }
    internalFrameTitle(f, moduleName());
  }
  
  S moduleLibID() {
    ret moduleID + "/" + dropPrefix("main$", _className);
  }
  
  S moduleName() {
    S name = (S) callOpt(o, 'moduleName);
    if (nempty(name)) ret name;
    S title = snippetTitle_cached(moduleID);
    //ret dropSuffixICTrimOneOf(title, "[Dyn Module]", "[Dyn Module, OK]", "[Dyn Module, shortened]");
    ret dropTrailingSquareBracketStuff(title);
  }
  
  void start() {
    if (moduleID == null) ret;
    if (c == null) c = hotwireModule(moduleID);
    replaceACCInClassLoader(c, globalACC);
    if (oStruct != null) pcall {
      Map<S, O> renames = cast getOpt(c, '_renameClasses);
      //print("Class renames: " + sfu(renames));
      S renamed = migrateClassesInStructureText(oStruct, renames);
      //print("Renamed: " + renamed);
      o = unstructureInRealm(renamed, c);
    }
    if (o == null)
      if (_className == null)
        o = c;
      else
        o = nu(_getClass(c, _className));
    setOptAll(o, _host := this, lock := lock);
    temp enter();
    if (o instanceof Class)
      callMain(o);
    else
      callOpt(o, 'start);
  }
  
  void unvisualize2() { callOpt(o, 'unvisualize); }
  
  void update() { callOpt(o, 'update); }
  
  // XXX - only when called from DynModule
  // (works for now, but should be renamed)
  void _change() {
    super._change();
    contentsDirty = true;
    if (rstPersist != null)
      rstPersist.trigger();
  }
  
  void persistContents() {
    temp enter();
    if (_concepts != null && contentsDirty) {
      contentsDirty = false;
      //oStruct = null;
      pcall {
        if (o != null && !o instanceof Class) {
          cset(this, oStruct := struct(o));
          print("Persisted contents: " + moduleID + " - " + l(oStruct) + " chars");
        }
      }
    }
  }
  
  void cleanMeUp() {
    persistContents();
    cleanUpObjectAndItsMainClass(o);
    o = null;
    c = null;
  }
  
  void reload() {
    if (reloadData == null)
      reloadData = callOpt(o, '_getReloadData);
    
    JInternalFrame frame = getInternalFrame(vis);
    unvisualize1b();
    unvisualize2();
    
    if (o != null)
      ghostModules.put(o.getClass(), nu(GhostModule,
        name := moduleName(),
        created := created,
        deleted := now(),
        instance := new WeakReference(o)));

    cleanUp(this); // also sets started to false
    
    if (frame != null)
      setInternalFrameContents(frame, jcenteredlabel("Reloading..."));
    visible = false;
    startModule(this);
    
    if (reloadData != null) {
      callOpt(o, '_setReloadData, reloadData);
      reloadData = null;
    }
    
    if (frame != null) {
      if (reload_replaceFrame) { // avoids some bugs
        cset(this, frameRect := toRect(getBounds(frame)));
        disposeInternalFrame(frame);
        showModule(this);
      } else {
        cset(this, visible := true);
        visualizeModule(this);
        //print("New content: " + vis);
        setInternalFrameContents(frame, vis);
      }
    }
    rstUpdateModules.trigger();
  }
  
  S sourceCode() {  
    ret loadSnippet(moduleID);
  }
  
  O resolve() { ret o; }
  O getError() {
    if (o != null) {
      O error = callOpt(o, 'getError);
      if (error != null) ret error;
    }
    ret super.getError();
  }
  
  toString {
    ret "DynModule " + moduleID + "/" + shortenClassName(_className);
  }
  
  void setError(Throwable e) {
    if (o != null && isTrue(callOpt(o, 'setError, e))) ret;
    super.setError(e);
  }

}

/*static L resolvedModules() {
  new L l;
  for (Module m : onModules())
    l.add(m.resolve());
  ret l;
}*/

static S moduleID(Module m) {
  ret m == null ? null : m.moduleID();
}

static O resolveModule(Module m) {
  ret m == null ? null : m.resolve();
}

static S makeModule(Class<? extends Module> moduleClass) {
  ret makeModule(shortClassName(moduleClass));
}

static S makeModule(S moduleLibID) {
  ret makeOrShowModule(moduleLibID, false);
}

static S makeOrShowModule(S moduleLibID) {
  ret makeOrShowModule(moduleLibID, true);
}

static S makeOrShowModule(S moduleLibID, bool orShow) {
  // makes dynamic & static modules
  
  if (isIdentifier(moduleLibID))
    ret moduleID(makeOrShowStaticModuleOfType(moduleLibID, orShow));
  
  L<S> l = splitAtSlash(moduleLibID);
  if (!isSnippetID(first(l)))
    fail("Unknown module lib ID: " + moduleLibID);
    
  S snippetID = first(l), className = second(l);
  className = className == null ? null : "main$" + className;
  DynamicModule m = findConcept(DynamicModule, on := true, moduleID := snippetID, _className := className);
  if (m == null) {
    Class c = hotwireModule(snippetID);
    m = DynamicModule(snippetID, className, c);
  }
  if (orShow) showModule(m); else startModule(m);
  ret moduleID(m);
}

static S makeNewModule(S moduleLibID, bool show) {
  print("makeNewModule " + moduleLibID);
  
  if (isIdentifier(moduleLibID))
    ret moduleID(makeNewStaticModuleOfType(moduleLibID, show));
  
  L<S> l = splitAtSlash(moduleLibID);
  if (!isSnippetID(first(l)))
    fail("Unknown module lib ID: " + moduleLibID);
    
  S snippetID = first(l), className = second(l);
  className = className == null ? null : "main$" + className;
  Class c = hotwireModule(snippetID);
  Module m = DynamicModule(snippetID, className, c);
  if (show) showModule(m); else startModule(m);
  ret moduleID(m);
}

// dynamic only
static S findModuleByLibID(S moduleLibID) {
  L<S> l = splitAtSlash(moduleLibID);
  if (!isSnippetID(first(l)))
    fail("Unknown module lib ID: " + moduleLibID);
    
  S snippetID = first(l), className = second(l);
  className = className == null ? null : "main$" + className;
  L<DynamicModule> list = findConcepts(DynamicModule, on := true, moduleID := snippetID);
  DynamicModule m = firstWhere(list, _className := className);
  if (m != null) ret moduleID(m);
  if (className != null) null;
  ret moduleID(first(list));
}

static Module makeOrShowStaticModuleOfType(S s) {
  ret makeOrShowStaticModuleOfType(s, true);
}

static Module makeOrShowStaticModuleOfType(S s, bool orShow) {
  ret makeOrShowStaticModuleOfType(classForName("main$" + s), orShow);
}
  
static Module makeOrShowStaticModuleOfType(Class<? extends Module> c) {
  ret makeOrShowStaticModuleOfType(c, true);
}

static Module makeOrShowStaticModuleOfType(Class<? extends Module> c, bool orShow) {
  final L<? extends Module> l = staticModulesOfExactType(c);
  Module m = empty(l) ? nu(c) : first(l);
  if (orShow) showModule(m); else startModule(m);
  ret m;
}

static Module makeNewStaticModuleOfType(S type, bool show) {
  Class c = classForName("main$" + type);
  Module m = cast nu(c);
  if (show) showModule(m); else startModule(m);
  ret m;
}

!include once #1016217 // Sticky Libs

static Class hotwireModule(S snippetID) {
  hotwire_autoStickyLibs();
  ret hotwire(snippetID); // give each their own local_log
}

// Make modules print with their module ID

set flag hotwire_copyOver_extend.
svoid hotwire_copyOver_extend(Class c) {
  S progID = getProgramID(c);
  if (nempty(progID) && fieldType(c, 'print_log) == Appendable.class)
    setOpt(c, 'print_log, _SubModulePrint("[" + progID + "] "));
}

sbool isLoading() {
  ret eq(systemStatus!, "loading");
}

svoid doInGlobalContext(final Runnable r) {
  final new Flag flag;
  systemQ.add(r {
    callF(r);
    flag.raise();
  });
  flag.waitUntilUp();
}

!include once #1015842 // SavedSessions
!include once #1015885 // Standard Modules
!include once #1015959 // More Standard Modules

please include function renderConcept.
please include function restart.

// do it here, x30 has a bug on old Windows
svoid restart {
  print("\nClean-restarting myself.");
  thread "Clean Restart" {
    call(javax(), 'preKill);
    nohupJavax(smartJoin((S[]) get(javax(), 'fullArgs)));
    System.exit(0);
  }
}

svoid setLookAndFeel() {
  if (eq(laf, 'webLAF))
    installWebLAF();
  else if (eq(laf, 'nimbus))
    nimbus();
  else if (eq(laf, 'jtattoo))
    jtattoo_mcWin();
  else if (eq(laf, 'platform))
    systemLAF();
    
  pcall {
    S scale = trim(loadTextFile(javaxDataDir("os-font-scale.txt")));
    if (nempty(scale))
      swingFontScale(parseDouble(scale));
  }
}

please include function myTranspilationDate.

// should happen in swing thread
svoid setActiveModule(Module m) {
  if (activeModule != m) {
    activeModule = m;
    updateModules(onActiveModuleChange);
  }
}

static O unwrappedActiveModule() {
  ret unwrapDynamicModule(activeModule);
}

concept TopInput {
  S text;
}

svoid nohupJavax(S javaxArgs) {
  nohupJavax(javaxArgs, javaxDefaultVMArgs());
}

sbool cleanedUp;

svoid nohupJavax(S javaxArgs, S vmArgs) {
  if (desktop != null && !cleanedUp) pcall { fullScreenOff(); }
  directNohupJavax(javaxArgs, vmArgs);
}

sbool isDevVersion() {
  ret neq(programID(), #1016005);
}

svoid startOtherVersion {
  nohupJavax(isDevVersion() ? #1016005 : #1016478);
}

sS otherVersionName() {
  ret isDevVersion() ? "v5" : "v6";
}

sS restoreModule(S structure) {
  O mod = safeUnstructure(structure);
  if (mod instanceof Map)
    mod = get((Map) mod, 'module);
    
  S shortName = dynShortName(mod);
  if (!eq(shortName, "DynamicModule"))
    fail("Can't restore static modules yet [" + shortName + "]");
    
  S snippetID = getString(mod, "moduleID");
  S className = getString(mod, "_className");
  
  Class c = hotwireModule(snippetID);
  DynamicModule m = new(snippetID, className, c);
  copyFields(mod, m, 'iconID);
  m.frameRect = (Rect) restruct(getOpt(m, 'frameRect));
  m.oStruct = getString(mod, "oStruct");
  showModule(m);
  ret moduleID(m);
}

sS duplicateModule(DynamicModule m) {
  if (m == null) null;
  m.persistContents();
  ret restoreModule(struct(m));
}

static O dm_current_mandatory() { fail(); }

// for modules
please include function mechList_opt_raw.
please include function mechList_clearCache.
please include function mechLists_clearCache.

// This is only answered from localhost
answer {
  if "enable remote control from *" {
    O mod = getDynModuleByID(makeOrShowModule("#1017127/RemoteControlled"));
    setAll(mod, controllingComputers := $1, enabled := true);
    ret "OK";
  }
}

srecord Service(O module, O worker) {}

static new MultiMap<S, Service> registeredServices;

static bool callService(S name, O... args) {
  for (Service service : cloneList(registeredServices.get(name)))
    if (isTrue(pcallF(service.worker, name, args))) true;
  false;
}

static void registerService(O module, S name, O service) {
  registeredServices.put(name, Service(module, service));
}

static void unregisterService(O module, S name, O service) {
  registeredServices.remove(name, Service(module, service));
}

Author comment

Began life as a copy of #1015871

download  show line numbers  debug dex   

Travelled to 73 computer(s): aexrvlgyxxhu, aoiabmzegqzx, bfejpblmqfdd, bmzxzaunwzbi, bwiwevlxmjkj, cbeiiklavjbb, cbybwowwnfue, cfunsshuasjs, cyrrfadztslw, dywbxgvplihv, edxbcdelwngs, eeixjhdgamgh, fbowqhydredm, fbyhosvjhqjy, feuxfscreywh, frodcriayyox, frwatazqozob, gbhdwhrweqzx, gftuwbxiqecl, gpnrjeoezwdq, gwrvuhgaqvyk, hbmmizwbdwfm, iatjqfrvxxqk, ishqpsrjomds, iuktgvugvsac, jchfcwwgaovw, kfszljdbspfc, kjxtcxvvemlo, kltrethejpux, kwdqxmbuyord, kzigpsqrqhiz, lcyaecmtehqv, lgfgxbumridf, lkfwyxhvodry, lpdgvwnxivlt, mqqgnosmbjvj, nnlgzsuogrvb, nqjakztgkqyz, ntxqecslutbp, nvmkokmjjhov, nwvfkhvmaacz, ohrelafwzpid, onxytkatvevr, ooltfwkuswlc, pisrsjnbinyw, qaafgiputhfz, rpaqqzwldebx, saqluqpkpfgs, sdykldobndnn, sedqhsndipkr, sjeytbqwrssw, swgouadsasaq, thuhawujahgc, tslmcundralx, tvejysmllsmz, udarphwuvilk, vfeiephztmcq, vkeewgkvfzvn, vpdjybntlxhb, vujiipfktnfq, vvsymedkkoqj, wdffvflfhhdx, wiitrlbbxolh, wtpqxftdxdrq, xdkjfzaehixp, xhdjdmyusaap, xjmwwpwwerjm, yhwfxiudbhlz, ynhcxhpejwih, yoeioefyhmua, yugkrbstzyuu, yzulcgujedzj, zkbeyrirjpvi

No comments. add comment

Snippet ID: #1016005
Snippet name: Stefan's OS v5 [OK]
Eternal ID of this version: #1016005/228
Text MD5: 83aa8c459decd7a604c4eebdb3b76d44
Transpilation MD5: b1440db5691cac7df3c0dab6d7f4acee
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: 2018-10-12 16:06:09
Source code size: 35640 bytes / 1231 lines
Pitched / IR pitched: No / No
Views / Downloads: 681 / 4635
Version history: 227 change(s)
Referenced in: [show]