1 | // The Runner! |
2 | |
3 | !752 |
4 | |
5 | static JFrame frame; |
6 | static JList list; |
7 | static JTextField tfCmd; |
8 | static JLabel status; |
9 | static JButton btnReload, btnRun, btnClear; |
10 | static S submittedInput; |
11 | static JCheckBox cbPrograms; |
12 | static TrayIcon trayIcon; |
13 | static volatile boolean searching; |
14 | static long lastSearch; // time of last search |
15 | |
16 | static S menuSnippet = "#1000880"; |
17 | static S menuScript; |
18 | |
19 | static int searchDelay = 100; |
20 | static int maxResults = 100; |
21 | static int autoResearchInterval = 30000; // 30 secs |
22 | static boolean useFastNohup = true; // use pre-spun VMs if available |
23 | static int topTenLookBack = 100; // look at last 100 program runs |
24 | |
25 | static L<S> actionHistory = synchroList(); |
26 | |
27 | !include #1000839 // PopupMenuHelper |
28 | |
29 | p-awt {
|
30 | becomeBotVMIfFirst(); |
31 | //mistAqua(); |
32 | //magellan(); |
33 | //gemini(); |
34 | emeraldDusk(); |
35 | |
36 | try {
|
37 | frame = showFrame(); |
38 | } catch (HeadlessException e) {
|
39 | System.out.println("We're headless...");
|
40 | // TODO: Something useful. |
41 | System.exit(0); |
42 | } |
43 | |
44 | updateTitle(); |
45 | makeAndroid3("JavaX Starter.");
|
46 | |
47 | setFrameIconLater(frame, "#1003596"); |
48 | |
49 | // Show the rays |
50 | disposeWindowOnClick(showAnimation("#1003828", 3.5));
|
51 | |
52 | list = new JList(); |
53 | |
54 | new PopupMenuHelper {
|
55 | void fillMenu() {
|
56 | try {
|
57 | if (menuScript == null) |
58 | menuScript = loadSnippet(menuSnippet); |
59 | |
60 | JMenuItem mi; |
61 | int idx = list.locationToIndex(point); |
62 | final String item = cast list.getModel().getElementAt(idx); |
63 | list.setSelectedIndex(idx); |
64 | |
65 | L<S> tok = javaTok(menuScript); |
66 | for (int i = 1; i+4 < tok.size(); i += 2) |
67 | if (tok.get(i+2).equals("=")) {
|
68 | final S snip = unquote(tok.get(i+4)); |
69 | S text = unquote(tok.get(i)); |
70 | mi = new JMenuItem(text); |
71 | mi.addActionListener(actionListener {
|
72 | runCustom(snip, item); |
73 | }); |
74 | menu.add(mi); |
75 | } |
76 | } catch (Throwable e) {
|
77 | popup(e); |
78 | } |
79 | } |
80 | }.install(list); |
81 | |
82 | // install double click listener on list |
83 | list.addMouseListener(new MouseAdapter() {
|
84 | public void mouseClicked(MouseEvent evt) {
|
85 | if (evt.getClickCount() == 2) {
|
86 | int idx = list.locationToIndex(evt.getPoint()); |
87 | final String item = cast list.getModel().getElementAt(idx); |
88 | print("Mouse location: " + evt.getPoint() + ", idx: " + idx + ", item: " + item);
|
89 | list.setSelectedIndex(idx); |
90 | runCustom("", item);
|
91 | } |
92 | } |
93 | }); |
94 | |
95 | // install enter key listener on list |
96 | |
97 | list.addKeyListener(new KeyAdapter() {
|
98 | public void keyReleased(KeyEvent ke) {
|
99 | if (ke.getKeyCode() == KeyEvent.VK_ENTER) {
|
100 | main.run(); |
101 | } |
102 | } |
103 | }); |
104 | |
105 | ActionListener go = actionListener {
|
106 | tfCmd.selectAll(); |
107 | search(true); |
108 | }; |
109 | |
110 | btnReload = new JButton(isWindows() ? "Reload" : "\u27F3"); |
111 | btnReload.setToolTipText("Search again (if our " + autoResearchInterval/1000 + "s update interval is not enough for you)");
|
112 | btnReload.addActionListener(go); |
113 | |
114 | btnClear = new JButton("X");
|
115 | btnClear.setToolTipText("Show latest");
|
116 | btnClear.addActionListener(actionListener { tfCmd.setText(""); });
|
117 | |
118 | tfCmd = new JTextField; |
119 | |
120 | cbPrograms = new JCheckBox("Programs", true);
|
121 | cbPrograms.setToolTipText("Show only runnable programs (not random text snippets)");
|
122 | cbPrograms.addActionListener(go); |
123 | |
124 | JPanel controls = jflow(btnClear, cbPrograms, btnReload); |
125 | |
126 | JPanel north = centerAndEast( |
127 | withLabel("Search term:", tfCmd),
|
128 | controls); |
129 | |
130 | btnRun = jbutton("Run", r { main.run() });
|
131 | listDependButton(list, btnRun); |
132 | |
133 | status = new JLabel(" ");
|
134 | JPanel panel = northCenterAndSouth(north, list, |
135 | centerAndEast(status, btnRun)); |
136 | |
137 | tfCmd.addActionListener(go); |
138 | |
139 | frame.addWindowListener(new WindowAdapter() {
|
140 | public void windowOpened(WindowEvent e) {
|
141 | tfCmd.requestFocus(); |
142 | } |
143 | |
144 | public void windowClosing(WindowEvent e) {
|
145 | frame.setVisible(false); |
146 | } |
147 | |
148 | public void windowActivated(WindowEvent e) {
|
149 | search(false); |
150 | } |
151 | }); |
152 | |
153 | installTimer(tfCmd, new Runnable() {
|
154 | String lastContents; |
155 | boolean autoSearchOn = true; |
156 | |
157 | public void run() {
|
158 | updateTitle(); |
159 | String text = getInput(); |
160 | if (text.equals(lastContents)) {
|
161 | if ( |
162 | isFocusedWindow(frame) && now() > lastSearch + autoResearchInterval |
163 | |
164 | || (!text.equals(submittedInput) && autoSearchOn && !searching)) |
165 | search(false); |
166 | } else |
167 | lastContents = text; |
168 | } |
169 | }, searchDelay); |
170 | |
171 | frame.add(panel); |
172 | frame.setBounds(100, 100, 500, 400); |
173 | frame.setVisible(true); |
174 | frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); |
175 | hideFrameOnMinimize(frame); |
176 | |
177 | addMenu(frame, "Starter", |
178 | "Start Talk Program", r { talkProgram() });
|
179 | |
180 | trayIcon = installTrayIcon("JavaX!", "#1003596", popupItems());
|
181 | |
182 | thread "Updating Menu every 10 minutes" {
|
183 | sleepMinutes(10); |
184 | while (licensed()) {
|
185 | pcall {
|
186 | print("Updating menu.");
|
187 | updateMenu(); |
188 | } |
189 | sleepMinutes(10); |
190 | } |
191 | } |
192 | |
193 | hideConsole(); |
194 | |
195 | search(false); |
196 | } |
197 | |
198 | svoid updateTitle {
|
199 | S title = "JavaX Starter"; |
200 | if (isOfflineMode()) title += " [OFFLINE MODE]"; |
201 | setFrameTitle(frame, title); |
202 | } |
203 | |
204 | svoid updateMenu {
|
205 | updateTitle(); |
206 | trayIcon.setPopupMenu(makePopupMenu(dropFirst(popupItems()))); |
207 | } |
208 | |
209 | static O[] popupItems() {
|
210 | new L topTenItems; |
211 | pcall {
|
212 | L<S> calls = programTopTenWithArgs(topTenLookBack).getTopTen(); |
213 | new Set<S> ids; |
214 | for (S s : calls) |
215 | ids.add(onlyUntilSpace(s)); |
216 | Map<S, S> titles = getSnippetTitles(asList(ids)); |
217 | |
218 | for (final S call : calls) {
|
219 | S id = onlyUntilSpace(call); |
220 | topTenItems.add(menuItem(id + " [" + lookupSnippetID(titles, id) + "]" + (eq(id, call) ? "" : " " + trim(dropPrefix(id, call))), |
221 | r { runProgram(call); }));
|
222 | } |
223 | } |
224 | |
225 | ret flattenArray( |
226 | r { bringUpFrame(); }, // on left click
|
227 | toObjectArray(topTenItems), |
228 | "***", |
229 | menuItem("Show Runner", r { bringUpFrame(); }),
|
230 | menuItem("Show Console", r { showConsole(); }),
|
231 | menuItem("Restart Runner", r { restart(); }),
|
232 | menuItem("Show Talk Program [Eleutheria]", r { talkProgram(); }),
|
233 | //menuItem("Hide Console", r { hideConsole(); }),
|
234 | isOfflineMode() |
235 | ? menuItem("Switch to online mode", r { goOnlineMode(); updateMenu(); })
|
236 | : menuItem("Switch to offline mode", r { goOfflineMode(); updateMenu(); }),
|
237 | menuItem("Exit", r { System.exit(0); }));
|
238 | } |
239 | |
240 | static S getInput() {
|
241 | ret tfCmd.getText().trim(); |
242 | } |
243 | |
244 | static void search(String cmd, final boolean requestFocus) ctex {
|
245 | searching = true; |
246 | try {
|
247 | status("Searching " + quote(cmd) + "...");
|
248 | if (empty(cmd)) cmd = "_"; |
249 | if (cbPrograms.isSelected()) |
250 | cmd += " type:runnable"; |
251 | S page = loadPage("http://tinybrain.de:8080/tb/search.php?q=" + urlencode(cmd) + "&limit=" + maxResults + "&sort=modified&quick=1" + standardCredentials());
|
252 | Matcher m = Pattern.compile(">(#\\d+)</a> - (.*?)<br>").matcher(page);
|
253 | |
254 | final new DefaultListModel model; |
255 | while (m.find()) {
|
256 | String title = m.group(2); |
257 | title = join(dropAllTags(htmlcoarsetok(title))); |
258 | model.addElement(htmldecode(m.group(1) + " - " + title)); |
259 | } |
260 | |
261 | awt {
|
262 | list.setModel(model); |
263 | status("Found " + model.size() + (model.size() == maxResults ? "+" : "") + (cbPrograms.isSelected() ? " runnable(s)." : " snippet(s)."));
|
264 | if (requestFocus) |
265 | tfCmd.requestFocus(); |
266 | } |
267 | } finally {
|
268 | searching = false; |
269 | } |
270 | } |
271 | |
272 | static void status(final S s) {
|
273 | awt { status.setText(s); }
|
274 | } |
275 | |
276 | static void runProgram(final S cmd) {
|
277 | print("Running " + cmd);
|
278 | S msg = format3("*: Running *", now(), cmd);
|
279 | actionHistory.add(msg); |
280 | logQuoted("run.log", msg);
|
281 | |
282 | thread { // new thread so we can see progress messages, e.g. for loading the JavaX jar
|
283 | if (useFastNohup) |
284 | fastNohupJavax(cmd); |
285 | else |
286 | nohupJavax(cmd); |
287 | } |
288 | } |
289 | |
290 | static void runHotwired(final S worker, final long id) {
|
291 | print("Hotwiring " + worker + " on " + id);
|
292 | S msg = format3("*: Hotwiring * on *", now(), worker, id);
|
293 | actionHistory.add(msg); |
294 | logQuoted("run.log", msg);
|
295 | |
296 | thread {
|
297 | _run(worker, new S[] {str(id)}); // TODO: cache code?
|
298 | } |
299 | } |
300 | |
301 | static void runCustom(S worker, S item) {
|
302 | if (item == null) ret; |
303 | int i = item.indexOf(' ');
|
304 | if (i >= 0) item = item.substring(0, i); |
305 | long id = parseSnippetID(item); |
306 | print("runCustom: " + id + " [" + worker + "]");
|
307 | if (empty(worker)) |
308 | runProgram(str(id)); |
309 | else |
310 | runHotwired(worker, id); |
311 | } |
312 | |
313 | static void runWithArguments(S item) {
|
314 | // TODO: run a dialog for that |
315 | } |
316 | |
317 | static void search(final boolean requestFocus) {
|
318 | submittedInput = getInput(); |
319 | lastSearch = now(); |
320 | final String cmd = submittedInput; |
321 | actionHistory.add(format3("*: Searching *", now(), cmd));
|
322 | thread {
|
323 | search(cmd, requestFocus); |
324 | } |
325 | } |
326 | |
327 | answer {
|
328 | if "very quick java *" |
329 | ret format("ok *", structure(callCalc(veryQuickJava(m.unq(0)))));
|
330 | } |
331 | |
332 | static void run() {
|
333 | S item = cast list.getModel().getElementAt(list.getSelectedIndex()); |
334 | runCustom("", item);
|
335 | } |
336 | |
337 | static void bringUpFrame() {
|
338 | makeFrameVisible(frame); |
339 | } |
Began life as a copy of #1000825
download show line numbers debug dex old transpilations
Travelled to 13 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
| Snippet ID: | #1006325 |
| Snippet name: | JavaX Starter - Runnables search, v2 (backup) |
| Eternal ID of this version: | #1006325/1 |
| Text MD5: | 2cbaf105ce9bc190c66ce8816972c07e |
| Author: | stefan |
| Category: | javax |
| Type: | JavaX source code |
| Public (visible to everyone): | Yes |
| Archived (hidden from active list): | No |
| Created/modified: | 2016-12-28 20:50:09 |
| Source code size: | 9460 bytes / 339 lines |
| Pitched / IR pitched: | No / No |
| Views / Downloads: | 686 / 667 |
| Referenced in: | [show references] |