/*--- formatted by Jindent 2.1, (www.c-lab.de/~jindent) ---*/

/*
 * The package jm.kidney is part of the Renal Function Project
 * for analysis of dynamic contrast medium evalutions MRT-Images
 * of the Kidneys.
 *
 * Copyright (C) 1999 / 2000 Jens Martin
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package jm.kidney;

import ij.*;
import ij.gui.*;
import ij.process.*;

import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;

// import java.lang.Thread.*;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;

import rad.dicom.dcm.*;

import jm.cepstrum.*;
import jm.sit.*;
import jm.extension.*;
import jm.kidney.*;
import jm.util.*;
import jm.segmentation.*;


/**
 * Diese Klasse stellt das Hauptfenster des Plugins zur renalen Funktionsanalyse dar.
 * Gleichzeitig uebernimmt sie die Funktionalitaet eines Datencontainers, indem
 * einige hier gespeicherte Settings als public deklariert sind und so ein
 * Zugriff von anderen Klassen aus stattfinden kann.
 * <BR> Der Aufrug erfolgt aus der Plugin-Schnittstellen-Klasse RENAL_FUNCTION_Analysis
 * @version  5.2, 14/02/2000
 * @author   Jens Martin
 */
public class AnalysisDialog extends JFrame implements ActionListener, ChangeListener, WindowListener {
  
  // Member-Variablen
  private PresetsDialog			presetsDialog = null;
  public boolean						test = false;
  private boolean						cepstrumSuccess = false;
  public boolean						isCancelPressed = false;
  public boolean						isStartAnalysisPressed = false;
  public boolean						propertiesOk = false;
  public boolean						newResultWindow = false;
  public boolean						interpolateNullValues = true;
  public boolean						showNullValues = false;
  public boolean						verboseResults = false;
  public boolean						secondChance = true;
  public boolean						rasterTransformation = false;
  public boolean						writeLog = true;
  public boolean						enableMinDiff = true;
  public boolean						verboseSIT = true;
  public boolean						splashScreen = true;
  
  public int								startImage = 1;
  public int								switchToMinDiff = 1000;
  public int								threadPriority = java.lang.Thread.MAX_PRIORITY;
  
  public int[]							acquisitionTime = null;
  public int[][]						cepstrumResult = null;
  private boolean						fetchStartParameters = false;
  private boolean						leftRoiLocked = false;
  private boolean						rightRoiLocked = false;
  private int								actualImage = 0;
  private int								maxImage = 0;
  public double							analysisAccuracy = 2.0;
  public double							classificationRange = 0.5;
  
  private String						dialogTitle = " RENAL FUNCTION Analysis";
  private Color							darkblue = new Color(0, 0, 100);
  private Color							darkred = new Color(136, 0, 0);
  private Font							MenuInactive = new Font("Dialog", 0, 11);
  private Font							MenuActive = new Font("Dialog", 1, 11);
  
  private Image							image;
  public ImagePlus					imagePlus = null;
  public ImageStack					imageStack = null;
  public ImageWindow				imageWindow = null;
  public ExImageCanvas			imageCanvas = null;
  public ExStackWindow			stackWindow = null;
  private StackWindow			oldStackWindow = null;
  private Roi								leftRoi = null;
  private Roi								rightRoi = null;
  private Roi								dummyRoi = null;
  private Rectangle					originalCancelSize = null;
  private CepstrumAnalysis	cepstrumAnalysis = null;
  private SITAnalysis				sitAnalysis = null;
  
  // GUI-Elemente des Dialoges
  JPanel										jPanelMain = new JPanel();
  GridBagLayout							gridBagLayoutMainPanel = new GridBagLayout();
  ExJButton									jButtonStartAnalysis = new ExJButton();
  ExJButton									jButtonPresets = new ExJButton();
  ExJButton									jButtonSegmentation = new ExJButton();
  ExJButton									jButtonExit = new ExJButton();
  JLabel										jLabelStatusBar = new JLabel();
  JLabel										jLabelImage = new JLabel();
  JTextArea									jTextAreaPatienInfo = new JTextArea();
  JPanel										jPanelRois = new JPanel();
  ExJButton									jButtonLeftRoi = new ExJButton();
  ExJButton									jButtonRightRoi = new ExJButton();
  GridBagLayout							gridBagLayoutPanelRois = new GridBagLayout();
  JLabel										jLabelAccuracy = new JLabel();
  JSlider										jSliderAccuracy = new JSlider();
  ExJButton									jButtonCancel = new ExJButton();
  ExJButton									jButtonSIT = new ExJButton();
  JPanel										jPanelMenue = new JPanel();
  JLabel										jLabelPatientHeadline = new JLabel();
  JLabel										jLabelAnalysisHeadline = new JLabel();
  GridBagLayout							gridBagLayout3 = new GridBagLayout();
  ExJButton									jButtonAbout = new ExJButton();
  
  // MultiLineLabel jLabelInfo = new MultiLineLabel(" Renal Function Analysis\n     Plugin for ImageJ\n(C)1999/2000 Jens Martin");
  // JLabel jLabelInfo = new JLabel(" Renal Function Analysis\n     Plugin for ImageJ\n(C)1999/2000 Jens Martin");
  JTextArea									jLabelInfo = new JTextArea();
  
  // JRadioButton jCheckBoxAutoSegmentation = new JRadioButton();
  
  public String							seriesDate = "";
  public String							studyDate = "";
  public String							patientName = "";
  public String							patientID = "";
  public String							patientBirth = "";
  public int								patientWeight = 0;
  public int								patientAge = 0;
  public double							timeTR = 0.0;
  public double							timeTE = 0.0;
  public String							patientSex = "";
  public String							institutionName = "";
  public String							matrix = "";
  public int								fovX = 0;
  public int								fovY = 0;
  public int								matrixX = 0;
  public int								matrixY = 0;
  public double							pixelSpacingX = 1.0;
  public double							pixelSpacingY = 1.0;
  
