1 | concept SFEditor { |
2 | // What are we editing? |
3 | O editing; // File or snippet ID |
4 | S remoteText; |
5 | |
6 | S savedText; |
7 | int caretPos; |
8 | int fontSize = 16; |
9 | S fontID = /*#1400030*/#1400031; |
10 | S snippetTitle; |
11 | |
12 | transient EditorFrame e; |
13 | transient SimpleLiveValue<O> lvEditing; |
14 | transient AutoCompletion autoCompletion; |
15 | transient ReliableSingleThread rstAutoComplete = new(r installAutoComplete); |
16 | transient bool installAutoComplete_first; |
17 | transient Set<S> autoComplete_lastSet; |
18 | transient DynamicHStack smartArea; |
19 | transient int autoCompleteRefreshDelay = 1000; |
20 | transient JTextArea transpilationErrorBox; |
21 | |
22 | !include #1015622 // setAndSave etc. |
23 | |
24 | void reset { |
25 | cleanMeUp(); |
26 | autoCompletion = null; |
27 | autoComplete_lastSet = null; |
28 | start(); |
29 | } |
30 | |
31 | void start { swing { |
32 | installAutoComplete_first = true; |
33 | lvEditing = new SimpleLiveValue(O); |
34 | |
35 | e = new EditorFrame; |
36 | e._setFont(deriveFont(loadFont(fontID), e._getFont().getSize())); |
37 | e._setFontSize(fontSize); |
38 | rstAutoComplete.trigger(); |
39 | onChange(e.textArea, rTrigger(rstAutoComplete)); |
40 | |
41 | addToWindowWithMargin(e, jHigherScrollPane(jfullcenter(smartArea = dynamicHStack()))); |
42 | |
43 | e.setText(savedText); |
44 | load('caretPos); |
45 | setCaretPosition(e.textArea, caretPos); |
46 | showFrame(e); |
47 | frameIcon(e, #1101185 /*#1004655*/); |
48 | addFontChangersToTitleMenu(e, r reset); |
49 | onFrameClosing(e, r { |
50 | if (!cleaningUp()) |
51 | deleteConcept(SFEditor.this); |
52 | }); |
53 | |
54 | addMenu(e, "&New", |
55 | "New text", r newText, |
56 | "New window", r newWindow); |
57 | |
58 | addMenu(e, "&Load", "Load snippet...", r { |
59 | selectSnippetID(voidfunc(S snippetID) { _loadSnippet(snippetID) }); |
60 | }, "Load file...", r { |
61 | selectFile("File to load", voidfunc(File f) { _loadFile(f) }); |
62 | }, "Reload", r-thread { // TODO: single thread |
63 | if (editing != null) { |
64 | reload(); |
65 | setText(e.textArea, remoteText); |
66 | } |
67 | }); |
68 | |
69 | LiveValue<S> lvSaveCmd = mapLiveValue(func(O editing) -> S { |
70 | editing instanceof S ? "Save snippet " + editing |
71 | : editing instanceof File ? "Save file " + f2s((File) editing) |
72 | : "{Save}" }, S.class, lvEditing); |
73 | |
74 | addMenu(e, "&Save", |
75 | lvSaveCmd, r { saveThen(null) }, |
76 | "Save as snippet...", r saveAsSnippet); |
77 | |
78 | addMenu(e, "&Transpile", |
79 | "Save & Quick Transpile", r { transpile(false) }, |
80 | "Save & Medium Transpile", r { transpile(true) }); |
81 | addMenu(e, "&Activate", |
82 | "Run", r runIt, |
83 | "Butter-Reload", r _butterReload); |
84 | |
85 | addMenu(e, "&View", |
86 | "Bigger font", r { e._setFontSize(setAndSave(fontSize := e._getFontSize()+1)) }, |
87 | "Smaller font", r { e._setFontSize(setAndSave(fontSize := max(1, e._getFontSize()-1))) }); |
88 | |
89 | reload(); |
90 | |
91 | awtCalcEvery(e, 1000, r update); |
92 | onFrameDeactivated(e, r fullUpdate); |
93 | } |
94 | } |
95 | |
96 | void reload { |
97 | if (editing instanceof S) _loadSnippet_noSet((S) editing); |
98 | else if (editing instanceof File) _loadFile_noSet((File) editing); |
99 | } |
100 | |
101 | void update { update(windowActive(e)); } |
102 | void fullUpdate { update(true); } |
103 | void update(bool full) { |
104 | S text = e.getText(); |
105 | setAndSaveIfChanged(savedText := text); |
106 | setAndSaveIfChanged(caretPos := getCaretPosition(e.textArea)); |
107 | |
108 | if (!full) ret; |
109 | S status = remoteText != null && neq(remoteText, text) ? "Changes. " : ""; |
110 | Pair<Int, S> p = testBracketHygieneExt(text); |
111 | status += p == null ? "Hygienic" : p.b; |
112 | silentStatus(trim(status)); |
113 | } |
114 | |
115 | void status(S s) { silentStatus(infoBoxAndReturn(s)); } |
116 | void silentStatus(S s) { e.setStatus(s); } |
117 | |
118 | void saveThen(final Runnable next) { |
119 | fS text = getText(); |
120 | if (editing instanceof S) { |
121 | status("Saving snippet..."); |
122 | thread { |
123 | fS page = editSnippet((S) editing, text); |
124 | remoteText = text; // TODO: check save result |
125 | status("Saved snippet: " + page); |
126 | awtCallF(next); |
127 | } |
128 | } else if (editing instanceof File) { |
129 | status("Saving file..."); |
130 | thread { |
131 | saveTextFile((File) editing, text); |
132 | remoteText = text; |
133 | status("Saved file"); |
134 | awtCallF(next); |
135 | } |
136 | } |
137 | } |
138 | |
139 | void _butterReload() { |
140 | time { butterReload((S) editing); } |
141 | infoBox("Reloaded in " + lastTiming_format100ms()); |
142 | } |
143 | |
144 | void transpile(final bool medium) { saveThen(r { _transpile(medium) }); } |
145 | |
146 | void _transpile(final bool medium) { |
147 | status("Transpiling..."); |
148 | //jdisable(btnEleuReload); |
149 | |
150 | thread "Transpiling" { |
151 | try { |
152 | final Pair<Bool, S> p = transpileOnServer((S) editing, medium ? "medium" : "quick"); |
153 | awt { |
154 | if (p.a) { |
155 | status("Transpiled OK!"); |
156 | hideWindow(transpilationErrorBox); |
157 | transpilationErrorBox = null; |
158 | } else { |
159 | status("Transpilation error. " + p.b); |
160 | bool first = transpilationErrorBox == null; |
161 | transpilationErrorBox = showText(transpilationErrorBox, "Transpilation Error", p.b); |
162 | if (first) { |
163 | setFrameIcon(#1101268, transpilationErrorBox); |
164 | addButtonsToWindow(transpilationErrorBox, "Medium transpile", r { _transpile(true) }); |
165 | } |
166 | } |
167 | } |
168 | } catch print e { |
169 | status("Transpilation problem. " + e); |
170 | } |
171 | //jenable(btnEleuReload); |
172 | } |
173 | } |
174 | |
175 | void _loadSnippet(S snippetID) { |
176 | _loadSnippet_noSet(snippetID); |
177 | e.textArea.setText(remoteText); |
178 | } |
179 | |
180 | void _loadSnippet_noSet(S snippetID) { |
181 | remoteText = loadSnippet(snippetID); |
182 | setAndSave('editing, snippetID); |
183 | lvEditing.set(snippetID); |
184 | frameTitle(e, snippetID + " - " + (snippetTitle = snippetTitle(snippetID))); |
185 | } |
186 | |
187 | void _loadFile(File f) { |
188 | _loadFile_noSet(f); |
189 | e.textArea.setText(remoteText); |
190 | } |
191 | |
192 | void _loadFile_noSet(File f) { |
193 | remoteText = loadTextFile(f); |
194 | setAndSave('editing, f); |
195 | lvEditing.set(f); |
196 | frameTitle(e, f2s(f)); |
197 | } |
198 | |
199 | void newText { |
200 | setAndSave(editing := null); |
201 | lvEditing.set(null); |
202 | remoteText = null; |
203 | S lastText = e.getText(); |
204 | if (nempty(lastText)) logQuotedWithDate("saved-texts.log", lastText); |
205 | e.setText(""); |
206 | frameTitle(e, programTitle()); |
207 | } |
208 | |
209 | void cleanMeUp { |
210 | update(false); |
211 | disposeWindow(e); |
212 | } |
213 | |
214 | void installAutoComplete { |
215 | if (installAutoComplete_first) installAutoComplete_first = false; |
216 | else sleep(autoCompleteRefreshDelay); // don't update too often |
217 | |
218 | //temp tempMiniLoadingAnim(); |
219 | |
220 | Set<S> set = concatListsToSet(allJavaKeywords(), standardFunctionNames(), deepWords(getText()), deepWords(snippetTitle)); |
221 | |
222 | if (eq(set, autoComplete_lastSet)) ret; |
223 | autoComplete_lastSet = set; |
224 | |
225 | final new DefaultCompletionProvider provider; |
226 | provider.addCompletions(map(func(S s) { new BasicCompletion(provider, s) }, set)); |
227 | |
228 | swing { |
229 | if (autoCompletion == null) { |
230 | (autoCompletion = new AutoCompletion(provider)).install(e.textArea); |
231 | call(autoCompletion, 'setHideOnCompletionProviderChange, false); |
232 | } else |
233 | autoCompletion.setCompletionProvider(provider); |
234 | } |
235 | } |
236 | |
237 | void newWindow { |
238 | copyFields(this, new SFEditor(), 'fontSize).start(); |
239 | } |
240 | |
241 | void runIt { |
242 | if (editing instanceof S) |
243 | nohupJavax((S) editing); |
244 | } |
245 | |
246 | void saveAsSnippet { |
247 | final JTextField tfTitle = jtextfield(); |
248 | final JComboBox cbType = jComboBox_javaxTypes(); |
249 | showFormTitled("Save as new snippet", |
250 | "Title:", tfTitle, |
251 | "Type:", cbType, |
252 | r-thread { |
253 | loading { |
254 | int type = parseFirstInt(getSelectedItem(cbType)); |
255 | S title = getTextTrim(tfTitle); |
256 | S snippetID = createSnippet(getText(), title, type); |
257 | _loadSnippet_noSet(snippetID); |
258 | } |
259 | }); |
260 | } |
261 | |
262 | S getText() { ret e.getText(); } |
263 | } |
Began life as a copy of #1015563
download show line numbers debug dex old transpilations
Travelled to 7 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv
No comments. add comment
Snippet ID: | #1028377 |
Snippet name: | SFEditor backup with old transpilation function |
Eternal ID of this version: | #1028377/1 |
Text MD5: | 37c2091d430572a9a27c3251aa668c19 |
Author: | stefan |
Category: | javax / gui |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2020-06-14 17:35:38 |
Source code size: | 8046 bytes / 263 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 145 / 160 |
Referenced in: | [show references] |