/*
 *
 *  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: 2003/09/08 10:17:26 $
 *  Revision :    $Revision: 1.2 $
 *  State:        $State: Exp $
 */
package viewer.presentation;

import viewer.paint.*;
import J2Ci.*;
import main.*;

import java.util.*;
import java.awt.geom.*;
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
/**
 * This class manages the Presentation State.
 *
 * @author Klaus Kleber
 * @since 30.04.1999
 */
public class PresentationStateGraphicsHandler {
    /**
     * Toggle PS on/off. If true the Presentation State is visible, if only the image
     * without the Presentation State is visible.
     *
     * @since 30.04.1999
     */
    public boolean enablePresentationState = true;
    
    /**
     * Contains the data of the Presentation State in a c++ Interface.
     *
     * @since 30.04.1999
     */
    public jDVPresentationState ps;
    
    /**
     * Vector which contains the layers of the presentation state.
     *
     * @since 30.04.1999
     */
    public Vector listPresentationStateGraphicLayer;
    
    
    /**
     * This object manages the overlays.
     *
     * @see OverlayList
     * @since 30.04.1999
     */
    public OverlayList overlayList;
    
    /**
     * This object manages the Shutters.
     *
     * @since 30.04.1999
     * @see ShutterList
     */
    public ShutterList  shutterList;
    
    /**
     * Specified the index of the current active PresentationStateGraphicsLayer.
     * If index = -1 no PresentationStateGraphicsLayer is avalable.
     * The current active PresentationStateGraphicsLayer is the layer on which you can
     * create, manipulate or delete PresentationStateLayerObjects
     *
     * @since 30.04.1999
     */
    int currentLayerIndex = -1;
    
    /**
     * Specified the index of the current active PresentationStateLayerObject in the
     * current active PresentationStateGraphicsLayer (specified form the  currentLayerIndex).
     * If index = -1 no PresentationStateLayerObject is active.
     * The current active PresentationStateLayerObject is the one which you can
     * create, manipulate or delete.
     *
     * @since 30.04.1999
     */
    int currentLayerObjectIndex= -1;
    
    /**
     * A <em>jDVInterface</em> represents the relating C++-Class DVInterface
     * in Java.
     *
     * @since 30.04.1999
     * @see J2Ci.jDVInterface
     */
    public jDVInterface dvi;
    
    /**
     * Contains the currently available size of the imageCanvas.
     *
     * @since 30.04.1999
     * @see GUI.ImageCanvas
     */
    Dimension screenSize;
    
    public double trueSizeX =1d;
    public  double trueSizeY =1d;
    double monitorScalingX = 1d;
    double monitorScalingY =1d;
    
    public  int selectedImageNumber = 1;
    public int selectedLutIndex = -1;
    public int psSelectedLUTIndex = -1;
    /**
     * Contains the vertical scaling factor of the image.
     *
     * @since 30.04.1999
     */
    private double scalingValueY = 1d;
    
    /**
     * Contains the horizontal scaling factor of the image.
     *
     * @since 30.04.1999
     */
    private double scalingValueX = 1d;
    
    /**
     * Contains the zoom factor of the displaying image.
     *
     * @since 30.04.1999
     */
    private double zoomValue=-1;
    
    /**
     * Contains true if the PresentationStateGraphicsHandler have a jDVPresentationState.
     *
     * @since 30.04.1999
     */
    public boolean havePresentationState = false;
    
    /**
     * Constructs the paintStructure from the specified jDVInterface.
     *
     * @param dvi Contains the current jDCInterface
     * @since 30.04.1999
     * @see J2Ci.jDVInterface
     */
    public PresentationStateGraphicsHandler(jDVInterface dvi) {
        this.dvi = dvi;
    }
    
    /**
     * Gets the current active PresentationStateLayerObject. This  PresentationStateLayerObject
     * is specified form the currentLayerObjectIndex and the currentLayerIndex.
     *
     * @return The current active PresentationStateLayerObject.
     * @since 30.04.1999
     */
    public PresentationStateLayerObject getCurrentLayerObject() {
        return ((PresentationStateLayerObject) ((PresentationStateGraphicLayer) listPresentationStateGraphicLayer.elementAt(currentLayerIndex)).layerObjectAt(currentLayerObjectIndex));
    }
    
    /**
     * Sets the currentLayerObjectIndex.
     *
     * @param newIndex New currentLayerObjectIndex.
     * @since 30.04.1999
     */
    public void setCurrentLayerObjectIndex(int newIndex) {
        this.currentLayerObjectIndex = newIndex;
    }
    
    /**
     * Gets the currentLayerObjectIndex.
     *
     * @return The currentLayerObjectIndex.
     * @since 30.04.1999
     */
    public int getCurrentLayerObjectIndex() {
        return currentLayerObjectIndex;
    }
    
    /**
     * Gets the current active PresentationStateGraphicLayer. This  PresentationStateGraphicLayer
     * is specified form the.currentLayerIndex.
     *
     * @return The current active PresentationStateGraphicLayer.
     * @since 30.04.1999
     */
    public PresentationStateGraphicLayer getCurrentLayer() {
        return getLayerAtIndex(currentLayerIndex);
    }
    
    /**
     * Sets the currentLayerIndex.
     *
     * @param newIndex New currentLayerIndex.
     * @since 30.04.1999
     */
    public void setCurrentLayerIndex( int newIndex) {
        currentLayerIndex = newIndex;
        currentLayerObjectIndex= -1;
        
    }
    
    /**
     * Gets the currentLayerObjectIndex.
     *
     * @return The currentLayerObjectIndex.
     * @since 30.04.1999
     */
    public int getCurrentLayerIndex() {
        return currentLayerIndex;
    }
    
    /**
     * Gets the horizontal scaling factor of the image.
     *
     * @return Horizontal scaling factor of the image.
     * @since 30.04.1999
     */
    public double getScalingX() {
        return scalingValueX*monitorScalingX;
        
    }
    
    /**
     * Gets the vertical scaling factor of the image.
     *
     * @return Vertical scaling factor of the image.
     * @since 30.04.1999
     */
    public  double getScalingY() {
        return scalingValueY*monitorScalingY;
    }
    /**
     * Gets the horizontal scaling factor of the image.
     *
     * @return Horizontal scaling factor of the image.
     * @since 30.04.1999
     */
    public double getScX() {
        return scalingValueX;
        
    }
    
    /**
     * Gets the vertical scaling factor of the image.
     *
     * @return Vertical scaling factor of the image.
     * @since 30.04.1999
     */
    public  double getScY() {
        return scalingValueY;
    }
    
    public double getMonitorScalingX() {
        return monitorScalingX;
    }
    
