From 1f6f843dd3d565b580698904f488a4739e4afa4d Mon Sep 17 00:00:00 2001
From: Gregor Kleen <gkleen@yggdrasil.li>
Date: Thu, 26 Nov 2015 04:46:13 +0000
Subject: Moved GraphicsWindow to saner location

---
 ws2015/eip/GraphicsWindow.java             | 393 +++++++++++++++++++++++++++++
 ws2015/eip/blaetter/04/GraphicsWindow.java |  28 +-
 ws2015/eip/blaetter/05/GraphicsWindow.java |  28 +-
 ws2015/eip/blaetter/06/GraphicsWindow.java | 393 +++++++++++++++++++++++++++++
 4 files changed, 810 insertions(+), 32 deletions(-)
 create mode 100644 ws2015/eip/GraphicsWindow.java
 create mode 100644 ws2015/eip/blaetter/06/GraphicsWindow.java

diff --git a/ws2015/eip/GraphicsWindow.java b/ws2015/eip/GraphicsWindow.java
new file mode 100644
index 0000000..2bb652d
--- /dev/null
+++ b/ws2015/eip/GraphicsWindow.java
@@ -0,0 +1,393 @@
+package gameoflifetest;
+
+import java.awt.*;
+import java.util.ArrayList;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.Timer;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.event.MouseEvent;
+import java.awt.geom.RectangularShape;
+import java.awt.geom.GeneralPath;
+
+/**
+ Eine Klasse zu pädagogischen Zwecken.
+ Erlaubt die Eingabe von Punktkoordinaten
+ mittels Mausklicks, das Zeichnen einfacher
+ 2D Objekte (java.awt.Shape), sowie die
+ Ausgabe von Texten in einer Statuszeile.
+ @version 3.043
+ @author Martin Hofmann und die EiP-Teams verschiedener Jahre
+ */
+
+public class GraphicsWindow {
+
+    private int width;
+    private int height;
+    private JFrame dasFenster;
+    private static int fensterZahl;
+    private static int fensterNr;
+    private Label label;
+    private GraphicsWindowPanel panel;
+    private Point mousePos;
+    private Color activeColor = Color.BLACK;
+    final private Color backColor = Color.WHITE;
+    MyMouseAdapter mouseListener;
+
+    /**
+     Erzeugt ein Fenster der Größe 640 auf 480 mit Textausgabe, Mauseingabe und Grafikausgabe.
+     */
+    public GraphicsWindow() {
+        this(640, 480);
+    }
+
+    /**
+     Erzeugt ein Fenster in vorgegebener Größe mit Textausgabe, Mauseingabe und Grafikausgabe.
+     @param width Breite des Fensters
+     @param height Höhe des Fensters
+     */
+    public GraphicsWindow(int width, int height) {
+        this.width  = width;
+        this.height = height;
+        dasFenster  = new JFrame();
+        dasFenster.setTitle("Grafikfenster " + ++fensterNr);
+        fensterZahl++;
+        dasFenster.setLocationByPlatform(true);
+        dasFenster.setSize(width,height+50);
+        dasFenster.getContentPane().setPreferredSize(new Dimension(width, height+50));
+        dasFenster.pack();
+        dasFenster.addWindowListener(new WindowAdapter(){
+            public void windowClosing(WindowEvent e) {
+                dasFenster.dispose(); // nicht gleich alle Fenster abschiessen
+                if (--fensterZahl<1) System.exit(0);
+            }
+        });
+
+        label = new Label("Statuszeile...");
+        label.setFont(new Font("Helvetica", Font.PLAIN, 12));
+        dasFenster.getContentPane().add(label,"North" );
+        panel = new GraphicsWindowPanel();
+        //panel.setBackground(Color.cyan);
+        panel.addCommand(new SetColor(activeColor));
+        dasFenster.getContentPane().add(panel,"Center");
+        mousePos = new Point();
+        mouseListener = new MyMouseAdapter();
+        panel.addMouseListener(mouseListener);
+        clear();
+        dasFenster.setVisible(true);
+    }
+
+    /**
+     Gibt eine Zeichenkette oben im Fenster aus.
+     @param text diese Zeichenkette
+     */
+    public void setText(String text) {
+        label.setText(text);
+    }
+    /**
+     Liest den oben im Fenster angezeigten Text aus.
+     @return den Text
+     */
+    public String getText() {
+        return label.getText();
+    }
+    /**
+     Wartet auf einen Mausklick. Die Methode blockiert das
+     aufrufende Programm solange bis der Mausklick erfolgt ist.
+     @return die Koordinaten des angeklickten Punkts
+     */
+
+    public Point mouseClick() {
+        try{
+            synchronized(mouseListener){mouseListener.wait();}
+        }
+        catch(InterruptedException e){
+            e.printStackTrace();
+        }
+        return mousePos;
+    }
+
+    class MyMouseAdapter extends MouseAdapter {
+
+        /**
+         Beendet das Warten auf den Mausklick und verwertet die Koordinaten.
+         Diese Methode ist nicht für den Anwender bestimmt.
+         */
+
+        synchronized public void mouseClicked(MouseEvent e){
+            mousePos = e.getPoint();
+            notifyAll();
+        }
+    }
+
+
+    /**
+     Schaltet die Zeichenfarbe auf die Hintergrundfarbe um. Dies ist
+     das Mittel, um gezeichnete Linien wieder zu löschen.
+     */
+    public void switchToBackgroundColor(){
+        activeColor = backColor;
+        panel.addCommand(new SwitchToBackgroundColor(activeColor));
+        panel.repaint();
+    }
+
+    /**
+     Schaltet die Zeichenfarbe auf Schwarz um.
+     */
+    public void switchToForegroundColor(){
+        activeColor = Color.BLACK;
+        panel.addCommand(new SetColor(activeColor));
+        panel.repaint();
+    }
+
+
+    /** Liefert die aktuelle Zeichenfarbe.
+     @return die aktuelle Zeichenfarbe des GraphicsWindow. */
+    public Color getColor() {
+        // return panel.getGraphics().getColor(); // getGraphics() has unpleasant side-effects. :(
+                /* Fixed by adding another instance variable activeColor for now. */
+        return activeColor;
+    }
+
+    /**
+     Zeichnet eine Linie in der aktuellen Zeichenfarbe.
+     @param x Anfangspunkt
+     @param y Endpunkt
+     */
+    public void drawLine(Point x, Point y){
+        // Odering points reduces the amount of graphical artifacts in rendering the same object in different ways
+        Point x1 = x;
+        Point y1 = y;
+        if ((x.x > y.x) || ((x.x == y.x) && (x.y > y.y))) {
+            x1 = y;
+            y1 = x;
+        }
+        panel.addCommand(new DrawLine(x1,y1));
+        panel.repaint();
+    }
+
+    /**
+     Zeichnet einen Punkt in der aktuellen Zeichenfarbe.
+     @param p Punkt
+     */
+    public void drawPoint(Point p){
+        drawLine(p, p);
+    }
+
+    /**
+     Zeichnet einen Punkt in der aktuellen Zeichenfarbe.
+     @param p Punkt
+     */
+    public void drawStringAt(String s, Point p){
+        Command c = new DrawString(s,p);
+        panel.addCommand(c);
+        panel.repaint();
+    }
+
+    /**
+     Zeichnet ein geometrisches Objekt.
+     */
+    public void draw(Shape s) {
+        panel.addCommand(new Draw(s));
+        panel.repaint();
+    }
+
+    /**
+     Füllt ein geometrisches Objekt aus.
+     */
+    public void fill(Shape s) {
+        panel.addCommand(new Fill(s));
+        panel.repaint();
+    }
+
+    /** Das aufrufende Programm wird für ein gegebene Zeitspanne blockiert.
+     @param millis Die Zeitspanne in Millisekunden*/
+    public void sleep(long millis) {
+        try {Thread.sleep(millis);} catch (Exception e){}
+    }
+
+    /** Setzt die Zeichenfarbe. */
+    public void setColor(Color d) {
+        activeColor = d;
+        panel.addCommand(new SetColor(activeColor));
+        panel.repaint();
+    }
+
+    /**
+     Setzt die Zeichenfarbe auf einen Grauwert
+     @param shade Grauwert zwischen 0(schwarz) und 255(weiß)
+     */
+    public void setGrayColor(int shade) {
+        setColor(new Color(shade, shade, shade));
+    }
+
+    /**
+     Setzt die Zeichenfarbe für die Mandelbrot-Aufgabe
+     @param n Anzahl der Iterationen, die durch die Farbe symboliziert werdem soll
+     */
+    public void setMandelColor(int n) {
+        float r = (float) Math.min(1.0,((double) n / 9.0) );
+        float g = (float) Math.min(1.0,((double) n / 99.0) );
+        float b = (float) Math.min(1.0,((double) n / 999.0) );
+        setColor(new Color(r, g, b));
+    }
+
+    /** Löscht das Bild */
+    public void clear() {
+//        Color oldActive = activeColor;
+        panel.clearAll();
+//        this.switchToBackgroundColor();
+//        fill(new Rectangle(0,0,width,height));
+//        setColor(oldActive);
+    }
+
+    public void killIn(int secs) {
+        Timer t  = new Timer(1000*secs, new ActionListener(){
+            @Override
+            public void actionPerformed(ActionEvent e) {dasFenster.dispose();}
+        }
+        );
+        t.setRepeats(false);
+        t.start();
+    }
+}
+
+
+class GraphicsWindowPanel extends JPanel
+{
+    private static final long serialVersionUID = 1L;
+    private ArrayList<Command> cl = new ArrayList<Command>();
+
+    public void paintComponent(Graphics g)
+    {
+        super.paintComponent(g);
+        Graphics2D g2D = (Graphics2D)g;
+
+        ArrayList<Command> cl = this.cl; // Kopie wegen Nebenläufigkeit von Swing
+        int size = cl.size();
+        for (int i=0; i<size; i++) {
+            Command c = cl.get(i);
+            if (c != null) c.execute(g2D);
+        }
+    }
+
+    void addCommand(Command c)
+    {
+        cl.add(c);
+    }
+
+    void clearAll()
+    {
+//              try {
+//                      SwingUtilities.invokeAndWait(new Runnable() {
+//                              @Override
+//                              public void run() {
+        cl = new ArrayList<Command>();
+//                              }
+//                      });
+//              } catch (InterruptedException e) {
+//                      // TODO Auto-generated catch block
+//                      e.printStackTrace();
+//              } catch (InvocationTargetException e) {
+//                      // TODO Auto-generated catch block
+//                      e.printStackTrace();
+//              }
+    }
+}
+
+
+abstract class Command //implements Serializable
+{
+    abstract  void execute(Graphics2D g2D);
+
+    /** Clone a shape. This method is needed because Shape
+     * does not define clone(), although many shape classes do.
+     * Kopiert aus jsky-2.6 auf ftp.eso.org */
+    static Shape cloneShape(Shape s) {
+        // FIXME Add more specific shapes
+        if (s instanceof RectangularShape) {
+            return (RectangularShape) ((RectangularShape) s).clone();
+        } else {
+            return new GeneralPath(s);
+        }
+    }
+
+}
+
+class DrawLine extends Command {
+    Point von;
+    Point bis;
+    DrawLine(Point von, Point bis) {
+                /* Clonen der Punkte essentiell um Aliasingeffekte beim Redraw zu verhindern */
+        this.von = new Point(von);
+        this.bis = new Point(bis);
+    }
+    void execute(Graphics2D g2D)
+    {
+        g2D.drawLine(this.von.x,this.von.y,this.bis.x,this.bis.y);
+    }
+}
+
+class SwitchToForegroundColor extends Command {
+    SwitchToForegroundColor() {}
+    void execute(Graphics2D g2D) {
+        g2D.setColor(Color.black);
+    }
+}
+
+class SwitchToBackgroundColor extends Command {
+    Color backcolor;
+    SwitchToBackgroundColor(Color backcolor) {this.backcolor = backcolor;}
+    void execute(Graphics2D g2D) {
+        g2D.setColor(backcolor);
+    }
+}
+
+class SetColor extends Command {
+    Color color;
+    SetColor(Color color) {this.color = color;}
+    void execute(Graphics2D g2D) {
+        g2D.setColor(this.color);
+    }
+}
+
+
+class Draw extends Command {
+    Shape shape;
+    Draw(Shape shape) {this.shape = cloneShape(shape);}
+    void execute(Graphics2D g2D) {
+        g2D.draw(this.shape);
+    }
+}
+
+class Fill extends Command {
+    Shape shape;
+    Fill(Shape shape) {this.shape = cloneShape(shape);}
+    void execute(Graphics2D g2D) {
+        g2D.fill(this.shape);
+    }
+}
+
+class DrawString extends Command {
+    String string;
+    Point position;
+    DrawString(String string, Point position) {this.string = string; this.position = position;}
+    @Override
+    void execute(Graphics2D g2D) {
+        g2D.drawString(string, position.x, position.y);
+    }
+}
+
+
+
+
+
+
+
+
+
diff --git a/ws2015/eip/blaetter/04/GraphicsWindow.java b/ws2015/eip/blaetter/04/GraphicsWindow.java
index b92fdaf..2bb652d 100644
--- a/ws2015/eip/blaetter/04/GraphicsWindow.java
+++ b/ws2015/eip/blaetter/04/GraphicsWindow.java
@@ -1,3 +1,6 @@
+package gameoflifetest;
+
+import java.awt.*;
 import java.util.ArrayList;
 import javax.swing.JFrame;
 import javax.swing.JPanel;
