krysalis-jplugin/src/java/org/krysalis/swingx/tree CArrowImage.java,NONE,1.1 CTransferableTreePath.java,NONE,1.1 CTree.java,NONE,1.1

[email protected]
Newsgroups gmane.comp.krysalis.metamorphosis.cvs
Message-ID <[email protected]>
Update of /cvsroot/metamorphosis/krysalis-jplugin/src/java/org/krysalis/swingx/tree
In directory sc8-pr-cvs1:/tmp/cvs-serv14625/org/krysalis/swingx/tree

Added Files:
	CArrowImage.java CTransferableTreePath.java CTree.java 
Log Message:
Move the tree stuff under swingx and thus clean the swingx.swing package

--- NEW FILE: CArrowImage.java ---
/*****************************************************************************
 * Copyright (C) The Krysalis project. All rights reserved.                  *
 * ------------------------------------------------------------------------- *
 * This software is published under the terms of the Krysalis Software       *
 * License version 1.1_01, a copy of which has been included  with this      *
 * distribution in the LICENSE file.                                         *
 *****************************************************************************/
package  org.krysalis.swingx.tree;

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.SystemColor;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;

/**
 *  A BufferedImage of one of four types of arrow (up, down, left or right)
 *  drawn to the size specified on the constructor.
 *
 *@author     Luca Jun Barozzi
 *@created    16 settembre 2001
 */
public class CArrowImage extends BufferedImage {
// Constants...
    /**
     *  Description of the Field
     */
    public final static int ARROW_UP = 0;
    /**
     *  Description of the Field
     */
    public final static int ARROW_DOWN = 1;
    /**
     *  Description of the Field
     */
    public final static int ARROW_LEFT = 2;
    /**
     *  Description of the Field
     */
    public final static int ARROW_RIGHT = 3;

// Member variables...
    private GeneralPath _pathArrow = new GeneralPath();


// Constructor...
    /**
     *  Constructor for the CArrowImage object
     *
     *@param  nArrowDirection  Description of Parameter
     */
    public CArrowImage(int nArrowDirection) {
        this(15, 9, nArrowDirection);
    }


