src.com.sun.jna.platform.dnd.GhostedDragImage Maven / Gradle / Ivy
/* Copyright (c) 2007 Timothy Wall, All Rights Reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna.platform.dnd;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.dnd.DragSource;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Area;
import javax.swing.Icon;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import com.sun.jna.platform.WindowUtils;
/** Provide a ghosted drag image for use during drags where
* {@link DragSource#isDragImageSupported} returns false.
* Its location in screen coordinates may be changed via {@link #move}.
* When the image is no longer needed, invoke {@link #dispose}, which
* hides the graphic immediately, or {@link #returnToOrigin}, which
* moves the image to its original location and then disposes it.
*/
public class GhostedDragImage {
private static final float DEFAULT_ALPHA = .5f;
private Window dragImage;
// Initial image position, relative to drag source
private Point origin;
/** Create a ghosted drag image, using the given icon.
* @param icon image to be drawn
* @param initialScreenLoc initial screen location of the image
*/
public GhostedDragImage(Component dragSource, final Icon icon, Point initialScreenLoc,
final Point cursorOffset) {
Window parent = dragSource instanceof Window
? (Window)dragSource : SwingUtilities.getWindowAncestor(dragSource);
// FIXME ensure gc is compatible (X11)
GraphicsConfiguration gc = parent.getGraphicsConfiguration();
dragImage = new Window(JOptionPane.getRootFrame(), gc) {
private static final long serialVersionUID = 1L;
public void paint(Graphics g) {
icon.paintIcon(this, g, 0, 0);
}
public Dimension getPreferredSize() {
return new Dimension(icon.getIconWidth(), icon.getIconHeight());
}
public Dimension getMinimumSize() {
return getPreferredSize();
}
public Dimension getMaximumSize() {
return getPreferredSize();
}
};
dragImage.setFocusableWindowState(false);
dragImage.setName("###overrideRedirect###");
Icon dragIcon = new Icon() {
public int getIconHeight() {
return icon.getIconHeight();
}
public int getIconWidth() {
return icon.getIconWidth();
}
public void paintIcon(Component c, Graphics g, int x, int y) {
g = g.create();
Area area = new Area(new Rectangle(x, y, getIconWidth(), getIconHeight()));
// X11 needs more of a window due to differences in event processing
area.subtract(new Area(new Rectangle(x + cursorOffset.x-1, y + cursorOffset.y-1, 3, 3)));
g.setClip(area);
icon.paintIcon(c, g, x, y);
g.dispose();
}
};
dragImage.pack();
WindowUtils.setWindowMask(dragImage, dragIcon);
WindowUtils.setWindowAlpha(dragImage, DEFAULT_ALPHA);
move(initialScreenLoc);
dragImage.setVisible(true);
}
/** Set the transparency of the ghosted image. */
public void setAlpha(float alpha) {
WindowUtils.setWindowAlpha(dragImage, alpha);
}
/** Make all ghosted images go away. */
public void dispose() {
dragImage.dispose();
dragImage = null;
}
/** Move the ghosted image to the requested location.
* @param screenLocation Where to draw the image, in screen coordinates
*/
public void move(Point screenLocation) {
if (origin == null) {
origin = screenLocation;
}
dragImage.setLocation(screenLocation.x, screenLocation.y);
}
private static final int SLIDE_INTERVAL = 1000/30;
/** Animate the ghosted image returning to its origin. */
public void returnToOrigin() {
final Timer timer = new Timer(SLIDE_INTERVAL, null);
timer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Point location = dragImage.getLocationOnScreen();
Point dst = new Point(origin);
int dx = (dst.x - location.x)/2;
int dy = (dst.y - location.y)/2;
if (dx != 0 || dy != 0) {
location.translate(dx, dy);
move(location);
}
else {
timer.stop();
dispose();
}
}
});
timer.setInitialDelay(0);
timer.start();
}
}