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

331
LINES

< > BotCompany Repo | #1016118 - Code Editor [edits snippets and files]

JavaX source code (Dynamic Module) [tags: use-pretranspiled] - run with: Stefan's OS

Uses 1403K of libraries. Click here for Pure Java version (17958L/141K).

!7

// TODO: use central transpiler

set flag bindLiveValueListenerToComponent_debug.
//set flag addMenu_debug.

module SFEditor {
  // What are we editing?
  O editing; // File or snippet ID
  S remoteText;
  Int snippetType;
  
  S savedText;
  int caretPos;
  int fontSize = 16;
  S fontID = /*#1400030*/#1400031;
  S snippetTitle;
  
  transient EditorFrame2 e;
  transient SimpleLiveValue<O> lvEditing;
  transient AutoCompletion autoCompletion;
  transient ReliableSingleThread rstAutoComplete = dm_rst(this, r installAutoComplete);
  transient bool installAutoComplete_first;
  transient Set<S> autoComplete_lastSet;
  transient int autoCompleteRefreshDelay = 1000;
  transient JTextArea transpilationErrorBox;
  transient ReliableSingleThread persistLater = rstWithDelay(10.0, r persistMe);
  
  !include #1016117 // setAndSave etc.
  
  bool warnOnDelete() { ret neq(e.getText(), unnull(remoteText)); }

  void reset {
    cleanMeUp();
    autoCompletion = null;
    autoComplete_lastSet = null;
    start();
  }
  