    public double getMonitorScalingY() {
        return monitorScalingY;
    }
    /**
     * Gets the horizontal scaling factor after the rotation. If rotation == 90-deg or 270 deg
     * scalingValueX and scalingValueY will be exchanged.
     *
     * @return Horizontal scaling factor after the rotation.
     * @since 30.04.1999
     */
    public double getCurrentScalingX() {
        if ((getRotation() == 0) ||(getRotation() ==2))return scalingValueX*monitorScalingX;
        else return scalingValueY*monitorScalingX;
    }
    
    /**
     * Gets the vertical scaling factor after  rotation. If rotation == 90-deg or 270 deg
     * scalingValueX and scalingValueY will be exchanged.
     *
     * @return Vertical scaling factor after  rotation.
     * @since 30.04.1999
     */
    public double getCurrentScalingY() {
        if ((getRotation() == 0) ||(getRotation() ==2))return scalingValueY*monitorScalingY;
        else return scalingValueX*monitorScalingY;
    }
    
    
    /**
     * Gets the height of the image.
     *
     * @return Heigth of the image.
     * @since 30.04.1999
     * @see J2Ci.jDVPresentationState
     */
    public int getImageHeight() {
        jIntByRef height = new jIntByRef();
        ps.getImageHeight(height);
        return height.value;
        
    }
    /**
     * Gets the height of the image.
     *
     * @return Heigth of the image.
     * @since 30.04.1999
     * @see J2Ci.jDVPresentationState
     */
    public double getDisplayedAreaPresentationPixelMagnificationRatio() {
        jDoubleByRef ratio = new jDoubleByRef();
        ps.getDisplayedAreaPresentationPixelMagnificationRatio(ratio);
        return ratio.value;
        
    }
    /**
     * Gets the height of the image.
     *
     * @return Heigth of the image.
     * @since 30.04.1999
     * @see J2Ci.jDVPresentationState
     */
    public double getDisplayedAreaPresentationPixelAspectRatio() {
        double i = ps.getDisplayedAreaPresentationPixelAspectRatio();
        if (i<=0) i = 1;
        return i;
    }
    /**
     * Gets the height of the image.
     *
     * @return Heigth of the image.
     * @since 30.04.1999
     * @see J2Ci.jDVPresentationState
     */
    public double getDisplayedAreaPresentationPixelSpacingX() {
        jDoubleByRef x = new jDoubleByRef();
        jDoubleByRef y = new jDoubleByRef();
        ps.getDisplayedAreaPresentationPixelSpacing(x, y);
        double i = x.value;
        if (i<=0) i = 1;
        return i;
        
        
    }
    public boolean haveDisplayedAreaPresentationPixelSpacing() {
        jDoubleByRef x = new jDoubleByRef();
        jDoubleByRef y = new jDoubleByRef();
        int status = ps.getDisplayedAreaPresentationPixelSpacing(x, y);
        if (status == jE_Condition.EC_Normal) return true;
        else return false;
        
    }
    /**
     * Gets the height of the image.
     *
     * @return Heigth of the image.
     * @since 30.04.1999
     * @see J2Ci.jDVPresentationState
     */
    public double getDisplayedAreaPresentationPixelSpacingY() {
        jDoubleByRef x = new jDoubleByRef();
        jDoubleByRef y = new jDoubleByRef();
        ps.getDisplayedAreaPresentationPixelSpacing(x, y);
        double i = y.value;
        if (i<=0) i = 1;
        return i;
        
    }
    
    /**
     * Gets the width of the image.
     *
     * @return Width of the image.
     * @since 30.04.1999
     * @see J2Ci.jDVPresentationState
     */
    public int getImageWidth() {
        jIntByRef width = new jIntByRef();
        ps.getImageWidth(width);
        return width.value;
    }
    
    /**
     * Gets the height of the image after  rotation.If rotation == 90-deg or 270 deg
     * height and width of the image will be exchanged.
     *
     * @return Heigth of the image after  rotation..
     * @since 30.04.1999
     * @see J2Ci.jDVPresentationState
     */
    public int getCurrentImageHeight() {
        if ((getRotation() == 0) ||(getRotation() ==2))return  getImageHeight();
        else return getImageWidth();
        
    }
    
    /**
     * Gets the height of the image after  rotation.If rotation == 90-deg or 270 deg
     * height and width of the image will be exchanged.
     *
     * @return Heigth of the image after  rotation..
     * @since 30.04.1999
     * @see J2Ci.jDVPresentationState
     */
    public int getCurrentImageWidth() {
        if ((getRotation() == 0) ||(getRotation() ==2))return  getImageWidth();
        else return  getImageHeight();
    }
    /**
     * Calculates the horizontal and vertical scaling values. There are two parameters which can
     * influcene these values. First, the Presentation Pixel Spacing value or
     * the Presentation Pixel Aspect Ratio value contains implicit or explicit sacling values.
     * Secoundly the pixel size of the monitor will influence the scale.
     *
     * @return Heigth of the image after  rotation..
     * @since 30.04.1999
     * @see J2Ci.jDVPresentationState
     */
    public void buildScaling() {
        jDoubleByRef xValue = new jDoubleByRef();
        jDoubleByRef yValue = new jDoubleByRef();
        monitorScalingX = 1d;
        monitorScalingY = 1d;
        scalingValueY = 1d;
        scalingValueX = 1d;
        //Calculates the scale values resulting of the monitor characteristics.
        if (trueSizeX > trueSizeY)monitorScalingX = trueSizeY/trueSizeX;
        else monitorScalingY = trueSizeX/trueSizeY;
        
        int status = ps.getDisplayedAreaPresentationPixelSpacing(xValue, yValue);
        if (xValue.value <= 0) xValue.value = 1;
        if (yValue.value <= 0) yValue.value = 1;
        
        if (status ==jE_Condition.EC_Normal) {
            if (ps.getDisplayedAreaPresentationSizeMode() == jDVPSPresentationSizeMode.DVPSD_trueSize) {
                monitorScalingX= xValue.value/trueSizeX;
                monitorScalingY = yValue.value/trueSizeY;
            }
            else {
                if (xValue.value > yValue.value) {
                    scalingValueX = yValue.value/xValue.value;
                    scalingValueY = 1d;
                }
                else {
                    scalingValueY = xValue.value/yValue.value;
                    scalingValueX = 1d;
                    
                }
            }
        }
        else {
            double aspectRatio = ps.getDisplayedAreaPresentationPixelAspectRatio();
            if (aspectRatio >= 1d) {
                scalingValueX = aspectRatio;
                scalingValueY =1d;
            }
            else {
                scalingValueY = (1d/aspectRatio);
                scalingValueX = 1d;
            }
        }
        
        
        //Gets the scalingValues
        
    }
    
    
    /**
     * Builds the internal structure of the PresentationStateGraphicsHandler if a new jDVPresentationState will be received.
     * The overlayList, the shutterList and the listPresentationStateGraphicLayer will be create from the
     * jDVPresentationState obejct.
     *
     * @since 30.04.1999
     * @see J2Ci.jDVPresentationState
     */
    public void buildPresentationState() {
        selectedLutIndex = -1;
        
        
        enablePresentationState = true;
        this.ps = dvi.getCurrentPState();
        buildScaling();
        havePresentationState = true;
        listPresentationStateGraphicLayer = new Vector();
        
        overlayList = new OverlayList(ps);
        
        //builds the ShutterList
        shutterList = new ShutterList(ps);
        
        //builds the layer list.
        ps.sortGraphicLayers();
        
        DisplayArea da = getDisplayArea();
        int numLayer = ps.getNumberOfGraphicLayers()-1;
        for (int i = 0; i <= numLayer; i++) {
            
            listPresentationStateGraphicLayer.add(new PresentationStateGraphicLayer(i,ps,da,overlayList));
        }
        if (listPresentationStateGraphicLayer.size() !=0) currentLayerIndex = ps.getNumberOfGraphicLayers()-1;
        else currentLayerIndex = -1;
        
        //Init size in layer. Calculates dispaly relative annotation.
        for (int i = 0; i < listPresentationStateGraphicLayer.size(); i++) {
            
            ((PresentationStateGraphicLayer)listPresentationStateGraphicLayer.elementAt(i)).setScreenSize(screenSize);
        }
        
    }
    
