Added support for autoscrolling.

git-svn-id: https://samskivert.googlecode.com/svn/trunk@831 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
ray
2002-09-06 21:56:57 +00:00
parent 2bdb22349c
commit d5ec4bba40
2 changed files with 152 additions and 8 deletions
@@ -0,0 +1,21 @@
//
// $Id: AutoscrollingDropTarget.java,v 1.1 2002/09/06 21:56:57 ray Exp $
package com.samskivert.swing.dnd;
import java.awt.Dimension;
/**
* An extension of DropTarget that allows its associated component to be
* automatically scrolled during DnD operations. So easy!
*/
public interface AutoscrollingDropTarget extends DropTarget
{
/**
* Return a dimension that represents the horizontal and vertical
* 'sensitive' area around the component's bounds. When the mouse leaves
* the component and is inside the sensitive area, the component is
* autoscrolled.
*/
public Dimension getAutoscrollBorders ();
}
@@ -1,5 +1,5 @@
//
// $Id: DnDManager.java,v 1.10 2002/09/06 17:46:29 ray Exp $
// $Id: DnDManager.java,v 1.11 2002/09/06 21:56:57 ray Exp $
package com.samskivert.swing.dnd;
@@ -11,9 +11,12 @@ import java.awt.Graphics;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Transparency;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AWTEventListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
@@ -23,6 +26,7 @@ import java.util.Iterator;
import java.util.Stack;
import javax.swing.JComponent;
import javax.swing.Timer;
import javax.swing.event.AncestorEvent;
@@ -173,7 +177,7 @@ public class DnDManager
// install a listener so we know everywhere that the mouse enters
Toolkit.getDefaultToolkit().addAWTEventListener(this,
AWTEvent.MOUSE_EVENT_MASK);
AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
// find the top-level window and set the cursor there.
for (_topComp = _sourceComp; true; ) {
@@ -219,15 +223,19 @@ public class DnDManager
{
switch (event.getID()) {
case MouseEvent.MOUSE_ENTERED:
mouseEntered((MouseEvent) event);
globalMouseEntered((MouseEvent) event);
break;
case MouseEvent.MOUSE_EXITED:
mouseExited((MouseEvent) event);
globalMouseExited((MouseEvent) event);
break;
case MouseEvent.MOUSE_RELEASED:
mouseReleased((MouseEvent) event);
globalMouseReleased((MouseEvent) event);
break;
case MouseEvent.MOUSE_DRAGGED:
globalMouseDragged((MouseEvent) event);
break;
}
}
@@ -235,7 +243,7 @@ public class DnDManager
/**
* Handle the mouse entering a new component.
*/
protected void mouseEntered (MouseEvent event)
protected void globalMouseEntered (MouseEvent event)
{
Component newcomp = ((MouseEvent) event).getComponent();
_lastTarget = findAppropriateTarget(newcomp);
@@ -253,7 +261,7 @@ public class DnDManager
/**
* Handle the mouse leaving a component.
*/
protected void mouseExited (MouseEvent event)
protected void globalMouseExited (MouseEvent event)
{
clearComponentCursor();
@@ -262,12 +270,14 @@ public class DnDManager
_lastTarget.noDrop();
_lastTarget = null;
}
checkAutoscroll(event);
}
/**
* Handle the mouse button being released.
*/
protected void mouseReleased (MouseEvent event)
protected void globalMouseReleased (MouseEvent event)
{
// stop listening to every little event
Toolkit.getDefaultToolkit().removeAWTEventListener(this);
@@ -285,6 +295,34 @@ public class DnDManager
reset();
}
/**
* Track global drags for autoscrolling support.
*/
protected void globalMouseDragged (MouseEvent event)
{
if (_scrollComp == null) {
return;
}
int x = event.getX();
int y = event.getY();
Point p = event.getComponent().getLocationOnScreen();
p.translate(x, y);
Rectangle r = getRectOnScreen(_scrollComp);
if (!r.contains(p)) {
r.grow(_scrollDim.width, _scrollDim.height);
if (r.contains(p)) {
_scrollPoint = p;
return; // still autoscrolling
}
}
// stop autoscrolling
_scrollComp = null;
_scrollTimer.stop();
}
/**
* Find the lowest accepting parental target to this component.
*/
@@ -307,11 +345,63 @@ public class DnDManager
}
}
/**
* Check to see if we want to enter autoscrolling mode.
*/
protected void checkAutoscroll (MouseEvent exitEvent)
{
Component comp = exitEvent.getComponent();
Point p = exitEvent.getPoint();
Point scr = comp.getLocationOnScreen();
p.translate(scr.x, scr.y);
Component parent;
Object target;
while (true) {
target = _droppers.get(comp);
if (target instanceof AutoscrollingDropTarget) {
AutoscrollingDropTarget adt = (AutoscrollingDropTarget) target;
JComponent jc = (JComponent) comp;
Rectangle r = getRectOnScreen(jc);
// make sure we're actually out of the autoscrolling component
if (!r.contains(p)) {
// start autoscrolling.
_scrollComp = jc;
_scrollDim = adt.getAutoscrollBorders();
_scrollPoint = p;
_scrollTimer.start();
return;
}
}
parent = comp.getParent();
if (parent == null) {
return;
}
comp = parent;
}
}
/**
* Find the rectangular area that is visible in screen coordinates
* for the given component.
*/
protected Rectangle getRectOnScreen (JComponent comp)
{
Rectangle r = comp.getVisibleRect();
Point p = comp.getLocationOnScreen();
r.translate(p.x, p.y);
return r;
}
/**
* Reset dnd to a starting state.
*/
protected void reset ()
{
_scrollTimer.stop();
_source = null;
_sourceComp = null;
_lastComp = null;
@@ -322,6 +412,10 @@ public class DnDManager
_topComp = null;
_topCursor = null;
_curCursor = null;
_scrollComp = null;
_scrollDim = null;
_scrollPoint = null;
}
/** A handy helper that removes components when they're no longer in
@@ -335,6 +429,25 @@ public class DnDManager
}
};
/** A timer used for autoscrolling. */
protected Timer _scrollTimer = new Timer(100, new ActionListener() {
public void actionPerformed (ActionEvent x)
{
// bail if we're behind the times
if (_scrollComp == null) {
return;
}
// translate the scrollpoint into a point in the scroll component's
// coordinates
Point p = _scrollComp.getLocationOnScreen();
// and tell the scrolling component to scroll that bit on screen
_scrollComp.scrollRectToVisible(new Rectangle(
_scrollPoint.x - p.x, _scrollPoint.y - p.y, 1, 1));
}
});
/** Our DropTargets, indexed by associated Component. */
protected HashMap _droppers = new HashMap();
@@ -365,6 +478,16 @@ public class DnDManager
/** The data to be passed in the drop. */
protected Object[] _data = new Object[1];
/** The component associated with an AutoscrollingDropTarget when we're
* in autoscrolling mode. */
protected JComponent _scrollComp;
/** The area around the _scrollComp that is active for autoscrolling. */
protected Dimension _scrollDim;
/** The last screen-coordinate point of a drag while autoscrolling. */
protected Point _scrollPoint;
/** A single manager for the entire JVM. */
protected static final DnDManager singleton = new DnDManager();
}