
/*
 * Copyright (c) 1998, 1999 Kevan Stannard. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
 * without fee is hereby granted. 
 * 
 * Please note that this software comes with
 * NO WARRANTY 
 *
 * BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED
 * BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
 * PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
 * TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
 * THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 
 * 
 * IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER
 * PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
 * INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
 * THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED
 * BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
 * OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * HISTORY
 *   1998.xx.xx  kevan  Created
 *   1999.05.11  kevan  Modified button link to allow simple relative references.
 */

import java.awt.*;
import java.applet.Applet;
import java.util.Vector;
import java.net.URL;

public class JZOOButtonRing
extends Applet
implements Runnable
{
    final int DEFAULT_RADIUS = 100;

    Vector items = new Vector();
    Thread thread = null;

    int appletWidth = 0;
    int appletHeight = 0;

    int radius = DEFAULT_RADIUS;
    int newRadius = radius;
    boolean follow = false;

    int centerX = 0;
    int centerY = 0;

    final double MAX_THETA = 2 * Math.PI;
    final double ONE_DEGREE = 2 * Math.PI / 360;

    double currTheta = 0;
    double deltaTheta = 0;

    Image buffer = null;
    Graphics bufferGraphics = null;

    Image bgImage = null;

    boolean ready = false;

    MediaTracker tracker = new MediaTracker(this);

    JZOOButton currButton = null;

    String oldStatus = "";
    String currStatus = "";

    public void init()
    {
        // get applet details

        appletWidth = size().width;
        appletHeight = size().height;

        centerY = appletHeight / 2;

        buffer = createImage(appletWidth, appletHeight);
        bufferGraphics = buffer.getGraphics();

        // get images

        String imagePath = null;
        int i=1;
        while (true)
        {
            imagePath = getParameter("image" + i);
            if (imagePath == null)
            {
                break;
            }

            Image image = getImage(getCodeBase(), imagePath);
            tracker.addImage(image, 0);

            JZOOButton button = new JZOOButton(this);
            button.addImage(image);
            items.addElement(button);

            String link = getParameter("link" + i);
            if (link != null)
            {
                try
                {
                    if ( link.startsWith("http") || link.startsWith("HTTP") ) {
                        button.url = new URL(link);
                    }
                    else {
                        button.url = new URL(getCodeBase(), link);
                    }
                }
                catch (Exception e)
                {
                    System.out.println("Invalid url: " + link);
                }
            }

            String target = getParameter("target" + i);
            System.out.println("found target " + i + ": " + target);
            if (target != null) {
                button.target = target;
                System.out.println(i + " button.target " + button.target);
            }

 
            i++;
        }

        imagePath = getParameter("bgimage");
        if (imagePath != null)
        {
            bgImage = getImage(getCodeBase(), imagePath);
            tracker.addImage(bgImage, 0);
        }

        tracker.checkAll(true);

        // other parameters

        String param;
        param = getParameter("radius");
        if (param != null)
        {
            try
            {
                newRadius = Integer.parseInt(param);
            }
            catch (Exception e)
            {
                newRadius = DEFAULT_RADIUS;
            }
        }

        param = getParameter("startradius");
        if (param != null)
        {
            try
            {
                radius = Integer.parseInt(param);
            }
            catch (Exception e)
            {
                radius = DEFAULT_RADIUS;
            }
        }

        param = getParameter("follow");
        if (param != null)
        {
            follow = param.equalsIgnoreCase("true");
        }

        param = getParameter("centerx");
        if (param != null)
        {
            try
            {
                centerX = Integer.parseInt(param);
            }
            catch (Exception e)
            {
                centerX = appletWidth / 2;
            }
        }

        param = getParameter("centery");
        if (param != null)
        {
            try
            {
                centerY = Integer.parseInt(param);
            }
            catch (Exception e)
            {
                centerY = appletHeight / 2;
            }
        }

        // initialise

        deltaTheta = (double) MAX_THETA / items.size();
    }

    private boolean imagesLoaded()
    {
        return tracker.checkAll();
    }

    public void start()
    {
        if (thread == null)
        {
            thread = new Thread(this);
            thread.start();
        }
    }

    public void stop()
    {
        if (thread != null && thread.isAlive())
        {
            thread.stop();
            thread = null;
        }
    }

    public void update(Graphics g) 
    {
        paint(bufferGraphics);
        g.drawImage(buffer, 0, 0, this);
    }

    public void paint(Graphics g)
    {
        if (ready)
        {
            // clear screen

            g.setColor(Color.black);
            g.fillRect(0,0,appletWidth, appletHeight);

            // draw bgImage

            if (bgImage != null)
            {
                g.drawImage( bgImage, 0, 0, this);
            }

            // draw buttons

            for (int i=0; i<items.size(); i++)
            {
                JZOOButton button = (JZOOButton) items.elementAt(i);
                g.drawImage(
                    button.image,
                    centerX + (int) Math.round(button.x),
                    centerY + (int) Math.round(button.y),
                    this);
            }
        }
    }

    public void run()
    {
        while (true)
        {

            // check if images have loaded

            if (ready)
            {
                // move images

                double tempTheta = currTheta;
                for (int i=0; i<items.size(); i++)
                {
                    JZOOButton button = (JZOOButton) items.elementAt(i);
                    button.x = radius * Math.cos(tempTheta);
                    button.y = radius * Math.sin(tempTheta);
                    tempTheta += deltaTheta;
                }
                currTheta += ONE_DEGREE ;

                // check radius

                if (newRadius != radius) 
                {
                    if (newRadius < radius)
                    {
                        radius--;
                    }
                    else 
                    {
                        radius++;
                    }
                }
            }
            else
            {
                ready = imagesLoaded();
            }

            // display

            repaint();

            try
            {
                thread.sleep(50);
            }
            catch (Exception e)
            {
                System.err.println(e);
            }
        }
    }

    public boolean mouseDown(Event e, int xpos, int ypos)
    {
        if (currButton != null)
        {
            if (currButton.target == null) {
                getAppletContext().showDocument(currButton.url);
            }
            else {
                System.out.println(currButton.target);
                getAppletContext().showDocument(currButton.url, currButton.target);
            }
        }

        return true;
    }

    public boolean mouseMove(Event e, int xpos, int ypos)
    {
        if (follow)
        {

            // determine new radius

            int x = Math.abs(centerX - xpos);
            int y = Math.abs(centerY - ypos);

            newRadius = (int) Math.round(Math.sqrt(x*x + y*y));

            return true;
        }

        for (int i=0; i<items.size(); i++)
        {
            JZOOButton b = (JZOOButton) items.elementAt(i);
            int x = (int) b.x;
            int y = (int) b.y;
            int w = b.getWidth();
            int h = b.getHeight();

            Rectangle r = new Rectangle(x + centerX, y + centerY, w, h);
            if (r.inside(xpos, ypos))
            {
                currButton = b;
                newStatus(b.url.toString());
                return true;
            }
        }

        resetStatus();
        currButton = null;

        return true;
    }

    private void newStatus(String newStatus)
    {
        if (!currStatus.equals(newStatus))
        {
            oldStatus = currStatus;
            currStatus = newStatus;
            showStatus(currStatus);            
        }
    }

    private void resetStatus()
    {
        currStatus = oldStatus;
        showStatus(currStatus);
    }
}


