/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.components.browser.dnd; import java.awt.Cursor; import java.awt.Point; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetContext; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.io.IOException; import javax.swing.JTree; import javax.swing.tree.TreePath; import org.openflexo.components.browser.BrowserElement; import org.openflexo.components.browser.ProjectBrowser; import org.openflexo.components.browser.view.BrowserView; import org.openflexo.foundation.FlexoEditor; import org.openflexo.toolbox.ToolBox; /** * @author bmangez <B>Class Description</B> */ public class TreeDropTarget implements DropTargetListener { private static Cursor VALID_CURSOR; private static Cursor INVALID_CURSOR; static { try { VALID_CURSOR = Cursor.getSystemCustomCursor("MoveDrop32x32"); INVALID_CURSOR = Cursor.getSystemCustomCursor("Invalid32x32"); } catch (Exception e) { e.printStackTrace(); VALID_CURSOR = Cursor.getDefaultCursor(); INVALID_CURSOR = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); } } protected DropTarget target; protected BrowserView.FlexoJTree targetTree; protected ProjectBrowser _browser; public TreeDropTarget(BrowserView.FlexoJTree tree, ProjectBrowser browser) { targetTree = tree; target = new DropTarget(targetTree, this); _browser = browser; } protected FlexoEditor getEditor() { return targetTree.getBrowserView().getEditor(); } /* * Drop Event Handlers */ private BrowserElement getNodeForEvent(DropTargetDragEvent dtde) { Point p = dtde.getLocation(); DropTargetContext dtc = dtde.getDropTargetContext(); JTree tree = (JTree) dtc.getComponent(); TreePath path = tree.getClosestPathForLocation(p.x, p.y); if (path == null) { return null; } else { return (BrowserElement) path.getLastPathComponent(); } } @Override public void dragEnter(DropTargetDragEvent dtde) { dtde.acceptDrag(DnDConstants.ACTION_MOVE); BrowserElement node = getNodeForEvent(dtde); TreePath path = targetTree.getClosestPathForLocation(dtde.getLocation().x, dtde.getLocation().y); if (!targetTree.getModel().isLeaf(path.getLastPathComponent()) && !targetTree.isExpanded(path)) { targetTree.handleAutoExpand(path); } targetTree.paintDraggedNode(dtde.getLocation()); /* if (node==null || !sourceIsDroppableInTarget(getSourceNode(dtde.getTransferable()), node)) { dtde.rejectDrag(); } else { targetTree.setSelectionPath(path); // start by supporting move operations dtde.acceptDrag(DnDConstants.ACTION_MOVE); }*/ } @Override public void dragOver(DropTargetDragEvent dtde) { BrowserElement node = getNodeForEvent(dtde); TreePath path = targetTree.getClosestPathForLocation(dtde.getLocation().x, dtde.getLocation().y); TreePath realPath = targetTree.getPathForLocation(dtde.getLocation().x, dtde.getLocation().y); if (realPath != null && !targetTree.getModel().isLeaf(realPath.getLastPathComponent()) && !targetTree.isExpanded(path)) { targetTree.handleAutoExpand(realPath); } else { targetTree.stopExpandCountDown(); } targetTree.paintDraggedNode(dtde.getLocation()); targetTree.setSelectionPath(realPath); BrowserElement source = getSourceNode(dtde.getTransferable()); if (source == node) { return; } if (node == null || !targetAcceptsSource(node, source)) { dtde.rejectDrag(); if (ToolBox.getPLATFORM() == ToolBox.MACOS && _browser != null && _browser.getController() != null && _browser.getController().getFlexoFrame() != null) { _browser.getController().getFlexoFrame().setCursor(INVALID_CURSOR); } } else { targetTree.setSelectionPath(path); // start by supporting move operations dtde.acceptDrag(DnDConstants.ACTION_MOVE); if (ToolBox.isMacOS() && _browser.getController() != null) { _browser.getController().getFlexoFrame().setCursor(VALID_CURSOR); } } } @Override public void dragExit(DropTargetEvent dte) { targetTree.stopExpandCountDown(); targetTree.clearDraggedNode(); } @Override public void dropActionChanged(DropTargetDragEvent dtde) { } @Override public void drop(DropTargetDropEvent dtde) { targetTree.stopExpandCountDown(); targetTree.clearDraggedNode(); Point pt = dtde.getLocation(); DropTargetContext dtc = dtde.getDropTargetContext(); JTree tree = (JTree) dtc.getComponent(); TreePath parentpath = tree.getClosestPathForLocation(pt.x, pt.y); if (parentpath == null) { return; } BrowserElement destination = (BrowserElement) parentpath.getLastPathComponent(); try { Transferable transferable = dtde.getTransferable(); DataFlavor[] dataFlavors = transferable.getTransferDataFlavors(); for (int i = 0; i < dataFlavors.length; i++) { if (transferable.isDataFlavorSupported(dataFlavors[i])) { BrowserElement moved = null; try { moved = (BrowserElement) transferable.getTransferData(dataFlavors[i]); } catch (ClassCastException e) { dtde.rejectDrop(); return; } if (targetAcceptsSource(destination, moved) && handleDrop(moved, destination)) { dtde.acceptDrop(dtde.getDropAction()); dtde.dropComplete(true); return; } } } dtde.rejectDrop(); } catch (Exception e) { e.printStackTrace(); dtde.rejectDrop(); } } private BrowserElement getSourceNode(Transferable transferable) { if (transferable instanceof ElementMovable) { return ((ElementMovable) transferable).path; } DataFlavor[] dataFlavors = transferable.getTransferDataFlavors(); for (int i = 0; i < dataFlavors.length; i++) { if (transferable.isDataFlavorSupported(dataFlavors[i])) { BrowserElement moved = null; try { moved = (BrowserElement) transferable.getTransferData(dataFlavors[i]); return moved; } catch (ClassCastException e) { } catch (UnsupportedFlavorException e) { } catch (IOException e) { } } } return null; } public boolean handleDrop(BrowserElement source, BrowserElement target) { return false; } public boolean targetAcceptsSource(BrowserElement target, BrowserElement source) { return false; } }