import java.awt.*;
import java.awt.image.*;
import java.net.*;

// Freedom VR 2.0
// (C) 1997 Paul A. Houle (houle@msc.cornell.edu)
// http://www.honeylocust.com/vr/
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
// (or see http://www.gnu.org/copyleft/gpl.html)

public class RectangularHotspot implements fvr2Hotspot
{

   /*
    *
    * Set to <CODE>true</CODE> to enable debugging output;  since this
    * variable is <CODE>static final</CODE>,  the compiler will actually
    * remove debugging code from the .class file completely if this is
    * set to <CODE>false</CODE>
    *
    */

   static final boolean debug = false;

   int frame_i, frame_j;         // frame hotspot is in
   int x, y;			 // x,y coordinates of upper left corner
   int width, height;		 // width and height of hotspot
   URL mouseUpURL;		 // URL to go to when mouse is released
   String mouseUpTarget;	 // window to target URL to
   String mouseOverText;         // status line text when mouse goes over
   fvr2 myApplet;		 // the Applet Hotspot is bound to

   boolean isVisible[];          // is the hotspot visible in each state?
   Color boxColor[];	         // the color of the Hotspot box in each state
   int state;                    // the current state of the Hotspot

   final static int MOUSE_OUT = 0;     // the three states
   final static int MOUSE_OVER = 1;
   final static int MOUSE_DOWN = 2;

   public RectangularHotspot()
   {
      this.frame_i = -1;
      this.frame_j = -1;
      this.x = 0;
      this.y = 0;
      this.width = 0;
      this.height = 0;
      this.state = MOUSE_OUT;
      mouseUpTarget = null;
      mouseOverText = null;
      isVisible = new boolean[3];
      setVisibleMouseOut(true);
      setVisibleMouseOver(true);
      setVisibleMouseDown(true);
      boxColor = new Color[3];
      boxColor[MOUSE_OUT] = Color.black;
      boxColor[MOUSE_OVER] = Color.white;
      boxColor[MOUSE_DOWN] = Color.red;
   }

   /**
    *
    * This method is called when the Rectangular Hotspot is initialized;
    * it tells the Hotspot which applet it's attached to.
    *
    * @param applet the applet to attach
    **/
   
   public void attachApplet(fvr2 applet)
   {
      myApplet = applet;
   }

   /**
    *
    * <B>Javascript binding:</B>
    *
    * Set the frame in which the Hotspot is in.
    *
    * @param i vertical frame index
    * @param j vertical frame index
    *
    **/

   public void setFrame(int i, int j)
   {
      this.frame_i = i;
      this.frame_j = j;
   }

   /**
    *
    * <B>Javascript binding:</B>
    *
    * Set the upper left corner of the Hotspot
    *
    * @param x vertical frame index
    * @param y vertical frame index
    *
    **/

   public void setCorner(int x, int y)
   {
      this.x = x;
      this.y = y;
   }

   /**
    *
    * <B>Javascript binding:</B>
    *
    * Set the size of the hotspot
    *
    * @param width width in pixels
    * @param height height in pixels
    *
    **/


   public void setSize(int width, int height)
   {
      this.width = width;
      this.height = height;
   }

   /**
    *
    * <B>Javascript binding:</B>
    *
    * Set the URL that we jump to when the mouse is released
    *
    * @param s string specifying a URL;  can be either an absolute URL
    * or a URL relative to the document base of the applet.
    * 
    **/

   public void setMouseUpURL(String s) throws MalformedURLException
   {
      mouseUpURL = new URL(myApplet.getDocumentBase(),s);
   }

   /**
    *
    * <B>Javascript binding:</B>
    *
    * Set the target window or frame for the mouseUpURL.  If this isn't
    * specified,  the default is to pop the URL up in the same frame as
    * the applet.  This works the same as the <CODE>TARGET</CODE> option
    * of the <CODE>&lt;A&gt;</CODE> tag in HTML.
    *
    * @param s string specifying a URL;  can be either an absolute URL
    * or a URL relative to the document base of the applet.
    * 
    **/

   public void setMouseUpTarget(String s)
   {
      mouseUpTarget = s;
   }

   /**
    *
    * <B>Javascript binding:</B>
    *
    * Set the text which appears in the status bar when the mouse moves over
    * the Hotspot.
    *
    * @param s text to appear in the status bar
    * 
    **/

   public void setMouseOverText(String s)
   {
      mouseOverText = s;
   }

   /**
    *
    * <B>Javascript binding:</B>
    *
    * Is the Hotspot visible when the mouse is away from it?
    * 
    * @param b
    * 
    **/

