diff --git a/src/antidote/org/apache/tools/ant/gui/modules/edit/DragTree.java b/src/antidote/org/apache/tools/ant/gui/modules/edit/DragTree.java
new file mode 100644
index 000000000..0e5e02759
--- /dev/null
+++ b/src/antidote/org/apache/tools/ant/gui/modules/edit/DragTree.java
@@ -0,0 +1,606 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999, 2000 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * DragTreeListener
+ * associated with this DragTree
.
+ */
+ private DragTreeListener _dragTreeListener;
+
+ /**
+ * Holds the position where the dropped item should be
+ * placed. Possible values are DROP_BEFORE, DROP_ON
+ * or DROP_AFTER.
+ */
+ private int _dropPosition;
+
+ /**
+ * The point where the drop line should be drawn.
+ */
+ private Point _point;
+
+ /**
+ * The object the drop occured on.
+ */
+ private Object _dropOn;
+
+ /**
+ * The path of where the drop occured.
+ */
+ private TreePath _dropOnPath;
+
+ /**
+ * The path of the item being dropped.
+ */
+ private TreePath _droppedPath;
+
+ /**
+ * The item being dragged should be placed before (or above)
+ * the item it is dropped on.
+ */
+ final static protected int DROP_BEFORE = 0;
+
+ /**
+ * The item being dragged should be placed on (as a child)
+ * the item it is dropped on.
+ */
+ final static protected int DROP_ON = 1;
+
+ /**
+ * The item being dragged should be placed on (or after)
+ * the item it is dropped on.
+ */
+ final static protected int DROP_AFTER = 2;
+
+ /**
+ * Default Constuctor
+ */
+ public DragTree() {
+
+ DragSource dragSource = DragSource.getDefaultDragSource();
+
+ // Use the default gesture recognizer
+ dragSource.createDefaultDragGestureRecognizer(
+ this,
+ DnDConstants.ACTION_COPY_OR_MOVE,
+ this);
+
+ // Setup to be a drop target
+ new DropTarget(this,
+ DnDConstants.ACTION_COPY_OR_MOVE,
+ this);
+ }
+
+ /**
+ * Starts the drag operation.
+ *
+ * @param e the DragGestureEvent
describing
+ * the gesture that has just occurred
+ */
+ public void dragGestureRecognized(DragGestureEvent e) {
+
+ // Find the path for the cursor position.
+ Point p = e.getDragOrigin();
+ _droppedPath = getPathForLocation(p.x, p.y);
+
+ if (_droppedPath == null) {
+ return;
+ }
+
+ // Select the item.
+ setSelectionPath(_droppedPath);
+
+ // Wrap the object and start the drag.
+ Object obj = _droppedPath.getLastPathComponent();
+ Wrapper wrapper = new Wrapper(obj);
+ e.startDrag(DragSource.DefaultMoveNoDrop, wrapper, this);
+ }
+
+ //
+ // DragSourceListener methods
+ //
+ public void dragDropEnd(DragSourceDropEvent e) {}
+ public void dragEnter(DragSourceDragEvent e) {}
+ public void dragExit(DragSourceEvent e) {}
+ public void dragOver(DragSourceDragEvent e) {}
+ public void dropActionChanged(DragSourceDragEvent e) {}
+
+ //
+ // DropTargetListener methods
+ //
+ public void dropActionChanged(java.awt.dnd.DropTargetDragEvent e) {}
+ public void dragEnter(DropTargetDragEvent e) {
+ dragOver(e);
+ }
+
+ /**
+ * Called when a drag operation is ongoing
+ * on the DropTarget
.
+ *
+ * @param dtde the DropTargetDragEvent
+ */
+ public void dragOver(DropTargetDragEvent e) {
+
+ checkAutoScroll(e.getLocation());
+
+ Point p = computeDropLocation(e.getLocation());
+
+ // Don't allow a parent to be dropped on one of its children.
+ if (_droppedPath.isDescendant(_dropOnPath)) {
+ _point = null;
+ _dropOn = null;
+ p = null;
+ e.rejectDrag();
+ } else {
+ e.acceptDrag(e.getDropAction());
+ }
+
+ // If the point has changed, repaint the display.
+ if (_point == null || !p.equals(_point)) {
+ _point = p;
+ repaint();
+ }
+ }
+
+ /**
+ * Determines where the item will be dropped.
+ */
+ private Point computeDropLocation(Point p) {
+
+ int rowCount = getRowCount();
+ int height = findCellHeight();
+ int row = (p.y / height);
+ int offset = (p.y % height);
+
+ // Move the point to the top of the cell.
+ p.y -= offset;
+
+ int delta = 0;
+
+ // Is the point at or past the end of the list?
+ if (row > (rowCount - 1) ) {
+ p.y = (rowCount - 1) * height;
+ row = rowCount - 1;
+ delta = height;
+ _dropPosition = DROP_AFTER;
+ }
+ // Is the point at the begining of the list?
+ else if (row <= 0) {
+ p.y = 0;
+ delta = height;
+ if (rowCount > 1) {
+ row = 1;
+ _dropPosition = DROP_BEFORE;
+ } else {
+ row = 0;
+ _dropPosition = DROP_ON;
+ }
+ }
+ // The point is in the middle of the tree.
+ else {
+ // Is the point on the top third of the cell?
+ if (offset < height * 0.333) {
+
+ // Set the line to the top of the cell.
+ delta = 0;
+ _dropPosition = DROP_BEFORE;
+ }
+ // Is the point on the bottom third of the cell?
+ else if (offset > height * 0.666){
+
+ // Set the line to the bottom of the cell.
+ delta = height;
+ _dropPosition = DROP_AFTER;
+ }
+ // The point is in the middle of the cell?
+ else {
+
+ // Set the line to the middle of the cell.
+ delta = height / 2;
+ _dropPosition = DROP_ON;
+ }
+ }
+
+ // Find the object to use for the drop.
+ _dropOnPath = getPathForRow(row);
+ if (_dropOnPath != null) {
+ _dropOn = _dropOnPath.getLastPathComponent();
+ } else {
+ _dropOn = null;
+ }
+
+ // Adjust the point used to draw the drop line.
+ p.y += delta;
+ p.x = 0;
+
+ return p;
+ }
+
+ /**
+ * Process the drop
+ *
+ * @param e the DropTargetDropEvent
+ * @see DropTargetListener.drop
+ */
+ public void drop(DropTargetDropEvent e) {
+
+ if (_dropOn == null || _dropOnPath == null) {
+ return;
+ }
+
+ // Get the object being transfered.
+ Object obj = null;
+ Transferable t = e.getTransferable();
+ try {
+ obj = t.getTransferData(_flavors[0]);
+ } catch (Exception exp) {
+ System.out.println(exp);
+ }
+
+ if (obj != null) {
+
+ Object droppedObj = obj;
+ Object droppedOnObj = _dropOn;
+ Object parentObj = getParentOfDroppedOnObject();
+
+ if (_dropPosition == DROP_ON) {
+
+ fireAppendChild(droppedOnObj, droppedObj);
+ setExpandedState(_dropOnPath, true);
+ }
+ else if (_dropPosition == DROP_BEFORE) {
+
+ fireInsertBefore(parentObj, droppedOnObj, droppedObj);
+ }
+ else if (_dropPosition == DROP_AFTER) {
+
+ // If the cell is exanded, add the new item before our
+ // first child.
+ if (isExpanded(getRowForPath(_dropOnPath))) {
+ parentObj = droppedOnObj;
+ }
+
+ // Find the next sibling
+ int index = getModel().getIndexOfChild(parentObj, droppedOnObj);
+ int count = getModel().getChildCount(parentObj);
+
+ if (index == count-1) {
+ fireAppendChild(parentObj, droppedObj);
+ } else {
+ Object sibling = getModel().getChild(parentObj, index+1);
+ fireInsertBefore(parentObj, sibling, droppedObj);
+ }
+ }
+
+ if (e.getDropAction() == DnDConstants.ACTION_MOVE) {
+ fireRemoveChild(droppedObj);
+ }
+
+ this.updateUI();
+ }
+ }
+
+ /**
+ * Returns the parent of the dropped on object.
+ */
+ private Object getParentOfDroppedOnObject() {
+ int count = _dropOnPath.getPathCount();
+ return _dropOnPath.getPathComponent(count-2);
+ }
+
+ /**
+ * Repaint the display to cleanup any lines.
+ */
+ public void dragExit(DropTargetEvent e) {
+ _point = null;
+ repaint();
+ }
+
+ /**
+ * Draws the line which shows where the dropped
+ * item will land.
+ *
+ * @see #JComponent.paintComponent
+ */
+ public void paintComponent(Graphics g){
+ super.paintComponent(g);
+
+ if (_point != null) {
+
+ if (_dropPosition == DROP_ON) {
+ // If the drop is on another item, draw
+ // two short lines.
+ g.drawLine(0, _point.y, 10, _point.y);
+ g.drawLine(getWidth()-10, _point.y, getWidth(), _point.y);
+ } else {
+ // If the drop is above or below an item, draw
+ // one long line.
+ g.drawLine(0, _point.y, getWidth(), _point.y);
+ }
+ }
+ }
+
+ /**
+ * Wrapper holds the object to transfer
+ */
+ protected class Wrapper implements Transferable {
+
+ /** The object to transfer */
+ private Object _obj;
+
+ /**
+ * Creates a wrapper for the input object.
+ *
+ * @param obj object to wrap
+ */
+ public Wrapper(Object obj) {
+ _obj = obj;
+ }
+
+ /**
+ * Return out object if the DataFlavor is correct.
+ *
+ * @param flavor only javaJVMLocalObjectMimeType is supported
+ */
+ public Object getTransferData(DataFlavor flavor)
+ throws UnsupportedFlavorException, IOException {
+ if (isDataFlavorSupported(flavor)) {
+ return _obj;
+ }
+ throw new UnsupportedFlavorException(flavor);
+ }
+
+ /**
+ * Return true if the input flavor is support.
+ *
+ * @param flavor DataFlavor to test
+ */
+ public boolean isDataFlavorSupported(DataFlavor flavor) {
+ return flavor.equals(_flavors[0]);
+ }
+
+ /**
+ * Return true if the input flavor is support.
+ *
+ * @param flavor DataFlavor to test
+ */
+ public DataFlavor[] getTransferDataFlavors() {
+ return _flavors;
+ }
+ }
+
+ /**
+ * DataFlavors which are support for transfer
+ */
+ private static final DataFlavor[] _flavors = {
+ createConstant(DataFlavor.javaJVMLocalObjectMimeType)
+ };
+
+ /**
+ * Returns a new DataFlavor or null
+ *
+ * @param flavor the flavor
+ */
+ static private DataFlavor createConstant(String flavor) {
+ try {
+ return new DataFlavor(flavor);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the cell height for the tree.
+ */
+ protected int findCellHeight() {
+ DefaultTreeCellRenderer renderer =
+ (DefaultTreeCellRenderer) getCellRenderer();
+ return renderer.getPreferredSize().height;
+ }
+
+ /**
+ * Register a new DragTreeListener
.
+ *
+ * @param dtl the DragTreeListener
to register
+ * with this DragTree
.
+ */
+ public synchronized void addDragTreeListener(DragTreeListener dtl) {
+ _dragTreeListener = dtl;
+ }
+
+ /**
+ * unregister the current DragTreeListener
+ *
+ * @param dtl the DragTreeListener
to unregister
+ *
+ * @throws IllegalArgumentException
if
+ * dtl is not (equal to) the currently registered
+ * DragTreeListener
.
+ */
+ public synchronized void removeDragTreeListener(DragTreeListener dtl) {
+ if (_dragTreeListener == null || !_dragTreeListener.equals(dtl))
+ throw new IllegalArgumentException();
+ else {
+ _dragTreeListener = null;
+ }
+ }
+
+ /**
+ * Notify the DragTreeListener that an appendChild
has
+ * been requested.
+ */
+ protected synchronized Object fireAppendChild(Object parent,
+ Object newChild) {
+
+ if (_dragTreeListener != null) {
+ return _dragTreeListener.appendChild(parent, newChild);
+ }
+ return null;
+ }
+
+ /**
+ * Notify the DragTreeListener that an insertBefore
has
+ * been requested.
+ */
+ protected synchronized Object fireInsertBefore(Object parent, Object index,
+ Object newChild) {
+
+ if (_dragTreeListener != null) {
+ return _dragTreeListener.insertBefore(parent, index, newChild);
+ }
+ return null;
+ }
+
+ /**
+ * Notify the DragTreeListener that an removeChild
has
+ * been requested.
+ */
+ protected synchronized void fireRemoveChild(Object child) {
+
+ if (_dragTreeListener != null) {
+ _dragTreeListener.removeChild(child);
+ }
+ }
+
+ /**
+ * Scrolls tree if nessasary
+ *
+ * @param p A Point
indicating the
+ * location of the cursor that triggered this operation.
+ */
+ protected void checkAutoScroll(Point p) {
+
+ Point locn = new Point(p);
+ javax.swing.SwingUtilities.convertPointToScreen(locn, this);
+ javax.swing.SwingUtilities.convertPointFromScreen(locn, getParent());
+
+ Rectangle outer = new Rectangle();
+ Rectangle inner = new Rectangle();
+
+ Insets i = new java.awt.Insets(10, 10, 10, 10);
+ Dimension size = getParent().getSize();
+
+ if (size.width != outer.width || size.height != outer.height)
+ outer.setBounds(0, 0, size.width, size.height);
+
+ if (inner.x != i.left || inner.y != i.top)
+ inner.setLocation(i.left, i.top);
+
+ int newWidth = size.width - (i.left + i.right);
+ int newHeight = size.height - (i.top + i.bottom);
+
+ if (newWidth != inner.width || newHeight != inner.height)
+ inner.setSize(newWidth, newHeight);
+
+ if (outer.contains(locn) && !inner.contains(locn)) {
+ if (locn.y >= inner.height) {
+ scrollDown();
+ } else {
+ scrollUp();
+ }
+ }
+ }
+
+ /**
+ * Scroll the tree up one cell
+ */
+ public void scrollUp() {
+ Rectangle visibleRect = getVisibleRect();
+ int height = findCellHeight();
+ visibleRect.y -= height;
+ visibleRect.height -= height;
+ scrollRectToVisible(visibleRect);
+ }
+
+ /**
+ * Scroll the tree down one cell
+ */
+ public void scrollDown() {
+ Rectangle visibleRect = getVisibleRect();
+ int height = findCellHeight();
+ visibleRect.y += height;
+ visibleRect.height += height;
+ scrollRectToVisible(visibleRect);
+ }
+}
diff --git a/src/antidote/org/apache/tools/ant/gui/modules/edit/DragTreeListener.java b/src/antidote/org/apache/tools/ant/gui/modules/edit/DragTreeListener.java
new file mode 100644
index 000000000..cd2271dbb
--- /dev/null
+++ b/src/antidote/org/apache/tools/ant/gui/modules/edit/DragTreeListener.java
@@ -0,0 +1,96 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999, 2000 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * DragTree
and is invoked
+ * when an object of that (sub)class detects the completion
+ * of a drag operation.
+ *
+ * @version $Revision$
+ * @author Nick Davisnick_home_account@yahoo.com
+ */
+public interface DragTreeListener extends EventListener {
+
+ /**
+ * Append the object to the end of the parent's child list.
+ *
+ * @param parent parent object
+ * @param newChild new child object
+ * @return the new object
+ */
+ public Object appendChild(Object parent, Object newChild);
+
+ /**
+ * Append the object to the end of the parent's child list.
+ *
+ * @param parent parent object
+ * @param index child object of parent the newChild should be added
+ * before.
+ * @param newChild new child object
+ * @return the new object
+ */
+ public Object insertBefore(Object parent, Object index, Object newChild);
+
+ /**
+ * Removes the child object from the parent.
+ *
+ * @param parent parent object
+ * @param child child object
+ */
+ public void removeChild(Object child);
+}