/**
   Klasse Draw<BR>  <BR>
   Sprache:  JAVA<BR>
   Autor:    Fabian Wleklinski, Martin Klossek, Martin Meedt<BR>
   Datum:    23.05.1999<BR>
   Funktion: Hauptklasse des JavaMalprogramms

   <BR>&nbsp;<BR>

   Klasse ist Zeichenbrett und Steuerzentrale des einfachen JavaMalprogramms
*/

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;

/** Klasse Draw: Zeichenbrett und Steuerzentrale */
public class Draw extends Applet {

 // Variablendeklaration
  Draw appletThis = null; // Dummy
  Frame appFrame = null; // Unser Frame im ApplicationMode -> Für Parentfeld der Dialoge
  boolean ApplicationMode = false; // Applikation oder Applet?

  TPaint Paint; // Objekt nimmt die Grafikelemente auf
  Dimension dSize; // Temporäre Größe der Zeichenfläche
  int MouseX, MouseY; // Temporäre Mauskoordinaten 
  int startx, starty, endx, endy; // Temporäre Koordinaten des neuen Zeichenobjekts
  boolean ShiftPressed = false; // Shift-gedrückt-Flag
  Image img_surface; // Buffering
  Graphics g_surface; // Buffering
  boolean moving_workplace = false; // Workspace-Wird-Bewegt-Flag  
  boolean selecting_object = false; // Objekt-Auswahl-Modus

  int drawing_Object = -1; // -1 = kein Objekt, 1 = Linie, 2 = Rechteck, 3 = Kreis, 22 = gefülltes Rechteck, 33 = gefüllter Kreis
  boolean creating_Object = false; // Flag, ob gemalt wird

  Color [] color_set; // Die zur Verfügung stehenden Farben
  boolean draw_filled = false; // gefüllt oder umrandet zeichnen

  MediaTracker dMediaTracker = null; // Der MediaTracker für die bmps
  TRect rect_toolbar = null; // Toolbarabmessungen
  TRect rect_innertoolbar = null; // Das Innere der Toolbar (Icons)
  boolean moving_toolbar = false; // Flag gesetzt, wenn Toolbar bewegt wird
  Image img_toolbar = null; // Das Image-Objekt für die Toolbar
  Image [] img_toolpixhigh; // Die High-Pix der Toolbar
  Image [] img_toolpixpressed; // Die Pressed-Pix der Toolbar
  Image [] img_toolpixhighpressed; // Die HighPressed-Pix der Toolbar
  int oldActiveToolPix = -1; // Vorhergehendes Toolbar-Pix (für Flickerreduktion)
  int activeToolPix = -1; // Kein Toolbar-Pix wird gezeichnet

  TRect rect_stylebar = null; // Toolbarabmessungen
  TRect rect_innerstylebar = null; // Das Innere der Toolbar (Icons)
  boolean moving_stylebar = false; // Flag gesetzt, wenn Toolbar bewegt wird
  Image img_stylebar = null; // Das Image-Objekt für die Stylebar
  Image img_colorpanel = null; // Das Panel für die Colorauswahl
  int color_picking = -1; // Flag, ob und welche Farbe gewählt wird (1=Vorder, 2=Hinter)

 /** Mit dieser Methode wird der Applikations-/Appletmodus gesetzt
   * @param boolean Mit true wird der Applikationsmodus gesetzt, mit false der Appletmodus
   * @param Frame Der Frame, in dem wir im Applikationsmodus dargestellt werden
   */
 public void setApplicationMode (boolean AppMode, Frame AppFrame) {
    ApplicationMode = AppMode;
    appFrame = AppFrame;
 }

 /** Der Action-Listener lauscht den UI-Actions */
/* class ButtonListener implements ActionListener {
  public void actionPerformed( ActionEvent e ) {
     if (e.getActionCommand().equals("OK")) { 
     }
  }
 } */

 // Tastatur-Handling
 KeyListener unserKeyListener = new KeyAdapter()
 {
    public void keyPressed(KeyEvent e) { // Taste gedrückt
       if (e.getKeyCode()==KeyEvent.VK_SHIFT) { 
          if (!ShiftPressed) {
             ShiftPressed = true; 
             if (creating_Object) { repaint(); } // Beim Objekt malen, redrawen -> smooth
          }
          ShiftPressed = true; 
       }
    }
    public void keyReleased(KeyEvent e) { // Taste losgelassen
       if (e.getKeyCode()==KeyEvent.VK_SHIFT) { 
          if (ShiftPressed) {
             ShiftPressed = false;
             if (creating_Object) { repaint(); } // Beim Objekt malen, redrawen -> smooth
          }
          ShiftPressed = false;
       }
       if (e.getKeyCode()==KeyEvent.VK_DELETE) { 
         // Wenn Objekt markiert, dann entfernen und neuzeichnen!
//System.out.println ("MUUUUH");
          TGraphic Graphic;
          for (int i = 0; i<Paint.PaintWorkplace().count();i++){
             if (Paint.PaintWorkplace().getItem(i).isSelected) {
//System.out.println ("MUUUUHSSSS");

                Paint.PaintWorkplace().delete(i);
             }
          }
          repaint(); 
       } 
    }
 };

