1 | sclass G22ManagedTextEditor<A extends G22Text> is Swingable { |
2 | settable G22Utils g22utils; |
3 | settable S noScriptSelectedMsg = "Please select or create a text to edit it"; |
4 | |
5 | gettable A script; |
6 | |
7 | transient SingleComponentPanel scp; |
8 | transient JSyntaxTextFileEditor[] ides; |
9 | transient JExtendedTabbedPane tabs; |
10 | transient JButton btnSave, btnDiscardChanges, btnClearForAutoRun; |
11 | transient CollapsibleLeftPanel collapsibleResultPanel; |
12 | transient G22ScriptResultPanel resultPanel; |
13 | transient Mode lastVisibleMode; |
14 | |
15 | abstract class Mode { |
16 | G22ScriptMode modeEnum; |
17 | S name; |
18 | gettable bool editable; |
19 | |
20 | *(G22ScriptMode *modeEnum, S *name, bool *editable) {} |
21 | |
22 | simplyCached abstract IVarWithNotify<S> scriptVar(); |
23 | |
24 | void addButtons(JPanel panel) {} |
25 | |
26 | toString { ret name; } |
27 | |
28 | S tabName() { ret scriptVar().has() ? name : "Not " + firstToLower(name); } |
29 | } |
30 | |
31 | class ModeClearedForAutoRun > Mode { |
32 | *() { super(G22ScriptMode.autoRunnable, "Cleared for auto-run", false); } |
33 | |
34 | IVarWithNotify<S> scriptVar_load() { |
35 | var var = new VirtualVar<S>( |
36 | -> script.codeForAutoRun(), |
37 | null /*text -> script.setClearedForAutoRun(text == null ?: new ClearForAutoRun(text))*/); |
38 | addWeakChangeListener(script.varClearedForAutoRun(), var); |
39 | ret var; |
40 | } |
41 | |
42 | void addButtons(JPanel panel) { |
43 | panel.add(jbutton("Forget auto-run code", rThread forgetAutoRunCode)); |
44 | } |
45 | } |
46 | |
47 | class ModeSaved > Mode { |
48 | *() { super(G22ScriptMode.saved, "Saved", false); } |
49 | |
50 | IVarWithNotify<S> scriptVar_load() { |
51 | ret getterVarOnly(script.varText()); |
52 | } |
53 | |
54 | void addButtons(JPanel panel) { |
55 | panel.add(btnClearForAutoRun = jbutton("Clear for auto-run", rThread clearForAutoRun)); |
56 | panel.add(jbutton("Forget code", rThread forgetSaved)); |
57 | } |
58 | } |
59 | |
60 | class ModeEdit > Mode { |
61 | *() { super(G22ScriptMode.edit, "Edit", true); } |
62 | |
63 | IVarWithNotify<S> scriptVar_load() { |
64 | var var = new VirtualVar<S>( |
65 | -> script.textForEditing(), |
66 | text -> script.receiveEditingText(text) |
67 | ); |
68 | addWeakChangeListener(script, var); |
69 | ret var; |
70 | } |
71 | |
72 | void addButtons(JPanel panel) { |
73 | panel.add(btnSave = jbutton("Save", rThread saveEdit)); |
74 | panel.add(btnDiscardChanges = jbutton("Discard changes", rThread discardEdit)); |
75 | } |
76 | } |
77 | |
78 | transient new ModeEdit modeEdit; |
79 | transient new ModeSaved modeSaved; |
80 | transient L<Mode> modes = ll( |
81 | modeEdit, |
82 | modeSaved |
83 | ); |
84 | |
85 | *(G22Utils *g22utils) {} |
86 | |
87 | cachedVisualize { |
88 | ides = new JSyntaxTextFileEditor[l(modes)]; |
89 | if (scp == null) scp = singleComponentPanel(); |
90 | loadScript(script); |
91 | ret scp; |
92 | } |
93 | |
94 | void setScript(A script) { |
95 | if (this.script != script) |
96 | if (this.script != null) |
97 | fail("Can't set script after initialisation"); |
98 | else |
99 | loadScript(script); |
100 | } |
101 | |
102 | void loadScript(A script) { |
103 | this.script = script; |
104 | if (scp == null) ret; |
105 | if (script == null) |
106 | scp.set(jcenteredlabel(noScriptSelectedMsg())); |
107 | else { |
108 | tabs = jExtendedTabs(); |
109 | resultPanel = new G22ScriptResultPanel; |
110 | collapsibleResultPanel = new CollapsibleLeftPanel(false, "Output", resultPanel.visualize(), tabs.visualize()); |
111 | collapsibleResultPanel.sidePanelMargins = c -> withTopAndLeftMargin(c); |
112 | |
113 | // This places tabs vertically at the right hand side... |
114 | // (not what we want) |
115 | //setTabPlacement(JTabbedPane.RIGHT, tabs); |
116 | |
117 | for (int i, Mode mode : unpair iterateWithIndex(modes)) { |
118 | var ide = ides[i] = new JSyntaxTextFileEditor; |
119 | ide.withResultPanel(false); |
120 | ide.resultPanel = resultPanel; |
121 | ide.collapsibleResultPanel = collapsibleResultPanel; |
122 | ide.wrapSection = c -> wrapEditorSection(mode, c); |
123 | ide.newCompileResult = -> script.newCompileResult(); |
124 | ide.makeParser = -> script.makeParser(); |
125 | modifyIDE(ide); |
126 | var varScript = mode.scriptVar(); |
127 | ide.lvScript(varWithNotifyToLiveValue(S.class, varScript)); |
128 | addTab(tabs, str(mode)); |
129 | mode.addButtons(ide.buttons()); |
130 | ide.visualize(); |
131 | ide.setEditable(mode.editable()); |
132 | varScript.onChangeAndNow(text -> |
133 | setTab(tabs, i, text == null ? jcenteredlabel("Empty") : wrapIDE(mode, ide))); |
134 | ide.popDownButton.onFillingMenu(menu -> |
135 | addMenuItem(menu, "Show History", rThread showHistory)); |
136 | } |
137 | |
138 | script.onChangeAndNow(r { |
139 | for (int i, Mode mode : unpair iterateWithIndex(modes)) |
140 | setTabTitle(tabs, i, mode.tabName()); |
141 | setEnabled(script.isEditing(), btnSave, btnDiscardChanges); |
142 | setEnabled(btnClearForAutoRun, script.isSavedDistinctFromAutoRunVersion()); |
143 | for (ide : ides) |
144 | ide.sectionTitle(str(script)); |
145 | }); |
146 | |
147 | onTabSelectedAndNow(tabs, -> { |
148 | var mode = visibleMode(); |
149 | if (lastVisibleMode != null && lastVisibleMode != mode) { |
150 | // Move selected IDE to same position as previous IDE |
151 | |
152 | var lastIDE = ide(lastVisibleMode); |
153 | var ide = visibleIDE(); |
154 | awtLater(0.5, -> { |
155 | LineAndColumn lac = caretLineAndCol(lastIDE.textArea()); |
156 | moveCaretToLineAndCol(ide.textArea(), lac); |
157 | setEnclosingViewPosition(ide.textArea(), enclosingViewPosition(lastIDE.textArea())); |
158 | focus(ide.textArea()); |
159 | }); |
160 | } |
161 | lastVisibleMode = mode; |
162 | |
163 | tabs.setComponentBesideTabs( |
164 | mode != modeEdit |
165 | ? jfullcenter(withRightMargin(jbutton("Edit script", -> setMode(modeEdit)))) |
166 | : null); |
167 | }); |
168 | |
169 | setMode(script.isEditing() ? modeEdit : modeSaved); |
170 | scp.set(collapsibleResultPanel); |
171 | } |
172 | } |
173 | |
174 | swappable JComponent wrapEditorSection(Mode mode, JComponent editorSection) { |
175 | /*if (mode != modeEdit) |
176 | ret withTopMargin(northAndCenterWithMargin( |
177 | withRightMargin(jline(jbutton("Edit script", -> setMode(modeEdit)))), |
178 | editorSection)); |
179 | else*/ |
180 | ret editorSection; |
181 | } |
182 | |
183 | swappable JComponent wrapIDE(Mode mode, JSyntaxTextFileEditor ide) { |
184 | ret ide.visualize(); |
185 | } |
186 | |
187 | void saveEdit { |
188 | script.completeEdit(); |
189 | setMode(modeSaved); |
190 | } |
191 | |
192 | JSyntaxTextFileEditor ide(Mode mode) { |
193 | if (ides == null) visualize(); |
194 | ret _get(ides, indexOf(modes, mode)); |
195 | } |
196 | |
197 | RSyntaxTextArea visibleTextArea() { |
198 | var ide = visibleIDE(); |
199 | ret ide?.textArea(); |
200 | } |
201 | |
202 | void setMode(Mode mode) { |
203 | var caretPos = caretLineAndCol(visibleTextArea()); |
204 | printVars("setMode", +caretPos); |
205 | selectTab(tabs, indexOf(modes, mode)); |
206 | var ide = visibleIDE(); |
207 | printVars("setMode", +ide, mode := visibleMode()); |
208 | ide.goToPosition_noFocus(caretPos); |
209 | if (mode == modeEdit) |
210 | focus(visibleTextArea()); |
211 | } |
212 | |
213 | // get currently visible mode |
214 | Mode visibleMode() { |
215 | ret _get(modes, indexOfSelectedTab(tabs)); |
216 | } |
217 | |
218 | JSyntaxTextFileEditor visibleIDE() { |
219 | ret ide(visibleMode()); |
220 | } |
221 | |
222 | void discardEdit { |
223 | setMode(modeSaved); |
224 | script.discardEdit(); |
225 | } |
226 | |
227 | void forgetSaved { |
228 | script.setTextWithHistory(null); |
229 | } |
230 | |
231 | void clearForAutoRun { |
232 | script.clearForAutoRun(); |
233 | setMode(modeClearedForAutoRun); |
234 | } |
235 | |
236 | void forgetAutoRunCode { |
237 | script.forgetAutoRunCode(); |
238 | } |
239 | |
240 | private void selfTest_impl { |
241 | new G22Text script; |
242 | setScript((A) script); |
243 | ide(modeEdit).setText("hello"); |
244 | assertEqualsVerbose(null, script.text()); |
245 | assertEqualsVerbose("hello", script.editedText()); |
246 | saveEdit(); |
247 | assertEqualsVerbose("hello", script.text()); |
248 | assertEqualsVerbose(null, script.editedText()); |
249 | } |
250 | |
251 | static void selfTest(G22Utils g22utils) { |
252 | new G22ManagedTextEditor(g22utils).selfTest_impl(); |
253 | } |
254 | |
255 | void showHistory { |
256 | showText("Edit history of " + script, loadTextFile(script.historyFile())); |
257 | } |
258 | |
259 | void goToPositionInAllModes(LineAndColumn lac) { |
260 | for (ide : ides) |
261 | ide?.goToPosition_noFocus(lac); |
262 | } |
263 | } |
Began life as a copy of #1034345
download show line numbers debug dex old transpilations
Travelled to 2 computer(s): mqqgnosmbjvj, wnsclhtenguj
No comments. add comment
Snippet ID: | #1036610 |
Snippet name: | G22ManagedTextEditor - for G22Text [dev.] |
Eternal ID of this version: | #1036610/1 |
Text MD5: | 83fd872587802219732748e86b1c9143 |
Author: | stefan |
Category: | javax / gazelle 22 |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2023-04-27 18:47:50 |
Source code size: | 8240 bytes / 263 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 150 / 158 |
Referenced in: | [show references] |