|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun * Microsystems, Inc. All Rights Reserved. */ package org.openide.explorer.view; import java.awt.Component; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.Line2D; import java.awt.datatransfer.Transferable; import java.awt.dnd.*; import java.awt.geom.Line2D.Double; import java.util.Arrays; import java.util.Comparator; import java.util.TreeSet; import javax.swing.JTree; import javax.swing.SwingUtilities; import javax.swing.Timer; import javax.swing.tree.TreeCellEditor; import javax.swing.tree.TreePath; import org.openide.ErrorManager; import org.openide.nodes.Children; import org.openide.nodes.Index; import org.openide.nodes.Node; import org.openide.util.datatransfer.PasteType; /** Implementation of drop support for asociated Tree View. * * @author Dafe Simonek, Jiri Rechtacek */ final class TreeViewDropSupport implements DropTargetListener, Runnable { // Attributes /** true if support is active, false otherwise */ boolean active = false; boolean dropTargetPopupAllowed; /** Drop target asociated with the tree */ DropTarget dropTarget; /** Node area which we were during * DnD operation. */ Rectangle lastNodeArea; private int upperNodeIdx = -1; private int lowerNodeIdx = -1; /** Swing Timer for expand node's parent with delay time. */ Timer timer; /** Glass pane for JTree which is associate with this class. */ DropGlassPane dropPane; final static protected int FUSSY_POINTING = 3; final static private int DELAY_TIME_FOR_EXPAND = 1000; final static private int SHIFT_DOWN = -1; final static private int SHIFT_RIGHT = 10; final static private int SHIFT_LEFT = 15; private int pointAt = DragDropUtilities.NODE_CENTRAL; // Associations /** View manager. */ protected TreeView view; /** The component we are supporting with drop support */ protected JTree tree; // Operations /** Creates new TreeViewDropSupport */ public TreeViewDropSupport (TreeView view, JTree tree, boolean dropTargetPopupAllowed) { this.view = view; this.tree = tree; this.dropTargetPopupAllowed = dropTargetPopupAllowed; } public void setDropTargetPopupAllowed(boolean value) { dropTargetPopupAllowed=value; } public boolean isDropTargetPopupAllowed() { return dropTargetPopupAllowed; } /** User is starting to drag over us */ public void dragEnter (DropTargetDragEvent dtde) { checkStoredGlassPane (); // set a status and cursor of dnd action doDragOver (dtde); } /** User drags over us */ public void dragOver (DropTargetDragEvent dtde) { // bugfix #34483; jdk1.4.1 on w2k could calls dragOver() before dragEnter() // (jkdbug fixed in 1.4.2) // this check make dragOver/Enter more robust checkStoredGlassPane (); // set a status and cursor of dnd action doDragOver (dtde); } private void checkStoredGlassPane () { // remember current glass pane to set back at end of dragging over this compoment if (!DropGlassPane.isOriginalPaneStored ()) { Component comp = tree.getRootPane ().getGlassPane (); DropGlassPane.setOriginalPane (tree, comp, comp.isVisible ()); // set glass pane for paint selection line dropPane = DropGlassPane.getDefault (tree); tree.getRootPane ().setGlassPane (dropPane); dropPane.revalidate(); dropPane.setVisible (true); } } /** Process events dragEnter or dragOver. */ private void doDragOver (DropTargetDragEvent dtde) { // 1. test if I'm over any node TreePath tp = getTreePath(dtde); if (tp == null) { dtde.rejectDrag(); removeDropLine (); return ; } // 2. find node for drop Point p = dtde.getLocation (); Node dropNode = getNodeForDrop (p); // if I haven't any node for drop then reject drop if (dropNode==null) { dtde.rejectDrag (); removeDropLine (); return ; } Rectangle nodeArea = tree.getPathBounds (tp); int endPointX = nodeArea.x + nodeArea.width; int row = tree.getRowForPath (tp); if (nodeArea!=null) { pointAt = DragDropUtilities.NODE_CENTRAL; if (p.y <= nodeArea.y+FUSSY_POINTING) { // don't get line above root if (row != 0) { // point above node pointAt = DragDropUtilities.NODE_UP; TreePath upPath = tree.getPathForRow (row-1); if (upPath!=null && !upPath.equals (tp)) { endPointX = Math.max (nodeArea.x + nodeArea.width, tree.getPathBounds (upPath).x + tree.getPathBounds (upPath).width); } // drop candidate is parent if (dropNode.getParentNode ()!=null) { dropNode = dropNode.getParentNode (); tp = null; } } } else if (p.y >= (nodeArea.y+nodeArea.height-FUSSY_POINTING)) { // exclude expanded folder if (!view.isExpanded (dropNode)) { // point bellow node pointAt = DragDropUtilities.NODE_DOWN; TreePath downPath = tree.getPathForRow (row+1); if (downPath!=null && !downPath.equals (tp)) { endPointX = Math.max (nodeArea.x + nodeArea.width, tree.getPathBounds (downPath).x + tree.getPathBounds (downPath).width); } // drop candidate is parent if (dropNode.getParentNode ()!=null) { dropNode = dropNode.getParentNode (); tp = null; } } } } endPointX = endPointX + SHIFT_RIGHT; // 2.b. check index cookie Index indexCookie = (Index)dropNode.getCookie (Index.class); if (indexCookie!=null) { if (pointAt==DragDropUtilities.NODE_UP) { lowerNodeIdx = indexCookie.indexOf (getNodeForDrop (p)); upperNodeIdx = lowerNodeIdx - 1; } else if (pointAt==DragDropUtilities.NODE_DOWN) { upperNodeIdx = indexCookie.indexOf (getNodeForDrop (p)); lowerNodeIdx = upperNodeIdx + 1; } } // 3. expand with a delay if ((timer==null || !timer.isRunning ()) && dropNode!=null && !dropNode.isLeaf() && !view.isExpanded (dropNode)) { // ok, let's expand in a while // node is candidate for expand final Node cn = dropNode; // remove old timer removeTimer (); // create new timer timer = new Timer (DELAY_TIME_FOR_EXPAND, new ActionListener () { final public void actionPerformed (ActionEvent e) { view.expandNode (cn); } }); timer.setRepeats (false); timer.start (); } // 4. present node for drop // prepare selection or line if (pointAt==DragDropUtilities.NODE_CENTRAL) { // no line dropPane.setDropLine (null); } else { // line and selection of parent if any if (pointAt==DragDropUtilities.NODE_UP) { Line2D line = new Double (nodeArea.x-SHIFT_LEFT, nodeArea.y+SHIFT_DOWN, endPointX, nodeArea.y+SHIFT_DOWN); convertBoundsAndSetDropLine (line); // enlagre node area with area for line Rectangle lineArea = new Rectangle (nodeArea.x-SHIFT_LEFT, nodeArea.y+SHIFT_DOWN-3, endPointX-nodeArea.x+SHIFT_LEFT, 5); nodeArea = (Rectangle)nodeArea.createUnion (lineArea); } else { Line2D line = new Double (nodeArea.x-SHIFT_LEFT, nodeArea.y+nodeArea.height+SHIFT_DOWN, endPointX, nodeArea.y+nodeArea.height+SHIFT_DOWN); convertBoundsAndSetDropLine (line); // enlagre node area with area for line Rectangle lineArea = new Rectangle (nodeArea.x-SHIFT_LEFT, nodeArea.y+nodeArea.height, endPointX-nodeArea.x+SHIFT_LEFT, SHIFT_DOWN+3); nodeArea = (Rectangle)nodeArea.createUnion (lineArea); //System.out.println("OLD + LINE: "+lineArea+" = AREA: "+nodeArea); } // the parent node won't be selected /*// select parent and enlarge paint area if (tp.getParentPath ()!=null) { tp = tp.getParentPath (); } nodeArea = (Rectangle)nodeArea.createUnion (tree.getPathBounds (tp));*/ } // back normal view w/o any selecetion nor line if ((lastNodeArea != null) && (!lastNodeArea.equals (nodeArea))) { NodeRenderer.dragExit (); repaint (lastNodeArea); } // paint new state if (!nodeArea.equals (lastNodeArea)) { if (tp!=null) NodeRenderer.dragEnter (tp.getLastPathComponent ()); repaint (nodeArea); lastNodeArea = nodeArea; removeTimer (); } // 5 show to cursor belong to state if (canDrop (dropNode, dtde.getDropAction ())) { // ok, can accept dtde.acceptDrag (dtde.getDropAction ()); } else { // can only reorder? if (canReorder (dropNode, ExplorerDnDManager.getDefault ().getDraggedNodes ())) { // ok, can accept only reoder dtde.acceptDrag (dtde.getDropAction ()); } else { dtde.rejectDrag (); } } } /** Repaints TreeView, the given rectangle is enlarged for 5 pixels * because some parts was not repainted correctly. * @param Rectangle r rectangle which will be repainted.*/ private void repaint (Rectangle r) { tree.repaint (r.x-5, r.y-5, r.width+10, r.height+10); } /** Converts line's bounds by the bounds of the root pane. Drop glass pane * is over this root pane. After covert a given line is set to drop glass pane. * @param line line for show in drop glass pane */ private void convertBoundsAndSetDropLine (final Line2D line) { int x1 = (int)line.getX1 (), x2 = (int)line.getX2 (); int y1 = (int)line.getY1 (), y2 = (int)line.getY2 (); Point p1 = SwingUtilities.convertPoint (tree, x1, y1, tree.getRootPane ()); Point p2 = SwingUtilities.convertPoint (tree, x2, y2, tree.getRootPane ()); line.setLine (p1, p2); dropPane.setDropLine (line); } /** Removes timer and all listeners. */ private void removeTimer () { if (timer!=null) { ActionListener[] l = (ActionListener[])timer.getListeners (ActionListener.class); for (int i=0; i |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.