//resides in default package.

/*
 * (C) ELRIDEV SOFTWARE, 1999. ALL RIGHTS RESERVED.
 * THIS SOFTWARE IS THE PROPERTY OF ELRIDEV SOFTWARE, YOU CAN USE THIS SOFTWARE
 * ON YOUR WEBPAGE (OR USE THE SOURCE FOR LEARNING JAVA), IT PROVIDED AS AN EXAMPLE,
 * WITH NO WARRANTIES WHATSOEVER, SHOULD ANY DAMAGE OCCUR FROM THE USE OF THIS
 * PRODUCT ELRIDEV WILL BE HELD IN NO WAY LIABLE FOR DAMAGES.
 * YOU CAN ALSO MODIFY THIS CODE FOR YOU OWN PURPOSES, HOWEVER ONCE THIS IS DONE
 * YOU MUST INDICATE THAT THESE CHANGES HAVE BEEN MADE, SHOULD YOU WISH IT REMAIN
 * FREELY AVAILABLE.
 */

import java.applet.*;
import java.awt.*;
import java.net.*;

/**
 * click button, used on a html page as an applet, it will rotate between 2
 * images, looking like the image is turning round. the image is configured
 * by applet parameters. these are as follows:
 *
 * ClickNoise the au file to play when clicked.
 * EnterNoise the au file to play when mouse is over item
 * ImageSrc the first image to rotate
 * ImageDest the other image to rotate
 * ImageBack use this to set an image background
 * ImageBkCol use this to set a background colour
 * URLName the name of the URL associated with the button
 *
 * @version Thor
 * @author Dave Cherry
 */
public class ClickBtn extends Applet implements Runnable
{
	// THREAD SUPPORT:
	//		m_ClickBtn	is the Thread object for the applet
	//--------------------------------------------------------------------------
	private Thread	 m_ClickBtn = null;

	final int mainZoomIn=1;
	final int mainZoomOut=2;
	final int destZoomIn=3;
	final int destZoomOut=4;
	final int restartZoom=5;

	// all my class specifics are here
	AudioClip audClicked,audEntered;
	Image     imgMain,imgDest;
	boolean   bEntered,bClicked;
	double    dfCurrentMag,magFactor=0.1;
	int		  iCurrentState;
	Image	  offScreenImage;
	Image	  backImage;

	// PARAMETER SUPPORT:
	//		Parameters allow an HTML author to pass information to the applet;
	// the HTML author specifies them using the <PARAM> tag within the <APPLET>
	// tag.  The following variables are used to store the values of the
	// parameters.
    //--------------------------------------------------------------------------

    // Members for applet parameters
    // <type>       <MemberVar>    = <Default Value>
    //--------------------------------------------------------------------------
	private String m_ClickNoise = "";
	private String m_EnterNoise = "";
	private String m_ImageSrc = "";
	private String m_ImageDest = "";
	private String m_ImageBack = "";
	private String m_ImageBCol = "";
	private String m_URL = "";
	private Color colBCol;
	private boolean bWhiteBk=false;

    // Parameter names.  To change a name of a parameter, you need only make
	// a single change.  Simply modify the value of the parameter string below.
    //--------------------------------------------------------------------------
	private final String PARAM_ClickNoise = "ClickNoise";
	private final String PARAM_EnterNoise = "EnterNoise";
	private final String PARAM_ImageSrc = "ImageSrc";
	private final String PARAM_ImageDest = "ImageDest";
	private final String PARAM_ImageBack = "ImageBack";
	private final String PARAM_ImageBCol = "ImageBkCol";
	private final String PARAM_URL = "URLName";

    /**
     * empty constructor, see init
     */
	public ClickBtn()
	{
	}

