abstract sclass DynRecordingTextArea extends DynModule { S text; switchable S title; switchable bool wordWrap; S globalID = aGlobalID(); transient JTextArea ta; transient EditRecorder recorder; transient ReliableSingleThread rstPersistText = rstWithDelay(1000, r persistText); transient JButton popDownButton; // We have auto-save of deleted modules //bool warnOnDelete() { ret nempty(text); } File logFile() { ret javaxDataDir("Text Area Logs/" + globalID); } start { dm_watchFieldAndNow title(r { setModuleName(title) }); dm_watchField wordWrap(r { enableWordWrapForTextArea(ta, wordWrap); if (ta != null && wordWrap) dm_reloadModule(); }); dm_vmBus_onMessages_q(ll("modulePoppedOut", "modulePoppedIn"), (m, myFrame) -> { if (dm_isMe(m)) adjustUIForPoppedOutWindow(); }); } visualize { ta = jenableUndoRedo(typeWriterTextArea(text)); enableWordWrapForTextArea(ta, wordWrap); logQuoted(logFile(), "text: " + text); recorder = new EditRecorder(voidfunc(EREvent e) { logStructure(logFile(), e); }); recorder.text = text; main.onChange(ta, rstPersistText); ret jscroll(setOpaqueBackground(Color.white, withMargin(ta))); } void persistText enter { if (ta == null) ret; Pair p = textAndCaretPosition(ta); recorder.update(p.a); recorder.updateCaret(p.b); print("persistText " + now()); setField(text := getText(ta)); } void unvisualize { persistText(); super.unvisualize(); } void setText(S text) { main.setText(ta, text); } S text() { ret or(main.getText(ta), text); } S _modifyStructForDuplication(S struct) { // TODO: could fail if module gets more complex ret jreplace_first(struct, "globalID=*", "globalID=" + quote(aGlobalID())); } enhanceFrame { internalFrameMenuItem(f, "Global ID: " + globalID, null); } void adjustUIForPoppedOutWindow swing { if ((popDownButton != null) != dm_moduleIsPoppedOut(me())) { if (popDownButton != null) { removeFromParent(getParent(popDownButton)); popDownButton = null; ret; } Window window = cast getWindow(dm_vis()); var popBackInButton = findButton(window, "Pop Back In"); var parent = getParent(popBackInButton); print(+parent); removeFromParent(parent); // hide controls popDownButton = jPopDownButton_noText( "Pop Back In", r { dm_popInModule(me()) }, jCheckBoxMenuItem("Always On Top", isAlwaysOnTop(window), rEnter dm_toggleAlwaysOnTop), ); replaceComponent(ta, -> centerAndEastWithMargin(ta, vstackWithSpacing(popDownButton))); } } }