001: /*
002: * Created on 2003-nov-08
003: */
004: package org.columba.mail.gui.config.filter;
005:
006: import java.awt.Component;
007: import java.awt.datatransfer.DataFlavor;
008: import java.awt.datatransfer.Transferable;
009:
010: import javax.swing.JComponent;
011: import javax.swing.JScrollPane;
012: import javax.swing.TransferHandler;
013:
014: import org.columba.core.facade.DialogFacade;
015: import org.columba.core.filter.Filter;
016:
017: /**
018: * A <code>TransferHandler</code> that handles the transfering of filters
019: * between two filter dialogs.
020: * <p>
021: * Note that the transfer handler will only allow to move filters within a
022: * component, whereas it is possible to either move or copy filters between two
023: * different components.
024: *
025: * @author Erik Mattsson
026: */
027:
028: public class FilterTransferHandler extends TransferHandler {
029:
030: /**
031: * Creates a FilterTransferHandler.
032: *
033: * @param src
034: * the source component.
035: */
036: public FilterTransferHandler() {
037: }
038:
039: /** {@inheritDoc} */
040: public boolean canImport(JComponent comp,
041: DataFlavor[] transferFlavors) {
042: boolean canHandleOneOfDataFlavors = false;
043:
044: if (canHandleImport(comp)) {
045: for (int k = 0; (k < transferFlavors.length)
046: || (!canHandleOneOfDataFlavors); k++) {
047: if (transferFlavors[k]
048: .equals(ObjectArrayTransfer.FLAVOR)) {
049: canHandleOneOfDataFlavors = true;
050: }
051: }
052: }
053:
054: return canHandleOneOfDataFlavors;
055: }
056:
057: /** {@inheritDoc} */
058: protected Transferable createTransferable(JComponent c) {
059: if (!canHandleExport(c)) {
060: return null;
061: }
062:
063: Transferable transferable = null;
064: FilterListTable filterTable = getFilterListTable(c);
065:
066: if (filterTable != null) {
067: FilterListDataModel model = (FilterListDataModel) filterTable
068: .getModel();
069:
070: int[] selectedRows = filterTable.getSelectedRows();
071: Object[] selectedFilters = new Object[selectedRows.length];
072:
073: for (int i = 0; i < selectedFilters.length; i++) {
074: selectedFilters[i] = model.getFilter(selectedRows[i])
075: .clone();
076: }
077:
078: transferable = new ObjectArrayTransfer(filterTable,
079: selectedFilters);
080: }
081:
082: return transferable;
083: }
084:
085: /** {@inheritDoc} */
086: protected void exportDone(JComponent source, Transferable data,
087: int action) {
088: if (!canHandleExport(source)) {
089: return;
090: }
091:
092: if (!((action == COPY_OR_MOVE) || (action == MOVE))) {
093: return;
094: }
095:
096: FilterListTable list = getFilterListTable(source);
097:
098: if (list != null) {
099: try {
100: Object transferable = data
101: .getTransferData(ObjectArrayTransfer.FLAVOR);
102:
103: if (!(transferable instanceof ObjectArrayTransfer)) {
104: return;
105: }
106:
107: ObjectArrayTransfer arrayTransferable = (ObjectArrayTransfer) transferable;
108:
109: if (!source.equals(arrayTransferable.getSource())) {
110: return;
111: }
112:
113: Object[] filters = arrayTransferable.getData();
114: FilterListDataModel model = (FilterListDataModel) list
115: .getModel();
116:
117: for (int i = 0; i < filters.length; i++) {
118: model.removeFilter((Filter) filters[i]);
119: }
120: } catch (Exception e) {
121: DialogFacade.showExceptionDialog(e);
122: }
123: }
124: }
125:
126: /**
127: * Returns the source actions that the specified component can handle. If
128: * the source component is the same as the specified component, then there
129: * should only be possible to move the filter not copy it. {@inheritDoc}
130: */
131: public int getSourceActions(JComponent c) {
132: /*
133: * if ( c == transferSource ) return MOVE;
134: */
135: if (canHandleImport(c)) {
136: return COPY_OR_MOVE;
137: } else {
138: return NONE;
139: }
140: }
141:
142: /** {@inheritDoc} */
143: public boolean importData(JComponent comp, Transferable t) {
144: if (!canHandleImport(comp)) {
145: return false;
146: }
147:
148: FilterListTable list = getFilterListTable(comp);
149:
150: if (list != null) {
151: FilterListDataModel model = (FilterListDataModel) list
152: .getModel();
153:
154: try {
155: Object obj = t
156: .getTransferData(ObjectArrayTransfer.FLAVOR);
157:
158: if (!(obj instanceof ObjectArrayTransfer)) {
159: return false;
160: }
161:
162: ObjectArrayTransfer at = (ObjectArrayTransfer) obj;
163: Object[] filters = at.getData();
164:
165: // block transfer to self!
166: if (comp.equals(at.getSource())) {
167: return false;
168: }
169:
170: // if it is in a table, then we need to insert it at the
171: // selected position.
172: if (comp instanceof FilterListTable) {
173: int selectedRow = list.getSelectedRow();
174:
175: int i;
176:
177: for (i = (filters.length - 1); i >= 0; i--) {
178: model.insertFilter((Filter) filters[i],
179: selectedRow);
180: }
181:
182: list.getSelectionModel().clearSelection();
183: }
184: // if it is in a scroll pane, then we add to the end of the
185: // list.
186: else if (comp instanceof JScrollPane) {
187: for (int i = 0; i < filters.length; i++) {
188: model.addFilter((Filter) filters[i]);
189: }
190: }
191: } catch (Exception e) {
192: DialogFacade.showExceptionDialog(e);
193: }
194: }
195:
196: return true;
197: }
198:
199: /**
200: * Returns true if this handler can import data from the specified
201: * component.
202: *
203: * @param component
204: * the component that is exporting the data.
205: * @return true if this handler can import data from the specified
206: * component.
207: */
208: private boolean canHandleImport(JComponent component) {
209: return ((component instanceof FilterListTable) || (component instanceof JScrollPane));
210: }
211:
212: /**
213: * Returns true if this handler can export data to the specified component.
214: *
215: * @param component
216: * the component that is importing the data.
217: * @return true if this handler can export data to the specified component.
218: */
219: private boolean canHandleExport(JComponent component) {
220: return (component instanceof FilterListTable);
221: }
222:
223: /**
224: * Returns the <code>FilterListTable</code> from the component. This is a
225: * utility method to simplify the retrieving of a FilterListTable. Since the
226: * table and the JScollPane is a valid importer, then we need a method that
227: * returns the table when adding filters to it.
228: *
229: * @param comp
230: * a JComponent that either is a <code>JScrollPane</code> or a
231: * <code>FilterListTable</code>
232: * @return a FilterListTable; or null if the component doesnt contain a
233: * <code>FilterListTable</code>.
234: */
235: private FilterListTable getFilterListTable(JComponent comp) {
236: Component tableComponent = null;
237:
238: if (comp instanceof JScrollPane) {
239: tableComponent = ((JScrollPane) comp).getViewport()
240: .getView();
241: } else if (comp instanceof FilterListTable) {
242: tableComponent = comp;
243: }
244:
245: return (FilterListTable) tableComponent;
246: }
247: }
|