package stiftUndCo;

import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import java.awt.AWTEvent.*;


/**
 Ein Fenster ist das Modell eines rechteckigen Bereiches auf dem
 angeschlossenen Computerbildschirm. Es entspricht der Klasse  Bildschirm
 allerdings dient es zur Darstellung von in die Seiten integrierten Applets.
 Auf ihm kann mit Stiften gezeichnet werden. Zu diesem Zweck ist die 
 Zeichenebene auf dem Bildschirm mit einem Koordinatensystem versehen, 
 dessen Ursprung sich in der oberen linken Ecke der Zeichenebene befindet
 und dessen Achsen horizontal nach rechts und vertikal nach unten 
 gerichtet sind. Die Einheit ist ein Pixel.
 Die Implementierung enth&auml;lt einige Zus&auml;tze zum Standard der Stifte und M&auml;use,
 etwa die M&ouml;glichkeit f&uuml;r double-buffering.

@author Georg Dick
@version 6.4.98

  */
public class Fenster extends Applet implements Malflaeche, ComponentListener
{
	/**
	Das >hauptFenster< ist das erste Fensterobjekt, das von einer Anwendung erzeugt wird.
	Darauf greifen Stift, Maus etc. zu, wenn sie mit den jeweiligen parameterfreien Konstruktoren
	erzeugt werden.
	@see Maus#Maus()
	@see Tastatur#Tastatur()
	@see Stift#Stift()
	@see BuntStift#BuntStift()
	*/
	public static Fenster hauptFenster=null;
	private Color zhintergrundfarbe=Farbe.WEISS;
	private int zhoehe=0,zbreite=0;
	protected Graphics grafikKontext=this.getGraphics();
	protected Graphics hggrafikkontext=null;
	protected Image hintergrundbild=createImage(1,1);
	protected boolean zhintergrundmodus=false;
	

	
	
	public void info(String s)
	{
		System.out.println(s);
	}
	/**
	Konstruktor	Fenster<br>
    nachher:	Der Fenster ist initialisiert. Breite 400, Hoehe 300 Pixel
	*/
	public Fenster(){
		this(400,300);
		
	}

	/**
	Konstruktor	Fenster<br>
    nachher:	Der Fenster ist  initialisiert. 
	@param breite bestimmt die Breite des Fensters
	@param hoehe bestimmt die Hoehe des Fensters
	*/
	public Fenster (int breite, int hoehe) 
	{
	  super();
	   addComponentListener(this);
	  zbreite=breite;
	  zhoehe=hoehe;
	  this.setSize(zbreite,zhoehe);
	  this.setLayout(new FlowLayout());
	  //info("Breite:"+breite+" zbreite:"+zbreite+" linker Rand:"+this.insets().left );
	//this.setLayout(null);
	  this.setBackground(zhintergrundfarbe);
	  hintergrundbild = createImage(getSize().width,getSize().height);
	  zhintergrundmodus=false;  
	  this.registriere();
	  this.requestFocus();
	}

	/** Macht einen Grafikkontext f&uuml;r dieses Fenster dauerhaft(!) verf&uuml;gbar.
	Auch ausserhalb von paint! */
	public synchronized void addNotify()
	{
		super.addNotify();
		grafikKontext = this.getGraphics();
		
	}

	/**
	Das Hintergrundbild wird angezeigt
	@see Fenster#setzeHintergrundmodus
	*/
	public void aktualisiere()
	{
		if (zhintergrundmodus)
		{
		    grafikKontext.drawImage(hintergrundbild,0,0,this);
		}
	}
	
	/**
	stellt einen Grafikkontext f&uuml;r Malwerkzeuge, wie den Stift,
	zur Verf&uuml;gung. 
	*/

	public Graphics aktuellerGrafikkontext()
	{
		if (zhintergrundmodus)
		{
		     return hggrafikkontext;
		} else
		{
		     return grafikKontext;
		}
	}

	/**
	liefert den Wert wahr, wenn double-buffering benutzt wird
	*/
	public boolean hintergrundmodus()
	{ 
		return zhintergrundmodus;
	}

	public void componentShown(ComponentEvent e){
		//info ("Cshow");
	}
	public void componentResized(ComponentEvent e)
	{
		//info("CResized")		;
		bearbeiteFensterver\u00e4ndert();
	}
	public void componentHidden(ComponentEvent e)
	{   //info("CHidden")		;
		bearbeiteFensterver\u00e4ndert();}
	public void componentMoved(ComponentEvent e)
	{  //info("CMoved");
		bearbeiteFensterver\u00e4ndert();
	}


	

