/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package de.cismet.cismap.commons.gui.piccolo;
import com.vividsolutions.jts.geom.Geometry;
import java.awt.Paint;
import java.awt.PaintContext;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.TexturePaint;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
/**
* This class can be used as a TexturePaint that considers the selection status of the corresponding feature.
*
* @author therter
* @version $Revision$, $Date$
*/
public class SelectionAwareTexturePaint implements Paint, Cloneable, PaintWrapper {
//~ Enums ------------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
public enum SelectionMode {
//~ Enum constants -----------------------------------------------------
HIGHLIGHTED, SELECTED, UNSELECTED
}
//~ Instance fields --------------------------------------------------------
private final double MIN_SIDE_LENGTH = 0.5;
private final BufferedImage defaultImage;
private final BufferedImage highlightedImage;
private final BufferedImage selectedImage;
private final Rectangle2D rec;
private TexturePaint paint;
private BufferedImage currentImage;
private Rectangle2D currentRec;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new SelectionAwareTexturePaint object.
*
* @param defaultImage this image is used, if the corresponding feature is unselected and not highlighted
* @param highlightedImage this image is used, if the corresponding feature is highlighted
* @param selectedImage this image is used, if the corresponding feature is selected
* @param rec the Rectangle2D in user space used to anchor and replicate the texture
*/
public SelectionAwareTexturePaint(final BufferedImage defaultImage,
final BufferedImage highlightedImage,
final BufferedImage selectedImage,
final Rectangle2D rec) {
paint = new TexturePaint(defaultImage, rec);
this.rec = rec;
this.currentRec = rec;
this.defaultImage = defaultImage;
this.highlightedImage = highlightedImage;
this.selectedImage = selectedImage;
this.currentImage = defaultImage;
}
//~ Methods ----------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
@Override
public Paint getPaint() {
return paint;
}
/**
* Set the selection mode to highlighted, selected or unselected.
*
* @param mode the new selection mode
*/
public void setMode(final SelectionMode mode) {
switch (mode) {
case HIGHLIGHTED: {
paint = new TexturePaint(highlightedImage, currentRec);
this.currentImage = highlightedImage;
break;
}
case SELECTED: {
paint = new TexturePaint(selectedImage, currentRec);
this.currentImage = selectedImage;
break;
}
case UNSELECTED: {
paint = new TexturePaint(defaultImage, currentRec);
this.currentImage = defaultImage;
break;
}
}
}
@Override
public PaintContext createContext(final ColorModel cm,
final Rectangle deviceBounds,
final Rectangle2D userBounds,
final AffineTransform xform,
final RenderingHints hints) {
return paint.createContext(cm, deviceBounds, userBounds, xform, hints);
}
@Override
public int getTransparency() {
return paint.getTransparency();
}
@Override
public Object clone() {
final SelectionAwareTexturePaint clone = new SelectionAwareTexturePaint(
defaultImage,
highlightedImage,
selectedImage,
rec);
clone.currentRec = currentRec;
clone.currentImage = currentImage;
return clone;
}
/**
* Set the scale of the map that shows the corresponding feature.
*
* @param scale the current scale
* @param geom the current feature geometry (a very small feature geometry is assumed to be in a geographic crs
* and causes very small rectangle height/width)
*/
public void setScale(final double scale, final Geometry geom) {
double factor = (1 / scale);
final double minSide = Math.min(rec.getWidth() * factor, rec.getHeight() * factor);
if (minSide < MIN_SIDE_LENGTH) {
// if the side is smaller than MIN_SIDE_LENGTH, display errors will be occur
factor = MIN_SIDE_LENGTH / Math.min(rec.getWidth(), rec.getHeight());
}
if (geom.getArea() < 0.0001d) {
// wgs 84 is assumed
factor *= Math.sqrt(geom.getArea());
}
currentRec = new Rectangle2D.Double(
rec.getMinX(),
rec.getMinY(),
rec.getWidth()
* factor,
rec.getHeight()
* factor);
paint = new TexturePaint(
defaultImage,
currentRec);
}
}