    /**
     * read in all the parameters, and get the applet ready to start rotating
     * between the 2 images
     */
	public void init()
	{
		// PARAMETER SUPPORT
		//		The following code retrieves the value of each parameter
		// specified with the <PARAM> tag and stores it in a member
		// variable.
		//----------------------------------------------------------------------
		String param;
		colBCol = Color.white;
		// ClickNoise: when clicked
		//----------------------------------------------------------------------
		param = getParameter(PARAM_ClickNoise);
		if (param != null)
			m_ClickNoise = param;

		// EnterNoise: when entered
		//----------------------------------------------------------------------
		param = getParameter(PARAM_EnterNoise);
		if (param != null)
			m_EnterNoise = param;

		// ImageSrc: The main image name
		//----------------------------------------------------------------------
		param = getParameter(PARAM_ImageSrc);
		if (param != null)
			m_ImageSrc = param;

		// ImageDest: The click me image name
		//----------------------------------------------------------------------
		param = getParameter(PARAM_ImageDest);
		if (param != null)
			m_ImageDest = param;

		param = getParameter(PARAM_URL);
		if (param != null)
			m_URL = param;

		// ImageBack: The background image name
		//----------------------------------------------------------------------
		param = getParameter(PARAM_ImageBack);
		if (param != null)
			m_ImageBack = param;
		else // you cant have both
		{
			// ImageBack: The background colour
			//----------------------------------------------------------------------
			param = getParameter(PARAM_ImageBCol);
			if (param != null)
			{
				m_ImageBCol = param;

				if(param.equalsIgnoreCase("gray")) colBCol = Color.lightGray;
				else if(param.equalsIgnoreCase("black")) colBCol = Color.black;
				else if(param.equalsIgnoreCase("red")) colBCol = Color.red;
				else // decode as rrggbb in hex??
				{
					bWhiteBk=true;
				}
			}
			else bWhiteBk=true;
		}

        // If you use a ResourceWizard-generated "control creator" class to
        // arrange controls in your applet, you may want to call its
        // CreateControls() method from within this method. Remove the following
        // call to resize() before adding the call to CreateControls();
        // CreateControls() does its own resizing.
        //----------------------------------------------------------------------
//    	resize(320, 240);
		audClicked = getAudioClip(getDocumentBase(),m_ClickNoise);
		audEntered = getAudioClip(getDocumentBase(),m_EnterNoise);
		
		try
		{
			Image Back=backImage;
			if(m_ImageBack.length()!=0) Back= getImage(getDocumentBase(),m_ImageBack);
			MediaTracker mt=new MediaTracker(this);
			imgMain = getImage(getDocumentBase(),m_ImageSrc);
			imgDest = getImage(getDocumentBase(),m_ImageDest);
			mt.addImage(imgMain,0);
			mt.addImage(imgDest,1);
			if(m_ImageBack.length()!=0) mt.addImage(Back,2);
			mt.waitForAll(90000);

			dfCurrentMag=0.;
			iCurrentState=1;

			Dimension dims=size();
			offScreenImage = createImage(dims.width,dims.height);

			// make the background.
			if(m_ImageBack.length()!=0) 
			{
				backImage = createImage(dims.width,dims.height);
				Graphics gfx = backImage.getGraphics();
				for(int iX=0;iX<backImage.getWidth(this);iX+=Back.getWidth(this))
				{
					for(int iY=0;iY<backImage.getHeight(this);iY+=Back.getHeight(this))
					{
						gfx.drawImage(Back,iX,iY,Color.white,this);
					}
				}
			}
		}
		catch(InterruptedException e)
		{
			showStatus("Interupted loading images!");
		}
	}


	/** move on the current state value, check if its looped. */
	protected void BumpCurrentState()
	{
		if(bClicked==true&&iCurrentState==mainZoomIn) return;
		iCurrentState++;
		if(iCurrentState==restartZoom) iCurrentState=mainZoomIn;
	}

    public void update(Graphics g)
    {
        paint(g);
    }
    /** draw my offscreen image, avoids paint problems. */
	public void paint(Graphics gfx)
	{
		gfx.drawImage(offScreenImage,0,0,Color.white,this);
	}

    /**
     * draws a 3d rectangle, of a width and height, raised or indented
     * @param g the device to draw on
     * @param x the starting x location
     * @param y the starting y location
     * @param w the width of the rectangle
     * @param h the height of the rectangle
     * @param raised true to draw a raised rectangle, false indented
     */
	protected void myDraw3DRect(Graphics g,int x,int y,int w,int h,boolean raised)
	{
		Color wht;
		if(bWhiteBk)
			wht=Color.lightGray;
		else
			wht=Color.white;

		h+=y;
		w+=x;

		g.setColor(((raised)?wht:Color.darkGray));
		g.drawLine(x,h,x,y);
		g.drawLine(x,y,w,y);
		g.setColor(((!raised)?wht:Color.darkGray));
		g.drawLine(x,h,w,h);
		g.drawLine(w,h,w,y);
	}

