/* 
 * XMoveElement.java --
 *
 *      animation stuff.
 *
 * Copyright 1995 Regents of the University of California
 * Permission to use, copy, modify, and distribute this
 * software and its documentation for any purpose and without
 * fee is hereby granted, provided that this copyright
 * notice appears in all copies.  The University of California
 * makes no representations about the suitability of this
 * software for any purpose.  It is provided "as is" without
 * express or implied warranty.
 *
 * rcsid = "$Header: /disks/barad-dur/now/rywang/src/java/classes/ryw/XMoveElement.java,v 1.8 1995/11/15 21:44:41 rywang Exp $ xFS (Berkeley)"
 */

package ryw;

import java.awt.*;
import java.awt.image.*;
import java.util.Vector;
import java.util.Enumeration;


/**
 * One action item to be placed on queue.
 * Some thread object will dequeue such an element and perform the
 * actual animation.
 * @see ryw.XMover
 * @see ryw.XMoverItem
 * @see ryw.XSleepElement
 */
public class XMoveElement extends XMoverItem {
    public int moveSteps = 60;
    public int moveSleep = 5;

    public XPanel0    parent;
    public Component  comps[];
    public Point      points[][];
    public boolean    remove;
    
    public boolean    added;
    public Dimension  dim;

    
    private void setOneComp (Component comp) {
	this.comps    = new Component[1];
	this.comps[0] = comp;
    }


    /*
     * move "comp" from "start" to "end".
     */
    public XMoveElement (XPanel0 parent, Component comp,
			 Point start, Point end, boolean remove) {
	this.parent   = parent;
	setOneComp (comp);
	points        = new Point[1][2];
	points[0][0]  = start;
	points[0][1]  = end;
	this.remove   = remove;
    }


    public XMoveElement (XPanel0 parent, Component comp,
			 Point start, Point end, boolean remove,
			 boolean added, Dimension dim) {
	this (parent, comp, start, end, remove);
	this.added = added;
	this.dim = dim;
    }

    
    /*
     * move "comp" from "start" to "end", via "mid".
     */
    public XMoveElement (XPanel0 parent, Component comp,
			 Point start, Point mid, Point end, boolean remove) {
	this.parent   = parent;
	setOneComp (comp);
	points        = new Point[1][3];
	points[0][0]  = start;
	points[0][1]  = mid;
	points[0][2]  = end;
	this.remove   = remove;
    }


    public XMoveElement (XPanel0 parent, Component comp,
			 Point start, Point mid, Point end, boolean remove,
			 boolean added, Dimension dim) {
	this (parent, comp, start, mid, end, remove);
	this.added = added;
	this.dim = dim;
    }


    /*
     * move bunch of elements from "start" to "ends".
     */
    public XMoveElement (XPanel0 parent, Component comps[],
			 Point start, Point ends[],
			 boolean remove, boolean added, Dimension dim) {

	int numComps = 0;

	if (comps != null)
	    numComps = comps.length;
	
	this.parent  = parent;
	this.comps   = comps;
	int numEnds  = ends.length;
	points       = new Point[numEnds][2];

	for (int i = 0; i < numEnds; i++) {
	    points[i][0] = start;
	    points[i][1] = ends[i];
	}

	this.remove = remove;
	this.added  = added;
	this.dim    = dim;
    }