    /**
     * Gets the pixel aspect ratio of the attached image.
     * Pixel aspect ratio is defined here as the width of a pixel divided
     * by the height of a pixel (x/y).
     *
     * @since 30.04.1999
     * @see J2Ci.jDVPresentationState
     */
    public double getPixelAspectRatio() {
        /*//Gets the scalingValues
        jDoubleByRef aspectRatio = new jDoubleByRef();
        ps.getImageAspectRatio(aspectRatio);
        return aspectRatio.value;
         */
        return 1;
    }
    
    /**
     * Resets the currentLayerObjectIndex.
     *
     * @since 30.04.1999
     */
    
    public void reset() {
        currentLayerObjectIndex   = -1;
        selectedLutIndex = -1;
    }
    
    
    /**
     * Draws the all PresentationStateGraphicLayer in listPresentationStateGraphicLayer and all
     * Overlays defined in OverlayList after the sprecified transformation aff in the specified BufferedImage.
     * All PresntationStateLayerObjects in each PresentationStateGraphicLayer will be drawn.
     *
     * @param bufferedImage Specifies the BufferedImage in which you can draw.
     * @param aff Specifies the transformation which will be used for PresentationStateAnnotationObjects.
     * @param aff Specifies the transformation which will be used for PresentationStateOverlayObjects.
     * @since 30.04.1999
     * @see Viewer.Main.ScreenImageHandler#buildImageBuffer
     */
    public void drawPaintStructure( BufferedImage bufferedImage,AffineTransform aff,AffineTransform overlayAff, boolean trueSize, int bits,boolean scale) {
        if (bufferedImage== null) return;
        //Creating the graphics2D
        Graphics2D g2 = (Graphics2D)bufferedImage.getGraphics();
        if (g2!= null) {
            try {
                for (int i = 0; i < listPresentationStateGraphicLayer.size(); i++) {
                    ((PresentationStateGraphicLayer) listPresentationStateGraphicLayer.elementAt(i)).draw(g2, aff, overlayAff,bits, scale);
                }
            }
            finally {
                g2.dispose();
            }
        }
    }
    
    /**
     * Searched for the PresentationStateLayerObject containing the specified point.
     * The result is a new active PresentationStateLayerObject (specified with a new
     * currentLayerObjectIndex) and a new active PresentationStateGraphicLayer (specified with a new
     * currentLayerIndex.
     *
     * @param point Contains the searched point.
     * @since 30.04.1999
     * @see Viewer.Main.ScreenImageHandler#buildImageBuffer
     */
    
    public void containsObject(Point2D.Float point) {
        
        
        for (int i = listPresentationStateGraphicLayer.size()-1; i >= 0; i--) {
            currentLayerObjectIndex = ((PresentationStateGraphicLayer) listPresentationStateGraphicLayer.elementAt(i)).containsLayerObject(point);
            if (currentLayerObjectIndex != -1) {
                currentLayerIndex = i;
                return;
            }
        }
    }
    
    
    /**
     * Returns a String representing this object.
     *
     * @return A String representing this object
     * @since 30.04.1999
     */
    public String getInfo() {
        String returnString;
        returnString = new String( "PresentationStateGraphicHandler" + "\n" );
        for(int i = 0; i <listPresentationStateGraphicLayer.size(); i++) {
            returnString= returnString.concat(new String("    Index: " +i +"\n"));
            returnString=returnString.concat(((PresentationStateGraphicLayer) listPresentationStateGraphicLayer.elementAt(i)).getInfo());
        }
        return returnString;
    }
    
    /**
     * Sets the new available size for displaying the image. If no zoom value is set the zoom value will be calculate.
     * The size of the available display is important for display realtive annotations
     * (handled in PresentationStateGraphicObject and PresentationStateTextObject). Changing the size
     * resluts in changing all display relative annotations.
     *
     * @param screenSize New available size for displaying the image.
     * @since 30.04.1999
     */
    public void setScreenSize(Dimension screenSize) {
        
        this.screenSize = screenSize;
        calculateFirstZoomValue();
        
        //Init size in layer. Calculates dispaly relative annotation.
        for (int i = 0; i < listPresentationStateGraphicLayer.size(); i++) {
            ((PresentationStateGraphicLayer)listPresentationStateGraphicLayer.elementAt(i)).setScreenSize(screenSize);
        }
        
    }
    /**
     * Calculates the zoom value if the image should displayed first time. The zoom value
     * must be caluclated because the presnetations state do not contain this. There are only the
     * top left hand corner and the bottom right hand corner of the displaying part of the image available.
     *
     * @since 30.04.1999
     */
    public void calculateFirstZoomValue() {
        DisplayArea da = getDisplayArea();
        if (ps.getDisplayedAreaPresentationSizeMode() ==jDVPSPresentationSizeMode.DVPSD_scaleToFit) {
            
            zoomValue = calculateZoomValue(da);
        }
        else if (ps.getDisplayedAreaPresentationSizeMode() ==jDVPSPresentationSizeMode.DVPSD_magnify) {
            jDoubleByRef zoom = new jDoubleByRef();
            ps.getDisplayedAreaPresentationPixelMagnificationRatio(zoom);
            zoomValue = zoom.value;
        }
        else if (ps.getDisplayedAreaPresentationSizeMode() ==jDVPSPresentationSizeMode.DVPSD_trueSize) {
            
            zoomValue =1d;
        }
        //zoomValue = (Math.round(zoomValue*100d)/100d);
        
    }
    public void convertDisplayedAreas(DisplayArea imageArea, DisplayArea newArea) {
        float transX = ((float)(imageArea.getBrhcX()-imageArea.getTlhcX()))/((float)(newArea.getBrhcX()-newArea.getTlhcX()));
        float transY = ((float)(imageArea.getBrhcY()-imageArea.getTlhcY()))/((float)(newArea.getBrhcY()-newArea.getTlhcY()));
        
        // The display reletive annotationa must be applyed afte the spatial transformations
        
        if ((getRotation() == 1) || (getRotation() ==3)) {
            float help = transX;
            transX = transY;
            transY = help;
        }
        
        //needed for the future
        float offsetX = 0;
        float offsetY = 0;
        
        for (int i = 0; i < listPresentationStateGraphicLayer.size(); i++) {
            ((PresentationStateGraphicLayer) listPresentationStateGraphicLayer.elementAt(i)).convertDisplayedAreas(offsetX, offsetY, transX, transY);
        }
        
    }
    
