package org.limewire.ui.swing.dnd; import java.awt.Component; import java.awt.Point; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import javax.swing.JComponent; import javax.swing.SwingUtilities; /** * Listens to drag and drop events. When files are dragged onto a * component implementing this listener, a semi-transparent image * will be appear next to mouse to give better feedback as to what * action the drop will result in. * <p> * This class is responsible for loading the glass pane, making it * visible, displaying the transparent drag, and hiding the glass * pane when the drag exits or completes. */ public class GhostDropTargetListener implements DropTargetListener { private final GhostDragGlassPane ghostDragGlassPane; private final JComponent parent; private Point offset = new Point(8,15); public GhostDropTargetListener(JComponent parent, GhostDragGlassPane ghostDragGlassPane) { this.parent = parent; this.ghostDragGlassPane = ghostDragGlassPane; } @Override public void dragEnter(DropTargetDragEvent dtde) { Component component = getGlassPane(); // something is already currently occupying the glass pane and its visible if(!(component instanceof GhostDragGlassPane) && component.isVisible()) return; // the ghost glass pane is not occupying the glass pane if(!(component instanceof GhostDragGlassPane)) { SwingUtilities.getRootPane(parent).setGlassPane(ghostDragGlassPane); } updateText(dtde, ghostDragGlassPane); ghostDragGlassPane.repaint(); } /** * Converts the mouse coordinates on the component, to mouse coordinates * on the glass pane, positions the glass pane, then updates the image. */ private void updateText(DropTargetDragEvent dtde, GhostDragGlassPane ghostPane) { Point p = (Point) dtde.getLocation().clone(); SwingUtilities.convertPointToScreen(p, parent); SwingUtilities.convertPointFromScreen(p, ghostPane); ghostPane.setPoint(new Point(p.x + offset.x, p.y + offset.y)); } /** * When the drag exits, hide the glass pane. */ @Override public void dragExit(DropTargetEvent dte) { if(!(getGlassPane() instanceof GhostDragGlassPane)) return; GhostDragGlassPane glassPane = (GhostDragGlassPane) getGlassPane(); glassPane.setVisible(false); } /** * As a drag occurs over this component, update the image's position * as the mouse moves. */ @Override public void dragOver(DropTargetDragEvent dtde) { if(!(getGlassPane() instanceof GhostDragGlassPane)) return; GhostDragGlassPane glassPane = (GhostDragGlassPane) getGlassPane(); Point p = (Point) dtde.getLocation().clone(); SwingUtilities.convertPointToScreen(p, parent); SwingUtilities.convertPointFromScreen(p, glassPane); glassPane.setPoint(new Point(p.x + offset.x, p.y + offset.y)); glassPane.repaint(glassPane.getRepaintRect()); } /** * When a drop occurs, hide the glass pane. */ @Override public void drop(DropTargetDropEvent dtde) { if(!(getGlassPane() instanceof GhostDragGlassPane)) return; GhostDragGlassPane glassPane = (GhostDragGlassPane) getGlassPane(); glassPane.setVisible(false); } @Override public void dropActionChanged(DropTargetDragEvent dtde) {} private Component getGlassPane() { return SwingUtilities.getRootPane(parent).getGlassPane(); } }