/*
Datei............: Aufg1429.java
Projekt..........: Einführung in die Java-Programmierung
Erstellt.........: 30.11.97, Guido Krüger
Geändert.........: --
Aufgabe..........: Musterlösung zu Aufgabe 14.29
Kommentare.......:

Die Lösung dieser Aufgabe mag auf den ersten Blick kompliziert
erscheinen, ist bei näherer Betrachtung aber eigentlich sehr
einfach zu verstehen. Wichtig ist insbesondere das Zusammenspiel
der drei Mausereignisse:

- Beim Drücken der Maustaste wird die aktuelle Mauszeigerposition in 
  der Instanzvariable lastpoint gespeichert.
- Beim Ziehen der Maus wird geprüft, ob zwischen der aktuellen und
  der zuletzt in lastpoint gespeicherten Mausposition ein Unterschied
  besteht (also eine Mausbewegung bei gedrückter Maustaste
  stattgefunden hat). Ist dies der Fall, wird eine Verbindungslinie
  von lastpoint zur aktuellen Position gezogen und lastpoint bekommt
  die Koordinaten der aktuellen Position zugewiesen.
- Beim Loslassen der Maustaste wird exakt dasselbe gemacht, mit dem
  Unterschied, daß am Ende lastpoint wieder auf (-1, -1) gesetzt wird,
  was soviel bedeutet wie "es gibt derzeit keinen Punkt, der zuletzt 
  bei gedrückter Maustaste besucht wurde".

Das Handling dieser Mausereignisse wird in den beiden lokalen Klassen
MyMouseListener und MyMouseMotionListener erledigt, die im Konstruktor
instanziert und als Eventhandler registriert werden.

Um auch nach einem repaint die Zeichnung rekonstruieren zu können, ist
es erforderlich, alle gezeichneten Liniensegmente zu speichern. Das
Programm verwendet dazu einen Vektor von Polygonen, die bei jedem der
drei Mausereignisse geeignet bedient werden:

- Beim Drücken der Maustaste wird ein neues Polygon erzeugt und die
  aktuelle Mausposition als Anfangspunkt darin abgelegt.
- Beim Ziehen der Maus wird die aktuelle Mausposition als neuer 
  Punkt im Polygon abgelegt.
- Beim Loslassen der Maustaste wird die aktuelle Position als Endpunkt
  im Polygon abgelegt und das komplette Polygon an das Ende des 
  Vektors gehängt.

Beim repaint braucht dann bloß noch der Vektor elementweise durchlaufen
und jedes darin enthaltene Polygon auf dem Bildschirm ausgegeben werden.
*/
import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class Aufg1429
extends Frame
{
  //Instanzmerkmale
  Point lastpoint;
  Polygon actpolygon;
  Vector paintelements;

  public static void main(String[] args)
  {
	Aufg1429 wnd = new Aufg1429();
	wnd.setSize(500,400);
	wnd.setVisible(true);
  }

  public Aufg1429()
  {
	super("Aufg1429");
	//Eventlistener aktivieren
	addWindowListener(
	  new WindowAdapter() {
	    public void windowClosing(WindowEvent event) {
		  System.exit(0);
		}
	  }
    );
	addMouseListener(new MyMouseListener());
	addMouseMotionListener(new MyMouseMotionListener());
	//Weitere Initialisierungen
	setBackground(Color.lightGray);
	lastpoint = new Point(-1, -1);
	paintelements = new Vector();
  }

  /**
   * Ausgabe aller Elemente des Vektors mit den Zeichenpolygonen. Um keine
   * geschlossenen Linienzüge zu zeichnen, wird drawPolyline anstelle von
   * drawPolygon verwendet. Da diese Methode kein Polygon-Objekt als
   * Argument akzeptiert, müssen die x- und y-Arrays des Polygons separat
   * übergeben werden. Vorsicht ist geboten, da diese meist mehr Elemente
   * enthalten, als tatsächlich Punkte im Polygon sind (die nicht benutzen
   * Punkte haben die Koordinaten (0, 0)). Die Anzahl der Elemente im 
   * Polygon muß also mit p.npoints ermitteln werden; auf keinen Fall darf
   * man p.xpoints.length oder p.ypoints.length verwenden.
   */
  public void paint(Graphics g)
  {
	Enumeration e = paintelements.elements();
	while (e.hasMoreElements()) {
	  Polygon p = (Polygon) e.nextElement();
	  g.drawPolyline(p.xpoints, p.ypoints, p.npoints);
	}
  }

  /**
   * Der MouseListener implementiert das Handling der Maustasten.
   */
  class MyMouseListener
  extends MouseAdapter
  {
	public void mousePressed(MouseEvent event)
	{
	  //Aktuellen Punkt merken
	  lastpoint.x = event.getX();
	  lastpoint.y = event.getY();
	  //Neues Polygon erzeugen
	  actpolygon = new Polygon();
	  actpolygon.addPoint(lastpoint.x, lastpoint.y);
	}

	public void mouseReleased(MouseEvent event)
	{
	  int actx = event.getX();
	  int acty = event.getY();
	  if (lastpoint.x != actx || lastpoint.y != acty) {
		//Linienstück zeichnen
		Graphics g = getGraphics();
		g.drawLine(lastpoint.x, lastpoint.y, actx, acty);
		//Polygon ergänzen
		actpolygon.addPoint(actx, acty);
	  }
	  //Polygon in den Vektor der Zeichenelemente einhängen
	  paintelements.addElement(actpolygon);
	  //Aktuellen Punkt initialisieren
	  lastpoint.x = -1;
	  lastpoint.y = -1;
	}
  }

  /**
   * Der MouseMotionListener erledigt das Handling der Mausbewegung.
   */
  class MyMouseMotionListener
  extends MouseMotionAdapter
  {
	public void mouseDragged(MouseEvent event)
	{
	  if (lastpoint.x == -1) {
		lastpoint.x = event.getX();
		lastpoint.y = event.getY();
	  } else {
		int actx = event.getX();
		int acty = event.getY();
		if (lastpoint.x != actx || lastpoint.y != acty) {
		  //Linienstück zeichnen
		  Graphics g = getGraphics();
		  g.drawLine(lastpoint.x, lastpoint.y, actx, acty);
		  //Polygon ergänzen
		  actpolygon.addPoint(actx, acty);
		  lastpoint.x = actx;
		  lastpoint.y = acty;
		}
	  }
	}
  }
}