    /**
     *  Constructor for the CArrowImage object
     *
     *@param  nWidth           Description of Parameter
     *@param  nHeight          Description of Parameter
     *@param  nArrowDirection  Description of Parameter
     */
    public CArrowImage(int nWidth, int nHeight, int nArrowDirection) {
        super(nWidth, nHeight, TYPE_INT_ARGB_PRE);
        // Set the width, height and image type

        Map map = new HashMap();
        map.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        map.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        RenderingHints hints = new RenderingHints(map);

        Graphics2D g2 = this.createGraphics();
        // Create a graphics context for this buffered image
        g2.setRenderingHints(hints);

        float h = getHeight();
        float w = getWidth();
        float w13 = w / 3;
        float w12 = w / 2;
        float w23 = w * 2 / 3;
        float h13 = h / 3;
        float h12 = h / 2;
        float h23 = h * 2 / 3;

        switch (nArrowDirection) {
            case ARROW_UP:
                _pathArrow.moveTo(w12, h12);
                _pathArrow.lineTo(w12, 0);
                _pathArrow.lineTo(w, h - 1);
                _pathArrow.lineTo(0, h - 1);
                _pathArrow.closePath();
                g2.setPaint(new GradientPaint(
                        w13, h13, SystemColor.controlLtHighlight,
                        w, h - 1, SystemColor.controlShadow
                        )
                        );

                g2.fill(_pathArrow);

                g2.setColor(SystemColor.controlDkShadow);
                g2.draw(new Line2D.Float(0, h - 1, w, h - 1));
                g2.setColor(SystemColor.controlShadow);
                g2.draw(new Line2D.Float(w12, 0, w, h - 1));
                g2.setColor(SystemColor.controlLtHighlight);
                g2.draw(new Line2D.Float(0, h - 1, w12, 0));
                break;
            case ARROW_DOWN:
                _pathArrow.moveTo(w12, h12);
                _pathArrow.lineTo(w, 0);
                _pathArrow.lineTo(w12, h - 1);
                _pathArrow.closePath();
                g2.setPaint(new GradientPaint(
                        0, 0, SystemColor.controlLtHighlight,
                        w23, h23, SystemColor.controlShadow
                        )
                        );
                g2.fill(_pathArrow);

                g2.setColor(SystemColor.controlDkShadow);
                g2.draw(new Line2D.Float(w, 0, w12, h - 1));
                g2.setColor(SystemColor.controlShadow);
                g2.draw(new Line2D.Float(w12, h - 1, 0, 0));
                g2.setColor(SystemColor.controlLtHighlight);
                g2.draw(new Line2D.Float(0, 0, w, 0));
                break;
            case ARROW_LEFT:
                _pathArrow.moveTo(w - 1, h13);
                _pathArrow.lineTo(w13, h13);
                _pathArrow.lineTo(w13, 0);
                _pathArrow.lineTo(0, h12);
                _pathArrow.lineTo(w13, h - 1);
                _pathArrow.lineTo(w13, h23);
                _pathArrow.lineTo(w - 1, h23);
                _pathArrow.closePath();
                g2.setPaint(new GradientPaint(
                        0, 0, Color.white,
                //SystemColor.controlLtHighlight,
                        0, h, SystemColor.controlShadow
                        )
                        );
                g2.fill(_pathArrow);

                _pathArrow.reset();
                _pathArrow.moveTo(w13, 0);
                _pathArrow.lineTo(w13, h13);
                _pathArrow.moveTo(w - 1, h13);
                _pathArrow.lineTo(w - 1, h23);
                _pathArrow.lineTo(w13, h23);
                _pathArrow.lineTo(w13, h - 1);
                g2.setColor(SystemColor.controlDkShadow);
                g2.draw(_pathArrow);

                g2.setColor(SystemColor.controlShadow);
                g2.draw(new Line2D.Float(0, h12, w13, h - 1));

                _pathArrow.reset();
                _pathArrow.moveTo(0, h12);
                _pathArrow.lineTo(w13, 0);
                _pathArrow.moveTo(w13, h13);
                _pathArrow.lineTo(w - 1, h13);
                g2.setColor(SystemColor.controlLtHighlight);
                g2.draw(_pathArrow);
                break;
            case ARROW_RIGHT:
            default:
            {
                _pathArrow.moveTo(0, h13);
                _pathArrow.lineTo(w23, h13);
                _pathArrow.lineTo(w23, 0);
                _pathArrow.lineTo(w - 1, h12);
                _pathArrow.lineTo(w23, h - 1);
                _pathArrow.lineTo(w23, h23);
                _pathArrow.lineTo(0, h23);
                _pathArrow.closePath();
                g2.setPaint(new GradientPaint(
                        0, 0, Color.white,
                //SystemColor.controlLtHighlight,
                        0, h, SystemColor.controlShadow
                        )
                        );
                g2.fill(_pathArrow);

                _pathArrow.reset();
                _pathArrow.moveTo(0, h23);
                _pathArrow.lineTo(w23, h23);
                _pathArrow.moveTo(w23, h - 1);
                _pathArrow.lineTo(w - 1, h12);
                g2.setColor(SystemColor.controlDkShadow);
                g2.draw(_pathArrow);

                g2.setColor(SystemColor.controlShadow);
                g2.draw(new Line2D.Float(w - 1, h12, w23, 0));

                _pathArrow.reset();
                _pathArrow.moveTo(w23, 0);
                _pathArrow.lineTo(w23, h13);
                _pathArrow.lineTo(0, h13);
                _pathArrow.lineTo(0, h23);
                _pathArrow.moveTo(w23, h23);
                _pathArrow.lineTo(w23, h - 1);
                g2.setColor(SystemColor.controlLtHighlight);
                g2.draw(_pathArrow);
                break;
            }
        }

    }

}