   public void setVisibleMouseOut(boolean b)
   {
      isVisible[MOUSE_OUT] = b;
   }

   /**
    *
    * <B>Javascript binding:</B>
    *
    * Is the Hotspot visible when the mouse is above it but not depressed?
    * 
    * @param b
    * 
    **/

   public void setVisibleMouseOver(boolean b)
   {
      isVisible[MOUSE_OVER] = b;
   }

   /**
    *
    * <B>Javascript binding:</B>
    *
    * Is the Hotspot visible when the mouse is above it and depressed?
    * 
    * @param b
    * 
    **/

   public void setVisibleMouseDown(boolean b)
   {
      isVisible[MOUSE_DOWN] = b;
   }

   /**
    * Make the hotspot completely invisible.  This is equivalent to calling
    * <CODE><PRE>
    * hotspot.setVisibleMouseOut(false);
    * hotspot.setVisibleMouseOver(false);
    * hotspot.setVisibleMouseDown(false);
    * </PRE></CODE>
    *
    **/
 
   public void beInvisible()
   {
      for(int i = 0;i < isVisible.length;i++)
         isVisible[i] = false;
   }

   /**
    *
    * Colors are set with a hexadecimal value (#RRGGBB),  the same format
    * used for setting colors in HTML.  
    *
    * @param c the color of the Hotspot's box when the mouse is away from it
    *
    **/

   public void setMouseOutColor(String c) throws NumberFormatException
   {
      boxColor[MOUSE_OUT] = parseColorString(c);
   }

   /**
    *
    * @param c the color of the Hotspot's box when the mouse is above it
    * but not depressed
    *
    **/


   public void setMouseOverColor(String c) throws NumberFormatException
   {
      boxColor[MOUSE_OVER] = parseColorString(c);
   }

   /**
    *
    * @param c the color of the Hotspot's box when the mouse is above it
    * and depressed
    *
    **/

   public void setMouseDownColor(String c) throws NumberFormatException
   {
      boxColor[MOUSE_DOWN] = parseColorString(c);
   }

   /**
    * The following methods implement <CODE>fvr2Hotspot</CODE>;  look
    * there for documentation.  These will not be of interest to you if
    * you're only writing Java or Javascript to place Hotspots into a
    * world.
    *
    * @see fvr2Hotspot.
    * 
    **/

   public void mouseOver()
   {
      if(debug)
         System.out.println("RectangularHotspot.mouseOver() called.");
      setState(MOUSE_OVER);
      myApplet.setCursor(Frame.DEFAULT_CURSOR);
      if(mouseOverText != null)
         myApplet.getAppletContext().showStatus(mouseOverText);
   }


   public void mouseOut()
   {
      setState(MOUSE_OUT);
      myApplet.getAppletContext().showStatus(null);
   }

   public void mouseDown()
   {
      setState(MOUSE_DOWN);
   }

   public void mouseUp()
   {
      setState(MOUSE_OVER);
      System.out.println("Mouse up event over hotspot!");
      if(mouseUpTarget == null)
         myApplet.getAppletContext().showDocument(mouseUpURL);
      else
         myApplet.getAppletContext().showDocument(mouseUpURL,mouseUpTarget);
   }

   public boolean isMouseOver(int frame_i, int frame_j, int x, int y)
   {
      // am I in the frame?

      if(!isInFrame(frame_i,frame_j))
         return false;

      // is the cursor within my rectangle?
      return (x > this.x && x < this.x + width && y > this.y && y < this.y + height);
   }

   public boolean isInFrame(int frame_i, int frame_j)
   {
      return (this.frame_i == frame_i && this.frame_j == frame_j);
   }

   public void paint(Graphics g)
   {
      if(debug)
      {
         System.out.println("RectangularHotspot.paint() called");
         System.out.println("state=" + state);
         System.out.println("isVisible[state]=" + isVisible[state]);
         System.out.println("boxColor[state]=" + boxColor[state]);
      }

      if(isVisible[state])
      {
         g.setColor(boxColor[state]);
         g.drawRect(x,y,width,height);
      }

   }

   // and a few non-public methods for internal consumption.

   void setState(int state)
   {
      // to erase an existing box it's necessary (sigh) to
      // repaint the applet,  otherwise we just paint ourself

      if(isVisible[this.state] && !isVisible[state])
      {
         this.state = state;
         myApplet.repaint();
      }
      else
      {
         Graphics g = myApplet.getGraphics();
         this.state = state;
         paint(g);
      }
   }


   static Color parseColorString(String s) throws NumberFormatException
   {
      int intvalue;
      intvalue = Integer.parseInt(s,16);
      return new Color(intvalue);
   }



}