 // Mouse-Handling
 MouseListener unserMouseListener = new MouseAdapter()
 {
    public void mousePressed(MouseEvent e) { // Mouse gedrückt
       MouseX = e.getX();   MouseY = e.getY();       
 
      // Die Statusvariablen/-flags resetten
       creating_Object = false;
       moving_toolbar = false;
       moving_stylebar = false;
       moving_workplace = false;
       color_picking = -1;

      // Ist Mauscursor in der Toolbar
       if (rect_toolbar.IsIn (MouseX, MouseY)) {
            // Ist der Mauscursor am Rand der Toolbar 
             if (!rect_innertoolbar.IsIn (MouseX, MouseY)) {
                moving_toolbar = true;
            // Hier ist der Mauscursor auf den Buttons
             } else {

               // Berechnen, welcher gedrückt wurde
                int col = (MouseX - rect_innertoolbar.x) / 25;
                int row = (MouseY - rect_innertoolbar.y) / 25;
                oldActiveToolPix = activeToolPix;
                activeToolPix = -1; // col + row*3;          

               // ZOOM, Scrollen, Löschen
                if (row==0) {
                   switch (col) { 
                   case 0: // ZEIGER-SYMBOL -> BENUTZEN WIR ZUM VERSCHIEBEN DES WORKSPACE
                      drawing_Object = -1;
                      selecting_object = false;
		      // creating_Object = -1;
                      break;                      
                   case 1: // ZOOM -> RÜCK MIT ShiftPressed
                      selecting_object = false;
                      if (!ShiftPressed) { // VERGRÖßERN
                         Paint.PaintSettings().Xratio = Paint.PaintSettings().Xratio * Math.sqrt(2);
                         Paint.PaintSettings().Yratio = Paint.PaintSettings().Yratio * Math.sqrt(2);
                         repaint();
                      } else { // VERKLEINERN
                         Paint.PaintSettings().Xratio = Paint.PaintSettings().Xratio / Math.sqrt(2);
                         if ( double2pixX (Paint.PaintSettings().maxX)+1 < getSize().width -1 ) {
                            Paint.PaintSettings().mapStartX = 0;
                         }
                         Paint.PaintSettings().Yratio = Paint.PaintSettings().Yratio / Math.sqrt(2);
                         if ( double2pixY (Paint.PaintSettings().maxY)+1 < getSize().height -1 ) {
                            Paint.PaintSettings().mapStartY = 0;
                         }
                         repaint();
                      }
                      break;
                   case 2: // RADIERGUMMI-SYMBOL -> OBJEKTAUWAHL, LÖSCHEN MIT ENTF-TASTE
                      selecting_object = true;
                      drawing_Object = -1;
                      break;                      
                   }
                }

               // Neu, Öffnen, Speichern:
                if (row==1) {
                   switch (col) { 
                   case 0: // NEU
                      selecting_object = false;
                      TNewDrawBox NewDrawBox = new TNewDrawBox(); // New-Dialog
                      NewDrawBox.setPreset ((long)Paint.PaintSettings().maxX+1, (long)Paint.PaintSettings().maxY+1);
                      NewDrawBox.show();
                      if (NewDrawBox.result==1) { // OK gedrückt
                          Paint.PaintWorkplace().clear();
                          Paint.PaintSettings().Xratio = 1;
		          Paint.PaintSettings().Yratio = 1;
                          Paint.PaintSettings().mapStartX = 0;
                          Paint.PaintSettings().mapStartY = 0;
                          Paint.PaintSettings().maxX = (double)NewDrawBox.NewWidth -1;
                          Paint.PaintSettings().maxY = (double)NewDrawBox.NewHeight -1; 
                          repaint();
                      }
                      break;                      
                   case 1: // LADEN (nur als Applikation)
                      if (ApplicationMode) {
                         removeKeyListener(unserKeyListener); 
                         FileDialog OpenFileDialog = new FileDialog (appFrame, "Bitte wählen Sie eine Datei zum Öffnen", FileDialog.LOAD);
                         OpenFileDialog.show();
                         if (OpenFileDialog.getFile()!=null) {
                            try {
                               Paint.loadFromFile( OpenFileDialog.getDirectory()+OpenFileDialog.getFile() ); 
                               repaint();
                            } catch (java.io.StreamCorruptedException ex1) { 
                               System.out.println ("Konnte Datei nicht öffnen.");
                               new MessageBox ("Datei-Lese-Fehler", "Die Datei >"+OpenFileDialog.getFile()+"< konnte nicht geöffnet werden.").show();
                            } catch (java.io.IOException ex2) {
                               System.out.println ("Konnte Datei nicht öffnen.");
                               new MessageBox ("Datei-Lese-Fehler", "Die Datei >"+OpenFileDialog.getFile()+"< konnte nicht geöffnet werden.").show();
                            } catch (java.lang.ClassNotFoundException ex3) {
                               System.out.println ("Formatfehler.");
                               new MessageBox ("Datei-Format-Fehler", "Die Datei >"+OpenFileDialog.getFile()+"< enthält ungültige Elemente.").show();
                            }
                         }
                         addKeyListener(unserKeyListener); 
                      }
                      break;   
                   case 2: // SPEICHERN (nur als Applikation)
                      if (ApplicationMode) {
                         FileDialog SaveFileDialog = new FileDialog (appFrame, "Bitte wählen Sie eine Datei zum Speichern", FileDialog.SAVE);
                         SaveFileDialog.show();
                         if (SaveFileDialog.getFile()!=null) {
                            try {
                               Paint.saveToFile( SaveFileDialog.getDirectory()+SaveFileDialog.getFile() ); 
                            } catch (java.io.FileNotFoundException ex1) { 
                               System.out.println ("Konnte Datei nicht speichern.");
                               new MessageBox ("Datei-Schreib-Fehler", "Die Datei >"+SaveFileDialog.getFile()+"< konnte nicht gespeichert werden.").show();
                            } catch (java.io.IOException ex2) {
                               System.out.println ("Konnte Datei nicht speichern.");
                               new MessageBox ("Datei-Schreib-Fehler", "Die Datei >"+SaveFileDialog.getFile()+"< konnte nicht gespeichert werden.").show();
                            }
                         }
                      }
                      break;
                   }
                }        

               // Wurde untere Reihe gewählt, dann: Welches Zeichenobjekt wurde gewählt     
                if (row==2) { 
                   selecting_object = false;
                   switch (col) {
                   case 0: // LINIE 
                      drawing_Object = 1; 
                      break;
                   case 1: // RECHTECK
                      if (draw_filled) { 
                         drawing_Object = 22;
                      } else {
                         drawing_Object = 2; 
                      }
                      break;
                   case 2: // KREIS
                      if (draw_filled) { 
                         drawing_Object = 33;
                      } else {
                         drawing_Object = 3;
                      }
                      break;
                   }
                } 

                repaint();
             }
      // Ist Cursor in Stylebar?
       } else if (rect_stylebar.IsIn (MouseX, MouseY)) {
         // Ist der Mauscursor am Rand der Stylebar?            
          if (!rect_innerstylebar.IsIn (MouseX, MouseY)) {
             moving_stylebar = true;
         // Also ist Cursor auf den Buttons -> Reaktion
          } else {
            // Berechnen, welcher gedrückt wurde
             int col = (MouseX - rect_innerstylebar.x);

            // Filled-Status-Button
             if (col<25) {
                if (draw_filled) {
                   draw_filled = false;
                   if (drawing_Object == 22) { drawing_Object = 2; }
                   if (drawing_Object == 33) { drawing_Object = 3; }
                } else {
                   draw_filled = true;
                   if (drawing_Object == 2) { drawing_Object = 22; }
                   if (drawing_Object == 3) { drawing_Object = 33; }
                }
                repaint();
             }
            // Erster ColorPicker -> Vordergrund
             if ((col>24) && (col<67)) {
                color_picking = 1;
                repaint();
             }
            // Zweiter ColorPicker -> Hintergrund
             if (col>66) {
                color_picking = 2;
                repaint();
             }

             oldActiveToolPix = activeToolPix;
             activeToolPix = -1; 
          }       
      // also nicht in Tool- und Stylebar, sondern auf dem Rest der Zeichenfläche
       } else {        
          if (drawing_Object != -1) {
             creating_Object = true;
             startx = MouseX;  starty = MouseY;
          } else if (selecting_object) { // OBJEKT-FANG-MODUS
    	     TGraphic Graphic;
             boolean oneIsSelected = false;
             for (int i = Paint.PaintWorkplace().count()-1; i >= 0; i--) {
                Graphic = Paint.PaintWorkplace().getItem(i);
                if (Graphic.isInside (double2pixX(MouseX), double2pixY(MouseY), double2pixWidth(4))) {
                   if (!oneIsSelected) { Graphic.isSelected = true; oneIsSelected = true; }
                   else { Graphic.isSelected = false; } 
                   repaint();
                } else {
                   Graphic.isSelected = false;
                   repaint();
                }
             }           
          } else { // WENN NUR SO GEKLICKT, DANN WIRD WORKSPACE BEWEGT
            // Nur Scrollen, wenn die Zeichenfläche > als Fenster ist
             if (( double2pixX (Paint.PaintSettings().maxX)+1 > getSize().width -1 ) || ( double2pixY (Paint.PaintSettings().maxY)+1 > getSize().height -1 )) {
                moving_workplace = true;
             }
          }

       }
    }

    public void mouseReleased(MouseEvent e) { // Mouse gedrückt
       endx = e.getX();  endy = e.getY();

      // Objekte in Workspace einfügen
       if (creating_Object){
          int x1,x2,y1,y2;
   
          x1 = startx;    y1 = starty;
          x2 = startx - endx;   y2 = starty - endy;
          if (x2 < 0 )  { x2 = -x2; }
          if (y2 < 0 )  { y2 = -y2; }
 
         // Mit gedrückter Shift-Taste: gleiche Seitenverhältnisse
          if (ShiftPressed) {
             if (x2 < y2) { y2 = x2; }
             else { x2 = y2; }
          }
  
         // Orientierungs-Korrektur
          if (startx>endx) { x1 = x1 - x2; } 
          if (starty>endy) { y1 = y1 - y2; } 

         // Die einzelnen Objekte erzeugen
          switch ( drawing_Object ) {
          case 1: // LINIE
             Paint.PaintWorkplace().add(new TLine(pix2doubleX(startx),pix2doubleY(starty),pix2doubleX(endx),pix2doubleY(endy),Paint.PaintSettings().currentColor));
             break;
          case 2: // RECHTECK
             Paint.PaintWorkplace().add(new TRectangle(pix2doubleX(x1),pix2doubleY(y1),pix2doubleX(x2),pix2doubleY(y2),false,Paint.PaintSettings().currentColor));
             break;
          case 3: // KREIS/ELLIPSE
             Paint.PaintWorkplace().add(new TCircle(pix2doubleX(x1),pix2doubleY(y1),pix2doubleX(x2),pix2doubleY(y2),false,Paint.PaintSettings().currentColor));
             break;
          case 22: // RECHTECK GEFÜLLT
             Paint.PaintWorkplace().add(new TRectangle(pix2doubleX(x1),pix2doubleY(y1),pix2doubleX(x2),pix2doubleY(y2),true,Paint.PaintSettings().currentColor));
             break;
          case 33: // KREIS/ELLIPSE GEFÜLLT
             Paint.PaintWorkplace().add(new TCircle(pix2doubleX(x1),pix2doubleY(y1),pix2doubleX(x2),pix2doubleY(y2),true,Paint.PaintSettings().currentColor));
             break;
          }   
       } else if (color_picking > 0) {
         // Farbe holen
          if (new TRect (rect_innerstylebar.x + 25 + ((color_picking-1)*42), 
                         rect_innerstylebar.y + rect_innerstylebar.height, 
                         42, 177 ).IsIn (endx, endy)) {
             if (color_picking==1) {
                int new_color_num = (endy - rect_innerstylebar.y - rect_innerstylebar.height) / 13; 
                if (new_color_num > 12) { new_color_num = 12; }
                Paint.PaintSettings().currentColor = color_set[new_color_num];
             } else {
                int new_color_num = (endy - rect_innerstylebar.y - rect_innerstylebar.height) / 13; 
                if (new_color_num > 12) { new_color_num = 12; }
                Paint.PaintSettings().currentBGColor = color_set[new_color_num];
             }
          }
          repaint();
       }       

      // Statusflags resetten
       moving_toolbar = false;
       moving_stylebar = false;
       creating_Object = false;     
       moving_workplace = false;
       color_picking = -1;
    }

    public void mouseClicked(MouseEvent e) { // Zurücksetzen
       MouseX = e.getX();   MouseY = e.getY();    // if (e.getClickCount()==2) { // Bei Doppelklick

       /*} else if (activeToolPix != -1) { 
          activeToolPix = -1;  
          repaint(); 
       }*/
    }
 };