@@ -9,16 +12,8 @@ import java.awt.event.MouseAdapter;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
 import java.awt.event.MouseEvent;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.Shape;
 import java.awt.geom.RectangularShape;
 import java.awt.geom.GeneralPath;
-import java.awt.Point;
-import java.awt.Label;
-import java.awt.Font;
-import java.awt.Color;
-import java.awt.Rectangle;
 
 /**
  Eine Klasse zu pädagogischen Zwecken.
@@ -26,7 +21,7 @@ import java.awt.Rectangle;
  mittels Mausklicks, das Zeichnen einfacher
  2D Objekte (java.awt.Shape), sowie die
  Ausgabe von Texten in einer Statuszeile.
- @version 3.042
+ @version 3.043
  @author Martin Hofmann und die EiP-Teams verschiedener Jahre
  */
 
@@ -57,13 +52,15 @@ public class GraphicsWindow {
      @param height Höhe des Fensters
      */
     public GraphicsWindow(int width, int height) {
-        this.width = width;
+        this.width  = width;
         this.height = height;
-        dasFenster = new JFrame();
+        dasFenster  = new JFrame();
         dasFenster.setTitle("Grafikfenster " + ++fensterNr);
         fensterZahl++;
         dasFenster.setLocationByPlatform(true);
         dasFenster.setSize(width,height+50);
+        dasFenster.getContentPane().setPreferredSize(new Dimension(width, height+50));
+        dasFenster.pack();
         dasFenster.addWindowListener(new WindowAdapter(){
             public void windowClosing(WindowEvent e) {
                 dasFenster.dispose(); // nicht gleich alle Fenster abschiessen
@@ -74,7 +71,6 @@ public class GraphicsWindow {
         label = new Label("Statuszeile...");
         label.setFont(new Font("Helvetica", Font.PLAIN, 12));
         dasFenster.getContentPane().add(label,"North" );
-
         panel = new GraphicsWindowPanel();
         //panel.setBackground(Color.cyan);
         panel.addCommand(new SetColor(activeColor));
@@ -243,11 +239,11 @@ public class GraphicsWindow {
 
     /** Löscht das Bild */
     public void clear() {
-        Color oldActive = activeColor;
+//        Color oldActive = activeColor;
         panel.clearAll();
-        this.switchToBackgroundColor();
-        fill(new Rectangle(0,0,width,height));
-        setColor(oldActive);
+//        this.switchToBackgroundColor();
+//        fill(new Rectangle(0,0,width,height));
+//        setColor(oldActive);
     }
 
     public void killIn(int secs) {
diff --git a/ws2015/eip/blaetter/05/GraphicsWindow.java b/ws2015/eip/blaetter/05/GraphicsWindow.java
index b92fdaf..2bb652d 100644
--- a/ws2015/eip/blaetter/05/GraphicsWindow.java
+++ b/ws2015/eip/blaetter/05/GraphicsWindow.java
@@ -1,3 +1,6 @@
+package gameoflifetest;
+
+import java.awt.*;
 import java.util.ArrayList;
 import javax.swing.JFrame;
 import javax.swing.JPanel;
@@ -9,16 +12,8 @@ import java.awt.event.MouseAdapter;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
 import java.awt.event.MouseEvent;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.Shape;
 import java.awt.geom.RectangularShape;
 import java.awt.geom.GeneralPath;
-import java.awt.Point;
-import java.awt.Label;
-import java.awt.Font;
-import java.awt.Color;
-import java.awt.Rectangle;
 
 /**
  Eine Klasse zu pädagogischen Zwecken.
@@ -26,7 +21,7 @@ import java.awt.Rectangle;
  mittels Mausklicks, das Zeichnen einfacher
  2D Objekte (java.awt.Shape), sowie die
  Ausgabe von Texten in einer Statuszeile.
- @version 3.042
+ @version 3.043
  @author Martin Hofmann und die EiP-Teams verschiedener Jahre
  */
 
@@ -57,13 +52,15 @@ public class GraphicsWindow {
      @param height Höhe des Fensters
      */
     public GraphicsWindow(int width, int height) {
-        this.width = width;
+        this.width  = width;
         this.height = height;
-        dasFenster = new JFrame();
+        dasFenster  = new JFrame();
         dasFenster.setTitle("Grafikfenster " + ++fensterNr);
         fensterZahl++;
         dasFenster.setLocationByPlatform(true);
         dasFenster.setSize(width,height+50);
+        dasFenster.getContentPane().setPreferredSize(new Dimension(width, height+50));
+        dasFenster.pack();
         dasFenster.addWindowListener(new WindowAdapter(){
             public void windowClosing(WindowEvent e) {
                 dasFenster.dispose(); // nicht gleich alle Fenster abschiessen
@@ -74,7 +71,6 @@ public class GraphicsWindow {
         label = new Label("Statuszeile...");
         label.setFont(new Font("Helvetica", Font.PLAIN, 12));
         dasFenster.getContentPane().add(label,"North" );
-
         panel = new GraphicsWindowPanel();
         //panel.setBackground(Color.cyan);
         panel.addCommand(new SetColor(activeColor));
@@ -243,11 +239,11 @@ public class GraphicsWindow {
 
     /** Löscht das Bild */
     public void clear() {
-        Color oldActive = activeColor;
+//        Color oldActive = activeColor;
         panel.clearAll();
-        this.switchToBackgroundColor();
-        fill(new Rectangle(0,0,width,height));
-        setColor(oldActive);
+//        this.switchToBackgroundColor();
+//        fill(new Rectangle(0,0,width,height));
+//        setColor(oldActive);
     }
 
     public void killIn(int secs) {
diff --git a/ws2015/eip/blaetter/06/GraphicsWindow.java b/ws2015/eip/blaetter/06/GraphicsWindow.java
new file mode 100644
index 0000000..2bb652d
--- /dev/null
+++ b/ws2015/eip/blaetter/06/GraphicsWindow.java
@@ -0,0 +1,393 @@
+package gameoflifetest;
+
+import java.awt.*;
+import java.util.ArrayList;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.Timer;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.event.MouseEvent;
+import java.awt.geom.RectangularShape;
+import java.awt.geom.GeneralPath;
+
+/**
+ Eine Klasse zu pädagogischen Zwecken.
+ Erlaubt die Eingabe von Punktkoordinaten
+ mittels Mausklicks, das Zeichnen einfacher
+ 2D Objekte (java.awt.Shape), sowie die
+ Ausgabe von Texten in einer Statuszeile.
+ @version 3.043
+ @author Martin Hofmann und die EiP-Teams verschiedener Jahre
+ */
+
+public class GraphicsWindow {
+
+    private int width;
+    private int height;
+    private JFrame dasFenster;
+    private static int fensterZahl;
+    private static int fensterNr;
+    private Label label;
+    private GraphicsWindowPanel panel;
+    private Point mousePos;
+    private Color activeColor = Color.BLACK;
+    final private Color backColor = Color.WHITE;
+    MyMouseAdapter mouseListener;
+
+    /**
+     Erzeugt ein Fenster der Größe 640 auf 480 mit Textausgabe, Mauseingabe und Grafikausgabe.
+     */
+    public GraphicsWindow() {
+        this(640, 480);
+    }
+
+    /**
+     Erzeugt ein Fenster in vorgegebener Größe mit Textausgabe, Mauseingabe und Grafikausgabe.
+     @param width Breite des Fensters
+     @param height Höhe des Fensters
+     */
+    public GraphicsWindow(int width, int height) {
+        this.width  = width;
+        this.height = height;
+        dasFenster  = new JFrame();
+        dasFenster.setTitle("Grafikfenster " + ++fensterNr);
+        fensterZahl++;
+        dasFenster.setLocationByPlatform(true);
+        dasFenster.setSize(width,height+50);
+        dasFenster.getContentPane().setPreferredSize(new Dimension(width, height+50));
+        dasFenster.pack();
+        dasFenster.addWindowListener(new WindowAdapter(){
+            public void windowClosing(WindowEvent e) {
+                dasFenster.dispose(); // nicht gleich alle Fenster abschiessen
+                if (--fensterZahl<1) System.exit(0);
+            }
+        });
+
+        label = new Label("Statuszeile...");
+        label.setFont(new Font("Helvetica", Font.PLAIN, 12));
+        dasFenster.getContentPane().add(label,"North" );
+        panel = new GraphicsWindowPanel();
+        //panel.setBackground(Color.cyan);
+        panel.addCommand(new SetColor(activeColor));
+        dasFenster.getContentPane().add(panel,"Center");
+        mousePos = new Point();
+        mouseListener = new MyMouseAdapter();
+        panel.addMouseListener(mouseListener);
+        clear();
+        dasFenster.setVisible(true);
+    }
+
+    /**
+     Gibt eine Zeichenkette oben im Fenster aus.
+     @param text diese Zeichenkette
+     */
+    public void setText(String text) {
+        label.setText(text);
+    }
+    /**
+     Liest den oben im Fenster angezeigten Text aus.
+     @return den Text
+     */
+    public String getText() {
+        return label.getText();
+    }
+    /**
+     Wartet auf einen Mausklick. Die Methode blockiert das
+     aufrufende Programm solange bis der Mausklick erfolgt ist.
+     @return die Koordinaten des angeklickten Punkts
+     */
+
+    public Point mouseClick() {
+        try{
+            synchronized(mouseListener){mouseListener.wait();}
+        }
+        catch(InterruptedException e){
+            e.printStackTrace();
+        }
+        return mousePos;
+    }
+
+    class MyMouseAdapter extends MouseAdapter {
+
+        /**
+         Beendet das Warten auf den Mausklick und verwertet die Koordinaten.
+         Diese Methode ist nicht für den Anwender bestimmt.
+         */
+
+        synchronized public void mouseClicked(MouseEvent e){
+            mousePos = e.getPoint();
+            notifyAll();
+        }
+    }
+
+
+    /**
+     Schaltet die Zeichenfarbe auf die Hintergrundfarbe um. Dies ist
+     das Mittel, um gezeichnete Linien wieder zu löschen.
+     */
+    public void switchToBackgroundColor(){
+        activeColor = backColor;
+        panel.addCommand(new SwitchToBackgroundColor(activeColor));
+        panel.repaint();
+    }
+
+    /**
+     Schaltet die Zeichenfarbe auf Schwarz um.
+     */
+    public void switchToForegroundColor(){
+        activeColor = Color.BLACK;
+        panel.addCommand(new SetColor(activeColor));
+        panel.repaint();
+    }
+
+
+    /** Liefert die aktuelle Zeichenfarbe.
+     @return die aktuelle Zeichenfarbe des GraphicsWindow. */
+    public Color getColor() {
+        // return panel.getGraphics().getColor(); // getGraphics() has unpleasant side-effects. :(
+                /* Fixed by adding another instance variable activeColor for now. */
+        return activeColor;
+    }
+
+    /**
+     Zeichnet eine Linie in der aktuellen Zeichenfarbe.
+     @param x Anfangspunkt
+     @param y Endpunkt
+     */
+    public void drawLine(Point x, Point y){
+        // Odering points reduces the amount of graphical artifacts in rendering the same object in different ways
+        Point x1 = x;
+        Point y1 = y;
+        if ((x.x > y.x) || ((x.x == y.x) && (x.y > y.y))) {
+            x1 = y;
+            y1 = x;
+        }
+        panel.addCommand(new DrawLine(x1,y1));
+        panel.repaint();
+    }
+
+    /**
+     Zeichnet einen Punkt in der aktuellen Zeichenfarbe.
+     @param p Punkt
+     */
+    public void drawPoint(Point p){
+        drawLine(p, p);
+    }
+
+    /**
+     Zeichnet einen Punkt in der aktuellen Zeichenfarbe.
+     @param p Punkt
+     */
+    public void drawStringAt(String s, Point p){
+        Command c = new DrawString(s,p);
+        panel.addCommand(c);
+        panel.repaint();
+    }
+
+    /**
+     Zeichnet ein geometrisches Objekt.
+     */
+    public void draw(Shape s) {
+        panel.addCommand(new Draw(s));
+        panel.repaint();
+    }
+
+    /**
+     Füllt ein geometrisches Objekt aus.
+     */
+    public void fill(Shape s) {
+        panel.addCommand(new Fill(s));
+        panel.repaint();
+    }
+
+    /** Das aufrufende Programm wird für ein gegebene Zeitspanne blockiert.
+     @param millis Die Zeitspanne in Millisekunden*/
+    public void sleep(long millis) {
+        try {Thread.sleep(millis);} catch (Exception e){}
+    }
+
+    /** Setzt die Zeichenfarbe. */
+    public void setColor(Color d) {
+        activeColor = d;
+        panel.addCommand(new SetColor(activeColor));
+        panel.repaint();
+    }
+
+    /**
+     Setzt die Zeichenfarbe auf einen Grauwert
+     @param shade Grauwert zwischen 0(schwarz) und 255(weiß)
+     */
+    public void setGrayColor(int shade) {
+        setColor(new Color(shade, shade, shade));
+    }
+
+    /**
+     Setzt die Zeichenfarbe für die Mandelbrot-Aufgabe
+     @param n Anzahl der Iterationen, die durch die Farbe symboliziert werdem soll
+     */
+    public void setMandelColor(int n) {
+        float r = (float) Math.min(1.0,((double) n / 9.0) );
+        float g = (float) Math.min(1.0,((double) n / 99.0) );
+        float b = (float) Math.min(1.0,((double) n / 999.0) );
+        setColor(new Color(r, g, b));
+    }
+
+    /** Löscht das Bild */
+    public void clear() {
+//        Color oldActive = activeColor;
+        panel.clearAll();
+//        this.switchToBackgroundColor();
+//        fill(new Rectangle(0,0,width,height));
+//        setColor(oldActive);
+    }
+
+    public void killIn(int secs) {
+        Timer t  = new Timer(1000*secs, new ActionListener(){
+            @Override
+            public void actionPerformed(ActionEvent e) {dasFenster.dispose();}
+        }
+        );
+        t.setRepeats(false);
+        t.start();
+    }
+}
+
+
+class GraphicsWindowPanel extends JPanel
+{
+    private static final long serialVersionUID = 1L;
+    private ArrayList<Command> cl = new ArrayList<Command>();
+
+    public void paintComponent(Graphics g)
+    {
+        super.paintComponent(g);
+        Graphics2D g2D = (Graphics2D)g;
+
+        ArrayList<Command> cl = this.cl; // Kopie wegen Nebenläufigkeit von Swing
+        int size = cl.size();
+        for (int i=0; i<size; i++) {
+            Command c = cl.get(i);
+            if (c != null) c.execute(g2D);
+        }
+    }
+
+    void addCommand(Command c)
+    {
+        cl.add(c);
+    }
+
+    void clearAll()
+    {
+//              try {
+//                      SwingUtilities.invokeAndWait(new Runnable() {
+//                              @Override
+//                              public void run() {
+        cl = new ArrayList<Command>();
+//                              }
+//                      });
+//              } catch (InterruptedException e) {
+//                      // TODO Auto-generated catch block
+//                      e.printStackTrace();
+//              } catch (InvocationTargetException e) {
+//                      // TODO Auto-generated catch block
+//                      e.printStackTrace();
+//              }
+    }
+}
+
+
+abstract class Command //implements Serializable
+{
+    abstract  void execute(Graphics2D g2D);
+
+    /** Clone a shape. This method is needed because Shape
+     * does not define clone(), although many shape classes do.
+     * Kopiert aus jsky-2.6 auf ftp.eso.org */
+    static Shape cloneShape(Shape s) {
+        // FIXME Add more specific shapes
+        if (s instanceof RectangularShape) {
+            return (RectangularShape) ((RectangularShape) s).clone();
+        } else {
+            return new GeneralPath(s);
+        }
+    }
+
+}
+
+class DrawLine extends Command {
+    Point von;
+    Point bis;
+    DrawLine(Point von, Point bis) {
+                /* Clonen der Punkte essentiell um Aliasingeffekte beim Redraw zu verhindern */
+        this.von = new Point(von);
+        this.bis = new Point(bis);
+    }
+    void execute(Graphics2D g2D)
+    {
+        g2D.drawLine(this.von.x,this.von.y,this.bis.x,this.bis.y);
+    }
+}
+
+class SwitchToForegroundColor extends Command {
+    SwitchToForegroundColor() {}
+    void execute(Graphics2D g2D) {
+        g2D.setColor(Color.black);
+    }
+}
+
+class SwitchToBackgroundColor extends Command {
+    Color backcolor;
+    SwitchToBackgroundColor(Color backcolor) {this.backcolor = backcolor;}
+    void execute(Graphics2D g2D) {
+        g2D.setColor(backcolor);
+    }
+}
+
+class SetColor extends Command {
+    Color color;
+    SetColor(Color color) {this.color = color;}
+    void execute(Graphics2D g2D) {
+        g2D.setColor(this.color);
+    }
+}
+
+
+class Draw extends Command {
+    Shape shape;
+    Draw(Shape shape) {this.shape = cloneShape(shape);}
+    void execute(Graphics2D g2D) {
+        g2D.draw(this.shape);
+    }
+}
+
+class Fill extends Command {
+    Shape shape;
+    Fill(Shape shape) {this.shape = cloneShape(shape);}
+    void execute(Graphics2D g2D) {
+        g2D.fill(this.shape);
+    }
+}
+
+class DrawString extends Command {
+    String string;
+    Point position;
+    DrawString(String string, Point position) {this.string = string; this.position = position;}
+    @Override
+    void execute(Graphics2D g2D) {
+        g2D.drawString(string, position.x, position.y);
+    }
+}
+
+
+
+
+
+
+
+
+
-- 
cgit v1.2.3