/*
 *
 *  Copyright (C) 1999, Institute for MicroTherapy
 *
 *  This software and supporting documentation were developed by
 *
 *    University of Witten/Herdecke
 *    Department of Radiology and MicroTherapy
 *    Institute for MicroTherapy
 *    Medical computer science
 *    
 *    Universitaetsstrasse 142
 *    44799 Bochum, Germany
 *    
 *    http://www.microtherapy.de/go/cs
 *    mailto:computer.science@microtherapy.de
 *
 *  THIS SOFTWARE IS MADE AVAILABLE,  AS IS,  AND THE INSTITUTE MAKES  NO 
 *  WARRANTY REGARDING THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY
 *  OR FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES 
 *  OR ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY 
 *  AND PERFORMANCE OF THE SOFTWARE IS WITH THE USER.
 *
 *  Author :      $Author: kleber $
 *  Last update : $Date: 2001/06/06 10:32:30 $
 *  Revision :    $Revision: 1.1.1.1 $
 *  State:        $State: Exp $
*/
package viewer.presentation;

import java.util.*;
import java.awt.geom.*;
import java.awt.*;
import java.awt.image.*;

import J2Ci.*;
import viewer.paint.*;
import viewer.gui.*;
import main.*;
import javax.swing.*;
/**
 * This class manages the drawing and manipulating of 
 * the currently active objects on the display. 
 * 
 * @author Klaus Kleber
 * @since 30.04.1999
 */
public class PaintStructure
{

    /**
     * Contains the Point where a moving opations of a PresentationStateLayerObject 
     * starts.
     * 
     * @since 30.04.1999
     */
    
      Point2D.Float moveAnn= new Point2D.Float();
    
	
    /**
    * Contains the currently painted Paintobject. This
    * Object is painted in the xorMode because it saves speed.
    *
    * @since 30.04.1999
    */
	 PaintObject currentPaintObject = null;
    
    /**
    * Contains the a help value . This
    * Object is painted in the xorMode because it saves speed.
    *
    * @since 30.04.1999
    */
    public PaintObject oldPaintObject = null;
    

    
    /**
     * Contains the xorColor for displaying the active object.
     * The xorMode will be used for drawing the active object.
     *
     * @since 30.04.1999
     */
    Color xorColor = Color.gray;
    
    /**
     * Contains the image displaying Canvas 
     *
     * @since 30.04.1999
     * @see PresentationStateGraphicsHandler
     */
    JPanel imageCanvas;
    
    /**
     * Contains the current PresentationStateGraphicsHandler.
     *
     * @since 30.04.1999
     * @see PresentationStateGraphicsHandler
     */
    PresentationStateGraphicsHandler presentationStateGraphicsHandler;
    
    /**
     * Contains the currently active PresentationStateLayerObject on the 
     * display if exist. If a  PresentationStateLayerObject is active
     * you can manipulate this object in the Canvas.
     *
     * @since 30.04.1999
     * @see PresentationStateLayerObject
     */
    public PresentationStateLayerObject currentObject = null;
    
    /**
     * Contains the current transformation for drawing objects.
     * 
     * @since 30.04.1999
     */
    public AffineTransform aff;
    
    public boolean filled = false;
    
    public boolean imageRelative = true;
    /**
     * Constructs a new object.
     * 
     * @param presentationStateGraphicsHandler Contains the current PresentationStateGraphicsHandler
     * @since 30.04.1999
     */
    public PaintStructure(PresentationStateGraphicsHandler presentationStateGraphicsHandler)
    {
        currentPaintObject =null;
        oldPaintObject = null;
        aff = new AffineTransform();
	    
	    this.presentationStateGraphicsHandler = presentationStateGraphicsHandler;
    }
    
    /**
     * Fills/unfills the currentPaintObject.
     * 
     * @param filled Fills/unfills the currentPaintObject.
     * @since 30.04.1999
     */
    public void setFilled()
    {
        filled = !filled;
        if (currentPaintObject != null) currentPaintObject.setFilled(filled);
    }
    