 // Mousebewegungshandling
 MouseMotionListener unserMotionListener = new MouseMotionAdapter()
 {
    // Methode wird aufgerufen, wenn sich der Mauscursor bewegt hat (nicht gedragt!)
    public void mouseMoved(MouseEvent e) {
       MouseX = e.getX();   MouseY = e.getY();
             
      // High-Lighting der Buttons implementieren    
       if (rect_innertoolbar.IsIn(MouseX,MouseY)) {
 
         // Jetzt checken, welcher Button gedrawt werden muß
          int col = (MouseX - rect_innertoolbar.x) / 25;
          int row = (MouseY - rect_innertoolbar.y) / 25;
          oldActiveToolPix = activeToolPix;
          activeToolPix = col + row*3;          
          if (oldActiveToolPix != activeToolPix) { repaint(); }

       } else if (rect_innerstylebar.IsIn(MouseX,MouseY)) {
          if (MouseX-rect_innerstylebar.x < 25) {
             oldActiveToolPix = activeToolPix;
             activeToolPix = 9; // Der Filled-Button
             repaint();
          } else {
             oldActiveToolPix = activeToolPix;    
             activeToolPix = -1;  
             repaint();
          }
       } else if (activeToolPix != -1) { 
          oldActiveToolPix = activeToolPix;
          activeToolPix = -1;  
          repaint();
       }
    }

    // Methode wird beim Draggen (gedrückter Mausbutton+Bewegung) aufgerufen
    public void mouseDragged(MouseEvent e) {
 
      // Abmessungen unserer Zeichenfläche holen
       dSize = getSize (); // .height, .width sind die Maße...

      // Toolbar wird bewegt
       if (moving_toolbar) {
          rect_toolbar.x -= MouseX - e.getX();
          if (rect_toolbar.x + rect_toolbar.width/2 > dSize.width) {
             rect_toolbar.x = dSize.width - rect_toolbar.width/2;
          }
          if (rect_toolbar.x + rect_toolbar.width/2 < 0) {
             rect_toolbar.x = - rect_toolbar.width/2;
          }
          rect_toolbar.y -= MouseY - e.getY();
          if (rect_toolbar.y + rect_toolbar.height/2 > dSize.height) {
             rect_toolbar.y = dSize.height - rect_toolbar.height/2;
          }
          if (rect_toolbar.y < 0) {
             rect_toolbar.y = 0;
          }
          rect_innertoolbar.x = rect_toolbar.x+5;
          rect_innertoolbar.y = rect_toolbar.y+20;

          repaint();

          MouseX = e.getX(); // Neue "alte" Werte Zwischenspeichern
          MouseY = e.getY();
      // Stylebar wird bewegt
       } else if (moving_stylebar) {
          rect_stylebar.x -= MouseX - e.getX();
          if (rect_stylebar.x + rect_stylebar.width/2 > dSize.width) {
             rect_stylebar.x = dSize.width - rect_stylebar.width/2;
          }
          if (rect_stylebar.x + rect_stylebar.width/2 < 0) {
             rect_stylebar.x = - rect_stylebar.width/2;
          }
          rect_stylebar.y -= MouseY - e.getY();
          if (rect_stylebar.y + rect_stylebar.height/2 > dSize.height) {
             rect_stylebar.y = dSize.height - rect_stylebar.height/2;
          }
          if (rect_stylebar.y < 0) {
             rect_stylebar.y = 0;
          }
          rect_innerstylebar.x = rect_stylebar.x+5;
          rect_innerstylebar.y = rect_stylebar.y+20;

          repaint();

          MouseX = e.getX(); // Neue "alte" Werte Zwischenspeichern
          MouseY = e.getY();
      // Grafikelement wird erzeugt
       } else if (creating_Object) {
             switch (drawing_Object) {
             default:
                startx = MouseX;  starty = MouseY;
                endx = e.getX();  endy = e.getY();
                repaint();
                break;
             }
       } else if (moving_workplace) { // SCROLLEN
        
          if ( double2pixX (Paint.PaintSettings().maxX)+1 > getSize().width -1 ) {
             Paint.PaintSettings().mapStartX += (MouseX - e.getX()) / Paint.PaintSettings().Xratio;
             if (Paint.PaintSettings().mapStartX < 0) { Paint.PaintSettings().mapStartX = 0; }
             if (Paint.PaintSettings().mapStartX + 1 + (getSize().width / Paint.PaintSettings().Xratio) > Paint.PaintSettings().maxX) { 
                Paint.PaintSettings().mapStartX = Paint.PaintSettings().maxX - (getSize().width / Paint.PaintSettings().Xratio);
             }
          }
         
          if ( double2pixY (Paint.PaintSettings().maxY)+1 > getSize().height -1 ) {
             Paint.PaintSettings().mapStartY += (MouseY - e.getY()) / Paint.PaintSettings().Yratio;
             if (Paint.PaintSettings().mapStartY < 0) { Paint.PaintSettings().mapStartY = 0; }
             if (Paint.PaintSettings().mapStartY + 1 + (getSize().height / Paint.PaintSettings().Yratio) > Paint.PaintSettings().maxY) { 
                Paint.PaintSettings().mapStartY = Paint.PaintSettings().maxY - (getSize().height / Paint.PaintSettings().Yratio);
             }
          }

          repaint();   
          MouseX = e.getX();  MouseY = e.getY();
       }        
    }
 };