--- NEW FILE: CTransferableTreePath.java ---
/*****************************************************************************
 * Copyright (C) The Krysalis project. All rights reserved.                  *
 * ------------------------------------------------------------------------- *
 * This software is published under the terms of the Krysalis Software       *
 * License version 1.1_01, a copy of which has been included  with this      *
 * distribution in the LICENSE file.                                         *
 *****************************************************************************/
package  org.krysalis.swingx.tree;
import java.awt.datatransfer.*;
import javax.swing.tree.TreePath;

/**
 *  This represents a TreePath (a node in a JTree) that can be transferred
 *  between a drag source and a drop target.
 *
 *@author     Luca Jun Barozzi
 *@created    16 settembre 2001
 */
class CTransferableTreePath implements Transferable {
    // The type of DnD object being dragged...
    /**
     *  Description of the Field
     */
    public final static DataFlavor TREEPATH_FLAVOR = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType, "TreePath");

    private TreePath _path;

    private DataFlavor[] _flavors =
            {
            TREEPATH_FLAVOR
            };


    /**
     *  Constructs a transferrable tree path object for the specified path.
     *
     *@param  path  Description of Parameter
     */
    public CTransferableTreePath(TreePath path) {
        _path = path;
    }


    // Transferable interface methods...
    /**
     *  Gets the transferDataFlavors attribute of the CTransferableTreePath
     *  object
     *
     *@return    The transferDataFlavors value
     */
    public DataFlavor[] getTransferDataFlavors() {
        return _flavors;
    }


    /**
     *  Gets the dataFlavorSupported attribute of the CTransferableTreePath
     *  object
     *
     *@param  flavor  Description of Parameter
     *@return         The dataFlavorSupported value
     */
    public boolean isDataFlavorSupported(DataFlavor flavor) {
        return java.util.Arrays.asList(_flavors).contains(flavor);
    }


    /**
     *  Gets the transferData attribute of the CTransferableTreePath object
     *
     *@param  flavor                          Description of Parameter
     *@return                                 The transferData value
     *@exception  UnsupportedFlavorException  Description of Exception
     */
    public synchronized Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
        if (flavor.isMimeTypeEqual(TREEPATH_FLAVOR.getMimeType())) {
            // DataFlavor.javaJVMLocalObjectMimeType))
            return _path;
        } else {
            throw new UnsupportedFlavorException(flavor);
        }
    }

}


--- NEW FILE: CTree.java ---
/*****************************************************************************
 * Copyright (C) The Krysalis project. All rights reserved.                  *
 * ------------------------------------------------------------------------- *
 * This software is published under the terms of the Krysalis Software       *
 * License version 1.1_01, a copy of which has been included  with this      *
 * distribution in the LICENSE file.                                         *
 *****************************************************************************/
package  org.krysalis.swingx.tree;
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.SystemColor;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.Autoscroll;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

/**
 *  Demonstrates how to display a 'drag image' when using drag and drop on those
 *  platforms whose JVMs do not support it natively (eg Win32).
 *
 *@author     Luca Jun Barozzi
 *@created    16 settembre 2001
 */
public class CTree extends JTree implements DragSourceListener,
        DragGestureListener,
        Autoscroll,
        TreeModelListener {


// Autoscroll Interface...
// The following code was borrowed from the book:
//		Java Swing
//		By Robert Eckstein, Marc Loy & Dave Wood
//		Paperback - 1221 pages 1 Ed edition (September 1998)
//		O'Reilly & Associates; ISBN: 156592455X
//
// The relevant chapter of which can be found at:
//		http://www.oreilly.com/catalog/jswing/chapter/dnd.beta.pdf

    private final static int AUTOSCROLL_MARGIN = 12;
// Constants...


// Fields...
    private TreePath _pathSource;
    // The path being dragged
    private BufferedImage _imgGhost;
    // The 'drag image'
    private Point _ptOffset = new Point();

    // Where, in the drag image, the mouse was clicked


// Constructors...
    /**
     *  Constructor for the CTree object
     */
    public CTree() {
        // Use the default JTree constructor so that we get a sample TreeModel built for us

        putClientProperty("JTree.lineStyle", "Angled");
        // I like this look

        // Make this JTree a drag source
        DragSource dragSource = DragSource.getDefaultDragSource();
        dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, this);

        // Also, make this JTree a drag target
        DropTarget dropTarget = new DropTarget(this, new CDropTargetListener());
        dropTarget.setDefaultActions(DnDConstants.ACTION_COPY_OR_MOVE);

    }