    /**
     * Sets the currentPaintObject to image relative or display relative.
     * 
     * @param isDisplayRelative True sets the currentPaintObject to display relative, false sets the currentPaintObject to imageRelative.
     * @since 30.04.1999
     */
    public void setImageRelative()
    {
       imageRelative = !imageRelative;
       if (currentPaintObject != null) currentPaintObject.isDisplayRelative= !imageRelative;
        
    }
    
    
    
   
    /**
    * Insert a new point to the currentPaintObject.
    * If the  status of the PaintObejct becomes STATUS_STOP,
    * the PointObject will be transformed to a PresentationStateGraphicObject.
    *
    * @param newPoint Specifies the new point of the PaintObject.
    * @since 30.04.1999
    */
      public void setNewPoint(Point2D.Float newPoint, int applyTo)
      {
         
         
         System.out.println("setNewPoint");
         if (currentPaintObject.getStatus() == PaintObject.STATUS_STOP) 
         {
         }  
            
         //First point
         if (currentPaintObject.getStatus() == PaintObject.STATUS_NULL)
         {
            //setNewGraphicPaintObject(currentPaintObject);
            
         }
         
         currentPaintObject.setNewPoint(getInverseTransformedPoint(newPoint));
         if (currentPaintObject.getStatus() == PaintObject.STATUS_STOP) 
         {
            paintInImageCanvas(currentPaintObject, presentationStateGraphicsHandler.getCurrentColor());
            presentationStateGraphicsHandler.newPaintObject(currentPaintObject,aff, applyTo);
            currentPaintObject = currentPaintObject.getNewPaintObject();
         }  
         if ((oldPaintObject != null) && (oldPaintObject instanceof InterpolatedObject))
         {
            setWorkingShape(null);
         }
         oldPaintObject = null;
         
      }
   
   
    /**
    * Deletes the currentPaintObject.
    *
    * @since 30.04.1999
    */
   public void deleteCurrentPaintObject()
   {
        //Creating the graphics2D
        Graphics2D g2 = (Graphics2D)imageCanvas.getGraphics();
        if (g2!= null)
        {
            try
            {
               
               //Painting the new shape
               g2.setXORMode(xorColor);
               if (oldPaintObject != null) oldPaintObject.drawTransformedShape(g2,aff);
               if (currentPaintObject != null)currentPaintObject.drawTransformedShape(g2,aff);
               
            }
            finally
            {
               g2.dispose();
            }
        }
        if (currentPaintObject!= null) currentPaintObject = currentPaintObject.getNewPaintObject();
   }
  
     
    /**
    * Paints a new Point to the currentPaintObject, removes the last Point and 
    * draws the currentPaintObject with the xorMode in the imageCanvas. 
    *
    * @param newPoint Specifies the new point of the currentPaintObject.
    * @since 30.04.1999
    */
    public void setPaintPoint(Point2D.Float nextPoint)
    {
        System.out.println("setPaintPoint");
        if ((currentPaintObject.getStatus() == PaintObject.STATUS_BEGIN)||
            (currentPaintObject.getStatus() == PaintObject.STATUS_WORK))
        {
            setWorkingShape(currentPaintObject.getMovePaintObject(getInverseTransformedPoint(nextPoint)));
        }
        
    }
    
    
    
    /**
    * Draws the current state of the paintStructure in the xorMode.
    *
    * @since 30.04.1999
    */
    public void drawState(Graphics2D g2)
    {
        g2.setXORMode(xorColor);
        if (oldPaintObject != null)          oldPaintObject.drawTransformedShape(g2,aff);
        if (currentPaintObject != null)       currentPaintObject.drawTransformedShape(g2,aff);
        
    }
    
