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

434
LINES

< > BotCompany Repo | #1033540 // GazelleHost + Stem

JavaX fragment (include) [tags: use-pretranspiled]

lib 1400521 // FlatLAF

set flag PingV3.
set flag NotifyingPrintLog.
set flag SymbolAsString.

// Do the JavaX init
svoid standaloneInit {
  __javax = x30.class;
  x30.__javax = x30.class; // for hotwire
  x30_pkg.x30_util.__setJavaX(x30.class);
  x30.cleanKillMsg = "";
  callOnLoadMethods(mc());
}

concept PrintLogModule > DynPrintLog {
  *() { setModuleName("Print Log"); }
  
  S getPrintLog() {
    ret printLog();
  }
  
  bool useErrorHandling() { false; }
}

concept Stem {
  transient GazelleHost host;
  DynModule module;
  Rect frameRect;
  bool maximized, alwaysOnTop, autoUpdate;
  
  transient JFrame window;
  transient JButton btnMax;
  
  *() {}
  *(GazelleHost *host) {}
  *(GazelleHost *host, DynModule *module) {}
  
  Rect getFrameRect() {
    ret toRect(getBounds(window));
  }
  
  void saveFrameRect {
    setField(frameRect := getFrameRect());
  }
  
  void setAlwaysOnTop(bool alwaysOnTop) {
    this.alwaysOnTop = alwaysOnTop;
    change();
    alwaysOnTop(window, alwaysOnTop);
  }

  void setWindow(JFrame window) {  
    this.window = window;
    if (frameRect != null)  
      setBounds(window, frameRect);
    //onWindowClosing(window, -> host.cleanExit());
    onBoundsChange(window, r saveFrameRect);
    alwaysOnTop(window, alwaysOnTop);
  }
  
  bool isMain() { ret this == host.stem; }
  
  void minimize {
    if (host.trayIcon == null || !isMain())
      minimizeWindow(window);
    else
      hideWindow(window);
  }
  
  void deleteMe {
    printAlsoToSystemOut = true;
    print("deleteMe " + isMain());
    if (isMain()) {
      host.cleanExit();
    } else {
      disposeWindow(window);
      dispose module;
      cdelete(this);
    }
  }
  
  void grabWindowState {
    setField(maximized := !isExtendedStateNormal(window));
  }
  
  void updateBtnMax {
    if (!isShowing(btnMax)) ret;
    grabWindowState();
    setText(btnMax, maximized ? "NORM" : "MAX");
  }
  
  JComponent makeWindowBorderAndTitle(JComponent contents, S title) {
    //ret jCenteredSection_fontSizePlus(10, title, vis);
    
    var icons = jline();
    if (host.allowFrameMaximization) {
      icons.add(btnMax = jbutton("", rThread {
        maximizeOrRestoreFrame(window);
        updateBtnMax();
      }));
      onFirstShowing(btnMax, r updateBtnMax);
    }
    
    icons.add(jbutton("MIN", r minimize));
    icons.add(jbutton("QUIT", rThread {
      if (swingConfirm("Really quit Gazelle?"))
        deleteMe();
    }));
    setHorizontalMarginForAllButtons(icons, 4);
    icons.add(jPopDownButton_noText(flattenToList(
      // restart + update
      
      !isMain() ? null : ll(
        "Restart", rThread { host.restart() },
        "Update Gazelle", rThread { host.upgradeGazelle() },
      jCheckBoxMenuItem_dyn("Auto-Update",
        -> autoUpdate,
        b -> cset(Stem.this, autoUpdate := b)),
      ),
        
      // always on top
      
      "---",
      jCheckBoxMenuItem_dyn("Always on top",
        -> alwaysOnTop,
        alwaysOnTop -> setAlwaysOnTop(alwaysOnTop)),
        
      // debugging + screenshooting gazelle
      
      "---",
      !isMain() ? null : ll(
        "Screenshoot this window", rThread shootWindow,
        "Dump threads", rThread { showText("User threads", renderUserThreadsWithStackTraces()); },
        !isMain() ? null : "Print log", !isMain() ? null : rThread { host.showPrintLog() },
      ),
      
      ccallOpt(module, "popDownItems")
    )));
    
    var actualTitle = fontSizePlus(7, jCenteredLabel(title));
    var spacer = gazelle_wavySpacer();
    var titleBarMain = setOpaqueBackground(host.color1,
      westCenterAndEastWithMargin(
        jImage_scaledToHeight(24, host.trayIconImageID),
        actualTitle,
        setOpaqueBackground(host.color2, spacer));
    
    installWindowDragger(actualTitle);
    installWindowDragger(spacer);
    
    var titleBar = setBackground(host.color2, centerAndEast(
      titleBarMain,
      icons));
    
    var border =
      // createBevelBorder();
      BorderFactory.createLineBorder(host.color1, host.borderSize);
      
    var outerPanel = withBorder(border,
      northAndCenter(titleBar, contents));
      
    installWindowResizeDraggerOnBorder(outerPanel);
    ret outerPanel;
  }

  void startAndShow() {
    module._host = this;
    setOpt_raw(module, +threadPool); // only if the field exists
    setOpt_raw(module, concepts := host.concepts);
    copyLocalLog(module, mc());
  
    var vis, title = unpair makeVisAndTitle();
    printWithMS("Show frame");

    JFrame frame = makeUndecoratedFrame(title, vis);
    setFrameIcon(frame, host.trayIconImageID);
    setWindow(frame);
    showWindow(window);
    if (maximized && host.allowFrameMaximization) maximizeFrame(window);
  }
  
  Pair<JComponent, S> makeVisAndTitle() {
    JComponent vis;
    {
      temp module.enter();
      module.start();
    
      printWithMS("Visualize");
      vis = swing(-> {
        temp module.enter();
        ret module.visualize();
      });
    }
    
    S title = host.windowTitle;
    if (!isMain()) title += appendWithColon(module.moduleName());
    vis = makeWindowBorderAndTitle(vis, title);
    ret pair(vis, title);
  }
  
  void revisualize {
    if (window == null) ret;
    
    pcall {
      module.unvisualize();
    }
    
    var vis, title = unpair makeVisAndTitle();
    setFrameContents(window, vis);
  }
  
  void shootWindow {
    var img = renderComponentToImage(window);
    copyImageToClipboard(img);
    saveInImageDirectoryWithCounter("Gazelle/Gazelle", img);
  }
} // end of Stem

// This replaces the Stefan's OS main class. It is not persisted
transient sclass GazelleHost {
  Stem stem;
  DynModule gazelle;
  
  transient S windowTitle = "November Gazelle v1";
  transient S trayIconImageID = #1103047;
  transient int borderSize = 5;
  transient Color color1 = awtColor("ADD8E6");
  transient Color color2 = awtColor("EEEEEE");
  transient Color color3 = awtColor("A3C0AA");
  transient IF0<DynModule> moduleMaker;
  transient ThreadPool threadPool;
  
  transient TrayIcon trayIcon;
  transient TrayIconLastPosition trayIconLastPosition;
  
  transient Set<S> argsSet;
  
  transient Concepts concepts;
  
  // This caused problems, disabled for now
  transient bool allowFrameMaximization;
  
  *(ThreadPool *threadPool, IF0<DynModule> *moduleMaker) {}

  void trayIconLeftClick {
    activateFrame_v3(mainWindow());
  }
  
  void makeTrayIcon {
    pcall-short {
      trayIcon_imageAutoSize = false;
      trayIcon = installTrayIcon(trayIconImageID, windowTitle,
        r trayIconLeftClick,
        "Show Gazelle", r trayIconLeftClick,
        "Exit Gazelle", r cleanExit
      );
      trayIconLastPosition = new TrayIconLastPosition(trayIcon);
    }
  }
  
  void run(S[] args) {
    try {
      run2(args);
    } catch print e {
      //messageBox(e);
      hideTrayIcon(trayIcon);
      onWindowClosing(-> systemExit(1), getWindow(
        showText_fast_noWrap("Gazelle Error", renderStackTrace(e))));
      //AutoVMExit.install();
    }
  }
  
  void run2(S[] args) {
    argsSet = asSet(args);
    
    if (!argsSet.contains("noflatlaf"))
      com.formdev.flatlaf.FlatLightLaf.setup();
    
    if (contains(args, "profile"))
      profileToConsole(() -> actualMain(args));
    else
      actualMain(args);
      
    if (argsSet.contains("brexit")) System.exit(0);
  }
  
  void actualMain(S... args) {
    vm_generalMap_put(stefansOS := this);
    
    System.out.println(hmsWithColonsAndMS() + ": Init");
    //x30.coreInit();
    
    // Ready to roll
    
    if (containsOneOf(argsSet, "upgrade", "update"))
      ret with upgradeGazelle();
  
    makeTrayIcon();
    
    initAutoUpdate();
    
    // Test classFinder sanity
    
    set flag defaultDefaultClassFinder_debug.
    assertEquals(callF(_defaultClassFinder(), "main$Stem"), Stem.class);

    // Start DB
    
    concepts = newConceptsWithClassFinder(programID);
    concepts.fileLock().lockOrFail();
    concepts.fileLock().deleteOnExit();
    concepts.persist();
    
    print("Concepts loaded: " + map className(allConcepts(concepts));
    
    var stems = findConcepts(concepts, Stem);
    print("Stems in DB: " + l(stems));
    stem = first(stems);
    if (stem == null) {
      print("Starting new module");
      makeModule();
      stem = registerConcept(concepts, new Stem(this, gazelle));
    }
    gazelle = stem.module;

    for (stem : list Stem(concepts)) {
      stem.host = this;
      stem.startAndShow();
    }
    
    printWithMS("Dudadoneski");
  }
  
  void showPrintLog {
    registerConcept(concepts, new Stem(this, new PrintLogModule)).startAndShow();
  }
  
  JFrame mainWindow() {
    ret stem?.window;
  }
  
  O dm_getStem(O moduleOrID) {
    ret stem;
  }
  
  O resolveModule(O moduleOrID) { ret moduleOrID == stem ? gazelle : moduleOrID; }
  
  void cleanExit {
    thread {
      print("Saving DB for exit");
      dispose concepts;
      System.exit(0);
    }
  }
  
  File myJar() { ret getBytecodePathForClass(this); }
  
  void upgradeGazelle {
    File myJar = myJar();
    print(+myJar);
    
    S date = ymdMinusHMS();
    File f = javaxCodeDir("Downloaded Updates/" + "gazelle-" + date + ".jar");
    infoBox("Downloading Update...");
    loadBinaryPageToFile(downloadURL(), f);
    printFileInfo(f);
    if (!isNonEmptySingleZip_byMagicHeader(f))
      ret with  infoBox("Bad file downloaded... :(");
      
    bool replaced;
    if (isFile(myJar)) {
      print("Loaded " + nClasses(loadAllClassesInByteCodePath(myJar)));
      print("Replacing with new version: " + myJar);
      renameFile(myJar, fileInSubDir("old-code",
        appendToBaseName(myJar, ".bak." + date)));
      copyFile(f, myJar);
      printFileInfo(myJar);
      set replaced;
    }
      
    infoBox(replaced
      ? "Installed update, replaced " + f2s(myJar) + " - now starting"
      : "Starting update, but could not replace originally downloaded jar");
      
    restart(replaced ? myJar : f);
  }
  
  void restart(File jar default myJar()) {
    S javaCmd = or2(currentProcessCommand(), "java");
    S cmd = pqO(javaCmd) + " -jar " + pqO(jar);
    print(cmd);
    nohup(cmd);
    cleanExit();
  }
  
  void makeModule() {
    if (gazelle == null)
      gazelle = callF(moduleMaker);
  }
  
  void reloadModuleInBackground(Stem mod) {
    restart();
  }

  void initAutoUpdate {  
    print("Making SnippetUpdateConnector.");
    snippetUpdateConnector(verbose := true);
  
    vmBus_onMessage snippetUpdate(voidfunc(L l) {
      S uri = getString(l, 1);
      new Matches m;
      if (swic(uri, "/transpileOK/", m))
        if (sameSnippetID(programID(), firstIntAsString(m.rest()))) {
          if (stem.autoUpdate)
            upgradeGazelle();
          //infoBox("Gazelle can be updated!");
        }
    });
  }
  
  S downloadURL() {
    ret "https://botcompany.de/jar/" 
      + psI(programID()) + "?withLibs=1&noCompiler=1"
      + (downloadUncompressedJAR() ? "&uncompressed=1" : "");
  }
  
  bool downloadUncompressedJAR() { false; }
  
  // called by DynModule
  void revisualizeModule(Stem stem) {
    stem.revisualize();
  }
} // end of GazelleHost

Author comment

Began life as a copy of #1033525

download  show line numbers  debug dex  old transpilations   

Travelled to 4 computer(s): bhatertpkbcr, ekrmjmnbrukm, mowyntqkapby, mqqgnosmbjvj

No comments. add comment

Snippet ID: #1033540
Snippet name: GazelleHost + Stem
Eternal ID of this version: #1033540/130
Text MD5: 091cae0ad0e1775b6ea30631d606aff6
Author: stefan
Category: javax / gazelle v
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-01-11 18:39:24
Source code size: 11576 bytes / 434 lines
Pitched / IR pitched: No / No
Views / Downloads: 398 / 1177
Version history: 129 change(s)
Referenced in: #1033525 - Standalone November Gazelle [OK]
#1033577 - Standalone November Gazelle [backup]
#1033707 - GazelleHost backup
#1033891 - GazelleHost + Stem [dev]
#1033892 - Gazelle 22 Standalone [stable version backup]