  void start { swing {
    temp enter();
    installAutoComplete_first = true;
    lvEditing = dm_fieldLiveValue('editing);
    
    e = new EditorFrame2;
    e._setFont(deriveFont(loadFont(fontID), e._getFont().getSize()));
    e._setFontSize(fontSize);
    rstAutoComplete.trigger();
    main.onChange(e.textArea, rTrigger(rstAutoComplete));
    
    e.setText(savedText);
    load('caretPos);
    setCaretPosition(e.textArea, caretPos);
  }}
  
  visualize {
 ret e.panel;
 }
  
  enhanceFrame {
    print("enhanceFrame");
    e.prepareFrame(f/JInternalFrame);
    minimalFrameSize(f/JInternalFrame, 400, 400);
    reload();
    makeMenus(f);
    awtCalcEvery(f/JInternalFrame.getRootPane(), 1000, r update);
    onPossiblyInternalFrameDeactivated(f/JInternalFrame.getRootPane(), r fullUpdate);
  }

  void makeMenus(Container f) {
    if (f == null) ret;
    addMenu(f, "&View",
      "Bigger font", r { e._setFontSize(setAndSave(fontSize := e._getFontSize()+1)) },
      "Smaller font", r { e._setFontSize(setAndSave(fontSize := max(1, e._getFontSize()-1))) });
      
    addMenu(f, "&New",
      "New text", r newText,
      "New window", rThread { dm_showNewModule(dm_moduleLibID()) });
  
    addMenu(f, "&Load", "Load snippet...", r {
      selectSnippetID(voidfunc(S snippetID) { _loadSnippet(snippetID) });
    }, "Load file...", r {
      selectFile("File to load", voidfunc(File f) { _loadFile(f) });
    }, "Reload", r-thread { // TODO: single thread
      if (editing != null) {
        reload();
        main setText(e.textArea, remoteText);
      }
    });
    
    // There is a weird bug that breaks the bindToComponent magic
    LiveValue<S> lvSaveCmd = mapLiveValue(func(O editing) -> S {
      editing instanceof S ? "Save snippet " + editing
        : editing instanceof File ? "Save file " + f2s((File) editing)
        : "{Save}" }, S.class, lvEditing);

    addMenu(f, "&Save",
      lvSaveCmd, r { saveThen(null) },
      "Save as snippet...", r saveAsSnippet,
      "Save as file...", r saveAsFile);
    
    addMenu(f, "&Transpile",
      "Save & Quick Transpile", r { transpile(false) },
      "Save & Medium Transpile", r { transpile(true) },
      "---",
      "Show transpilation", r showTranspilation);
      
    //print("Editing: " + editing);
    
    addMenu(f, "&Activate",
      eq(snippetType, snippetType_JavaXDesktop()) ? "Run" : null, rThread runIt,
      isString(editing) ? "Load Module" : null, rThread _loadModule,
      isString(editing) ? "Reload Module" : null, rThread _reloadModule,
      haveMuricaPassword() ? "Reload on server" : null, rThread _butterReload,
      haveMuricaPassword() ? "Transpile quick & reload on server" : null, rThread { transpileAndButterReload(false) },
      haveMuricaPassword() ? "Transpile medium & reload on server" : null, rThread { transpileAndButterReload(true) });
  }

  void reload {
    if (editing instanceof S) _loadSnippet_noSet((S) editing);
    else if (editing instanceof File) _loadFile_noSet((File) editing);
  }
  
  void update { update(internalFrameActive(e.panel)); }
  void fullUpdate { update(true); }
  void update(bool full) {
    S text = e.getText();
    int cp = getCaretPosition(e.textArea);
    if (neq(savedText, text)) {
      setAndSave(savedText := text);
      setAndSave(caretPos := cp);
    } else if (cp != caretPos) {
      caretPos = cp;
      persistLater.trigger();
    }
      
    if (!full) ret;
    S status = remoteText != null && neq(remoteText, text) ? "Changes. " : "";
    Pair<Int, S> p = testBracketHygieneExt(text);
    status += p == null ? "Hygienic" : p.b;
    silentStatus(trim(status));
  }
  
  void status(S s) { silentStatus(infoBoxAndReturn(s)); }
  void silentStatus(S s) { e.setStatus(s); }
  
  void saveThen(final Runnable next) {
    fS text = getText();
    if (editing instanceof S) {
      status("Saving snippet...");
      thread {
        fS page = editSnippet((S) editing, text);
        remoteText = text; // TODO: check save result
        status("Saved snippet: " + page);
        callF(next);
      }
    } else if (editing instanceof File) {
      status("Saving file...");
      thread {
        saveTextFile((File) editing, text);
        remoteText = text;
        status("Saved file");
        callF(next);
      }
    }
  }
  
  void _butterReload() {
    time { butterReload((S) editing); }
    infoBox("Reloaded in " + lastTiming_format100ms());
  }

  void transpileAndButterReload(bool medium) {
    transpile(medium, onSuccess := r _butterReload);
  }
  
  void transpile(bool medium, O... _) { saveThen(r { _transpile(medium, _) }); }
  
  void _transpile(bool medium, O... _) {
    optPar Runnable onSuccess;
    status("Transpiling...");
    //jdisable(btnEleuReload);
    
    thread "Transpiling" {
      try {
        final Pair<Bool, S> p = transpileOnBestServer((S) editing, medium ? "medium" : "quick");
        awt {
          if (p.a) {
            status("Transpiled OK!");
            hideWindow(transpilationErrorBox);
            transpilationErrorBox = null;
            callFInNewThread(onSuccess);
          } else {
            S text = htmlDecode(htmlDecode(p.b)); /// XXX
            status("Transpilation error. " + text);
            bool first = transpilationErrorBox == null;
            transpilationErrorBox = showText(transpilationErrorBox, "Transpilation Error", text);
            if (first) {
              setFrameIcon(#1101268, transpilationErrorBox);
              addButtonsToWindow(transpilationErrorBox, "Medium transpile", r { _transpile(true) });
            }
          }
        }
      } catch print e {
        status("Transpilation problem. " + e);
      }
      //jenable(btnEleuReload);
    }
  }
  
  void _loadSnippet(S snippetID) enter {
    _loadSnippet_noSet(snippetID);
    e.textArea.setText(remoteText);
  }
  
  void _loadSnippet_noSet(S snippetID) {
    remoteText = loadSnippet(snippetID);
    setField(snippetType := getSnippetType(snippetID));
    setAndSave('editing, snippetID);
    setModuleName("Editing: " + snippetID + " - " + quote(snippetTitle = snippetTitle(snippetID)));
    print("_loadSnippet_noSet: Making menus for " + dm_frame() + " of " + className(dm_vis()));
    makeMenus(dm_frame());
  }
  
  void _loadFile(File f) {
    _loadFile_noSet(f);
    e.textArea.setText(remoteText);
  }
  
  void _loadFile_noSet(File f) {
    remoteText = loadTextFile(f);
    setField(snippetType := null);
    setAndSave('editing, f);
    setModuleName("Editing: " + f2s(f));
    makeMenus(dm_frame());
  }
  
  void newText {
    setAndSave(editing := null);
    remoteText = null;
    setField(snippetType := null);
    S lastText = e.getText();
    if (nempty(lastText)) logQuotedWithDate("saved-texts.log", lastText);
    e.setText("");
    setModuleName(programTitle());
  }
  
  void cleanMeUp {
    update(false);
  }
  
  void installAutoComplete {
    if (installAutoComplete_first) installAutoComplete_first = false;
    else sleep(autoCompleteRefreshDelay); // don't update too often
    
    //temp tempMiniLoadingAnim();
  
    Set<S> set = concatListsToSet(allJavaKeywords(), standardFunctionNames(), deepWords(getText()), deepWords(snippetTitle));
      
    if (eq(set, autoComplete_lastSet)) ret;
    autoComplete_lastSet = set;
    
    final new DefaultCompletionProvider provider;
    provider.addCompletions(map(func(S s) -> Completion { new BasicCompletion(provider, s) }, set));
      
    swing {
      if (autoCompletion == null) {
        (autoCompletion = new AutoCompletion(provider)).install(e.textArea);
        call(autoCompletion, 'setHideOnCompletionProviderChange, false);
      } else
        autoCompletion.setCompletionProvider(provider);
    }
  }
  
  void newWindow {
    copyFields(this, new SFEditor(), 'fontSize).start();
  }
  
  void runIt {
    if (editing instanceof S)
      nohupJavax((S) editing);
  }
  
  void saveAsSnippet {
    final JTextField tfTitle = jtextfield(snippetTitle);
    final JComboBox cbType = jComboBox_javaxTypes();
    showFormTitled("Save as new snippet",
      "Title:", tfTitle,
      "Type:", cbType,
      r-thread {
        loading {
          int type = parseFirstInt(getSelectedItem(cbType));
          S title = getTextTrim(tfTitle);
          S snippetID = createSnippet(getText(), title, type);
          _loadSnippet_noSet(snippetID);
        }
      });
  }
  
  void saveAsFile {
    inputFilePath("Save as...", optCast(File, editing), voidfunc(File f) {
      saveTextFile(f, getText());
      _loadFile_noSet(f);
    });
  }
  
  S getText() { ret e.getText(); }

  void _reloadModule enter {
    dm_reloadAllModulesWithSnippetID((S) editing);
  }

  void _loadModule enter {
    dm_addDynamicModuleDialog2((S) editing);
  }

  S snippetID() { ret optCast S(editing); }

  void showTranspilation enter {
    if (snippetID() == null) ret;
    showText("Transpilation of " + snippetID(),
      getServerTranspiledWithoutLibs(snippetID()));
  }
  
  // API
  
  void setText(S text) enter {
    e.textArea.setText(text);
  }
}

Author comment

Began life as a copy of #1015563

download  show line numbers  debug dex   

Travelled to 12 computer(s): aoiabmzegqzx, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, hpgrupgrauku, irmadwmeruwu, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, tslmcundralx, tvejysmllsmz

No comments. add comment

Snippet ID: #1016118
Snippet name: Code Editor [edits snippets and files]
Eternal ID of this version: #1016118/78
Text MD5: 8d727b441303508ffc72d7ba3c8d0dad
Transpilation MD5: 6cf5e5ae3650351726da0446953a906b
Author: stefan
Category: javax / gui
Type: JavaX source code (Dynamic Module)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2019-09-24 15:09:17
Source code size: 10401 bytes / 331 lines
Pitched / IR pitched: No / No
Views / Downloads: 336 / 5030
Version history: 77 change(s)
Referenced in: [show references]

Formerly at http://tinybrain.de/1016118 & http://1016118.tinybrain.de