    public double calculateZoomValue(DisplayArea da) {
        double zoom;
        if ((getRotation() == 0) ||(getRotation() ==2)) {
            zoom = Math.min(  (double) screenSize.width/((double)(da.getBrhcX()-da.getTlhcX()+1)*getCurrentScalingX()),
            (double)screenSize.height/((double)(da.getBrhcY()-da.getTlhcY()+1)*getCurrentScalingY()));
        }
        else {
            zoom = Math.min(  (double) screenSize.width/((double)(da.getBrhcY()-da.getTlhcY()+1)*getCurrentScalingX()),
            (double)screenSize.height/((double)(da.getBrhcX()-da.getTlhcX()+1)*getCurrentScalingY()));
        }
        return zoom;
        
    }
    /**
     * The Vector of  PresentationStateGraphicLayers.
     *
     * @return The Vector of  PresentationStateGraphicLayers.
     * @since 30.04.1999
     */
    public Vector getListPresentationStateGraphicLayer() {
        return listPresentationStateGraphicLayer;
    }
    
    /**
     * Returns the PresentationStateGraphicLayer with the specified index
     *
     */
    public PresentationStateGraphicLayer getPresentationStateGraphicLayer(int index) {
        return (PresentationStateGraphicLayer)listPresentationStateGraphicLayer.elementAt(index);
    }
    
    
    /**
     * Gets the creators name of the presentation state.
     * The value is stored in the c++ interface
     * and is available in  the jDVPresententationState object ps.
     *
     * @return The creators name of the presentation state.
     * @see J2Ci.jDVPresentationState
     * @since 30.04.1999
     */
    public String getPresentationCreatorsName() {
        return ps.getPresentationCreatorsName();
    }
    
    /**
     * Gets the label of the presentation state.
     * The value is stored in the c++ interface
     * and is available in  the jDVPresententationState object ps.
     *
     * @return The label of the presentation state.
     * @see J2Ci.jDVPresentationState
     * @since 30.04.1999
     */
    public String getPresentationLabel() {
        return ps.getPresentationLabel();
    }
    
    /**
     * Gets the description of the presentation state.
     * The value is stored in the c++ interface
     * and is available in  the jDVPresententationState object ps.
     *
     * @return The description of the presentation state.
     * @see J2Ci.jDVPresentationState
     * @since 30.04.1999
     */
    public String getPresentationDescription() {
        return ps.getPresentationDescription();
    }
    
    
    
    
    /**
     * Gets the the displayed area of the presentation state.
     * The value is stored in the c++ interface
     * and is available in  the jDVPresententationState object ps.
     *
     * @return The top left hand corner of the displayed area of the presentation state.
     * @see J2Ci.jDVPresentationState
     * @since 30.04.1999
     */
    public DisplayArea getDisplayArea() {
        jIntByRef tlhc_xValue = new jIntByRef();
        jIntByRef tlhc_yValue = new jIntByRef();
        jIntByRef brhc_yValue= new jIntByRef();
        jIntByRef brhc_xValue= new jIntByRef();
        
        ps.getImageRelativeDisplayedArea(tlhc_xValue, tlhc_yValue, brhc_xValue, brhc_yValue);
        return new DisplayArea(tlhc_xValue.value, tlhc_yValue.value, brhc_xValue.value, brhc_yValue.value);
        
    }
    /**
    
     */
    public DisplayArea getStandardDisplayedArea() {
        jIntByRef tlhc_xValue = new jIntByRef();
        jIntByRef tlhc_yValue = new jIntByRef();
        jIntByRef brhc_yValue= new jIntByRef();
        jIntByRef brhc_xValue= new jIntByRef();
        
        ps.getStandardDisplayedArea(tlhc_xValue, tlhc_yValue, brhc_xValue, brhc_yValue);
     //  System.err.println("DDDD" +new DisplayArea(tlhc_xValue.value, tlhc_yValue.value, brhc_xValue.value, brhc_yValue.value));
           return new DisplayArea(tlhc_xValue.value, tlhc_yValue.value, brhc_xValue.value, brhc_yValue.value);
        
    }
    
    
    
    
    
    /**
     * Checks if a VOI window is active.
     * The value is stored in the c++ interface
     * and is available in  the jDVPresententationState object ps.
     *
     * @return True if a VOI window is active.
     * @see J2Ci.jDVPresentationState
     * @since 30.04.1999
     */
    public boolean haveActiveVOIWindow() {
        return ps.haveActiveVOIWindow();
    }
    
    
    /**
     * Checks if a VOI LUT is active.
     * The value is stored in the c++ interface
     * and is available in  the jDVPresententationState object ps.
     *
     * @return True if a VOI LUT is active.
     * @see J2Ci.jDVPresentationState
     * @since 30.04.1999
     */
    
    public boolean haveActiveVOILUT() {
        return ps.haveActiveVOILUT();
    }
    
    /**
     * Returns the description of the currently active VOI window.
     * The value is stored in the c++ interface
     * and is available in  the jDVPresententationState object ps.
     *
     * @return The description of the currently active VOI window.
     * @see J2Ci.jDVPresentationState
     * @since 30.04.1999
     */
    public String getCurrentVOIDescription() {
        return ps.getCurrentVOIDescription();
    }
    
    
    /**
     * Returns the center of the currently active VOI window.
     * The value is stored in the c++ interface
     * and is available in  the jDVPresententationState object ps.
     *
     * @return The center of the currently active VOI window.
     * @see J2Ci.jDVPresentationState
     * @since 30.04.1999
     */
    public int getCurrentWindowCenter() {
        jDoubleByRef help = new jDoubleByRef();
        ps.getCurrentWindowCenter(help);
        return (int) help.value;
    }
    