// Test harness...
    /**
     *  Description of the Method
     *
     *@param  argv  Description of Parameter
     */
    public static void main(String argv[]) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
        }

        CTree tree = new CTree();
        tree.setPreferredSize(new Dimension(300, 300));
        JScrollPane scrollPane = new JScrollPane(tree);

        JFrame frame = new JFrame("Drag Images");
        frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
        frame.pack();

        Dimension dimScreen = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension dimFrame = frame.getSize();
        frame.setLocation((dimScreen.width - dimFrame.width) / 2,
                (dimScreen.height - dimFrame.height) / 2);

        frame.addWindowListener
                (
            new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            }
                );

        frame.show();

    }


    // Calculate the insets for the *JTREE*, not the viewport

    // the tree is in. This makes it a bit messy.
    /**
     *  Gets the autoscrollInsets attribute of the CTree object
     *
     *@return    The autoscrollInsets value
     */
    public Insets getAutoscrollInsets() {
        Rectangle raOuter = getBounds();
        Rectangle raInner = getParent().getBounds();
        return new Insets(
                raInner.y - raOuter.y + AUTOSCROLL_MARGIN, raInner.x - raOuter.x + AUTOSCROLL_MARGIN,
                raOuter.height - raInner.height - raInner.y + raOuter.y + AUTOSCROLL_MARGIN,
                raOuter.width - raInner.width - raInner.x + raOuter.x + AUTOSCROLL_MARGIN);
    }



// Interface: DragGestureListener
    /**
     *  Description of the Method
     *
     *@param  e  Description of Parameter
     */
    public void dragGestureRecognized(DragGestureEvent e) {

        Point ptDragOrigin = e.getDragOrigin();
        TreePath path = getPathForLocation(ptDragOrigin.x, ptDragOrigin.y);
        if (path == null) {
            return;
        }
        if (isRootPath(path)) {
            return;
        }
        // Ignore user trying to drag the root node


        // Work out the offset of the drag point from the TreePath bounding rectangle origin
        Rectangle raPath = getPathBounds(path);
        _ptOffset.setLocation(ptDragOrigin.x - raPath.x, ptDragOrigin.y - raPath.y);

        // Get the cell renderer (which is a JLabel) for the path being dragged
        JLabel lbl = (JLabel) getCellRenderer().getTreeCellRendererComponent
                (
                this,
        // tree
                path.getLastPathComponent(),
        // value
                false,
        // isSelected	(dont want a colored background)
                isExpanded(path),
        // isExpanded
                getModel().isLeaf(path.getLastPathComponent()),
        // isLeaf
                0,
        // row			(not important for rendering)
                false
        // hasFocus		(dont want a focus rectangle)
                );
        lbl.setSize((int) raPath.getWidth(), (int) raPath.getHeight());
        // <-- The layout manager would normally do this

        // Get a buffered image of the selection for dragging a ghost image
        _imgGhost = new BufferedImage((int) raPath.getWidth(), (int) raPath.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE);
        Graphics2D g2 = _imgGhost.createGraphics();

        // Ask the cell renderer to paint itself into the BufferedImage
        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, 0.5f));
        // Make the image ghostlike
        lbl.paint(g2);

        // Now paint a gradient UNDER the ghosted JLabel text (but not under the icon if any)
        // Note: this will need tweaking if your icon is not positioned to the left of the text
        Icon icon = lbl.getIcon();
        int nStartOfText = (icon == null) ? 0 : icon.getIconWidth() + lbl.getIconTextGap();
        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OVER, 0.5f));
        // Make the gradient ghostlike
        g2.setPaint(new GradientPaint(nStartOfText, 0, SystemColor.controlShadow,
                getWidth(), 0, new Color(255, 255, 255, 0)));
        g2.fillRect(nStartOfText, 0, getWidth(), _imgGhost.getHeight());

        g2.dispose();

        setSelectionPath(path);
        // Select this path in the tree

        System.out.println("DRAGGING: " + path.getLastPathComponent());

        // Wrap the path being transferred into a Transferable object
        Transferable transferable = new CTransferableTreePath(path);

        // Remember the path being dragged (because if it is being moved, we will have to delete it later)
        _pathSource = path;

        // We pass our drag image just in case it IS supported by the platform
        e.startDrag(null, _imgGhost, new Point(5, 5), transferable, this);
    }