 /** Rechnet Reele Zahl aus Koordinatensystem in X-Pixel um 
   * @param double Der Wert in Reeler Zahl, der in Pixel umgerechnet werden soll
   */
 private int double2pixX ( double x ) {
    int w = (int) ( (x - Paint.PaintSettings().mapStartX) * Paint.PaintSettings().Xratio );
    return (w);
 }

 /** Rechnet Reele Zahl aus Koordinatensystem in Y-Pixel um 
   * @param double Der Wert in Reeler Zahl, der in Pixel umgerechnet werden soll
   */
 private int double2pixY ( double y ) {
    int w = (int) ( (y - Paint.PaintSettings().mapStartY) * Paint.PaintSettings().Yratio );
    return (w);
 }

 /** Rechnet Breite als Reele Zahl aus Koordinatensystem in Pixelanzahl um 
   * @param double Der Wert in Reeler Zahl, der in Pixel umgerechnet werden soll
   */
 private int double2pixWidth ( double x ) {
    int w = (int) ( x * Paint.PaintSettings().Xratio );
    return (w);
 }

 /** Rechnet Reele Zahl aus Koordinatensystem in Y-Pixel um 
   * @param double Der Wert in Reeler Zahl, der in Pixel umgerechnet werden soll
   */
 private int double2pixHeight ( double y ) {
    int w = (int) ( y * Paint.PaintSettings().Yratio );
    return (w);
 }

 /** Rechnet X-Pixelangabe in Reele Zahl des Koordinatensystems um
   * @param int Der Pixel, der in die reele Zahl umgerechnet werdeb soll
   */
 private double pix2doubleX ( int x ) {
    double w = (double) ( (x / Paint.PaintSettings().Xratio) + Paint.PaintSettings().mapStartX );
    return (w);
 }

