/*
 * Scrivere: 
 *   Un'interface 'listable' che preveda: 
 *     1.Un metodo 'aggiungi' che aggiunga l'elemento ad una lista data come parametro 
 *     2.Un metodo 'paint' che riceva come parametro un oggetto Graphics, che 'disegni' l'oggetto 
 *     3.Un metodo 'in' che riceve due coordinate come parametri e indichi se il punto dato appartiene alla figura listata 
 *   Una classe limage che possegga un' 'Image', implementi 'listable' e possegga come attributi una coppia di coordinate,
 *     inizializzate dal costruttore 
 *   Una classe quadrato che implementi 'listable' e disegni un quadrato di dimensione data, alla posizione indicata dal
 *     costruttore 
 *   Un applet che, ogni volta che viene premuto il tasto del mouse, disegni una pallina (Image) se il mouse è stato premuto
 *     sullo sfondo o un quadrato, se è stato premuto su una pallina. Tutti gli oggetti creati saranno contenuti in una lista di
 *     'listable' 
 */
import java.awt.*;
import java.awt.Image;
import java.awt.image.ImageObserver;
import java.applet.Applet;

// Interfaccia per oggetti 'listabili'
interface listable {
  listable aggiungi (listable toadd); // Aggiunge l'oggetto alla lista
  void paint (Graphics g);            // Disegna l'oggetto
  boolean in (int x, int y);          // Controlla se il mouse sta' nell'area data
  listable getNext ();                // Restituisce il prossimo oggetto
};

// Classe limage, non puo' derivare da un'immagine (che e' una classe astratta)
// Costituisce un'immagine (di dimensione w=20, h=20) in posizione fissa
class lmage implements listable {
  static final int w = 20; // Larghezza predeterminata
  static final int h = 20; // Altezza predeterminata
  ImageObserver o;         // il proprietario dell'immagine (un ImageObserver)
  int x,y;                 // la posizione dell'immagine
  listable next;           // Il prossimo elemento della lista
  Image i;                 // L'immagine da visualizzare

  // Costruttore che semplicemente inizializza gli attributi
  public lmage (int px, int py, Image img, ImageObserver obs) {
    x = px;
    y = py;
    o = obs;
    i = img;
  }

  // Metodo che attacca la lista (toadd) in coda all'elemento e ritorna l'elemento
  // come nuovo inizio lista
  public listable aggiungi (listable toadd) {
    next = toadd;
    return this;
  }

  // Metodo che chiama la paint del resto della lista, poi desegna se stesso
  public void paint (Graphics g) {
    if (next != null) {
      next.paint (g);
    }
    g.drawImage (i, x, y, o);             // Disegna l'immagine alle coordinate memorizzate
  }

  // Confronta le coordinate
  public boolean in (int isx, int isy) {
    return isx >= x && isx <= (x + w) && isy >= y && isy <= (y + h);
  }

  // Ritorna il prossimo elemento della lista
  public listable getNext () {
    return next;
  }
}

class quadrato implements listable {
  static final int w = 20; // Larghezza predeterminata
  static final int h = 20; // Altezza predeterminata
  int x,y;                 // la posizione del quadrato
  listable next;           // Il prossimo elemento della lista

  // Costruttore che semplicemente inizializza gli attributi
  quadrato (int px, int py) {
    x = px;
    y = py;
  }

  // Metodo che attacca la lista (toadd) in coda all'elemento e ritorna l'elemento
  // come nuovo inizio lista
  public listable aggiungi (listable toadd) {
    next = toadd;
    return this;
  }

  // Metodo che chiama la paint del resto della lista, poi desegna se stesso
  public void paint (Graphics g) {
    if (next != null) {
      next.paint (g);
    }
    g.drawLine (x, y, x, y + h);
    g.drawLine (x, y + h, x + w, y + h);
    g.drawLine (x + w, y + h, x + w, y);
    g.drawLine (x + w, y, x, y);
  }

  // Confronta le coordinate
  public boolean in (int isx, int isy) {
    return isx >= x && isx <= (x + w) && isy >= y && isy <= (y + h);
  }

  // Ritorna il prossimo elemento della lista
  public listable getNext () {
    return next;
  }
}

public class interfacetest extends Applet {
private Image dot = null;     // L'immagine da muovere sullo schermo
private listable l;

  public void init () {                         // Metodo chiamato all'avvio dell'applet
    dot = getImage(getCodeBase(), "lista.gif"); // Lancia il caricamento dell'immagine
  }

  // Gestisce l'evento della pressione del mouse
  public boolean mouseDown(Event evt, int x, int y) {
  listable c = l;
    while (c != null) {  // Percorre la lista, fino a che e' finita
      if (c.in (x,y))    // Se il mouse e' nell'area
        break;           // Interropme il ciclo
      c = c.getNext ();  // Altrimenti va al prossimo elemento
    }
    if (c == null) {     // Se ha esaurito la lista (non e' all'interno di un oggetto
      c = new lmage (x,y,dot,this); // Costruisce l'immagine
    } else {
      c = new quadrato (x,y);  // Altrimenti, costruisce il quadrato
    }
    l = c.aggiungi (l);    // Quindi aggiunge l'oggetto creato alla lista
    repaint ();            // Ridisegna
    return true;           // E lascia il sistema gestire il resto
  }
	
  synchronized public void paint(Graphics g) { // Metodo invocato per ridisegnare l'Applet
    if (l != null) {  // Se la lista non e' vuota
      l.paint (g);    // Chiede alla lista di ridisegnarsi (metodo ricorsivo)
    }
  }
}