package com.idega.presentation.awt;
import java.awt.*;
import java.net.*;
import java.awt.image.*; // For ImageFilter stuff
// This appears in Core Web Programming from
// Prentice Hall Publishers, and may be freely used
// or adapted. 1997 Marty Hall, hall@apl.jhu.edu.
//======================================================
/**
* A button class that uses an image instead of a
* textual label. Clicking and releasing the mouse over
* the button triggers an ACTION_EVENT, so you can add
* behavior in the same two ways as you with a normal
* Button (in Java 1.0):
* <OL>
* <LI>Make an ImageButton subclass and put the
* behavior in the action method of that subclass.
* <LI>Use the main ImageButton class but then catch
* the events in the action method of the Container.
* </OL>
* <P>
* Normally, the ImageButton's preferredSize (used,
* for instance, by FlowLayout) is just big enough
* to hold the image. However, if you give an explicit
* resize or reshape call <B>before</B> adding the
* ImageButton to the Container, this size will
* override the defaults.
* <P>
* @author Marty Hall (hall@apl.jhu.edu)
* @see Icon
* @see GrayFilter
* @version 1.0 (1997)
*/
public class ImageButton extends ImageLabel {
//----------------------------------------------------
/** Default width of 3D border around image.
* Currently 4.
* @see ImageLabel#setBorder
* @see ImageLabel#getBorder
*/
protected static final int defaultBorderWidth = 4;
/** Default color of 3D border around image.
* Currently a gray with R/G/B of 160/160/160.
* Light grays look best.
* @see ImageLabel#setBorderColor
* @see ImageLabel#getBorderColor
*/
protected static final Color defaultBorderColor =
new Color(160, 160, 160);
private boolean mouseIsDown = false;
//----------------------------------------------------
// Constructors
/** Create an ImageButton with the default image.
* @see ImageLabel#getDefaultImageString
*/
public ImageButton() {
super();
setBorders();
}
/** Create an ImageButton using the image at URL
* specified by the string.
* @param imageURLString A String specifying the URL
* of the image.
*/
public ImageButton(String imageURLString) {
super(imageURLString);
setBorders();
}
/** Create an ImageButton using the image at URL
* specified.
* @param imageURL The URL of the image.
*/
public ImageButton(URL imageURL) {
super(imageURL);
setBorders();
}
/** Creates an ImageButton using the file in
* the directory specified.
* @param imageDirectory The URL of a directory
* @param imageFile File in the above directory
*/
public ImageButton(URL imageDirectory,
String imageFile) {
super(imageDirectory, imageFile);
setBorders();
}
/** Create an ImageButton using the image specified.
* You would only want to use this if you already
* have an image (e.g. created via createImage).
* @param image The image.
*/
public ImageButton(Image image) {
super(image);
setBorders();
}
//----------------------------------------------------
/** Draws the image with the border around it. If you
* override this in a subclass, call super.paint().
*/
public void paint(Graphics g) {
super.paint(g);
if (this.grayImage == null) {
createGrayImage(g);
}
drawBorder(true);
}
//----------------------------------------------------
// You only want mouseExit to repaint when mouse
// is down, so you have to set that flag here.
/** When the mouse is clicked, reverse the 3D border
* and draw a dark-gray version of the image.
* The action is not triggered until mouseUp.
*/
public boolean mouseDown(Event event, int x, int y) {
this.mouseIsDown = true;
Graphics g = getGraphics();
int border = getTheBorder();
if (hasExplicitSize()) {
g.drawImage(this.grayImage, border, border,
getWidth()-2*border,
getHeight()-2*border,
this);
}
else {
g.drawImage(this.grayImage, border, border, this);
}
drawBorder(false);
return(true);
}
//----------------------------------------------------
/** If cursor is still inside, trigger the action
* event and redraw the image (non-gray, button
* "out"). Otherwise ignore this.
*/
public boolean mouseUp(Event event, int x, int y) {
this.mouseIsDown = false;
if (inside(x,y)) {
paint(getGraphics());
event.id = Event.ACTION_EVENT;
event.arg = getImage();
return(action(event, event.arg));
}
else {
return(false);
}
}
//----------------------------------------------------
/** Generated when the button is clicked and released.
* Override this in subclasses to give behavior to
* the button. Alternatively, since the default
* behavior is to pass the ACTION_EVENT along to the
* Container, you can catch events for a bunch of
* buttons there.
* @see Component#action
*/
public boolean action(Event event, Object arg) {
debug("Clicked on button for " +
getImageString() + ".");
return(false);
}
//----------------------------------------------------
/** If you move the mouse off the button while the
* mouse is down, abort and do <B>not</B> trigger
* the action. Ignore this if button was not
* already down.
*/
public boolean mouseExit(Event event, int x, int y) {
if (this.mouseIsDown) {
paint(getGraphics());
}
return(true);
}
//----------------------------------------------------
/** The darkness value to use for grayed images.
* @see #setDarkness
*/
public int getDarkness() {
return(this.darkness);
}
/** An int whose bits are combined via "and" ("&")
* with the alpha, red, green, and blue bits of the
* pixels of the image to produce the grayed-out
* image to use when button is depressed.
* Default is 0xffafafaf: af combines with r/g/b
* to darken image.
*/
public void setDarkness(int darkness) {
this.darkness = darkness;
}
// Changing darker is consistent with regular buttons
private int darkness = 0xffafafaf;
//----------------------------------------------------
/** The gray image used when button is down.
* @see #setGrayImage
*/
public Image getGrayImage() {
return(this.grayImage);
}
/** Sets gray image created automatically from regular
* image via an image filter to use when button is
* depressed. You won't normally use this directly.
*/
public void setGrayImage(Image grayImage) {
this.grayImage = grayImage;
}
private Image grayImage = null;
//----------------------------------------------------
private void drawBorder(boolean isUp) {
Graphics g = getGraphics();
g.setColor(getBorderColor());
int left = 0;
int top = 0;
int width = getWidth();
int height = getHeight();
int border = getTheBorder();
for(int i=0; i<border; i++) {
g.draw3DRect(left, top, width, height, isUp);
left++;
top++;
width = width - 2;
height = height - 2;
}
}
//----------------------------------------------------
private void setBorders() {
setBorder(defaultBorderWidth);
setBorderColor(defaultBorderColor);
}
//----------------------------------------------------
// The first time the image is drawn, update() is
// called, and the result does not come out correctly.
// So this forces a brief draw on loadup, replaced
// by real, non-gray image.
private void createGrayImage(Graphics g) {
ImageFilter filter = new GrayFilter(this.darkness);
ImageProducer producer =
new FilteredImageSource(getImage().getSource(),
filter);
this.grayImage = createImage(producer);
int border = getTheBorder();
if (hasExplicitSize()) {
prepareImage(this.grayImage, getWidth()-2*border,
getHeight()-2*border, this);
}
else {
prepareImage(this.grayImage, this);
}
super.paint(g);
}
//----------------------------------------------------
}