 /** Rechnet Y-Pixelangabe in Reele Zahl des Koordinatensystems um
   * @param int Der Pixel, der in die reele Zahl umgerechnet werdeb soll
   */
 private double pix2doubleY ( int y ) {
    // double w = (double) (y * (Paint.PaintSettings().mapEndY - Paint.PaintSettings().mapStartY +1) / getSize().height + Paint.PaintSettings().mapStartY);
    double w = (double) ( (y / Paint.PaintSettings().Yratio) + Paint.PaintSettings().mapStartY );
    return (w);
 }

 /** Die Paint-Methode des JavaMalprogramms
   * @param Graphics Das Java-Grafik-Ausgabe-Objekt 
   */  
 public void paint (Graphics g) {

   // Zeichen der einzelnen Bildschirmelemente:

   // 1. Alte aus Datenbank zeichnen
    TGraphic Graphic;
    if (Paint.PaintWorkplace().count() > 0) {
       for (int i = 0; i<Paint.PaintWorkplace().count();i++){
          Graphic = Paint.PaintWorkplace().getItem(i);

          if (Graphic instanceof TLine) {
             g.setColor(((TLine)Graphic).Pen().color);
             g.drawLine (double2pixX(((TLine)Graphic).x1),double2pixY(((TLine)Graphic).y1),double2pixX(((TLine)Graphic).x2),double2pixY(((TLine)Graphic).y2));
             if (Graphic.isSelected) { 
                g.setColor (new Color(0,0,190));
                g.fillRect (double2pixX(((TLine)Graphic).x1)-2, double2pixY(((TLine)Graphic).y1)-2, 5, 5);
             }
          }
          if (Graphic instanceof TCircle) {
             g.setColor(((TCircle)Graphic).Pen().color);
             if (((TCircle)Graphic).filled){
                g.fillOval (double2pixX(((TCircle)Graphic).x),double2pixY(((TCircle)Graphic).y),double2pixWidth(((TCircle)Graphic).xradius),double2pixHeight(((TCircle)Graphic).yradius));
             } else {
                g.drawOval (double2pixX(((TCircle)Graphic).x),double2pixY(((TCircle)Graphic).y),double2pixWidth(((TCircle)Graphic).xradius),double2pixHeight(((TCircle)Graphic).yradius));
             }
             if (Graphic.isSelected) { 
                g.setColor (new Color(0,0,190));
                g.fillRect (double2pixX(((TCircle)Graphic).x)-2, double2pixY(((TCircle)Graphic).y)-2, 5, 5);
             }
          }
          if (Graphic instanceof TRectangle) {
             g.setColor(((TRectangle)Graphic).Pen().color);
             if (((TRectangle)Graphic).filled){
                g.fillRect (double2pixX(((TRectangle)Graphic).x),double2pixY(((TRectangle)Graphic).y),double2pixWidth(((TRectangle)Graphic).width),double2pixHeight(((TRectangle)Graphic).height));
             } else {
                g.drawRect (double2pixX(((TRectangle)Graphic).x),double2pixY(((TRectangle)Graphic).y),double2pixWidth(((TRectangle)Graphic).width),double2pixHeight(((TRectangle)Graphic).height));
             }
             if (Graphic.isSelected) { 
                g.setColor (new Color(0,0,190));
                g.fillRect (double2pixX(((TRectangle)Graphic).x)-2, double2pixY(((TRectangle)Graphic).y)-2, 5, 5);
             }
          }
       }
    }


   // 2. Aktuelles Zeichenobjekt ausgeben
    int x, y, breite, hoehe;
    x = startx;   y = starty;
    breite = endx - startx;   hoehe =  endy - starty;
    if (breite < 0 )  { breite = -breite;}
    if (hoehe < 0 )  { hoehe = -hoehe;}

   // Mit gedrückter Shift-Taste: gleiche Seitenverhältnisse
    if (ShiftPressed) {
       if (breite < hoehe) {hoehe = breite;}
       else {breite = hoehe;}
    }

   // Orientierungs-Korrektur
    if (startx>endx) { x = startx - breite; } else { x = startx; }
    if (starty>endy) { y = starty - hoehe; } else { y = starty; }

    if (creating_Object) {
       switch (drawing_Object) {
       case 1: // LINIE
          g.setColor ( Paint.PaintSettings().currentColor );
          g.drawLine ( startx, starty, endx, endy );
          break;
       case 2: //Rechteck
          g.setColor ( Paint.PaintSettings().currentColor );            
          g.drawRect ( x, y, breite, hoehe );
          break;
       case 3: //Kreis
          g.setColor ( Paint.PaintSettings().currentColor );
          g.drawOval ( x, y, breite, hoehe );
          break;
       case 22: //gefülltes Rechteck
          g.setColor ( Paint.PaintSettings().currentColor );
          g.fillRect ( x, y, breite, hoehe );
          break;
       case 33: //gefülter Kreis
          g.setColor ( Paint.PaintSettings().currentColor );
          g.fillOval ( x, y, breite, hoehe );
          break;
       }
    }    

   // Wenn Zeichenfläche kleiner als Frame ist, dann graue Freiflächen einzeichnen
    if (( double2pixX (Paint.PaintSettings().maxX)+1 < getSize().width -1 ) || ( double2pixY (Paint.PaintSettings().maxY)+1 < getSize().height -1 )) {
       g.setColor (new Color(80,80,80));
       g.fillRect ( double2pixX (Paint.PaintSettings().maxX)+1, 0, getSize().width - double2pixX(Paint.PaintSettings().maxX)+1, getSize().height );
       g.fillRect ( 0, double2pixY (Paint.PaintSettings().maxY)+1, double2pixX (Paint.PaintSettings().maxX)+1, getSize().height - double2pixY (Paint.PaintSettings().maxY)+1);
    }


   // 3. Stylebar wird über Bild gezeichnet
    g.drawImage ( img_stylebar, rect_stylebar.x, rect_stylebar.y, appletThis );
    g.setColor ( Paint.PaintSettings().currentColor );
    g.fillRect ( rect_innerstylebar.x + 30, rect_innerstylebar.y + 6, 24, 12);
    g.setColor ( Paint.PaintSettings().currentBGColor );
    g.fillRect ( rect_innerstylebar.x + 72, rect_innerstylebar.y + 6, 24, 12);

   // Filled-Button, wenn nötig
    if (activeToolPix != 9) {
       if (draw_filled) {
          g.drawImage ( img_toolpixpressed[9], rect_innerstylebar.x, rect_innerstylebar.y, appletThis );
       }
    } else { // if == 9
       if (draw_filled) {
          g.drawImage ( img_toolpixhighpressed[9], rect_innerstylebar.x, rect_innerstylebar.y, appletThis );
       } else {
          g.drawImage ( img_toolpixhigh[9], rect_innerstylebar.x, rect_innerstylebar.y, appletThis );
       }
    }

   // Wenn color_picker, dann malen
    if (color_picking > 0) { // Vordergrund- oder Hintergrundfarbe auswählen
      // Panel zeichnen        
       g.drawImage ( img_colorpanel, rect_innerstylebar.x + 25 + ((color_picking-1)*42), rect_innerstylebar.y + rect_innerstylebar.height, appletThis );

      // Die Farbbalken zeichnen
       int i = 0;
       for (i = 0; i < 13; i++) {
          g.setColor ( color_set[i] );
          g.fillRect ( rect_innerstylebar.x + 30 + ((color_picking-1)*42), rect_innerstylebar.y + rect_innerstylebar.height + 5 + i*13, 31, 11);
       } 
    }


   // 4. Toolbar wird über Bild und StyleBar gezeichnet
    g.drawImage ( img_toolbar, rect_toolbar.x, rect_toolbar.y, appletThis );

    if ((activeToolPix == 0) || (activeToolPix == 1) || (activeToolPix == 3) 
            || (activeToolPix == 4) || (activeToolPix == 5)) {
       g.drawImage ( img_toolpixhigh[activeToolPix], rect_innertoolbar.x + (activeToolPix%3)*25, rect_innertoolbar.y + (activeToolPix / 3) * 25, appletThis );
    } // Die ersten 6 Buttons

    if (activeToolPix != 2) {
       if (selecting_object) {
          g.drawImage ( img_toolpixpressed[2], rect_innertoolbar.x +50, rect_innertoolbar.y, appletThis );
       }
    } else { // if == 2
       if (selecting_object) {
          // g.drawImage ( img_toolpixhighpressed[2], rect_innertoolbar.x +50, rect_innertoolbar.y, appletThis );
          g.drawImage ( img_toolpixpressed[2], rect_innertoolbar.x +50, rect_innertoolbar.y, appletThis );
       } else {
          g.drawImage ( img_toolpixhigh[2], rect_innertoolbar.x +50, rect_innertoolbar.y, appletThis );
       }
    }

    if (activeToolPix != 6) {
       if (drawing_Object == 1) {
          g.drawImage ( img_toolpixpressed[6], rect_innertoolbar.x, rect_innertoolbar.y +50, appletThis );
       }
    } else { // if == 6
       if (drawing_Object == 1) {
          g.drawImage ( img_toolpixhighpressed[6], rect_innertoolbar.x, rect_innertoolbar.y +50, appletThis );
       } else {
          g.drawImage ( img_toolpixhigh[6], rect_innertoolbar.x, rect_innertoolbar.y +50, appletThis );
       }
    }

    if (activeToolPix != 7) {
       if ((drawing_Object == 2) || (drawing_Object == 22)) {
          g.drawImage ( img_toolpixpressed[7], rect_innertoolbar.x +25, rect_innertoolbar.y +50, appletThis );
       }
    } else { // if == 7
       if ((drawing_Object == 2) || (drawing_Object == 22)) {
          g.drawImage ( img_toolpixhighpressed[7], rect_innertoolbar.x +25, rect_innertoolbar.y +50, appletThis );
       } else {
          g.drawImage ( img_toolpixhigh[7], rect_innertoolbar.x +25, rect_innertoolbar.y +50, appletThis );
       }
    }

    if (activeToolPix != 8) {
       if ((drawing_Object == 3) || (drawing_Object == 33)) {
          g.drawImage ( img_toolpixpressed[8], rect_innertoolbar.x +50, rect_innertoolbar.y +50, appletThis );
       }
    } else { // if == 8
       if ((drawing_Object == 3) || (drawing_Object == 33)) {
          g.drawImage ( img_toolpixhighpressed[8], rect_innertoolbar.x +50, rect_innertoolbar.y +50, appletThis );
       } else {
          g.drawImage ( img_toolpixhigh[8], rect_innertoolbar.x +50, rect_innertoolbar.y +50, appletThis );
       }
    }

 }

