/**************************************************************************
* Copyright (c) 1996 Jim Crossley
*
* Although it's unlikely that anyone would actually want it,
* permission is hereby granted, without written agreement and
* without license or royalty fees, to use, copy, modify, and
* distribute this software and its documentation for any purpose,
* provided that the above copyright notice and the following three
* paragraphs appear in all copies of this software, its documentation
* and any derivative work.
*
* In no event shall Jim Crossley or Automated Design Systems, Inc. be
* liable to any party for direct, indirect, special, incidental, or
* consequential damages arising out of the use of this software and
* its documentation.
*
* The software provided hereunder is on an "as is" basis, and neither
* Jim Crossley nor Automated Design Systems, Inc. has any obligation
* to provide maintenance, support, updates, enhancements, or modifications.
*
* Derived or altered versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
***************************************************************************/
package dots;

import java.awt.*;
import java.util.*;
import java.applet.*;
import utilities.AppletShell;

/**
 * Applet that allows a user to create and manipulate DottedLine objects.
 * Both the DottedLine speed and decay may be adjusted through the use of
 * two scrollbars, appropriately named "speed" and "decay".
 * <p>
 * The applet's size should be at least 300x300.
 *
 * @author Jim Crossley
 * @version 1.0, 10/17/1996
 */
public class DottedLineLand extends Applet {
    private static final int MAX_DELAY = 1000;
    private static final int MAX_DECAY = 10;
    private static final int DOT_SIZE = 10;
    Point p,q; /** The beginning and ending points of a DottedLine. */
    Vector vect; /** This contains the DottedLines created within the applet. */
    Scrollbar speed, decay; /** These allow the user to manipulate the DottedLines. */

    /**
     * Initialize the applet -- create the scrollbars and the clear button.
     * The DottedLines assume a black background -- the dots "decay" to that color.
     * The values of the scrollbars default to their maximum.
     */
    public void init() {
        super.init();
        setLayout(new FlowLayout());
        Panel p = new Panel();
        p.setLayout(new GridLayout(2,1));
        p.setBackground(Color.white);

        Panel p1 = new Panel();
        p1.add(new Button("Clear"));
        p.add(p1);

        Panel p2 = new Panel();
        p2.add(new Label("Speed:"));
        speed = new Scrollbar(Scrollbar.HORIZONTAL, MAX_DELAY-100, 0, 0, MAX_DELAY);
        p2.add(speed);
        speed.setPageIncrement(100);
        speed.setLineIncrement(50);
        p2.add(new Label("Decay:"));
        decay = new Scrollbar(Scrollbar.HORIZONTAL, MAX_DECAY, 0, 1, MAX_DECAY);
        p2.add(decay);
        p.add(p2);

        add(p);
        setBackground(Color.black);
        vect = new Vector();
    }

    /**
     * Give the user some idea of what's possible.
     */
    public void start() {
        Dimension d = this.size();
        int dx = d.width/3;
        int dy = d.height*2/3;
        int x = d.width/2;
        int y = d.height - d.height/10;
        Point p = new Point(x,y);
        vect.addElement(new DottedLine(p, new Point(x,y-dy), DOT_SIZE, Color.white, MAX_DELAY - speed.getValue(), MAX_DECAY - decay.getValue(), this));
        vect.addElement(new DottedLine(p, new Point(x-dx,y), DOT_SIZE, Color.blue, MAX_DELAY - speed.getValue(), MAX_DECAY - decay.getValue(), this));
        vect.addElement(new DottedLine(p, new Point(x+dx,y), DOT_SIZE, Color.red, MAX_DELAY - speed.getValue(), MAX_DECAY - decay.getValue(), this));
        vect.addElement(new DottedLine(p, new Point(x-dx,y-dy), DOT_SIZE, Color.red, MAX_DELAY - speed.getValue(), MAX_DECAY - decay.getValue(), this));
        vect.addElement(new DottedLine(p, new Point(x+dx,y-dy), DOT_SIZE, Color.blue, MAX_DELAY - speed.getValue(), MAX_DECAY - decay.getValue(), this));
    }

    /**
     * Stop the threads and remove the DottedLine objects from the vector.
     */
    public void stop() {
        Enumeration enum = vect.elements();
        while (enum.hasMoreElements()) {
            DottedLine d = (DottedLine)enum.nextElement();
            d.stop();
        }
        vect.removeAllElements();
        repaint();
    }

    /**
     * Handle the "Clear" button.  Stop all DottedLine threads when clicked.
     */
    public boolean action(Event e, Object arg) {
        if (arg.equals("Clear")) {
            stop();
            return true;
        }
        else return super.action(e,arg);
    }

    /**
     * Handle the scrollbar events.  This allows an operator to dynamically change
     * the attributes of all active DottedLines.
     */
    public boolean handleEvent(Event e) {
        if (e.target == speed) {
            Enumeration enum = vect.elements();
            while (enum.hasMoreElements()) {
                DottedLine d = (DottedLine)enum.nextElement();
                d.setDelay(MAX_DELAY-speed.getValue());
            }
            return true;
        }
        if (e.target == decay) {
            Enumeration enum = vect.elements();
            while (enum.hasMoreElements()) {
                DottedLine d = (DottedLine)enum.nextElement();
                d.setDecay(MAX_DECAY - decay.getValue());
            }
            return true;
        }
        return super.handleEvent(e);
    }

    /**
     * The user creates DottedLines by dragging the mouse.  On the mouseDown event,
     * we establish the beginning of the line at point p.
     */
	public boolean mouseDown(Event e, int x, int y) {
        p = new Point(x,y);
        q = p; // set q just in case the user releases the click immediately.
	    return true;
	}

	/**
	 * As the user drags the mouse, we continuously reset the point q and draw a
	 * guideline from p to q.
	 */
	public boolean mouseDrag(Event e, int x, int y) {
	    Graphics g = this.getGraphics();
	    g.setColor(this.getBackground());
	    g.drawLine(p.x,p.y,q.x,q.y); // erase the previous guideline.
	    q = new Point(x,y);
	    g.setColor(Color.red);
	    g.drawLine(p.x,p.y,q.x,q.y);
	    g.dispose();
	    return true;
	}

	/**
	 * At this point we can create a DottedLine -- we have a beginning and an end.
	 * The DottedLine's color is randomly determined.
	 */
	public boolean mouseUp(Event e, int x, int y) {
	    Graphics g = this.getGraphics();
	    g.setColor(this.getBackground());
	    g.drawLine(p.x,p.y,q.x,q.y); // erase the guideline.
	    g.dispose();

	    vect.addElement(new DottedLine(p, new Point(x,y), DOT_SIZE, new Color((int)(Integer.MAX_VALUE * Math.random())), MAX_DELAY - speed.getValue(), MAX_DECAY - decay.getValue(), this));
	    return true;
	}

    /**
     * Provide standalone functionality
     */
	public static void main(String[] args) {
        new AppletShell(new DottedLineLand(), 400, 400);
	}
}