// Interface: DragSourceListener
    /**
     *  Description of the Method
     *
     *@param  e  Description of Parameter
     */
    public void dragEnter(DragSourceDragEvent e) { }


    /**
     *  Description of the Method
     *
     *@param  e  Description of Parameter
     */
    public void dragOver(DragSourceDragEvent e) { }


    /**
     *  Description of the Method
     *
     *@param  e  Description of Parameter
     */
    public void dragExit(DragSourceEvent e) { }


    /**
     *  Description of the Method
     *
     *@param  e  Description of Parameter
     */
    public void dropActionChanged(DragSourceDragEvent e) { }


    /**
     *  Description of the Method
     *
     *@param  e  Description of Parameter
     */
    public void dragDropEnd(DragSourceDropEvent e) {
        if (e.getDropSuccess()) {
            int nAction = e.getDropAction();
            if (nAction == DnDConstants.ACTION_MOVE) {
                // The dragged item (_pathSource) has been inserted at the target selected by the user.
                // Now it is time to delete it from its original location.
                System.out.println("REMOVING: " + _pathSource.getLastPathComponent());

                // .
                // .. ask your TreeModel to delete the node
                // .

                _pathSource = null;
            }
        }
    }


    // Ok, we’ve been told to scroll because the mouse cursor is in our

    // scroll zone.
    /**
     *  Description of the Method
     *
     *@param  pt  Description of Parameter
     */
    public void autoscroll(Point pt) {
        // Figure out which row we’re on.
        int nRow = getRowForLocation(pt.x, pt.y);

        // If we are not on a row then ignore this autoscroll request
        if (nRow < 0) {
            return;
        }

        Rectangle raOuter = getBounds();
        // Now decide if the row is at the top of the screen or at the
        // bottom. We do this to make the previous row (or the next
        // row) visible as appropriate. If we’re at the absolute top or
        // bottom, just return the first or last row respectively.

        nRow = (pt.y + raOuter.y <= AUTOSCROLL_MARGIN)
        // Is row at top of screen?
                 ?
                (nRow <= 0 ? 0 : nRow - 1)
        // Yes, scroll up one row
                 :
                (nRow < getRowCount() - 1 ? nRow + 1 : nRow);
        // No, scroll down one row

        scrollRowToVisible(nRow);
    }


    /*
     *  / Use this method if you want to see the boundaries of the
     *  / autoscroll active region. Toss it out, otherwise.
     *  public void paintComponent(Graphics g)
     *  {
     *  super.paintComponent(g);
     *  Rectangle raOuter = getBounds();
     *  Rectangle raInner = getParent().getBounds();
     *  g.setColor(Color.red);
     *  g.drawRect(-raOuter.x + 12, -raOuter.y + 12,
     *  raInner.width - 24, raInner.height - 24);
     *  }
     */

// TreeModelListener interface...
    /**
     *  Description of the Method
     *
     *@param  e  Description of Parameter
     */
    public void treeNodesChanged(TreeModelEvent e) {
        System.out.println("treeNodesChanged");
        sayWhat(e);
        // We dont need to reset the selection path, since it has not moved
    }


    /**
     *  Description of the Method
     *
     *@param  e  Description of Parameter
     */
    public void treeNodesInserted(TreeModelEvent e) {
        System.out.println("treeNodesInserted ");
        sayWhat(e);

        // We need to reset the selection path to the node just inserted
        int nChildIndex = e.getChildIndices()[0];
        TreePath pathParent = e.getTreePath();
        setSelectionPath(getChildPath(pathParent, nChildIndex));
    }


    /**
     *  Description of the Method
     *
     *@param  e  Description of Parameter
     */
    public void treeNodesRemoved(TreeModelEvent e) {
        System.out.println("treeNodesRemoved ");
        sayWhat(e);
    }


    /**
     *  Description of the Method
     *
     *@param  e  Description of Parameter
     */
    public void treeStructureChanged(TreeModelEvent e) {
        System.out.println("treeStructureChanged ");
        sayWhat(e);
    }