    /**
    * Resets the paintStructure.
    *
    * @since 30.04.1999
    */
    public void reset()
    {
        currentObject = null;  
        currentPaintObject = null;
        oldPaintObject = null;
    }
    
    /**
    * Gets the currentPaintObject
    *
    * @return The currentPaintObject. 
    * @since 30.04.1999
    */
    public PaintObject getCurrentPaintObject()
    {
        return currentPaintObject;
        
    }
    
    /**
    * Sets the currentPaintObject
    *
    * @param The new PaintObject. 
    * @since 30.04.1999
    */
    public void  setCurrentPaintObject(PaintObject  newPaintObject)
    {
         currentPaintObject = newPaintObject;
        
    }
    /**
    * Sets a new Point for moveAnn
    *
    * @param The new value
    * @since 30.04.1999
    */
    public void  setMoveAnn(Point2D.Float  newPoint)
    {
         moveAnn = newPoint;
        
    }
    
    
    /**
    * Sets the Canvas in which the you can draw.
    *
    * @param imageCanvas The new Canvas.
    * @since 30.04.1999
    */
    public void setImageCanvas(JPanel imageCanvas)
    {
        this.imageCanvas = imageCanvas;
    }
    
    /**
    * Returns the inverse transformed point form the AffineTransformation aff.
    *
    * @param displayPoint The transforming point.
    * @return The inverse transformed point
    * @since 30.04.1999
    */
    public Point2D.Float getInverseTransformedPoint(Point2D.Float displayPoint)
    {
        Point2D.Float dstPoint = new Point2D.Float();
        try
        {
            aff.inverseTransform(displayPoint,dstPoint);
        }
        catch(NoninvertibleTransformException e)
        {
            System.out.println("NoninvertibleTransformException: " + e);
        }
        return dstPoint;
    }
   
    
    /**
    * Moves the currentObject if this object is a PresentationStateGraphicObject.
    * The moving size and the direction depends form the Point moveAnn (defined in this
    * class) and the specified point. 
    *
    * @param point The next point where the  currentObject have to moved.
    * @since 30.04.1999
    */
    public void movePresentationStateGraphicObject(Point2D.Float point)
    {
        
        //Creating the graphics2D
        Graphics2D g2 = (Graphics2D)imageCanvas.getGraphics();
        if (g2!= null)
        {
            try
            {
               
                g2.setXORMode(xorColor);
                if (this.currentObject != null) 
                {
                    //Overwrites the old currentObject
                    currentObject.drawMarked(g2,aff);
                    currentObject.moveTo(moveAnn, point);
                    //writes the new currentObject
                    currentObject.drawMarked(g2,aff);
                }
                
            }
            finally
            {
               g2.dispose();
            }
            moveAnn = point;
        }
    }
    
    
    
    /**
    * Moves the currentObject if this object is a PresentationStateTextObject
    * to the specified point. There are two types of moving: First you can move
    * the bounding box of the PresentationStateTextObject. Secoundly you can move 
    * the anchor point of the PresentationStateTextObject. Which type of moving 
    * is used depends from the properties of the PresentationStateTextObject.
    *
    * @param point The next point where the  PresentationStateTextObject have to moved.
    * @since 30.04.1999
    */
    public void movePresentationStateTextObject(Point2D.Float point)
    {
        if (currentObject instanceof PresentationStateTextObject)
        {
           PresentationStateTextObject clickedText =(PresentationStateTextObject)currentObject;
            //Creating the graphics2D
            Graphics2D g2 = (Graphics2D)imageCanvas.getGraphics();
            if (g2!= null)
            {
                
                try
                {
                    g2.setXORMode(xorColor);
                    //clears the old text
                    if ((clickedText!= null)&&(clickedText.firstDraw == true))clickedText.draw(g2,aff, false);
                    clickedText.firstDraw = true;
                    //Draws the bunding box if needed
                    if (clickedText.needBox)
                    {
                        clickedText.setNewBoundingBox(g2,point,aff);
                    }
                        //draws the anchor point if needed
                    else if (clickedText.needAnchorPoint)
                    {
                            
                        clickedText.setNewAnchor(g2,point,aff);
                        //Draws the new box
                            
                    }
                    if (clickedText!= null)clickedText.draw(g2,aff, false);
                   
                }
                finally
                {
                    g2.dispose();
                    
                }
            }
        }
        
    }
      
