// The Runner! !752 static JFrame frame; static JList list; static JTextField tfCmd; static JLabel status; static JButton btnReload, btnRun, btnClear; static S submittedInput; static JCheckBox cbPrograms; static TrayIcon trayIcon; static volatile boolean searching; static long lastSearch; // time of last search static S menuSnippet = "#1000880"; static S menuScript; static int searchDelay = 100; static int maxResults = 100; static int autoResearchInterval = 30000; // 30 secs static boolean useFastNohup = true; // use pre-spun VMs if available static int topTenLookBack = 100; // look at last 100 program runs static L actionHistory = synchroList(); !include #1000839 // PopupMenuHelper p-awt { becomeBotVMIfFirst(); //mistAqua(); //magellan(); //gemini(); emeraldDusk(); try { frame = showFrame(); } catch (HeadlessException e) { System.out.println("We're headless..."); // TODO: Something useful. System.exit(0); } updateTitle(); makeAndroid3("JavaX Starter."); setFrameIconLater(frame, "#1003596"); // Show the rays disposeWindowOnClick(showAnimation("#1003828", 3.5)); list = new JList(); new PopupMenuHelper { void fillMenu() { try { if (menuScript == null) menuScript = loadSnippet(menuSnippet); JMenuItem mi; int idx = list.locationToIndex(point); final String item = cast list.getModel().getElementAt(idx); list.setSelectedIndex(idx); L tok = javaTok(menuScript); for (int i = 1; i+4 < tok.size(); i += 2) if (tok.get(i+2).equals("=")) { final S snip = unquote(tok.get(i+4)); S text = unquote(tok.get(i)); mi = new JMenuItem(text); mi.addActionListener(actionListener { runCustom(snip, item); }); menu.add(mi); } } catch (Throwable e) { popup(e); } } }.install(list); // install double click listener on list list.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent evt) { if (evt.getClickCount() == 2) { int idx = list.locationToIndex(evt.getPoint()); final String item = cast list.getModel().getElementAt(idx); print("Mouse location: " + evt.getPoint() + ", idx: " + idx + ", item: " + item); list.setSelectedIndex(idx); runCustom("", item); } } }); // install enter key listener on list list.addKeyListener(new KeyAdapter() { public void keyReleased(KeyEvent ke) { if (ke.getKeyCode() == KeyEvent.VK_ENTER) { main.run(); } } }); ActionListener go = actionListener { tfCmd.selectAll(); search(true); }; btnReload = new JButton(isWindows() ? "Reload" : "\u27F3"); btnReload.setToolTipText("Search again (if our " + autoResearchInterval/1000 + "s update interval is not enough for you)"); btnReload.addActionListener(go); btnClear = new JButton("X"); btnClear.setToolTipText("Show latest"); btnClear.addActionListener(actionListener { tfCmd.setText(""); }); tfCmd = new JTextField; cbPrograms = new JCheckBox("Programs", true); cbPrograms.setToolTipText("Show only runnable programs (not random text snippets)"); cbPrograms.addActionListener(go); JPanel controls = jflow(btnClear, cbPrograms, btnReload); JPanel north = centerAndEast( withLabel("Search term:", tfCmd), controls); btnRun = jbutton("Run", r { main.run() }); listDependButton(list, btnRun); status = new JLabel(" "); JPanel panel = northCenterAndSouth(north, list, centerAndEast(status, btnRun)); tfCmd.addActionListener(go); frame.addWindowListener(new WindowAdapter() { public void windowOpened(WindowEvent e) { tfCmd.requestFocus(); } public void windowClosing(WindowEvent e) { frame.setVisible(false); } public void windowActivated(WindowEvent e) { search(false); } }); installTimer(tfCmd, new Runnable() { String lastContents; boolean autoSearchOn = true; public void run() { updateTitle(); String text = getInput(); if (text.equals(lastContents)) { if ( isFocusedWindow(frame) && now() > lastSearch + autoResearchInterval || (!text.equals(submittedInput) && autoSearchOn && !searching)) search(false); } else lastContents = text; } }, searchDelay); frame.add(panel); frame.setBounds(100, 100, 500, 400); frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); hideFrameOnMinimize(frame); addMenu(frame, "Starter", "Start Talk Program", r { talkProgram() }); trayIcon = installTrayIcon("JavaX!", "#1003596", popupItems()); thread "Updating Menu every 10 minutes" { sleepMinutes(10); while (licensed()) { pcall { print("Updating menu."); updateMenu(); } sleepMinutes(10); } } hideConsole(); search(false); } svoid updateTitle { S title = "JavaX Starter"; if (isOfflineMode()) title += " [OFFLINE MODE]"; setFrameTitle(frame, title); } svoid updateMenu { updateTitle(); trayIcon.setPopupMenu(makePopupMenu(dropFirst(popupItems()))); } static O[] popupItems() { new L topTenItems; pcall { L calls = programTopTenWithArgs(topTenLookBack).getTopTen(); new Set ids; for (S s : calls) ids.add(onlyUntilSpace(s)); Map titles = getSnippetTitles(asList(ids)); for (final S call : calls) { S id = onlyUntilSpace(call); topTenItems.add(menuItem(id + " [" + lookupSnippetID(titles, id) + "]" + (eq(id, call) ? "" : " " + trim(dropPrefix(id, call))), r { runProgram(call); })); } } ret flattenArray( r { bringUpFrame(); }, // on left click toObjectArray(topTenItems), "***", menuItem("Show Runner", r { bringUpFrame(); }), menuItem("Show Console", r { showConsole(); }), menuItem("Restart Runner", r { restart(); }), menuItem("Show Talk Program [Eleutheria]", r { talkProgram(); }), //menuItem("Hide Console", r { hideConsole(); }), isOfflineMode() ? menuItem("Switch to online mode", r { goOnlineMode(); updateMenu(); }) : menuItem("Switch to offline mode", r { goOfflineMode(); updateMenu(); }), menuItem("Exit", r { System.exit(0); })); } static S getInput() { ret tfCmd.getText().trim(); } static void search(String cmd, final boolean requestFocus) ctex { searching = true; try { status("Searching " + quote(cmd) + "..."); if (empty(cmd)) cmd = "_"; if (cbPrograms.isSelected()) cmd += " type:runnable"; S page = loadPage("http://tinybrain.de:8080/tb/search.php?q=" + urlencode(cmd) + "&limit=" + maxResults + "&sort=modified&quick=1" + standardCredentials()); Matcher m = Pattern.compile(">(#\\d+) - (.*?)
").matcher(page); final new DefaultListModel model; while (m.find()) { String title = m.group(2); title = join(dropAllTags(htmlcoarsetok(title))); model.addElement(htmldecode(m.group(1) + " - " + title)); } awt { list.setModel(model); status("Found " + model.size() + (model.size() == maxResults ? "+" : "") + (cbPrograms.isSelected() ? " runnable(s)." : " snippet(s).")); if (requestFocus) tfCmd.requestFocus(); } } finally { searching = false; } } static void status(final S s) { awt { status.setText(s); } } static void runProgram(final S cmd) { print("Running " + cmd); S msg = format3("*: Running *", now(), cmd); actionHistory.add(msg); logQuoted("run.log", msg); thread { // new thread so we can see progress messages, e.g. for loading the JavaX jar if (useFastNohup) fastNohupJavax(cmd); else nohupJavax(cmd); } } static void runHotwired(final S worker, final long id) { print("Hotwiring " + worker + " on " + id); S msg = format3("*: Hotwiring * on *", now(), worker, id); actionHistory.add(msg); logQuoted("run.log", msg); thread { _run(worker, new S[] {str(id)}); // TODO: cache code? } } static void runCustom(S worker, S item) { if (item == null) ret; int i = item.indexOf(' '); if (i >= 0) item = item.substring(0, i); long id = parseSnippetID(item); print("runCustom: " + id + " [" + worker + "]"); if (empty(worker)) runProgram(str(id)); else runHotwired(worker, id); } static void runWithArguments(S item) { // TODO: run a dialog for that } static void search(final boolean requestFocus) { submittedInput = getInput(); lastSearch = now(); final String cmd = submittedInput; actionHistory.add(format3("*: Searching *", now(), cmd)); thread { search(cmd, requestFocus); } } answer { if "very quick java *" ret format("ok *", structure(callCalc(veryQuickJava(m.unq(0))))); } static void run() { S item = cast list.getModel().getElementAt(list.getSelectedIndex()); runCustom("", item); } static void bringUpFrame() { makeFrameVisible(frame); }