//----------------------------------------------------------------------------//
// //
// G h o s t G l a s s P a n e //
// //
//----------------------------------------------------------------------------//
// <editor-fold defaultstate="collapsed" desc="hdr"> //
// Copyright © Hervé Bitteur and others 2000-2013. All rights reserved. //
// This software is released under the GNU General Public License. //
// Goto http://kenai.com/projects/audiveris to report bugs or suggestions. //
//----------------------------------------------------------------------------//
// </editor-fold>
package omr.ui.dnd;
import omr.ui.symbol.SymbolImage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.AlphaComposite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
/**
* Class {@code GhostGlassPane} is a special glasspane, meant for
* displaying a shape being dragged and finally dropped.
*
* @author Hervé Bitteur (from Romain Guy's demo)
*/
public class GhostGlassPane
extends JPanel
{
//~ Static fields/initializers ---------------------------------------------
/** Usual logger utility */
private static final Logger logger = LoggerFactory.getLogger(
GhostGlassPane.class);
/** Composite to be used over a droppable target */
private static AlphaComposite targetComposite = AlphaComposite.getInstance(
AlphaComposite.SRC_OVER,
0.5f);
/** Composite to be used over a non-droppable target */
private static AlphaComposite nonTargetComposite = AlphaComposite.getInstance(
AlphaComposite.SRC_OVER,
0.2f);
//~ Instance fields --------------------------------------------------------
/** The image to be dragged */
private BufferedImage draggedImage = null;
/** The previous display bounds */
private Rectangle prevRectangle = null;
/** The current location within this glasspane */
private Point localPoint = null;
/** Are we over a droppable target? */
private boolean overTarget = false;
//~ Constructors -----------------------------------------------------------
//----------------//
// GhostGlassPane //
//----------------//
/**
* Create a new GhostGlassPane object
*/
public GhostGlassPane ()
{
setOpaque(false);
setName("GhostGlassPane");
}
//~ Methods ----------------------------------------------------------------
//----------------//
// paintComponent //
//----------------//
@Override
public void paintComponent (Graphics g)
{
if ((draggedImage == null) || (localPoint == null)) {
return;
}
Graphics2D g2 = (Graphics2D) g;
// Use composition with display underneath
if (!overTarget) {
g2.setComposite(nonTargetComposite);
} else {
g2.setComposite(targetComposite);
}
Rectangle rect = getImageBounds(localPoint);
g2.drawImage(draggedImage, null, rect.x, rect.y);
}
//---------//
// setImage //
//---------//
/**
* Assign the image to be dragged
*
* @param draggedImage the image to drag
*/
public void setImage (BufferedImage draggedImage)
{
this.draggedImage = draggedImage;
}
//---------------//
// setOverTarget //
//---------------//
/**
* Tell the glasspane whether we are currently over a droppable target
*
* @param overTarget true if over a target
*/
public void setOverTarget (boolean overTarget)
{
this.overTarget = overTarget;
}
//----------//
// setPoint //
//----------//
/**
* Assign the current point, where the dragged image is to be displayed,
* and repaint as few as possible of the glass pane.
*
* @param localPoint the current location (glasspane-based)
*/
public void setPoint (Point localPoint)
{
// Anything to repaint since last time the point was set?
if (draggedImage != null) {
Rectangle rect = getImageBounds(localPoint);
Rectangle dirty = new Rectangle(rect);
if (prevRectangle != null) {
dirty.add(prevRectangle);
}
dirty.grow(1, 1); // To cope with rounding errors
// Set new values now, to avoid race condition with repaint
this.localPoint = localPoint;
prevRectangle = rect;
repaint(dirty.x, dirty.y, dirty.width, dirty.height);
} else {
this.localPoint = localPoint;
prevRectangle = null;
}
}
//----------//
// setPoint //
//----------//
/**
* Assign the current point, where the dragged image is to be displayed
*
* @param screenPoint the current location (screen-based)
*/
public void setPoint (ScreenPoint screenPoint)
{
setPoint(screenPoint.getLocalPoint(this));
}
//----------------//
// getImageBounds //
//----------------//
private Rectangle getImageBounds (Point center)
{
Rectangle rect = new Rectangle(center);
rect.grow(draggedImage.getWidth() / 2, draggedImage.getHeight() / 2);
if (draggedImage instanceof SymbolImage) {
SymbolImage symbolImage = (SymbolImage) draggedImage;
Point refPoint = symbolImage.getRefPoint();
if (refPoint != null) {
rect.translate(-refPoint.x, -refPoint.y);
}
}
return rect;
}
}