0001: /*
0002: * QueryEditorTextPanel.java
0003: *
0004: * Copyright (C) 2002, 2003, 2004, 2005, 2006 Takis Diakoumis
0005: *
0006: * This program is free software; you can redistribute it and/or
0007: * modify it under the terms of the GNU General Public License
0008: * as published by the Free Software Foundation; either version 2
0009: * of the License, or any later version.
0010: *
0011: * This program is distributed in the hope that it will be useful,
0012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0014: * GNU General Public License for more details.
0015: *
0016: * You should have received a copy of the GNU General Public License
0017: * along with this program; if not, write to the Free Software
0018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
0019: *
0020: */
0021:
0022: package org.executequery.gui.editor;
0023:
0024: import java.awt.AWTException;
0025: import java.awt.BorderLayout;
0026: import java.awt.Color;
0027: import java.awt.Component;
0028: import java.awt.Graphics;
0029: import java.awt.Insets;
0030: import java.awt.Robot;
0031: import java.awt.event.MouseListener;
0032: import java.awt.event.ActionListener;
0033: import java.awt.event.ActionEvent;
0034: import java.awt.event.MouseEvent;
0035: import java.awt.event.KeyEvent;
0036:
0037: import javax.swing.JPanel;
0038: import javax.swing.JScrollPane;
0039: import javax.swing.JTextPane;
0040: import javax.swing.JMenuItem;
0041: import javax.swing.KeyStroke;
0042: import javax.swing.JPopupMenu;
0043:
0044: import java.sql.SQLException;
0045: import java.sql.ResultSet;
0046:
0047: import java.util.Vector;
0048: import java.util.regex.Matcher;
0049: import java.util.regex.Pattern;
0050: import javax.swing.SwingUtilities;
0051: import javax.swing.border.Border;
0052: import javax.swing.text.BadLocationException;
0053: import javax.swing.text.Document;
0054: import javax.swing.text.Element;
0055:
0056: import org.executequery.GUIUtilities;
0057: import org.underworldlabs.util.SystemProperties;
0058: import org.executequery.SystemUtilities;
0059: import org.executequery.gui.text.TextUtilities;
0060: import org.underworldlabs.swing.actions.ActionBuilder;
0061: import org.executequery.databasemediators.DatabaseConnection;
0062: import org.executequery.gui.SQLExecutor;
0063: import org.underworldlabs.swing.GUIUtils;
0064:
0065: /* ----------------------------------------------------------
0066: * CVS NOTE: Changes to the CVS repository prior to the
0067: * release of version 3.0.0beta1 has meant a
0068: * resetting of CVS revision numbers.
0069: * ----------------------------------------------------------
0070: */
0071:
0072: /** <p>This object is the primary mediator between the parent
0073: * <code>QueryEditor</code> object and the actual Query Editor's
0074: * text pane - the <code>QueryEditorTextPane</code>. All commands for the
0075: * text pane are propagated through here. This includes all requests
0076: * to execute queries, maintainance of the executed history list,
0077: * the editor's popup menu to the more simple cut/copy/paste commands.
0078: *
0079: * @author Takis Diakoumis
0080: * @version $Revision: 1.8 $
0081: * @date $Date: 2006/08/24 09:38:11 $
0082: */
0083: public class QueryEditorTextPanel extends JPanel implements
0084: SQLExecutor, MouseListener {
0085:
0086: /** The SQL text pane */
0087: private QueryEditorTextPane queryPane;
0088:
0089: /** The editor's controller */
0090: private QueryEditor queryEditor;
0091:
0092: /** Analyses and executes queries */
0093: private QueryAnalyser analyser;
0094:
0095: /** The text pane's popup menu */
0096: private PopMenu popup;
0097:
0098: /** The current history index */
0099: private int historyNum;
0100:
0101: /** Constructs a new instance. */
0102: public QueryEditorTextPanel(QueryEditor queryEditor) {
0103: super (new BorderLayout());
0104:
0105: this .queryEditor = queryEditor;
0106:
0107: try {
0108: jbInit();
0109: } catch (Exception e) {
0110: e.printStackTrace();
0111: }
0112:
0113: historyNum = -1;
0114: //historyList = new Vector();
0115: }
0116:
0117: /** Initializes the state of this instance. */
0118: private void jbInit() throws Exception {
0119: // setup the query text panel and associated scroller
0120: queryPane = new QueryEditorTextPane(this );
0121: analyser = new QueryAnalyser(this );
0122:
0123: JScrollPane queryScroller = new JScrollPane();
0124: queryScroller.getViewport().add(queryPane, BorderLayout.CENTER);
0125: queryScroller.setRowHeaderView(queryPane.getLineBorder());
0126: queryScroller
0127: .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
0128: queryScroller.setBorder(new EditorScrollerBorder());
0129:
0130: //setPreferredSize(QueryEditorConstants.PANEL_SIZE);
0131: add(queryScroller, BorderLayout.CENTER);
0132:
0133: popup = new PopMenu();
0134: queryPane.addMouseListener(this );
0135:
0136: boolean commitMode = SystemProperties.getBooleanProperty(
0137: "user", "editor.connection.commit");
0138: popup.enableCommits(!commitMode);
0139: }
0140:
0141: public void setActivityStatusText(String s) {
0142: queryEditor.setActivityStatusText(s);
0143: }
0144:
0145: public void destroyConnection() {
0146: analyser.destroyConnection();
0147: }
0148:
0149: public void setTextPaneBackground(Color c) {
0150: queryPane.setBackground(c);
0151: }
0152:
0153: public void setSQLKeywords(boolean reset) {
0154: queryPane.setSQLKeywords(reset);
0155: }
0156:
0157: public void setExecuting(boolean executing) {
0158: queryEditor.setExecuting(executing);
0159: }
0160:
0161: public void setOutputMessage(int type, String text) {
0162: queryEditor.setOutputMessage(type, text);
0163: }
0164:
0165: /*
0166: public void setExecutingMessage(String s) {
0167: queryEditor.setExecutingMessage(s);
0168: }
0169: */
0170:
0171: /**
0172: * Indicates that the editor is closing and performs some cleanup.
0173: */
0174: protected void closingEditor() {
0175: closeConnection();
0176:
0177: /* ------------------------------------------------
0178: * profiling found the popup keeps the
0179: * editor from being garbage collected at all!!
0180: * a call to removeAll() is a work around for now.
0181: * ------------------------------------------------
0182: */
0183: popup.removeAll();
0184:
0185: queryEditor = null;
0186: }
0187:
0188: public void showLineNumbers(boolean show) {
0189: queryPane.showLineNumbers(show);
0190: }
0191:
0192: protected void setTextFocus() {
0193: GUIUtils.requestFocusInWindow(queryPane);
0194: }
0195:
0196: /**
0197: * Resets the executing line within the line
0198: * number border panel.
0199: */
0200: public void resetExecutingLine() {
0201: queryPane.resetExecutingLine();
0202: }
0203:
0204: /**
0205: * Resets the text pane's caret position to zero.
0206: */
0207: public void resetCaretPosition() {
0208: queryPane.setCaretPosition(0);
0209: }
0210:
0211: /**
0212: * Interrupts any executing statements and propagates the
0213: * call to close the connection to the QueryAnalyser object.
0214: */
0215: public void closeConnection() {
0216: interruptStatement();
0217: analyser.closeConnection();
0218: }
0219:
0220: /**
0221: * Returns whether a statement execution is in progress.
0222: *
0223: * @return true | false
0224: */
0225: public boolean isExecuting() {
0226: return analyser.isExecuting();
0227: }
0228:
0229: /**
0230: * Sets the editor's auto-commit mode to that specified.
0231: */
0232: public void setCommitMode(boolean mode) {
0233: analyser.setCommitMode(mode);
0234: popup.enableCommits(!mode);
0235: }
0236:
0237: /**
0238: * Returns the editor's current auto-commit mode.
0239: */
0240: public boolean getCommitMode() {
0241: return analyser.getCommitMode();
0242: }
0243:
0244: // -------------------------------------
0245: // Executed query history methods
0246: // -------------------------------------
0247:
0248: /**
0249: * Selects the next query from the history list and places the
0250: * query text into the editor.
0251: */
0252: public void selectNextQuery() {
0253: Vector history = SystemUtilities.getSqlCommandHistory();
0254: queryPane.setText((String) history
0255: .elementAt(decrementHistoryNum()));
0256: }
0257:
0258: /**
0259: * Selects the previous query from the history list and places the
0260: * query text into the editor.
0261: */
0262: public void selectPrevQuery() {
0263: Vector history = SystemUtilities.getSqlCommandHistory();
0264: queryPane.setText((String) history
0265: .elementAt(incrementHistoryNum()));
0266: }
0267:
0268: /**
0269: * Increments the history index value.
0270: */
0271: private int incrementHistoryNum() {
0272: // for previous
0273: Vector history = SystemUtilities.getSqlCommandHistory();
0274: if (historyNum < history.size() - 1) {
0275: historyNum++;
0276: }
0277:
0278: queryEditor.setNextButtonEnabled(true);
0279:
0280: if (historyNum == history.size() - 1) {// || historyNum == 0) {
0281: queryEditor.setPreviousButtonEnabled(false);
0282: }
0283:
0284: return historyNum;
0285: }
0286:
0287: /**
0288: * Decrements the history index value.
0289: */
0290: private int decrementHistoryNum() {
0291: if (historyNum != 0) {
0292: historyNum--;
0293: }
0294:
0295: queryEditor.setPreviousButtonEnabled(true);
0296:
0297: if (historyNum == 0) {
0298: queryEditor.setNextButtonEnabled(false);
0299: }
0300:
0301: return historyNum;
0302: }
0303:
0304: /** ignored statements for the history list */
0305: private final String[] HISTORY_IGNORE = { "COMMIT", "ROLLBACK" };
0306:
0307: /**
0308: * Adds the secified query to the executed statement history list.
0309: */
0310: public void addToHistory(String query) {
0311: String _query = query.toUpperCase();
0312: for (int i = 0; i < HISTORY_IGNORE.length; i++) {
0313: if (HISTORY_IGNORE[i].compareTo(_query) == 0) {
0314: return;
0315: }
0316: }
0317: SystemUtilities.addSqlCommand(query);
0318: }
0319:
0320: /**
0321: * Returns whether a call to previous history would be successful.
0322: */
0323: public boolean hasPreviousHistory() {
0324: Vector history = SystemUtilities.getSqlCommandHistory();
0325: return historyNum < history.size() - 1;
0326: }
0327:
0328: /**
0329: * Returns whether a call to next history would be successful.
0330: */
0331: public boolean hasNextHistory() {
0332: return historyNum > 0;
0333: }
0334:
0335: /**
0336: * Returns the executed query history list.
0337: */
0338: public Vector getHistoryList() {
0339: return SystemUtilities.getSqlCommandHistory();
0340: }
0341:
0342: /**
0343: * Enters the specified text at the editor's current
0344: * insertion point.
0345: *
0346: * @param text - the text to insert
0347: */
0348: public void insertTextAtCaret(String text) {
0349: int caretIndex = queryPane.getCaretPosition();
0350: queryPane.replaceSelection(text);
0351: setTextFocus();
0352: }
0353:
0354: public JTextPane getQueryArea() {
0355: return queryPane;
0356: }
0357:
0358: public void selectAll() {
0359: TextUtilities.selectAll(queryPane);
0360: }
0361:
0362: public void selectNone() {
0363: TextUtilities.selectNone(queryPane);
0364: }
0365:
0366: public void focusGained() {
0367: queryEditor.focusGained();
0368: }
0369:
0370: public void focusLost() {
0371: if (queryEditor != null) {
0372: queryEditor.focusLost();
0373: }
0374: }
0375:
0376: public void setRightStatusText(String s) {
0377: queryEditor.setRightStatusText(s);
0378: }
0379:
0380: /**
0381: * Sets the editor's text content that specified.
0382: *
0383: * @param s - the text to be set
0384: */
0385: public void setQueryAreaText(String s) {
0386: try {
0387: // uninstall listeners on the text pane
0388: queryPane.uninstallListeners();
0389: // clear the current held edits
0390: queryPane.clearEdits();
0391: // set the text
0392: queryPane.setText(s);
0393: } finally {
0394: // reinstall listeners on the text pane
0395: queryPane.reinstallListeners();
0396: }
0397: }
0398:
0399: /**
0400: * Loads the specified text into a blank 'offscreen' document
0401: * before switching to the SQL document.
0402: */
0403: public void loadText(String text) {
0404: queryPane.loadText(text);
0405: }
0406:
0407: /**
0408: * Clears the output pane.
0409: */
0410: public void clearOutputPane() {
0411: if (analyser.isExecuting()) {
0412: return;
0413: }
0414: queryEditor.clearOutputPane();
0415: }
0416:
0417: public QueryEditorStatusBar getStatusBar() {
0418: return queryEditor.getStatusBar();
0419: }
0420:
0421: public void disableUpdates(boolean disable) {
0422: queryPane.disableUpdates(disable);
0423: }
0424:
0425: public void disableCaretUpdate(boolean disable) {
0426: queryPane.disableCaretUpdate(disable);
0427: }
0428:
0429: public void preferencesChanged() {
0430: queryPane.resetAttributeSets();
0431: analyser.preferencesChanged();
0432: }
0433:
0434: /**
0435: * Indicates a connection has been closed.
0436: *
0437: * @param the connection thats been closed
0438: */
0439: public void disconnected(DatabaseConnection dc) {
0440: analyser.disconnected(dc);
0441: }
0442:
0443: // -----------------------------------
0444: // regex replacement arrays
0445: // -----------------------------------
0446:
0447: private static final String[] REGEX_CHARS = { "\\*", "\\^", "\\.",
0448: "\\[", "\\]", "\\(", "\\)", "\\?", "\\&", "\\{", "\\}",
0449: "\\+" };
0450:
0451: private static final String[] REGEX_SUBS = { "\\\\*", "\\\\^",
0452: "\\\\.", "\\\\[", "\\\\]", "\\\\(", "\\\\)", "\\\\?",
0453: "\\\\&", "\\\\{", "\\\\}", "\\\\+" };
0454:
0455: /**
0456: * Moves the caret to the beginning of the specified query.
0457: *
0458: * @param query - the query to move the cursor to
0459: */
0460: public void caretToQuery(String query) {
0461:
0462: /*
0463: String num = query.substring(query.indexOf("Z") + 1, query.indexOf("Z") + 3);
0464: int number = Integer.parseInt(num);
0465: Log.debug("number: " + number);
0466: */
0467:
0468: // replace any regex control chars
0469: for (int i = 0; i < REGEX_CHARS.length; i++) {
0470: //if (i == number) i++;
0471:
0472: query = query.replaceAll(REGEX_CHARS[i], REGEX_SUBS[i]);
0473:
0474: //Log.debug("index : " + i + " " + query);
0475: }
0476:
0477: /*
0478: Log.debug("---------------------");
0479: Log.debug(query);
0480: Log.debug("---------------------");
0481: */
0482:
0483: // replace the block comment marker
0484: //query = query.replaceAll(
0485: // QueryEditorConstants.BLOCK_COMMENT_REGEX,
0486: // ".*/\\\\*.*\\\\*/.*");
0487: Matcher matcher = Pattern.compile(query, Pattern.DOTALL)
0488: .matcher(queryPane.getText());
0489:
0490: if (matcher.find()) {
0491: int index = matcher.start();
0492: //Log.debug("index: " + index);
0493: if (index != -1) {
0494: queryPane.setCaretPosition(index);
0495: }
0496: }
0497: matcher = null;
0498: GUIUtils.requestFocusInWindow(queryPane);
0499: }
0500:
0501: /**
0502: * Returns the currently selected text, or null if not text
0503: * is currently selected.
0504: *
0505: * @return selected text
0506: */
0507: public String getSelectedText() {
0508: String selection = queryPane.getSelectedText();
0509: if (selection != null && selection.trim().length() > 0) {
0510: return selection;
0511: }
0512: return null;
0513: }
0514:
0515: public void executeSQLAtCursor(DatabaseConnection dc) {
0516: if (analyser.isExecuting()) {
0517: return;
0518: }
0519: queryPane.executeSQLAtCursor(dc);
0520: historyNum = 0;
0521: }
0522:
0523: /**
0524: * Executes the specified query with the specified connection properties
0525: * object.
0526: *
0527: * @param dc - the database connection properties object
0528: * @param query - the query
0529: * @param executeAsBlock - whether to execute as a block
0530: */
0531: public void executeSQLQuery(DatabaseConnection dc, String query,
0532: boolean executeAsBlock) {
0533: if (analyser.isExecuting()) {
0534: return;
0535: }
0536:
0537: if (query == null) {
0538: query = getQueryAreaText();
0539: }
0540:
0541: if (query.trim().length() == 0) {
0542: return;
0543: }
0544:
0545: //queryPane.resetExecutingLine();
0546: historyNum = 0;
0547: queryEditor.setPreviousButtonEnabled(true);
0548: queryEditor.setNextButtonEnabled(false);
0549: analyser.executeSQLQuery(dc, query, executeAsBlock);
0550: }
0551:
0552: /**
0553: * Executes the specified query.
0554: *
0555: * @param query - the query
0556: */
0557: public void executeSQLQuery(String query) {
0558: executeSQLQuery(queryEditor.getSelectedConnection(), query,
0559: false);
0560: }
0561:
0562: /**
0563: * Executes the specified query as a 'block' if specified.
0564: *
0565: * @param the query
0566: * @param whether to execute ALL query text as one statement
0567: */
0568: public void executeSQLQuery(String query, boolean executeAsBlock) {
0569: executeSQLQuery(queryEditor.getSelectedConnection(), query,
0570: executeAsBlock);
0571: }
0572:
0573: /**
0574: * Executes the specified query using the specified connection
0575: * properties object.
0576: *
0577: * @param the the database connection object
0578: * @param the query
0579: */
0580: public void executeSQLQuery(DatabaseConnection dc, String query) {
0581: executeSQLQuery(dc, query, false);
0582: }
0583:
0584: public void setLeftStatusText(String s) {
0585: queryEditor.setLeftStatusText(s);
0586: }
0587:
0588: public void goToRow(int row) {
0589: queryPane.goToRow(row);
0590: }
0591:
0592: public void destroyTable() {
0593: queryEditor.destroyTable();
0594: }
0595:
0596: /**
0597: * Propagates the call to interrupt the statement currently being
0598: * executed to the QueryAnalyser.
0599: */
0600: public void interruptStatement() {
0601: analyser.interruptStatement();
0602: }
0603:
0604: /**
0605: * Sets the table results to the specified
0606: * <code>ResultSet</code> object for display.
0607: *
0608: * @param the table results to display
0609: * @param whether the row count is displayed
0610: * @return the row count of this <code>ResultSet</code> object
0611: */
0612: public int setResultSet(ResultSet rset, boolean showRowNumber)
0613: throws SQLException {
0614: return setResultSet(rset, showRowNumber, null);
0615: }
0616:
0617: /**
0618: * Sets the table results to the specified
0619: * <code>ResultSet</code> object for display.
0620: *
0621: * @param the table results to display
0622: * @param whether the row count is displayed
0623: * @param the executed query of the result set
0624: * @return the row count of this <code>ResultSet</code> object
0625: */
0626: public int setResultSet(ResultSet rset, boolean showRowNumber,
0627: String query) throws SQLException {
0628: return queryEditor.setResultSet(rset, showRowNumber, query);
0629: }
0630:
0631: public void interrupt() {
0632: //queryEditor.interrupt();
0633: }
0634:
0635: /**
0636: * Sets the table results to the specified
0637: * <code>ResultSet</code> object for display.
0638: *
0639: * @param the table results to display
0640: */
0641: public void setResultSet(ResultSet rset) throws SQLException {
0642: queryEditor.setResultSet(rset);
0643: }
0644:
0645: /**
0646: * Sets the table results to the specified
0647: * <code>ResultSet</code> object for display.
0648: *
0649: * @param the table results to display
0650: * @param the executed query of the result set
0651: */
0652: public void setResultSet(ResultSet rset, String query)
0653: throws SQLException {
0654: queryEditor.setResultSet(rset, query);
0655: }
0656:
0657: public void setResultText(int r, int t) {
0658: queryEditor.setResultText(r, t);
0659: }
0660:
0661: public String getQueryAreaText() {
0662: return queryPane.getText();
0663: }
0664:
0665: public void setStopButtonEnabled(boolean enable) {
0666: queryEditor.setStopButtonEnabled(enable);
0667: popup.enableExecutes(enable);
0668: }
0669:
0670: /**
0671: * Adds a comment tag to the beginning of the current line
0672: * or selected lines.
0673: */
0674: public void addCommentToLines() {
0675: queryPane.addUndoEdit();
0676: if (getSelectedText() == null) {
0677: int start = queryPane.getCurrentRowStart();
0678: queryPane.insertTextAtOffset(start, "--");
0679: } else {
0680: int index = queryPane.getSelectionStart();
0681: int firstRow = queryPane.getRowAt(index);
0682:
0683: index = queryPane.getSelectionEnd();
0684: int lastRow = queryPane.getRowAt(index);
0685:
0686: for (int i = firstRow; i <= lastRow; i++) {
0687: index = queryPane.getRowStartOffset(i);
0688: queryPane.insertTextAtOffset(index, "--");
0689: }
0690: }
0691:
0692: // add this as an edit if its not
0693: ensureUndo();
0694: }
0695:
0696: /**
0697: * Ensures an edit may be undone by forcing an end
0698: * to the current compound edit within the text pane.
0699: */
0700: protected void ensureUndo() {
0701: if (!queryPane.canUndo()) {
0702: queryPane.addUndoEdit();
0703: }
0704: }
0705:
0706: /** pattern matcher to check for comments to be removed */
0707: private Matcher commentRemovalMatcher;
0708:
0709: /**
0710: * Removes a comment tag from the current line or selected lines.
0711: */
0712: public void removeCommentFromLines() {
0713: if (queryPane.getDocument().getLength() > 0) {
0714:
0715: if (commentRemovalMatcher == null) {
0716: String regex = "^\\s*--";
0717: commentRemovalMatcher = Pattern.compile(regex).matcher(
0718: "");
0719: }
0720:
0721: // add an undo edit
0722: queryPane.addUndoEdit();
0723:
0724: try {
0725: int start = queryPane.getSelectionStart();
0726: int end = queryPane.getSelectionEnd();
0727:
0728: Element map = queryPane.getElementMap();
0729: start = queryPane.getRowAt(start);
0730: end = queryPane.getRowAt(end);
0731:
0732: String text = null;
0733: Document document = queryPane.getDocument();
0734: for (int i = start; i <= end; i++) {
0735: Element line = map.getElement(i);
0736: int startOffset = line.getStartOffset();
0737: int endOffset = line.getEndOffset();
0738:
0739: text = queryPane.getText(startOffset,
0740: (endOffset - startOffset));
0741: commentRemovalMatcher.reset(text);
0742:
0743: if (commentRemovalMatcher.find()) {
0744: // retrieve the exact index of '--' since
0745: // matcher will return first whitespace
0746: int index = text.indexOf("--");
0747: document.remove(startOffset + index, 2);
0748: }
0749:
0750: }
0751:
0752: // add this as an edit if its not
0753: ensureUndo();
0754:
0755: } catch (BadLocationException e) {
0756: e.printStackTrace();
0757: }
0758:
0759: }
0760: }
0761:
0762: /**
0763: * Shifts the text on the current line or the currently
0764: * selected text to the right one TAB.
0765: */
0766: public void shiftTextRight() {
0767: if (getSelectedText() == null) {
0768: int start = queryPane.getCurrentRowStart();
0769: queryPane.shiftTextRight(start);
0770: } else { // simulate a tab key for selected text
0771: try {
0772: Robot robot = new Robot();
0773: robot.keyPress(KeyEvent.VK_TAB);
0774: robot.keyRelease(KeyEvent.VK_TAB);
0775: } catch (AWTException e) {
0776: e.printStackTrace();
0777: }
0778: }
0779: }
0780:
0781: /**
0782: * Shifts the text on the current line or the currently
0783: * selected text to the left one TAB.
0784: */
0785: public void shiftTextLeft() {
0786: if (getSelectedText() == null) {
0787: int start = queryPane.getCurrentRowStart();
0788: int end = queryPane.getCurrentRowEnd();
0789: queryPane.shiftTextLeft(start, end);
0790: } else { // simulate a tab key for selected text
0791: try {
0792: Robot robot = new Robot();
0793: robot.keyPress(KeyEvent.VK_SHIFT);
0794: robot.keyPress(KeyEvent.VK_TAB);
0795: robot.keyRelease(KeyEvent.VK_TAB);
0796: robot.keyRelease(KeyEvent.VK_SHIFT);
0797: } catch (AWTException e) {
0798: e.printStackTrace();
0799: }
0800: }
0801: }
0802:
0803: // ---------------------------------------------
0804: // TextFunction implementation
0805: // ---------------------------------------------
0806:
0807: public void paste() {
0808: queryPane.paste();
0809: }
0810:
0811: public void copy() {
0812: queryPane.copy();
0813: }
0814:
0815: public void cut() {
0816: queryPane.cut();
0817: }
0818:
0819: public void changeSelectionCase(boolean upper) {
0820: queryPane.addUndoEdit();
0821: TextUtilities.changeSelectionCase(queryPane, upper);
0822: }
0823:
0824: public void deleteLine() {
0825: queryPane.addUndoEdit();
0826: TextUtilities.deleteLine(queryPane);
0827: }
0828:
0829: public void deleteWord() {
0830: queryPane.addUndoEdit();
0831: TextUtilities.deleteWord(queryPane);
0832: }
0833:
0834: public void deleteSelection() {
0835: queryPane.addUndoEdit();
0836: TextUtilities.deleteSelection(queryPane);
0837: }
0838:
0839: public void insertFromFile() {
0840: queryPane.addUndoEdit();
0841: TextUtilities.insertFromFile(queryPane);
0842: }
0843:
0844: public void insertLineAfter() {
0845: queryPane.addUndoEdit();
0846: TextUtilities.insertLineAfter(queryPane);
0847: }
0848:
0849: public void insertLineBefore() {
0850: queryPane.addUndoEdit();
0851: TextUtilities.insertLineBefore(queryPane);
0852: }
0853:
0854: // ---------------------------------------------
0855:
0856: /**
0857: * Propagates the call to the parent QueryEditor object
0858: * that the text content has been altered from the original
0859: * or previously saved state.
0860: *
0861: * @param true | false
0862: */
0863: public void setContentChanged(boolean contentChanged) {
0864: queryEditor.setContentChanged(contentChanged);
0865: }
0866:
0867: public void mousePressed(MouseEvent e) {
0868: maybeShowPopup(e);
0869: }
0870:
0871: public void mouseReleased(MouseEvent e) {
0872: maybeShowPopup(e);
0873: }
0874:
0875: private void maybeShowPopup(MouseEvent e) {
0876:
0877: if (e.isPopupTrigger()) {
0878: popup.show(e.getComponent(), e.getX(), e.getY());
0879: }
0880:
0881: }
0882:
0883: public void mouseClicked(MouseEvent e) {
0884: }
0885:
0886: public void mouseEntered(MouseEvent e) {
0887: }
0888:
0889: public void mouseExited(MouseEvent e) {
0890: }
0891:
0892: private static Insets borderInsets;
0893: private static Color borderColour;
0894:
0895: private class EditorScrollerBorder implements Border {
0896:
0897: protected EditorScrollerBorder() {
0898: if (borderInsets == null) {
0899: borderInsets = new Insets(0, 0, 1, 0);
0900: }
0901: if (borderColour == null) {
0902: borderColour = GUIUtilities.getDefaultBorderColour();
0903: }
0904: }
0905:
0906: public Insets getBorderInsets(Component c) {
0907: return borderInsets;
0908: }
0909:
0910: public void paintBorder(Component c, Graphics g, int x, int y,
0911: int width, int height) {
0912: g.setColor(borderColour);
0913: g.drawLine(x, height - 1, width, height - 1);
0914: }
0915:
0916: public boolean isBorderOpaque() {
0917: return false;
0918: }
0919:
0920: }
0921:
0922: /** The Query Editor's popup menu function */
0923: private class PopMenu extends JPopupMenu implements ActionListener {
0924:
0925: private JMenuItem execute;
0926: private JMenuItem executeBlock;
0927: private JMenuItem stop;
0928: private JMenuItem clearOutput;
0929: private JMenuItem rollback;
0930: private JMenuItem commit;
0931:
0932: public PopMenu() {
0933: JMenuItem cut = new JMenuItem(ActionBuilder
0934: .get("cut-command"));
0935: cut.setText("Cut");
0936: cut.setIcon(null);
0937:
0938: JMenuItem copy = new JMenuItem(ActionBuilder
0939: .get("copy-command"));
0940: copy.setText("Copy");
0941: copy.setIcon(null);
0942:
0943: JMenuItem paste = new JMenuItem(ActionBuilder
0944: .get("paste-command"));
0945: paste.setText("Paste");
0946: paste.setIcon(null);
0947:
0948: execute = new JMenuItem("Execute");
0949: execute.setAccelerator(KeyStroke.getKeyStroke(
0950: KeyEvent.VK_F5, 0));
0951: execute.addActionListener(this );
0952:
0953: JMenuItem partialExecute = new JMenuItem(ActionBuilder
0954: .get("execute-at-cursor-command"));
0955: partialExecute.setText("Execute Query at Cursor");
0956: partialExecute.setIcon(null);
0957:
0958: JMenuItem executeSelection = new JMenuItem(ActionBuilder
0959: .get("execute-selection-command"));
0960: executeSelection.setText("Execute Selected Query Text");
0961: executeSelection.setIcon(null);
0962:
0963: executeBlock = new JMenuItem("Execute as Single Statement");
0964: //execute.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0));
0965: executeBlock.addActionListener(this );
0966:
0967: stop = new JMenuItem("Cancel Query");
0968: stop.addActionListener(this );
0969:
0970: commit = new JMenuItem("Commit");
0971: commit.addActionListener(this );
0972:
0973: rollback = new JMenuItem("Rollback");
0974: rollback.addActionListener(this );
0975:
0976: clearOutput = new JMenuItem("Clear Output Log");
0977: clearOutput.addActionListener(this );
0978:
0979: JMenuItem help = new JMenuItem(ActionBuilder
0980: .get("help-command"));
0981: help.setIcon(null);
0982: help.setActionCommand("qedit");
0983: help.setText("Help");
0984:
0985: add(cut);
0986: add(copy);
0987: add(paste);
0988: addSeparator();
0989: add(execute);
0990: add(partialExecute);
0991: add(executeSelection);
0992: add(executeBlock);
0993: add(stop);
0994: addSeparator();
0995: add(commit);
0996: add(rollback);
0997: addSeparator();
0998: add(clearOutput);
0999: addSeparator();
1000: add(help);
1001:
1002: stop.setEnabled(false);
1003: }
1004:
1005: public void actionPerformed(ActionEvent e) {
1006: Object source = e.getSource();
1007:
1008: if (source == stop) {
1009: interruptStatement();
1010: } else if (source == execute) {
1011: executeSQLQuery(null);
1012: } else if (source == executeBlock) {
1013: queryEditor.setExecutingSingle(false);
1014: executeSQLQuery(null, true);
1015: } else if (source == clearOutput) {
1016: clearOutputPane();
1017: } else if (source == commit) {
1018: executeSQLQuery("commit");
1019: } else if (source == rollback) {
1020: executeSQLQuery("rollback");
1021: }
1022:
1023: }
1024:
1025: public void enableExecutes(boolean enable) {
1026: stop.setEnabled(enable);
1027: execute.setEnabled(!enable);
1028: }
1029:
1030: public void enableCommits(boolean enable) {
1031: commit.setEnabled(enable);
1032: rollback.setEnabled(enable);
1033: }
1034:
1035: } // class PopMenu
1036:
1037: }
|