import java.lang.*;
import java.io.*;
import java.util.*; 

import java.awt.*;
import java.awt.event.*;

class GrafMain extends Frame{

    private static final String VersionsDatum = "29. September 2004";
    
    private static final int XMin = 10;
    private static final int XMax = 1000;
    private static final int W = XMax-XMin+1;
    private static final int YMin = 50;
    private static final int YMax = 710;
    private static final int H = YMax-YMin+1;
    
    private static final Font FontMono  = new Font("Monospaced", Font.PLAIN, 18);
    private static final Font FontSansSerif = new Font("SansSerif", Font.PLAIN, 14);
    private static final Font BigItalicSansSerif = new Font("SansSerif", Font.ITALIC, 16);
       
    private static MenuBar MainMenuBar = new MenuBar();
    private static Menu DateiMenu = new Menu("Datei");
    /*private static MenuItem DateiOpen = new MenuItem("Öffnen");
    private static MenuItem DateiSave = new MenuItem("Speichern");
    private static MenuItem DateiSaveAs = new MenuItem("Speichern Unter");*/
    private static MenuItem Beenden = new MenuItem("Beenden");
        
    private static Menu GrafikDemoMenu = new Menu("GrafikDemos");
    private static MenuItem StandardLinie = new MenuItem("Standard Linie");
    private static MenuItem EigeneLinie = new MenuItem("Eigene Linie");
    private static MenuItem BresenhamLinie  = new MenuItem("Bresenham Linie");
    private static MenuItem StandardKreis = new MenuItem("Standard Kreis");
    private static MenuItem Bresenham1Kreis = new MenuItem("Bresenham 1 Kreis");
    private static MenuItem Bresenham2Kreis = new MenuItem("Bresenham 2 Kreis");
    private static MenuItem BresenhamOptKreis = new MenuItem("Bresenham Opt. Kreis");
    private static MenuItem Loeschen  = new MenuItem("Löschen Bildschirm");
    
    private static Menu HilfeMenu = new Menu("Hilfe");
    private static MenuItem Hilfe = new MenuItem("Es gibt keine Hilfe...");
    private static MenuItem AboutBox = new MenuItem("About");
        
  
    private static String Titel = "Grafik2d Kapitel 3";
        
    //// Constructor.
     