 /** Die Update-Methode der Klasse (ruft paint auf...)
   * @param Graphics Das Java-Grafik-Ausgabe-Objekt 
   */
 public void update (Graphics g) {

   // BufferImage anlegen, wenn nicht
    if (img_surface == null) {
       img_surface = createImage (getSize().width, getSize().height);
       Paint.PaintSettings().frameWidth = getSize().width;   Paint.PaintSettings().frameHeight = getSize().height;
       g_surface = img_surface.getGraphics();
    }

   // BufferImage resizen, wenn Frame geresizet wurde
    if ((Paint.PaintSettings().frameWidth != getSize().width) || (Paint.PaintSettings().frameHeight != getSize().height)) {
       img_surface = createImage (getSize().width, getSize().height);
       //Paint.PaintSettings().mapEndX = Paint.PaintSettings().mapStartX + (((Paint.PaintSettings().mapEndX - Paint.PaintSettings().mapStartX) * getSize().width) / Paint.PaintSettings().frameWidth);
       //Paint.PaintSettings().mapEndY = Paint.PaintSettings().mapStartY + ((Paint.PaintSettings().mapEndY - Paint.PaintSettings().mapStartY) * getSize().height / Paint.PaintSettings().frameHeight);
       Paint.PaintSettings().frameWidth = getSize().width;   Paint.PaintSettings().frameHeight = getSize().height;
       g_surface = img_surface.getGraphics();
    }       

    setBackground (Paint.PaintSettings().currentBGColor);

    dSize = getSize();
    g_surface.setColor (Paint.PaintSettings().currentBGColor);
    g_surface.fillRect (0, 0, dSize.width, dSize.height);

    paint (g_surface);
    g.drawImage (img_surface, 0, 0, appletThis);
 }


