0001: package net.sourceforge.squirrel_sql.client.session.mainpanel;
0002:
0003: /*
0004: * Copyright (C) 2001-2004 Colin Bell
0005: * colbell@users.sourceforge.net
0006: *
0007: * Modifications Copyright (C) 2001-2004 Johan Compagner
0008: * jcompagner@j-com.nl
0009: *
0010: * Modifications Copyright (C) 2003-2004 Jason Height
0011: *
0012: * This library is free software; you can redistribute it and/or
0013: * modify it under the terms of the GNU Lesser General Public
0014: * License as published by the Free Software Foundation; either
0015: * version 2.1 of the License, or (at your option) any later version.
0016: *
0017: * This library is distributed in the hope that it will be useful,
0018: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0019: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0020: * Lesser General Public License for more details.
0021: *
0022: * You should have received a copy of the GNU Lesser General Public
0023: * License along with this library; if not, write to the Free Software
0024: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0025: */
0026: import java.awt.BorderLayout;
0027: import java.awt.Dimension;
0028: import java.awt.GridLayout;
0029: import java.awt.event.ActionEvent;
0030: import java.awt.event.ActionListener;
0031: import java.beans.PropertyChangeEvent;
0032: import java.beans.PropertyChangeListener;
0033: import java.sql.SQLException;
0034: import java.util.ArrayList;
0035: import java.util.HashMap;
0036: import java.util.List;
0037: import java.util.prefs.Preferences;
0038:
0039: import javax.swing.Action;
0040: import javax.swing.BorderFactory;
0041: import javax.swing.Box;
0042: import javax.swing.ImageIcon;
0043: import javax.swing.JButton;
0044: import javax.swing.JCheckBox;
0045: import javax.swing.JComponent;
0046: import javax.swing.JMenu;
0047: import javax.swing.JMenuItem;
0048: import javax.swing.JPanel;
0049: import javax.swing.JScrollPane;
0050: import javax.swing.JSplitPane;
0051: import javax.swing.JTabbedPane;
0052: import javax.swing.SwingUtilities;
0053: import javax.swing.event.ChangeEvent;
0054: import javax.swing.event.ChangeListener;
0055: import javax.swing.event.DocumentEvent;
0056: import javax.swing.event.DocumentListener;
0057: import javax.swing.event.EventListenerList;
0058: import javax.swing.undo.UndoManager;
0059:
0060: import net.sourceforge.squirrel_sql.client.IApplication;
0061: import net.sourceforge.squirrel_sql.client.gui.builders.UIFactory;
0062: import net.sourceforge.squirrel_sql.client.resources.SquirrelResources;
0063: import net.sourceforge.squirrel_sql.client.session.ISQLEntryPanel;
0064: import net.sourceforge.squirrel_sql.client.session.ISQLPanelAPI;
0065: import net.sourceforge.squirrel_sql.client.session.ISession;
0066: import net.sourceforge.squirrel_sql.client.session.SQLPanelAPI;
0067: import net.sourceforge.squirrel_sql.client.session.action.OpenSqlHistoryAction;
0068: import net.sourceforge.squirrel_sql.client.session.action.RedoAction;
0069: import net.sourceforge.squirrel_sql.client.session.action.UndoAction;
0070: import net.sourceforge.squirrel_sql.client.session.event.IResultTabListener;
0071: import net.sourceforge.squirrel_sql.client.session.event.ISQLExecutionListener;
0072: import net.sourceforge.squirrel_sql.client.session.event.ISQLPanelListener;
0073: import net.sourceforge.squirrel_sql.client.session.event.ISQLResultExecuterTabListener;
0074: import net.sourceforge.squirrel_sql.client.session.event.ResultTabEvent;
0075: import net.sourceforge.squirrel_sql.client.session.event.SQLExecutionAdapter;
0076: import net.sourceforge.squirrel_sql.client.session.event.SQLPanelEvent;
0077: import net.sourceforge.squirrel_sql.client.session.event.SQLResultExecuterTabEvent;
0078: import net.sourceforge.squirrel_sql.client.session.parser.IParserEventsProcessorFactory;
0079: import net.sourceforge.squirrel_sql.client.session.properties.SessionProperties;
0080: import net.sourceforge.squirrel_sql.fw.gui.FontInfo;
0081: import net.sourceforge.squirrel_sql.fw.gui.IntegerField;
0082: import net.sourceforge.squirrel_sql.fw.gui.MemoryComboBox;
0083: import net.sourceforge.squirrel_sql.fw.sql.ISQLConnection;
0084: import net.sourceforge.squirrel_sql.fw.util.Resources;
0085: import net.sourceforge.squirrel_sql.fw.util.StringManager;
0086: import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
0087: import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
0088: import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
0089:
0090: /**
0091: * This is the panel where SQL scripts can be entered and executed.
0092: *
0093: * @author <A HREF="mailto:colbell@users.sourceforge.net">Colin Bell</A>
0094: */
0095: public class SQLPanel extends JPanel {
0096: private static final long serialVersionUID = 1L;
0097:
0098: /** Logger for this class. */
0099: private static final ILogger s_log = LoggerController
0100: .createLogger(SQLPanel.class);
0101:
0102: /** Internationalized strings for this class. */
0103: private static final StringManager s_stringMgr = StringManagerFactory
0104: .getStringManager(SQLPanel.class);
0105:
0106: /** Used to separate lines in the SQL entry area. */
0107: private final static String LINE_SEPARATOR = "\n";
0108:
0109: /**
0110: * Set to <TT>true</TT> once SQL history has been loaded from the file
0111: * system.
0112: */
0113: private static boolean s_loadedSQLHistory;
0114:
0115: /** Current session. */
0116: transient private ISession _session;
0117:
0118: private SQLHistoryComboBox _sqlCombo;
0119: transient private ISQLEntryPanel _sqlEntry;
0120: private JCheckBox _limitRowsChk;
0121: private IntegerField _nbrRows = new IntegerField();
0122:
0123: private JScrollPane _sqlEntryScroller;
0124:
0125: transient private SqlComboListener _sqlComboListener = new SqlComboListener();
0126: transient private MyPropertiesListener _propsListener;
0127:
0128: /** Each tab is a <TT>ResultTab</TT> showing the results of a query. */
0129: // private JTabbedPane _tabbedResultsPanel;
0130: /**
0131: * Collection of <TT>ResultTabInfo</TT> objects for all
0132: * <TT>ResultTab</TT> objects that have been created. Keyed
0133: * by <TT>ResultTab.getIdentifier()</TT>.
0134: */
0135: // private Map _allTabs = new HashMap();
0136: /**
0137: * Pool of <TT>ResultTabInfo</TT> objects available for use.
0138: */
0139: // private List _availableTabs = new ArrayList();
0140: /**
0141: * Pool of <TT>ResultTabInfo</TT> objects currently being used.
0142: */
0143: // private ArrayList _usedTabs = new ArrayList();
0144: /** Each tab is a <TT>ExecuterTab</TT> showing an installed executer. */
0145:
0146: /**
0147: * Is the bottom component of the split.
0148: * Holds the _simpleExecuterPanel if there is just one entry in _executors,
0149: * holds the _tabbedExecuterPanel if there is more that one element in _executors,
0150: */
0151: private JPanel _executerPanleHolder;
0152:
0153: private JTabbedPane _tabbedExecuterPanel;
0154: private JPanel _simpleExecuterPanel;
0155:
0156: private boolean _hasBeenVisible = false;
0157: private JSplitPane _splitPane;
0158:
0159: /** Listeners */
0160: private EventListenerList _listeners = new EventListenerList();
0161:
0162: private UndoManager _undoManager = new SquirrelDefaultUndoManager();
0163:
0164: /** Factory for generating unique IDs for new <TT>ResultTab</TT> objects. */
0165: // private IntegerIdentifierFactory _idFactory = new IntegerIdentifierFactory();
0166: private final List<ISQLResultExecuter> _executors = new ArrayList<ISQLResultExecuter>();
0167:
0168: private SQLResultExecuterPanel _sqlExecPanel;
0169:
0170: transient private ISQLPanelAPI _panelAPI;
0171:
0172: private static final String PREFS_KEY_SPLIT_DIVIDER_LOC = "squirrelSql_sqlPanel_divider_loc";
0173: private UndoAction _undoAction;
0174: private RedoAction _redoAction;
0175:
0176: /**
0177: * true if this panel is within a SessionInternalFrame
0178: * false if this panle is within a SQLInternalFrame
0179: */
0180: private boolean _inMainSessionWindow;
0181: transient private SQLPanel.SQLExecutorHistoryListener _sqlExecutorHistoryListener = new SQLExecutorHistoryListener();
0182: private ArrayList<SqlPanelListener> _sqlPanelListeners = new ArrayList<SqlPanelListener>();
0183:
0184: /**
0185: * Ctor.
0186: *
0187: * @param session Current session.
0188: *
0189: * @throws IllegalArgumentException
0190: * Thrown if a <TT>null</TT> <TT>ISession</TT> passed.
0191: */
0192: public SQLPanel(ISession session, boolean isInMainSessionWindow) {
0193: super ();
0194: _inMainSessionWindow = isInMainSessionWindow;
0195: setSession(session);
0196: createGUI();
0197: propertiesHaveChanged(null);
0198: _sqlExecPanel = new SQLResultExecuterPanel(session);
0199: _sqlExecPanel
0200: .addSQLExecutionListener(_sqlExecutorHistoryListener);
0201: addExecutor(_sqlExecPanel);
0202: _panelAPI = new SQLPanelAPI(this );
0203: }
0204:
0205: /**
0206: * Set the current session.
0207: *
0208: * @param session Current session.
0209: *
0210: * @throws IllegalArgumentException
0211: * Thrown if a <TT>null</TT> <TT>ISession</TT> passed.
0212: */
0213: public synchronized void setSession(ISession session) {
0214: if (session == null) {
0215: throw new IllegalArgumentException("Null ISession passed");
0216: }
0217: sessionClosing();
0218: _session = session;
0219: _propsListener = new MyPropertiesListener();
0220: _session.getProperties().addPropertyChangeListener(
0221: _propsListener);
0222: }
0223:
0224: /**
0225: * JASON: This method may go eventually if the SQLPanel implements the
0226: * ISQLPanelAPI interface.
0227: */
0228: public ISQLPanelAPI getSQLPanelAPI() {
0229: return _panelAPI;
0230: }
0231:
0232: /** Current session. */
0233: public synchronized ISession getSession() {
0234: return _session;
0235: }
0236:
0237: public void addExecutor(ISQLResultExecuter exec) {
0238: _executors.add(exec);
0239:
0240: if (1 == _executors.size()) {
0241: _executerPanleHolder.remove(_tabbedExecuterPanel);
0242: _executerPanleHolder.add(_simpleExecuterPanel);
0243: } else if (2 == _executors.size()) {
0244: _executerPanleHolder.remove(_simpleExecuterPanel);
0245: _executerPanleHolder.add(_tabbedExecuterPanel);
0246: _executors.get(0);
0247: ISQLResultExecuter buf = _executors.get(0);
0248: _tabbedExecuterPanel.addTab(buf.getTitle(), null, buf
0249: .getComponent(), buf.getTitle());
0250: }
0251:
0252: if (1 < _executors.size()) {
0253: _tabbedExecuterPanel.addTab(exec.getTitle(), null, exec
0254: .getComponent(), exec.getTitle());
0255: } else {
0256: _simpleExecuterPanel.add(exec.getComponent());
0257: }
0258:
0259: this .fireExecuterTabAdded(exec);
0260: }
0261:
0262: public void removeExecutor(ISQLResultExecuter exec) {
0263: _executors.remove(exec);
0264: }
0265:
0266: public SQLResultExecuterPanel getSQLExecPanel() {
0267: return _sqlExecPanel;
0268: }
0269:
0270: /**
0271: * Add a listener listening for SQL Execution.
0272: *
0273: * @param lis Listener to add
0274: *
0275: * @throws IllegalArgumentException
0276: * Thrown if a null <TT>ISQLExecutionListener</TT> passed.
0277: */
0278: public synchronized void addSQLExecutionListener(
0279: ISQLExecutionListener lis) {
0280: if (lis == null) {
0281: throw new IllegalArgumentException(
0282: "null ISQLExecutionListener passed");
0283: }
0284: //_listeners.add(ISQLExecutionListener.class, lis);
0285: _sqlExecPanel.addSQLExecutionListener(lis);
0286: }
0287:
0288: /**
0289: * Remove an SQL execution listener.
0290: *
0291: * @param lis Listener
0292: *
0293: * @throws IllegalArgumentException
0294: * If a null <TT>ISQLExecutionListener</TT> passed.
0295: */
0296: public synchronized void removeSQLExecutionListener(
0297: ISQLExecutionListener lis) {
0298: if (lis == null) {
0299: throw new IllegalArgumentException(
0300: "null ISQLExecutionListener passed");
0301: }
0302: //_listeners.remove(ISQLExecutionListener.class, lis);
0303: _sqlExecPanel.removeSQLExecutionListener(lis);
0304: }
0305:
0306: /**
0307: * Add a listener to this panel.
0308: *
0309: * @param lis Listener
0310: *
0311: * @throws IllegalArgumentException
0312: * If a null <TT>ISQLPanelListener</TT> passed.
0313: */
0314: public synchronized void addSQLPanelListener(ISQLPanelListener lis) {
0315: if (lis == null) {
0316: throw new IllegalArgumentException(
0317: "null ISQLPanelListener passed");
0318: }
0319: _listeners.add(ISQLPanelListener.class, lis);
0320: }
0321:
0322: /**
0323: * Remove a listener.
0324: *
0325: * @param lis Listener
0326: *
0327: * @throws IllegalArgumentException
0328: * If a null <TT>ISQLPanelListener</TT> passed.
0329: */
0330: public synchronized void removeSQLPanelListener(
0331: ISQLPanelListener lis) {
0332: if (lis == null) {
0333: throw new IllegalArgumentException(
0334: "null ISQLPanelListener passed");
0335: }
0336: _listeners.remove(ISQLPanelListener.class, lis);
0337: }
0338:
0339: /**
0340: * Add a listener for events in this sql panel executer tabs.
0341: *
0342: * @param lis Listener
0343: *
0344: * @throws IllegalArgumentException
0345: * If a null <TT>ISQLResultExecuterTabListener</TT> passed.
0346: */
0347: public void addExecuterTabListener(ISQLResultExecuterTabListener lis) {
0348: if (lis == null) {
0349: throw new IllegalArgumentException(
0350: "ISQLExecutionListener == null");
0351: }
0352: _listeners.add(ISQLResultExecuterTabListener.class, lis);
0353: }
0354:
0355: public synchronized void removeExecuterTabListener(
0356: ISQLResultExecuterTabListener lis) {
0357: if (lis == null) {
0358: throw new IllegalArgumentException(
0359: "ISQLResultExecuterTabListener == null");
0360: }
0361: _listeners.remove(ISQLResultExecuterTabListener.class, lis);
0362: }
0363:
0364: public ISQLEntryPanel getSQLEntryPanel() {
0365: return _sqlEntry;
0366: }
0367:
0368: public void runCurrentExecuter() {
0369: if (1 == _executors.size()) {
0370: ISQLResultExecuter exec = _executors.get(0);
0371: exec.execute(_sqlEntry);
0372: } else {
0373: int selectedIndex = _tabbedExecuterPanel.getSelectedIndex();
0374: ISQLResultExecuter exec = _executors.get(selectedIndex);
0375: exec.execute(_sqlEntry);
0376: }
0377: }
0378:
0379: /**
0380: * Sesssion is ending.
0381: * Remove all listeners that this component has setup. Close all
0382: * torn off result tab windows.
0383: */
0384: void sessionClosing() {
0385: if (_propsListener != null) {
0386: _session.getProperties().removePropertyChangeListener(
0387: _propsListener);
0388: _propsListener = null;
0389: }
0390: }
0391:
0392: public void sessionWindowClosing() {
0393:
0394: fireSQLEntryAreaClosed();
0395:
0396: if (_hasBeenVisible) {
0397: int dividerLoc = _splitPane.getDividerLocation();
0398: Preferences.userRoot().putInt(PREFS_KEY_SPLIT_DIVIDER_LOC,
0399: dividerLoc);
0400: }
0401:
0402: _sqlCombo.removeActionListener(_sqlComboListener);
0403: _sqlCombo.dispose();
0404: _sqlExecPanel
0405: .removeSQLExecutionListener(_sqlExecutorHistoryListener);
0406:
0407: for (SqlPanelListener l : _sqlPanelListeners) {
0408: l.panelParentWindowClosing();
0409: }
0410:
0411: _sqlEntry.dispose();
0412:
0413: }
0414:
0415: private void installSQLEntryPanel(ISQLEntryPanel pnl) {
0416: if (pnl == null) {
0417: throw new IllegalArgumentException(
0418: "Null ISQLEntryPanel passed");
0419: }
0420:
0421: _sqlEntry = pnl;
0422:
0423: final int pos = _splitPane.getDividerLocation();
0424: if (!_sqlEntry.getDoesTextComponentHaveScroller()) {
0425: _sqlEntryScroller = new JScrollPane(_sqlEntry
0426: .getTextComponent());
0427: _sqlEntryScroller.setBorder(BorderFactory
0428: .createEmptyBorder());
0429: _splitPane.add(_sqlEntryScroller);
0430: } else {
0431: _splitPane.add(_sqlEntry.getTextComponent(),
0432: JSplitPane.LEFT);
0433: }
0434: _splitPane.setDividerLocation(pos);
0435:
0436: if (!_sqlEntry.hasOwnUndoableManager()) {
0437: IApplication app = _session.getApplication();
0438: Resources res = app.getResources();
0439: _undoAction = new UndoAction(app, _undoManager);
0440: _redoAction = new RedoAction(app, _undoManager);
0441:
0442: JComponent comp = _sqlEntry.getTextComponent();
0443: comp.registerKeyboardAction(_undoAction, res
0444: .getKeyStroke(_undoAction),
0445: WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
0446: comp.registerKeyboardAction(_redoAction, res
0447: .getKeyStroke(_redoAction),
0448: WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
0449: _sqlEntry.setUndoActions(_undoAction, _redoAction);
0450:
0451: _sqlEntry.setUndoManager(_undoManager);
0452: }
0453:
0454: fireSQLEntryAreaInstalled();
0455: }
0456:
0457: public void setVisible(boolean value) {
0458: super .setVisible(value);
0459: if (!_hasBeenVisible && value == true) {
0460: final int dividerLoc = Preferences.userRoot().getInt(
0461: PREFS_KEY_SPLIT_DIVIDER_LOC,
0462: _splitPane.getMaximumDividerLocation() / 4);
0463:
0464: SwingUtilities.invokeLater(new Runnable() {
0465: public void run() {
0466: _splitPane.setDividerLocation(dividerLoc);
0467: }
0468: });
0469:
0470: _hasBeenVisible = true;
0471: }
0472: }
0473:
0474: /**
0475: * Add the passed item to end of the SQL history. If the item
0476: * at the end of the history is the same as the passed one
0477: * then don't add it.
0478: *
0479: * @param sql SQL item to add.
0480: *
0481: * @throws IllegalArgumentException
0482: * Thrown if <TT>null</TT> sql passed.
0483: */
0484: public void addSQLToHistory(SQLHistoryItem sql) {
0485: if (sql == null) {
0486: throw new IllegalArgumentException("SQLHistoryItem == null");
0487: }
0488:
0489: _sqlComboListener.stopListening();
0490: try {
0491: int beforeSize = 0;
0492: int afterSize = _sqlCombo.getItemCount();
0493: do {
0494: beforeSize = afterSize;
0495: _sqlCombo.removeItem(sql);
0496: afterSize = _sqlCombo.getItemCount();
0497: } while (beforeSize != afterSize);
0498: _sqlCombo.insertItemAt(sql, afterSize);
0499: _sqlCombo.setSelectedIndex(afterSize);
0500: _sqlCombo.repaint();
0501: } finally {
0502: _sqlComboListener.startListening();
0503: }
0504: }
0505:
0506: /**
0507: * Add a hierarchical menu to the SQL Entry Area popup menu.
0508: *
0509: * @param menu The menu that will be added.
0510: *
0511: * @throws IllegalArgumentException
0512: * Thrown if <TT>null</TT> <TT>Menu</TT> passed.
0513: */
0514: public void addToSQLEntryAreaMenu(JMenu menu) {
0515: if (menu == null) {
0516: throw new IllegalArgumentException("Menu == null");
0517: }
0518: getSQLEntryPanel().addToSQLEntryAreaMenu(menu);
0519: }
0520:
0521: /**
0522: * Add an <TT>Action</TT> to the SQL Entry Area popup menu.
0523: *
0524: * @param action The action to be added.
0525: *
0526: * @throws IllegalArgumentException
0527: * Thrown if <TT>null</TT> <TT>Action</TT> passed.
0528: */
0529: public JMenuItem addToSQLEntryAreaMenu(Action action) {
0530: if (action == null) {
0531: throw new IllegalArgumentException("Action == null");
0532: }
0533: return getSQLEntryPanel().addToSQLEntryAreaMenu(action);
0534: }
0535:
0536: private void fireSQLEntryAreaInstalled() {
0537: // Guaranteed to be non-null.
0538: Object[] listeners = _listeners.getListenerList();
0539: // Process the listeners last to first, notifying
0540: // those that are interested in this event.
0541: SQLPanelEvent evt = null;
0542: for (int i = listeners.length - 2; i >= 0; i -= 2) {
0543: if (listeners[i] == ISQLPanelListener.class) {
0544: // Lazily create the event:
0545: if (evt == null) {
0546: evt = new SQLPanelEvent(_session, this );
0547: }
0548: ((ISQLPanelListener) listeners[i + 1])
0549: .sqlEntryAreaInstalled(evt);
0550: }
0551: }
0552: }
0553:
0554: private void fireSQLEntryAreaClosed() {
0555: // Guaranteed to be non-null.
0556: Object[] listeners = _listeners.getListenerList();
0557: // Process the listeners last to first, notifying
0558: // those that are interested in this event.
0559: SQLPanelEvent evt = null;
0560: for (int i = listeners.length - 2; i >= 0; i -= 2) {
0561: if (listeners[i] == ISQLPanelListener.class) {
0562: // Lazily create the event:
0563: if (evt == null) {
0564: evt = new SQLPanelEvent(_session, this );
0565: }
0566: ((ISQLPanelListener) listeners[i + 1])
0567: .sqlEntryAreaClosed(evt);
0568: }
0569: }
0570: }
0571:
0572: @SuppressWarnings("unused")
0573: private void fireTabTornOffEvent(IResultTab tab) {
0574: // Guaranteed to be non-null.
0575: Object[] listeners = _listeners.getListenerList();
0576: // Process the listeners last to first, notifying
0577: // those that are interested in this event.
0578: ResultTabEvent evt = null;
0579: for (int i = listeners.length - 2; i >= 0; i -= 2) {
0580: if (listeners[i] == IResultTabListener.class) {
0581: // Lazily create the event:
0582: if (evt == null) {
0583: evt = new ResultTabEvent(_session, tab);
0584: }
0585: ((IResultTabListener) listeners[i + 1])
0586: .resultTabTornOff(evt);
0587: }
0588: }
0589: }
0590:
0591: @SuppressWarnings("unused")
0592: private void fireTornOffResultTabReturned(IResultTab tab) {
0593: // Guaranteed to be non-null.
0594: Object[] listeners = _listeners.getListenerList();
0595: // Process the listeners last to first, notifying
0596: // those that are interested in this event.
0597: ResultTabEvent evt = null;
0598: for (int i = listeners.length - 2; i >= 0; i -= 2) {
0599: if (listeners[i] == IResultTabListener.class) {
0600: // Lazily create the event:
0601: if (evt == null) {
0602: evt = new ResultTabEvent(_session, tab);
0603: }
0604: ((IResultTabListener) listeners[i + 1])
0605: .tornOffResultTabReturned(evt);
0606: }
0607: }
0608: }
0609:
0610: private void fireExecuterTabAdded(ISQLResultExecuter exec) {
0611: // Guaranteed to be non-null.
0612: Object[] listeners = _listeners.getListenerList();
0613: // Process the listeners last to first, notifying
0614: // those that are interested in this event.
0615: SQLResultExecuterTabEvent evt = null;
0616: for (int i = listeners.length - 2; i >= 0; i -= 2) {
0617: if (listeners[i] == ISQLResultExecuterTabListener.class) {
0618: // Lazily create the event:
0619: if (evt == null) {
0620: evt = new SQLResultExecuterTabEvent(_session, exec);
0621: }
0622: ((ISQLResultExecuterTabListener) listeners[i + 1])
0623: .executerTabAdded(evt);
0624: }
0625: }
0626: }
0627:
0628: private void fireExecuterTabActivated(ISQLResultExecuter exec) {
0629: // Guaranteed to be non-null.
0630: Object[] listeners = _listeners.getListenerList();
0631: // Process the listeners last to first, notifying
0632: // those that are interested in this event.
0633: SQLResultExecuterTabEvent evt = null;
0634: for (int i = listeners.length - 2; i >= 0; i -= 2) {
0635: if (listeners[i] == ISQLResultExecuterTabListener.class) {
0636: // Lazily create the event:
0637: if (evt == null) {
0638: evt = new SQLResultExecuterTabEvent(_session, exec);
0639: }
0640: ((ISQLResultExecuterTabListener) listeners[i + 1])
0641: .executerTabActivated(evt);
0642: }
0643: }
0644: }
0645:
0646: private void appendSQL(String sql) {
0647: if (_sqlEntry.getText().length() > 0) {
0648: _sqlEntry.appendText(LINE_SEPARATOR + LINE_SEPARATOR);
0649: }
0650: _sqlEntry.appendText(sql, true);
0651: _sqlEntry.requestFocus();
0652: }
0653:
0654: private void copySelectedItemToEntryArea() {
0655: SQLHistoryItem item = (SQLHistoryItem) _sqlCombo
0656: .getSelectedItem();
0657: if (item != null) {
0658: appendSQL(item.getSQL());
0659: }
0660: }
0661:
0662: @SuppressWarnings("unused")
0663: private void openSQLHistory() {
0664: new SQLHistoryController(_session, getSQLPanelAPI(),
0665: ((SQLHistoryComboBoxModel) _sqlCombo.getModel())
0666: .getItems());
0667: }
0668:
0669: private void propertiesHaveChanged(String propName) {
0670: final SessionProperties props = _session.getProperties();
0671: if (propName == null
0672: || propName
0673: .equals(SessionProperties.IPropertyNames.SQL_SHARE_HISTORY)) {
0674: _sqlCombo.setUseSharedModel(props.getSQLShareHistory());
0675: }
0676:
0677: if (propName == null
0678: || propName
0679: .equals(SessionProperties.IPropertyNames.AUTO_COMMIT)) {
0680: SetAutoCommitTask task = new SetAutoCommitTask();
0681: if (SwingUtilities.isEventDispatchThread()) {
0682: _session.getApplication().getThreadPool().addTask(task);
0683: } else {
0684: task.run();
0685: }
0686: }
0687:
0688: if (propName == null
0689: || propName
0690: .equals(SessionProperties.IPropertyNames.SQL_LIMIT_ROWS)) {
0691: _limitRowsChk.setSelected(props.getSQLLimitRows());
0692: }
0693:
0694: if (propName == null
0695: || propName
0696: .equals(SessionProperties.IPropertyNames.SQL_NBR_ROWS_TO_SHOW)) {
0697: _nbrRows.setInt(props.getSQLNbrRowsToShow());
0698: }
0699:
0700: if (propName == null
0701: || propName
0702: .equals(SessionProperties.IPropertyNames.FONT_INFO)) {
0703: FontInfo fi = props.getFontInfo();
0704: if (fi != null) {
0705: _sqlEntry.setFont(fi.createFont());
0706: }
0707: }
0708:
0709: if (propName == null
0710: || propName
0711: .equals(SessionProperties.IPropertyNames.SQL_ENTRY_HISTORY_SIZE)
0712: || propName
0713: .equals(SessionProperties.IPropertyNames.LIMIT_SQL_ENTRY_HISTORY_SIZE)) {
0714: if (props.getLimitSQLEntryHistorySize()) {
0715: _sqlCombo.setMaxMemoryCount(props
0716: .getSQLEntryHistorySize());
0717: } else {
0718: _sqlCombo.setMaxMemoryCount(MemoryComboBox.NO_MAX);
0719: }
0720: }
0721:
0722: }
0723:
0724: public void addSqlPanelListener(SqlPanelListener sqlPanelListener) {
0725: _sqlPanelListeners.add(sqlPanelListener);
0726: }
0727:
0728: public ArrayList<SQLHistoryItem> getSQLHistoryItems() {
0729: return ((SQLHistoryComboBoxModel) _sqlCombo.getModel())
0730: .getItems();
0731: }
0732:
0733: private class SetAutoCommitTask implements Runnable {
0734:
0735: public void run() {
0736: final ISQLConnection conn = _session.getSQLConnection();
0737: final SessionProperties props = _session.getProperties();
0738: if (conn != null) {
0739: boolean auto = true;
0740: try {
0741: auto = conn.getAutoCommit();
0742: } catch (SQLException ex) {
0743: s_log.error("Error with transaction control", ex);
0744: _session.showErrorMessage(ex);
0745: }
0746: try {
0747: conn.setAutoCommit(props.getAutoCommit());
0748: } catch (SQLException ex) {
0749: props.setAutoCommit(auto);
0750: _session.showErrorMessage(ex);
0751: }
0752: }
0753: }
0754: }
0755:
0756: private void createGUI() {
0757: final IApplication app = _session.getApplication();
0758: synchronized (getClass()) {
0759: if (!s_loadedSQLHistory) {
0760: final SQLHistory sqlHistory = app.getSQLHistory();
0761: SQLHistoryComboBoxModel
0762: .initializeSharedInstance(sqlHistory.getData());
0763: s_loadedSQLHistory = true;
0764: }
0765: }
0766:
0767: // _tabbedResultsPanel = UIFactory.getInstance().createTabbedPane();
0768: _tabbedExecuterPanel = UIFactory.getInstance()
0769: .createTabbedPane();
0770: _tabbedExecuterPanel
0771: .addChangeListener(new MyExecuterPaneListener());
0772:
0773: setLayout(new BorderLayout());
0774:
0775: _nbrRows.setColumns(8);
0776:
0777: final SessionProperties props = _session.getProperties();
0778: _sqlCombo = new SQLHistoryComboBox(props.getSQLShareHistory());
0779: _sqlCombo.setEditable(false);
0780: if (_sqlCombo.getItemCount() > 0) {
0781: _sqlCombo.setSelectedIndex(_sqlCombo.getItemCount() - 1);
0782: }
0783:
0784: {
0785: JPanel pnl = new JPanel();
0786: pnl.setLayout(new BorderLayout());
0787: pnl.add(_sqlCombo, BorderLayout.CENTER);
0788:
0789: Box box = Box.createHorizontalBox();
0790: box.add(new CopyLastButton(app));
0791: box.add(new ShowHistoryButton(app));
0792: box.add(Box.createHorizontalStrut(10));
0793: // i18n[SQLPanel.limitrowscheckbox.hint=Limit rows: ]
0794: String hint = s_stringMgr
0795: .getString("SQLPanel.limitrowscheckbox.label");
0796: _limitRowsChk = new JCheckBox(hint);
0797: box.add(_limitRowsChk);
0798: box.add(Box.createHorizontalStrut(5));
0799: box.add(_nbrRows);
0800: pnl.add(box, BorderLayout.EAST);
0801: add(pnl, BorderLayout.NORTH);
0802: }
0803:
0804: _splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
0805: _splitPane.setOneTouchExpandable(true);
0806:
0807: installSQLEntryPanel(app.getSQLEntryPanelFactory()
0808: .createSQLEntryPanel(_session,
0809: new HashMap<String, Object>()));
0810:
0811: _executerPanleHolder = new JPanel(new GridLayout(1, 1));
0812: _simpleExecuterPanel = new JPanel(new GridLayout(1, 1));
0813: _executerPanleHolder.add(_simpleExecuterPanel);
0814: _splitPane.add(_executerPanleHolder, JSplitPane.RIGHT);
0815:
0816: add(_splitPane, BorderLayout.CENTER);
0817:
0818: _sqlCombo.addActionListener(_sqlComboListener);
0819: _limitRowsChk
0820: .addChangeListener(new LimitRowsCheckBoxListener());
0821: _nbrRows.getDocument().addDocumentListener(
0822: new LimitRowsTextBoxListener());
0823:
0824: // Set focus to the SQL entry panel.
0825: SwingUtilities.invokeLater(new Runnable() {
0826: public void run() {
0827: _sqlEntry.getTextComponent().requestFocus();
0828: }
0829: });
0830: }
0831:
0832: public Action getUndoAction() {
0833: return _undoAction;
0834: }
0835:
0836: public Action getRedoAction() {
0837: return _redoAction;
0838: }
0839:
0840: public boolean isInMainSessionWindow() {
0841: return _inMainSessionWindow;
0842: }
0843:
0844: /**
0845: * Listens for changes in the execution jtabbedpane and then fires
0846: * activation events
0847: */
0848: private class MyExecuterPaneListener implements ChangeListener {
0849: public void stateChanged(ChangeEvent e) {
0850: JTabbedPane pane = (JTabbedPane) e.getSource();
0851: int index = pane.getSelectedIndex();
0852: if (index != -1) {
0853: fireExecuterTabActivated(_executors.get(index));
0854: }
0855: }
0856: }
0857:
0858: private class MyPropertiesListener implements
0859: PropertyChangeListener {
0860: private boolean _listening = true;
0861:
0862: void stopListening() {
0863: _listening = false;
0864: }
0865:
0866: void startListening() {
0867: _listening = true;
0868: }
0869:
0870: public void propertyChange(PropertyChangeEvent evt) {
0871: if (_listening) {
0872: propertiesHaveChanged(evt.getPropertyName());
0873: }
0874: }
0875: }
0876:
0877: private class SqlComboListener implements ActionListener {
0878: private boolean _listening = true;
0879:
0880: void stopListening() {
0881: _listening = false;
0882: }
0883:
0884: void startListening() {
0885: _listening = true;
0886: }
0887:
0888: public void actionPerformed(ActionEvent evt) {
0889: if (_listening) {
0890: // Because the datamodel for the combobox may be shared
0891: // between sessions we only want to update the sql entry area
0892: // if this is actually the combox box that a new item has been
0893: // selected in.
0894: // SessionWindowManager winMgr = _session.getApplication().getSessionWindowManager();
0895: // if (winMgr.getInternalFrame(_session).isSelected())
0896: // {
0897: copySelectedItemToEntryArea();
0898: }
0899: }
0900: // }
0901:
0902: // private void copySelectedItemToEntryArea()
0903: // {
0904: // SQLHistoryItem item = (SQLHistoryItem)_sqlCombo.getSelectedItem();
0905: // if (item != null)
0906: // {
0907: // appendSQL(item.getSQL());
0908: // }
0909: // }
0910: }
0911:
0912: private class LimitRowsCheckBoxListener implements ChangeListener {
0913: public void stateChanged(ChangeEvent evt) {
0914: if (_propsListener != null) {
0915: _propsListener.stopListening();
0916: }
0917: try {
0918: final boolean limitRows = ((JCheckBox) evt.getSource())
0919: .isSelected();
0920: _nbrRows.setEnabled(limitRows);
0921: _session.getProperties().setSQLLimitRows(limitRows);
0922: } finally {
0923: if (_propsListener != null) {
0924: _propsListener.startListening();
0925: }
0926: }
0927: }
0928: }
0929:
0930: private class LimitRowsTextBoxListener implements DocumentListener {
0931: public void insertUpdate(DocumentEvent evt) {
0932: updateProperties(evt);
0933: }
0934:
0935: public void changedUpdate(DocumentEvent evt) {
0936: updateProperties(evt);
0937: }
0938:
0939: public void removeUpdate(DocumentEvent evt) {
0940: updateProperties(evt);
0941: }
0942:
0943: @SuppressWarnings("unused")
0944: private void updateProperties(DocumentEvent evt) {
0945: if (_propsListener != null) {
0946: _propsListener.stopListening();
0947: }
0948: try {
0949: _session.getProperties().setSQLNbrRowsToShow(
0950: _nbrRows.getInt());
0951: } finally {
0952: if (_propsListener != null) {
0953: _propsListener.startListening();
0954: }
0955: }
0956: }
0957: }
0958:
0959: private class CopyLastButton extends JButton {
0960: private static final long serialVersionUID = 1L;
0961:
0962: CopyLastButton(IApplication app) {
0963: super ();
0964: final SquirrelResources rsrc = app.getResources();
0965: final ImageIcon icon = rsrc
0966: .getIcon(SquirrelResources.IImageNames.COPY_SELECTED);
0967: setIcon(icon);
0968: // i18n[SQLPanel.copylastbutton.hint=Copy current SQL history to entry area]
0969: String hint = s_stringMgr
0970: .getString("SQLPanel.copylastbutton.hint");
0971: setToolTipText(hint);
0972: Dimension dm = getPreferredSize();
0973: dm.setSize(dm.height, dm.height);
0974: setPreferredSize(dm);
0975: addActionListener(new ActionListener() {
0976: public void actionPerformed(ActionEvent e) {
0977: copySelectedItemToEntryArea();
0978: }
0979: });
0980: }
0981: }
0982:
0983: private class ShowHistoryButton extends JButton {
0984: private static final long serialVersionUID = 1L;
0985:
0986: ShowHistoryButton(IApplication app) {
0987: final SquirrelResources rsrc = app.getResources();
0988: final ImageIcon icon = rsrc
0989: .getIcon(SquirrelResources.IImageNames.SQL_HISTORY);
0990: setIcon(icon);
0991: // i18n[SQLPanel.openSqlHistory.hint=Open SQL History]
0992: String hint = s_stringMgr
0993: .getString("SQLPanel.openSqlHistory.hint");
0994: setToolTipText(hint);
0995: Dimension dm = getPreferredSize();
0996: dm.setSize(dm.height, dm.height);
0997: setPreferredSize(dm);
0998: addActionListener(_session.getApplication()
0999: .getActionCollection().get(
1000: OpenSqlHistoryAction.class));
1001: }
1002: }
1003:
1004: /**
1005: * This class is responsible for listening for sql that executes
1006: * for a SQLExecuterPanel and adding it to the SQL history.
1007: */
1008: private class SQLExecutorHistoryListener extends
1009: SQLExecutionAdapter {
1010: public void statementExecuted(String sql) {
1011: _panelAPI.addSQLToHistory(sql);
1012: }
1013: }
1014: }
|