	/**
	passt den Fensterinhalt an, wenn das Fenster bewegt wurde 
	oder die Gr&ouml;sse sich ge&auml;ndert hat. Die Methode ist noch nicht 
	"fertig".
	*/
	public void bearbeiteFensterver\u00e4ndert()
	{
		
		if (zhintergrundmodus)
		{//info("&auml;nderung");
		Image hilf=createImage(getSize().width,getSize().height);
		hilf.getGraphics().drawImage(hintergrundbild,0,0,this);
		hintergrundbild=null;
		hggrafikkontext= null;
		System.gc();
		hintergrundbild=hilf;
		hggrafikkontext= hintergrundbild.getGraphics();
		//hggrafikkontext.translate(this.insets().left,this.insets().top);
		hilf=null;
		}
	}

	/**
	Anfrage	breite() liefert die Breite der Zeichenebene.
	*/
	public int breite()
	{
		return this.getSize().width;
	}
	
	protected Graphics g() {
	 return grafikKontext;
	}
	/**
	das Fenster wird abgebaut
	*/
	public void gibFrei()
	{
		this.setVisible(false);
		if (this == hauptFenster) 
		{
			hauptFenster=null;
		}	
		zhintergrundfarbe=null;
		grafikKontext=null;
		hggrafikkontext=null;
		hintergrundbild=null;

	}
	/**
	Anfrage	hintergrundFarbe() liefert die Farbe des Hintergrundes
	*/
	public Color hintergrundFarbe()
	{
		return zhintergrundfarbe ;
	}
	/**
	Anfrage	hoehe()  liefert die H&ouml;he der Zeichenebene.
	*/
	public int hoehe()
	{
	   	return this.getSize().height;
	}
	/**
	Auftrag	loescheAlles() <br>
	nachher:	Die Zeichenebene ist leer.
	*/
	public void loescheAlles() 
	{ 		 
		if ( ! zhintergrundmodus)
		{
			this.setBackground(zhintergrundfarbe);
			this.setSize(this.getSize().width-1,this.getSize().height-1);
			this.setSize(this.getSize().width+1,this.getSize().height+1);
		} else
		{
			
			hggrafikkontext.setColor(zhintergrundfarbe);
			hggrafikkontext.fillRect(0,0,getSize().width,getSize().height);
			grafikKontext.drawImage(hintergrundbild,0,0,this);
		}
	}
	/**
	Der erste Fenster, den eine Anwendung erzeugt wird als Klassenobjekt
	gespeichert
	@see#hauptFenster
	*/
	private void registriere(){
		if (hauptFenster==null) {hauptFenster=this;}
	}
	/**
	Beim Abbau des Fensters wird der Grafikkontext wieder freigegeben
	*/
	public synchronized void removeNotify()
	{
		super.removeNotify();
		grafikKontext = null;
	}
	/**
	Auftrag	setzeHintergrundFarbe(Color c) <br>
	nachher	Der Fenster hat die angegebene Hintergrundfarbe
	*/
	public synchronized void setzeHintergrundFarbe(Color c) 
	{
		zhintergrundfarbe=c;
		if ( ! zhintergrundmodus)
		{
			this.setBackground(zhintergrundfarbe);
			this.setSize(this.getSize().width-1,this.getSize().height-1);
			this.setSize(this.getSize().width+1,this.getSize().height+1);
		} else
		{
			hggrafikkontext.setColor(zhintergrundfarbe);
			hggrafikkontext.fillRect(0,0,getSize().width,getSize().height);
			grafikKontext.drawImage(hintergrundbild,0,0,this);
			
		}
	}
	/**
	Schaltet double-Buffering ein oder aus. Bei eingeschaltetem 
	Hintergrundmodus werden alle Zeichenoperationen unsichtbar 
	auf ein Hintergrundbild angewendet.
	Sie werden erst sichtbar, wenn der Fenster aktualisiert wird.
	@see Fenster#aktualisiere()
	*/
	public void setzeHintergrundmodus(boolean ein)
	{
		if (ein)
		{
			// neues Hintergrundbild erzeugen
			hggrafikkontext= hintergrundbild.getGraphics();
			//hggrafikkontext.translate(this.insets().left,this.insets().top);
			this.setzeHintergrundFarbe(zhintergrundfarbe);
			// kopiere Vordergrund auf Hintergrund
			// geht wohl nicht! 			
		}
		else
		{
			// kopiere gegebenenfalls Hintergund auf Vordergrund
			// wirklich n&ouml;tig ?
			if (hintergrundbild != null)
			grafikKontext.drawImage(hintergrundbild,0,0,this);
			// gib Hintergrundbild frei
			hintergrundbild=null;
		}
		zhintergrundmodus=ein;
	}

	
	public void update (Graphics g) 
	{
		this.paint(g);
	}
	
}