package primitives.frames;
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.util.Enumeration ;
/**
*Frames is an abstract applet class which provides a standart GUI and provides 
*common methods used by its ofsprings.
*A Frames consists of a predefined number of frames with a label attached to each frame.
*The number of frames created depends on the parameter <big>frames</big> passed to the
*Frames object from the applet Tag on the html source. To set the labels under each frame set the 
*label-<i>i</i>parameter.
*Another common task provided by the Frames class is the creation of a thread which carries
* the refreshing of the Frames objects located in the same html page of this object.
*@author Dori Eldar.
*/
public abstract class Frames extends Applet implements Runnable,MouseListener{			       
	/**
	*Array of the Label objects.
	*/
	public Label[] labels;
	/**
	*Array of DrawFrame Objects
	*@see DrawFrame
	*/
	public DrawFrame[] frames;
	/**
	*Number of frames contained by the applet.
	*[should be hidden.]
	*/
	public int frameNumber = 1;
	/**
	*[?]
	*/
	protected  int index;
	/**
	*Number of miliseconds to wait between refreshing the Frames object for which run=true.
	*@see #run
	*/
	protected int waitFor;
	/**
	*A Frames objects signals the refreshing thread it should call its changeFrames method
	*by setting this flag to true.
	*@see #changeFrames
	*/
	public boolean run	= false;

	int j = 0;
	/**
	* a thread object used to refresh Frames object located in appletContext of this object.
	* declaring <code>t</code> static assures only one thread is created to refresh all applets.
	*/
	static protected Thread t = null;
	/**
	*@deprecated
	*/
	public boolean threadSuspended = false;
	/**
	*activates the static thread t.
	*you can set a "waitFor" parameter at the applet Tag to specify the number of milliseconds
	*to wait between refresh.
	*/
	protected void startThread(){ 
			waitFor = getParam("waitFor",60);
			t = new Thread(this);
			t.start();
	}
	/**
	*calls the changeFrame method of all Frames object on this appletContext with the run flag
	*set to true.
	*@see #changeFrames
	*/
	public void run(){
		Thread nonInterActive = Thread.currentThread();
		while (t == nonInterActive)             
		try{
			for (Enumeration e = getAppletContext().getApplets() ; e.hasMoreElements() ;) {
				   try{
					Applet applet1 = (Applet)(e.nextElement());
					if ((applet1	instanceof Frames)&&((Frames)applet1).run){
						try{
							((Frames)applet1).changeFrames();
						}catch(RuntimeException re){}
					}
				    }catch (Throwable eg){}	
			}
			j = j+waitFor;
			if(j>3000){
				j = 0;
				System.gc();
			}
			Thread.sleep(waitFor);
		} catch (Throwable e) {}  		
	}

	/**
	*creates a Frames object with a number of <code>DrawFrame</code> and Labels set by the
	*"frames" parameter of the applet Tag.
	*/
	public void init() {
        frameNumber = getParam("frames",1);
		labels = new Label[frameNumber];
		this.frames = new DrawFrame[frameNumber];
		for(int i=0;i<frameNumber;i++){
			frames[i] = new DrawFrame();
			labels[i] = new Label("");
		}
		setLayout(new BorderLayout());
		add("Center",new ExPanel(frames));
		add("South",new ExPanel(labels));
		validate();
		for(int i=0;i<frameNumber;i++) labels[i].setText(getParameter("label-"+i));
		for(int i=0;i<frameNumber;i++){
			frames[i].drawArea.addMouseListener(this);
		}
	
	}
	/**
	*changeFrames is repeatedly called by the run method every period stated by the <code>waitFor</code> field.
	*every object inherting from Frames and needs to updated should override this method.
	*The changeFrames method of class Frames does nothing.
	*@see #run
	*/
	protected void changeFrames(){}
 
	/**
	*Returns parses a given applet Tag parameter to an integer value.
	*If there is no parameter with the given name or the value of 
	* the parameter is not a valid integer a default value is returned.
	*@param name the parameter name.
	*@param defValue a default integer value.
	*@return the integer value associated with <code>name</code>.
	*/
	protected int getParam(String name,int defValue){
		try{
			return Integer.parseInt(getParameter(name));
		}catch(NumberFormatException e){
			return defValue;
		}
	}
	/**
	*Should be removed
	*/
	public void start(){
		
		for(int i=0;i<frames.length;i++)
			frames[i].drawArea.repaint();
	}
	/**
	*sets the thread t to null, this ensurse that the thread t will be envoced by a Frames object
	*of the current appletContext.
	*Also frees memory associated by the graphic buffers of the fraemes[].drawArea members.
	*/
	public void stop(){
		t = null;
		run = false;
		for(int i=0;i<frames.length;i++)
			frames[i].drawArea.freeBuffers();
	}
	/**
	*Clears memory set for awt objects associated with this Frames class object.
	*/
	public void destory(){
		for(int i=0;i<frames.length;i++)
			frames[i].drawArea.removeMouseListener(this);
		removeAll();
		labels = null;
		frames = null;
	}
	/**
	*a mouse click switch the values of the run field.
	*@see #run
	*/
	public void mouseClicked(MouseEvent m){
	
		this.run  = !this.run;
	}
	/**
	*Not implemented.
	*/
	public  void mousePressed(MouseEvent e){}
	/**
	*Not implemented.
	*/
	public  void mouseReleased(MouseEvent e){}
	/**
	*Not implemented.
	*/

	public  void mouseEntered(MouseEvent e){}
	/**
	*Not implemented.
	*/
 	public  void mouseExited(MouseEvent e){}
}

/*class Updater extends Thread implements Runnable{
	Frames applet;
	protected Thread updater = null;
	protected Updater(Frames applet){
		this.applet = applet;
		this.setPriority(MIN_PRIORITY); 
	}
	
/*	private void repaintContainer(Container comp){
		Component[] subcomps = comp.getComponents();
		for(int i=0;i<subcomps.length;i++){
			subcomps[i].repaint();
			if (subcomps[i] instanceof Container) 
				repaintContainer((Container)subcomps[i]);
		}
	}*/
/*	public void run(){
		Thread nonInterActive = Thread.currentThread();
		while (updater == nonInterActive)
			if((applet.isShowing())&&(applet.isActive()))
				try{
					applet.repaint();
					for(int i=0;i<applet.frames.length;i++){
						applet.frames[i].repaint();
						applet.frames[i].drawArea.repaint();
			}
			//		repaintContainer(applet);
					Thread.sleep(3000);
				} catch (InterruptedException e) {
				} catch (NullPointerException e) {
				} catch (IndexOutOfBoundsException e){}

	}
	public void finalize() throws Throwable{
		applet = null;
		super.finalize();
	}
}*/												   




