From b88d832aeb606d449b4da72e62b61e1b97c86408 Mon Sep 17 00:00:00 2001 From: ray Date: Fri, 9 May 2003 21:32:11 +0000 Subject: [PATCH] git-svn-id: https://samskivert.googlecode.com/svn/trunk@1126 6335cc39-0255-0410-8fd6-9bcaacd3b74c --- .../com/samskivert/swing/dnd/DnDManager.java | 370 ++++++++++-------- 1 file changed, 206 insertions(+), 164 deletions(-) diff --git a/projects/samskivert/src/java/com/samskivert/swing/dnd/DnDManager.java b/projects/samskivert/src/java/com/samskivert/swing/dnd/DnDManager.java index 2458e914..f2402977 100644 --- a/projects/samskivert/src/java/com/samskivert/swing/dnd/DnDManager.java +++ b/projects/samskivert/src/java/com/samskivert/swing/dnd/DnDManager.java @@ -1,10 +1,10 @@ // -// $Id: DnDManager.java,v 1.16 2003/05/08 21:46:28 ray Exp $ +// $Id: DnDManager.java,v 1.17 2003/05/09 21:32:11 ray Exp $ package com.samskivert.swing.dnd; -import java.awt.AWTEvent; import java.awt.Component; +import java.awt.Container; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics; @@ -18,21 +18,19 @@ import java.awt.Transparency; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.AWTEventListener; +import java.awt.event.ContainerEvent; +import java.awt.event.ContainerListener; import java.awt.event.MouseEvent; -import java.awt.event.MouseMotionListener; import java.util.HashMap; -import java.util.Iterator; -import java.util.Stack; import javax.swing.JComponent; import javax.swing.Timer; import javax.swing.event.AncestorEvent; +import javax.swing.event.MouseInputAdapter; import com.samskivert.swing.event.AncestorAdapter; -import com.samskivert.swing.util.SwingUtil; import com.samskivert.Log; /** @@ -40,7 +38,6 @@ import com.samskivert.Log; * need it to do and no more. */ public class DnDManager - implements MouseMotionListener, AWTEventListener { /** * Add the specified component as a source of drags, with the DragSource @@ -173,7 +170,8 @@ public class DnDManager DragSource source, JComponent comp, boolean autoremove) { _draggers.put(comp, source); - comp.addMouseMotionListener(this); + comp.addMouseListener(_sourceListener); + comp.addMouseMotionListener(_sourceListener); if (autoremove) { comp.addAncestorListener(_remover); } @@ -185,7 +183,8 @@ public class DnDManager protected void removeSource (JComponent comp) { _draggers.remove(comp); - comp.removeMouseMotionListener(this); + comp.removeMouseListener(_sourceListener); + comp.removeMouseMotionListener(_sourceListener); } /** @@ -195,6 +194,7 @@ public class DnDManager DropTarget target, JComponent comp, boolean autoremove) { _droppers.put(comp, target); + addTargetListeners(comp); if (autoremove) { comp.addAncestorListener(_remover); } @@ -206,60 +206,41 @@ public class DnDManager protected void removeTarget (JComponent comp) { _droppers.remove(comp); + removeTargetListeners(comp); } - // documentation inherited from interface MouseMotionListener - public void mouseMoved (MouseEvent me) + /** + * Add the appropriate target listeners to this component + * and all its children. + */ + protected void addTargetListeners (Component comp) { - // who cares. - } - - // documentation inherited from interface MouseMotionListener - public void mouseDragged (MouseEvent me) - { - // make sure a drag hasn't already started. - if (_sourceComp != null) { - return; - } - - _sourceComp = me.getComponent(); - _source = (DragSource) _draggers.get(_sourceComp); - - // make sure the source wants to start a drag. - if ((_source == null) || (!_sourceComp.isEnabled()) || - (!_source.startDrag(_cursors, _data))) { - // if not, reset our start conditions and bail - reset(); - return; - } - - // use standard cursors if custom ones not specified - if (_cursors[0] == null) { - _cursors[0] = java.awt.dnd.DragSource.DefaultMoveDrop; - } - if (_cursors[1] == null) { - _cursors[1] = java.awt.dnd.DragSource.DefaultMoveNoDrop; - } - - // start out with the no-drop cursor. - _curCursor = _cursors[1]; - - // install a listener so we know everywhere that the mouse enters - Toolkit.getDefaultToolkit().addAWTEventListener(this, - AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK); - - // find the top-level window and set the cursor there. - for (_topComp = _sourceComp; true; ) { - Component c = _topComp.getParent(); - if (c == null) { - break; + comp.addMouseListener(_targetListener); + comp.addMouseMotionListener(_targetListener); + if (comp instanceof Container) { // hm, always true for JComp.. + Container cont = (Container) comp; + cont.addContainerListener(_childListener); + for (int ii=0, nn=cont.getComponentCount(); ii < nn; ii++) { + addTargetListeners(cont.getComponent(ii)); } - _topComp = c; } - _topCursor = _topComp.getCursor(); - _topComp.setCursor(_curCursor); + } - setComponentCursor(_sourceComp); + /** + * Remove the appropriate target listeners to this component + * and all its children. + */ + protected void removeTargetListeners (Component comp) + { + comp.removeMouseListener(_targetListener); + comp.removeMouseMotionListener(_targetListener); + if (comp instanceof Container) { // again, always true for JComp... + Container cont = (Container) comp; + cont.removeContainerListener(_childListener); + for (int ii=0, nn=cont.getComponentCount(); ii < nn; ii++) { + removeTargetListeners(cont.getComponent(ii)); + } + } } /** @@ -287,115 +268,12 @@ public class DnDManager } } - // documentation inherited from interface AWTEventListener - public void eventDispatched (AWTEvent event) - { - switch (event.getID()) { - case MouseEvent.MOUSE_ENTERED: - globalMouseEntered((MouseEvent) event); - break; - - case MouseEvent.MOUSE_EXITED: - globalMouseExited((MouseEvent) event); - break; - - case MouseEvent.MOUSE_RELEASED: - globalMouseReleased((MouseEvent) event); - break; - - case MouseEvent.MOUSE_DRAGGED: - globalMouseDragged((MouseEvent) event); - break; - } - } - /** - * Handle the mouse entering a new component. + * Are we currently involved in a drag? */ - protected void globalMouseEntered (MouseEvent event) + protected boolean isDragging () { - Component newcomp = ((MouseEvent) event).getComponent(); - _lastTarget = findAppropriateTarget(newcomp); - Cursor newcursor = _cursors[(_lastTarget == null) ? 1 : 0]; - - // see if the current cursor changed. - if (newcursor != _curCursor) { - _topComp.setCursor(_curCursor = newcursor); - } - - // and check the cursor at the component level - setComponentCursor(newcomp); - } - - /** - * Handle the mouse leaving a component. - */ - protected void globalMouseExited (MouseEvent event) - { - clearComponentCursor(); - - // and if we were over a target, let the target know that we left - if (_lastTarget != null) { - _lastTarget.noDrop(); - _lastTarget = null; - } - - checkAutoscroll(event); - } - - /** - * Handle the mouse button being released. - */ - protected void globalMouseReleased (MouseEvent event) - { - // stop listening to every little event - Toolkit.getDefaultToolkit().removeAWTEventListener(this); - - // reset cursors - clearComponentCursor(); - _topComp.setCursor(_topCursor); - - // the event.getComponent() will be the source component here (huh..) - // so we instead use the last component seen in mouseEnter - if (_lastTarget != null) { - _lastTarget.dropCompleted(_source, _data[0]); - _source.dragCompleted(_lastTarget); - } - reset(); - } - - /** - * Track global drags for autoscrolling support. - */ - protected void globalMouseDragged (MouseEvent event) - { - if (_scrollComp == null) { - return; - } - - int x = event.getX(); - int y = event.getY(); - - try { - 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 - } - } - } catch (IllegalComponentStateException icse) { - // the component could no longer be on screen - // don't complain, just stop autoscroll - } - - // stop autoscrolling - _scrollComp = null; - _scrollTimer.stop(); + return (_source != null); } /** @@ -526,6 +404,170 @@ public class DnDManager } }); + /** Listens to registered drag source components. */ + protected MouseInputAdapter _sourceListener = new MouseInputAdapter() { + public void mouseDragged (MouseEvent me) + { + // make sure a drag hasn't already started. + if (isDragging()) { + return; + } + + _sourceComp = me.getComponent(); + _source = (DragSource) _draggers.get(_sourceComp); + + // make sure the source wants to start a drag. + if ((_source == null) || (!_sourceComp.isEnabled()) || + (!_source.startDrag(_cursors, _data))) { + // if not, reset our start conditions and bail + reset(); + return; + } + + // use standard cursors if custom ones not specified + if (_cursors[0] == null) { + _cursors[0] = java.awt.dnd.DragSource.DefaultMoveDrop; + } + if (_cursors[1] == null) { + _cursors[1] = java.awt.dnd.DragSource.DefaultMoveNoDrop; + } + + // start out with the no-drop cursor. + _curCursor = _cursors[1]; + + // find the top-level window and set the cursor there. + for (_topComp = _sourceComp; true; ) { + Component c = _topComp.getParent(); + if (c == null) { + break; + } + _topComp = c; + } + _topCursor = _topComp.getCursor(); + _topComp.setCursor(_curCursor); + + setComponentCursor(_sourceComp); + } + + public void mouseReleased (MouseEvent event) + { + if (!isDragging()) { + return; + } + + // reset cursors + clearComponentCursor(); + _topComp.setCursor(_topCursor); + + // get the last target seen... + if (_lastTarget != null) { + _lastTarget.dropCompleted(_source, _data[0]); + _source.dragCompleted(_lastTarget); + } + reset(); + } + + public void mouseExited (MouseEvent event) + { + if (isDragging()) { + clearComponentCursor(); + } + } + + public void mouseEntered (MouseEvent event) + { + if (isDragging()) { + setComponentCursor(event.getComponent()); + } + } + }; + + /** Listens to registered drop targets and their children. */ + protected MouseInputAdapter _targetListener = new MouseInputAdapter() { + public void mouseEntered (MouseEvent event) + { + if (!isDragging()) { + return; + } + + Component newcomp = event.getComponent(); + _lastTarget = findAppropriateTarget(newcomp); + Cursor newcursor = _cursors[(_lastTarget == null) ? 1 : 0]; + + // see if the current cursor changed. + if (newcursor != _curCursor) { + _topComp.setCursor(_curCursor = newcursor); + } + + // and check the cursor at the component level + setComponentCursor(newcomp); + } + + public void mouseExited (MouseEvent event) + { + if (!isDragging()) { + return; + } + + clearComponentCursor(); + + // and if we were over a target, let the target know that we left + if (_lastTarget != null) { + _lastTarget.noDrop(); + _lastTarget = null; + } + + checkAutoscroll(event); + } + + public void mouseDragged (MouseEvent event) + { + if (!isDragging()) { + return; + } + if (_scrollComp == null) { + return; + } + + int x = event.getX(); + int y = event.getY(); + + try { + 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 + } + } + } catch (IllegalComponentStateException icse) { + // the component could no longer be on screen + // don't complain, just stop autoscroll + } + + // stop autoscrolling + _scrollComp = null; + _scrollTimer.stop(); + } + }; + + /** Listens to the drop target components and all their children. */ + protected ContainerListener _childListener = new ContainerListener() { + public void componentAdded (ContainerEvent e) + { + addTargetListeners(e.getChild()); + } + + public void componentRemoved (ContainerEvent e) + { + removeTargetListeners(e.getChild()); + } + }; + /** Our DropTargets, indexed by associated Component. */ protected HashMap _droppers = new HashMap();