 /** Fügt ein neues Label mit den angegebenen Parametern ins Interface ein
   * @param String Die Caption des Labels
   * @param int Der Modus (Label.LEFT, Label.CENTER, Label.RIGHT) des Labels
   * @param GridBagLayout Der zu verwendende LayoutManager
   * @param GridBagConstraints Die zu verwendenden Constraints
   */
 void addLabel ( String caption, int mode, GridBagLayout layout, GridBagConstraints constr ) {
    Label dummyLabel = new Label(caption, mode);
    layout.setConstraints (dummyLabel, constr);
    add (dummyLabel);
 }

 /** Fügt ein bestehendes Label ins Interface ein
   * @param Label Das einzufügende Label
   * @param GridBagLayout Der zu verwendende LayoutManager
   * @param GridBagConstraints Die zu verwendenden Constraints
   */
 void addLabel ( Label dummyLabel, GridBagLayout layout, GridBagConstraints constr ) {
    layout.setConstraints (dummyLabel, constr);
    add (dummyLabel);
 }

 /** Fügt ein bestehendes Textfeld ins Interface ein
   * @param TextField Das einzufügende Textfeld
   * @param GridBagLayout Der zu verwendende LayoutManager
   * @param GridBagConstraints Die zu verwendenden Constraints
   */
 void addTextField ( TextField dummyTextField, GridBagLayout layout, GridBagConstraints constr ) {
    layout.setConstraints (dummyTextField, constr);
    add (dummyTextField);
 }

 /** Die Initialisierungsmethode -> plaziert UI-Elemente */
 public void init() {

   // Pointer auf Draw selbst für DrawCanvas
    appletThis = this; // Dummy
    
   // Paint-Database-Klasse von Fabian
    Paint = new TPaint();
    Paint.PaintSettings().maxX = 299;   Paint.PaintSettings().maxY = 299; // Größe der Zeichenfläche
    Paint.PaintSettings().mapStartX = 0;   Paint.PaintSettings().mapStartY = 0; // Linker oberer, sichtbarer Punkt
    Paint.PaintSettings().Xratio = 1;   Paint.PaintSettings().Yratio = 1; // ZOOM = 100% 

   // Bitmap-Arrays besetzen
    img_toolpixhigh = new Image[10];
    img_toolpixpressed = new Image[10];
    img_toolpixhighpressed = new Image[10];
    int curPix = 0;

   // Grafiken und MediaTracker initialisieren
    if (ApplicationMode) {
       img_toolbar = Toolkit.getDefaultToolkit().getImage("toolbox.gif");

       img_toolpixhigh[0] = Toolkit.getDefaultToolkit().getImage("point2.gif");
       img_toolpixhigh[1] = Toolkit.getDefaultToolkit().getImage("lupe2.gif");
       img_toolpixhigh[2] = Toolkit.getDefaultToolkit().getImage("erase2.gif");
       img_toolpixhigh[3] = Toolkit.getDefaultToolkit().getImage("new2.gif");
       img_toolpixhigh[4] = Toolkit.getDefaultToolkit().getImage("load2.gif");
       img_toolpixhigh[5] = Toolkit.getDefaultToolkit().getImage("save2.gif");
       img_toolpixhigh[6] = Toolkit.getDefaultToolkit().getImage("line2.gif");
       img_toolpixhigh[7] = Toolkit.getDefaultToolkit().getImage("rect2.gif");
       img_toolpixhigh[8] = Toolkit.getDefaultToolkit().getImage("circ2.gif");
       img_toolpixhigh[9] = Toolkit.getDefaultToolkit().getImage("filled2.gif");

       img_toolpixpressed[0] = Toolkit.getDefaultToolkit().getImage("point5.gif");
       img_toolpixpressed[1] = Toolkit.getDefaultToolkit().getImage("lupe5.gif");
       img_toolpixpressed[2] = Toolkit.getDefaultToolkit().getImage("erase5.gif");
       img_toolpixpressed[3] = Toolkit.getDefaultToolkit().getImage("new5.gif");
       img_toolpixpressed[4] = Toolkit.getDefaultToolkit().getImage("load5.gif");
       img_toolpixpressed[5] = Toolkit.getDefaultToolkit().getImage("save5.gif");
       img_toolpixpressed[6] = Toolkit.getDefaultToolkit().getImage("line5.gif");
       img_toolpixpressed[7] = Toolkit.getDefaultToolkit().getImage("rect5.gif");
       img_toolpixpressed[8] = Toolkit.getDefaultToolkit().getImage("circ5.gif");
       img_toolpixpressed[9] = Toolkit.getDefaultToolkit().getImage("filled5.gif");

       img_toolpixhighpressed[6] = Toolkit.getDefaultToolkit().getImage("line3.gif");
       img_toolpixhighpressed[7] = Toolkit.getDefaultToolkit().getImage("rect3.gif");
       img_toolpixhighpressed[8] = Toolkit.getDefaultToolkit().getImage("circ3.gif");
       img_toolpixhighpressed[9] = Toolkit.getDefaultToolkit().getImage("filled3.gif");

       img_stylebar = Toolkit.getDefaultToolkit().getImage("stylebox.gif");
       img_colorpanel = Toolkit.getDefaultToolkit().getImage("panel1.gif");
    } else {
       img_toolbar = getImage (getCodeBase(), "toolbox2.gif");

       img_toolpixhigh[0] = getImage (getCodeBase(), "point2.gif");
       img_toolpixhigh[1] = getImage (getCodeBase(), "lupe2.gif");
       img_toolpixhigh[2] = getImage (getCodeBase(), "erase2.gif");
       img_toolpixhigh[3] = getImage (getCodeBase(), "new2.gif");
       img_toolpixhigh[4] = getImage (getCodeBase(), "load4.gif");
       img_toolpixhigh[5] = getImage (getCodeBase(), "save4.gif");
       img_toolpixhigh[6] = getImage (getCodeBase(), "line2.gif");
       img_toolpixhigh[7] = getImage (getCodeBase(), "rect2.gif");
       img_toolpixhigh[8] = getImage (getCodeBase(), "circ2.gif");
       img_toolpixhigh[9] = getImage (getCodeBase(), "filled2.gif");

       img_toolpixpressed[0] = getImage (getCodeBase(), "point5.gif");
       img_toolpixpressed[1] = getImage (getCodeBase(), "lupe5.gif");
       img_toolpixpressed[2] = getImage (getCodeBase(), "erase5.gif");
       img_toolpixpressed[3] = getImage (getCodeBase(), "new5.gif");
       img_toolpixpressed[4] = null;
       img_toolpixpressed[5] = null;
       img_toolpixpressed[6] = getImage (getCodeBase(), "line5.gif");
       img_toolpixpressed[7] = getImage (getCodeBase(), "rect5.gif");
       img_toolpixpressed[8] = getImage (getCodeBase(), "circ5.gif");
       img_toolpixpressed[9] = getImage (getCodeBase(), "filled5.gif");

       img_toolpixhighpressed[0] = null;  img_toolpixhighpressed[1] = null;
       img_toolpixhighpressed[2] = null;  img_toolpixhighpressed[3] = null;
       img_toolpixhighpressed[4] = null;  img_toolpixhighpressed[5] = null;
       img_toolpixhighpressed[6] = getImage (getCodeBase(), "line3.gif");
       img_toolpixhighpressed[7] = getImage (getCodeBase(), "rect3.gif");
       img_toolpixhighpressed[8] = getImage (getCodeBase(), "circ3.gif");
       img_toolpixhighpressed[9] = getImage (getCodeBase(), "filled3.gif");

       img_stylebar = getImage (getCodeBase(), "stylebox.gif");
       img_colorpanel = getImage (getCodeBase(), "panel1.gif");
       
       dMediaTracker = new MediaTracker (this);
       if (img_toolbar!=null) { dMediaTracker.addImage (img_toolbar, 0); }
       for (curPix = 0; curPix < 10; curPix++) {
          if (img_toolpixhigh[curPix]!=null) { dMediaTracker.addImage (img_toolbar, 1+curPix); } // 1 - 10
          if (img_toolpixpressed[curPix]!=null) { dMediaTracker.addImage (img_toolbar, 11+curPix); } // 11 - 20
       }

       try {
          dMediaTracker.waitForID (0);   dMediaTracker.waitForID (1);    dMediaTracker.waitForID (2);
          dMediaTracker.waitForID (3);   dMediaTracker.waitForID (4);    dMediaTracker.waitForID (5);
          dMediaTracker.waitForID (6);   dMediaTracker.waitForID (7);    dMediaTracker.waitForID (8);
          dMediaTracker.waitForID (9);   dMediaTracker.waitForID (10);
					 dMediaTracker.waitForID (11);   dMediaTracker.waitForID (12);
          dMediaTracker.waitForID (13);  dMediaTracker.waitForID (14);
                                         dMediaTracker.waitForID (17);   dMediaTracker.waitForID (18);
          dMediaTracker.waitForID (19);  dMediaTracker.waitForID (20);
       } catch (InterruptedException ex) {
          System.out.println ( "Konnte Grafik nicht laden ("+ex.toString()+")" ); 
       } 

      // Zeichenfläche für Flickerreduktion setzen
       dSize = getSize();
       img_surface = createImage (dSize.width, dSize.height); // gfx-Buffering
       g_surface = img_surface.getGraphics ();
    }

   // Koordinaten der Toolbar setzen
    rect_toolbar = new TRect (260, 20, 85, 100);
    rect_innertoolbar = new TRect (265, 40, 75, 75);
    rect_stylebar = new TRect (240, 145, 119, 50);
    rect_innerstylebar = new TRect (245, 165, 109, 25);

   // Farben zuweisen
    Paint.PaintSettings().currentBGColor = Color.white;
    Paint.PaintSettings().currentColor = Color.black;
    color_set = new Color[13];
    color_set[0] = Color.black;  color_set[1] = Color.blue;  color_set[2] = Color.cyan;
    color_set[3] = Color.darkGray;  color_set[4] = Color.gray;  color_set[5] = Color.green;
    color_set[6] = Color.lightGray;  color_set[7] = Color.magenta;  color_set[8] = Color.orange;
    color_set[9] = Color.pink;  color_set[10] = Color.red;  color_set[11] = Color.white;
    color_set[12] = Color.yellow;  

   // Hintergrundfarbe setzen 
    setBackground (Paint.PaintSettings().currentBGColor);

   // Event-Handling anschalten
    addMouseListener(unserMouseListener); // Mouse-Event-Handling aktiv.
    addMouseMotionListener(unserMotionListener); 
    addKeyListener(unserKeyListener); 
 }  

