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

1513
LINES

< > BotCompany Repo | #1022729 // Stefan's OS v6 - copy for transpiler test

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

Download Jar. Uses 1177K of libraries. Click here for Pure Java version (27941L/221K).

!759

set flag InOSCore.
set flag NotifyingPrintLog.

sS defaultBackground = #1101488; //#1101303; //#1101465; //#1101438; //#1101355; // #1009931;
sS background = defaultBackground;
sS backgroundMode = 'fit;
sS mainIconID = #1101432, moduleDefaultIconID = #1101337;
sS laf;
static double minLoadScreenShowingTime = 2;
sbool loadBackgroundLater = true;
sbool showLoadingScreen = false;
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) });
sS lastTopInput;
static ReliableSingleThread rstTopInputChanged = rstWithDelay(250, r {
  S s = getText(tfTopInput);
  if (neq(lastTopInput, s))
    vmBus_send('topInputChanged, lastTopInput = s);
});

static volatile long updateCycles;
static L systemErrors = synchroList();
static int systemErrors_pointer;
static new Flag stopRequested;
static SimpleLiveValue<S> systemStatus = stringLiveValue("loading");
static bool firstModuleShown;
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 JTextField tfTopInput; // the input field in the OS menu bar
static long tfTopInput_dontSelectAll; // sysNow timestamp
static StefansOS_ConnectToServer connector;
static Map generalMap = synchroMap();
static L<Component> trayAreaComponents = synchroList();
sbool printOnPersistContents, verboseCleanUp;
static JMenuBar menuBar;
sbool katze_send = true, katze_sendTyped;
sO makeReloadingComponent; // F1<Module, Component>
static long startTime;

// if you want other initial modules
sO initialModules_override; // VF1<OS reference>

static Runnable restarter_override;

p {
  startTime = sysNow();
  vm_generalMap_put(stefansOS := mc());
  
  if (!headless()) showControls(jbutton("TROUBLESHOOTING", r { stopRequested.raise() }));
  noRegularGC(); // not while we're loading
  
  if (onLocallyInferiorJavaX()) {
    print("Restarting to use standard JavaX");
    restart();
  }
  
  checkMaxWindowBoundsBug();
  
  if (!eq("0", trim(loadTextFile(javaxDataDir("compile-on-server")))))
    set hotwire_compileOnServer;
  
  /*if (isLinux() && isRoot())
    addToDefaultVMArgs("-XX:ThreadPriorityPolicy");*/
    
  if (java10OrHigher()) {
    addStandardAddOpensFlags();
    addPermitIllegalAccessesFlag();
    if (!hasPermitIllegalAccessesFlagInCurrentVM()) {
      print("RESTARTING with proper JDK 11 arguments");
      restart();
    }
  }
  
  if (java8OrHigher())
    addToDefaultVMArgs(smallHeapArgs());
  
  //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 (isMac()) vmGeneralMap_set('iconifyBroken, true);
  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 = showLoadingScreen ? stefansOS_loadingAnimation(r {
    stopRequested.raise()
  }, lvDetails) : null;
  
  try {
    long start = sysNow();
    systemQ = startQ("System Q");
    useDBOf(#1015871);
    lvDetails.set("Loading database");
    db(autoSaveInterval);
    if (!headless()) {
      // if you use Processing
      JPopupMenu.setDefaultLightWeightPopupEnabled(false);
  
      lvDetails.set("Loading background");
      background = or2(trim(loadTextFile(javaxDataDir("os-background.txt"))), background);
      if (!isSnippetID(background))
        background = fileToURI(new File(background));
      try {
        if (eq(backgroundMode, 'fit))
          desktop = loadBackgroundLater
            ? jDesktopPaneWithFitPicture_smooth_cacheScaled_loadLater(background)
            : jDesktopPaneWithFitPicture_smooth_cacheScaled(background);
        else
          desktop = jDesktopPaneWithSkyPicture/*_autoUnload*/(background, Color.black);
      } catch print e {
        desktop = jDesktopPaneWithFitPicture_smooth(defaultBackground);
      }
      setMainDesktopPane(desktop);
      autoFixDesktopPane(desktop);
      
      // Allow frame switching from AI bar & similar components
      installInternalFrameSwitcher_v3(desktop).shouldSwitch =
        func -> bool { sameComponentOrDeepChildOf(getFocusOwner(), menuBar) };
    }
    
    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, but will wait if you hit the troubleshooting button 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("More 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;
              cleanMeUp_concepts();
              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();
  setOpt(javax(), regularGC_firstDelay := 60000);
  call(javax(), 'regularGC);
  if (!headless()) {
    final NotTooOften hourlyGC = onlyEveryHour();
    setOpt(javax(), regularGC_condition := func -> bool {
      if (hourlyGC! || isInForeground(desktop))
        ret true with print("GC");
      else
        ret false with print("Skipping GC (not in foreground)");
    });
  }
  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;
  
  S title = programName();
  S subDir = javaxVirtualSpaceName();
  if (subDir != null) title = "[" + subDir + "] " + title;

  if (showDesktop_first && startInFullScreen()) pcall {
    showFullScreen(title, desktop);
    done = true;
  }

  if (!done) {
    showMaximizedFrame(title, desktop);
    titlePopupMenu_top(desktop, voidfunc(JPopupMenu menu) {
      addMenuItems(menu,
        "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 updateMenuBar() swing {
  //temp tempRememberFocusedComponent();
  JMenuBar mb = getMenuBar(desktop);
  if (mb == null) {
    mb = addMenuBar(desktop);
    mb.setLayout(new javax.swing.plaf.basic.DefaultMenuLayout(menuBar, BoxLayout.X_AXIS));
  } 
  keepComponentsByPred(mb, func(Component c) -> bool {
    c instanceof JMenu || c == tfTopInput
  });
  //clearMenuBar();
  fillMenuBar();
}

svoid fillMenuBar() swing {
  menuBar = addMenuBar(desktop);
  set jmenuItem_newThreads;
  S version = ai_versionFromName(programName());
  final bool dev = isDevVersion();
  S name = "Stefan's OS " + version;
  //S subDir = userHomeSubDirName();
  //if (subDir != null) name += " [" + subDir + "]";
  addMenu(desktop, trim(name),
    "Screenshot", r stefansOS_screenshot,
    "Full screen on/off", r fullScreenOnOff,
    "Switch to " + otherVersionName(), r {
      innerCleanUp();
      startOtherVersion();
      cleanKill();
    },
    "System Version", r { makeOrShowModule("#1016442/SystemVersion") },
    "---",
    "Restart Stefan's OS", r { showConsole(); restart(); },
    "Exit", r cleanKill
  );
  
  addMenu(desktop, "Current Module",
    "Show Menu", r showCurrentModuleMenu);
  
  addMenu(desktop, "Modules",
    "Other Module...", r stefansOS_addDynamicModuleDialog,
    "---",
    jDynamicScrollingMenu("All Modules", voidfunc(JPopupMenu menu) {
      for (final Module m : sortedByMethodIC('moduleName, onModules()))
        addMenuItem(menu, m.moduleName(), rThread { showModule(m) });
    }),
    "Welcome Screen", r { makeOrShowModule("#1016067/WelcomeScreen") },
    "Quick Module Search", r addQuickModuleSearch,
    //"Hello (input field for everything)", r { makeOrShowModule("Hello") },
    "Task Bar", r { makeOrShowModule("#1019712/TaskBar_dev") },
    "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) },
  );
  
  // TODO - need to generate menu items differently in enhanceFrame
  //addFullyDynamicMenu(desktop, "Current module",
  
  addMenu(desktop, "More",
    "Start External JavaX Program...", r stefansOS_startExternalJavaXProgram,
    "---",
    "Find memory leaks (PID: " + getPID() + ")", r stefansOS_findMemoryLeaks,
    "Computer ID: " + computerID(), r { copyTextToClipboard_infoBox(computerID()) },
    "Show console", rThread showConsole,
    "Remove moduleless frames", rThread dm_closeModuleLessFrames);
    
  // Add the fancy stuff
  
  JMenuBar menuBar = cast call(getFrame(desktop), 'getJMenuBar);
  
  if (tfTopInput == null) {
    tfTopInput = jcenteredtextfield(uniq(TopInput).text);
    setFontSize(tfTopInput, 16);
    selectAllOnFocusIf(tfTopInput, func -> bool {
      elapsedTime(tfTopInput_dontSelectAll) >= 2000
    });
    onChange(tfTopInput, r {
      cset(uniq(TopInput), text := getText(tfTopInput));
      rstTopInputChanged.trigger();
    });
    onEnter(tfTopInput, r {
      S info = cast generalMap.get('topInputInfo);
      temp dm_generalMap_tempPut(topInputInfo := or2(info, "typed"));
      S text = getText(tfTopInput);
      vmBus_send('topInput, text);
      if (katze_send)
        if (nempty(info))
          katze_userSaid(info, text);
        else if (katze_sendTyped)
          katze_userTyped(text);
    });
  }
    
  if (getParent(tfTopInput) == null) {
    menuBar.add(Box.createHorizontalStrut(20));
    menuBar.add(tfTopInput);
  }
  
  if (!containsChildOfType(menuBar, JLabel.class)) {
    //menuBar.add(Box.createHorizontalGlue());
    menuBar.add(Box.createHorizontalStrut(5));
    menuBar.add(onClick(setToolTip([[Simulate pressing Enter key in input field to the left ("AI bar")]], jimage(#1101426)), r { simulateEnter(tfTopInput) }));
    //menuBar.add(jhgrid(null, tfTopInput));
    //menuBar.add(jhgrid(tfTopInput, null));
    menuBar.add(Box.createHorizontalStrut(20));
    for i over trayAreaComponents: {
      Component c = trayAreaComponents.get(i);
      continue if c == null;
      menuBar.add(c);
      menuBar.add(Box.createHorizontalStrut(i == l(trayAreaComponents)-1 ? 20 : 6));
    }
    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 final tempDisposeInternalFrame_obj<JLabel> anim = tempBusyAnimation(lvText);
  if (anim != null) {
    onResizeAndNow(anim.component, r {
      setVerticalAlignment(
        anim.component.getHeight() >= 150 ? JLabel.CENTER : JLabel.TOP,
        anim.component)
    });
    growInternalFrameLeft(anim.component, 50);
    growInternalFrameSouth(anim.component, 50);
  }
  
  initialModules();
  
  UpdateCycles uc = conceptWhere(UpdateCycles);
  if (uc != null) updateCycles = uc.value;
  
  stefansOS_installQuickSearchHelper();
  
  L<Module> modules = startOrder(onModules());
  int i = 0;
  for (Module m : modules) {
    if (isShuttingDown()) ret;
    ++i;
    lvText.set(jlabel_textAsHTML_center(
      "Starting module " + i + "/" + l(modules) + ":\n"
      + m.moduleName()));
    startModule(m);
  }
  
  /*addConceptIndex(simpleConceptIndex(rstUpdateModules));
  rstUpdateModules.trigger();*/

  if (isShuttingDown()) ret;
  systemStatus.set("running");
  print("== OS BOOTED IN " + iceil(elapsedSeconds(/*vmStartTime_sys()*/startTime)) + " SECONDS ==");
}

static L<Module> startOrder(L<Module> modules) {
  ret sortedByComparator(
    combineComparators(
      main.<Module> descFieldComparator('visible),
      main.<Module> fieldComparator('zOrder)),
    modules);
}

svoid initialModules {
  if (initialModules_override != null)
    ret with pcallF(initialModules_override, mc());
  
  if (headless()) {
    makeOrShowModule("#1016576/ConnectToServer");
    ret;
  }
    
  if (empty(onModules())) {
    if (isDevVersion())
      showModule(new DynamicModule(#1016081, 'main$WelcomeScreen));
    else
      showModule(new DynamicModule(#1016067, 'main$WelcomeScreen));
    showModule_noFocus(getModuleByID(makeModule("#1018866/SystemPrintLog")));
    showModule_noFocus(getModuleByID(makeModule("#1019954/TaskBar_dev")));
    //makeModule("#1016872/SnippetsDB");
    makeModule("#1016932/ServerModuleSearch");
    makeModule("#1016702/LoadedModuleSearch");
    //makeModule("#1018602/QuickAudioRecord");
    makeModule("#1019326/WitAILastRecording");
    makeModule("#1019400/SpeechRecogConfirmation");
  }
}

svoid triggerUpdate { rstUpdateModules.trigger(); }

// not done anymore
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 saveZOrder {
  for (Module m)
    cset(m, zOrder := getComponentZOrder(getInternalFrame(m.vis)));
}

svoid cleanMeUp {
  saveZOrder();
  autoConsole();
  showConsole();
  killProgram(#1019683); // stop watch dog
  systemStatus.set("shutting down");
  temp tempBusyAnimation("Shutting Down");
  preCleanUp(list(Module));
  for (Module m) {
    if (m.vis != null) pcall {
      m.unvisualize();
    }
    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);
  }
  vmBus_send('moduleStarted, m.moduleID());
  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);
}

svoid runInSystemQAndWait(Runnable r) {
  if (isAWTThread()) ret with callF(r);
  runInQAndWait(systemQ, r);
}

static Module showModule(final Module m, final bool focus) {
  if (m == null) ret m;
  runInSystemQAndWait(r {
    startModule(m);
    if (headless()) ret;
    temp m.enter();
    if (m.vis != null) {
      if (focus && !isLoading())
        activateInternalFrame(m.vis);
      ret;
    }
    csetAndStatusChange(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;
      bool toBack = isLoading() && firstModuleShown;
      bool activate = focus && !toBack;
      {
        temp tempSetThreadLocal(addInternalFrame_toBack, toBack);
        temp tempSetThreadLocal(addInternalFrame_dontSelect, !activate);
        f = showInternalFrame(desktop, frameTitle, r, m.vis);
        set firstModuleShown;
      }
      if (r == null) centerPackInternalFrame(f);
      f.setDefaultCloseOperation(JInternalFrame.DO_NOTHING_ON_CLOSE);
      
      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);
      if (activate) setActiveModule(m);
    }
  });
  ret m;
}

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

sbool deleteModule(final Module m) {
  pcall {
    bool warn = isTrue(callOpt(resolveModule(m), 'warnOnDelete));
    if (warn && !confirmOKCancel("Really delete module " + m + "?"))
      false;
  }
  runInSystemQAndWait(r {
    O m2 = unwrapDynamicModule(m);
    vmBus_send('deletingModule, m2);
    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
    vmBus_send('moduleDeleted, m);
    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);
  }
  vmBus_send('moduleVisualized, m);
}

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

svoid csetAndStatusChange(Module m, O... params) {
  if (cset(m, params) > 0)
    vmBus_send('moduleStatusChange, m, params);
}

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;
  int zOrder;
  S iconID;
  PersistableThrowable error;
  
  //transient Set timers;
  
  JComponent visualize() { null; }
  void unvisualize() {
    pcall { unvisualize1(); }
    pcall { unvisualize2(); }
    vmBus_send('moduleUnvisualized, this);
  }
  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) {
    final WeakReference<JInternalFrame> fRef = new(f);
    final WeakReference<DynamicModule> mRef = new(this);
    S idText = str(id);
    
    if (isTrue(vmGeneralMap_get('iconifyBroken)))
      internalFrameTitlePopupMenuItem(f, "Hide/Minimize", r { hideModule(mRef!) });
    
    idText += "/" + moduleLibID();
    internalFrameTitlePopupMenuItem(f, "Source code [Module ID: " + idText + "]", r-thread { pcall {
      if (empty(mRef->moduleID)) ret with infoBox("No source code found");
      dm_openSnippetInEditor(mRef->moduleID);
    }});
    
    internalFrameTitlePopupMenuItem(f, "Reload", r reload);
    internalFrameTitlePopupMenuItem(f, "Duplicate", rThread { duplicateModule(DynamicModule.this) });
    if (isDevVersion())
      internalFrameTitlePopupMenuItem(f, "Medium Retranspile", rThread { transpileOnServerWithErrorWindow(moduleID, true, r reload) });
    internalFrameTitlePopupMenuItem(f, "Pop Out", r { stefansOS_popOutModule(DynamicModule.this) });
    
    {
      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;
    ret originalModuleName();
  }
  
  S originalModuleName() {
    S title = snippetTitle_cached(moduleID);
    //ret dropSuffixICTrimOneOf(title, "[Dyn Module]", "[Dyn Module, OK]", "[Dyn Module, shortened]");
    ret stefansOS_cleanModuleName(title);
  }
  
  void start() {
    try {
      start_impl();
    } catch e {
      setError(e);
      _handleException(e);
    }
  }
  
  void start_impl {
    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));
          if (printOnPersistContents)
            print("Persisted contents: " + moduleID + " - " + l(oStruct) + " chars");
          callOpt(o, 'onPersisted);
        }
      }
    }
  }
  
  void cleanMeUp() {
    persistContents();
    if (verboseCleanUp)
      print("o: " + className(o) + ". Cleaning up main class: " + mainClass(o));
    cleanUpObjectAndItsMainClass(o);
    o = null;
    c = null;
  }
  
  void reload() {
    reloadModuleInBackground(this);
  }
  
  // don't call directly
  void reload_impl() {
    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, makeReloadingComponent != null ? callF(makeReloadingComponent, this) : makeStandardReloadingComponent(this) );
    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 {
        csetAndStatusChange(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(O m) {
  ret m instanceof Module ? m/Module.resolve() : m;
}

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);
}

sS makeOrShowModule(fS moduleLibID, final bool orShow) {
  ret //evalInQ(systemQ, func -> S {
    makeOrShowModule_impl(moduleLibID, orShow)
  /*})*/;
}

sS makeOrShowModule_impl(fS moduleLibID, final 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);
    vmBus_send('moduleLoaded, m);
  }
  if (orShow) showModule(m); else startModule(m);
  ret moduleID(m);
}

static S makeNewModule(S moduleLibID, bool show) {
  print("Loading module " + 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);
  startModule(m);
  if (show && !isTrue(getOpt(unwrapDynamicModule(m), '_startMinimized)))
    showModule(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
!include once #1020744 // Sticky Libs & Src 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");
}

sbool isShuttingDown() {
  ret eq(systemStatus!, "shutting down");
}

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.

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;
    vmBus_send('newActiveModule, m);
  }
}

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();
  S struct = struct(m);
  fO resolved = resolveModule(m);
  
  if (hasMethod(resolved, '_modifyStructForDuplication, struct))
    struct = jreplace_first_dyn(struct, "oStruct=*", func(LS tok, int i) -> S {
      S s = unquote(tok.get(i+4));
      s = callOpt(resolved, '_modifyStructForDuplication, s);
      if (s == null) fail("Module does not want to be duplicated");
      ret "oStruct=" + quote(s);
    });

  ret restoreModule(struct);
}

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 "swing latency" { ret str(swingLatency()); }
  
  if "activate frames" {
    awt { activateMyFrames(); }
    ret "OK";
  }
  
  if "program id" ret programID();
  
  if "enable remote control from *" {
    O mod = getDynModuleByID(makeOrShowModule("#1017127/RemoteControlled"));
    call(mod, 'setFields, new O[] {new O[] {controllingComputers := $1, enabled := true}});
    ret "OK";
  }
  
  if "stack traces"
    ret renderAllThreadsWithStackTraces();
}

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));
}

static O dm_os() { ret main.class; }

please include function robot_keyPress.
please include function robot_keyRelease.
please include function robot_safetyKeyReleaser.

svoid showCurrentModuleMenu {
  swing {
    showInternalFramePopupMenu(desktop.getSelectedFrame());
  }
}

svoid inSystemQ(Runnable r) {
  systemQ.add(r);
}

svoid reloadModuleInBackground(final DynamicModule m) {
  if (m == null) ret;
  inSystemQ(r { m.reload_impl() });
}

svoid deleteModuleInBackground(final DynamicModule m) {
  if (m == null) ret;
  inSystemQ(r { deleteModule(m) });
}

svoid restart {
  if (restarter_override != null)
    ret with callF(restarter_override);
  restartWithDefaultVMArgs();
  sleep();
}

static Component makeStandardReloadingComponent(Module m) {
  ret jcenteredlabel("Reloading...");
}

Author comment

Began life as a copy of #1016478

download  show line numbers  debug dex  old transpilations   

Travelled to 7 computer(s): bhatertpkbcr, cfunsshuasjs, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1022729
Snippet name: Stefan's OS v6 - copy for transpiler test
Eternal ID of this version: #1022729/3
Text MD5: 200d747d28dda646d8b23e1bd3fe1b4c
Transpilation MD5: f8e626052561cc21d29d629bf7a6fd39
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: 2019-04-03 15:44:45
Source code size: 44699 bytes / 1513 lines
Pitched / IR pitched: No / No
Views / Downloads: 183 / 607
Version history: 2 change(s)
Referenced in: [show references]