001: package net.sourceforge.squirrel_sql.client.session.sqlfilter;
002:
003: /*
004: * Copyright (C) 2003-2004 Maury Hammel
005: * mjhammel@users.sourceforge.net
006: *
007: * Modifications Copyright (C) 2003-2004 Jason Height
008: *
009: * Adapted from SessionPropertiesSheet.java by Colin Bell.
010: *
011: * This library is free software; you can redistribute it and/or
012: * modify it under the terms of the GNU Lesser General Public
013: * License as published by the Free Software Foundation; either
014: * version 2.1 of the License, or (at your option) any later version.
015: *
016: * This library is distributed in the hope that it will be useful,
017: * but WITHOUT ANY WARRANTY; without even the implied warranty of
018: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: * Lesser General Public License for more details.
020: *
021: * You should have received a copy of the GNU Lesser General Public
022: * License along with this library; if not, write to the Free Software
023: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024: */
025: import java.awt.Dimension;
026: import java.awt.GridBagConstraints;
027: import java.awt.GridBagLayout;
028: import java.awt.event.ActionEvent;
029: import java.awt.event.ActionListener;
030: import java.sql.SQLException;
031: import java.sql.Types;
032: import java.util.ArrayList;
033: import java.util.Iterator;
034: import java.util.List;
035: import java.util.Map;
036: import java.util.SortedSet;
037: import java.util.TreeMap;
038: import java.util.TreeSet;
039:
040: import javax.swing.BorderFactory;
041: import javax.swing.JButton;
042: import javax.swing.JLabel;
043: import javax.swing.JPanel;
044: import javax.swing.JScrollPane;
045: import javax.swing.JTabbedPane;
046: import javax.swing.event.ChangeEvent;
047: import javax.swing.event.ChangeListener;
048:
049: import net.sourceforge.squirrel_sql.client.gui.builders.UIFactory;
050: import net.sourceforge.squirrel_sql.client.gui.session.BaseSessionInternalFrame;
051: import net.sourceforge.squirrel_sql.client.session.IObjectTreeAPI;
052: import net.sourceforge.squirrel_sql.client.session.mainpanel.objecttree.tabs.table.ContentsTab;
053: import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetException;
054: import net.sourceforge.squirrel_sql.fw.gui.GUIUtils;
055: import net.sourceforge.squirrel_sql.fw.sql.IDatabaseObjectInfo;
056: import net.sourceforge.squirrel_sql.fw.sql.ISQLConnection;
057: import net.sourceforge.squirrel_sql.fw.sql.ITableInfo;
058: import net.sourceforge.squirrel_sql.fw.sql.SQLDatabaseMetaData;
059: import net.sourceforge.squirrel_sql.fw.sql.TableColumnInfo;
060: import net.sourceforge.squirrel_sql.fw.util.StringManager;
061: import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
062: import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
063: import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
064:
065: /**
066: * SQLFilter dialog gui.
067: * JASON: Rename to SQLFilterInternalFrame
068: *
069: * @author <A HREF="mailto:mjhammel@users.sourceforge.net">Maury Hammel</A>
070: */
071: public class SQLFilterSheet extends BaseSessionInternalFrame {
072: private static final long serialVersionUID = 1L;
073:
074: /** Logger for this class. */
075: private static final ILogger s_log = LoggerController
076: .createLogger(SQLFilterSheet.class);
077:
078: /** Internationalized strings for this class. */
079: private static final StringManager s_stringMgr = StringManagerFactory
080: .getStringManager(SQLFilterSheet.class);
081:
082: private static final String TITLE = s_stringMgr
083: .getString("SQLFilterSheet.title");
084:
085: /** The object tree we are filtering. */
086: private final IObjectTreeAPI _objectTree;
087:
088: /** A reference to a class containing information about the database metadata. */
089: transient private final IDatabaseObjectInfo _objectInfo;
090:
091: /** A list of panels that make up this sheet. */
092: private List<ISQLFilterPanel> _panels = new ArrayList<ISQLFilterPanel>();
093:
094: /** A variable that contains a value that indicates which tab currently has focus. */
095: private int _tabSelected;
096:
097: /** Frame title. */
098: private JLabel _titleLbl = new JLabel();
099:
100: /** A button used to trigger the clearing of SQL Filter information. */
101: private JButton _clearFilter = new JButton();
102:
103: /** A reference to a panel for the SQL Where Clause. */
104: transient private WhereClausePanel _whereClausePanel = null;
105:
106: /** A reference to a panel for the SQL Order By Clause. */
107: transient private OrderByClausePanel _orderByClausePanel = null;
108:
109: /**
110: * Creates a new instance of SQLFilterSheet
111: *
112: * @param objectTree
113: * @param objectInfo The object we are filtering within the object
114: * tree.
115: */
116: public SQLFilterSheet(IObjectTreeAPI objectTree,
117: IDatabaseObjectInfo objectInfo) {
118: super (objectTree.getSession(), TITLE, true);
119: if (objectInfo == null) {
120: throw new IllegalArgumentException(
121: "IDatabaseObjectInfo == null");
122: }
123: _objectTree = objectTree;
124: _objectInfo = objectInfo;
125:
126: createGUI();
127: }
128:
129: /**
130: * Position and display the sheet.
131: *
132: * @param show A boolean that determines whether the sheet is shown
133: * or hidden.
134: */
135: public synchronized void setVisible(boolean show) {
136: boolean reallyShow = true;
137:
138: if (show) {
139: if (!isVisible()) {
140: ContentsTab tab = (ContentsTab) _objectTree
141: .getTabbedPaneIfSelected(_objectInfo
142: .getDatabaseObjectType(), ContentsTab
143: .getContentsTabTitle());
144:
145: if (tab == null) {
146: reallyShow = false;
147: // i18n[SQLFilterSheet.contentsMsg=You must have the Contents Tab selected to activate the SQL Filter]
148: String msg = s_stringMgr
149: .getString("SQLFilterSheet.contentsMsg");
150: _objectTree.getSession().showMessage(msg);
151: } else {
152: final boolean isDebug = s_log.isDebugEnabled();
153: long start = 0;
154: for (Iterator<ISQLFilterPanel> it = _panels
155: .iterator(); it.hasNext();) {
156: ISQLFilterPanel pnl = it.next();
157: if (isDebug) {
158: start = System.currentTimeMillis();
159: }
160:
161: pnl.initialize(tab.getSQLFilterClauses());
162: if (isDebug) {
163: s_log
164: .debug("Panel "
165: + pnl.getTitle()
166: + " initialized in "
167: + (System
168: .currentTimeMillis() - start)
169: + "ms");
170: }
171: }
172: pack();
173: /*
174: * TODO: Find out why
175: * KLUDGE: For some reason, I am not able to get the sheet to
176: * size correctly. It always displays with a size that causes
177: * the sub-panels to have their scrollbars showing. Add a bit
178: * of an increase in the size of the panel so the scrollbars
179: * are not displayed.
180: */
181: Dimension d = getSize();
182: d.width += 5;
183: d.height += 5;
184: setSize(d);
185: /*
186: * END-KLUDGE
187: */
188: GUIUtils.centerWithinDesktop(this );
189: moveToFront();
190: }
191: }
192: }
193:
194: if (!show || reallyShow) {
195: super .setVisible(show);
196: }
197: }
198:
199: /**
200: * Set title of this frame. Ensure that the title label matches the frame title.
201: *
202: * @param title New title text.
203: */
204: public void setTitle(String title) {
205: if (null != _titleLbl) {
206: // this method is called from the super class's constructor
207: // therfore _titleLbl is null for that call.
208: _titleLbl.setText(title + ": "
209: + _objectInfo.getSimpleName());
210: }
211: }
212:
213: /**
214: * Dispose of the sheet.
215: */
216: private void performClose() {
217: dispose();
218: }
219:
220: public IDatabaseObjectInfo getDatabaseObjectInfo() {
221: return _objectInfo;
222: }
223:
224: public IObjectTreeAPI getObjectTree() {
225: return _objectTree;
226: }
227:
228: /**
229: * OK button pressed. Edit data and if ok save to aliases model and
230: * then close dialog.
231: */
232: private void performOk() {
233: final boolean isDebug = s_log.isDebugEnabled();
234: long start = 0;
235: for (Iterator<ISQLFilterPanel> it = _panels.iterator(); it
236: .hasNext();) {
237: ISQLFilterPanel pnl = it.next();
238: if (isDebug) {
239: start = System.currentTimeMillis();
240: }
241: pnl.applyChanges();
242: if (isDebug) {
243: s_log.debug("Panel " + pnl.getTitle()
244: + " applied changes in "
245: + (System.currentTimeMillis() - start) + "ms");
246: }
247: }
248: try {
249: ContentsTab cTab = (ContentsTab) _objectTree
250: .getTabbedPaneIfSelected(_objectInfo
251: .getDatabaseObjectType(), ContentsTab
252: .getContentsTabTitle());
253: if (cTab != null) {
254: cTab.refreshComponent();
255: }
256: } catch (DataSetException ex) {
257: getSession().showErrorMessage(ex);
258: }
259:
260: dispose();
261: }
262:
263: /**
264: * Create the GUI elements for the sheet.
265: */
266: private void createGUI() {
267: SortedSet<String> columnNames = new TreeSet<String>();
268: Map<String, Boolean> textColumns = new TreeMap<String, Boolean>();
269:
270: setDefaultCloseOperation(DISPOSE_ON_CLOSE);
271: setTitle(getTitle());
272:
273: // This is a tool window.
274: GUIUtils.makeToolWindow(this , true);
275:
276: try {
277: ISQLConnection sqlConnection = getSession()
278: .getSQLConnection();
279: SQLDatabaseMetaData md = sqlConnection.getSQLMetaData();
280: TableColumnInfo[] infos = md
281: .getColumnInfo((ITableInfo) _objectInfo);
282: for (int i = 0; i < infos.length; i++) {
283: String columnName = infos[i].getColumnName();
284: int dataType = infos[i].getDataType();
285: columnNames.add(columnName);
286: if ((dataType == Types.CHAR)
287: || (dataType == Types.CLOB)
288: || (dataType == Types.LONGVARCHAR)
289: || (dataType == Types.VARCHAR)) {
290: textColumns.put(columnName, Boolean.valueOf(true));
291: }
292:
293: }
294: } catch (SQLException ex) {
295: // i18n[SQLFilterSheet.error.columnList=Unable to get list of columns {0}]
296: String msg = s_stringMgr.getString(
297: "SQLFilterSheet.error.columnList", ex);
298: getSession().getApplication().showErrorDialog(msg);
299: }
300:
301: _whereClausePanel = new WhereClausePanel(columnNames,
302: textColumns, _objectInfo.getQualifiedName());
303: _orderByClausePanel = new OrderByClausePanel(columnNames,
304: _objectInfo.getQualifiedName());
305: _panels.add(_whereClausePanel);
306: _panels.add(_orderByClausePanel);
307:
308: JTabbedPane tabPane = UIFactory.getInstance()
309: .createTabbedPane();
310: for (Iterator<ISQLFilterPanel> it = _panels.iterator(); it
311: .hasNext();) {
312: ISQLFilterPanel pnl = it.next();
313: String pnlTitle = pnl.getTitle();
314: String hint = pnl.getHint();
315: final JScrollPane sp = new JScrollPane(pnl
316: .getPanelComponent());
317: sp.setBorder(BorderFactory.createEmptyBorder());
318: tabPane.addTab(pnlTitle, null, sp, hint);
319: }
320:
321: tabPane.addChangeListener(new ChangeListener() {
322: public void stateChanged(ChangeEvent event) {
323: setButtonLabel(((JTabbedPane) event.getSource())
324: .getSelectedIndex());
325: }
326: });
327:
328: final JPanel contentPane = new JPanel(new GridBagLayout());
329: contentPane.setBorder(BorderFactory.createEmptyBorder(5, 10, 5,
330: 10));
331: setContentPane(contentPane);
332:
333: GridBagConstraints gbc = new GridBagConstraints();
334:
335: gbc.gridwidth = 1;
336:
337: gbc.gridx = 0;
338: gbc.gridy = 0;
339:
340: gbc.fill = GridBagConstraints.BOTH;
341: gbc.weightx = 1;
342: contentPane.add(_titleLbl, gbc);
343:
344: gbc.fill = GridBagConstraints.NONE;
345: gbc.gridx = GridBagConstraints.REMAINDER;
346: setButtonLabel(0);
347: _tabSelected = 0;
348: _clearFilter.addActionListener(new ActionListener() {
349: public void actionPerformed(ActionEvent evt) {
350: clearFilter();
351: }
352: });
353: contentPane.add(_clearFilter);
354:
355: gbc.fill = GridBagConstraints.BOTH;
356: gbc.gridwidth = 2;
357: gbc.gridx = 0;
358: ++gbc.gridy;
359: gbc.weighty = 1;
360: contentPane.add(tabPane, gbc);
361:
362: ++gbc.gridy;
363: gbc.gridwidth = 2;
364: gbc.weighty = 0;
365: contentPane.add(createButtonsPanel(), gbc);
366: }
367:
368: /**
369: * Clear out the SQL Filter information for the appropriate tab.
370: */
371: private void clearFilter() {
372: if (_tabSelected == 0) {
373: _whereClausePanel.clearFilter();
374: } else {
375: _orderByClausePanel.clearFilter();
376: }
377: }
378:
379: /**
380: * Create a panel that contains the buttons that control the closing
381: * of the sheet.
382: *
383: * @return An instance of a JPanel.
384: */
385: private JPanel createButtonsPanel() {
386: JPanel pnl = new JPanel();
387: // i18n[SQLFilterSheet.okButtonLabel=OK]
388: String okLabel = s_stringMgr
389: .getString("SQLFilterSheet.okButtonLabel");
390: JButton okBtn = new JButton(okLabel);
391: okBtn.addActionListener(new ActionListener() {
392: public void actionPerformed(ActionEvent evt) {
393: performOk();
394: }
395: });
396: // i18n[SQLFilterSheet.closeButtonLabel=Close]
397: String closeLabel = s_stringMgr
398: .getString("SQLFilterSheet.closeButtonLabel");
399: JButton closeBtn = new JButton(closeLabel);
400: closeBtn.addActionListener(new ActionListener() {
401: public void actionPerformed(ActionEvent evt) {
402: performClose();
403: }
404: });
405:
406: pnl.add(okBtn);
407: pnl.add(closeBtn);
408:
409: GUIUtils
410: .setJButtonSizesTheSame(new JButton[] { okBtn, closeBtn });
411: getRootPane().setDefaultButton(okBtn);
412:
413: return pnl;
414: }
415:
416: /**
417: * Change the text of the 'clear' button depending on which
418: * clause panel has focus.
419: *
420: * @param tabSelected An integer indicating which panel has focus
421: */
422: private void setButtonLabel(int tabSelected) {
423: String title = null;
424: if (tabSelected == 0) {
425: title = _whereClausePanel.getTitle();
426: } else {
427: title = _orderByClausePanel.getTitle();
428: }
429: // i18n[SQLFilterSheet.clearButtonLabel=Clear {0}]
430: String label = s_stringMgr.getString(
431: "SQLFilterSheet.clearButtonLabel", title);
432: _clearFilter.setText(label);
433: _tabSelected = tabSelected;
434: }
435: }
|