      /**
      * Draws the specified paintObject with the specified Color in 
      * the Graphics2D context of the imageCanvas.
      *
      * @param paintObject Specifies the drawing PaintObject
      * @param color Specifies the drawing Color.
      * @since 30.04.1999
      */
      private void paintInImageCanvas(PaintObject paintObject, Color color)
      {
        //Creating the graphics2D
        Graphics2D g2 = (Graphics2D)imageCanvas.getGraphics();
        if (g2!= null)
        {
            try
            {
               //Overpainting the last shape
               g2.setPaint(color);
               if (paintObject != null) paintObject.drawTransformedShape(g2,aff);
            }
            finally
            {
               g2.dispose();
            }
        }
         
      }
      /**
      * Sets the specified status to the currentPaintObject.
      *
      * @param status Specifies the new status of the current PaintObject
      * @since 30.04.1999
      */
    public void setCurrentStatus(int status, int applyTo)
    {
        getCurrentPaintObject().setStatus(status);
        paintInImageCanvas(currentPaintObject, presentationStateGraphicsHandler.getCurrentColor());
        presentationStateGraphicsHandler.newPaintObject(currentPaintObject,aff,  applyTo);
    
    }
      
      /**
      * Deletes the currentPaintobject, overwites the geometic representation
      * in the imageCanvas in the xorMode, sets the specified
      * PaintObject as the new PaintObejct and draws this object in the imageCanvas 
      * with the xorMode.
      *
      * @param thePaintObject Specifies the new  PaintObject
      * @since 30.04.1999
      */
    public  void setWorkingShape(PaintObject thePaintObject)
    {
     
        //Creating the graphics2D
        Graphics2D g2 = (Graphics2D)imageCanvas.getGraphics();
        if (g2!= null)
        {
            try
            {
               //Overpainting the last shape
               g2.setXORMode(xorColor);
               if (oldPaintObject != null) oldPaintObject.drawTransformedShape(g2,aff);
               
               //Painting the new shape
               if (thePaintObject != null) thePaintObject.drawTransformedShape(g2,aff);
               
            }
            finally
            {
               g2.dispose();
            }
        }
        
        if (thePaintObject != null) 
        {
            oldPaintObject= thePaintObject.copy();
        }
        else oldPaintObject = null;
    }//setAktualShape
    
    /**
    * Sets a new currentObject and draws it with the xorMode in the imageCanvas 
    * 
    * @param newCurrentObject The new currentObject.
    * @param redrawOld If true drwas the old currentObject with the xorMode in the imageCanvas.
    * @since 30.04.1999
    */
    public void setCurrentObject(PresentationStateLayerObject newCurrentObject,boolean redrawOld)
    {
        
        //Creating the graphics2D
        Graphics2D g2 = (Graphics2D)imageCanvas.getGraphics();
        if (g2!= null)
        {
            try
            {
               
               g2.setXORMode(xorColor);
               if ((this.currentObject != null) && redrawOld)currentObject.drawMarked(g2,aff);
               //Painting the new shape
               if (newCurrentObject != null) newCurrentObject.drawMarked(g2,aff);
               currentObject = newCurrentObject;
            
            }
            finally
            {
               g2.dispose();
            }
            
        }
    }
}

/*
 *  CVS Log
 *  $Log: PaintStructure.java,v $
 *  Revision 1.1.1.1  2001/06/06 10:32:30  kleber
 *  Init commit for DICOMscope 3.5
 *  Create new CVS
 *
*/
