1 package net.argius.stew.ui.window;
3 import static java.awt.event.ActionEvent.ACTION_PERFORMED;
4 import static javax.swing.JOptionPane.*;
5 import static javax.swing.JSplitPane.VERTICAL_SPLIT;
6 import static javax.swing.KeyStroke.getKeyStroke;
7 import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER;
8 import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS;
9 import static net.argius.stew.ui.window.AnyActionKey.*;
12 import java.awt.event.*;
15 import java.lang.Thread.UncaughtExceptionHandler;
18 import java.util.Map.Entry;
19 import java.util.List;
20 import java.util.Timer;
21 import java.util.concurrent.*;
22 import java.util.regex.*;
25 import javax.swing.event.*;
26 import javax.swing.table.*;
27 import javax.swing.text.*;
29 import net.argius.stew.*;
30 import net.argius.stew.ui.*;
31 import net.argius.stew.ui.window.Menu.Item;
34 * The Launcher implementation for GUI(Swing).
36 public final class WindowLauncher implements
40 UncaughtExceptionHandler {
42 private static final Logger log = Logger.getLogger(WindowLauncher.class);
43 private static final ResourceManager res = ResourceManager.getInstance(WindowLauncher.class);
44 private static final List<WindowLauncher> instances = Collections.synchronizedList(new ArrayList<WindowLauncher>());
46 private final WindowOutputProcessor op;
47 private final Menu menu;
48 private final JPanel panel1;
49 private final JPanel panel2;
50 private final JSplitPane split1;
51 private final JSplitPane split2;
52 private final ResultSetTable resultSetTable;
53 private final ConsoleTextArea textArea;
54 private final DatabaseInfoTree infoTree;
55 private final TextSearchPanel textSearchPanel;
56 private final JLabel statusBar;
57 private final List<String> historyList;
58 private final ExecutorService executorService;
60 private Environment env;
61 private Map<JComponent, TextSearch> textSearchMap;
62 private int historyIndex;
63 private JComponent focused;
68 final JSplitPane split1 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
69 final DatabaseInfoTree infoTree = new DatabaseInfoTree(this);
70 final ResultSetTable resultSetTable = new ResultSetTable(this);
71 final JTableHeader resultSetTableHeader = resultSetTable.getTableHeader();
72 final ConsoleTextArea textArea = new ConsoleTextArea(this);
73 this.op = new WindowOutputProcessor(this, resultSetTable, textArea);
74 this.menu = new Menu(this);
75 this.panel1 = new JPanel(new BorderLayout());
76 this.panel2 = new JPanel(new BorderLayout());
78 this.split2 = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
79 this.resultSetTable = resultSetTable;
80 this.textArea = textArea;
81 this.infoTree = infoTree;
82 this.textSearchPanel = new TextSearchPanel(op);
83 this.statusBar = new JLabel(" ");
84 this.historyList = new LinkedList<String>();
85 this.historyIndex = 0;
86 this.executorService = Executors.newScheduledThreadPool(3,
87 DaemonThreadFactory.getInstance());
89 // OutputProcessor as frame
90 op.setTitle(res.get(".title"));
91 op.setIconImage(Utilities.getImageIcon("stew.png").getImage());
92 op.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
93 // splitpane (infotree and sub-splitpane)
94 split1.setResizeWeight(0.6f);
95 split1.setDividerSize(4);
96 // splitpane (table and textarea)
97 split2.setOrientation(VERTICAL_SPLIT);
98 split2.setDividerSize(6);
99 split2.setResizeWeight(0.6f);
101 textArea.setMargin(new Insets(4, 8, 4, 4));
102 textArea.setLineWrap(true);
103 textArea.setWrapStyleWord(false);
105 this.textSearchMap = new LinkedHashMap<JComponent, TextSearch>();
106 final TextSearchPanel textSearchPanel = this.textSearchPanel;
107 final Map<JComponent, TextSearch> textSearchMap = this.textSearchMap;
108 textSearchMap.put(infoTree, infoTree);
109 textSearchMap.put(resultSetTable, resultSetTable);
110 textSearchMap.put(resultSetTableHeader,
111 new ResultSetTable.TableHeaderTextSearch(resultSetTable,
112 resultSetTableHeader));
113 textSearchMap.put(textArea, textArea);
114 for (Entry<JComponent, TextSearch> entry : textSearchMap.entrySet()) {
115 final JComponent c = entry.getKey();
116 c.addFocusListener(new FocusAdapter() {
118 public void focusGained(FocusEvent e) {
120 textSearchPanel.setCurrentTarget(textSearchMap.get(c));
123 textSearchPanel.addTarget(entry.getValue());
126 statusBar.setForeground(Color.BLUE);
129 * split2 = ResultSetTable + TextArea
130 * +----------------------------+
132 * | +------------------------+ |
133 * | | scroll(resultSetTable) | |
134 * | +------------------------+ |
135 * | +------------------------+ |
137 * | | +--------------------+ | |
138 * | | | scroll(textArea) | | |
139 * | | +--------------------+ | |
140 * | | | textSearchPanel | | |
141 * | | +--------------------+ | |
142 * | +------------------------+ |
143 * +----------------------------+
144 * when DatabaseInfoTree is visible
145 * +-----------------------------------+
147 * | +-------------------------------+ |
149 * | | +------------+ +------------+ | |
150 * | | | scroll | | split2 | | |
151 * | | | (infoTree) | | | | |
152 * | | +------------+ +------------+ | |
153 * | +-------------------------------+ |
154 * +-----------------------------------+
156 * +-----------------------------------+
157 * when DatabaseInfoTree is not visible
158 * +-----------------------------------+
160 * | +-------------------------------+ |
162 * | +-------------------------------+ |
163 * +-----------------------------------+
165 * +-----------------------------------+
167 panel2.add(new JScrollPane(textArea, VERTICAL_SCROLLBAR_ALWAYS, HORIZONTAL_SCROLLBAR_NEVER),
168 BorderLayout.CENTER);
169 panel2.add(textSearchPanel, BorderLayout.SOUTH);
170 split2.setTopComponent(new JScrollPane(resultSetTable));
171 split2.setBottomComponent(panel2);
172 op.add(panel1, BorderLayout.CENTER);
173 op.add(statusBar, BorderLayout.PAGE_END);
174 op.setJMenuBar(menu);
175 // [Restores Configs]
176 op.addPropertyChangeListener(menu);
177 infoTree.addPropertyChangeListener(menu);
178 resultSetTable.addPropertyChangeListener(menu);
179 statusBar.addPropertyChangeListener(menu);
181 op.removePropertyChangeListener(menu);
182 infoTree.removePropertyChangeListener(menu);
183 resultSetTable.removePropertyChangeListener(menu);
184 // XXX cannot restore config of status-bar at following code
185 // statusBar.removePropertyChangeListener(menu);
187 op.addWindowListener(new WindowAdapter() {
189 public void windowClosing(WindowEvent e) {
193 ContextMenu.create(infoTree, infoTree);
194 ContextMenu.create(resultSetTable);
195 ContextMenu.create(resultSetTable.getRowHeader(), resultSetTable, "ResultSetTable");
196 ContextMenu.create(resultSetTableHeader, resultSetTable, "ResultSetTableColumnHeader");
197 ContextMenu.createForText(textArea);
201 public void launch(Environment env) {
203 op.setEnvironment(env);
205 op.output(new Prompt(env));
206 textArea.requestFocus();
211 Thread.setDefaultUncaughtExceptionHandler(this);
216 public void uncaughtException(Thread t, Throwable e) {
217 log.fatal(e, "%s", t);
218 op.showErrorDialog(e);
222 public void anyActionPerformed(AnyActionEvent ev) {
223 log.atEnter("anyActionPerformed", ev);
226 resultSetTable.editingCanceled(new ChangeEvent(ev.getSource()));
227 final Object source = ev.getSource();
228 if (ev.isAnyOf(newWindow)) {
230 } else if (ev.isAnyOf(closeWindow)) {
232 } else if (ev.isAnyOf(quit)) {
234 } else if (ev.isAnyOf(showInfoTree)) {
235 setInfoTreePaneVisibility(((JCheckBoxMenuItem)source).isSelected());
238 } else if (ev.isAnyOf(cut, copy, paste, selectAll)) {
239 if (focused != null) {
241 if (ev.isAnyOf(cut)) {
242 if (focused instanceof JTextComponent) {
243 cmd = "cut-to-clipboard";
247 } else if (ev.isAnyOf(copy)) {
248 if (focused instanceof JTextComponent) {
249 cmd = "copy-to-clipboard";
251 cmd = ev.getActionCommand();
253 } else if (ev.isAnyOf(paste)) {
254 if (focused instanceof JTextComponent) {
255 cmd = "paste-from-clipboard";
256 } else if (focused instanceof DatabaseInfoTree) {
259 cmd = ev.getActionCommand();
261 } else if (ev.isAnyOf(selectAll)) {
262 if (focused instanceof JTextComponent) {
265 cmd = ev.getActionCommand();
270 if (cmd.length() == 0) {
271 log.debug("no action: %s, cmd=%s",
273 ev.getActionCommand());
275 final Action action = focused.getActionMap().get(cmd);
276 log.debug("convert to plain Action Event: orig=%s", ev);
277 action.actionPerformed(new ActionEvent(focused, ACTION_PERFORMED, cmd));
280 } else if (ev.isAnyOf(find)) {
281 textSearchPanel.setCurrentTarget(textSearchMap.get(focused));
282 textSearchPanel.setVisible(true);
283 } else if (ev.isAnyOf(toggleFocus)) {
284 if (textArea.isFocusOwner()) {
285 resultSetTable.requestFocus();
287 textArea.requestFocus();
289 } else if (ev.isAnyOf(clearMessage)) {
292 } else if (ev.isAnyOf(showStatusBar)) {
293 statusBar.setVisible(((JCheckBoxMenuItem)source).isSelected());
294 } else if (ev.isAnyOf(showColumnNumber)) {
295 resultSetTable.anyActionPerformed(ev);
296 } else if (ev.isAnyOf(refresh)) {
298 } else if (ev.isAnyOf(autoAdjustModeNone,
299 autoAdjustModeHeader,
301 autoAdjustModeHeaderAndValue)) {
302 resultSetTable.setAutoAdjustMode(ev.getActionCommand());
303 } else if (ev.isAnyOf(widenColumnWidth, narrowColumnWidth, adjustColumnWidth)) {
304 resultSetTable.anyActionPerformed(ev);
305 } else if (ev.isAnyOf(executeCommand, execute)) {
306 executeCommand(textArea.getEditableText());
307 } else if (ev.isAnyOf(breakCommand)) {
308 env.getOutputProcessor().close();
309 env.setOutputProcessor(new WindowOutputProcessor.Bypass(op));
310 op.output(res.get("i.cancelled"));
312 } else if (ev.isAnyOf(lastHistory)) {
314 } else if (ev.isAnyOf(nextHistory)) {
316 } else if (ev.isAnyOf(sendRollback)) {
317 if (confirmCommitable()
318 && showConfirmDialog(op, res.get("i.confirm-rollback"), null, OK_CANCEL_OPTION) == OK_OPTION) {
319 executeCommand("rollback");
321 } else if (ev.isAnyOf(sendCommit)) {
322 if (confirmCommitable()
323 && showConfirmDialog(op, res.get("i.confirm-commit"), null, OK_CANCEL_OPTION) == OK_OPTION) {
324 executeCommand("commit");
326 } else if (ev.isAnyOf(connect)) {
327 env.updateConnectorMap();
328 if (env.getConnectorMap().isEmpty()) {
329 showMessageDialog(op, res.get("w.no-connector"));
332 Object[] a = ConnectorEntry.toList(env.getConnectorMap().values()).toArray();
333 final String m = res.get("i.choose-connection");
334 Object value = showInputDialog(op, m, null, PLAIN_MESSAGE, null, a, a[0]);
336 ConnectorEntry c = (ConnectorEntry)value;
337 executeCommand("connect " + c.getId());
339 } else if (ev.isAnyOf(disconnect)) {
340 executeCommand("disconnect");
341 } else if (ev.isAnyOf(postProcessModeNone,
342 postProcessModeFocus,
343 postProcessModeShake,
344 postProcessModeBlink)) {
345 op.setPostProcessMode(ev.getActionCommand());
346 } else if (ev.isAnyOf(inputEcryptionKey)) {
348 } else if (ev.isAnyOf(editConnectors)) {
350 } else if (ev.isAnyOf(sortResult)) {
351 resultSetTable.doSort(resultSetTable.getSelectedColumn());
352 } else if (ev.isAnyOf(importFile, exportFile, showAbout)) {
353 op.anyActionPerformed(ev);
354 } else if (ev.isAnyOf(showHelp)) {
356 } else if (ev.isAnyOf(ResultSetTable.ActionKey.findColumnName)) {
357 resultSetTable.getTableHeader().requestFocus();
358 textSearchPanel.setVisible(true);
359 } else if (ev.isAnyOf(ResultSetTable.ActionKey.jumpToColumn)) {
360 resultSetTable.anyActionPerformed(ev);
361 } else if (ev.isAnyOf(ConsoleTextArea.ActionKey.insertText)) {
362 textArea.anyActionPerformed(ev);
364 log.warn("not expected: Event=%s", ev);
366 } catch (Exception ex) {
367 op.showErrorDialog(ex);
369 log.atExit("dispatch");
373 * Controls visibility of DatabaseInfoTree pane.
376 void setInfoTreePaneVisibility(boolean show) {
379 split1.setTopComponent(new JScrollPane(infoTree));
380 split1.setBottomComponent(split2);
382 panel1.add(split1, BorderLayout.CENTER);
383 infoTree.setEnabled(true);
386 infoTree.refreshRoot(env);
387 } catch (SQLException ex) {
389 op.showErrorDialog(ex);
394 infoTree.setEnabled(false);
396 panel1.add(split2, BorderLayout.CENTER);
398 SwingUtilities.updateComponentTreeUI(op);
401 private void loadConfiguration() {
402 Configuration cnf = Configuration.load(Bootstrap.getDirectory());
403 op.setSize(cnf.getSize());
404 op.setLocation(cnf.getLocation());
405 split2.setDividerLocation(cnf.getDividerLocation());
406 statusBar.setVisible(cnf.isShowStatusBar());
407 resultSetTable.setShowColumnNumber(cnf.isShowTableColumnNumber());
408 split1.setDividerLocation(cnf.getDividerLocation0());
409 op.setAlwaysOnTop(cnf.isAlwaysOnTop());
410 resultSetTable.setAutoAdjustMode(cnf.getAutoAdjustMode());
411 op.setPostProcessMode(cnf.getPostProcessMode());
412 setInfoTreePaneVisibility(cnf.isShowInfoTree());
413 changeFont("monospaced", Font.PLAIN, 1.0d);
416 private void saveConfiguration() {
417 Configuration cnf = Configuration.load(Bootstrap.getDirectory());
418 if ((op.getExtendedState() & Frame.MAXIMIZED_BOTH) == 0) {
419 // only not maximized
420 cnf.setSize(op.getSize());
421 cnf.setLocation(op.getLocation());
422 cnf.setDividerLocation(split2.getDividerLocation());
423 cnf.setDividerLocation0(split1.getDividerLocation());
425 cnf.setShowStatusBar(statusBar.isVisible());
426 cnf.setShowTableColumnNumber(resultSetTable.isShowColumnNumber());
427 cnf.setShowInfoTree(infoTree.isEnabled());
428 cnf.setAlwaysOnTop(op.isAlwaysOnTop());
429 cnf.setAutoAdjustMode(resultSetTable.getAutoAdjustMode());
430 cnf.setPostProcessMode(op.getPostProcessMode());
435 * Configuration (Bean) for saving and loading.
437 @SuppressWarnings("all")
438 public static final class Configuration {
440 private static final Logger log = Logger.getLogger(Configuration.class);
442 private transient File directory;
444 private Dimension size;
445 private Point location;
446 private int dividerLocation;
447 private int dividerLocation0;
448 private boolean showStatusBar;
449 private boolean showTableColumnNumber;
450 private boolean showInfoTree;
451 private boolean alwaysOnTop;
452 private String autoAdjustMode;
453 private String postProcessMode;
455 public Configuration() {
456 this.size = new Dimension(640, 480);
457 this.location = new Point(200, 200);
458 this.dividerLocation = -1;
459 this.dividerLocation0 = -1;
460 this.showStatusBar = false;
461 this.showTableColumnNumber = false;
462 this.showInfoTree = false;
463 this.alwaysOnTop = false;
464 this.autoAdjustMode = AnyActionKey.autoAdjustMode.toString();
465 this.postProcessMode = AnyActionKey.postProcessMode.toString();
468 void setDirectory(File directory) {
469 this.directory = directory;
473 final File file = getFile(directory);
474 log.debug("save Configuration to: [%s]", file);
476 XMLEncoder encoder = new XMLEncoder(new FileOutputStream(file));
478 encoder.writeObject(this);
482 } catch (Exception ex) {
487 static Configuration load(File directory) {
488 final File file = getFile(directory);
489 log.debug("load Configuration from: [%s]", file);
492 XMLDecoder decoder = new XMLDecoder(new FileInputStream(file));
494 final Configuration instance = (Configuration)decoder.readObject();
495 instance.setDirectory(directory);
500 } catch (Exception ex) {
504 final Configuration instance = new Configuration();
505 instance.setDirectory(directory);
509 private static File getFile(File systemDirectory) {
510 final File file = new File(systemDirectory, Configuration.class.getName() + ".xml");
511 return file.getAbsoluteFile();
514 public Dimension getSize() {
518 public void setSize(Dimension size) {
522 public Point getLocation() {
526 public void setLocation(Point location) {
527 this.location = location;
530 public int getDividerLocation() {
531 return dividerLocation;
534 public void setDividerLocation(int dividerLocation) {
535 this.dividerLocation = dividerLocation;
538 public int getDividerLocation0() {
539 return dividerLocation0;
542 public void setDividerLocation0(int dividerLocation0) {
543 this.dividerLocation0 = dividerLocation0;
546 public boolean isShowStatusBar() {
547 return showStatusBar;
550 public void setShowStatusBar(boolean showStatusBar) {
551 this.showStatusBar = showStatusBar;
554 public boolean isShowTableColumnNumber() {
555 return showTableColumnNumber;
558 public void setShowTableColumnNumber(boolean showTableColumnNumber) {
559 this.showTableColumnNumber = showTableColumnNumber;
562 public boolean isShowInfoTree() {
566 public void setShowInfoTree(boolean showInfoTree) {
567 this.showInfoTree = showInfoTree;
570 public boolean isAlwaysOnTop() {
574 public void setAlwaysOnTop(boolean alwaysOnTop) {
575 this.alwaysOnTop = alwaysOnTop;
578 public String getAutoAdjustMode() {
579 return autoAdjustMode;
582 public void setAutoAdjustMode(String autoAdjustMode) {
583 this.autoAdjustMode = autoAdjustMode;
586 public String getPostProcessMode() {
587 return postProcessMode;
590 public void setPostProcessMode(String postProcessMode) {
591 this.postProcessMode = postProcessMode;
596 private void changeFont(String family, int style, double sizeRate) {
597 FontControlLookAndFeel.change(family, style, sizeRate);
598 SwingUtilities.updateComponentTreeUI(op);
599 Font newfont = textArea.getFont();
600 if (newfont != null) {
601 statusBar.setFont(newfont.deriveFont(newfont.getSize() * 0.8f));
605 void handleError(Throwable th) {
607 op.showErrorDialog(th);
612 * @param keyBindInfos key bind infos (info is String value of KeyStroke)
614 static void changeKeyBinds(List<String> keyBindInfos) {
615 final Pattern p = Pattern.compile("\\s*([^=\\s]+)\\s*=(.*)");
616 List<String> errorInfos = new ArrayList<String>();
617 for (String s : keyBindInfos) {
618 if (s.trim().length() == 0 || s.matches("\\s*#.*")) {
621 Matcher m = p.matcher(s);
624 Item item = Item.valueOf(m.group(1));
625 KeyStroke keyStroke = getKeyStroke(m.group(2));
626 for (WindowLauncher instance : instances) {
627 instance.menu.setAccelerator(item, keyStroke);
629 } catch (Exception ex) {
636 if (!errorInfos.isEmpty()) {
637 throw new IllegalArgumentException(errorInfos.toString());
641 static void invoke() {
642 invoke(new WindowLauncher());
645 static void invoke(WindowLauncher instance) {
646 final Environment env = new Environment();
647 env.setOutputProcessor(new WindowOutputProcessor.Bypass(instance.op));
648 instance.launch(env);
651 File keyBindConf = new File(Bootstrap.getDirectory(), "keybind.conf");
652 if (keyBindConf.exists()) {
653 List<String> a = new ArrayList<String>();
654 Scanner scanner = new Scanner(keyBindConf);
656 while (scanner.hasNextLine()) {
657 a.add(scanner.nextLine());
664 } catch (Exception ex) {
665 instance.handleError(ex);
670 * Starts to exit application.
673 for (WindowLauncher instance : new ArrayList<WindowLauncher>(instances)) {
676 } catch (Exception ex) {
677 log.warn(ex, "error occurred when closing all instances");
683 * Closes this window.
686 instances.remove(this);
690 executorService.shutdown();
697 * Confirms whether pressed YES or not at dialog.
699 * @return true if pressed YES
701 private boolean confirmYes(String message) {
702 return showConfirmDialog(op, message, "", YES_NO_OPTION) == YES_OPTION;
705 private boolean confirmCommitable() {
706 if (env.getCurrentConnection() == null) {
707 showMessageDialog(op, res.get("w.not-connect"), null, OK_OPTION);
710 if (env.getCurrentConnector().isReadOnly()) {
711 showMessageDialog(op, res.get("w.connector-readonly"), null, OK_OPTION);
717 private void retrieveHistory(int value) {
718 if (historyList.isEmpty()) {
721 historyIndex += value;
722 if (historyIndex >= historyList.size()) {
724 } else if (historyIndex < 0) {
725 historyIndex = historyList.size() - 1;
727 textArea.replace(historyList.get(historyIndex));
728 final int endPosition = textArea.getEndPosition();
729 textArea.setSelectionStart(endPosition);
730 textArea.moveCaretPosition(endPosition);
731 textArea.requestFocus();
735 * Requests to close this window.
737 void requestClose() {
738 if (instances.size() == 1) {
740 } else if (env.getCurrentConnection() == null || confirmYes(res.get("i.confirm-close"))) {
746 * Requests to exit this application.
749 if (confirmYes(res.get("i.confirm-quit"))) {
754 private void refreshResult() {
755 if (resultSetTable.getModel() instanceof ResultSetTableModel) {
756 ResultSetTableModel m = resultSetTable.getResultSetTableModel();
757 if (m.isSameConnection(env.getCurrentConnection())) {
758 final String s = m.getCommandString();
759 if (s != null && s.length() > 0) {
766 private void editEncryptionKey() {
767 JPasswordField password = new JPasswordField(20);
768 Object[] a = {res.get("i.input-encryption-key"), password};
769 if (showConfirmDialog(op, a, null, OK_CANCEL_OPTION) == OK_OPTION) {
770 CipherPassword.setSecretKey(String.valueOf(password.getPassword()));
774 private void editConnectorMap() {
775 env.updateConnectorMap();
776 if (env.getCurrentConnector() != null) {
777 showMessageDialog(op, res.get("i.reconnect-after-edited-current-connector"));
779 ConnectorMapEditDialog dialog = new ConnectorMapEditDialog(op, env);
781 dialog.setModal(true);
782 dialog.setLocationRelativeTo(op);
783 dialog.setVisible(true);
784 env.updateConnectorMap();
787 private static void showHelp() {
788 final String htmlFileName = "MANUAL_ja.html";
789 if (Desktop.isDesktopSupported()) {
790 Desktop desktop = Desktop.getDesktop();
791 if (desktop.isSupported(Desktop.Action.OPEN)) {
792 File file = new File(htmlFileName);
796 } catch (IOException ex) {
797 throw new RuntimeException(ex);
802 final String msg = res.get("e.cannot-open-help-automatically", htmlFileName);
803 WindowOutputProcessor.showInformationMessageDialog(getRootFrame(), msg, "");
808 * Executes a command.
809 * @param commandString
811 void executeCommand(String commandString) {
812 assert commandString != null;
813 if (!commandString.equals(textArea.getEditableText())) {
814 textArea.replace(commandString);
817 if (commandString.trim().length() == 0) {
820 final String cmd = commandString;
821 final Environment env = this.env;
822 final DatabaseInfoTree infoTree = this.infoTree;
823 final JLabel statusBar = this.statusBar;
824 final OutputProcessor opref = env.getOutputProcessor();
827 executorService.execute(new Runnable() {
830 Connection conn = env.getCurrentConnection();
831 long time = System.currentTimeMillis();
832 if (!Command.invoke(env, cmd)) {
835 if (infoTree.isEnabled()) {
837 if (env.getCurrentConnection() != conn) {
839 if (env.getCurrentConnection() != null) {
840 infoTree.refreshRoot(env);
843 } catch (Throwable th) {
847 if (env.getOutputProcessor() == opref) {
848 time = System.currentTimeMillis() - time;
849 statusBar.setText(res.get("i.statusbar-message", time / 1000f, cmd));
850 AnyAction invoker = new AnyAction(this);
851 invoker.doLater("callDoPostProcess");
854 @SuppressWarnings("unused")
855 void callDoPostProcess() {
856 WindowLauncher.this.doPostProcess();
859 } catch (Exception ex) {
860 throw new RuntimeException(ex);
862 historyIndex = historyList.size();
864 if (historyList.contains(commandString)) {
865 historyList.remove(commandString);
867 historyList.add(commandString);
869 historyIndex = historyList.size();
872 void doPreProcess() {
873 ((Menu)op.getJMenuBar()).setEnabledStates(true);
874 resultSetTable.setEnabled(false);
875 textArea.setEnabled(false);
879 void doPostProcess() {
880 ((Menu)op.getJMenuBar()).setEnabledStates(false);
881 resultSetTable.setEnabled(true);
882 textArea.setEnabled(true);
883 op.output(new Prompt(env));
887 static void wakeup() {
888 for (WindowLauncher instance : new ArrayList<WindowLauncher>(instances)) {
890 SwingUtilities.updateComponentTreeUI(instance.op);
891 } catch (Exception ex) {
898 private static final class WakeupTimerTask extends TimerTask {
899 private final AnyAction aa = new AnyAction(this);
902 aa.doLater("callWakeup");
904 @SuppressWarnings("unused")
914 public static void main(String... args) {
915 final int residentCycle = Bootstrap.getPropertyAsInt("net.argius.stew.ui.window.resident",
917 if (residentCycle > 0) {
918 final long msec = residentCycle * 60000L;
919 Timer timer = new Timer(true);
920 timer.scheduleAtFixedRate(new WakeupTimerTask(), msec, msec);
922 EventQueue.invokeLater(new WindowLauncher());