Package org.apache.tools.ant.gui.modules.edit

Source Code of org.apache.tools.ant.gui.modules.edit.DragTree$Wrapper

/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2003 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 "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
* <http://www.apache.org/>.
*/

package org.apache.tools.ant.gui.modules.edit;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
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.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.io.IOException;

import javax.swing.JTree;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreePath;

/**
* A tree which allows reorganization via drop and drag
*
* @version $Revision: 1.5 $
* @author Nick Davis<a href="mailto:nick_home_account@yahoo.com">nick_home_account@yahoo.com</a>
*/
public class DragTree extends JTree implements DragSourceListener,
    DragGestureListener, DropTargetListener {
       
    /**
     * The <code>DragTreeListener</code>
     * associated with this <code>DragTree</code>.
     */
    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.
     * <P>
     * @param e the <code>DragGestureEvent</code> 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 <code>DropTarget</code>.
     * <P>
     * @param e the <code>DropTargetDragEvent</code>
     */
    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 <code>DropTargetDropEvent</code>
     * @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.
         */
        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 <code>DragTreeListener</code>.
     * <P>
     * @param dtl the <code>DragTreeListener</code> to register
     * with this <code>DragTree</code>.
     */
    public synchronized void addDragTreeListener(DragTreeListener dtl) {
        _dragTreeListener = dtl;
    }

    /**
     * Unregister the current DragTreeListener.
     *
     * @param dtl the <code>DragTreeListener</code> to unregister
     * <P>
     * @throws IllegalArgumentException if
     * dtl is not (equal to) the currently registered
     * <code>DragTreeListener</code>.
     */
    public synchronized void removeDragTreeListener(DragTreeListener dtl) {
  if (_dragTreeListener == null || !_dragTreeListener.equals(dtl))
      throw new IllegalArgumentException();
  else {
      _dragTreeListener = null;
  }
    }

    /**
     * Notify the DragTreeListener that an <code>appendChild</code> 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 <code>insertBefore</code> 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 <code>removeChild</code> has
     * been requested.
     */
    protected synchronized void fireRemoveChild(Object child) {
               
  if (_dragTreeListener != null) {
      _dragTreeListener.removeChild(child);
  }
    }

    /**
     * The method checkAutoScroll scrolls the tree based upon the Point
     * of the cursor which triggered the scroll operation.
     * <P>
     * @param p A <code>Point</code> 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);
    }
}
TOP

Related Classes of org.apache.tools.ant.gui.modules.edit.DragTree$Wrapper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.