    /*
     * move bunch of elements from "starts" to "ends".
     */
    public XMoveElement (XPanel0 parent, Component comps[],
			 Point starts[], Point ends[],
			 boolean remove, boolean added, Dimension dim) {

	this.parent   = parent;
	this.comps    = comps;
	int numPoints = starts.length;
	
	points        = new Point[numPoints][2];

	for (int i = 0; i < numPoints; i++) {
	    points[i][0] = starts[i];
	    points[i][1] = ends[i];
	}

	this.remove = remove;
	this.added  = added;
	this.dim    = dim;
    }

    
    /*
     * move bunch of elements from "starts" to "ends", with
     * customized move steps and move sleeps.
     */
    public XMoveElement (XPanel0 parent, Component comps[],
			 Point starts[], Point ends[],
			 boolean remove, boolean added, Dimension dim,
			 int moveSteps,  int moveSleep) {
	this (parent, comps, starts, ends, remove, added, dim);
	this.moveSteps = moveSteps;
	this.moveSleep = moveSleep;
    }

    
    /*
     * move bunch of elements from "starts" to "ends" via "mids".
     */
    public XMoveElement (XPanel0 parent, Component comps[],
			 Point starts[], Point mids[], Point ends[],
			 boolean remove, boolean added, Dimension dim) {

	this.parent   = parent;
	this.comps    = comps;
	int numPoints = starts.length;
	
	points        = new Point[numPoints][3];

	for (int i = 0; i < numPoints; i++) {
	    points[i][0] = starts[i];
	    points[i][1] = mids[i];
	    points[i][2] = ends[i];
	}

	this.remove = remove;
	this.added  = added;
	this.dim    = dim;
    }

    
    /*
     * move bunch of elements from "starts" to "ends" via "mids".
     */
    public XMoveElement (XPanel0 parent, Component comps[],
			 Point starts[], Point mids[], Point ends[],
			 boolean remove, boolean added, Dimension dim,
			 int moveSteps, int moveSleep) {
	this (parent, comps, starts, mids, ends, remove, added, dim);
	this.moveSteps = moveSteps;
	this.moveSleep = moveSleep;
    }

    
    /*
     * create a picture component,
     * and then move it from "start" to "end".
     */
    public XMoveElement (XPanel0 parent, Image image, Dimension dim,
			 Point start, Point end, boolean remove) {
	this (parent, null, start, end, remove, false, dim);
	XPict comp = new XPict (image);
	setOneComp (comp);
    }
	

    /*
     * create a picture component,
     * and then move it from "start" to "end", via "mid".
     */
    public XMoveElement (XPanel0 parent, Image image, Dimension dim,
			 Point start, Point mid, Point end, boolean remove) {
	this (parent, null, start, mid, end, remove, false, dim);
	XPict comp = new XPict (image);
	setOneComp (comp);
    }

    /*
     * create picture components,
     * and then move it from "start" to "ends".
     */
    public XMoveElement (XPanel0 parent, Image image, Dimension dim,
			 Point start, Point ends[], boolean remove) {
	this (parent, null, start, ends, remove, false, dim);
	int numComps = ends.length;
	XPict comps[] = new XPict[numComps];
	for (int i = 0; i < numComps; i++)
	    comps[i] = new XPict (image);
	this.comps = comps;
    }

    
    /*
     * move "comp" from "start" to "end",
     * and this is the nth step of the process.
     */
    private void moveOneOnce (Component comp, Point start, Point end,
			      int nth) {
	comp.move (start.x + nth * (end.x - start.x) / moveSteps,
		   start.y + nth * (end.y - start.y) / moveSteps);
	comp.paint (comp.getGraphics ());
	
	if (moveSleep > 0) {
	    try {
		Thread.sleep (moveSleep);
	    } catch (InterruptedException e) {
		return;
	    }
	}
    }
    

    /*
     * move a bunch of objects,
     * each of which might pass through a number intermediate points.
     */
    public void doMove () {

	XMoveElement move = this;

	int i, j, k;
	int numComps = move.comps.length;
	int numSegs   = move.points[0].length - 1;

	if (!move.added) {
	    for (k = 0; k < numComps; k++) {
		move.parent.add (move.comps[k], move.points[k][0], move.dim);
		move.added = true;
	    }
	}

	for (i = 0; i < numSegs; i++) {

	    for (j = 1; j <= moveSteps; j++) {

		for (k = 0; k < numComps; k++) {

		    moveOneOnce (move.comps[k],
				 move.points[k][i], move.points[k][i+1], j);

		}
	    }
	}

	if (move.remove) {
	    for (k = 0; k < numComps; k++) {
		move.parent.remove (move.comps[k]);
	    }
	}
    }
}

