001: /*
002: * DefineFilterExpressionPanel.java
003: *
004: * This file is part of SQL Workbench/J, http://www.sql-workbench.net
005: *
006: * Copyright 2002-2008, Thomas Kellerer
007: * No part of this code maybe reused without the permission of the author
008: *
009: * To contact the author please send an email to: support@sql-workbench.net
010: *
011: */
012: package workbench.gui.filter;
013:
014: import java.awt.BorderLayout;
015: import java.awt.Dimension;
016: import java.awt.FlowLayout;
017: import java.awt.GridBagConstraints;
018: import java.awt.GridBagLayout;
019: import java.awt.Insets;
020: import java.awt.event.ActionEvent;
021: import java.awt.event.ActionListener;
022: import java.io.IOException;
023: import java.util.ArrayList;
024: import java.util.List;
025: import javax.swing.BorderFactory;
026: import javax.swing.ButtonGroup;
027: import javax.swing.JButton;
028: import javax.swing.JFileChooser;
029: import javax.swing.JPanel;
030: import javax.swing.JRadioButton;
031: import javax.swing.JScrollPane;
032: import javax.swing.SwingUtilities;
033: import javax.swing.filechooser.FileFilter;
034: import workbench.gui.WbSwingUtilities;
035: import workbench.gui.components.ExtensionFileFilter;
036: import workbench.gui.components.FlatButton;
037: import workbench.gui.components.ValidatingDialog;
038: import workbench.gui.components.WbTable;
039: import workbench.gui.components.WbToolbar;
040: import workbench.interfaces.ValidatingComponent;
041: import workbench.resource.ResourceMgr;
042: import workbench.resource.Settings;
043: import workbench.storage.DataStore;
044: import workbench.storage.ResultInfo;
045: import workbench.storage.filter.AndExpression;
046: import workbench.storage.filter.ColumnComparator;
047: import workbench.storage.filter.ComplexExpression;
048: import workbench.storage.filter.ExpressionValue;
049: import workbench.storage.filter.FilterExpression;
050: import workbench.storage.filter.OrExpression;
051: import workbench.util.ExceptionUtil;
052: import workbench.util.StringUtil;
053: import workbench.util.WbFile;
054:
055: /**
056: * A Panel to display a filter dialog for a {@link workbench.storage.DataStore}
057: * @author support@sql-workbench.net
058: */
059: public class DefineFilterExpressionPanel extends JPanel implements
060: ActionListener, ValidatingComponent {
061: private ResultInfo columnInfo;
062: private List<PanelEntry> panels = new ArrayList<PanelEntry>();
063: private JButton addLineButton;
064: private JRadioButton andButton;
065: private JRadioButton orButton;
066: private JPanel expressions;
067: private JScrollPane scroll;
068: private JButton saveButton = new JButton();
069: private JButton loadButton = new JButton();
070:
071: public DefineFilterExpressionPanel(ResultInfo source) {
072: this (source, true);
073: }
074:
075: public DefineFilterExpressionPanel(ResultInfo source,
076: boolean allowSave) {
077: columnInfo = source;
078: expressions = new JPanel();
079: this .expressions.setLayout(new GridBagLayout());
080:
081: this .setLayout(new BorderLayout(0, 2));
082:
083: Insets ins = new Insets(0, 0, 0, 0);
084: orButton = new JRadioButton(ResourceMgr
085: .getString("LblFilterOrOption"));
086: orButton.setToolTipText(ResourceMgr
087: .getDescription("LblFilterOrOption"));
088: orButton.setMargin(ins);
089: andButton = new JRadioButton(ResourceMgr
090: .getString("LblFilterAndOption"));
091: andButton.setToolTipText(ResourceMgr
092: .getDescription("LblFilterAndOption"));
093: andButton.setMargin(ins);
094: ButtonGroup g = new ButtonGroup();
095: g.add(orButton);
096: g.add(andButton);
097: andButton.setSelected(true);
098:
099: JPanel radioPanel = new JPanel();
100: radioPanel.setLayout(new FlowLayout(FlowLayout.RIGHT, 0, 0));
101: radioPanel.setBorder(BorderFactory.createEtchedBorder());
102: radioPanel.add(andButton);
103: radioPanel.add(orButton);
104:
105: JPanel p = new JPanel();
106: p.setLayout(new GridBagLayout());
107: GridBagConstraints c = new GridBagConstraints();
108: c.gridx = 0;
109: c.gridy = 0;
110: c.anchor = GridBagConstraints.EAST;
111: c.weighty = 0;
112: c.weightx = 0;
113:
114: if (allowSave) {
115: WbToolbar bar = new WbToolbar();
116: bar.setBorder(BorderFactory.createEtchedBorder());
117: saveButton.setIcon(ResourceMgr
118: .getImage(ResourceMgr.IMG_SAVE));
119: saveButton.setMargin(ins);
120: saveButton.setToolTipText(ResourceMgr
121: .getDescription("SaveFilter"));
122:
123: loadButton.setIcon(ResourceMgr.getImage("Open"));
124: loadButton.setMargin(new Insets(0, 0, 0, 0));
125: loadButton.setToolTipText(ResourceMgr
126: .getDescription("LoadFilter"));
127:
128: loadButton.addActionListener(this );
129: saveButton.addActionListener(this );
130: bar.add(loadButton);
131: bar.addSeparator();
132: bar.add(saveButton);
133: p.add(bar, c);
134: }
135: c.anchor = GridBagConstraints.EAST;
136: c.gridx++;
137: c.weightx = 1;
138: p.add(radioPanel, c);
139:
140: addLineButton = new FlatButton(ResourceMgr
141: .getString("LblFilterAddLine"));
142: Dimension d = radioPanel.getPreferredSize();
143: int ph = (int) d.getHeight();
144: addLineButton.setMinimumSize(new Dimension(25, ph));
145: d = addLineButton.getPreferredSize();
146: addLineButton.setPreferredSize(new Dimension(
147: (int) d.getWidth(), ph));
148: addLineButton.addActionListener(this );
149: c.gridx++;
150: c.anchor = GridBagConstraints.NORTHEAST;
151: c.weightx = 1;
152: c.insets = new Insets(0, 15, 0, 2);
153: p.add(addLineButton);
154:
155: this .add(p, BorderLayout.NORTH);
156: scroll = new JScrollPane(this .expressions);
157: scroll.setBorder(BorderFactory.createEtchedBorder());
158: this .add(scroll, BorderLayout.CENTER);
159: d = addExpressionPanel();
160: scroll.getVerticalScrollBar().setUnitIncrement(
161: (int) d.getHeight());
162: scroll.getHorizontalScrollBar().setUnitIncrement(25);
163:
164: double w = d.getWidth()
165: + scroll.getHorizontalScrollBar().getPreferredSize()
166: .getWidth();
167: double h = (d.getHeight() * 3)
168: + andButton.getPreferredSize().getHeight()
169: + scroll.getHorizontalScrollBar().getPreferredSize()
170: .getHeight();
171: this .setPreferredSize(new Dimension((int) w, (int) h));
172: }
173:
174: private void saveFilter() {
175: FilterExpression filter = this .getExpression();
176: if (filter == null) {
177: WbSwingUtilities
178: .showMessageKey(this , "ErrFilterNotPresent");
179: return;
180: }
181:
182: String lastDir = Settings.getInstance().getLastFilterDir();
183: FileFilter ff = ExtensionFileFilter.getXmlFileFilter();
184: JFileChooser fc = new JFileChooser(lastDir);
185: fc.addChoosableFileFilter(ff);
186: int answer = fc.showSaveDialog(SwingUtilities
187: .getWindowAncestor(this ));
188: if (answer == JFileChooser.APPROVE_OPTION) {
189: String file = fc.getSelectedFile().getAbsolutePath();
190: if (!file.toLowerCase().endsWith(".xml")) {
191: file = file + ".xml";
192: }
193: String dir = fc.getCurrentDirectory().getAbsolutePath();
194: Settings.getInstance().setLastFilterDir(dir);
195: try {
196: WbFile f = new WbFile(file);
197: FilterDefinitionManager.getInstance().saveFilter(
198: filter, f);
199: } catch (IOException e) {
200: String msg = ResourceMgr.getString("ErrLoadingFilter");
201: msg = msg + "\n" + ExceptionUtil.getDisplay(e);
202: WbSwingUtilities.showErrorMessage(this , msg);
203: }
204: }
205: }
206:
207: private void loadFilter() {
208: String lastDir = Settings.getInstance().getLastFilterDir();
209: FileFilter ff = ExtensionFileFilter.getXmlFileFilter();
210: JFileChooser fc = new JFileChooser(lastDir);
211: fc.addChoosableFileFilter(ff);
212: int answer = fc.showOpenDialog(SwingUtilities
213: .getWindowAncestor(this ));
214: if (answer == JFileChooser.APPROVE_OPTION) {
215: String file = fc.getSelectedFile().getAbsolutePath();
216: String dir = fc.getCurrentDirectory().getAbsolutePath();
217: Settings.getInstance().setLastFilterDir(dir);
218: try {
219: FilterExpression f = FilterDefinitionManager
220: .getInstance().loadFilter(file);
221: if (f != null) {
222: this .setFilter(f);
223: }
224: } catch (Exception e) {
225: String msg = ResourceMgr.getString("ErrLoadingFilter");
226: msg = msg + "\n" + ExceptionUtil.getDisplay(e);
227: WbSwingUtilities.showErrorMessage(this , msg);
228: }
229: }
230: }
231:
232: private void removeAllPanels() {
233: this .panels.clear();
234: this .expressions.removeAll();
235: }
236:
237: public void setFilter(FilterExpression filter) {
238: if (filter == null)
239: return;
240:
241: if (filter instanceof AndExpression) {
242: this .andButton.setSelected(true);
243: } else if (filter instanceof OrExpression) {
244: this .orButton.setSelected(true);
245: } else {
246: return;
247: }
248: removeAllPanels();
249: ComplexExpression cExp = (ComplexExpression) filter;
250: List expList = cExp.getExpressions();
251: int count = expList.size();
252: for (int i = 0; i < count; i++) {
253:
254: try {
255: ExpressionValue exp = (ExpressionValue) expList.get(i);
256: this .addExpressionPanel(exp);
257: PanelEntry item = this .panels
258: .get(this .panels.size() - 1);
259: ColumnExpressionPanel panel = item.expressionPanel;
260: panel.setExpressionValue(exp);
261: } catch (ClassCastException e) {
262: // ignore this as we cannot handle other expressions anyway...
263: }
264: }
265: this .invalidate();
266: this .validate();
267: this .repaint();
268: }
269:
270: public boolean validateInput() {
271: for (PanelEntry entry : panels) {
272: ColumnComparator comp = entry.expressionPanel
273: .getComparator();
274: if (comp == null) {
275: String msg = ResourceMgr
276: .getString("ErrFilterNoComparator");
277: WbSwingUtilities.showErrorMessage(this , msg);
278: return false;
279: }
280:
281: if (!entry.expressionPanel.validateInput()) {
282: String msg = ResourceMgr
283: .getString("ErrFilterWrongValue");
284: msg = StringUtil.replace(msg, "%value%",
285: entry.expressionPanel.getInputValue());
286: msg = StringUtil.replace(msg, "%op%", comp
287: .getOperator());
288: WbSwingUtilities.showErrorMessage(this , msg);
289: return false;
290: }
291: }
292: return true;
293: }
294:
295: public FilterExpression getExpression() {
296: ComplexExpression exp = null;
297:
298: for (PanelEntry entry : panels) {
299: FilterExpression f = (FilterExpression) entry.expressionPanel
300: .getExpressionValue();
301: if (f != null) {
302: if (exp == null) {
303: if (andButton.isSelected())
304: exp = new AndExpression();
305: else
306: exp = new OrExpression();
307: }
308: exp.addExpression(f);
309: }
310: }
311: return exp;
312: }
313:
314: private Dimension addExpressionPanel() {
315: return addExpressionPanel(null);
316: }
317:
318: private Dimension addExpressionPanel(ExpressionValue filter) {
319: final ColumnExpressionPanel exp = new ColumnExpressionPanel(
320: columnInfo, filter);
321: JButton b = new FlatButton(ResourceMgr.getImage("Remove"));
322: b.setPreferredSize(new Dimension(21, 21));
323: b.addActionListener(this );
324: JPanel p = new JPanel(new GridBagLayout());
325: GridBagConstraints c1 = new GridBagConstraints();
326: c1.gridx = 0;
327: c1.gridy = 0;
328: c1.fill = GridBagConstraints.HORIZONTAL;
329: c1.anchor = GridBagConstraints.WEST;
330: c1.weighty = 0.0;
331: c1.weightx = 1.0;
332: p.add(exp, c1);
333:
334: c1.gridx++;
335: c1.weightx = 0.0;
336: c1.fill = GridBagConstraints.NONE;
337: p.add(b, c1);
338:
339: PanelEntry item = new PanelEntry(p, exp);
340: b.putClientProperty("panel", item);
341: this .panels.add(item);
342: GridBagConstraints c = new GridBagConstraints();
343: c.gridx = 0;
344: c.gridy = GridBagConstraints.RELATIVE;
345: c.fill = GridBagConstraints.HORIZONTAL;
346: c.anchor = GridBagConstraints.NORTHWEST;
347: c.weighty = 1.0;
348: c.weightx = 1.0;
349:
350: GridBagLayout l = (GridBagLayout) expressions.getLayout();
351: for (int i = 0; i < this .panels.size(); i++) {
352: PanelEntry entry = panels.get(i);
353: GridBagConstraints cons = l.getConstraints(entry.container);
354: cons.weighty = 0;
355: l.setConstraints(entry.container, cons);
356: }
357: this .expressions.add(p, c);
358: this .invalidate();
359: this .validate();
360: this .repaint();
361: Dimension ps = exp.getPreferredSize();
362: Dimension bs = b.getPreferredSize();
363: Dimension prefSize = new Dimension((int) (ps.getWidth() + bs
364: .getWidth()), (int) ps.getHeight());
365: return prefSize;
366: }
367:
368: public void actionPerformed(ActionEvent e) {
369: if (e.getSource() == saveButton) {
370: saveFilter();
371: } else if (e.getSource() == loadButton) {
372: loadFilter();
373: } else if (e.getSource() == addLineButton) {
374: addExpressionPanel();
375: } else if (e.getSource() instanceof JButton) {
376: JButton button = (JButton) e.getSource();
377: PanelEntry entry = (PanelEntry) button
378: .getClientProperty("panel");
379: //entry.expressionPanel.removeChangeListener(this);
380: this .panels.remove(entry);
381: this .expressions.remove(entry.container);
382: GridBagLayout l = (GridBagLayout) expressions.getLayout();
383: int count = this .panels.size();
384: for (int i = 0; i < count; i++) {
385: entry = panels.get(i);
386: GridBagConstraints cons = l
387: .getConstraints(entry.container);
388: if (i < count - 1)
389: cons.weighty = 0;
390: else
391: cons.weighty = 1.0;
392: l.setConstraints(entry.container, cons);
393: }
394: this .invalidate();
395: this .validate();
396: this .repaint();
397: }
398: }
399:
400: public static void showDialog(WbTable source) {
401: DataStore ds = source.getDataStore();
402: if (ds == null)
403: return;
404: ResultInfo info = ds.getResultInfo();
405: if (info == null)
406: return;
407:
408: DefineFilterExpressionPanel panel = new DefineFilterExpressionPanel(
409: info);
410:
411: panel.setFilter(source.getLastFilter());
412: String title = ResourceMgr.getString("MsgFilterWindowTitle");
413: boolean showDialog = true;
414: while (showDialog) {
415:
416: boolean result = ValidatingDialog.showConfirmDialog(
417: SwingUtilities.getWindowAncestor(source), panel,
418: title);
419: if (result) {
420: if (panel.validateInput()) {
421: FilterExpression filter = panel.getExpression();
422: source.applyFilter(filter);
423: showDialog = false;
424: }
425: } else {
426: showDialog = false;
427: }
428: }
429: }
430:
431: public void stateChanged(javax.swing.event.ChangeEvent changeEvent) {
432: FilterExpression e = this .getExpression();
433: this .saveButton.setEnabled(e != null);
434: }
435:
436: public void componentDisplayed() {
437: if (this .panels.size() == 0)
438: return;
439: PanelEntry entry = panels.get(0);
440: if (entry == null || entry.expressionPanel == null)
441: return;
442: entry.expressionPanel.setFocusToColumn();
443: }
444:
445: }
446:
447: class PanelEntry {
448: JPanel container;
449: ColumnExpressionPanel expressionPanel;
450:
451: public PanelEntry(JPanel p, ColumnExpressionPanel ep) {
452: container = p;
453: expressionPanel = ep;
454: }
455: }
|