001: /*
002: * TableReplacer.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.components;
013:
014: import java.awt.Component;
015: import java.awt.EventQueue;
016: import javax.swing.SwingUtilities;
017: import javax.swing.event.TableModelEvent;
018: import javax.swing.event.TableModelListener;
019: import workbench.gui.WbSwingUtilities;
020: import workbench.gui.actions.FindDataAction;
021: import workbench.gui.actions.FindDataAgainAction;
022: import workbench.gui.actions.ReplaceDataAction;
023: import workbench.interfaces.Replaceable;
024: import workbench.interfaces.Searchable;
025: import workbench.resource.ResourceMgr;
026: import workbench.storage.DataStoreReplacer;
027: import workbench.storage.Position;
028: import workbench.storage.Position;
029: import workbench.storage.filter.ColumnComparator;
030: import workbench.storage.filter.ColumnExpression;
031: import workbench.storage.filter.ContainsComparator;
032: import workbench.storage.filter.RegExComparator;
033: import workbench.util.ConverterException;
034: import workbench.util.ExceptionUtil;
035:
036: /**
037: * @author support@sql-workbench.net
038: */
039: public class TableReplacer implements Searchable, Replaceable,
040: TableModelListener {
041: private WbTable client;
042: private FindDataAction findAction;
043: private FindDataAgainAction findAgainAction;
044: private ReplaceDataAction replaceAction;
045: private DataStoreReplacer replacer;
046: private boolean tableChanging = false;
047: private boolean oldColumnSelection = false;
048:
049: public TableReplacer(WbTable table) {
050: this .client = table;
051: this .client.addTableModelListener(this );
052: this .replacer = new DataStoreReplacer();
053: this .findAction = new FindDataAction(this );
054: this .findAction.setEnabled(false);
055: this .findAction.setCreateMenuSeparator(true);
056: this .findAgainAction = new FindDataAgainAction(this );
057: this .findAgainAction.setEnabled(false);
058: this .replaceAction = new ReplaceDataAction(this );
059: this .replaceAction.setEnabled(false);
060: oldColumnSelection = client.getColumnSelectionAllowed();
061: }
062:
063: public FindDataAction getFindAction() {
064: return this .findAction;
065: }
066:
067: public FindDataAgainAction getFindAgainAction() {
068: return this .findAgainAction;
069: }
070:
071: public ReplaceDataAction getReplaceAction() {
072: return this .replaceAction;
073: }
074:
075: public int find() {
076: boolean showDialog = true;
077: String crit = this .replacer.getLastCriteria();
078: SearchCriteriaPanel p = new SearchCriteriaPanel(crit,
079: "workbench.data.search", true);
080:
081: Component parent = SwingUtilities
082: .getWindowAncestor(this .client);
083: Position pos = Position.NO_POSITION;
084: while (showDialog) {
085: boolean doFind = p.showFindDialog(parent, ResourceMgr
086: .getString("TxtWindowTitleSearchDataText"));
087: if (!doFind)
088: return -1;
089: String criteria = p.getCriteria();
090: boolean ignoreCase = p.getIgnoreCase();
091: boolean wholeWord = p.getWholeWordOnly();
092: boolean useRegex = p.getUseRegex();
093: try {
094: this .findAgainAction.setEnabled(false);
095: if (p.getHighlightAll()) {
096: initTableHighlighter(criteria, ignoreCase, useRegex);
097: } else {
098: client.clearHighlightExpression();
099: pos = this .replacer.find(criteria, ignoreCase,
100: wholeWord, useRegex);
101: }
102: showDialog = false;
103: this .findAgainAction.setEnabled(pos.isValid());
104: } catch (Exception e) {
105: pos = Position.NO_POSITION;
106: WbSwingUtilities.showErrorMessage(parent, ExceptionUtil
107: .getDisplay(e));
108: showDialog = true;
109: }
110: }
111:
112: highlightPosition(pos);
113:
114: return pos.getRow();
115: }
116:
117: protected void initTableHighlighter(String criteria,
118: boolean ignoreCase, boolean useRegex) {
119: ColumnComparator comp = null;
120: if (useRegex) {
121: comp = new RegExComparator();
122: } else {
123: comp = new ContainsComparator();
124: }
125: ColumnExpression filter = new ColumnExpression(comp, criteria);
126: filter.setIgnoreCase(ignoreCase);
127: client.applyHighlightExpression(filter);
128: }
129:
130: protected void highlightPosition(final Position pos) {
131: final int row = pos.getRow();
132: int col = pos.getColumn();
133: final int realCol = (this .client.getShowStatusColumn() ? col + 1
134: : col);
135: EventQueue.invokeLater(new Runnable() {
136: public void run() {
137: client.clearSelection();
138: if (pos.isValid()) {
139: client.selectCell(row, realCol);
140: }
141: }
142: });
143: }
144:
145: public int findNext() {
146: Position pos = this .replacer.findNext();
147: highlightPosition(pos);
148: return pos.getRow();
149: }
150:
151: public void replace() {
152: if (this .client == null)
153: return;
154:
155: if (!this .client.checkPkColumns(true)) {
156: return;
157: }
158: ReplacePanel panel = new ReplacePanel(this ,
159: "workbench.data.replace", ResourceMgr
160: .getString("LblSelectedRowsOnly"));
161: String title = ResourceMgr
162: .getString("TxtWindowTitleReplaceDataText");
163: panel.showReplaceDialog(this .client, this .replacer
164: .getLastCriteria(), title);
165: }
166:
167: /**
168: * Called by the ReplacePanel.
169: */
170: public int findFirst(String text, boolean ignoreCase,
171: boolean wholeWord, boolean useRegex) {
172: this .replacer.reset();
173: Position pos = this .replacer.find(text, ignoreCase, wholeWord,
174: useRegex);
175: highlightPosition(pos);
176: return pos.getRow();
177: }
178:
179: public boolean replaceCurrent(String aReplacement, boolean useRegex) {
180: boolean replaced = false;
181: try {
182: Position pos = this .replacer.getLastFoundPosition();
183: replaced = this .replacer.replaceCurrent(aReplacement);
184: if (replaced) {
185: fireTableChanged(pos);
186: }
187: } catch (ConverterException e) {
188: WbSwingUtilities.showErrorMessage(client, e.getMessage());
189: replaced = false;
190: }
191: return replaced;
192: }
193:
194: public boolean replaceNext(String aReplacement, boolean useRegex) {
195: boolean replaced = false;
196: replaced = replaceCurrent(aReplacement, useRegex);
197: if (replaced) {
198: Position pos = this .replacer.findNext();
199: highlightPosition(pos);
200: }
201: return replaced;
202: }
203:
204: private void fireTableChanged(Position pos) {
205: try {
206: tableChanging = true;
207:
208: this .client.setShowStatusColumn(true);
209:
210: TableModelEvent event = null;
211: if (pos == null) {
212: event = new TableModelEvent(this .client.getModel(), 0,
213: this .client.getRowCount() - 1);
214: } else {
215: event = new TableModelEvent(this .client.getModel(), pos
216: .getRow(), pos.getRow());
217: }
218: this .client.getDataStoreTableModel().fireTableDataChanged();
219: } finally {
220: tableChanging = false;
221: }
222: }
223:
224: public int replaceAll(String value, String replacement,
225: boolean selectedText, boolean ignoreCase,
226: boolean wholeWord, boolean useRegex) {
227: int rows[] = null;
228:
229: if (selectedText) {
230: rows = this .client.getSelectedRows();
231: }
232: int replaced = 0;
233: try {
234: replaced = this .replacer.replaceAll(value, replacement,
235: rows, ignoreCase, wholeWord, useRegex);
236: if (replaced > 0) {
237: fireTableChanged(null);
238: }
239: } catch (ConverterException e) {
240: WbSwingUtilities.showErrorMessage(client, e.getMessage());
241: }
242: return replaced;
243: }
244:
245: public boolean isTextSelected() {
246: return (this .client.getSelectedColumnCount() > 0);
247: }
248:
249: public void tableChanged(TableModelEvent arg0) {
250: if (tableChanging)
251: return;
252:
253: this .replacer.setDataStore(this .client.getDataStore());
254: final boolean hasData = client.getRowCount() > 0;
255: EventQueue.invokeLater(new Runnable() {
256: public void run() {
257: findAction.setEnabled(hasData);
258: replaceAction.setEnabled(hasData);
259: }
260: });
261:
262: }
263:
264: }
|