/*
 * @(#)ImageButton.java
 *
 * Copyright (c) 1997 NAKAGAWA Masami
 *
 * Permission to use, copy, modify, and distribute this software
 * for NON-COMMERCIAL purpose and without fee is hereby granted.
 */

import java.applet.*;
import java.awt.*;
import java.awt.image.*;
import java.net.*;

/** A class of ImageButton
 * @author	NAKAGAWA Masami
 * @version	1.1, 13 Jul 1997
 */
public class ImageButton extends Applet {
    private Image current;
    private Image image;
    private Image gray;
    private URL url;
    private int border = 2;
    private Color bgColor = Color.lightGray;
    private Graphics screen;
    private Graphics offScreen;
    private Image offImage;
    private String target;
    private String label;
    private AppletContext ac;
    private float hue = -1.0f;
    private float saturation = 1.0f;
    private float brightness = 1.0f;
    private boolean pushed;
    private boolean reverse;

    public void init() {
        String s = getParameter("image");
        if (s != null) image = getImage(getDocumentBase(), s);
        s = getParameter("border");
        if (s != null) border = Integer.parseInt(s);
        s = getParameter("target");
        if (s != null) target = s;
        s = getParameter("bgColor");
        if (s != null) bgColor = new Color(Integer.parseInt(s, 16));
        setBackground(bgColor);
        s = getParameter("label");
        if (s != null) label = s;
        s = getParameter("hue");
        if (s != null) hue = Float.valueOf(s).floatValue()/6.0f;
        s = getParameter("saturation");
        if (s != null) saturation = Float.valueOf(s).floatValue();
        s = getParameter("brightness");
        if (s != null) brightness = Float.valueOf(s).floatValue();
        s = getParameter("reverse");
        if (s != null) reverse = Boolean.valueOf(s).booleanValue();
        s = getParameter("url");
        if (s != null) {
            try {
                url = new URL(s);
            } catch (MalformedURLException e1) {
                try {
                    url = new URL(getDocumentBase(), s);
                } catch (MalformedURLException e2) {
                    e2.printStackTrace();
                }
            }
        }
        Dimension d = size();
        screen = getGraphics();
        offImage = createImage(d.width, d.height);
        offScreen = offImage.getGraphics();
        ac = getAppletContext();
        if (prepareImage(image, this)) {
            makeGrayImage();
        }
    }

    public void paint(Graphics g) {
        Dimension d = size();
        if (d.width != offImage.getWidth(null) || d.height != offImage.getHeight(null)) {
            offImage = createImage(d.width, d.height);
            offScreen = offImage.getGraphics();
        }
        offScreen.setColor(bgColor);
        offScreen.fillRect(0, 0, d.width, d.height);
        if (current != null) {
            int w = current.getWidth(this);
            int h = current.getHeight(this);
            if (w <= 0 || h <= 0) return;
            int x = (d.width-w)/2;
            int y = (d.height-h)/2;
            offScreen.drawImage(current, x + (pushed?1:0), y + (pushed?1:0), null);
        }
        for (int i = 0; i <= border; i++) {
            offScreen.setColor((i==0)?Color.black:bgColor);
            offScreen.draw3DRect(i-(pushed?0:1), i-(pushed?0:1), d.width-2*i, d.height-2*i, !pushed);
        }
        g.drawImage(offImage, 0, 0, null);
    }

    public boolean mouseDown(Event evt, int x, int y) {
        pushed = true;
        current = image;
        paint(screen);
        return true;
    }

    public boolean mouseEnter(Event evt, int x, int y) {
        if (evt.target == this) {
            current = image;
            paint(screen);
            if (label != null || url != null) {
                ac.showStatus((label != null)?label:url.toString());
            }
        }
        return true;
    }

    public boolean mouseExit(Event evt, int x, int y) {
        pushed = false;
        current = gray;
        paint(screen);
        return true;
    }

    public boolean mouseUp(Event evt, int x, int y) {
        if (pushed) {
            pushed = false;
            Dimension d = size();
            if (x >= 0 && y >= 0 && x < d.width && y < d.height) {
                current = image;
                paint(screen);
                if (url != null) {
                    if (target != null) ac.showDocument(url, target);
                    else ac.showDocument(url);
                }
            } else {
                current = gray;
                paint(screen);
            }
        }
        return true;
    }

    private void makeGrayImage() {
        ImageFilter filter = new HSBImageFilter(hue, saturation, brightness);
        ImageProducer producer = new FilteredImageSource(image.getSource(), filter);
        gray = createImage(producer);
        prepareImage(gray, this);
    }

    public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h) {
        if ((flags & ALLBITS) != 0) {
            if (img == gray) {
                if (!reverse) {
                    current = gray;
                } else {
                    current = image;
                    image = gray;
                    gray = current;
                }
                repaint();
                return false;
            } else {
                makeGrayImage();
                return true;
            }
        }
        if ((flags & WIDTH) != 0) {
            repaint();
            return false;
        }
        if ((flags & HEIGHT) != 0) {
            repaint();
            return false;
        }
        return true;
    }
}

class HSBImageFilter extends RGBImageFilter {
    private float[] hsb = new float[3];
    private float hue;
    private float saturation;
    private float brightness;

    public HSBImageFilter(float hue, float saturation, float brightness) {
        canFilterIndexColorModel = true;
        this.hue = hue;
        this.saturation = saturation;
        this.brightness = brightness;
    }

    public int filterRGB(int x, int y, int rgb) {
        Color.RGBtoHSB((rgb & 0xFF0000)>>16, (rgb & 0xFF00)>>8, (rgb & 0xFF), hsb);
        float sat = hsb[1] * saturation;
        if (sat > 1.0f) sat = 1.0f;
        float bri = hsb[2] * brightness;
        if (bri > 1.0f) bri = 1.0f;
        return Color.HSBtoRGB((hue >= 0)?hue:hsb[0], sat, bri);
    }
}