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, weve 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 were 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 were 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.