/**
* ======================== legal notice ======================
*
* File: TreeSourceAndDestTransferHandler.java Created: 13. June 2012, 04:57
* Author: Geronimo Project: cmpc - a
* java frontend (client) part of compound media player uses external players to
* play the media
*
* CMP - compound media player
*
* is a client/server mediaplayer intended to play any media from any
* workstation without the need to export or mount shares. cmps is an easy to
* use backend with a (ready to use) HTML-interface. Additionally the backend
* supports authentication via HTTP-digest authorization. cmpc is a client with
* vdr-like osd-menues.
*
* Copyright (c) 2012 Reinhard Mantey, some rights reserved! published under
* Creative Commons by-sa For details see
* http://creativecommons.org/licenses/by-sa/3.0/
*
* The cmp project's homepage is at
* http://projects.vdr-developer.org/projects/cmp
*
* --------------------------------------------------------------
*/
package de.schwarzrot.control.dnd;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.io.File;
import java.util.List;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.TransferHandler;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import ca.odell.glazedlists.EventList;
import de.schwarzrot.media.domain.AbstractMediaNode;
import de.schwarzrot.media.domain.Genre;
import de.schwarzrot.media.domain.Media;
public class TreeSourceAndDestTransferHandler extends TransferHandler {
private static final long serialVersionUID = 713L;
public TreeSourceAndDestTransferHandler(JTree tree, Map cache,
EventList changes) {
this.tree = tree;
nodeCache = cache;
this.changes = changes;
}
// dest
@Override
public boolean canImport(TransferHandler.TransferSupport support) {
if (!support.isDrop())
return false;
support.setShowDropLocation(true);
if (support.isDataFlavorSupported(TreePathTransferable.TreePathFlavor) && support.getDropAction() == MOVE)
return true;
if (support.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
return true;
return false;
}
// source
@Override
public Transferable createTransferable(JComponent c) {
if (c != tree)
return null;
TreePath selectionPath = tree.getSelectionPath();
return new TreePathTransferable(selectionPath);
}
// source
@Override
public void exportDone(JComponent c, Transferable data, int action) {
tree.updateUI();
}
// source
@Override
public int getSourceActions(JComponent c) {
return MOVE;
}
// dest
@Override
public boolean importData(TransferHandler.TransferSupport support) {
if (!canImport(support))
return false;
JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation();
TreePath targetPath = tree.getClosestPathForLocation(dl.getDropPoint().x, dl.getDropPoint().y);
DefaultMutableTreeNode targetNode = (DefaultMutableTreeNode) targetPath.getLastPathComponent();
if (support.isDataFlavorSupported(TreePathTransferable.TreePathFlavor)) {
// move a genre in tree
try {
TreePath sourcePath = (TreePath) support.getTransferable().getTransferData(
TreePathTransferable.TreePathFlavor);
DefaultMutableTreeNode transferNode = (DefaultMutableTreeNode) sourcePath.getLastPathComponent();
DefaultMutableTreeNode sourceParentNode = (DefaultMutableTreeNode) transferNode.getParent();
Genre target = (Genre) targetNode.getUserObject();
Genre transfer = (Genre) transferNode.getUserObject();
// System.out.println("importData() targetPath: " + targetPath);
// System.out.println("importData() sourcePath: " + sourcePath);
sourceParentNode.remove(transferNode);
targetNode.add(transferNode);
nodeCache.remove(transfer.getRealPath());
// System.out.println("old path of genre to move: " + transfer.getRealPath().getAbsolutePath());
transfer.setParent(target);
// System.out.println("new path of moved genre: " + transfer.getRealPath().getAbsolutePath());
nodeCache.put(transfer.getRealPath(), transferNode);
transfer.update();
refreshNodeCache();
if (!changes.contains(transfer)) {
changes.getReadWriteLock().writeLock().lock();
changes.add(transfer);
changes.getReadWriteLock().writeLock().unlock();
}
} catch (Throwable t) {
t.printStackTrace();
}
} else if (support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
// move media files from one genre to another (no visible tree change)
try {
@SuppressWarnings("unchecked")
List fileList = (List) support.getTransferable().getTransferData(
DataFlavor.javaFileListFlavor);
for (File f : fileList)
move2TargetNode(targetNode, f); // each media can have different parent, so don't optimize here
} catch (Throwable t) {
t.printStackTrace();
}
}
return false;
}
protected void cacheNode(DefaultMutableTreeNode node) {
Genre g = (Genre) node.getUserObject();
nodeCache.put(g.getRealPath(), node);
for (int i = 0; i < node.getChildCount(); ++i) {
DefaultMutableTreeNode sub = (DefaultMutableTreeNode) node.getChildAt(i);
cacheNode(sub);
}
}
protected void move2TargetNode(DefaultMutableTreeNode targetNode, File mediaPath) {
if (targetNode == null || mediaPath == null)
return;
Genre targetGenre = (Genre) targetNode.getUserObject();
DefaultMutableTreeNode node = nodeCache.get(mediaPath.getParentFile());
if (targetGenre != null && node != null) {
Media transferMedia = null;
Genre sourceGenre = (Genre) node.getUserObject();
for (Media m : sourceGenre.getMediaList()) {
if (m.getRealPath().equals(mediaPath)) {
transferMedia = m;
break;
}
}
if (transferMedia != null) {
System.out.println("old path of media to transfer: " + transferMedia.getRealPath().getAbsolutePath());
transferMedia.setParent(targetGenre);
System.out.println("new path of transferred media: " + transferMedia.getRealPath().getAbsolutePath());
if (!changes.contains(transferMedia)) {
changes.getReadWriteLock().writeLock().lock();
changes.add(transferMedia);
changes.getReadWriteLock().writeLock().unlock();
}
}
// } else {
// if (targetGenre == null)
// System.err.println("failed to determine target genre!");
// if (node == null)
// System.err.println("failed to determine source parent of media: <|" + mediaPath.getAbsolutePath()
// + "|>");
// for (File f : nodeCache.keySet()) {
// String ap = f.getAbsolutePath();
//
// if (ap.startsWith("/audio/in/"))
// System.out.println("nodeCache contains: " + ap);
// }
}
}
protected void refreshNodeCache() {
nodeCache.clear();
DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getModel().getRoot();
cacheNode(node);
}
private JTree tree;
private EventList changes;
private Map nodeCache;
}