    /**
     * Returns the width of the currently active VOI window.
     * The value is stored in the c++ interface
     * and is available in  the jDVPresententationState object ps.
     *
     * @return The width of the currently active VOI window.
     * @see J2Ci.jDVPresentationState
     * @since 30.04.1999
     */
    public int getCurrentWindowWidth() {
        jDoubleByRef help = new jDoubleByRef();
        ps.getCurrentWindowWidth(help);
        return (int) help.value;
    }
    
    /**
     * Sets rotation status of the presentation state.
     * The value is stored in the c++ interface
     * and is available in  the jDVPresententationState object ps.
     *
     * @param rotation the rotation to be set (from jDVPSRotationType).
     * @see J2Ci.jDVPresentationState
     * @see J2Ci.jDVPSRotationType
     * @since 30.04.1999
     */
    
    public void setRotation(int rot) {
        ps.setRotation(rot);
        
    }
    /**
     * Rotate 90 degree.
     * The value is stored in the c++ interface
     * and is available in  the jDVPresententationState object ps.
     *
     * @param rotation the rotation to be set (from jDVPSRotationType).
     * @see J2Ci.jDVPresentationState
     * @see J2Ci.jDVPSRotationType
     * @since 30.04.1999
     */
    public void setRotation() {
        if (ps.getRotation() <=2) ps.setRotation(ps.getRotation()+1);
        else ps.setRotation(0);
        for (int i = 0; i < listPresentationStateGraphicLayer.size(); i++) {
            ((PresentationStateGraphicLayer) listPresentationStateGraphicLayer.elementAt(i)).setRotation();
        }
        
    }
    
    
    /**
     * Gets the rotation status of the presentation state.
     * The value is stored in the c++ interface
     * and is available in  the jDVPresententationState object ps.
     *
     * @return The rotation of the presentation state.
     * @see J2Ci.jDVPresentationState
     * @see J2Ci.jDVPSRotationType
     * @since 30.04.1999
     */
    
    public int getRotation() {
        return  ps.getRotation();
        
    }
    
    
    
    /**
     * Flips the image of the presentation state.
     * The value is stored in the c++ interface
     * and is available in  the jDVPresententationState object ps.
     *
     * @see J2Ci.jDVPresentationState
     * @see J2Ci.jDVPSRotationType
     * @since 30.04.1999
     */
    public void setFlip() {
        DisplayArea da =getDisplayArea();
        ps.setFlip(!ps.getFlip());
        
        for (int i = 0; i < listPresentationStateGraphicLayer.size(); i++) {
            ((PresentationStateGraphicLayer) listPresentationStateGraphicLayer.elementAt(i)).setFlip(getRotation());
        }
        
    }
    
    
    /**
     * Inserts a PaintObject as a new PresentationStateGraphicObject in
     * the currently active PresentationStateGraphicLayer or as a new shutter
     * in the ShutterList.
     *
     * @param newPaintObject Contains the inserting PaintObject.
     * @param aff Contains the current transfomations.
     * @see ShutterList
     * @see PresentationStateGraphicObject
     */
    public void newPaintObject(PaintObject newPaintObject,AffineTransform aff,int applyTo) {
        //Inserts Lines an polylines
        if ((newPaintObject instanceof Line2DObject)||
        (newPaintObject instanceof PolylineObject)) {
            
            float thePoints[] = new float[newPaintObject.getObjectPoints().size()*2];
            
            //Converts points
            for (int i = 0; i< newPaintObject.getObjectPoints().size(); i++) {
                thePoints[2*i] = newPaintObject.getCopyPointAt(i).x+1f;
                thePoints[2*i+1] = newPaintObject.getCopyPointAt(i).y+1f;
            }
            //Insert shutter / polyline
            if (!newPaintObject.isShutter)getCurrentLayer().add(new PresentationStateGraphicObject(ps.addGraphicObject(currentLayerIndex,applyTo),0,jDVPSGraphicType.DVPST_polyline,thePoints,newPaintObject.getType(),newPaintObject.filled,screenSize,aff));
            else {
                shutterList.addPolygonalShutter(thePoints,newPaintObject.getObjectPoints().size());
            }
        }
        if ((newPaintObject instanceof Point2DObject)) {
            
            float thePoints[] = new float[newPaintObject.getObjectPoints().size()*2];
            
            //Converts points
            for (int i = 0; i< newPaintObject.getObjectPoints().size(); i++) {
                thePoints[2*i] = newPaintObject.getCopyPointAt(i).x+1f;
                thePoints[2*i+1] = newPaintObject.getCopyPointAt(i).y+1f;
            }
            
            getCurrentLayer().add(new PresentationStateGraphicObject(ps.addGraphicObject(currentLayerIndex,applyTo),0,jDVPSGraphicType.DVPST_point,thePoints,newPaintObject.getType(),newPaintObject.filled,screenSize,aff));
        }
        //Rectangle
        else if (newPaintObject instanceof Rectangle2DObject) {
            Point2D.Float point1 = newPaintObject.getPoint(0);
            Point2D.Float point2 = newPaintObject.getPoint(1);
            if (point1.x >point2.x) {
                float change = point1.x;
                point1.x = point2.x;
                point2.x = change;
            }
            if (point1.y >point2.y) {
                float change = point1.y;
                point1.y = point2.y;
                point2.y = change;
            }
            
            //Converts points
            float x = point1.x;
            float y = point1.y;
            float w = point2.x-x;
            float h = point2.y-y;
            float thePoints[] = new float[10];
            thePoints[0] = x+1f;
            thePoints[1] = y+1f;
            
            thePoints[2] = x+w+1f;
            thePoints[3] = y+1f;
            
            thePoints[4] = x+w+1f;
            thePoints[5] = y+h+1f;
            
            thePoints[6] = x+1f;
            thePoints[7] = y+h+1f;
            
            thePoints[8] = x+1f;
            thePoints[9] = y+1f;
            
            //Insert polyline/ shutter
            if (!newPaintObject.isShutter)getCurrentLayer().add(new PresentationStateGraphicObject(ps.addGraphicObject(currentLayerIndex,applyTo),0,jDVPSGraphicType.DVPST_polyline,thePoints,newPaintObject.getType(),newPaintObject.filled,screenSize,aff));
            else {
                
                shutterList.addRectangularShutter((int)(point1.x+1f),(int)(point2.x+1f),(int)(point1.y+1f),(int)(point2.y+1f));
            }
            
        }
        //Ellipse
        else if (newPaintObject instanceof Ellipse2DObject) {
            //System.out.println("###");
            float[] thePoints = new float[8];
            Point2D.Float point1 = newPaintObject.getPoint(0);
            Point2D.Float point2 = newPaintObject.getPoint(1);
            if (point1.x >point2.x) {
                float change = point1.x;
                point1.x = point2.x;
                point2.x = change;
            }
            if (point1.y >point2.y) {
                float change = point1.y;
                point1.y = point2.y;
                point2.y = change;
            }
            
            float x = point1.x;
            float y = point1.y;
            float w = point2.x-x;
            float h = point2.y-y;
            //The first two points must be  the end points oft the major axis.
            int index=0;
            if (w<h) {
               index=4;
            }
            thePoints[index++] = x+w+1f;
           // System.err.println("index : "+(index-1) +", " +thePoints[index-1]);
            thePoints[index++] = y+1f+h/2f;
         // System.err.println("index : "+(index-1) +", " +thePoints[index-1]);
            
            thePoints[index++] = x+1f;
          //  System.err.println("index : "+(index-1) +", " +thePoints[index-1]);
            thePoints[index++] = y+1f+h/2f;
          //   System.err.println("index : "+(index-1) +", " +thePoints[index-1]);
            if (w<h) {
               index=0;
            }
            
            thePoints[index++] = x+w/2+1f;
             //System.err.println("index : "+(index-1) +", " +thePoints[index-1]);
            thePoints[index++] = y+1f;
            //System.err.println("index : "+(index-1) +", " +thePoints[index-1]);
            
            thePoints[index++] = x+w/2+1f;
            // System.err.println("index : "+(index-1) +", " +thePoints[index-1]);
            thePoints[index++] = y+h+1f;
             //System.err.println("index : "+(index-1) +", " +thePoints[index-1]);
             
            
            getCurrentLayer().add(new PresentationStateGraphicObject(ps.addGraphicObject(currentLayerIndex,applyTo),0,jDVPSGraphicType.DVPST_ellipse,thePoints,newPaintObject.getType(),newPaintObject.filled,screenSize,aff));
        }
        //Circle
        else if (newPaintObject instanceof Circle2DObject) {
            
            Point2D.Float point1 = newPaintObject.getPoint(0);
            Point2D.Float point2 = newPaintObject.getPoint(1);
            
            if (!newPaintObject.isShutter) {
                float[] thePoints = new float[4];
                
                
                thePoints[0] = point1.x+1f;
                thePoints[1] = point1.y+1f;
                
                thePoints[2] = point2.x+1f;
                thePoints[3] = point2.y+1f;
                getCurrentLayer().add(new PresentationStateGraphicObject(ps.addGraphicObject(currentLayerIndex,applyTo),0,jDVPSGraphicType.DVPST_circle,thePoints,newPaintObject.getType(),newPaintObject.filled,screenSize,aff));
            }
            else {
                
                shutterList.addCircularShutter((int)(point1.x+1f),(int)(point1.y+1f),(int)point1.distance(point2));
            }
        }
        //Interpolated.
        else if (newPaintObject instanceof InterpolatedObject) {
            float thePoints[] = new float[newPaintObject.getObjectPoints().size()*2];
            
            for (int i = 0; i< newPaintObject.getObjectPoints().size(); i++) {
                thePoints[2*i] = newPaintObject.getCopyPointAt(i).x+1f;
                thePoints[2*i+1] = newPaintObject.getCopyPointAt(i).y+1f;
            }
            
            getCurrentLayer().add(new PresentationStateGraphicObject(ps.addGraphicObject(currentLayerIndex,applyTo),0,jDVPSGraphicType.DVPST_interpolated,thePoints,newPaintObject.getType(),newPaintObject.filled,screenSize,aff));
        }
        
        
    }
    
    
    /**
     * Deletes all objects of the PresentationStateGraphicsHandler and
     * rebuilds them. Should be called if a new jDVPresentationState object is
     * available in the jDVInterface.
     *
     * @param screenSize The size of the available size for drawing the image.
     * @since 30.04.1999
     */
    
