package primitives.frames;
import java.awt.*;
import primitives.machines.MachineListener;
import primitives.machines.MachineUpdate;

/**
*A class which encapsulates the drawing on a canvas.
*The paint method calls the redraw method of the MachineListener interface associated with
*this canvas. associate a MachineListener interface by the setCurrentObject method.
*A double buffer is used to preform drawings the graphic context of this buffer is passed
*to the redraw method of the MachineListener interface.
*@author Dori Eldar
*@see primitives.machines.MachineListener
*/
public class CanvasArea extends Canvas{
	/**
	*The memory set for the backbuffer.
	*[should be private member]
	*/
	Image backBuffer = null;      
    /**
	*The graphic context of backBuffer.
	*[should be private]
	*/
	public Graphics backBufferG = null; 
	/**
	*The interface to call its redraw method from the paint method of this object.
	*@see primitives.machines.MachineListener
	*/
	public MachineListener machine;
	/**
	*@see #freeBuffers
	@exception java.lang.Throwable .
	*/
	public void finalize() throws Throwable{
		freeBuffers(); 
 	}
	/**
	*clears the memory associated with the backbuffer objects.
	*/
	void freeBuffers(){
		machine = null;
		if (backBufferG!=null){
			backBufferG.dispose();
			backBufferG = null;
		}
		if(backBuffer!=null){
		   backBuffer.flush();
		   backBuffer = null;
		}
	}
	/**
	*overrides update method of Canvas class.
	*calls paint method immidiatly.
	*/
	public synchronized void update(Graphics g){
		paint(g);
	}
	/**
	*calls the redraw method of the machine member.
	*Passing to this method the graphic context of the buffer.
	*/
	public synchronized void paint(Graphics g){
		Dimension d = getSize();
	        if (backBuffer == null 
                || backBuffer.getWidth(this) != d.width
                || backBuffer.getHeight(this) != d.height) {
            backBuffer = createImage(d.width, d.height);
            backBufferG = backBuffer.getGraphics();
        }
		backBufferG.setColor(getBackground());
		if((machine!=null)&&(machine instanceof MachineUpdate))
			((MachineUpdate)machine).update(backBufferG);
		else{
			backBufferG.clearRect(0, 0,d.width,d.height);
			backBufferG.setColor(getForeground());
		}
		if(machine!=null) machine.redraw(backBufferG);
		g.drawImage(backBuffer, 0, 0, this);
	}
	/**
	*sets the MachineListener object to be called by the paint method of this object.
	*@param obj the Machinelistener object to associate.
	*@see primitives.machine.Machinelistener
	*/
	public void setCurrentObject(MachineListener obj){
		this.machine = obj;
	}
}
