/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library 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 * Lesser General Public License for more details. */ package org.geotools.gui.swing.contexttree; import java.awt.AlphaComposite; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.swing.JComponent; import javax.swing.TransferHandler; import javax.swing.table.TableCellRenderer; import javax.swing.tree.TreePath; import org.geotools.map.MapContext; import org.geotools.map.MapLayer; import org.jdesktop.swingx.JXTreeTable; /** * TransferHandler Class used for drag and drop purpose * * @author Johann Sorel * */ final class DADContextTreeTransferHandler extends TransferHandler { private ArrayList<DADMetaTransfer> metaTransfers = null; /** * constructor */ DADContextTreeTransferHandler() { super(); } /** * create a transferable that contains all paths that are currently selected in * a given tree * @param c the draged component * @return all selected paths in the given tree * (or null if the given component is not a tree table) * @see javax.swing.TransferHandler#createTransferable(javax.swing.JComponent) */ @Override public Transferable createTransferable(JComponent c) { metaTransfers = new ArrayList<DADMetaTransfer>(); Transferable t = null; if (c instanceof JXTreeTable) { JXTreeTable treeTable = (JXTreeTable) c; int[] selectedRows = treeTable.getSelectedRows(); int nbSelected = selectedRows.length; for (int i = 0; i < nbSelected; i++) { DADMetaTransfer mt = new DADMetaTransfer(); mt.dragPath = treeTable.getPathForRow(selectedRows[i]); metaTransfers.add(mt); } if (metaTransfers.size() > 0) { for (DADMetaTransfer mt : metaTransfers) { mt.draggedNode = (ContextTreeNode) mt.dragPath.getLastPathComponent(); ContextTreeNode parent = (ContextTreeNode) mt.draggedNode.getParent(); mt.origine = parent.getIndex(mt.draggedNode); mt.origine_parent = parent.getUserObject(); } } t = new DADContextTreeTransferable(metaTransfers); } return t; } /** * move selected paths when export of drag is done * @param source the component that was the source of the data * @param data the data that was transferred or possibly null if the action is NONE. * @param action the actual action that was performed */ @Override protected void exportDone(JComponent source, Transferable data, int action) { if (source instanceof JXTreeTable) { JXTreeTable treeTable = (JXTreeTable) source; ContextTreeModel model = (ContextTreeModel) treeTable.getTreeTableModel(); TreePath currentPath = treeTable.getPathForRow(treeTable.getSelectedRow()); if (currentPath != null) { addNodes(currentPath, model, data); } else { insertNodes(treeTable, model, data); } } super.exportDone(source, data, action); } protected void addNodes(TreePath currentPath, ContextTreeModel model, Transferable data) { ContextTreeNode targetNode = (ContextTreeNode) currentPath.getLastPathComponent(); try { List<DADMetaTransfer> metatransfers = (List<DADMetaTransfer>) data.getTransferData(DataFlavor.stringFlavor); for (DADMetaTransfer metatransfer : metatransfers) { TreePath movedPath = metatransfer.dragPath; ContextTreeNode moveNode = (ContextTreeNode) movedPath.getLastPathComponent(); if (!moveNode.equals(targetNode) && !targetNode.isNodeAncestor(moveNode)) { //deplacement de maplayer dans un mapcontext if ((targetNode.getUserObject() instanceof MapContext) && (moveNode.getUserObject() instanceof MapLayer)) { int place = targetNode.getChildCount(); model.removeLayerFromParent(moveNode); model.insertLayerInto(moveNode, targetNode, place); } //deplacement de mapcontext sur mapcontext else if ((targetNode.getUserObject() instanceof MapContext) && (moveNode.getUserObject() instanceof MapContext)) { ContextTreeNode father = (ContextTreeNode) targetNode.getParent(); int place = father.getIndex(targetNode); model.moveMapContext(moveNode, father, place); } //deplacement de maplayer sur maplayer else if ((targetNode.getUserObject() instanceof MapLayer) && (moveNode.getUserObject() instanceof MapLayer)) { ContextTreeNode father = (ContextTreeNode) targetNode.getParent(); int place = father.getIndex(targetNode); model.removeLayerFromParent(moveNode); model.insertLayerInto(moveNode, father, place); } } } } catch (UnsupportedFlavorException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * insert a number of given nodes * @param treeTable the target treetable * @param model the model containing the nodes * @param data the nodes to insert */ protected void insertNodes(JXTreeTable treeTable, ContextTreeModel model, Transferable data) { Point location = ((DADContextTreeDrop) treeTable.getDropTarget()).getMostRecentDragLocation(); TreePath path = treeTable.getPathForLocation(location.x, location.y); ContextTreeNode targetNode = (ContextTreeNode) path.getLastPathComponent(); ContextTreeNode parent = (ContextTreeNode) targetNode.getParent(); try { List<DADMetaTransfer> metatransfers = (List<DADMetaTransfer>) data.getTransferData(DataFlavor.stringFlavor); for (DADMetaTransfer metatransfer : metatransfers) { TreePath movedPath = metatransfer.dragPath; ContextTreeNode moveNode = (ContextTreeNode) movedPath.getLastPathComponent(); if (!moveNode.equals(targetNode) && !parent.isNodeAncestor(moveNode)) { // deplacement maplayer dans mapcontext if ((moveNode.getUserObject() instanceof MapLayer) && (parent.getUserObject() instanceof MapContext)) { int place = model.getIndexOfChild(parent, targetNode); if (parent.getUserObject().equals(metatransfer.origine_parent) && place > metatransfer.origine) { place--; } if (moveNode.getParent().equals(parent)) { model.moveLayer(moveNode, parent, place); } else { model.removeLayerFromParent(moveNode); model.insertLayerInto(moveNode, parent, place); } } // delacement de mapcontext else if ((moveNode.getUserObject() instanceof MapContext) && (parent.getUserObject() == null)) { int place = model.getIndexOfChild(parent, targetNode); if (parent.getUserObject() != null) { if (parent.getUserObject().equals(metatransfer.origine_parent) && place > metatransfer.origine) { place--; } } model.moveMapContext(moveNode, parent, place); } } } } catch (UnsupportedFlavorException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * Returns the type of transfer actions supported by the source. * This transfer handler supports moving of tree nodes so it returns MOVE. * @param c the draged component * @return TransferHandler.MOVE */ @Override public int getSourceActions(JComponent c) { return TransferHandler.MOVE; } /** * get a drag image from the currently dragged node (if any) * @param tree the tree table showing the node * @return the image to draw during drag */ public BufferedImage getDragImage(JXTreeTable tree) { BufferedImage image = null; try { for (DADMetaTransfer mt : metaTransfers) { if (mt.dragPath != null) { int row = tree.getRowForPath(mt.dragPath); Rectangle pathBounds = tree.getCellRect(row, 0, false); TableCellRenderer r = tree.getCellRenderer(row, 0); JComponent lbl = (JComponent) r.getTableCellRendererComponent(tree, mt.draggedNode.toString(), false, false, row, 0); lbl.setBounds(pathBounds); image = new BufferedImage((int) pathBounds.getWidth(), (int) pathBounds.getHeight(), java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE); Graphics2D graphics = image.createGraphics(); graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f)); boolean previousOpaque = lbl.isOpaque(); lbl.setOpaque(false); lbl.paint(graphics); lbl.setOpaque(previousOpaque); graphics.dispose(); } } } catch (RuntimeException re) { } return image; } }