/**
*
*/
package javax.swing.origamist;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Point;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
/**
* This class handles displaying an image on the background of the component that contains it.
*
* To display the background image, just override <code>paintComponent</code> in the Swing component and call
* <code>backgroundImageSupport.paintComponent()</code> from it.
*
* @author Martin Pecka
*/
public class BackgroundImageSupport
{
/** The image to display. */
protected ImageIcon image;
/** The component which the background is drawn on. */
protected JComponent component;
/** The position of the image. */
protected PositionInComponent position;
/** The directions to in which to repeat the background. */
protected BackgroundRepeat repeat;
/**
* Setup the background image for <code>component</code>.
*
* @param image The image to be displayed.
* @param component The component the image will be displayed on.
* @param xPos Horizontal position of the background: can be a number (px from the left), string ("left", "center",
* "right") or a percent-string ("36%").
* @param yPos Vertical position of the background: can be a number (px from the top), string ("top", "center",
* "bottom") or a percent-string ("36%").
* @param repeat The repeat behavior. If repeating along an axis is enabled, the corresponding background position
* is ignored and the image is repeated along the axis.
*/
public BackgroundImageSupport(ImageIcon image, JComponent component, String xPos, String yPos,
BackgroundRepeat repeat)
{
this.image = image;
MediaTracker mt = new MediaTracker(component);
mt.addImage(image.getImage(), 1);
try {
mt.waitForID(1);
} catch (InterruptedException e) {}
this.component = component;
this.position = new PositionInComponent(component, xPos, yPos, image.getIconWidth(), image.getIconWidth());
this.repeat = repeat;
}
/**
* Setup the background image for <code>component</code>.
*
* @param image The image to be displayed.
* @param component The component the image will be displayed on.
* @param xPos Horizontal position of the background: the distance from the left side in <code>px</code>.
* @param yPos Vertical position of the background: the distance from the top side in <code>px</code>.
* @param repeat The repeat behavior. If repeating along an axis is enabled, the corresponding background position
* is ignored and the image is repeated along the axis.
*/
public BackgroundImageSupport(ImageIcon image, JComponent component, int xPos, int yPos, BackgroundRepeat repeat)
{
this(image, component, String.valueOf(xPos), String.valueOf(yPos), repeat);
}
/**
* Setup the background image for <code>component</code>.
*
* @param image The image to be displayed.
* @param component The component the image will be displayed on.
* @param xPos Horizontal position of the background: can be a number (px from the left), string ("left", "center",
* "right") or a percent-string ("36%").
* @param yPos Vertical position of the background: can be a number (px from the top), string ("top", "center",
* "bottom") or a percent-string ("36%").
* @param repeat The repeat behavior. If repeating along an axis is enabled, the corresponding background position
* is ignored and the image is repeated along the axis.
*/
public BackgroundImageSupport(Image image, JComponent component, String xPos, String yPos, BackgroundRepeat repeat)
{
this(new ImageIcon(image), component, xPos, yPos, repeat);
}
/**
* Setup the background image for <code>component</code>.
*
* @param image The image to be displayed.
* @param component The component the image will be displayed on.
* @param xPos Horizontal position of the background: the distance from the left side in <code>px</code>.
* @param yPos Vertical position of the background: the distance from the top side in <code>px</code>.
* @param repeat The repeat behavior. If repeating along an axis is enabled, the corresponding background position
* is ignored and the image is repeated along the axis.
*/
public BackgroundImageSupport(Image image, JComponent component, int xPos, int yPos, BackgroundRepeat repeat)
{
this(new ImageIcon(image), component, xPos, yPos, repeat);
}
/**
* Setup the background image for <code>component</code>.
*
* @param image The image to be displayed.
* @param component The component the image will be displayed on.
* @param xPos Horizontal position of the background: can be a number (px from the left), string ("left", "center",
* "right") or a percent-string ("36%").
* @param yPos Vertical position of the background: can be a number (px from the top), string ("top", "center",
* "bottom") or a percent-string ("36%").
* @param repeat The repeat behavior. If repeating along an axis is enabled, the corresponding background position
* is ignored and the image is repeated along the axis.
*/
public BackgroundImageSupport(URL image, JComponent component, String xPos, String yPos, BackgroundRepeat repeat)
{
this(new ImageIcon(image), component, xPos, yPos, repeat);
}
/**
* Setup the background image for <code>component</code>.
*
* @param image The image to be displayed.
* @param component The component the image will be displayed on.
* @param xPos Horizontal position of the background: the distance from the left side in <code>px</code>.
* @param yPos Vertical position of the background: the distance from the top side in <code>px</code>.
* @param repeat The repeat behavior. If repeating along an axis is enabled, the corresponding background position
* is ignored and the image is repeated along the axis.
*/
public BackgroundImageSupport(URL image, JComponent component, int xPos, int yPos, BackgroundRepeat repeat)
{
this(new ImageIcon(image), component, xPos, yPos, repeat);
}
/**
* This method should be called from the owner component's <code>paintComponent()</code> to draw the background.
*
* Ideally, this should be called just after <code>super.paintComponent()</code> is called in the owner.
*
* @param g The graphics to use for the drawing.
*/
public void paintComponent(Graphics g)
{
Point loc = position.getLocation();
if (repeat.repeatX)
loc.x = 0;
if (repeat.repeatY)
loc.y = 0;
int iw = image.getIconWidth();
int ih = image.getIconHeight();
int cw = component.getWidth();
int ch = component.getHeight();
for (int x = 0; x < (repeat.repeatX ? Math.ceil((cw / (double) iw)) : 1); x++) {
for (int y = 0; y < (repeat.repeatY ? Math.ceil((ch / (double) ih)) : 1); y++) {
g.drawImage(image.getImage(), loc.x + x * iw, loc.y + y * ih, null);
}
}
}
public enum BackgroundRepeat
{
/** Don't repeat along any axis. */
NO_REPEAT(false, false),
/** Repeat horizontally. */
REPEAT_X(true, false),
/** Repeat vertically. */
REPEAT_Y(false, true),
/** Repeat along both aces. */
REPEAT_ALL(true, true);
boolean repeatX = false;
boolean repeatY = false;
BackgroundRepeat(boolean x, boolean y)
{
repeatX = x;
repeatY = y;
}
}
protected class PositionInComponent
{
String x;
String y;
int w;
int h;
JComponent c;
public PositionInComponent(JComponent c, String x, String y, int w, int h)
{
this.c = c;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
public PositionInComponent(JComponent c, int x, int y, int w, int h)
{
this(c, String.valueOf(x), String.valueOf(y), w, h);
}
public Point getLocation()
{
int cw = c.getWidth();
int ch = c.getHeight();
Point result = new Point();
if ("left".equals(x)) {
x = "0";
} else if ("center".equals(x)) {
x = "50%";
} else if ("right".equals(x)) {
x = "100%";
}
try {
result.x = Integer.parseInt(x);
} catch (NumberFormatException e) {
if (x.matches("%$")) {
try {
int percent = Integer.parseInt(x.substring(0, x.length() - 1));
if (percent < 0 || percent > 100)
throw new NumberFormatException();
result.x = (int) ((percent / 100d) * (cw - w));
} catch (NumberFormatException e1) {
result.x = 0;
}
} else {
result.x = 0;
}
}
if ("top".equals(y)) {
y = "0";
} else if ("center".equals(y)) {
y = "50%";
} else if ("bottom".equals(y)) {
y = "100%";
}
try {
result.y = Integer.parseInt(y);
} catch (NumberFormatException e) {
if (y.matches("%$")) {
try {
int percent = Integer.parseInt(y.substring(0, y.length() - 1));
if (percent < 0 || percent > 100)
throw new NumberFormatException();
result.y = (int) ((percent / 100d) * (ch - h));
} catch (NumberFormatException e1) {
result.y = 0;
}
} else {
result.y = 0;
}
}
return result;
}
}
}