// Near Infinity - An Infinity Engine Browser and Editor
// Copyright (C) 2001 - 2005 Jon Olav Hauglid
// See LICENSE.txt for license information
package org.infinity.gui;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.RenderingHints;
import javax.swing.JComponent;
import javax.swing.SwingConstants;
/**
* A component that displays an image. Provides support for scaling and filtering.
*/
public class RenderCanvas extends JComponent implements SwingConstants
{
// interpolation types used in scaling
public static final Object TYPE_NEAREST_NEIGHBOR = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
public static final Object TYPE_BILINEAR = RenderingHints.VALUE_INTERPOLATION_BILINEAR;
public static final Object TYPE_BICUBIC = RenderingHints.VALUE_INTERPOLATION_BICUBIC;
private Image currentImage;
private Object interpolationType;
private boolean isScaling;
private int verticalAlignment, horizontalAlignment;
public RenderCanvas()
{
this(null, false, TYPE_NEAREST_NEIGHBOR, CENTER, CENTER);
}
public RenderCanvas(Image image)
{
this(image, false, TYPE_NEAREST_NEIGHBOR, CENTER, CENTER);
}
public RenderCanvas(Image image, boolean scaled)
{
this(image, scaled, TYPE_NEAREST_NEIGHBOR, CENTER, CENTER);
}
public RenderCanvas(Image image, boolean scaled, Object interpolationType)
{
this(image, scaled, interpolationType, CENTER, CENTER);
}
public RenderCanvas(Image image, boolean scaled, Object interpolationType,
int horizontalAlign, int verticalAlign)
{
setOpaque(false);
currentImage = null;
interpolationType = TYPE_NEAREST_NEIGHBOR;
isScaling = false;
verticalAlignment = horizontalAlignment = CENTER;
setInterpolationType(interpolationType);
setScalingEnabled(scaled);
setHorizontalAlignment(horizontalAlign);
setVerticalAlignment(verticalAlign);
setImage(image);
}
/**
* Returns the currently assigned image.
* @return Image object if an image has been assigned, {@code false} otherwise.
*/
public Image getImage()
{
return currentImage;
}
/**
* Sets a new image
* @param image
*/
public void setImage(Image image)
{
if (currentImage != image) {
if (image == null) {
currentImage.flush();
}
currentImage = image;
updateSize();
}
}
/**
* Gets the alignment of the component's content along the Y axis.
* @return One of the following constants defined in SwingConstants: TOP, CENTER or BOTTOM.
*/
public int getVerticalAlignment()
{
return verticalAlignment;
}
/**
* Sets the alignment of the component's content along the Y axis. The default property is CENTER.
* @param alignment One of the following constants defined in SwingConstants: TOP, CENTER or BOTTOM.
*/
public void setVerticalAlignment(int alignment)
{
if (alignment != verticalAlignment) {
switch (alignment) {
case SwingConstants.TOP:
case SwingConstants.LEFT:
verticalAlignment = SwingConstants.TOP;
break;
case SwingConstants.BOTTOM:
case SwingConstants.RIGHT:
verticalAlignment = SwingConstants.BOTTOM;
break;
default:
verticalAlignment = SwingConstants.CENTER;
}
repaint();
}
}
/**
* Gets the alignment of the component's content along the X axis.
* @return One of the following constants defined in SwingConstants: LEFT, CENTER or RIGHT.
*/
public int getHorizontalAlignment()
{
return horizontalAlignment;
}
/**
* Sets the alignment of the component's content along the X axis. The default property is CENTER.
* @param alignment One of the following constants defined in SwingConstants: LEFT, CENTER or RIGHT.
*/
public void setHorizontalAlignment(int alignment)
{
if (alignment != horizontalAlignment) {
switch (alignment) {
case SwingConstants.LEFT:
case SwingConstants.TOP:
verticalAlignment = SwingConstants.LEFT;
break;
case SwingConstants.RIGHT:
case SwingConstants.BOTTOM:
verticalAlignment = SwingConstants.RIGHT;
break;
default:
verticalAlignment = SwingConstants.CENTER;
}
repaint();
}
}
/**
* Returns whether scaling has been activated.
* @return {@code true} if scaling has been activated.
*/
public boolean isScalingEnabled()
{
return isScaling;
}
/**
* Sets whether the image buffer's content should be drawn scaled.
* @param enable {@code true} to enable scaling.
*/
public void setScalingEnabled(boolean enable)
{
if (enable != isScaling) {
isScaling = enable;
repaint();
}
}
/**
* Returns the interpolation type used when scaling has been enabled.
* @return The interpolation type.
*/
public Object getInterpolationType()
{
return interpolationType;
}
/**
* Specify the interpolation type used when scaling has been enabled.
* One of TYPE_NEAREST_NEIGHBOR, TYPE_BILINEAR and TYPE_BICUBIC (Default: TYPE_NEAREST_NEIGHBOR).
* @param interpolationType The new interpolation type to set.
*/
public void setInterpolationType(Object interpolationType)
{
if (this.interpolationType != interpolationType) {
if (interpolationType == TYPE_NEAREST_NEIGHBOR ||
interpolationType == TYPE_BILINEAR ||
interpolationType == TYPE_BICUBIC) {
this.interpolationType = interpolationType;
if (isScaling) {
repaint();
}
}
}
}
protected void updateSize()
{
if (currentImage != null) {
setPreferredSize(new Dimension(currentImage.getWidth(null), currentImage.getHeight(null)));
if (!isScaling) {
setSize(getPreferredSize());
}
} else {
setPreferredSize(new Dimension(16, 16));
setSize(getPreferredSize());
}
repaint();
}
/**
* Renders the image to the canvas.
* @param g The graphics context in which to paint.
*/
protected void paintCanvas(Graphics g)
{
if (currentImage != null && currentImage.getWidth(null) > 0 && currentImage.getHeight(null) > 0) {
Graphics2D g2 = (Graphics2D)g;
if (isScaling) {
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, interpolationType);
g2.drawImage(currentImage, 0, 0, getWidth(), getHeight(), null);
} else {
Point srcPos = new Point(0, 0);
switch (horizontalAlignment) {
case LEFT:
srcPos.x = 0;
break;
case RIGHT:
srcPos.x = getWidth() - currentImage.getWidth(null);
break;
default:
srcPos.x = (getWidth() - currentImage.getWidth(null)) / 2;
}
switch (verticalAlignment) {
case TOP:
srcPos.y = 0;
break;
case BOTTOM:
srcPos.y = getHeight() - currentImage.getHeight(null);
break;
default:
srcPos.y = (getHeight() - currentImage.getHeight(null)) / 2;
}
g2.drawImage(currentImage, srcPos.x, srcPos.y, null);
}
}
}
//--------------------- Begin Class Component ---------------------
@Override
public void paint(Graphics g)
{
paintCanvas(g);
super.paint(g);
}
//--------------------- End Class Component ---------------------
}