 /** Die Main-Methode des JavaMalprogramms
   * @param String[] Die (nicht ausgewerteten) Kommandozeilenparameter
   */
 public static void main (String Args[]) {

   // Action-Listener für Exit-Event definieren
    WindowListener ExitListener = new WindowAdapter()
    {
      // Event-Methode die beim Schließen aufgerufen wird
       public void windowClosing (WindowEvent ThisEvent) {
          System.exit (0); // Errorlevel 0 zurück
       }
    };

   // Frame anlegen und die applet-Klasse einpflanzen    
    Frame AppletFrame = new Frame("Das JavaMalprogramm");
    AppletFrame.setSize (400,400);
    AppletFrame.addWindowListener(ExitListener); // Event-Handling aktiv.

   // Neue Instanz von uns selbst erzeugen
    Draw thisDraw = new Draw(); 
    thisDraw.setApplicationMode (true, AppletFrame);
    AppletFrame.add(thisDraw); // pflanze applet ein...

   // Initialisieren des Applets
    thisDraw.init();
    thisDraw.start();

    AppletFrame.setSize (400,400);
    // AppletFrame.pack();
    // AppletFrame.setSize(AppletFrame.getPreferredSize());
    AppletFrame.show(); // und anzeigen (visible=true)...
 }

}

// Die Klasse TRect enthält links, rechts und height, width - Variablen
class TRect {

  public int x, y;
  public int width, height;  

  public TRect () {
     x = 0;  y = 0;  width = 0;  height = 0;
  }  

  public TRect (int a1, int a2, int a3, int a4) {
     x = a1;  y = a2;  width = a3;  height = a4;
  }

  // Prüft, ob ax|ay in dem TRect enthalten ist
  public boolean IsIn (int ax, int ay) {
     if ((ax >= x) && (ax < x+width) && (ay >= y) && (ay < y+height)) {
        return (true);
     } else {
        return (false); 
     } 
  }

}