Java tutorial
/* * QueryEditor.java * * Copyright (C) 2002-2015 Takis Diakoumis * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 3 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package org.executequery.gui.editor; import java.awt.BorderLayout; import java.awt.Component; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.print.Printable; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Vector; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.BorderFactory; import javax.swing.InputMap; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JLayeredPane; import javax.swing.JPanel; import javax.swing.JSplitPane; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.text.JTextComponent; import org.apache.commons.lang.StringUtils; import org.executequery.EventMediator; import org.executequery.GUIUtilities; import org.executequery.base.DefaultTabView; import org.executequery.components.SplitPaneFactory; import org.executequery.databasemediators.DatabaseConnection; import org.executequery.datasource.ConnectionManager; import org.executequery.event.ApplicationEvent; import org.executequery.event.ConnectionEvent; import org.executequery.event.ConnectionListener; import org.executequery.event.KeywordEvent; import org.executequery.event.KeywordListener; import org.executequery.event.QueryBookmarkEvent; import org.executequery.event.QueryBookmarkListener; import org.executequery.event.QueryShortcutEvent; import org.executequery.event.QueryShortcutListener; import org.executequery.event.UserPreferenceEvent; import org.executequery.event.UserPreferenceListener; import org.executequery.gui.FocusablePanel; import org.executequery.gui.SaveFunction; import org.executequery.gui.editor.autocomplete.QueryEditorAutoCompletePopupProvider; import org.executequery.gui.resultset.ResultSetTable; import org.executequery.gui.resultset.ResultSetTableModel; import org.executequery.gui.text.TextEditor; import org.executequery.log.Log; import org.executequery.print.TablePrinter; import org.executequery.print.TextPrinter; import org.executequery.sql.TokenizingFormatter; import org.executequery.util.UserProperties; import org.underworldlabs.swing.DefaultTextField; import org.underworldlabs.swing.NumberTextField; import org.underworldlabs.util.MiscUtils; import org.underworldlabs.util.SystemProperties; /** * The Query Editor. * * @author Takis Diakoumis * @version $Revision: 1487 $ * @date $Date: 2015-08-23 22:21:42 +1000 (Sun, 23 Aug 2015) $ */ public class QueryEditor extends DefaultTabView implements ConnectionListener, QueryBookmarkListener, QueryShortcutListener, UserPreferenceListener, TextEditor, KeywordListener, FocusablePanel { public static final String TITLE = "Query Editor"; public static final String FRAME_ICON = "Edit16.png"; private static final String DEFAULT_SCRIPT_PREFIX = "script"; private static final String DEFAULT_SCRIPT_SUFFIX = ".sql"; /** editor open count for title numbering */ private static int editorCountSequence = 1; /** The editor's status bar */ private QueryEditorStatusBar statusBar; /** The editor's text pan panel */ private QueryEditorTextPanel editorPanel; /** The editor's results panel */ private QueryEditorResultsPanel resultsPanel; private ScriptFile scriptFile; /** flags the content as having being changed */ private boolean contentChanged; /** the editor's tool bar */ private QueryEditorToolBar toolBar; /** the active connections combo */ private OpenConnectionsComboBox connectionsCombo; /** The text pane's popup menu */ private QueryEditorPopupMenu popup; /** enable/disable max rows */ private JCheckBox maxRowCountCheckBox; /** the max row count returned field */ private NumberTextField maxRowCountField; /** the result pane base panel */ private JPanel resultsBase; /** the editor split pane */ private JSplitPane splitPane; /** sql query execution delegate */ private QueryEditorDelegate delegate; private TokenizingFormatter formatter; private JPanel toolsPanel; private List<ConnectionChangeListener> connectionChangeListeners; /** Constructs a new instance. */ public QueryEditor() { this(null, null); } /** * Creates a new query editor with the specified text content. * * @param the text content to be set */ public QueryEditor(String text) { this(text, null); } /** * Creates a new query editor with the specified text content * and the specified absolute file path. * * @param the text content to be set * @param the absolute file path; */ public QueryEditor(String text, String absolutePath) { super(new GridBagLayout()); try { init(); } catch (Exception e) { e.printStackTrace(); } scriptFile = new ScriptFile(); scriptFile.setFileName(defaultScriptName()); scriptFile.setAbsolutePath(absolutePath); if (text != null) { loadText(text); } contentChanged = false; formatter = new TokenizingFormatter(); } private String defaultScriptName() { return DEFAULT_SCRIPT_PREFIX + (editorCountSequence++) + DEFAULT_SCRIPT_SUFFIX; } private void init() throws Exception { // construct the two query text area and results panels statusBar = new QueryEditorStatusBar(); statusBar.setBorder(BorderFactory.createEmptyBorder(0, -1, -2, -2)); editorPanel = new QueryEditorTextPanel(this); resultsPanel = new QueryEditorResultsPanel(this); delegate = new QueryEditorDelegate(this); popup = new QueryEditorPopupMenu(delegate); editorPanel.addEditorPaneMouseListener(popup); baseEditorPanel = new JPanel(new BorderLayout()); baseEditorPanel.add(editorPanel, BorderLayout.CENTER); baseEditorPanel.add(statusBar, BorderLayout.SOUTH); baseEditorPanel .setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, GUIUtilities.getDefaultBorderColour())); // add to a base panel - when last tab closed visible set // to false on the tab pane and split collapses - want to avoid this resultsBase = new JPanel(new BorderLayout()); resultsBase.add(resultsPanel, BorderLayout.CENTER); if (new SplitPaneFactory().usesCustomSplitPane()) { splitPane = new EditorSplitPane(JSplitPane.VERTICAL_SPLIT, baseEditorPanel, resultsBase); } else { splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, baseEditorPanel, resultsBase); } splitPane.setDividerSize(4); splitPane.setResizeWeight(0.5); // --------------------------------------- // the tool bar and conn combo toolBar = new QueryEditorToolBar(editorPanel.getTextPaneActionMap(), editorPanel.getTextPaneInputMap()); Vector<DatabaseConnection> connections = ConnectionManager.getActiveConnections(); connectionsCombo = new OpenConnectionsComboBox(this, connections); maxRowCountCheckBox = new JCheckBox(); maxRowCountCheckBox.setToolTipText("Enable/disable max records"); maxRowCountCheckBox.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { maxRowCountCheckBoxSelected(); } }); maxRowCountField = new MaxRowCountField(this); toolsPanel = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = new Insets(0, 0, 0, 0); gbc.anchor = GridBagConstraints.NORTHWEST; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridy++; gbc.gridx++; gbc.weightx = 1.0; gbc.gridwidth = GridBagConstraints.REMAINDER; toolsPanel.add(toolBar, gbc); gbc.gridy++; gbc.weightx = 0; gbc.gridwidth = 1; gbc.insets.top = 7; gbc.insets.left = 5; gbc.insets.right = 10; toolsPanel.add(createLabel("Connection:", 'C'), gbc); gbc.gridx++; gbc.weightx = 1.0; gbc.insets.top = 2; gbc.insets.bottom = 2; gbc.insets.left = 0; gbc.insets.right = 0; toolsPanel.add(connectionsCombo, gbc); gbc.gridx++; gbc.weightx = 0; gbc.insets.left = 0; gbc.insets.top = 7; gbc.insets.right = 10; gbc.insets.left = 10; toolsPanel.add(createLabel("Filter:", 'l'), gbc); gbc.gridx++; gbc.weightx = 0.8; gbc.insets.top = 2; gbc.insets.bottom = 2; gbc.insets.right = 2; gbc.insets.left = 0; gbc.fill = GridBagConstraints.BOTH; toolsPanel.add(createResultSetFilterTextField(), gbc); gbc.gridx++; gbc.weightx = 0; gbc.insets.top = 5; gbc.insets.left = 10; toolsPanel.add(maxRowCountCheckBox, gbc); gbc.gridx++; gbc.insets.left = 0; gbc.insets.top = 7; gbc.insets.right = 10; toolsPanel.add(createLabel("Max Rows:", 'R'), gbc); gbc.gridx++; gbc.weightx = 0.3; gbc.insets.top = 2; gbc.insets.bottom = 2; gbc.insets.right = 2; gbc.fill = GridBagConstraints.BOTH; toolsPanel.add(maxRowCountField, gbc); splitPane.setBorder(BorderFactory.createEmptyBorder(0, 3, 3, 3)); JPanel base = new JPanel(new BorderLayout()); base.add(toolsPanel, BorderLayout.NORTH); base.add(splitPane, BorderLayout.CENTER); gbc.gridy = 1; gbc.gridx = 1; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.insets.top = 0; gbc.insets.bottom = 0; gbc.insets.left = 0; gbc.insets.right = 0; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.SOUTHEAST; add(base, gbc); // register for connection and keyword events EventMediator.registerListener(this); addDeleteLineActionMapping(); setEditorPreferences(); statusBar.setCaretPosition(1, 1); statusBar.setInsertionMode("INS"); } private JTextField createResultSetFilterTextField() { filterTextField = new DefaultTextField(); filterTextField.setFocusAccelerator('l'); filterTextField.setToolTipText("Apply filter to current result set"); filterTextField.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { resultsPanel.filter(filterTextField.getText()); } }); return filterTextField; } private void maxRowCountCheckBoxSelected() { maxRowCountField.setEnabled(maxRowCountCheckBox.isSelected()); maxRowCountField.requestFocus(); } public void addConnectionChangeListener(final ConnectionChangeListener connectionChangeListener) { connectionsCombo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { connectionChangeListener.connectionChanged(getSelectedConnection()); } }); if (connectionChangeListeners == null) { connectionChangeListeners = new ArrayList<ConnectionChangeListener>(); } connectionChangeListeners.add(connectionChangeListener); } public void removePopupComponent(JComponent component) { GUIUtilities.getFrameLayeredPane().remove(component); GUIUtilities.getFrameLayeredPane().repaint(); } public void addPopupComponent(JComponent component) { GUIUtilities.getFrameLayeredPane().add(component, JLayeredPane.POPUP_LAYER); GUIUtilities.getFrameLayeredPane().repaint(); } private void addDeleteLineActionMapping() { Action action = new AbstractAction() { public void actionPerformed(ActionEvent e) { deleteLine(); } }; KeyStroke keyStroke = KeyStroke.getKeyStroke("control D"); ActionMap textPaneActionMap = editorPanel.getTextPaneActionMap(); InputMap textPaneInputMap = editorPanel.getTextPaneInputMap(); String actionMapKey = "editor-delete-line"; textPaneActionMap.put(actionMapKey, action); textPaneInputMap.put(keyStroke, actionMapKey); } private JLabel createLabel(String text, char mnemonic) { final JLabel label = new JLabel(text); label.setDisplayedMnemonic(mnemonic); return label; } /** the last divider location before a output hide */ private int lastDividerLocation; private QueryEditorAutoCompletePopupProvider queryEditorAutoCompletePopupProvider; private DatabaseConnection selectConnection; private JPanel baseEditorPanel; private JTextField filterTextField; /** * Toggles the output pane visible or not. */ public void toggleOutputPaneVisible() { if (resultsBase.isVisible()) { lastDividerLocation = splitPane.getDividerLocation(); resultsBase.setVisible(false); } else { resultsBase.setVisible(true); splitPane.setDividerLocation(lastDividerLocation); } } /** * Enters the specified text at the editor's current * insertion point. * * @param text - the text to insert */ public void insertTextAtCaret(String text) { editorPanel.insertTextAtCaret(text); } /** * Returns the default focus component, the query text * editor component. * * @return the editor component */ public Component getDefaultFocusComponent() { return editorPanel.getQueryArea(); } /** * Sets the editor user preferences. */ public void setEditorPreferences() { setPanelBackgrounds(); statusBar.setVisible(isStatusBarVisible()); toolsPanel.setVisible(isToolsPanelVisible()); editorPanel.showLineNumbers(isLineNumbersVisible()); editorPanel.preferencesChanged(); delegate.preferencesChanged(); delegate.setCommitMode(isAutoCommit()); popup.setCommitMode(isAutoCommit()); resultsPanel.setTableProperties(); if (isAutoCompleteOn()) { queryEditorAutoCompletePopupProvider = new QueryEditorAutoCompletePopupProvider(this); editorPanel.registerAutoCompletePopup(queryEditorAutoCompletePopupProvider); } else { editorPanel.deregisterAutoCompletePopup(); } int maxRecords = SystemProperties.getIntProperty("user", "editor.max.records"); maxRowCountCheckBox.setSelected((maxRecords > 0)); maxRowCountCheckBoxSelected(); } private boolean isAutoCompleteOn() { UserProperties userProperties = userProperties(); if (userProperties.containsKey("editor.autocomplete.on") && (!userProperties.containsKey("editor.autocomplete.keywords.on")) && !userProperties.containsKey("editor.autocomplete.schema.on")) { // old property key boolean allOn = true; if (!userProperties.getBooleanProperty("editor.autocomplete.on")) { allOn = false; } userProperties.setBooleanProperty("editor.autocomplete.keywords.on", allOn); userProperties.setBooleanProperty("editor.autocomplete.schema.on", allOn); } return userProperties.getBooleanProperty("editor.autocomplete.keywords.on") || userProperties.getBooleanProperty("editor.autocomplete.schema.on"); } private boolean isAutoCommit() { return userProperties().getBooleanProperty("editor.connection.commit"); } private boolean isLineNumbersVisible() { return userProperties().getBooleanProperty("editor.display.linenums"); } private boolean isStatusBarVisible() { return userProperties().getBooleanProperty("editor.display.statusbar"); } private boolean isToolsPanelVisible() { return userProperties().getBooleanProperty("editor.display.toolsPanel"); } private UserProperties userProperties() { return UserProperties.getInstance(); } /** * Called to inform this component of a change/update * to the user defined key words. */ public void updateSQLKeywords() { editorPanel.setSQLKeywords(true); } /** * Notification of a new keyword added to the list. */ public void keywordsAdded(KeywordEvent e) { editorPanel.setSQLKeywords(true); } /** * Notification of a keyword removed from the list. */ public void keywordsRemoved(KeywordEvent e) { editorPanel.setSQLKeywords(true); } /** * Sets the activity status bar label text to * that specified. * * @param the activity label text */ public void executing() { popup.statementExecuting(); setStopButtonEnabled(true); statusBar.startProgressBar(); statusBar.setExecutionTime(" Executing.. "); } /** * Notifies that the query execute is finished. */ public void finished(String message) { popup.statementFinished(); resultsPanel.finished(); statusBar.stopProgressBar(); setStopButtonEnabled(false); statusBar.setExecutionTime(message); resetPanels(); } /** * Sets the right status bar label text to * that specified. * * @param the right label text */ public void commitModeChanged(boolean autoCommit) { statusBar.setCommitStatus(autoCommit); } /** * Sets the text of the left status label. * * @param the text to be set */ public void setLeftStatusText(String s) { statusBar.setStatus(s); } /** * Propagates the call to interrupt an executing process. */ public void interrupt() { resultsPanel.interrupt(); } /** * Sets the result set object. * * @param the executed result set * @param whether to return the result set row count */ public int setResultSet(ResultSet rset, boolean showRowNumber) throws SQLException { return setResultSet(rset, showRowNumber, null); } /** * Returns the vakue from the max record count fields. * * @return the max row count to be shown */ public int getMaxRecords() { if (maxRowCountCheckBox.isSelected()) { int maxRecords = maxRowCountField.getValue(); if (maxRecords <= 0) { maxRecords = -1; maxRowCountField.setValue(-1); } return maxRecords; } return -1; } /** * Requests focus on connection combo */ public void selectConnectionCombo() { connectionsCombo.attemptToFocus(); } /** * Sets the result set object. * * @param the executed result set * @param whether to return the result set row count * @param the executed query of the result set */ public int setResultSet(ResultSet rset, boolean showRowNumber, String query) throws SQLException { int rowCount = resultsPanel.setResultSet(rset, showRowNumber, getMaxRecords()); revalidate(); return rowCount; } /** * Sets the result set object. * * @param rset the executed result set */ public void setResultSet(ResultSet rset) throws SQLException { resultsPanel.setResultSet(rset, true, getMaxRecords()); revalidate(); } /** * Sets the result set object. * * @param the executed result set * @param the executed query of the result set */ public void setResultSet(ResultSet rset, String query) throws SQLException { resultsPanel.setResultSet(rset, true, getMaxRecords(), query); } public void destroyTable() { resultsPanel.destroyTable(); } /** * Sets to display the result set meta data for the * currently selected result set tab. */ public void displayResultSetMetaData() { resultsPanel.displayResultSetMetaData(); } /** * Returns the editor status bar. * * @return the editor's status bar panel */ public QueryEditorStatusBar getStatusBar() { return statusBar; } /** * Disables/enables the listener updates as specified. */ public void disableUpdates(boolean disable) { editorPanel.disableUpdates(disable); } /** * Returns true that a search can be performed on the editor. */ public boolean canSearch() { return true; } /** * Disables/enables the caret update as specified. */ public void disableCaretUpdate(boolean disable) { editorPanel.disableCaretUpdate(disable); } public ResultSetTableModel getResultSetTableModel() { return resultsPanel.getResultSetTableModel(); } public ResultSetTable getResultSetTable() { return resultsPanel.getResultSetTable(); } public void setResultText(int updateCount, int type) { resultsPanel.setResultText(updateCount, type); } /** * Returns whether a result set panel is selected and that * that panel has a result set row count > 0. * * @return true | false */ public boolean isResultSetSelected() { return resultsPanel.isResultSetSelected(); } /** * Sets the respective panel background colours within * the editor as specified by the user defined properties. */ public void setPanelBackgrounds() { editorPanel.setTextPaneBackground(userProperties().getColourProperty("editor.text.background.colour")); resultsPanel.setResultBackground(userProperties().getColourProperty("editor.results.background.colour")); } /** * Sets the text of the editor pane to the previous * query available in the history list. Where no previous * query exists, nothing is changed. */ public void selectPreviousQuery() { try { GUIUtilities.showWaitCursor(); String query = delegate.getPreviousQuery(); setEditorText(query); } finally { GUIUtilities.showNormalCursor(); } } /** * Sets the text of the editor pane to the next * query available in the history list. Where no * next query exists, nothing is changed. */ public void selectNextQuery() { try { String query = delegate.getNextQuery(); setEditorText(query); } finally { GUIUtilities.showNormalCursor(); } } /** * Enables/disables the show meta data button. */ public void setMetaDataButtonEnabled(boolean enable) { if (retainMetaData()) { getTools().setMetaDataButtonEnabled(enable); } else { getTools().setMetaDataButtonEnabled(false); } } /** * Sets the history next button enabled as specified. */ public void setHasNextStatement(boolean enabled) { getTools().setNextButtonEnabled(enabled); } /** * Sets the history previous button enabled as specified. */ public void setHasPreviousStatement(boolean enabled) { getTools().setPreviousButtonEnabled(enabled); } /** * Enables/disables the transaction related buttons. */ public void setCommitsEnabled(boolean enable) { getTools().setCommitsEnabled(enable); } /** * Enables/disables the export result set button. */ public void setExportButtonEnabled(boolean enable) { getTools().setExportButtonEnabled(enable); } /** * Enables/disables the query execution stop button. */ public void setStopButtonEnabled(boolean enable) { getTools().setStopButtonEnabled(enable); } public void resetCaretPositionToLast() { editorPanel.setTextFocus(); } /** * Updates the interface and any system buttons as * required on a focus gain. */ public void focusGained() { QueryEditorToolBar tools = getTools(); tools.setMetaDataButtonEnabled(resultsPanel.hasResultSetMetaData() && retainMetaData()); tools.setCommitsEnabled(!delegate.getCommitMode()); tools.setNextButtonEnabled(delegate.hasNextStatement()); tools.setPreviousButtonEnabled(delegate.hasPreviousStatement()); tools.setStopButtonEnabled(delegate.isExecuting()); tools.setExportButtonEnabled(resultsPanel.isResultSetSelected()); editorPanel.setTextFocus(); } public void focusLost() { // nothing to do here } private boolean retainMetaData() { return userProperties().getBooleanProperty("editor.results.metadata"); } private QueryEditorToolBar getTools() { return toolBar; } public void destroyConnection() { delegate.destroyConnection(); queryEditorAutoCompletePopupProvider.reset(); } public void toggleCommitMode() { boolean mode = !delegate.getCommitMode(); delegate.setCommitMode(mode); popup.setCommitMode(mode); getTools().setCommitsEnabled(!mode); } // -------------------------------------------- // TabView implementation // -------------------------------------------- /** * Indicates the panel is being removed from the pane */ public boolean tabViewClosing() { if (isExecuting()) { if (MiscUtils.isMinJavaVersion(1, 6)) { GUIUtilities.displayWarningMessage("Editor is currently executing.\nPlease wait until " + "finished or attempt to cancel the running query."); } return false; } UserProperties properties = UserProperties.getInstance(); if (properties.getBooleanProperty("general.save.prompt") && contentChanged) { if (!GUIUtilities.saveOpenChanges(this)) { return false; } } try { cleanup(); } catch (Exception e) { GUIUtilities .displayExceptionErrorDialog("An error occurred when closing this editor.\nWhile this could " + "be nothing, sometimes it helps to check the stack trace to see if anything " + "peculiar happened.\n\nThe system returned:\n" + e.getMessage(), e); } return true; } /** * Indicates the panel is being selected in the pane */ public boolean tabViewSelected() { focusGained(); return true; } /** * Indicates the panel is being de-selected in the pane */ public boolean tabViewDeselected() { return true; } // -------------------------------------------- /** * Performs any resource clean up for a pending removal. */ public void cleanup() { /* ------------------------------------------------ * profiling found the popup keeps the * editor from being garbage collected at all!! * a call to removeAll() is a work around for now. * ------------------------------------------------ */ popup.removeAll(); editorPanel.closingEditor(); resultsPanel.cleanup(); statusBar.cleanup(); resultsPanel = null; statusBar = null; toolBar = null; editorPanel = null; queryEditorAutoCompletePopupProvider = null; delegate.disconnected(getSelectedConnection()); if (connectionChangeListeners != null) { for (ConnectionChangeListener listener : connectionChangeListeners) { listener.connectionChanged(null); } } removeAll(); EventMediator.deregisterListener(this); GUIUtilities.registerUndoRedoComponent(null); } public void interruptStatement() { if (Log.isDebugEnabled()) { Log.debug("Interrupt statement selected"); } delegate.interrupt(); } public void clearOutputPane() { if (!delegate.isExecuting()) { resultsPanel.clearOutputPane(); } } public void selectAll() { editorPanel.selectAll(); } public void goToRow(int row) { editorPanel.goToRow(row); } public void selectNone() { editorPanel.selectNone(); } public Vector<String> getHistoryList() { return delegate.getHistoryList(); } /** * Executes the currently selected query text. */ public void executeSelection() { String query = editorPanel.getSelectedText(); if (query != null) { executeSQLQuery(query); } } /** * Returns the currently selcted connection properties object. * * @return the selected connection */ public DatabaseConnection getSelectedConnection() { if (connectionsCombo.getSelectedIndex() != -1) { return (DatabaseConnection) connectionsCombo.getSelectedItem(); } return null; } public void setSelectedConnection(DatabaseConnection databaseConnection) { if (connectionsCombo.contains(databaseConnection)) { connectionsCombo.getModel().setSelectedItem(databaseConnection); } else { selectConnection = databaseConnection; } } public void preExecute() { filterTextField.setText(""); resultsPanel.preExecute(); } public String getWordToCursor() { return editorPanel.getWordToCursor(); } public String getCompleteWordEndingAtCursor() { return editorPanel.getCompleteWordEndingAtCursor(); } private boolean isExecuting() { return delegate.isExecuting(); } public void executeAsBlock() { delegate.executeQuery(null, true); } /** * Executes the specified query. * * @param the query */ public void executeSQLQuery(String query) { preExecute(); if (query == null) { query = editorPanel.getQueryAreaText(); } editorPanel.resetExecutingLine(); delegate.executeQuery(getSelectedConnection(), query, false); } public void executeSQLAtCursor() { preExecute(); String query = getQueryAtCursor().getQuery(); if (StringUtils.isNotBlank(query)) { editorPanel.setExecutingQuery(query); delegate.executeQuery(query); } } public QueryWithPosition getQueryAtCursor() { return editorPanel.getQueryAtCursor(); } public JTextComponent getEditorTextComponent() { return editorPanel.getQueryArea(); } /** * Adds a comment tag to the beginning of the current line * or selected lines. */ public void commentLines() { editorPanel.commentLines(); } /** * Shifts the text on the current line or the currently * selected text to the right one TAB. */ public void shiftTextRight() { editorPanel.shiftTextRight(); } /** * Shifts the text on the current line or the currently * selected text to the left one TAB. */ public void shiftTextLeft() { editorPanel.shiftTextLeft(); } public void moveSelectionUp() { editorPanel.moveSelectionUp(); } public void moveSelectionDown() { editorPanel.moveSelectionDown(); } /** * Duplicates the cursor current row up */ public void duplicateRowUp() { editorPanel.duplicateRowUp(); } /** * Duplicates the cursor current row down */ public void duplicateRowDown() { editorPanel.duplicateRowDown(); } /** * Sets the editor's text content that specified. * * @param s - the text to be set */ public void setEditorText(String s) { editorPanel.setQueryAreaText(s); } /** * Moves the caret to the beginning of the specified query. * * @param query - the query to move the cursor to */ public void caretToQuery(String query) { editorPanel.caretToQuery(query); } /** * Loads the specified text into a blank 'offscreen' document * before switching to the SQL document. */ public void loadText(String text) { editorPanel.loadText(text); } public void insertTextAtEnd(String text) { int end = getEditorText().length(); insertTextAfter(end - 1, text); caretToQuery(text); } public void insertTextAfter(int after, String text) { editorPanel.insertTextAfter(after, text); } public boolean hasText() { return !(MiscUtils.isNull(getEditorText())); } public String getEditorText() { return editorPanel.getQueryAreaText(); } public void setOutputMessage(int type, String text) { resultsPanel.setOutputMessage(type, text); } public void setOutputMessage(int type, String text, boolean selectTab) { resultsPanel.setOutputMessage(type, text, selectTab); //revalidate(); } /** * Sets the state for an open file. * * @param the absolute file path */ public void setOpenFilePath(String absolutePath) { scriptFile.setAbsolutePath(absolutePath); } /** * Returns whether the text component is in a printable state. * * @return true | false */ public boolean canPrint() { return true; } public Printable getPrintable() { return getPrintableForResultSet(); } public Printable getPrintableForResultSet() { return new TablePrinter(resultsPanel.getResultSetTable(), "Query: " + editorPanel.getQueryAreaText()); } public Printable getPrintableForQueryArea() { return new TextPrinter(editorPanel.getQueryAreaText()); } public String getPrintJobName() { return "Execute Query - editor"; } // --------------------------------------------- // TextEditor implementation // --------------------------------------------- public void paste() { editorPanel.paste(); } public void copy() { editorPanel.copy(); } public void cut() { editorPanel.cut(); } public void deleteLine() { editorPanel.deleteLine(); } public void deleteWord() { editorPanel.deleteWord(); } public void deleteSelection() { editorPanel.deleteSelection(); } public void insertFromFile() { editorPanel.insertFromFile(); } public void insertLineAfter() { editorPanel.insertLineAfter(); } public void insertLineBefore() { editorPanel.insertLineBefore(); } public void changeSelectionCase(boolean upper) { editorPanel.changeSelectionCase(upper); } public void changeSelectionToUnderscore() { editorPanel.changeSelectionToUnderscore(); } public void changeSelectionToCamelCase() { editorPanel.changeSelectionToCamelCase(); } // --------------------------------------------- // --------------------------------------------- // SaveFunction implementation // --------------------------------------------- public String getDisplayName() { return toString(); } public boolean contentCanBeSaved() { return contentChanged; } public int save(boolean saveAs) { String text = editorPanel.getQueryAreaText(); QueryEditorFileWriter writer = new QueryEditorFileWriter(); boolean saved = writer.write(text, scriptFile, saveAs); if (saved) { GUIUtilities.setTabTitleForComponent(this, getDisplayName()); statusBar.setStatus(" File saved to " + scriptFile.getFileName()); contentChanged = false; } return SaveFunction.SAVE_COMPLETE; } // --------------------------------------------- /** * Returns the display name of this panel. This may * include the path of any open file. * * @return the display name */ public String toString() { return String.format("%s - %s", TITLE, scriptFile.getFileName()); } /** * Returns whether the content has changed for a * possible document save. * * @return true if text content changed, false otherwise */ public boolean isContentChanged() { return contentChanged; } /** * Sets that the text content of the editor has changed from * the original or previously saved state. * * @param true | false */ public void setContentChanged(boolean contentChanged) { this.contentChanged = contentChanged; } // --------------------------------------------- // ConnectionListener implementation // --------------------------------------------- /** * Indicates a connection has been established. * * @param the encapsulating event */ public void connected(ConnectionEvent connectionEvent) { connectionsCombo.addElement(connectionEvent.getDatabaseConnection()); DatabaseConnection databaseConnection = connectionEvent.getDatabaseConnection(); if (databaseConnection == selectConnection) { connectionsCombo.getModel().setSelectedItem(databaseConnection); selectConnection = null; } } /** * Indicates a connection has been closed. * * @param the encapsulating event */ public void disconnected(ConnectionEvent connectionEvent) { connectionsCombo.removeElement(connectionEvent.getDatabaseConnection()); // TODO: NEED TO CHECK OPEN CONN } // --------------------------------------------- public boolean canHandleEvent(ApplicationEvent event) { return (event instanceof ConnectionEvent) || (event instanceof KeywordEvent) || (event instanceof UserPreferenceEvent) || (event instanceof QueryShortcutEvent) || (event instanceof QueryBookmarkEvent); } public void queryBookmarkAdded(QueryBookmarkEvent e) { handleBookmarkEvent(e); } public void queryBookmarkRemoved(QueryBookmarkEvent e) { handleBookmarkEvent(e); } private void handleBookmarkEvent(QueryBookmarkEvent e) { toolBar.reloadBookmarkItems(); } public void formatSQLtext() { int start = editorPanel.getSelectionStart(); int end = editorPanel.getSelectionEnd(); String text = getSelectedText(); if (text == null) { QueryWithPosition queryAtCursor = getQueryAtCursor(); start = queryAtCursor.getStart(); end = queryAtCursor.getEnd(); text = getQueryAtCursor().getQuery(); } String formattedText = formatter.format(text); editorPanel.replaceRegion(start, end, formattedText); // setEditorText(formattedText); } private String getSelectedText() { return editorPanel.getSelectedText(); } public void preferencesChanged(UserPreferenceEvent event) { QueryEditorSettings.initialise(); if (event.getEventType() == UserPreferenceEvent.QUERY_EDITOR || event.getEventType() == UserPreferenceEvent.ALL) { setEditorPreferences(); } } public void queryShortcutAdded(QueryShortcutEvent e) { editorPanel.editorShortcutsUpdated(); } public void queryShortcutRemoved(QueryShortcutEvent e) { editorPanel.editorShortcutsUpdated(); } public void refreshAutocompleteList() { queryEditorAutoCompletePopupProvider.reset(); } public void allResultTabsClosed() { lastDividerLocation = splitPane.getDividerLocation(); baseEditorPanel.setVisible(true); resultsBase.setVisible(false); } public void toggleResultPane() { if (baseEditorPanel.isVisible()) { lastDividerLocation = splitPane.getDividerLocation(); baseEditorPanel.setVisible(false); } else { baseEditorPanel.setVisible(true); splitPane.setDividerLocation(lastDividerLocation); } } private void resetPanels() { resultsBase.setVisible(true); baseEditorPanel.setVisible(true); if (lastDividerLocation > 0) { splitPane.setDividerLocation(lastDividerLocation); } else { splitPane.setDividerLocation(0.5); } } }