    public void setNewPresentationState(Dimension screenSize) {
        if (havePresentationState) deleteAll();
        //int status = dvi.resetPresentationState();
        buildPresentationState();
        setScreenSize(screenSize);
    }
    
    /**
     * Resets the presentation state to the last saved status.
     *
     * @since 30.04.1999
     */
    public void resetPresentationState() {
        deleteAll();
        int status = dvi.resetPresentationState();
        buildPresentationState();
        setScreenSize(screenSize);
    }
    
    
    /**
     * Deletes all objects of the PresentationStateGraphicsHandler.
     *
     * @since 30.04.1999
     */
    public void deleteAll() {
        
        for(int i = 0; i <listPresentationStateGraphicLayer.size(); i++) {
            ((PresentationStateGraphicLayer) listPresentationStateGraphicLayer.elementAt(0)).deleteAll();
            listPresentationStateGraphicLayer.removeElementAt(0);
        }
        
        
        currentLayerIndex = -1;
        currentLayerObjectIndex = -1;
        listPresentationStateGraphicLayer = null;
        shutterList.deleteAll();
        shutterList = null;
        zoomValue=-1;
        ps = null;
        System.gc();
        
    }
    /**
     * Deletes the currently active PresentationStateLayerObject,
     * specified with the currentLayerObjectIndex.
     *
     * @since 30.04.1999
     */
    
    public void deleteCurrentObject() {
        if (currentLayerObjectIndex != -1)deleteObjectAtIndex(currentLayerObjectIndex);
    }
    
    /**
     * Deletes the specified PresentationStateLayerObject in
     * the currently active PresentationStateGraphicLayer.
     *
     * @param index The index of the deleting PresentationStateLayerObject in
     * the currently active PresentationStateGraphicLayer.
     *
     * @since 30.04.1999
     */
    public void deleteObjectAtIndex(int index) {
        ((PresentationStateGraphicLayer) listPresentationStateGraphicLayer.elementAt(currentLayerIndex)).deleteObjectAt(index);
        currentLayerObjectIndex = -1;
    }
    
    /**
     * Deletes the  PresentationStateGraphicLayer with the specified index
     *
     * @param index The index of the deleting PresentationStateGraphicLayer
     * @since 30.04.1999
     */
    public void deleteLayer(int index) {
        //Delete layer
        ((PresentationStateGraphicLayer) listPresentationStateGraphicLayer.elementAt(index)).deleteAll();
        listPresentationStateGraphicLayer.removeElementAt(index);
        ps.removeGraphicLayer(index);
        
        //Sets new indices for all PresentationStateGraphicLayer greater than the specified index
        for (int i = index; i < listPresentationStateGraphicLayer.size(); i++) {
            ((PresentationStateGraphicLayer) listPresentationStateGraphicLayer.elementAt(i)).index = ((PresentationStateGraphicLayer) listPresentationStateGraphicLayer.elementAt(i)).index-1;
        }
        
        //Select new  active listPresentationStateGraphicLayer
        if (listPresentationStateGraphicLayer.size() >0 ) currentLayerIndex = 0;
        else currentLayerIndex = -1;
        
    }
    
