001: //The contents of this file are subject to the Mozilla Public License Version 1.1
002: //(the "License"); you may not use this file except in compliance with the
003: //License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
004: //
005: //Software distributed under the License is distributed on an "AS IS" basis,
006: //WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
007: //for the specific language governing rights and
008: //limitations under the License.
009: //
010: //The Original Code is "The Columba Project"
011: //
012: //The Initial Developers of the Original Code are Frederik Dietz and Timo Stich.
013: //Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
014: //
015: //All Rights Reserved.
016: package org.columba.mail.gui.tree;
017:
018: import java.awt.datatransfer.DataFlavor;
019: import java.awt.datatransfer.Transferable;
020:
021: import javax.swing.JComponent;
022: import javax.swing.TransferHandler;
023: import javax.swing.tree.DefaultMutableTreeNode;
024: import javax.swing.tree.TreePath;
025:
026: import org.columba.api.gui.frame.IFrameMediator;
027: import org.columba.core.command.CommandProcessor;
028: import org.columba.core.facade.DialogFacade;
029: import org.columba.mail.command.IMailFolderCommandReference;
030: import org.columba.mail.command.MailFolderCommandReference;
031: import org.columba.mail.folder.IMailFolder;
032: import org.columba.mail.folder.IMailbox;
033: import org.columba.mail.folder.command.CopyMessageCommand;
034: import org.columba.mail.folder.command.MoveFolderCommand;
035: import org.columba.mail.folder.command.MoveMessageCommand;
036: import org.columba.mail.gui.frame.MailFrameMediator;
037: import org.columba.mail.gui.table.MessageReferencesTransfer;
038:
039: /**
040: * A Transferhandler for the TreeView. This handler will only work with a
041: * treeview component. The only type of folders that can be moved in the
042: * treeview are <code>VirtualFolder</code> and
043: * <code>AbstractLocalFolder</code>
044: * <p>
045: * The handler supports
046: * <ul>
047: * <li>Moving a folder into other folders. If the folder is a
048: * <code>VirtualFolder</code> or a <code>AbstractLocalFolder</code>.
049: * <li>Copying messages into one folder.
050: * </ul>
051: *
052: * @author redsolo
053: */
054: public class TreeViewTransferHandler extends TransferHandler {
055:
056: private IFrameMediator frameMediator;
057:
058: public TreeViewTransferHandler(IFrameMediator frameMediator) {
059: this .frameMediator = frameMediator;
060: }
061:
062: /** {@inheritDoc} */
063: public boolean importData(JComponent comp,
064: Transferable transferProxy) {
065: boolean dataWasImported = false;
066:
067: if (comp instanceof TreeView) {
068: TreeView treeView = (TreeView) comp;
069:
070: try {
071: DataFlavor[] dataFlavors = transferProxy
072: .getTransferDataFlavors();
073:
074: for (int i = 0; (i < dataFlavors.length)
075: && (!dataWasImported); i++) {
076: if (dataFlavors[i].equals(FolderTransfer.FLAVOR)) {
077: dataWasImported = importFolderReferences(
078: treeView,
079: (FolderTransfer) transferProxy
080: .getTransferData(FolderTransfer.FLAVOR));
081: } else if (dataFlavors[i]
082: .equals(MessageReferencesTransfer.FLAVOR)) {
083: MessageReferencesTransfer messageTransferable = (MessageReferencesTransfer) transferProxy
084: .getTransferData(MessageReferencesTransfer.FLAVOR);
085: dataWasImported = importMessageReferences(
086: treeView, messageTransferable);
087: }
088: }
089: } catch (Exception e) { // UnsupportedFlavorException, IOException
090: DialogFacade.showExceptionDialog(e);
091: }
092: }
093:
094: return dataWasImported;
095: }
096:
097: /**
098: * Try to import the folder references. Current implementation can only MOVE
099: * folders, it cannot copy them to a new destination. The actual MOVE call
100: * is done in the <code>exportDone()</code> method.
101: * <p>
102: * This method returns true if dragged folder and destination folder is not
103: * null.
104: *
105: * @param treeView
106: * the tree view to import data into.
107: * @param transferable
108: * the folder references.
109: * @return true if the folders could be imported; false otherwise.
110: */
111: private boolean importFolderReferences(TreeView treeView,
112: FolderTransfer transferable) {
113: boolean dataWasImported = false;
114:
115: IMailFolder destFolder = treeView.getDropTargetFolder();
116: IMailbox draggedFolder = transferable.getFolderReference();
117:
118: if ((destFolder != null) && (draggedFolder != null)) {
119: // We're always doing a MOVE
120: // and this is handled in the exportDone method.
121: dataWasImported = true;
122: }
123:
124: return dataWasImported;
125: }
126:
127: /**
128: * Try to import the message references. This method copies the messages to
129: * the new folder. Note that it will not delete them, since this is done by
130: * the transferhandler that initiated the drag.
131: *
132: * @param treeView
133: * the tree view to import data into.
134: * @param transferable
135: * the message references.
136: * @return true if the messages could be imported; false otherwise.
137: */
138: private boolean importMessageReferences(TreeView treeView,
139: MessageReferencesTransfer transferable) {
140: boolean dataWasImported = false;
141:
142: IMailbox destFolder = null;
143:
144: if (transferable.isDragOperation())
145: destFolder = (IMailbox) treeView.getDropTargetFolder();
146: else if (transferable.isClipboardOperation())
147: destFolder = (IMailbox) ((MailFrameMediator) frameMediator)
148: .getTableSelection().getSourceFolder();
149:
150: IMailFolderCommandReference result = transferable
151: .getFolderReferences();
152: result.setDestinationFolder(destFolder);
153:
154: if (transferable.getAction() == TransferHandler.MOVE) {
155: // move
156: MoveMessageCommand command = new MoveMessageCommand(result);
157: CommandProcessor.getInstance().addOp(command);
158: } else if (transferable.getAction() == TransferHandler.COPY) {
159: // copy
160: CopyMessageCommand command = new CopyMessageCommand(result);
161: CommandProcessor.getInstance().addOp(command);
162: }
163:
164: /*
165: * // copy CopyMessageCommand command = new CopyMessageCommand(result);
166: * CommandProcessor.getInstance().addOp(command);
167: */
168: dataWasImported = true;
169:
170: return dataWasImported;
171: }
172:
173: /** {@inheritDoc} */
174: protected void exportDone(JComponent source, Transferable data,
175: int action) {
176: if (source instanceof TreeView) {
177: TreeView treeView = (TreeView) source;
178:
179: if (data instanceof FolderTransfer) {
180: IMailbox draggedFolder = ((FolderTransfer) data)
181: .getFolderReference();
182: exportFolder(treeView, draggedFolder);
183: }
184: }
185: }
186:
187: /**
188: * Export the folder. Since there is only Virtual Folders who can be copied,
189: * then all other actions are MOVE.
190: *
191: * @param treeView
192: * the treeview that has dragged folder
193: * @param folder
194: * the folder to move.
195: */
196: private void exportFolder(TreeView treeView, IMailbox folder) {
197: MailFolderCommandReference commandRef = new MailFolderCommandReference(
198: folder);
199: IMailFolder destFolder = (IMailFolder) treeView
200: .getDropTargetFolder();
201:
202: if (folder.equals(destFolder))
203: return;
204:
205: commandRef.setDestinationFolder(destFolder);
206: treeView.resetDropTargetFolder();
207:
208: CommandProcessor.getInstance().addOp(
209: new MoveFolderCommand(commandRef));
210: }
211:
212: /** {@inheritDoc} */
213: public int getSourceActions(JComponent c) {
214: int action = TransferHandler.NONE;
215:
216: if (c instanceof TreeView) {
217: action = TransferHandler.MOVE;
218: }
219:
220: return action;
221: }
222:
223: /** {@inheritDoc} */
224: protected Transferable createTransferable(JComponent c) {
225: Transferable exportObject = null;
226:
227: if (c instanceof TreeView) {
228: TreeView treeView = (TreeView) c;
229: TreePath path = treeView.getSelectionModel()
230: .getSelectionPath();
231:
232: IMailFolder folderNode = (IMailFolder) path
233: .getLastPathComponent();
234:
235: if (folderNode.supportsMove()) {
236: exportObject = new FolderTransfer((IMailbox) folderNode);
237: }
238: }
239:
240: return exportObject;
241: }
242:
243: /** {@inheritDoc} */
244: public boolean canImport(JComponent comp,
245: DataFlavor[] transferFlavors) {
246: boolean canHandleOneOfDataFlavors = false;
247:
248: if (comp instanceof TreeView) {
249: TreeView treeView = (TreeView) comp;
250:
251: IMailFolder dropTarget = treeView.getDropTargetFolder();
252:
253: if (dropTarget != null) {
254: for (int k = 0; (k < transferFlavors.length)
255: && (!canHandleOneOfDataFlavors); k++) {
256: if (transferFlavors[k]
257: .equals(MessageReferencesTransfer.FLAVOR)) {
258: canHandleOneOfDataFlavors = canHandleMessageImport(
259: treeView, dropTarget);
260: } else if (transferFlavors[k]
261: .equals(FolderTransfer.FLAVOR)) {
262: canHandleOneOfDataFlavors = canHandleFolderImport(
263: treeView, dropTarget);
264: }
265: }
266: }
267: }
268:
269: return canHandleOneOfDataFlavors;
270: }
271:
272: /**
273: * Returns true if the dragged folder can be imported to the dropped folder.
274: *
275: * @param treeView
276: * the treeview containing the drag/drop folders.
277: * @param dropTarget
278: * the folder node that is intended for the drop action.
279: * @return true if the dragged folder can be imported to the dropped folder.
280: */
281: private boolean canHandleFolderImport(TreeView treeView,
282: IMailFolder dropTarget) {
283: boolean canImport = false;
284:
285: DefaultMutableTreeNode dragTarget = treeView
286: .getSelectedNodeBeforeDragAction();
287:
288: if ((dragTarget != null)
289: && (!dragTarget
290: .isNodeDescendant((DefaultMutableTreeNode) dropTarget))
291: && (dragTarget != dropTarget)) {
292: canImport = dropTarget
293: .supportsAddFolder(((IMailFolder) dragTarget)
294: .getType());
295: }
296:
297: return canImport;
298: }
299:
300: /**
301: * Returns true if the dragged messages can be imported to the dropped
302: * folder.
303: *
304: * @param treeView
305: * the treeview containing the drop folder.
306: * @param dropTarget
307: * the folder node that is intended for the drop action.
308: * @return true if the dragged messages can be imported to the dropped
309: * folder.
310: */
311: private boolean canHandleMessageImport(TreeView treeView,
312: IMailFolder dropTarget) {
313: boolean canImport = false;
314:
315: IMailFolder dragTarget = (IMailFolder) treeView
316: .getSelectedNodeBeforeDragAction();
317:
318: if (dragTarget != dropTarget) {
319: canImport = dropTarget.supportsAddMessage();
320: }
321:
322: return canImport;
323: }
324: }
|