    public GrafMain () {
	super(Titel);
	
	setFont(FontMono);
	DateiMenu.setFont(FontSansSerif);
	/*DateiOpen.setFont(FontSansSerif);
	DateiSave.setFont(FontSansSerif);
	DateiSaveAs.setFont(FontSansSerif);*/
	Beenden.setFont(FontSansSerif);
	
	GrafikDemoMenu.setFont(FontSansSerif);
	StandardLinie.setFont(FontSansSerif);
	EigeneLinie.setFont(FontSansSerif);
	BresenhamLinie.setFont(FontSansSerif);
	StandardKreis.setFont(FontSansSerif);
	Bresenham1Kreis.setFont(FontSansSerif);
	Bresenham2Kreis.setFont(FontSansSerif);
	BresenhamOptKreis.setFont(FontSansSerif);
	Loeschen.setFont(FontSansSerif);
	
	HilfeMenu.setFont(FontSansSerif);
	Hilfe.setFont(FontSansSerif);
	AboutBox.setFont(FontSansSerif);
	setLayout(null);

	
	//// Menüs
	setMenuBar(MainMenuBar);
	
	MainMenuBar.add(DateiMenu);
	/*DateiMenu.add(DateiOpen);
	DateiMenu.add(DateiSave);
	DateiMenu.add(DateiSaveAs);*/
	DateiMenu.addSeparator();
	DateiMenu.add(Beenden);
	
	MainMenuBar.add(GrafikDemoMenu);
	GrafikDemoMenu.add(StandardLinie);
	GrafikDemoMenu.add(EigeneLinie);
	GrafikDemoMenu.add(BresenhamLinie);
	GrafikDemoMenu.addSeparator();
	GrafikDemoMenu.add(StandardKreis);
	GrafikDemoMenu.add(Bresenham1Kreis);
	GrafikDemoMenu.add(Bresenham2Kreis);
	GrafikDemoMenu.add(BresenhamOptKreis);
	GrafikDemoMenu.addSeparator();
	GrafikDemoMenu.add(Loeschen);
	
	MainMenuBar.add(HilfeMenu);
	HilfeMenu.add(Hilfe);
	HilfeMenu.addSeparator();
	HilfeMenu.add(AboutBox);
	
	//// Allgemeine Initialisierung
	
	
	//// Menü Listener
	
	/*DateiOpen.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ doDateiLaden(); }
	    });
	    
	DateiSave.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ doDateiSpeichern(); }
	    });
	    
	DateiSaveAs.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ doDateiSpeichernUnter(); }
	    });*/	    
	    
	Beenden.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ FensterBeenden(); }
	    });
	    
	StandardLinie.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ 
	        doStandardLinie();
	        }
	    });
	    
	EigeneLinie.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ 
	        doEigeneLinie();
	        }
	    });    
	
	BresenhamLinie.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ 
	        doBresenhamLinie();
	        }
	    });
	    
	StandardKreis.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ 
	        doStandardKreis();
	        }
	    });
	    
	Bresenham1Kreis.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ 
	        doBresenham1Kreis();
	        }
	    });
	    
	Bresenham2Kreis.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ 
	        doBresenham2Kreis();
	        }
	    });    
	    
	BresenhamOptKreis.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ 
	        doBresenhamOptKreis();
	        }
	    });    
	
	Loeschen.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ 
	        Graphics g = getGraphics();
            g.clearRect(XMin, YMin, W, H);
	        }
	    });    
	    
	        	    	    
	AboutBox.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ showAboutBox(); }
	    });         
	
	//// Window Listener
	addWindowListener(new WindowAdapter() {    
        public void windowClosing(WindowEvent e) { FensterBeenden(); }
	    });
	    
	//// Jetzt Fenster zeigen!
	setBackground(Color.white);    
	setSize(1020,720);
    setVisible(true);
    }
 //// Ende des Konstruktors  
       
 //// Implementierung der Menübefehle    
    
    void doStandardLinie(){
    	Graphics g = getGraphics();
        MyLine0(g, XMin, YMin, XMax, YMax, Color.red);
    	}
	
	void doEigeneLinie(){	
    	Graphics g = getGraphics();
        Linie(g, XMin, YMin, XMax, YMax, Color.blue);
        }
        
    void doBresenhamLinie(){	
    	Graphics g = getGraphics();
        OptLinie(g, XMin, YMin, XMax, YMax, Color.green);
        }        

    void doStandardKreis(){	
    	Graphics g = getGraphics();
    	int dX = (XMax - XMin)/2;
    	int dY = (YMax - YMin)/2;
    	int xm = XMin + dX;
    	int ym = YMin + dY;
    	int r = java.lang.Math.min(dX, dY);
        MyCircle0(g, xm, ym, r, Color.red);
        } 
        
    void doBresenham1Kreis(){	
    	Graphics g = getGraphics();
    	int dX = (XMax - XMin)/2;
    	int dY = (YMax - YMin)/2;
    	int xm = XMin + dX;
    	int ym = YMin + dY;
    	int r = java.lang.Math.min(dX, dY);
        MyCircleB1(g, xm, ym, r, Color.blue);
        } 
        
    void doBresenham2Kreis(){	
    	Graphics g = getGraphics();
    	int dX = (XMax - XMin)/2;
    	int dY = (YMax - YMin)/2;
    	int xm = XMin + dX;
    	int ym = YMin + dY;
    	int r = java.lang.Math.min(dX, dY);
        MyCircleB2(g, xm, ym, r, Color.cyan);
        }    
        
    void doBresenhamOptKreis(){	
    	Graphics g = getGraphics();
    	int dX = (XMax - XMin)/2;
    	int dY = (YMax - YMin)/2;
    	int xm = XMin + dX;
    	int ym = YMin + dY;
    	int r = java.lang.Math.min(dX, dY);
        MyCircleBO(g, xm, ym, r, Color.green);
        }       
     

////  About Box
	
    void showAboutBox(){	
	final Frame f = new Frame("About Box");
	final Button Ok = new Button("Ok");

	f.addWindowListener(new WindowAdapter() {
	    public void windowClosing(WindowEvent e) {
		f.dispose();
		}
	    });
	    
	 Ok.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
		f.dispose();
		}
	    });
	
	f.setFont(BigItalicSansSerif);
	f.setLayout(new GridLayout(0, 1));

	f.add(new Label(" ", Label.CENTER));
	f.add(new Label("Universität Marburg - Fachbereich Mathematik und Informatik", Label.CENTER));
	f.add(new Label("Bresenham etc...", Label.CENTER));
	f.add(new Label("Datum der letzten Änderung: " + VersionsDatum, Label.CENTER));
	f.add(new Label("Autor: Prof. Dr. Manfred Sommer", Label.CENTER));
	f.add(new Label(" ", Label.CENTER));
	
	f.add(Ok);
	f.pack(); 
	f.setVisible(true);
	}	
	
