esercizio 1
In questa applet é presente un bottone che comanda l'animazione permettendo di fermarla e di farla ripartire. L'uso di un solo bottone richiede di mantenere coerente il messaggio visualizzato sullo stesso e una gestione degli eventi che consideri lo stato. É utile notare l'astrazione apportata nel concetto di canvas animabile che estende una canvas bufferizzata. Queste classi nascondono le usuali tecniche utilizzate per ottenere una animazione fluida. La classe BallCanvas deve implementare i metodi doAnimation e bufferedPaint senza occuparsi di altro. Queste classi verranno usate in futuro per nascondere queste laboriose tecniche e per concentrare l'attenzione solo sulle classi in esame.

package corsoDrZito.lez4.es1;

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;

public class esercizio1 extends Applet
{
	public esercizio1()
	{
		// allocate an array of bouncing balls
		balls = new Ball[15];
		// ACTHUNG!!! pass only an array reference without any single allocation still!!! Java Rulez! ^_^
		bc = new BallCanvas(balls);
	}

	public void init()
	{
		// GUI
		createGUI(this);

		// now can allocate some balls
		for (int i=0; i<balls.length; i++)
			balls[i] = new Ball(bc.size());

		setBackground(new Color(48,64,96));
	}

	void createGUI(Container c)
	{
		c.setLayout(new BorderLayout());

		toggle = new Button();
		toggle.addActionListener(new BL());

		c.add(toggle, BorderLayout.SOUTH );
		c.add(bc,     BorderLayout.CENTER);

		c.validate(); // to get a valid ball canvas size
	}

	public void start()
	{
		bc.setAnimation(true);
		toggle.setLabel("stop");
	}

	public void stop()
	{
		bc.setAnimation(false);
		toggle.setLabel("start");
	}


	// inner class for listeners
	class BL implements ActionListener
	{
		public void actionPerformed(ActionEvent e)
		{
			String s = e.getActionCommand();
			if (s.equals("start"))
			{
				bc.setAnimation(true);
				((Button)e.getSource()).setLabel("stop");
			}
			else
			if (s.equals("stop"))
			{
				bc.setAnimation(false);
				((Button)e.getSource()).setLabel("start");
			}
			else
			throw new IllegalStateException();
		}
	}

	Ball[] balls;
	BallCanvas bc;
	Button toggle;
}

package corsoDrZito.lez4.es1;

import java.awt.*;

public class Ball
{
	public Ball(Dimension d)
	{
		x = (int)(Math.random() * d.width);
		y = (int)(Math.random() * d.height);
		x_increment = 1 + (int)(Math.random() * 4.);
		y_increment = 1 + (int)(Math.random() * 4.);
		r = 28 - x_increment * y_increment;
		bounds = d;
	}

	public void paint(Graphics g)
	{
		g.fillOval(x, y, r, r);
	}

	public void move()
	{
		if(x + r >= bounds.width ) x_increment = -Math.abs(x_increment);
		else
		if(x < 0) x_increment = Math.abs(x_increment);

		if(y + r >= bounds.height) y_increment = -Math.abs(y_increment);
		else
		if(y < 0) y_increment = Math.abs(y_increment);

		x += x_increment;
		y += y_increment;
	}

	private int x, y, r, x_increment, y_increment;
	private Dimension bounds;
}

package corsoDrZito.lez4.es1;

import java.awt.*;
import java.awt.image.*;

public class BallCanvas extends AnimateCanvas
{
	public BallCanvas(Ball[] b)
	{
		super(10L);
		if(b==null) throw new NullPointerException();
		balls = b;
	}

	protected synchronized void doAnimation()
	{
		for (int i=0; i<balls.length; i++) balls[i].move();
	}

	protected synchronized void bufferedPaint(Graphics g)
	{
		for (int i=0; i<balls.length; i++) balls[i].paint(g);
	}

	Ball[] balls;
}

package corsoDrZito.lez4.es1;

import java.awt.*;
import java.awt.image.*;

public abstract class AnimateCanvas extends BufferedCanvas implements Runnable
{
	public AnimateCanvas()
	{
		super();

		animation = new Thread(this);
		animation.start();
	}

	public AnimateCanvas(long waitTimeInMillis)
	{
		this();
		this.waitTimeInMillis = waitTimeInMillis;
	}

	public void run()
	{
		animation.setPriority(Thread.MAX_PRIORITY);
		do
		{
			if(animate)
			{
				doAnimation();

				repaint();
			}
			try
			{
				Thread.currentThread();
				Thread.sleep(waitTimeInMillis);
			}
			catch(InterruptedException ex) {}

		} while(animation!=null);
	}

	protected abstract void doAnimation();

	public void setAnimation(boolean state)
	{
		animate = state;
	}


	static int times;

	boolean animate; // don't animate before explicit setAnimation(true) method invocation!
	long waitTimeInMillis = 20L;
	Thread animation;
}

package corsoDrZito.lez4.es1;

import java.awt.*;
import java.awt.image.*;

public abstract class BufferedCanvas extends Canvas
{
	public BufferedCanvas()
	{
		super();
	}

	public synchronized void update(Graphics g)
	{
		paint(g);
	}

	public synchronized void paint(Graphics g)
	{
		d = size();

		if (image==null)
		{
			image = createImage(d.width, d.height);
			bg = image.getGraphics();
		}

		bg.clearRect(0, 0, d.width, d.height);

		bufferedPaint(bg);

		g.drawImage(image, 0, 0, this);
	}

	public boolean isDoubleBuffered()
	{
		return true;
	}

	protected abstract void bufferedPaint(Graphics g);

	Dimension d;
	Graphics bg;
	Image image;
}