    /**
     * redraw the offscreen image, and bump the current state of the rotation
     */
	protected void redrawAll()
	{
		// get the images size..
		Dimension dims=size();

		// double buffer of the image.
		Graphics g = offScreenImage.getGraphics();
		if(m_ImageBack.length()!=0)
			g.drawImage(backImage,0,0,Color.white,this);
		else
		{
			g.setColor(colBCol);
			g.fillRect(0,0,dims.width,dims.height);
		}

		// see which direction we move in.
		if(iCurrentState==mainZoomIn||iCurrentState==destZoomIn)
		{

			if(dfCurrentMag>1.0)
				BumpCurrentState();
			else
				dfCurrentMag+=magFactor;
		}
		else
		{
			if(dfCurrentMag<=0.01)
				BumpCurrentState();
			else
				dfCurrentMag-=magFactor;
		}

		dfCurrentMag=Math.max(0.001,Math.min(dfCurrentMag,1.001));

		int ImgHeight=(int)((double)(dims.height-4)*dfCurrentMag);
		int ImgStart =(dims.height-ImgHeight)/2;

		if(iCurrentState==mainZoomIn||iCurrentState==mainZoomOut)
			g.drawImage(imgMain,2,ImgStart,dims.width-4,ImgHeight,this);
		else
			g.drawImage(imgDest,2,ImgStart,dims.width-4,ImgHeight,this);


		if(bEntered)
		{
			myDraw3DRect(g,1,1,dims.width-4,dims.height-4,!bClicked);
			myDraw3DRect(g,0,0,dims.width-2,dims.height-2,!bClicked);
		}
		else if(m_ImageBack.length()!=0)
		{
			myDraw3DRect(g,0,0,dims.width-2,dims.height-2,!bClicked);
		}

		repaint();
	}

    /** start applet and create new thread */
	public void start()
	{
		if (m_ClickBtn == null)
		{
			m_ClickBtn = new Thread(this);
			m_ClickBtn.start();
		}
	}

    /** kill the thread, were done */
	public void stop()
	{
		if (m_ClickBtn != null)
		{
			m_ClickBtn.stop();
			m_ClickBtn = null;
		}
	}

    /** stay in a loop repainting, the screen and delaying a while */
	public void run()
	{
		while (true)
		{
			try
			{
				redrawAll();
				if(iCurrentState==mainZoomIn&&dfCurrentMag>=1.00)
					Thread.sleep(4000);
				else
					Thread.sleep(50);
			}
			catch (InterruptedException e)
			{
				stop();
			}
		}
	}

    /** on a mouse down we draw the object "pressed" and play the click sound */
	public boolean mouseDown(Event evt, int x, int y)
	{
		// TODO: Place applet mouseDown code here

		audClicked.play();
		bClicked=true;
		redrawAll();
		if(iCurrentState>mainZoomOut)
			iCurrentState=destZoomOut;
		else
			iCurrentState=mainZoomIn;
		magFactor=0.5;

		return true;
	}

    /** on a mouse up we draw the object "normally" and goto the URL */
	public boolean mouseUp(Event evt, int x, int y)
	{
		bClicked=false;
		redrawAll();
		iCurrentState=mainZoomOut;
		magFactor=0.1;

		try
		{
			URL anchor = new URL(getDocumentBase(),m_URL);
			getAppletContext().showDocument(anchor);
		}
		catch(MalformedURLException e)
		{
			showStatus("the URL " + m_URL +" is invalid");
		}

		return true;
	}

    /** when the mouse is entered, show status of goto: URLPage., then
     * set the cursor to a hand pointer. Also play the entered sound */
	public boolean mouseEnter(Event evt, int x, int y)
	{
		// TODO: Place applet mouseEnter code here
		audEntered.play();
		bEntered=true;
		redrawAll();
		showStatus("Goto page: " + m_URL);
        setCursor(new Cursor(Cursor.HAND_CURSOR));
		return true;
	}

    /** when exited reset the cursor and unset the entered control condition */
	public boolean mouseExit(Event evt, int x, int y)
	{
		// TODO: Place applet mouseExit code here
		bEntered=false;
		redrawAll();
		showStatus(null);
        setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
		return true;
	}

}