    /**
     * Insert a new PresentationStateGraphicLayer with a RGB -Color.
     *
     * @param label Label of the layer.
     * @param description Decription of the layer.
     * @param r Red color value.
     * @param g Green color value.
     * @param b Blue color value.
     * @see PresentationStateGraphicLayer
     * @since 30.04.1999
     */
    public void insertNewColorLayer(String label, String description, int r,int g, int b) {
        listPresentationStateGraphicLayer.add(new PresentationStateGraphicLayer(listPresentationStateGraphicLayer.size(),ps,label, description, r,g,b,overlayList));
    }
    
    
    /**
     * Insert a new PresentationStateGraphicLayer with a Gray -Color.
     *
     * @param label Label of the layer.
     * @param description Decription of the layer.
     * @param monochome Gray color value.
     * @see PresentationStateGraphicLayer
     * @since 30.04.1999
     */
    public void insertNewMonochromeLayer(String label, String description, float monochome) {
        listPresentationStateGraphicLayer.add(new PresentationStateGraphicLayer(listPresentationStateGraphicLayer.size(),ps,label, description, monochome,overlayList));
        
    }
    
    /**
     * Gets the  PresentationStateGraphicLayer with the specified index.
     * Returns null if no object with the specified index exist.
     *
     * @param index Specifies the PresentationStateGraphicLayer.
     * @return The  PresentationStateGraphicLayer with the specified index.
     * @see PresentationStateGraphicLayer
     * @since 30.04.1999
     */
    public PresentationStateGraphicLayer getLayerAtIndex(int index) {
        if (index == -1) return null;
        else return ((PresentationStateGraphicLayer) listPresentationStateGraphicLayer.elementAt(index));
    }
    
    /**
     * Gets the  Color of the currently active PresentationStateGraphicLayer.
     * Returns null if no PresentationStateGraphicLayer is active.
     *
     * @return The color of the currently active PresentationStateGraphicLayer.
     * @see PresentationStateGraphicLayer
     * @since 30.04.1999
     */
    public Color getCurrentColor() {
        if (getCurrentLayer() == null) return Color.white;
        else return getCurrentLayer().getColor(8);
    }
    
    /**
     * Sets a new PresentationStateTextObject to the currently active
     * PresentationStateGraphicLayer.
     *
     * @param text The text of the new PresentationStateTextObject.
     * @param isBoundingBox If true the PresentationStateTextObject has a bounding box.
     * @param isAnchor If ture the PresentationStateTextObject has an anchor point.
     * @param isboth If true the PresentationStateTextObject has an anchor point and a bounding box.
     * @param isAnchorDisplay If true the exitsting anchor point is display relative.
     * @param isBoxDisplay If true the existing bounding box is display realtive.
     * @param isAnchorVisible If true the existing anchor point have a visible anchor point.
     * @since 30.04.1999
     * @see PresentationStateGraphicLayer
     * @see PresentationStateTextObject
     */
    public void setNewText( String text,
    boolean isBoundingBox,
    boolean isAnchor,
    boolean isAnchorDisplay,
    boolean isBoxDisplay,
    boolean isAnchorVisible,
    int just,
    int rot,
    int applyTo) {
        jDVPSTextObject newText =ps.addTextObject(currentLayerIndex,applyTo);
        
        newText.setText(text);
        
        getCurrentLayer().add(new PresentationStateTextObject(newText,0,screenSize,isAnchor,isBoundingBox,isAnchorDisplay,isBoxDisplay,isAnchorVisible, just, rot));
        currentLayerObjectIndex = getCurrentLayer().listPresentationStateObject.size()-1;
        
    }
    
    
    /**
     * Moves a PresentationStateLayerObject form one
     * PresentationStateGraphicLayer to an other.
     *
     * @param newLayer The index of the new PresentationStateGraphicLayer.
     * @param oldLayer The index of the current PresentationStateGraphicLayer.
     * @param objectIndex The index of the moving PresentationStateLayerObject in the current PresentationStateGraphicLayer.
     * @see PresentationStateGraphicLayer
     * @see PresentationStateTextObject
     * @since 30.04.1999
     */
    public void moveToLayer(    int newLayer,
    int oldLayer,
    int objectIndex, int applyTo) {
        PresentationStateGraphicLayer oldPresentationStateGraphicLayer =((PresentationStateGraphicLayer) listPresentationStateGraphicLayer.elementAt(oldLayer));
        PresentationStateGraphicLayer newPresentationStateGraphicLayer =((PresentationStateGraphicLayer) listPresentationStateGraphicLayer.elementAt(newLayer));
        PresentationStateLayerObject moveObject = oldPresentationStateGraphicLayer.layerObjectAt(objectIndex);
        
        //move in c++
        if (moveObject instanceof PresentationStateTextObject) {
            ps.moveGraphicObject( oldLayer, moveObject.getIndex(),  newLayer, applyTo);
        }
        if (moveObject instanceof PresentationStateGraphicObject) {
            ps.moveGraphicObject( oldLayer, moveObject.getIndex(),  newLayer,applyTo);
        }
        
        //move in java
        oldPresentationStateGraphicLayer.removeObjectAt(objectIndex);
        newPresentationStateGraphicLayer.add(moveObject);
    }
    
    /**
     * Returns the zoom value.
     *
     * @return The zoom value.
     * @since 30.04.1999
     */
    public double getZoomValue() {
        return zoomValue;
    }
    
    /**
     * Sets the zoom value.
     *
     * @param  zoomValue The new zoom value.
     * @since 30.04.1999
     */
    public void setZoomValue(double zoomValue) {
        this.zoomValue = zoomValue;
    }
    
    
    /**
     * Updates the PresentationStateGraphicsHandler without changing the enablePresentationState status.
     *
     * @since 30.04.1999
     */
    public void updatePresentationState() {
        deleteAll();
        boolean temp = enablePresentationState; // enable... wird in build..() überschrieben
        buildPresentationState();
        enablePresentationState = temp;
        setScreenSize(screenSize);
    }
    
