sclass InputChooser implements Swingable { DynModule module; bool myInput; S ownInput; transient int delay; transient ReliableSingleThread rst; transient S input; transient JPanel panel; transient JTextField tfInput; transient JCheckBox cbInput; *() {} // only for persistence *(DynModule *module) {} S input() { ret input; } S _freshInput() { ret myInput ? ownInput : dm_getInterestingString(); } void forceUpdate { input = null; module.updateMe(); } void forgetInput { input = null; } bool update() { S s = _freshInput(); ifdef InputChooser_verbose print("Fresh input: " + s); endifdef if (neq(input, s)) { input = s; true; //dm_updateModule(); } false; } public JComponent visualize() { if (panel != null) ret panel; tfInput = jcenteredtextfield(ownInput); cbInput = setToolTip("Checked: Use my own input. Unchecked: take input from AI bar on the top of OS", jcheckbox(myInput)); onChangeAndNow(cbInput, r { setEnabled(tfInput, isChecked(cbInput)); myInput = isChecked(cbInput); updateModule(); }); onChange(tfInput, r { if (myInput) { ownInput = getText(tfInput); updateModule(); } }); ret panel = westAndCenter(cbInput, tfInput); } void updateModule { if (rst == null) rst = rstWithDelay(delay, r { module.updateMe() }); rst.trigger(); } InputChooser setDelay(int delay) { this.delay = delay; this; } }