/*
* $RCSfile: DisplayJAI.java,v $
*
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
*
* Use is subject to license terms.
*
* $Revision: 1.1 $
* $Date: 2005/02/11 04:57:03 $
* $State: Exp $
*/
package com.lightcrafts.media.jai.widget;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.RenderedImage;
import javax.swing.JPanel;
/**
* A Java<sup>TM</sup> Foundation Classes {@link JPanel} which is able
* to contain an image. The image and its container may have different
* sizes. The image may also be positioned within the container.
*
* <p>This class extends <code>JPanel</code> in order to support layout
* management. Image tiling is supported as of version 1.3 of the
* Java<sup>TM</sup> 2 Platform via
* {@link Graphics2D#drawRenderedImage(RenderedImage,AffineTransform)}.</p>
*
* <p><i>This class is not a committed part of the Java<sup>TM</sup>
* Advanced Imaging API per se. It might therefore not be supported by
* JAI implementations other than that of Sun Microsystems, Inc.</i></p>
*
* @see java.awt.Graphics2D
* @see java.awt.image.RenderedImage
* @see javax.swing.JPanel
* @see javax.swing.JComponent
*/
public class DisplayJAI extends JPanel
implements MouseListener,
MouseMotionListener {
/** The image to display. */
protected RenderedImage source = null;
/** Abscissa of image origin relative to panel origin. */
protected int originX = 0;
/** Ordinate of image origin relative to panel origin. */
protected int originY = 0;
/**
* Constructs a <code>DisplayJAI</code> and sets its
* the layout to <code>null</code>.
*/
public DisplayJAI() {
super();
setLayout(null);
}
/**
* Constructs a <code>DisplayJAI</code>, sets its layout to
* <code>null</code>, and sets its displayed image.
*
* <p>The preferred size is set such that its width is the image
* width plus the left and right insets and its height is the image
* height plus the top and bottom insets.</p>
*
* @param image The image to display.
* @throws IllegalArgumentException if <code>image</code> is
* <code>null</code>.
*/
public DisplayJAI(RenderedImage image) {
super();
setLayout(null);
if(image == null) {
throw new IllegalArgumentException("image == null!");
}
source = image;
// Swing geometry
int w = source.getWidth();
int h = source.getHeight();
Insets insets = getInsets();
Dimension dim = new Dimension(w + insets.left + insets.right,
h + insets.top + insets.bottom);
setPreferredSize(dim);
}
/**
* Moves the image within it's container. The instance variables
* <code>originX</code> and <code>originY</code> are set to the
* parameter valus <code>x</code> and <code>y</code>, respectively.
* {@link #repaint()} is invoked after the origin values are changed.
*
* @param x image origin abscissa.
* @param y image origin ordinate.
*/
public void setOrigin(int x, int y) {
originX = x;
originY = y;
repaint();
}
/** Retrieves the image origin. */
public Point getOrigin() {
return new Point(originX, originY);
}
/**
* Sets a new image to display.
*
* <p>The preferred size is set such that its width is the image
* width plus the left and right insets and its height is the image
* height plus the top and bottom insets. {@link #revalidate()} and
* {@link #repaint()} are invoked after all other changes.</p>
*
* @param im The image to display.
* @throws IllegalArgumentException if <code>im</code> is
* <code>null</code>.
*/
public void set(RenderedImage im) {
if(im == null) {
throw new IllegalArgumentException("im == null!");
}
source = im;
// Swing geometry
int w = source.getWidth();
int h = source.getHeight();
Insets insets = getInsets();
Dimension dim = new Dimension(w + insets.left + insets.right,
h + insets.top + insets.bottom);
setPreferredSize(dim);
revalidate();
repaint();
}
/**
* Sets a new image to display and its coordinates within the container.
*
* <p>The preferred size is set such that its width is the image
* width plus the left and right insets and its height is the image
* height plus the top and bottom insets. {@link #revalidate()} and
* {@link #repaint()} are invoked after all other changes.</p>
*
* @param im The image to display.
* @param x image origin abscissa.
* @param y image origin ordinate.
* @throws IllegalArgumentException if <code>im</code> is
* <code>null</code>.
*/
public void set(RenderedImage im, int x, int y) {
if(im == null) {
throw new IllegalArgumentException("im == null!");
}
source = im;
// Swing geometry
int w = source.getWidth();
int h = source.getHeight();
Insets insets = getInsets();
Dimension dim = new Dimension(w + insets.left + insets.right,
h + insets.top + insets.bottom);
setPreferredSize(dim);
originX = x;
originY = y;
revalidate();
repaint();
}
/**
* Returns the image to be displayed by this panel.
*
* @return The value of the {@link #source} instance variable.
*/
public RenderedImage getSource() {
return source;
}
/**
* Draws the image or fills the panel with a background color.
*
* <p>If the current image is <code>null</code>, the rectangle
* <code>new Rectangle(0,0,{@link #getWidth()},{@link #getHeight()})</code>
* is filled with the background color returned by
* {@link #getBackground()}.</p>
*
* <p>If the current image is non-<code>null</code>, the rectangle
* returned by {@link Graphics2D#getClipBounds()} is filled with the
* background color and the image is drawn using
* {@link Graphics2D#drawRenderedImage(RenderedImage,AffineTransform)}
* at the location
* <code>({@link #getInsets()}.left+originX,
* {@link #getInsets()}.right+originY)</code>.
*
* @param g <code>Graphics</code> context in which to paint.
*/
public synchronized void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
// empty component (no image)
if ( source == null ) {
g2d.setColor(getBackground());
g2d.fillRect(0, 0, getWidth(), getHeight());
return;
}
// clear damaged component area
Rectangle clipBounds = g2d.getClipBounds();
g2d.setColor(getBackground());
g2d.fillRect(clipBounds.x,
clipBounds.y,
clipBounds.width,
clipBounds.height);
// account for borders
Insets insets = getInsets();
int tx = insets.left + originX;
int ty = insets.top + originY;
// Translation moves the entire image within the container
try {
g2d.drawRenderedImage(source,
AffineTransform.getTranslateInstance(tx, ty));
} catch( OutOfMemoryError e ) {
}
}
/**
* An empty method which should be overridden by subclasses which
* respond to mouse presses.
*/
public void mousePressed(MouseEvent e) { }
/**
* An empty method which should be overridden by subclasses which
* respond to mouse releases.
*/
public void mouseReleased(MouseEvent e) { }
/**
* An empty method which should be overridden by subclasses which
* respond to mouse movement.
*/
public void mouseMoved(MouseEvent e) { }
/**
* An empty method which should be overridden by subclasses which
* respond to mouse dragging.
*/
public void mouseDragged(MouseEvent e) { }
/**
* An empty method which should be overridden by subclasses which
* respond to mouse entrances.
*/
public void mouseEntered(MouseEvent e) { }
/**
* An empty method which should be overridden by subclasses which
* respond to mouse exits.
*/
public void mouseExited(MouseEvent e) { }
/**
* An empty method which should be overridden by subclasses which
* respond to mouse clicks.
*/
public void mouseClicked(MouseEvent e) { }
}