////  Programm Beenden
    
    void FensterBeenden() {		        
	dispose();
	System.exit(0);
	}	

////  Programm Starten

    public static void main(String args[]) {
    new GrafMain();
    }
    
////  Grafik Algorithmen 

void PutPixel(Graphics g, int x, int y, Color f){
    g.setColor(f);
	g.drawLine(x,y,x,y);
    } 
    
void PutPixel(Graphics g, int x, int y){
	g.drawLine(x,y,x,y);
    }    
    
void MyLine0(Graphics g, int x1, int y1, int x2, int y2, Color f){
    g.setColor(f);
    g.drawLine(x1,y1,x2,y2);
    } 
    
void Linie(Graphics g, int x1, int y1, int x2, int y2, Color Farbe){
    double dy = y2-y1;
	double dx = x2-x1;
	double  m = dy/dx;
	double  y = y1 + 0.5; // Rundung!

	for (int x=x1; x <= x2; x++ ){
	  PutPixel(g, x, (int) y , Farbe);
	  y += m; // Annahme : delta(x) = 1
	  } 
    } 
    

void OptLinie2(Graphics g, int x1, int y1, int x2, int y2, Color Farbe){
    int dy = y2-y1;
	int dx = x2-x1;
	int IncrE  = 2*dy;
	int  d = IncrE - dx;
	int IncrNE = 2*(dy-dx);
	int  y = y1;
	
	PutPixel(g, x1, y1, Farbe);
	for (int x=x1+1; x <= x2; x++ ){
	  if (d <= 0) d += IncrE;
	  else { d += IncrNE; y++; }
	  PutPixel(g, x, y, Farbe);
	  } 
    }
    
 void OptLinie(Graphics g, int x1, int y1, int x2, int y2, Color Farbe){
		int dy = (y2-y1);
		int dx = (x2-x1);
		int incKN = dy*2;
		int incGN = (dy-dx)*2;
		int D = incGN-dx;
		int y = y1;
		PutPixel(g, x1, y1, Farbe);
		for (int x=x1+1; x <= x2; x++ ){
	  		if (D <= 0) D += incKN;
	  		else { D += incGN; y++; }

	  		PutPixel(g, x, y, Farbe);
	  		}}
   
    
 void MyCircle0(Graphics g, int xm, int ym, int Radius, Color f){
    g.setColor(f);
    int xa = xm - Radius;
    int ya = ym - Radius;
    int w  = 2*Radius;
    int h  = 2*Radius;
    g.drawOval(xa,ya,w,h);
    }
    
 void KreisPunkt(Graphics g, int x1, int y1, int x, int y){
	PutPixel(g, x1 + x, y1 + y);
	PutPixel(g, x1 - x, y1 + y);
	PutPixel(g, x1 + x, y1 - y);
	PutPixel(g, x1 - x, y1 - y);

	PutPixel(g, x1 + y, y1 + x);
	PutPixel(g, x1 - y, y1 + x);
	PutPixel(g, x1 + y, y1 - x);
	PutPixel(g, x1 - y, y1 - x);
	}
	
 void MyCircleB1(Graphics g, int xm, int ym, int Radius, Color f){
    g.setColor(f);
    int y = Radius;
	double d = 1.25 - Radius; 

	KreisPunkt(g, xm, ym, 0, y);
	for (int x = 1; x < y; x++ ){
	  if (d < 0) d += 2*x + 3;
	  else { d += 2*(x-y)+5; y--; }
	  KreisPunkt(g, xm, ym, x, y);
	  }
    }
    
 void MyCircleB2(Graphics g, int xm, int ym, int Radius, Color f){
    g.setColor(f);
    int y = Radius;
	int d = 1 - Radius; 

	KreisPunkt(g, xm, ym, 0, y);
	for (int x = 1; x < y; x++ ){
	  if (d <= 0) d += 2*x + 3; 
	  else { d += 2*(x-y)+5; y--; }
	  KreisPunkt(g, xm, ym, x, y);
	  } 
    }   
    
 void MyCircleBO(Graphics g, int xm, int ym, int Radius, Color f){
    g.setColor(f);
    int y = Radius;
	int d = 1 - Radius; 
	int deltaE  = 3;
	int deltaSE = -2*Radius+5;

	KreisPunkt(g, xm, ym, 0, y);
	for (int x = 1; x < y; x++ ){
	  if (d <= 0) {d +=deltaE; deltaSE += 2;}	
	  else { d += deltaSE; deltaSE += 4; y--; }
	  deltaE += 2;
	  KreisPunkt(g, xm, ym, x, y);
	  } 
    }
}