  public boolean						hasPatientInfo = false;
  public boolean						seriesLoaded = false;
  
  
  /**
   * Der Konstruktor.
   * @param    win    Referenz auf das ImagePlus-Fenster-Objekt mit der Nierensequenz
   */
  public AnalysisDialog(ImageWindow win) {
    super();
    try {
      imageWindow = win;
      presetsDialog = new PresetsDialog(this);
      transferPresetValues();
      guiPreparation();
      
      // 2000.8.2 tha: String splashScreenFileName = "." + File.separator + "images" + File.separator + "Splash.gif";
      // 2000.8.2 tha: JSplashScreen splash = new JSplashScreen(this,splashScreenFileName,3900);
      JSplashScreen splash = new JSplashScreen(this, AnalysisDialog.class.getResource("Splash.gif"), 3900);
      
      splash.setVisible(splashScreen);
      jbInit();
      guiInit();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  
  
  /**
   * Hilfmethode, um die Werte der Presets-Variablen direkt aus der Klasse PresetsDialog
   * zu lesen. Dort muessen Deklarationen public sein
   * @see jm.kidney.PresetsDialog
   */
  private void transferPresetValues() {
    startImage = presetsDialog.ignoreFirst + 1;
    
    // IJ.write("Startimage: " + startImage);
    switchToMinDiff = presetsDialog.minDiffSwitch;
    
    // IJ.write("minDiffAfter: " + switchToMinDiff);
    enableMinDiff = presetsDialog.minDiff;
    
    // IJ.write("minDiffEnabled: " + enableMinDiff);
    newResultWindow = presetsDialog.newWindow;
    interpolateNullValues = presetsDialog.interpolateMissing;
    showNullValues = presetsDialog.showNullValues;
    verboseResults = presetsDialog.verboseText;
    secondChance = presetsDialog.secondChance;
    rasterTransformation = presetsDialog.rasterTransformation;
    threadPriority = presetsDialog.threadPriority;
    writeLog = presetsDialog.writeLog;
    classificationRange = presetsDialog.classificationRange;
    verboseSIT = presetsDialog.verboseSIT;
    splashScreen = presetsDialog.splashScreen;
  }
  
  
  /**
   * Initialisierung der Objekte des Fensters.
   * Von JBuilder automatisch eingefuegt.
   */
  private void jbInit() throws Exception {
    
    // GUI-Bestandteile formatieren
    jPanelMain.setForeground(Color.lightGray);
    jPanelMain.setBackground(Color.black);
    jButtonStartAnalysis.setText("Start Analysis");
    
    // jButtonStartAnalysis.setLabel("Start Analysis");
    jButtonPresets.setText("Presets");
    
    // jButtonPresets.setLabel("Presets");
    // jButtonSegmentation.setLabel("Try Segmentation");
    jButtonSegmentation.setText("Try Segmentation");
    jButtonExit.setText("Exit");
    
    // jButtonExit.setLabel("Exit");
    jLabelStatusBar.setText(" Ready");
    
    // jLabelStatusBar.setBorder(new LineBorder(Color.gray));
    jPanelMain.setLayout(gridBagLayoutMainPanel);
    jLabelStatusBar.setForeground(Color.orange);
    jTextAreaPatienInfo.setRequestFocusEnabled(false);
    jTextAreaPatienInfo.setEnabled(false);
    jTextAreaPatienInfo.setForeground(Color.white);
    jTextAreaPatienInfo.setBackground(Color.darkGray);
    jTextAreaPatienInfo.setFont(new Font("Monospaced", 0, 11));
    jTextAreaPatienInfo.setBorder(new LineBorder(Color.gray));
    
    // jTextAreaPatienInfo.setText("Patient \nInfo");
    this.setPatientInfoText();
    jButtonRightRoi.setText(" lock left ROI");
    jButtonRightRoi.setMargin(new Insets(0, 4, 0, 4));
    
    // jButtonRightRoi.setLabel("lock left ROI");
    jButtonRightRoi.setFont(new Font("Dialog", 1, 11));
    jButtonLeftRoi.setText("lock right ROI");
    jButtonLeftRoi.setMargin(new Insets(0, 4, 0, 4));
    
    // jButtonLeftRoi.setLabel(" lock right ROI");
    jButtonLeftRoi.setFont(new Font("Dialog", 1, 11));
    jButtonRightRoi.setText("lock left Roi");
    jButtonRightRoi.setForeground(Color.lightGray);
    jButtonLeftRoi.setText("lock right Roi");
    jButtonLeftRoi.setForeground(Color.lightGray);
    jPanelRois.setLayout(gridBagLayoutPanelRois);
    jPanelRois.setForeground(Color.lightGray);
    jPanelRois.setBackground(Color.black);
    jPanelRois.setBorder(new LineBorder(Color.gray));
    jButtonStartAnalysis.setText("Movement Correction");
    jButtonStartAnalysis.setMargin(new Insets(0, 0, 0, 8));
    jButtonPresets.setMargin(new Insets(0, 0, 0, 8));
    jButtonSegmentation.setMargin(new Insets(0, 0, 0, 8));
    jButtonExit.setMargin(new Insets(0, 0, 0, 8));
    
    // jButtonSIT.setText("jButton2");
    jButtonSIT.setText("Calculate SIT");
    
    // jButtonCancel.setText("jButton1");
    jButtonCancel.setText("Cancel");
    jButtonCancel.setForeground(Color.orange);
    jButtonCancel.setMargin(new Insets(2, 4, 2, 4));
    jButtonSIT.setMargin(new Insets(0, 0, 0, 8));
    jButtonCancel.setFont(new Font("Dialog", 1, 11));
    
    jSliderAccuracy.setMinimum(10);
    jSliderAccuracy.setMaximum(40);
    jSliderAccuracy.setMajorTickSpacing(10);
    jSliderAccuracy.setMinorTickSpacing(1);
    jSliderAccuracy.setSnapToTicks(true);
    jSliderAccuracy.setValue((int) (analysisAccuracy * 10.0));
    jLabelAccuracy.setText("-    Analysis accuracy: 1.0    +");
    jLabelAccuracy.setForeground(Color.lightGray);
    jLabelAccuracy.setFont(new Font("Dialog", 1, 11));
    jLabelAnalysisHeadline.setText("Settings Movement Correction");
    jLabelPatientHeadline.setText("Series Data");
    jPanelMenue.setLayout(gridBagLayout3);
    jPanelMenue.setForeground(Color.lightGray);
    jPanelMenue.setBackground(Color.black);
    jLabelStatusBar.setBackground(Color.darkGray);
    jLabelStatusBar.setOpaque(true);
    jLabelStatusBar.setFont(new Font("Dialog", 1, 11));
    
    // configure the menu bar
    // jPanelMenue.setBorder(new LineBorder(Color.gray));
    jButtonStartAnalysis.setForeground(Color.lightGray);
    jButtonStartAnalysis.setBackground(Color.black);
    jButtonPresets.setForeground(Color.lightGray);
    jButtonPresets.setBackground(Color.black);
    jButtonSegmentation.setForeground(Color.lightGray);
    jButtonSegmentation.setBackground(Color.black);
    jButtonSIT.setForeground(Color.lightGray);
    jButtonSIT.setBackground(Color.black);
    jButtonExit.setForeground(Color.lightGray);
    jButtonExit.setBackground(Color.black);
    
    jButtonSIT.setFont(this.MenuActive);
    jButtonExit.setFont(this.MenuActive);
    jButtonSegmentation.setFont(this.MenuActive);
    jButtonPresets.setFont(this.MenuActive);
    jButtonStartAnalysis.setFont(this.MenuActive);
    
    jButtonSIT.setFocusPainted(false);
    jButtonExit.setFocusPainted(false);
    jButtonSegmentation.setFocusPainted(false);
    jButtonPresets.setFocusPainted(false);
    jButtonStartAnalysis.setFocusPainted(false);
    
    jButtonStartAnalysis.setToolTipText("Start Cepstrum Movement Correction");
    jButtonExit.setToolTipText("Exit Renal Analysis Plugin");
    
    // IJ.write("Scheinen auch geklappt zu haben");
    // IJ.write("Nun Raidiobuttons und Action-Listener...");
    
    dummyRoi = new Roi(0, 0, imagePlus);
    jTextAreaPatienInfo.setSelectionColor(Color.darkGray);
    jTextAreaPatienInfo.setSelectedTextColor(Color.white);
    jLabelStatusBar.setToolTipText("actual Status");
    
    // Radiobuttons gruppieren
    
    jButtonAbout.setText("About");
    jButtonAbout.setMargin(new Insets(0, 0, 0, 8));
    jButtonAbout.setForeground(Color.lightGray);
    jLabelInfo.setRequestFocusEnabled(false);
    jLabelInfo.setEnabled(false);
    jLabelInfo.setText("\n Renal Function Analysis\n     Plugin for ImageJ\n(C)1999/2000 Jens Martin");
    jLabelInfo.setSelectedTextColor(Color.orange);
    
    // jLabelInfo.setRequestFocusEnabled(false);
    jLabelInfo.setForeground(Color.orange);
    jLabelInfo.setBackground(Color.black);
    jLabelInfo.setSelectionColor(Color.black);
    jLabelInfo.setFont(new Font("Dialog", 0, 9));
    jLabelInfo.setDisabledTextColor(Color.orange);
    jLabelInfo.setToolTipText("Press \"About\" for more Information");
    jLabelInfo.setEditable(false);
    
    // jLabelInfo.setOpaque(true);
    jButtonAbout.setBackground(Color.black);
    jButtonAbout.setFont(this.MenuActive);
    jButtonAbout.setFocusPainted(false);
    jButtonAbout.setToolTipText("About Renal Analysis Plugin");
    jButtonAbout.setFont(new Font("Dialog", 1, 11));
    jButtonAbout.setOpaque(true);
    jButtonCancel.setOpaque(true);
    jButtonCancel.setToolTipText("stop the current process");
    jButtonCancel.setBackground(Color.gray);
    jSliderAccuracy.setForeground(Color.lightGray);
    jSliderAccuracy.setBackground(Color.black);
    jSliderAccuracy.setToolTipText("adjust analysis accuracy");
    jSliderAccuracy.setRequestFocusEnabled(false);
    
    jLabelAccuracy.setOpaque(true);
    jLabelAccuracy.setBackground(Color.black);
    
    // jCheckBoxAutoSegmentation.setOpaque(false);
    // jCheckBoxAutoSegmentation.setFocusPainted(false);
    
    jButtonLeftRoi.setOpaque(true);
    jButtonLeftRoi.setToolTipText("locks the ROI for the right kidney");
    jButtonRightRoi.setOpaque(true);
    jButtonRightRoi.setToolTipText("locks the ROI for the left kidney");
    jButtonRightRoi.setBackground(Color.darkGray);
    jButtonLeftRoi.setBackground(Color.darkGray);
    jLabelAnalysisHeadline.setForeground(Color.lightGray);
    jLabelAnalysisHeadline.setBackground(Color.black);
    jLabelAnalysisHeadline.setFont(new Font("Dialog", 1, 11));
    jLabelAnalysisHeadline.setOpaque(true);
    jLabelPatientHeadline.setForeground(Color.lightGray);
    jLabelPatientHeadline.setBackground(Color.black);
    jLabelPatientHeadline.setFont(new Font("Dialog", 1, 11));
    jLabelPatientHeadline.setOpaque(true);
    
    // jFrameMain.setBackground(Color.black);
    jButtonSIT.setFont(new Font("Dialog", 1, 11));
    jButtonSIT.setOpaque(true);
    jButtonSIT.setToolTipText("Calculate Signal-Intensity-Time Curves");
    jButtonExit.setFont(new Font("Dialog", 1, 11));
    jButtonExit.setOpaque(true);
    jButtonSegmentation.setFont(new Font("Dialog", 1, 11));
    jButtonSegmentation.setOpaque(true);
    jButtonSegmentation.setToolTipText("detect the kidney\'s contour");
    jButtonPresets.setFont(new Font("Dialog", 1, 11));
    jButtonPresets.setOpaque(true);
    jButtonPresets.setToolTipText("Show / Edit Presets");
    jButtonStartAnalysis.setFont(new Font("Dialog", 1, 11));
    jButtonStartAnalysis.setOpaque(true);
    jButtonExit.setBorderPainted(false);
    jButtonAbout.setBorderPainted(false);
    jButtonSegmentation.setBorderPainted(false);
    jButtonPresets.setBorderPainted(false);
    jButtonSIT.setBorderPainted(false);
    jButtonRightRoi.setBorderPainted(false);
    jButtonLeftRoi.setBorderPainted(false);
    jTextAreaPatienInfo.setDisabledTextColor(Color.white);
    jTextAreaPatienInfo.setToolTipText("Information about imported Sequence");
    jTextAreaPatienInfo.setEditable(false);
    jTextAreaPatienInfo.setCaretColor(Color.darkGray);
    
    
    // jFrameMain.setForeground(Color.lightGray);
    this.getContentPane().add(jPanelMain, BorderLayout.CENTER);
    jPanelMain.add(jLabelStatusBar, new GridBagConstraints2(0, 6, 2, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(7, 0, 0, 0), 0, 0));
    jPanelMain.add(jTextAreaPatienInfo, new GridBagConstraints2(0, 2, 1, 4, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 12, 0, 15), 0, 0));
    jPanelMain.add(jPanelRois, new GridBagConstraints2(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.BOTH, new Insets(0, 0, 0, 10), 0, 0));
    jPanelRois.add(jButtonLeftRoi, new GridBagConstraints2(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 0, 5), 0, 0));
    jPanelRois.add(jButtonRightRoi, new GridBagConstraints2(2, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 0, 5), 0, 0));
    jPanelRois.add(jLabelAccuracy, new GridBagConstraints2(1, 2, 2, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0));
    jPanelRois.add(jSliderAccuracy, new GridBagConstraints2(1, 1, 2, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 0, 5), 0, 0));
    jPanelMain.add(jButtonCancel, new GridBagConstraints2(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTHEAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 10), 0, 0));
    jPanelMain.add(jPanelMenue, new GridBagConstraints2(0, 0, 2, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
    jPanelMenue.add(jButtonStartAnalysis, new GridBagConstraints2(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
    jPanelMenue.add(jButtonPresets, new GridBagConstraints2(2, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
    jPanelMenue.add(jButtonSegmentation, new GridBagConstraints2(3, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
    jPanelMenue.add(jButtonSIT, new GridBagConstraints2(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
    jPanelMenue.add(jButtonAbout, new GridBagConstraints2(4, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
    jPanelMenue.add(jButtonExit, new GridBagConstraints2(5, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
    jPanelMain.add(jLabelPatientHeadline, new GridBagConstraints2(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTHWEST, GridBagConstraints.HORIZONTAL, new Insets(10, 15, 0, 0), 0, 0));
    jPanelMain.add(jLabelAnalysisHeadline, new GridBagConstraints2(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTHWEST, GridBagConstraints.HORIZONTAL, new Insets(10, 5, 0, 0), 0, 0));
    jPanelMain.add(jLabelInfo, new GridBagConstraints2(1, 3, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
    
  }
  
  
  /**
   * Routine zur Nachrichtenbehandung von Mausklicks oder Tastatureingaben.
   * Stellt fest, auf welche Schaltflaechen des Dialogs geklickt wurde.
   * @param evt uebergebener ActionEvent, ausgeloest durch eine Mausklick oder Tastatureingabe.
   */
  public void actionPerformed(ActionEvent evt) {
    
    // IJ.write("pressed!!!!!!!");
    Object	src = evt.getSource();
    
    if (src instanceof JButton) {
      if (src == jButtonExit) {
        exitPlugin();
      }
      
      if (src == jButtonAbout) {
        
        // 2000.8.2 tha: String splashScreenFileName = "." + File.separator + "images" + File.separator + "Splash.gif";
        // 2000.8.2 tha: AboutDialog ad = new AboutDialog(splashScreenFileName);
        AboutDialog ad = new AboutDialog(AnalysisDialog.class.getResource("Splash.gif"));
        
        ad.setVisible(true);
      }
      
      
      if (src == jButtonSIT) {
        
        // IJ.write("StarteAnalyse!");
        startImage = presetsDialog.ignoreFirst + 1;
        switchToMinDiff = presetsDialog.minDiffSwitch;
        startSIT();
      }
      
      if (src == jButtonStartAnalysis) {
        
        // IJ.write("StarteAnalyse!");
        startCepstrum();
      }
      
      if (src == jButtonSegmentation) {
        
        // IJ.write("StarteAnalyse!");
        startSegmentation();
      }
      
      if (src == jButtonPresets) {
        presetsDialog.setVisible(true);
        presetsDialog.repaint();
      }
      
      if (src == jButtonCancel) {
        
        // IJ.write("UIIII !!! Abgebrochen !");
        // startAnalysis();
        if (cepstrumAnalysis != null) {
          cepstrumAnalysis.stopRunning = true;
          
          // this.cepstrumFinished();
        }
        if (sitAnalysis != null) {
          sitAnalysis.stopRunning = true;
          
          // this.sitFinished();
        }
        IJ.showProgress(1.0);
        IJ.showStatus("");
      }
      
      if (src == jButtonLeftRoi) {
        Roi roi = imagePlus.getRoi();
        
        if (roi != null) {
          int type = roi.getType();
          
          if (!(type == roi.RECTANGLE || type == roi.POLYGON || type == roi.FREEROI)) {
            JOptionPane.showMessageDialog(null, "Please lock a ROI for both Kidneys !\n\nUse a Rectangle, Polygon or Freehand ROI.", " Wrong type of ROI", JOptionPane.ERROR_MESSAGE);
            roi = null;
          } else {
            toggleLeftRoi(roi);
          }
        } else {
          toggleLeftRoi(roi);
        }
      }
      
      if (src == jButtonRightRoi) {
        Roi roi = imagePlus.getRoi();
        
        if (roi != null) {
          int type = roi.getType();
          
          if (!(type == roi.RECTANGLE || type == roi.POLYGON || type == roi.FREEROI)) {
            JOptionPane.showMessageDialog(null, "Please lock a ROI for both Kidneys !\n\nUse a Rectangle, Polygon or Freehand ROI.", " Wrong type of ROI", JOptionPane.ERROR_MESSAGE);
            roi = null;
          } else {
            toggleRightRoi(roi);
          }
        } else {
          toggleRightRoi(roi);
        }
      }
    }
  }
  
  
  /**
   * Bewirkt einen Wechsel des Zustandes der linken ROI zwischen arretiertem und
   * frei-aktivem Zustand.
   * @param roi uebergebene, aktive Roi (kann auch null sein)
   */
  private void toggleLeftRoi(Roi roi) {
    try {
      if (!(roi == null || leftRoiLocked)) {
        lockLeftRoi(roi, true, true);
      } else {
        lockLeftRoi(null, false, true);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  
  
  /**
   * Setzt den Zustand der linken Roi.
   * @param roi uebergebene, aktive Roi (kann auch null sein)
   * @param lockit true, wenn die im Parameter 1 uebergebene Roi arretiert werden soll.
   * @param keepit true, eine evtl. vorhandenen alte, arretierte Roi nicht geloescht werden soll.
   */
  public void lockLeftRoi(Roi roi, boolean lockIt, boolean keepIt) {
    if (lockIt && roi != null) {
      Rectangle rec = roi.getBoundingRect();
      
      if ((rec.x + rec.width / 2) < ((imagePlus.getWidth()) / 2)) {
        leftRoi = roi;
        imagePlus.killRoi();
        leftRoiLocked = true;
        imageCanvas.setRoi(JMConst.LEFT, leftRoi);
        
        // imagePlus.setRoi(dummyRoi);
        jButtonLeftRoi.setText("unlock right");
        jButtonLeftRoi.setForeground(Color.orange);
        imagePlus.updateAndDraw();
      }
    } else {
      leftRoiLocked = false;
      if ((leftRoi != null) && (imagePlus.getRoi() == null)) {
        imagePlus.setRoi(leftRoi);
      }
      leftRoi = null;
      if (!keepIt) {
        imageCanvas.deleteRois(JMConst.LEFT, JMConst.MAIN);
      }
      jButtonLeftRoi.setText("lock right Roi");
      jButtonLeftRoi.setForeground(Color.lightGray);
      imagePlus.updateAndDraw();
    }
  }
  
  
  /**
   * Bewirkt einen Wechsel des Zustandes der rechten ROI zwischen arretiertem und
   * frei-aktivem Zustand.
   * @param roi uebergebene, aktive Roi (kann auch null sein)
   */
  private void toggleRightRoi(Roi roi) {
    try {
      if (!(roi == null || rightRoiLocked)) {
        lockRightRoi(roi, true, true);
      } else {
        lockRightRoi(null, false, true);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  
  
  /**
   * Setzt den Zustand der rechten Roi.
   * @param roi uebergebene, aktive Roi (kann auch null sein)
   * @param lockit true, wenn die im Parameter 1 uebergebene Roi arretiert werden soll.
   * @param keepit true, eine evtl. vorhandenen alte, arretierte Roi nicht geloescht werden soll.
   */
  public void lockRightRoi(Roi roi, boolean lockIt, boolean keepIt) {
    if (lockIt && roi != null) {
      Rectangle rec = roi.getBoundingRect();
      
      if ((rec.x + rec.width / 2) > ((imagePlus.getWidth()) / 2)) {
        rightRoi = roi;
        imagePlus.killRoi();
        rightRoiLocked = true;
        imageCanvas.setRoi(JMConst.RIGHT, rightRoi);
        
        // imagePlus.setRoi(dummyRoi);
        jButtonRightRoi.setText("unlock left");
        jButtonRightRoi.setForeground(Color.orange);
        imagePlus.updateAndDraw();
      }
    } else {
      rightRoiLocked = false;
      if ((rightRoi != null) && (imagePlus.getRoi() == null)) {
        imagePlus.setRoi(rightRoi);
      }
      rightRoi = null;
      if (!keepIt) {
        imageCanvas.deleteRois(JMConst.RIGHT, JMConst.MAIN);
      }
      jButtonRightRoi.setText(" lock left Roi");
      jButtonRightRoi.setForeground(Color.lightGray);
      imagePlus.updateAndDraw();
    }
  }
  
  
  /**
   * Stellt fest, ob der Schieberegler zur Einstellung der Analysegenauigkiet veraendert wurde.
   * @param evt ChangeEvent, ausgeloest durch Bewegung des Schiebereglers.
   */
  public void stateChanged(ChangeEvent evt) {
    Object	src = evt.getSource();
    
    if (src == jSliderAccuracy) {
      
      // !!!
      // IJ.write("haha !!! Wurde gechanged !");
      analysisAccuracy = (double) jSliderAccuracy.getValue() / 10.0;
      String	text = "-    Analysis accuracy: ";
      
      text = text + d2s(analysisAccuracy, 1);		// (Double.toString(analysisAccuracy)).substring(0,3);
      text = text + "    +";
      jLabelAccuracy.setText(text);
    }
  }
  
  
  /**
   * Wird beim Verlassen des Plugins (Schliessen des Fensters) aufgerufen.
   * Setzt den ExImageCanvas wieder auf einen ImageCanvas zurueck (Typumwandlung).
   */
  private void exitPlugin() {
    
    IJ.write("Ende!");
    isCancelPressed = true;
    if (imagePlus != null && stackWindow != null && (imagePlus.getWindow() != null)) {
      imagePlus.unlock();
      stackWindow.unlock();
      //Rectangle bounds = stackWindow.getBounds();
      stackWindow.setVisible(false);
      imagePlus.setWindow(null);
      if(imageCanvas != null) {
        imageCanvas.endThreads();
        
        //imageCanvas.awtToolTip.setSourceClass(null);
      }
      
      // oldStackWindow =  new StackWindow(imagePlus);
      // imagePlus.setWindow(oldStackWindow);
      // imagePlus.setStack(getTitle(),imageStack);
      // imagePlus.setTitle(imagePlus.getTitle());
      // stackWindow = null;
      IJ.wait(100);
      imagePlus.show();
      
      // imagePlus.getWindow().setBounds(bounds);
    }
    this.setVisible(false);
    this.dispose();
    java.lang.System.runFinalization();
  }
  
  
  /**
   * Nimmt zusaetzliche Initialisierungen von Objekten der GUI vor.
   * Wird vor dem ersten Anzeigen des Plugins aufgerufen.
   */
  private void guiPreparation() {
    try {
      imagePlus = imageWindow.getImagePlus();
      imageStack = imagePlus.getStack();
      maxImage = imageStack.getSize();
      acquisitionTime = new int[maxImage];
      hasPatientInfo = this.getPatientInfo();
      if (!hasPatientInfo || acquisitionTime[1] == 0) {
        String	title = " Warning: missing Series Information";
        String	msg = "This series either contains no patient information or is a secondary-capture !\n \nExport of analysis result will contain no patient or time informations !\n \nContinue anyway ?";
        boolean questionResult = IJ.showMessageWithCancel(title, msg);
        
        if (!questionResult)	// == JOptionPane.CANCEL_OPTION)
        {
          imagePlus.unlock();
          this.dispose();
          return;
        }
      }
      //oldStackWindow = (StackWindow) imagePlus.getWindow();
      stackWindow = new ExStackWindow(imagePlus);
      imageCanvas = (ExImageCanvas) stackWindow.getCanvas();
      if (hasPatientInfo == true) {
        setPatientInfoText();
        String[]	acTimeText = new String[maxImage];
        
        for (int i = 0; i < maxImage; i++) {
          double	t = ((double) acquisitionTime[i]) / 1000.0;
          
          acTimeText[i] = ("acquisition time +" + (IJ.d2s(t, 2)) + " sec.");
        }
        imageCanvas.setAcquisitionTime(acTimeText);
      }
      imageCanvas.setParent(this);
      cepstrumResult = new int[2][maxImage];
      imagePlus.updateAndDraw();
    } catch (Exception e) {
      e.printStackTrace();
      IJ.write("Error in Window Init !" + e);
    }
  }
  
  
  /**
   * Nimmt zusaetzliche Initialisierungen von Objekten der GUI vor.
   * Wird vor dem ersten Anzeigen des Plugins aufgerufen.
   */
  private void guiInit() {
    
    // Action-Listener hinzufuegen...
    jButtonStartAnalysis.addActionListener(this);
    jButtonPresets.addActionListener(this);
    jButtonSegmentation.addActionListener(this);
    jButtonExit.addActionListener(this);
    jButtonRightRoi.addActionListener(this);
    jButtonLeftRoi.addActionListener(this);
    jButtonSIT.addActionListener(this);
    jButtonCancel.addActionListener(this);
    jButtonAbout.addActionListener(this);
    
    // Change-Listener hinzufuegen
    jSliderAccuracy.addChangeListener(this);
    
    // Window-Listener hinzufuegen
    this.addWindowListener(this);
    
    try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (Exception e) {
      System.err.println("Can't set GUI to look and feel: " + e);
    }
    
    this.setTitle(dialogTitle);
    this.pack();
    this.setBackground(Color.black);
    this.setForeground(Color.lightGray);
    this.setResizable(false);
    IJ.wait(150);
    
    // Das Fenster auf eine schoene Groesse bringen und zentrieren
    Rectangle rec = this.getBounds();
    Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize();
    
    this.setLocation(((screensize.width - rec.width) / 2), ((screensize.height - rec.height) / 2));
    this.setVisible(true);
    toggleCancelButton();
    analysisAccuracy = presetsDialog.cepstrumAccuracy;
    String	text = "-    Analysis accuracy: ";
    
    text = text + d2s(analysisAccuracy, 1);
    text = text + "    +";
    jLabelAccuracy.setText(text);
  }
  
  
  /**
   * Wird aufgerufen, wenn die Kepstrum-Filterung gestartet werden soll.
   * Nimmt Ueberpruefungen der arretierten ROIs vor, bevor die Filterung gestartet wird.
   */
  private void startCepstrum() {
    
    // if (seriesLoaded)
    {
      if (leftRoiLocked || rightRoiLocked) {
        cepstrumAnalysis = new CepstrumAnalysis(this, rightRoi, leftRoi);
        
        // uebergabe dieser Parameter nur fuer die Statistik (logFile) !
        cepstrumAnalysis.seriesDate = seriesDate;
        cepstrumAnalysis.studyDate = studyDate;
        cepstrumAnalysis.patientName = patientName;
        cepstrumAnalysis.patientBirth = patientBirth;
        cepstrumAnalysis.patientWeight = d2s((double) patientWeight, 1);
        
        // ----
        cepstrumAnalysis.setAccuracy(analysisAccuracy);
        setStatusText(" Movement Correction...      (Press CANCEL to stop)");
        toggleCancelButton();
        this.enableButtons(false);
        cepstrumAnalysis.setPriority(threadPriority);
        cepstrumAnalysis.setVerbose(verboseResults);
        cepstrumAnalysis.setSecondChance(secondChance);
        
        if (enableMinDiff) {
          cepstrumAnalysis.setMinDiff(switchToMinDiff);
        } else {
          cepstrumAnalysis.setMinDiff(1000);
        }
        
        stackWindow.showSlice(1);
        imagePlus.updateAndDraw();
        stackWindow.lock();
        cepstrumAnalysis.start();
        
        // toggleCancelButton();
        // while (!ca.finished) {}
      } else {
        JOptionPane.showMessageDialog(null, "No ROI locked !\nPlease lock at least one ROI.", " No ROI locked", JOptionPane.ERROR_MESSAGE);
        setStatusText(" Ready");	// Please lock at least one ROI.   Select ROIs close to both kidneys.");
      }
    }
    
    // if (leftRoiLocked) toggleLeftRoi(null);
    // if (rightRoiLocked) toggleRightRoi(null);
  }
  
  
  /**
   * Startet die Berechnung der SIT-Kurven.
   * Nimmt Ueberpruefungen der arretierten ROIs vor, bevor die Berechnung gestartet wird.
   */
  private void startSIT() {
    sitAnalysis = new SITAnalysis(this);	// , imagePlus, acquisitionTime, leftRoi,rightRoi);
    
    setStatusText(" calculating Signal-Intensity-Time-Curves...    (Press CANCEL to stop)");
    toggleCancelButton();
    this.enableButtons(false);
    sitAnalysis.setPriority(java.lang.Thread.MAX_PRIORITY);
    if (sitAnalysis.noRois[0] && sitAnalysis.noRois[1]) {
      JOptionPane.showMessageDialog(null, "No ROI locked !\nPlease lock at least one ROI.", " No ROI locked", JOptionPane.ERROR_MESSAGE);
      setStatusText("Ready");		// Please lock at least one ROI.   Select ROIs close to both kidneys.");
      
      // toggleCancelButton();
      // this.enableButtons(false);
      this.sitFinished();
    } else {
      sitAnalysis.setAdjustmentRange(1.0 - classificationRange, 1.0 + classificationRange);
      sitAnalysis.setVerbose(verboseSIT);
      sitAnalysis.start();
    }
    
    // if (leftRoiLocked) toggleLeftRoi(null);
    // if (rightRoiLocked) toggleRightRoi(null);
  }
  
  
  /**
   * Startet die automatische Detektion der Organkontur.
   * Nimmt Ueberpruefungen der arretierten ROI vor, bevor die Berechnung gestartet wird.
   */
  private void startSegmentation() {
    Roi roi = imagePlus.getRoi();
    
    if (roi == null) {
      JOptionPane.showMessageDialog(null, "No active ROI !\nPlease mark a rectangle ROI around one kidney.", " No active ROI", JOptionPane.ERROR_MESSAGE);
      return;
    }
    if (roi.getType() != Roi.RECTANGLE) {
      JOptionPane.showMessageDialog(null, "Wrong type of ROI !\nPlease mark a RECTANGLE ROI around one kidney.", " Wrong ROI type", JOptionPane.ERROR_MESSAGE);
      return;
    }
    KidneyExtraction	kidneyExtraction = new KidneyExtraction(imagePlus);		// , imagePlus, acquisitionTime, leftRoi,rightRoi);
    
    setStatusText(" Segmentation of kidney contour...    (Press CANCEL to stop)");
    
    // toggleCancelButton();
    this.enableButtons(false);
    this.repaint();
    this.validate();
    IJ.wait(100);
    try {
      kidneyExtraction.doSegmentation(imagePlus.getProcessor());
    } catch (Exception e) {
      e.printStackTrace();
      JOptionPane.showMessageDialog(null, "Error in kidney Segmentation!", " Error", JOptionPane.ERROR_MESSAGE);
    }
    
    // toggleCancelButton();
    kidneyExtraction = null;
    this.enableButtons(true);
    setStatusText("Ready.");
    this.repaint();
  }
  
  
  /**
   * Fuellt den Textbereich des Plugin-Fensters mit Informationen zur importierten Sequenz.
   * Voraussetzung ist, dass die Properties beim Import der Sequenz mit importiert wurden.
   */
  private void setPatientInfoText() {
    int			w = jTextAreaPatienInfo.getColumns();
    int			lineCounter = 0;
    String	text = "Name:   " + patientName + "\n";
    
    lineCounter++;
    text = text + "Sex:    " + patientSex + "\n";
    lineCounter++;
    text = text + "Birth:  " + patientBirth + "\n";
    lineCounter++;
    text = text + "Age:    " + patientAge + "\n";
    lineCounter++;
    text = text + "Weight: " + patientWeight + "\n";
    lineCounter++;
    text = text + "-------------\n";
    lineCounter++;
    text = text + "Study Date:  " + studyDate + "\n";
    lineCounter++;
    text = text + "Series Date: " + seriesDate + "\n";
    lineCounter++;
    text = text + "TR Time:     " + d2s(timeTR, 3) + "\n";
    lineCounter++;
    text = text + "TE Time:     " + d2s(timeTE, 3) + "\n";
    lineCounter++;
    text = text + "PixSpacingX: " + d2s(pixelSpacingX, 6) + "\n";
    lineCounter++;
    text = text + "PixSpacingY: " + d2s(pixelSpacingY, 6) + "\n";
    lineCounter++;
    text = text + "Matrix:      " + matrixX + " x " + matrixY + "\n";
    lineCounter++;
    text = text + "FOV (mm):    " + fovX + " x " + fovY + "\n";
    lineCounter++;
    text = text + "-------------\n";
    lineCounter++;
    text = text + institutionName;
    lineCounter++;
    jTextAreaPatienInfo.setText(text);
    if (("Name:   " + patientName).length() > w) {
      w = ("Name:   " + patientName).length();
    }
    if (institutionName.length() > w) {
      w = institutionName.length();
    }
    jTextAreaPatienInfo.setColumns(w);
    jTextAreaPatienInfo.setRows(lineCounter);
    jTextAreaPatienInfo.revalidate();
    jTextAreaPatienInfo.repaint();
  }
  
  
  /**
   * Liest den Properties-String der importierten Dicom-Sequenz und extrahiert
   * Patienteninformationen daraus. Diese werden in Klassevariablen gespeichert.
   * @return boolean true, wenn die Patienteninformationen extrahiert werden konnten.
   */
  private boolean getPatientInfo() {
    propertiesOk = false;
    
    Properties	prop = null;
    String[]		sl = null;
    int					index = -1;
    String			temp = "";
    int					i;
    
    prop = imagePlus.getProperties();
    
    if (prop != null) {
      if (prop.containsKey(DcmUID.DCM_STRING_HEADER_PROPERTY)) {
        sl = (String[]) prop.get(DcmUID.DCM_STRING_HEADER_PROPERTY);
      }
    }
    
    // Alte Version:
    // if (prop != null) {
    // sl = (String[]) prop.get(DcmUtil.DICOM_HEADER_INFO_PROPERTY);
    // }
    
    if (sl != null) {							// besser:
      try {
        
        // IJ.write("Prop[0]: " + sl[0]);
        index = sl[0].indexOf("[0x0010, 0x0010, 0x0000000c");
        if (index > 0) {
          temp = sl[0].substring(index + 35);
          index = temp.indexOf("\n");
          patientName = temp.substring(0, index);
        }
        
        index = sl[0].indexOf("[0x0010, 0x0020, 0x0000000c");
        if (index > 0) {
          temp = sl[0].substring(index + 35);
          index = temp.indexOf("\n");
          patientID = temp.substring(0, index);
        }
        
        index = sl[0].indexOf("[0x0008, 0x0080, 0x00000010");
        if (index > 0) {
          temp = sl[0].substring(index + 35);
          index = temp.indexOf("\n");
          institutionName = temp.substring(0, index);
        }
        
        index = sl[0].indexOf("[0x0010, 0x0040, 0x00000002");
        if (index > 0) {
          temp = sl[0].substring(index + 35);
          index = temp.indexOf("\n");
          patientSex = temp.substring(0, index);
        }
        
        index = sl[0].indexOf("[0x0010, 0x1030, 0x00000006");
        if (index > 0) {
          temp = sl[0].substring(index + 35);
          index = temp.indexOf("\n");
          String	weight = temp.substring(0, index);	// Short.valueOf( temp.substring(0,index) ).shortValue();
          
          patientWeight = s2i(weight);	// temp.substring(0,index);//Short.valueOf( temp.substring(0,index) ).shortValue();
        }
        
        index = sl[0].indexOf("[0x0008, 0x0020, 0x00000008");
        if (index > 0) {
          temp = sl[0].substring(index + 35);
          index = temp.indexOf("\n");
          studyDate = temp.substring(0, index);
          if (studyDate.length() == 8) {
            studyDate = studyDate.substring(6) + "." + studyDate.substring(4, 6) + "." + studyDate.substring(0, 4);
          }
        }
        
        index = sl[0].indexOf("[0x0008, 0x0021, 0x00000008");
        if (index > 0) {
          temp = sl[0].substring(index + 35);
          index = temp.indexOf("\n");
          seriesDate = temp.substring(0, index);
          if (seriesDate.length() == 8) {
            seriesDate = seriesDate.substring(6) + "." + seriesDate.substring(4, 6) + "." + seriesDate.substring(0, 4);
          }
        }
        
        index = sl[0].indexOf("[0x0010, 0x0030, 0x00000008");
        if (index > 0) {
          temp = sl[0].substring(index + 35);
          index = temp.indexOf("\n");
          patientBirth = temp.substring(0, index);
          if (patientBirth.length() == 8) {
            patientBirth = patientBirth.substring(6) + "." + patientBirth.substring(4, 6) + "." + patientBirth.substring(0, 4);
          }
        }
        
        index = sl[0].indexOf("[0x0010, 0x1010, 0x00000004");
        if (index > 0) {
          temp = sl[0].substring(index + 35);
          index = temp.indexOf("\n");
          String	age = temp.substring(0, index);
          
          patientAge = s2i(age);	// temp.substring(0,index);
        }
        
        index = sl[0].indexOf("[0x0018, 0x0080, 0x0000000e");
        if (index > 0) {
          temp = sl[0].substring(index + 35);
          index = temp.indexOf("\n");
          String	tr = temp.substring(0, index);
          
          timeTR = Double.valueOf(tr).doubleValue();	// temp.substring(0,index);
        }
        
        index = sl[0].indexOf("[0x0018, 0x0081, 0x0000000e");
        if (index > 0) {
          temp = sl[0].substring(index + 35);
          index = temp.indexOf("\n");
          String	te = temp.substring(0, index);
          
          timeTE = Double.valueOf(te).doubleValue();	// temp.substring(0,index);
        }
        
        index = sl[0].indexOf("[0x0028, 0x0030, 0x0000001c");
        if (index > 0) {
          try {
            temp = sl[0].substring(index + 35);
            index = temp.indexOf("\n");
            String	s = temp.substring(0, index);
            
            index = s.indexOf('\\');
            String	x = s.substring(0, index);
            String	y = s.substring(index + 1);
            
            pixelSpacingX = Double.valueOf(x).doubleValue();
            
            // IJ.write("Pixel Spacing:" + x);
            pixelSpacingY = Double.valueOf(y).doubleValue();
            matrixX = imagePlus.getWidth();
            matrixY = imagePlus.getHeight();
            fovX = (int) ((double) matrixX * pixelSpacingX);
            fovY = (int) ((double) matrixY * pixelSpacingY);
            
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
        
        for (i = 0; i < maxImage; i++) {
          index = sl[i].indexOf("[0x0008, 0x0032, 0x0000000e");
          if (index > 0) {
            temp = sl[i].substring(index + 35);
            index = temp.indexOf("\n");
            String	ImageTime = temp.substring(0, index);
            
            index = ImageTime.indexOf(".");
            String	hours = ImageTime.substring(0, 2);
            String	minutes = ImageTime.substring(2, 4);
            String	seconds = ImageTime.substring(4, 6);
            String	milliseconds = ImageTime.substring(7, 10);
            
            // milliseconds.replace('0',' ');
            acquisitionTime[i] = ((Integer.valueOf(hours)).intValue()) * 60 * 60 * 1000;
            acquisitionTime[i] = acquisitionTime[i] + ((Integer.valueOf(minutes)).intValue()) * 60 * 1000;
            acquisitionTime[i] = acquisitionTime[i] + ((Integer.valueOf(seconds)).intValue()) * 1000;
            acquisitionTime[i] = acquisitionTime[i] + (Integer.valueOf(milliseconds)).intValue();
            
            // IJ.write("ImageTime (" + i + "): " + ImageTime);
            // IJ.write("!!!" + hours + "!" + minutes + "!" + seconds + "!" + milliseconds);
            // IJ.write(">>>" + acquisitionTime[i]);
          }
        }
        
        for (i = maxImage - 1; i > 0; i--) {
          acquisitionTime[i] = acquisitionTime[i] - acquisitionTime[0];
          
          // IJ.write(">>>" + acquisitionTime[i]);
          // if (acquisitionTime[i] == 0) timeIsNull = true;
        }
        acquisitionTime[0] = 0;
        
      } catch (Exception e) {
        IJ.error("Error while reading patient info!\nExport of analysis results\nwill not be possible.");
        e.printStackTrace();
        return false;
      }
      
      propertiesOk = true;
      return true;
    } else {
      return false;
    }
  }
  
  
  /**
   * Hilfsfunktion. Wandelt einen Double in einen String um. Erweitert die ImageJ-d2s-Methode
   * um einige zusaetzliche Sicherheitsabfragen.
   * @param d der Double-Wert
   * @param l die Anzahl der Nachkommastellen
   * @return String der generierte String
   */
  private String d2s(double d, int l) {
    String	result = IJ.d2s(d, l);
    
    result = result.replace(',', '.');
    while ((result.length() > 1) && (result.charAt(0) == '0') && (result.charAt(1) != '.')) {
      result = result.substring(1);
    }
    return result;
  }
  
  
  /**
   * Hilfsfunktion. Wandelt einen String in einen Integer um. Funktioniert nur im
   * positiven Wertebereich.
   * Erweitert die standard-java-Methode um einige zusaetzliche Sicherheitsabfragen.
   * Alle nicht-numerischen Zeichen innerhalb des Stings werden irgnoriert
   * @param input der String.
   * @return int der berechnete Integer. -1, wenn der Sting nicht umgewandelt werden konnte.
   */
  private int s2i(String input) {
    int			i;
    int			result = -1;
    String	filter = "";
    
    for (i = 0; i < input.length(); i++) {
      if (Character.isDigit(input.charAt(i))) {
        filter = filter + input.charAt(i);
      }
    }
    while ((filter.length() > 0) && (filter.charAt(0) == '0')) {
      filter = filter.substring(1);
    }
    IJ.wait(5);
    if (filter.length() == 0) {
      return 0;
    }
    result = (Integer.valueOf(filter)).intValue();
    return result;
  }
  
  
  /**
   * Schreibt einen uebergebenen Sting in die Statuszeile des Dialogfensters.
   * @param status der uebergebene String.
   */
  private void setStatusText(String status) {
    jLabelStatusBar.setText(" " + status);
  }
  
  
  /**
   * Kippt den Zustand der CANCEL-Schaltflaeche. Wenn der Button zuvor aktiv war, wird er
   * ausgeblendet, ansonsten eingeblendet.
   * Sollte die Schalftlaeche eingeblendet werden, so werden gleichzeit alle uebrigen#
   * Schaltflaechen des Dialogfensters deaktiviert.
   */
  private void toggleCancelButton() {
    if (jButtonCancel.isEnabled()) {
      
      // originalCancelSize = jButtonCancel.getBounds();
      jButtonCancel.setEnabled(false);
      
      jButtonCancel.setOpaque(false);
      jButtonCancel.setForeground(Color.black);
      jButtonCancel.setBackground(Color.black);
      jButtonCancel.repaint();
      
      // jFrameMain.invalidate();
      
    } else {
      jButtonCancel.setEnabled(true);
      
      // jButtonCancel.show();
      jButtonCancel.setOpaque(true);
      jButtonCancel.setForeground(Color.orange);
      jButtonCancel.setBackground(Color.gray);
      jButtonCancel.repaint();
      
      // jFrameMain.invalidate();
    }
    IJ.wait(100);
  }
  
  
  /**
   * Wird von der Kepstrum-Berechnungsklasse aufgerufen, wenn die Filterung abgeschlossen ist.
   */
  public void cepstrumFinished() {
    setStatusText(" Ready");
    if (cepstrumAnalysis != null && cepstrumAnalysis.finished == false && cepstrumAnalysis.error == false) {
      JOptionPane.showMessageDialog(null, "Movement Correction aborded !\nWarning: User Break.", " User Break", JOptionPane.WARNING_MESSAGE);
      cepstrumSuccess = false;
    } else if (cepstrumAnalysis != null && cepstrumAnalysis.finished == false && cepstrumAnalysis.error == true) {
      JOptionPane.showMessageDialog(null, "Error in Movement Correction !\nWarning: Abnormal Termination.", " Error", JOptionPane.ERROR_MESSAGE);
      cepstrumSuccess = false;
    } else {
      int					badImageCounter = 0;
      String			ListLeft = "";
      String			ListRight = "";
      String			msg = "\nNo Errors.";
      boolean[][] results = imageCanvas.getEnabledForSIT();
      
      for (int i = startImage - 1; i < maxImage; i++) {
        if (results[0][i] == false) {
          ListLeft = ListLeft + (i + 1) + ", ";
          badImageCounter++;
        }
        if (results[1][i] == false) {
          ListRight = ListRight + (i + 1) + ", ";
          badImageCounter++;
        }
      }
      if (badImageCounter > 0) {
        msg = "\nPossible Errors:";
      }
      if (ListLeft.length() > 0) {
        ListLeft = ListLeft.substring(0, ListLeft.lastIndexOf(", "));
        msg = msg + "\nRight Kidney - images " + ListLeft;
      }
      if (ListRight.length() > 0) {
        ListRight = ListRight.substring(0, ListRight.lastIndexOf(", "));
        msg = msg + "\nLeft Kidney - images " + ListRight;
      }
      
      JOptionPane.showMessageDialog(null, "Movement Correction Finished !" + msg, " Information", JOptionPane.INFORMATION_MESSAGE);
      cepstrumSuccess = true;
    }
    stackWindow.unlock();
    toggleCancelButton();
    enableButtons(true);
    
    // if (leftRoiLocked) toggleLeftRoi(null);
    // if (rightRoiLocked) toggleRightRoi(null);
    cepstrumAnalysis = null;
  }
  
  
  /**
   * Wird von der SIT-Berechnungsklasse aufgerufen, wenn die Berechnung der
   * Signal-Intensitaets-Zeit-Kurven abgeschlossen ist.
   */
  public void sitFinished() {
    setStatusText(" Ready");
    if (sitAnalysis != null && sitAnalysis.finished == false && sitAnalysis.error == false) {
      JOptionPane.showMessageDialog(null, "Calculation of SIT-Graphs aborded !\nWarning: User Break.", " User Break", JOptionPane.WARNING_MESSAGE);
    } else if (sitAnalysis != null && sitAnalysis.finished == false && sitAnalysis.error == true) {
      JOptionPane.showMessageDialog(null, "Error in calculation of SIT-Graphs !\nWarning: Abnormal Termination.", " Error", JOptionPane.ERROR_MESSAGE);
    }
    this.toggleCancelButton();
    
    // this.setStatusText(status);
    this.enableButtons(true);
    
    // if (leftRoiLocked) toggleLeftRoi(null);
    // if (rightRoiLocked) toggleRightRoi(null);
    sitAnalysis = null;
  }
  
  
  /**
   * Wird aufgerufen, wenn das Presets-Fenster durch Klick auf die Cancel- oder OK-Schaltflaeche
   * geschlossen wird. Die veraenderten Voreinstellungen werden dann aus den Variabel der Klasse des
   * Voreinstellungs-Dialoges uebernommen
   */
  public void presetsDialogClosed() {
    transferPresetValues();
  }
  
  
  /**
   * Setzt das Ergebnis der Kepstrum-Filterung in einer Bildhaelfte des BIldstapelfensters.
   * Benutzt eine Referenz auf den ExImageCanvas, um die Werte direkt zu schreiben.
   * @param half die Bildhaelfte (0=links, 1=rechts)
   * @param slice die Bildnummer innerhalb der Nierensequenz
   * @param result das zu setzende Ergebnis des Kepstrums (Skala 1-5)
   */
  public void setCepstrumResult(int half, int slice, int result) {
    cepstrumResult[half][slice - 1] = result;
    if (result == 1) {
      imageCanvas.setCepstrumResult(half, slice, "++");
    }
    if (result == 2) {
      imageCanvas.setCepstrumResult(half, slice, "+");
    }
    if (result == 3) {
      imageCanvas.setCepstrumResult(half, slice, "o");
    }
    if (result == 4) {
      imageCanvas.setCepstrumResult(half, slice, "-");
    }
    if (result == 5) {
      imageCanvas.setCepstrumResult(half, slice, "--");
    }
    if (result == 0) {
      imageCanvas.setCepstrumResult(half, slice, "**");
    }
  }
  
  
  /**
   * Hilfsklasse, die die Schaltflaechen des Dialog-Hauptfensters Setzt das Ergebnis der Kepstrum-Filterung in einer Bildhaelfte des BIldstapelfensters.
   * Benutzt eine Referenz auf den ExImageCanvas, um die Werte direkt zu schreiben.
   * @param half die Bildhaelfte (0=links, 1=rechts)
   * @param slice die Bildnummer innerhalb der Nierensequenz
   * @param result das zu setzende Ergebnis des Kepstrums (Skala 1-5)
   */
  private void enableButtons(boolean active) {
    jButtonStartAnalysis.setEnabled(active);
    jButtonPresets.setEnabled(active);
    jButtonSegmentation.setEnabled(active);
    jButtonExit.setEnabled(active);
    jButtonRightRoi.setEnabled(active);
    jButtonLeftRoi.setEnabled(active);
    jButtonSIT.setEnabled(active);
    jButtonAbout.setEnabled(active);
    jSliderAccuracy.setEnabled(active);
    
    // jLabelAccuracy.setEnabled(active);
    this.repaint();
  }
  
  
  /**
   * Hilfsklasse. Faengt Window-Events ab. Wird zum korrekten Schliessen des
   * des Dialogfensters benoetigt.
   * @param evt WindowsEvent, durch Veraenderungen des Fensters ausgeloest.
   */
  public void windowDeactivated(WindowEvent evt) {}
  
  
  /**
   * Hilfsklasse. Faengt Window-Events ab. Wird zum korrekten Schliessen des
   * des Dialogfensters benoetigt.
   * @param evt WindowsEvent, durch Veraenderungen des Fensters ausgeloest.
   */
  public void windowActivated(WindowEvent evt) {}
  
  
  /**
   * Hilfsklasse. Faengt Window-Events ab. Wird zum korrekten Schliessen des
   * des Dialogfensters benoetigt.
   * @param evt WindowsEvent, durch Veraenderungen des Fensters ausgeloest.
   */
  public void windowDeiconified(WindowEvent evt) {}
  
  
  /**
   * Hilfsklasse. Faengt Window-Events ab. Wird zum korrekten Schliessen des
   * des Dialogfensters benoetigt.
   * @param evt WindowsEvent, durch Veraenderungen des Fensters ausgeloest.
   */
  public void windowIconified(WindowEvent evt) {}
  
  
  /**
   * Hilfsklasse. Faengt Window-Events ab. Wird zum korrekten Schliessen des
   * des Dialogfensters benoetigt.
   * @param evt WindowsEvent, durch Veraenderungen des Fensters ausgeloest.
   */
  public void windowOpened(WindowEvent evt) {}
  
  
  /**
   * Hilfsklasse. Faengt Window-Events ab. Wird zum korrekten Schliessen des
   * des Dialogfensters benoetigt.
   * @param evt WindowsEvent, durch Veraenderungen des Fensters ausgeloest.
   */
  public void windowClosed(WindowEvent evt) {}
  
  
  /**
   * Hilfsklasse. Faengt Window-Events ab. Wird zum korrekten Schliessen des
   * des Dialogfensters benoetigt.
   * @param evt WindowsEvent, durch Veraenderungen des Fensters ausgeloest.
   */
  public void windowClosing(WindowEvent evt) {
    exitPlugin();
  }
  
}


/*--- formatting done in "My Own Convention" style on 08-04-2000 ---*/