    public void getPrintImageBuffer(TransformationConverter transConv) {
        
        //Loads Size of the bitmap
        jIntByRef h = new jIntByRef();
        jIntByRef w = new jIntByRef();
        if ( ps.getPrintBitmapWidthHeight(w,h)!= jE_Condition.EC_Normal) {
            JOptionPane.showMessageDialog(null,"Error: Can not determine bitmap size");
            return ;
        }
        
        //Init shortArray
        short[] pix = new short[(int)ps.getPrintBitmapSize()/2];
        
        //Loads the print bitmap
        if (ps.getPrintBitmap(pix, ps.getPrintBitmapSize()) == jE_Condition.EC_Normal) {
            
            BufferedImage printImage;
            WritableRaster wr;
            DataBufferUShort dbs;;
            int bandOffsets[] = {0};
            
            //Aspect ration
            double asRatio = ps.getPrintBitmapPixelAspectRatio();
            
            
            //Init BurreredImage with print bitmap
            dbs = new DataBufferUShort( pix,pix.length);
            wr = Raster.createInterleavedRaster(dbs,w.value,h.value,w.value,1, bandOffsets,null);
            printImage = new BufferedImage(GrayColorIndex.getGray12BitColorModel(), wr, GrayColorIndex.getGray12BitColorModel().isAlphaPremultiplied(), null);
            DisplayArea da = getDisplayArea();
            
            
            //Saves the current screenSize
            Dimension saveScreen = screenSize;
            
            
            int width = da.getBrhcX()-da.getTlhcX();
            int height = da.getBrhcY()-da.getTlhcY();
            
            double        printZoom ;
            int rot = ps.getRotation();
            
            if ((rot ==1) ||(rot== 3)) {
                printZoom= (double)(h.value /width);
                setScreenSize(new Dimension(h.value, w.value));
            }
            else {
                
                printZoom= (double)(w.value /width);
                setScreenSize(new Dimension(w.value, h.value));
            }
            System.err.println("printZoom: "+printZoom);
            
            //Loads transformations
            AffineTransform aff = transConv.getPrintTransformation(printZoom);
            AffineTransform overlayAff = transConv.getPrintOverlayTransformation();
            
            Graphics2D g2 = (Graphics2D) printImage.createGraphics();
            
            shutterList.drawShutter(g2, aff, w.value,h.value, 12);
            
            
            drawPaintStructure(printImage,aff,overlayAff,true,12, true);
            //drawPaintStructure(printImage,aff,new AffineTransform(),true,12, true);
            
            
            setScreenSize(saveScreen);
            
            if (dvi.saveGrayscaleHardcopyImage(pix, w.value, h.value, asRatio)== jE_Condition.EC_Normal) {
                Controller.instance().firePrint(new PrintEvent(this,PrintEvent.ID_HC));
            }
            else {
                JOptionPane.showMessageDialog(null,"Error: Can not print image");
                
            }
            
        }
        else {
            JOptionPane.showMessageDialog(null,"Error: Can not create print display");
        }
        
        pix = null;
        System.gc();
        System.err.println("end-print");
    }
    
    /**
     * Selects one frame of a multiframe image. This affects the image bitmap
     * that is rendered, the overlay bitmaps and the visibility of graphic and text
     * objects. This method may only be called when an image is attached to the
     * presentation state.
     * @param idx frame number in the range [1..getImageNumberOfFrames()]
     */
    public void selectImageFrameNumber(int idx) {
        if ((idx >= 1)&&(idx <= getImageNumberOfFrames()))
            ps.selectImageFrameNumber(idx);
    }
    
    
    /**
     * Selects the next frame of a multiframe image. This affects the image bitmap
     * that is rendered, the overlay bitmaps and the visibility of graphic and text
     * objects. This method may only be called when an image is attached to the
     * presentation state.
     * @param idx frame number in the range [1..getImageNumberOfFrames()]
     */
    public  int getSelectedImageFrameNumber() {
        return ps.getSelectedImageFrameNumber();
        
    }
    
    /**
     *  Selects the next frame of a multiframe image.
     *  @return Number of the selected frame
     */
    public  int selectNextFrame() {
        
        if (getSelectedImageFrameNumber() < getImageNumberOfFrames()) {
            selectImageFrameNumber(getSelectedImageFrameNumber()+1);
            return getSelectedImageFrameNumber()+1;
        }
        else return getSelectedImageFrameNumber();
        
    }
    /**
     *  Selects the next frame of a multiframe image.
     *  @return Number of the selected frame
     */
    public  int selectPreviousFrame() {
        if (getSelectedImageFrameNumber() > 1) {
            selectImageFrameNumber(getSelectedImageFrameNumber()-1);
            return getSelectedImageFrameNumber()-1;
        }
        else return 1;
        
    }
    
    /**
     * Returns the number of frames of the current image.
     */
    public int getImageNumberOfFrames() {
        jIntByRef num = new jIntByRef();
        ps.getImageNumberOfFrames(num);
        return num.value;
    }
    
    
    
    
    
    
    /**
     * Gets the number of image references contained in the current presentation state.
     *  @return number of image references, 0 if an error occurred.
     */
    public int getNumberOfImages() {
        return dvi.getNumberOfImageReferences();
    }
    /**
     *  Loads an image which referenced by the current presentation
     *  state and needs to be contained in the database.
     *  This method acquires a database lock which must be explicitly freed by the user.
     *  @param idx index of the image to be loaded getNumberOfImage();
     */
    public  void selectImageNumber(int idx) {
        if ((idx >= 1)&&(idx <= getNumberOfImages())) {
            dvi.loadReferencedImage(idx-1,true);
            dvi.releaseDatabase();
            Controller.instance().fireEvent(new UpdateBrowserEvent(this));
            selectedImageNumber = idx;
            Controller.instance().fireStatus(new SignedStatusEvent(this,
            SignedStatusEvent.LOADIMAGE,
            dvi.getCurrentSignatureStatus(jDVPSObjectType.DVPSS_image),
            dvi.getCurrentSignatureStatus(jDVPSObjectType.DVPSS_structuredReport)));
            
        }
    }
    
    /**
     *  Gets the index of the currently selected image.
     *  @return index of the currently selected image, 0 if an error occurred
     */
    public int getSelectedImageNumber() {
        return selectedImageNumber;
    }
    
    
    
    /**
     *  Selects the next frame of a multiframe image.
     *  @return Number of the selected frame
     */
    public  int selectNextImage() {
        
        if (getSelectedImageNumber() < getNumberOfImages()) {
            selectImageNumber(getSelectedImageNumber()+1);
            return getSelectedImageNumber()+1;
        }
        else return getNumberOfImages();
        
    }
    /**
     *  Selects the next frame of a multiframe image.
     *  @return Number of the selected frame
     */
    public  int selectPreviousImage() {
        if (getSelectedImageNumber() > 1) {
            selectImageNumber(getSelectedImageNumber()-1);
            return getSelectedImageNumber()-1;
        }
        else return 1;
        
    }
    
    
}

/*
 *  CVS Log
 *  $Log: PresentationStateGraphicsHandler.java,v $
 *  Revision 1.2  2003/09/08 10:17:26  kleber
 *  Bugfix: The Displayed Area is defined after the spatial transformation.
 *
 *  Revision 1.1.1.1  2001/06/06 10:32:30  kleber
 *  Init commit for DICOMscope 3.5
 *  Create new CVS
 *
 */
