srecord noeq JTextFileEditor(File file) is Swingable { settable bool autoSave; JTextArea textArea; JButton btnReload, btnSave; volatile S fileContents, savedText; FileWatchService fileWatcher; Q q = startQ(); RSTOverQ rstLoad = rstWithPreDelay(1.0, q, r _load); RSTOverQ rstSave; cachedVisualize { assertNotNull(file); rstSave = rstWithPreDelay(autoSave ? 1.0 : 0.0, q, r _save); savedText = fileContents = loadTextFile(file); textArea = wordWrapTypeWriterTextArea(savedText); onChange(textArea, l0 updateButtons); bindToComponent(textArea, -> { fileWatcher = new FileWatchService; fileWatcher.addNonRecursiveListener(dirOfFile(file), f -> { if (sameFile(f, file)) rstLoad!; }); rstLoad!; }, -> { dispose fileWatcher; }); ret northAndCenterWithMargin( centerAndEastWithMargin( swing(-> JFilePathLabel(file).visualize()), jline( autoSave ? null : btnSave = disableButton(jbutton("Save", rstSave)), btnReload = jbutton("Reload", r reload) )), textArea ); } void updateButtons { setEnabled(btnSave, !eq(savedText, getText(textArea))); setEnabled(btnReload, !eq(fileContents, savedText)); } void _save { saveTextFile(file, savedText = getText(textArea)); } void reload { savedText = fileContents; setText(textArea, savedText); updateButtons(); } void _load { print("Loading " + file); fileContents = loadTextFile(file); updateButtons(); } }