// More helpers...
    /**
     *  Gets the childPath attribute of the CTree object
     *
     *@param  pathParent   Description of Parameter
     *@param  nChildIndex  Description of Parameter
     *@return              The childPath value
     */
    private TreePath getChildPath(TreePath pathParent, int nChildIndex) {
        TreeModel model = getModel();
        return pathParent.pathByAddingChild(model.getChild(pathParent.getLastPathComponent(), nChildIndex));
    }


    /**
     *  Gets the rootPath attribute of the CTree object
     *
     *@param  path  Description of Parameter
     *@return       The rootPath value
     */
    private boolean isRootPath(TreePath path) {
        return isRootVisible() && getRowForPath(path) == 0;
    }



    /**
     *  Description of the Method
     *
     *@param  e  Description of Parameter
     */
    private void sayWhat(TreeModelEvent e) {
        System.out.println(e.getTreePath().getLastPathComponent());
        int[] nIndex = e.getChildIndices();
        for (int i = 0; i < nIndex.length; i++) {
            System.out.println(i + ". " + nIndex[i]);
        }
    }





// DropTargetListener interface object...
    /**
     *  Description of the Class
     *
     *@author     Luca Jun Barozzi
     *@created    16 settembre 2001
     */
    class CDropTargetListener implements DropTargetListener {
        // Fields...
        private TreePath _pathLast = null;
        private Rectangle2D _raCueLine = new Rectangle2D.Float();
        private Rectangle2D _raGhost = new Rectangle2D.Float();
        private Color _colorCueLine;
        private Point _ptLast = new Point();
        private Timer _timerHover;
        private int _nLeftRight = 0;
        // Cumulative left/right mouse movement
        private BufferedImage _imgRight = new CArrowImage(15, 15, CArrowImage.ARROW_RIGHT);
        private BufferedImage _imgLeft = new CArrowImage(15, 15, CArrowImage.ARROW_LEFT);
        private int _nShift = 0;


        // Constructor...
        /**
         *  Constructor for the CDropTargetListener object
         */
        public CDropTargetListener() {
            _colorCueLine = new Color(
                    SystemColor.controlShadow.getRed(),
                    SystemColor.controlShadow.getGreen(),
                    SystemColor.controlShadow.getBlue(),
                    64
                    );

            // Set up a hover timer, so that a node will be automatically expanded or collapsed
            // if the user lingers on it for more than a short time
            _timerHover = new Timer(1000,
                new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        _nLeftRight = 0;
                        // Reset left/right movement trend
                        if (isRootPath(_pathLast)) {
                            return;
                        }
                        // Do nothing if we are hovering over the root node
                        if (isExpanded(_pathLast)) {
                            collapsePath(_pathLast);
                        } else {
                            expandPath(_pathLast);
                        }
                    }
                });
            _timerHover.setRepeats(false);
            // Set timer to one-shot mode
        }



        // Helpers...
        /**
         *  Gets the dragAcceptable attribute of the CDropTargetListener object
         *
         *@param  e  Description of Parameter
         *@return    The dragAcceptable value
         */
        public boolean isDragAcceptable(DropTargetDragEvent e) {
            // Only accept COPY or MOVE gestures (ie LINK is not supported)
            if ((e.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
                return false;
            }

            // Only accept this particular flavor
            if (!e.isDataFlavorSupported(CTransferableTreePath.TREEPATH_FLAVOR)) {
                return false;
            }

            /*
             *  / Do this if you want to prohibit dropping onto the drag source...
             *  Point pt = e.getLocation();
             *  TreePath path = getClosestPathForLocation(pt.x, pt.y);
             *  if (path.equals(_pathSource))
             *  return false;
             */
            /*
             *  / Do this if you want to select the best flavor on offer...
             *  DataFlavor[] flavors = e.getCurrentDataFlavors();
             *  for (int i = 0; i < flavors.length; i++ )
             *  {
             *  DataFlavor flavor = flavors[i];
             *  if (flavor.isMimeTypeEqual(DataFlavor.javaJVMLocalObjectMimeType))
             *  return true;
             *  }
             */
            return true;
        }


        /**
         *  Gets the dropAcceptable attribute of the CDropTargetListener object
         *
         *@param  e  Description of Parameter
         *@return    The dropAcceptable value
         */
        public boolean isDropAcceptable(DropTargetDropEvent e) {
            // Only accept COPY or MOVE gestures (ie LINK is not supported)
            if ((e.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
                return false;
            }

            // Only accept this particular flavor
            if (!e.isDataFlavorSupported(CTransferableTreePath.TREEPATH_FLAVOR)) {
                return false;
            }

            /*
             *  / Do this if you want to prohibit dropping onto the drag source...
             *  Point pt = e.getLocation();
             *  TreePath path = getClosestPathForLocation(pt.x, pt.y);
             *  if (path.equals(_pathSource))
             *  return false;
             */
            /*
             *  / Do this if you want to select the best flavor on offer...
             *  DataFlavor[] flavors = e.getCurrentDataFlavors();
             *  for (int i = 0; i < flavors.length; i++ )
             *  {
             *  DataFlavor flavor = flavors[i];
             *  if (flavor.isMimeTypeEqual(DataFlavor.javaJVMLocalObjectMimeType))
             *  return true;
             *  }
             */
            return true;
        }


        // DropTargetListener interface
        /**
         *  Description of the Method
         *
         *@param  e  Description of Parameter
         */
        public void dragEnter(DropTargetDragEvent e) {
            if (!isDragAcceptable(e)) {
                e.rejectDrag();
            } else {
                e.acceptDrag(e.getDropAction());
            }
        }


        /**
         *  Description of the Method
         *
         *@param  e  Description of Parameter
         */
        public void dragExit(DropTargetEvent e) {
            if (!DragSource.isDragImageSupported()) {
                repaint(_raGhost.getBounds());
            }
        }


        /**
         *  This is where the ghost image is drawn
         *
         *@param  e  Description of Parameter
         */
        public void dragOver(DropTargetDragEvent e) {
            // Even if the mouse is not moving, this method is still invoked 10 times per second
            Point pt = e.getLocation();
            if (pt.equals(_ptLast)) {
                return;
            }

            // Try to determine whether the user is flicking the cursor right or left
            int nDeltaLeftRight = pt.x - _ptLast.x;
            if ((_nLeftRight > 0 && nDeltaLeftRight < 0) || (_nLeftRight < 0 && nDeltaLeftRight > 0)) {
                _nLeftRight = 0;
            }
            _nLeftRight += nDeltaLeftRight;

            _ptLast = pt;

            Graphics2D g2 = (Graphics2D) getGraphics();

            // If a drag image is not supported by the platform, then draw my own drag image
            if (!DragSource.isDragImageSupported()) {
                paintImmediately(_raGhost.getBounds());
                // Rub out the last ghost image and cue line
                // And remember where we are about to draw the new ghost image
                _raGhost.setRect(pt.x - _ptOffset.x, pt.y - _ptOffset.y, _imgGhost.getWidth(), _imgGhost.getHeight());
                g2.drawImage(_imgGhost, AffineTransform.getTranslateInstance(_raGhost.getX(), _raGhost.getY()), null);
            } else {
                // Just rub out the last cue line
                paintImmediately(_raCueLine.getBounds());
            }

            TreePath path = getClosestPathForLocation(pt.x, pt.y);
            if (!(path == _pathLast)) {
                _nLeftRight = 0;
                // We've moved up or down, so reset left/right movement trend
                _pathLast = path;
                _timerHover.restart();
            }

            // In any case draw (over the ghost image if necessary) a cue line indicating where a drop will occur
            Rectangle raPath = getPathBounds(path);
            _raCueLine.setRect(0, raPath.y + (int) raPath.getHeight(), getWidth(), 2);

            g2.setColor(_colorCueLine);
            g2.fill(_raCueLine);

            // Now superimpose the left/right movement indicator if necessary
            if (_nLeftRight > 20) {
                g2.drawImage(_imgRight, AffineTransform.getTranslateInstance(pt.x - _ptOffset.x, pt.y - _ptOffset.y), null);
                _nShift = +1;
            } else if (_nLeftRight < -20) {
                g2.drawImage(_imgLeft, AffineTransform.getTranslateInstance(pt.x - _ptOffset.x, pt.y - _ptOffset.y), null);
                _nShift = -1;
            } else {
                _nShift = 0;
            }

            // And include the cue line in the area to be rubbed out next time
            _raGhost = _raGhost.createUnion(_raCueLine);

            /*
             *  / Do this if you want to prohibit dropping onto the drag source
             *  if (path.equals(_pathSource))
             *  e.rejectDrag();
             *  else
             *  e.acceptDrag(e.getDropAction());
             */
        }


        /**
         *  Description of the Method
         *
         *@param  e  Description of Parameter
         */
        public void dropActionChanged(DropTargetDragEvent e) {
            if (!isDragAcceptable(e)) {
                e.rejectDrag();
            } else {
                e.acceptDrag(e.getDropAction());
            }
        }


        /**
         *  Description of the Method
         *
         *@param  e  Description of Parameter
         */
        public void drop(DropTargetDropEvent e) {
            _timerHover.stop();
            // Prevent hover timer from doing an unwanted expandPath or collapsePath

            if (!isDropAcceptable(e)) {
                e.rejectDrop();
                return;
            }

            e.acceptDrop(e.getDropAction());

            Transferable transferable = e.getTransferable();

            DataFlavor[] flavors = transferable.getTransferDataFlavors();
            for (int i = 0; i < flavors.length; i++) {
                DataFlavor flavor = flavors[i];
                if (flavor.isMimeTypeEqual(DataFlavor.javaJVMLocalObjectMimeType)) {
                    try {
                        Point pt = e.getLocation();
                        TreePath pathTarget = getClosestPathForLocation(pt.x, pt.y);
                        TreePath pathSource = (TreePath) transferable.getTransferData(flavor);

                        System.out.println("DROPPING: " + pathSource.getLastPathComponent());
                        TreeModel model = getModel();
                        TreePath pathNewChild = null;

                        // .
                        // .. Add your code here to ask your TreeModel to copy the node and act on the mouse gestures...
                        // .

                        // For example:

                        // If pathTarget is an expanded BRANCH,
                        // 		then insert source UNDER it (before the first child if any)
                        // If pathTarget is a collapsed BRANCH (or a LEAF),
                        //		then insert source AFTER it
                        // 		Note: a leaf node is always marked as collapsed
                        // You ask the model to do the copying...
                        // ...and you supply the copyNode method in the model as well of course.
//						if (_nShift == 0)
//							pathNewChild = model.copyNode(pathSource, pathTarget, isExpanded(pathTarget));
//						else if (_nShift > 0)	// The mouse is being flicked to the right (so move the node right)
//							pathNewChild = model.copyNodeRight(pathSource, pathTarget);
//						else					// The mouse is being flicked to the left (so move the node left)
//							pathNewChild = model.copyNodeLeft(pathSource);

                        if (pathNewChild != null) {
                            setSelectionPath(pathNewChild);
                        }
                        // Mark this as the selected path in the tree
                        break;
                        // No need to check remaining flavors
                    } catch (UnsupportedFlavorException ufe) {
                        System.out.println(ufe);
                        e.dropComplete(false);
                        return;
                    } catch (IOException ioe) {
                        System.out.println(ioe);
                        e.dropComplete(false);
                        return;
                    }
                }
            }

            e.dropComplete(true);
        }

    }

}





-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.