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

/*
 * The package jm.extension 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.extension;

import jm.kidney.*;
import jm.util.*;

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

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

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


/**
 * Diese Klasse erweitert den ImageCanvas von ImageJ.
 * <BR> Zur Darstellung der Nierenserien werden verschiedene zusaetzliche Anzeigen
 * benoetigt: Aufnahmezeitpunkt, Ergebnis der Verschiebungkorrektur, sowie 4
 * zusaetzliche Buttons und 1 zusaetzlicher CheckButton pro Bildhaelfte.
 * @see     jm.extension.AwtToolTip
 * @see     jm.extension.AwtToolTipHelper
 * @see     jm.extension.AddRoiDialog
 * @version 3.1, 14/02/2000
 * @author  Jens Martin
 */
public class ExImageCanvas extends ImageCanvas implements ComponentListener, KeyListener {
	private Roi[]							leftRoi = null;
	private Roi[]							rightRoi = null;
	private Roi[][]						leftRoiCortex = null;
	private Roi[][]						rightRoiCortex = null;
	private Roi[][]						leftRoiMedulla = null;
	private Roi[][]						rightRoiMedulla = null;
	private Roi								dummy = null;
	private Roi								actualSelection = null;
	private Roi								storedRoi = null;
	private Color							darkgreen = new Color(0, 180, 0);
	private Color							darkred = new Color(136, 0, 0);
	private Color[][]					buttonBorderColor;
	private Color							myYellow = new Color(243, 239, 118);

	// private Color myWhite = new Color(253,246,213);
	private Color							myWhite = Color.white;
	private Color							myRed = new Color(227, 75, 75);
	private Color							myOrange = new Color(251, 196, 77);

	// private Point cepstrumPosition = new Point(1,7);
	// private Point timePosition = new Point(23,1);
	private Point							buttonPos = new Point(30, 0);
	private static final int	buttonWidth = 18;
	private static final int	buttonHeight = 10;

	private ImagePlus					imagePlus = null;
	private ImageStack				imageStack = null;
	private String[]					acquisitionTime = null;
	private String[][]				cepstrumEvaluation = null;
	private boolean[][]				manualSelector = null;
	private boolean						storeNextCanvasSize = false;

	private boolean						altKeyDown = false;
	private boolean						delKeyDown = false;

	private int								maxImage;
	private int								slice;
	private int								width, height;
	private int								xMouse, yMouse;
	private Color							textColor;
	private int								widthDiv2;

	private AnalysisDialog		analysisDialog = null;

	public static final int		MAXROIS = 100;

	private static final int	CANCEL = 0;
	private static final int	ALL = 1;
	private static final int	CURRENT = 2;

	private static final int	BUTTON1LEFT = 1;
	private static final int	BUTTON2LEFT = 2;
	private static final int	BUTTON3LEFT = 3;

	private static final int	BUTTON1RIGHT = 4;
	private static final int	BUTTON2RIGHT = 5;
	private static final int	BUTTON3RIGHT = 6;

	private static final int	SELECTORLEFT = 7;
	private static final int	SELECTORRIGHT = 8;

	private static final int	MOVELEFT = 9;
	private static final int	MOVERIGHT = 10;

	private Rectangle					rect = null;

	private Rectangle					repaintRect = new Rectangle(0, 0, 1, 1);
	private Rectangle					lastRect = new Rectangle(0, 0, 1, 1);

	private boolean						repaintDone = true;

	private Font							font = new Font("Dialog", 0, 10);

	private boolean						dontAskAgain = false;

	private JLabel						toolTipLabel = new JLabel("lock right main roi");

	public AwtToolTip					awtToolTip = new AwtToolTip();
	private AwtToolTipHelper	awtToolTipHelper = new AwtToolTipHelper();

        private Cursor                  defaultCursor = new Cursor(java.awt.Cursor.DEFAULT_CURSOR);
	// private javax.swing.JToolTip tt = null;//new JToolTip();  // Ein Swing-Tooltip erzeugen


	/**
	 * Der Konstruktor.
	 * @param    imp    ImagePlus-Objekt von ImageJ
	 */
	public ExImageCanvas(ImagePlus imp) {
		super(imp);

		// dummy = new Roi(0,0,1,1,imp);
		imagePlus = imp;
		imageStack = imp.getStack();
		maxImage = imageStack.getSize();

		this.addMouseMotionListener(awtToolTip);
		this.addMouseListener(awtToolTipHelper);
		awtToolTip.setSourceClass(this);

		this.addComponentListener(this);
		this.addKeyListener(this);

		width = imp.getWidth();
		height = imp.getHeight();
		widthDiv2 = width / 2;
		cepstrumEvaluation = new String[2][maxImage];
		manualSelector = new boolean[2][maxImage];
		leftRoi = new Roi[maxImage];
		rightRoi = new Roi[maxImage];

		leftRoiCortex = new Roi[maxImage][MAXROIS];
		rightRoiCortex = new Roi[maxImage][MAXROIS];
		leftRoiMedulla = new Roi[maxImage][MAXROIS];
		rightRoiMedulla = new Roi[maxImage][MAXROIS];

		for (slice = 0; slice < maxImage; slice++) {
			cepstrumEvaluation[JMConst.LEFT][slice] = "na";
			cepstrumEvaluation[JMConst.RIGHT][slice] = "na";
			manualSelector[JMConst.LEFT][slice] = false;
			manualSelector[JMConst.RIGHT][slice] = false;
			leftRoi[slice] = null;
			rightRoi[slice] = null;
		}

		buttonBorderColor = new Color[2][3];

		for (slice = 0; slice < 3; slice++) {
			buttonBorderColor[JMConst.LEFT][slice] = Color.darkGray;
			buttonBorderColor[JMConst.RIGHT][slice] = Color.darkGray;
		}
		JToolTip	toolTip = new JToolTip();		// Ein Swing-Tooltip erzeugen

		// JToolTip tt;// = null;
		awtToolTip.setDismissDelay(ToolTipManager.sharedInstance().getDismissDelay());
		awtToolTip.setInitialDelay(ToolTipManager.sharedInstance().getInitialDelay());

		// IJ.write ("holla1." + ToolTipManager.sharedInstance().getInitialDelay());//tt.get
		// IJ.write ("holla2." + ToolTipManager.sharedInstance().getDismissDelay());//tt.get
		toolTipLabel.setBackground(toolTip.getBackground());
		toolTipLabel.setForeground(toolTip.getForeground());

		toolTipLabel.setFont(new Font("Dialog", 0, 9));

	}


	/**
	 * Setzt den aktuell angezeigten Tooltip.
	 * @param    text String mit dem Tooltip-Text
	 */
	private void setToolTipText(String text) {
		toolTipLabel.setText(text);
	}


	/**
	 * Zulassen aller Halbbilder zur Berechnung der SIT-Kurven
	 * @param    half     Bildhaelfte (0 = links, 1 = rechts)
	 * @param    selected setzt oder loescht die Zulassung
	 */
	public void setManualSelector(int half, boolean selected) {
		for (slice = 0; slice < maxImage; slice++) {
			manualSelector[half][slice] = selected;
		}
	}


	/**
	 * Setzt das Vater-Objekt zur einfacheren
	 * Uebernahme von Paramerten und Enstellungen
	 * @see               jm.kidney.AnalysisDialog
	 * @param    dlg      AnalysisDialog
	 */
	public void setParent(AnalysisDialog dlg) {
		analysisDialog = dlg;
	}


	/**
	 * Setzt die Haupt-ROI fuer die ganze Niere fuer alle Halbbilder der Sequenz
	 * @param    half      Bildhaelfte (0 = links, 1 = rechts)
	 * @param    roi       Region of Interest
	 */
	public void setRoi(int half, Roi roi) {
		if (roi == null) {
			return;
		}
		int roiPos = roi.getBoundingRect().x + (roi.getBoundingRect().width / 2);

		if ((roiPos < imagePlus.getWidth() / 2) && (half == JMConst.RIGHT)) {
			return;
		}
		if ((roiPos >= imagePlus.getWidth() / 2) && (half == JMConst.LEFT)) {
			return;

		}
		Roi[] roiArray;

		if (half == JMConst.LEFT) {
			roiArray = leftRoi;
		} else {
			roiArray = rightRoi;
		}
		for (slice = 0; slice < maxImage; slice++) {
			Roi nr = (Roi) roi.clone();

			nr.setImage(imagePlus);
			roiArray[slice] = nr;
		}
		imagePlus.killRoi();
		repaint();
	}


	/**
	 * Setzt die Haupt-ROI fuer die ganze Niere fuer
	 * ein angegebenes Halbbild der Sequenz
	 * @param    slice     Nummer des Bildes
	 * @param    half      Bildhaelfte (0 = links, 1 = rechts)
	 * @param    roi       Region of Interest
	 */
	public void setRoi(int slice, int half, Roi roi) {
		if (roi == null) {
			return;
		}
		int roiPos = roi.getBoundingRect().x + (roi.getBoundingRect().width / 2);

		if ((roiPos < imagePlus.getWidth() / 2) && (half == JMConst.RIGHT)) {
			return;
		}
		if ((roiPos >= imagePlus.getWidth() / 2) && (half == JMConst.LEFT)) {
			return;

			// IJ.write("onesliceonly");

		}
		if (half == JMConst.LEFT) {
			leftRoi[slice] = roi;
		} else {
			rightRoi[slice] = roi;
		}
		imagePlus.killRoi();
		repaint();
	}


	/**
	 * Fuegt eine uebergenen ROI einem ROI-Array entsprechend des uebergebenen
	 * Gewebetyps zu. Gilt fuer ein angegebenes Halbbild der Sequenz.
	 * @param    slice     Nummer des Bildes
	 * @param    half      Bildhaelfte (0 = links, 1 = rechts)
	 * @param    tissue    Gewebetyp
	 * @param    roi       Region of Interest
	 */
	public void addToRoiArray(int slice, int half, int tissue, Roi roi) {
		if (roi == null) {
			return;
		}
		int roiPos = roi.getBoundingRect().x + (roi.getBoundingRect().width / 2);

		if ((roiPos < imagePlus.getWidth() / 2) && (half == JMConst.RIGHT)) {
			return;
		}
		if ((roiPos >= imagePlus.getWidth() / 2) && (half == JMConst.LEFT)) {
			return;

		}
		Roi[][] roiArray;

		if (half == JMConst.LEFT) {
			if (tissue == JMConst.MEDULLA) {
				roiArray = leftRoiMedulla;
			} else {
				roiArray = leftRoiCortex;
			}
		} else {
			if (tissue == JMConst.MEDULLA) {
				roiArray = rightRoiMedulla;
			} else {
				roiArray = rightRoiCortex;
			}
		}

		int			pos = 0;
		boolean success = false;

		while ((!success) && (pos < MAXROIS)) {
			if (roiArray[slice][pos] == null) {
				roiArray[slice][pos] = roi;
				success = true;
			}
			pos++;
		}
		if (success) {
			compressRoiArray(slice, roiArray);
			imagePlus.killRoi();
			repaint();
		}
	}


	/**
	 * Fuegt eine uebergenen ROI einem ROI-Array entsprechend des uebergebenen
	 * Gewebetyps zu. Gilt fuer alle Halbbild der Sequenz.
	 * @param    half      Bildhaelfte (0 = links, 1 = rechts)
	 * @param    tissue    Gewebetyp
	 * @param    roi       Region of Interest
	 */
	public void addToRoiArray(int half, int tissue, Roi roi) {
		if (roi == null) {
			return;
		}
		int roiPos = roi.getBoundingRect().x + (roi.getBoundingRect().width / 2);

		if ((roiPos < imagePlus.getWidth() / 2) && (half == JMConst.RIGHT)) {
			return;
		}
		if ((roiPos >= imagePlus.getWidth() / 2) && (half == JMConst.LEFT)) {
			return;
		}
		boolean atLeastOneRoiAdded = false;

		Roi[][] roiArray;

		if (half == JMConst.LEFT) {
			if (tissue == JMConst.MEDULLA) {
				roiArray = leftRoiMedulla;
			} else {
				roiArray = leftRoiCortex;
			}
		} else {
			if (tissue == JMConst.MEDULLA) {
				roiArray = rightRoiMedulla;
			} else {
				roiArray = rightRoiCortex;
			}
		}

		for (slice = 0; slice < maxImage; slice++) {
			int			pos = 0;
			boolean success = false;

			while ((!success) && (pos < MAXROIS)) {
				if (roiArray[slice][pos] == null) {
					roiArray[slice][pos] = roi;
					success = true;
				}
				pos++;
			}
			if (success) {
				atLeastOneRoiAdded = true;
				compressRoiArray(slice, roiArray);
			}
		}
		if (atLeastOneRoiAdded) {
			imagePlus.killRoi();
			repaint();
		}

	}


	/**
	 * Komprimiert das uebergebene ROI-Array nach dem Defragmentierungs-Prinzip.
	 * @param    slice     Nummer des Bildes
	 * @param    roiArray  Array von ROIs
	 */
	private void compressRoiArray(int slice, Roi[][] roiArray) {

		// if (!(slice >= 1 && slice <= maxImage)) return;
		int j;
		int i = 0;

		while (i < MAXROIS) {
			if (roiArray[slice][i] == null) {
				j = i + 1;
				while ((j < MAXROIS) && (roiArray[slice][j] == null)) {
					j++;
				}
				if (j < MAXROIS) {
					roiArray[slice][i] = roiArray[slice][j];
					roiArray[slice][j] = null;
				} else {
					i = MAXROIS;
				}
			}
			i++;
		}
	}


	/**
	 * Loescht alle ROIs des angegebenen Gewebetyps fuer alle Halbbilder der Sequenz.
	 * @param    half      Bildhaelfte (0 = links, 1 = rechts)
	 * @param    tissue    Typ des Gewebes
	 */
	public void deleteRois(int half, int tissue) {
		for (slice = 0; slice < maxImage; slice++) {
			if (tissue == JMConst.MAIN) {
				if (half == JMConst.LEFT) {
					leftRoi[slice] = null;
				}
				if (half == JMConst.RIGHT) {
					rightRoi[slice] = null;
				}
			}
			if (tissue == JMConst.MEDULLA) {
				for (int i = 0; i < MAXROIS; i++) {
					if (half == JMConst.LEFT) {
						leftRoiMedulla[slice][i] = null;
					}
					if (half == JMConst.RIGHT) {
						rightRoiMedulla[slice][i] = null;
					}
				}
			}
			if (tissue == JMConst.CORTEX) {
				for (int i = 0; i < MAXROIS; i++) {
					if (half == JMConst.LEFT) {
						leftRoiCortex[slice][i] = null;
					}
					if (half == JMConst.RIGHT) {
						rightRoiCortex[slice][i] = null;
					}
				}
			}
		}
		return;
	}


	/**
	 * Liefert ein Array mit den Haupt-ROIs fuer die angegebene Bildhaelfte zurueck.
	 * @param    half      Bildhaelfte (0 = links, 1 = rechts)
	 * @return   Roi       Array mit Roi-Objekten, eindimensional
	 */
	public Roi[] getRoi(int half) {
		Roi[] result = null;

		if (half == JMConst.LEFT) {
			result = leftRoi;
		}
		if (half == JMConst.RIGHT) {
			result = rightRoi;
		}
		return result;
	}


	/**
	 * Liefert ein Array mit den Gewebespezifischen
	 * ROIs fuer die angegebene Bildhaelfte zurueck.
	 * @param    half      Bildhaelfte (0 = links, 1 = rechts)
	 * @param    tissue    Gewebetyp
	 * @return   Roi       Array mit Roi-Objekten, zweidimensional
	 */
	public Roi[][] getRoi(int half, int tissue) {
		Roi[][] result = null;

		if (tissue == JMConst.MEDULLA) {
			if (half == JMConst.LEFT) {
				result = leftRoiMedulla;
			}
			if (half == JMConst.RIGHT) {
				result = rightRoiMedulla;
			}
		}
		if (tissue == JMConst.CORTEX) {
			if (half == JMConst.LEFT) {
				result = leftRoiCortex;
			}
			if (half == JMConst.RIGHT) {
				result = rightRoiCortex;
			}
		}
		return result;
	}


	/**
	 * Liefert ein Array von Booleans zurueck entsprechend der Zulassung
	 * der Bildhaeflten der ganzen Sequenz fuer die Berechnung der SIT-Kurven
	 * ROIs fuer die angegebene Bildhaelfte zurueck.
	 * @return   boolean       Array mit Zulassungswerten (Boolean), zweidimensional
	 */
	public boolean[][] getEnabledForSIT() {
		return manualSelector;
	}


	/**
	 * Setzt die angezeigten Aufnahmezeiten der Bilder.
	 * @param    data      String-Array mit den am unteren Bildrand angezeigten Zeit-Strings
	 */
	public void setAcquisitionTime(String[] data) {
		acquisitionTime = data;
	}


	/**
	 * Setzt die angezeigte Qualitaet (=Ergebnis) der Translationskorrektur
	 * @param    half      Bildhaelfte (0 = links, 1 = rechts)
	 * @param    slice     Nummer des Bildes
	 * @param    result    String entsprechend der Korrektur-Qualitaet
	 */
	public void setCepstrumResult(int half, int slice, String result) {
		if (half < 2 && half >= 0 && slice <= maxImage && slice > 0 && result != null) {
			cepstrumEvaluation[half][slice - 1] = result;
			if (result != "--")		// && result != "-")
			 {
				manualSelector[half][slice - 1] = true;
			}
			manualSelector[JMConst.LEFT][analysisDialog.startImage - 1] = true;
			manualSelector[JMConst.RIGHT][analysisDialog.startImage - 1] = true;
		}
	}


	/**
	 * Setzt die Farbe des Informationstextes auf dem Canvas
	 * @param    c    Farbe
	 */
	public void setTextColor(Color c) {
		if (c != null) {
			textColor = c;
		}
	}


	/**
	 * Ueberschreibung der Paint-Methode von ImageCanvas. Realisiert die erweiterte
	 * Informationsdarstellung auf dem Canvas sowie die zusaetzlichen Buttons.
	 * @param g Graphics-Objekt
	 */
	public void paint(Graphics g) {
		super.paint(g);

		// IJ.write("pw:"+imp.pixelWidth);
		// height = (int)((double)imp.getHeight() * this.getMagnification());
		// width = (int)((double)imp.getWidth() * this.getMagnification());
		// g.getClipBounds()
		if (storeNextCanvasSize) {
			width = g.getClipBounds().width;
			height = g.getClipBounds().height;
			widthDiv2 = width / 2;

			// IJ.write("pw:"+width + " ph:" + height);
			storeNextCanvasSize = false;
		}

		// g.setColor(Color.white);
		g.setColor(myWhite);
		g.setFont(font);
		slice = imp.getCurrentSlice() - 1;
		if (acquisitionTime != null) {
			if (acquisitionTime[slice] != null) {
				g.drawString(acquisitionTime[slice], 1, height - 2);
			}
		}
		g.drawString(cepstrumEvaluation[0][slice], 1, 7);
		g.drawString(cepstrumEvaluation[1][slice], (widthDiv2) + 1, 7);

		if (leftRoi != null) {
			if (leftRoi[slice] != null) {
				leftRoi[slice].setColor(darkgreen);
				leftRoi[slice].draw(g);
			}
		}

		if (rightRoi != null) {
			if (rightRoi[slice] != null) {
				rightRoi[slice].setColor(darkgreen);
				rightRoi[slice].draw(g);
			}
		}

		if (leftRoiCortex != null) {
			if (leftRoiCortex[slice] != null) {
				int pos = 0;

				while (pos < MAXROIS && leftRoiCortex[slice][pos] != null) {
					leftRoiCortex[slice][pos].setColor(myYellow);
					leftRoiCortex[slice][pos].draw(g);
					pos++;
				}
			}
		}

		if (leftRoiMedulla != null) {
			if (leftRoiMedulla[slice] != null) {
				int pos = 0;

				while (pos < MAXROIS && leftRoiMedulla[slice][pos] != null) {
					leftRoiMedulla[slice][pos].setColor(myRed);
					leftRoiMedulla[slice][pos].draw(g);
					pos++;
				}
			}
		}

		if (rightRoiCortex != null) {
			if (rightRoiCortex[slice] != null) {
				int pos = 0;

				while (pos < MAXROIS && rightRoiCortex[slice][pos] != null) {
					rightRoiCortex[slice][pos].setColor(myYellow);
					rightRoiCortex[slice][pos].draw(g);
					pos++;
				}
			}
		}

		if (rightRoiMedulla != null) {
			if (rightRoiMedulla[slice] != null) {
				int pos = 0;

				while (pos < MAXROIS && rightRoiMedulla[slice][pos] != null) {
					rightRoiMedulla[slice][pos].setColor(myRed);
					rightRoiMedulla[slice][pos].draw(g);
					pos++;
				}
			}
		}

		Roi roi = imp.getRoi();

		// Color c = roi.getColor();
		if (roi != null) {
			roi.setColor(myWhite);
			roi.draw(g);
		}

		g.setColor(darkgreen);

		// g.setColor(myOrange);
		g.fillRect(buttonPos.x + 1, buttonPos.y + 1, buttonWidth - 1, buttonHeight - 1);
		g.fillRect(widthDiv2 + buttonPos.x + 1, buttonPos.y + 1, buttonWidth - 1, buttonHeight - 1);
		g.setColor(myYellow);
		g.fillRect(buttonPos.x + (buttonWidth * 1) + (1 * 1) + 1, buttonPos.y + 1, buttonWidth - 1, buttonHeight - 1);
		g.fillRect(widthDiv2 + buttonPos.x + (buttonWidth * 1) + (1 * 1) + 1, buttonPos.y + 1, buttonWidth - 1, buttonHeight - 1);
		g.setColor(myRed);
		g.fillRect(buttonPos.x + (buttonWidth * 2) + (1 * 2) + 1, buttonPos.y + 1, buttonWidth - 1, buttonHeight - 1);
		g.fillRect(widthDiv2 + buttonPos.x + (buttonWidth * 2) + (1 * 2) + 1, buttonPos.y + 1, buttonWidth - 1, buttonHeight - 1);

		g.setColor(buttonBorderColor[JMConst.LEFT][0]);
		g.draw3DRect(buttonPos.x, buttonPos.y, buttonWidth, buttonHeight, true);
		g.setColor(buttonBorderColor[JMConst.RIGHT][0]);
		g.draw3DRect(widthDiv2 + buttonPos.x, buttonPos.y, buttonWidth, buttonHeight, true);
		g.setColor(buttonBorderColor[JMConst.LEFT][1]);
		g.draw3DRect(buttonPos.x + (buttonWidth * 1) + (1 * 1), buttonPos.y, buttonWidth, buttonHeight, true);
		g.setColor(buttonBorderColor[JMConst.RIGHT][1]);
		g.draw3DRect(widthDiv2 + buttonPos.x + (buttonWidth * 1) + (1 * 1), buttonPos.y, buttonWidth, buttonHeight, true);
		g.setColor(buttonBorderColor[JMConst.LEFT][2]);
		g.draw3DRect(buttonPos.x + (buttonWidth * 2) + (1 * 2), buttonPos.y, buttonWidth, buttonHeight, true);
		g.setColor(buttonBorderColor[JMConst.RIGHT][2]);
		g.draw3DRect(widthDiv2 + buttonPos.x + (buttonWidth * 2) + (1 * 2), buttonPos.y, buttonWidth, buttonHeight, true);

		g.setColor(myWhite);
		g.drawRect(16, 0, 9, 9);
		g.drawRect(widthDiv2 + 16, 0, 9, 9);
		if (manualSelector[JMConst.LEFT][slice] == true) {
			g.setColor(Color.green);
			g.drawLine(18, 5, 20, 7);
			g.drawLine(20, 7, 23, 2);
		} else {
			g.setColor(Color.red);
			g.drawLine(18, 2, 23, 7);
			g.drawLine(18, 7, 23, 2);
		}

		if (manualSelector[JMConst.RIGHT][slice] == true) {
			g.setColor(Color.green);
			g.drawLine(widthDiv2 + 18, 5, widthDiv2 + 20, 7);
			g.drawLine(widthDiv2 + 20, 7, widthDiv2 + 23, 2);
		} else {
			g.setColor(Color.red);
			g.drawLine(widthDiv2 + 18, 2, widthDiv2 + 23, 7);
			g.drawLine(widthDiv2 + 18, 7, widthDiv2 + 23, 2);
		}

		g.setColor(Color.white);
		int arrowButtonPos = buttonPos.x + (buttonWidth * 3) + (1 * 3) + 1;

		g.drawLine(arrowButtonPos, 5, arrowButtonPos + 8, 5);
		g.drawLine(arrowButtonPos + 4, 1, arrowButtonPos + 4, 9);
		g.drawLine(arrowButtonPos + 1, 4, arrowButtonPos + 1, 6);
		g.drawLine(arrowButtonPos + 7, 4, arrowButtonPos + 7, 6);
		g.drawLine(arrowButtonPos + 3, 2, arrowButtonPos + 5, 2);
		g.drawLine(arrowButtonPos + 3, 8, arrowButtonPos + 5, 8);
		arrowButtonPos = arrowButtonPos + widthDiv2;
		g.drawLine(arrowButtonPos, 5, arrowButtonPos + 8, 5);
		g.drawLine(arrowButtonPos + 4, 1, arrowButtonPos + 4, 9);
		g.drawLine(arrowButtonPos + 1, 4, arrowButtonPos + 1, 6);
		g.drawLine(arrowButtonPos + 7, 4, arrowButtonPos + 7, 6);
		g.drawLine(arrowButtonPos + 3, 2, arrowButtonPos + 5, 2);
		g.drawLine(arrowButtonPos + 3, 8, arrowButtonPos + 5, 8);


		if ((awtToolTip.showToolTip()) && (awtToolTipHelper.isMouseOver()) && (toolTipLabel.getText() != null) && (toolTipLabel.getText().length() != 0)) {

			String	s = toolTipLabel.getText();
			Font		f = toolTipLabel.getFont();

			g.setColor(toolTipLabel.getBackground());
			g.fillRect(xMouse, yMouse + 20, getFontMetrics(f).stringWidth(s) + 3, 12);
			g.setFont(f);
			g.setColor(toolTipLabel.getForeground());
			g.drawString(s, xMouse + 2, yMouse + 29);
		}
	}


	/**
	 * Faengt Mausklicks auf den Canvas ab.
	 * @param evt MouseEvent, durch Mausklick verursacht
	 */
	public void mousePressed(MouseEvent e) {

		// canvasButton.dispatchEvent(e);

		storedRoi = imagePlus.getRoi();

		// mouseButtonDown = true;
		int button = mouseOverButton(e.getX(), e.getY());

		if (button < 0) {
			super.mousePressed(e);

			// repaint();

		}
	}


	/**
	 * Faengt Mausklicks auf den Canvas ab.
	 * @param evt MouseEvent, durch Mausklick verursacht
	 */
	public void mouseReleased(MouseEvent e) {

		// canvasButton.dispatchEvent(e);

		// IJ.write("mouseReleased");
		// mouseButtonDown = false;
		int button = mouseOverButton(e.getX(), e.getY());

		if (button < 0) {
			super.mouseReleased(e);

			// repaint();
			// super.mouseReleased(e);

		}
	}


	/**
	 * Faengt Mausklicks auf den Canvas ab. In dieser Methode wird festgestellt,
	 * auf welche der Schaltflaechen geklickt wurde.
	 * @param evt MouseEvent, durch Mausklick verursacht
	 */
	public void mouseClicked(MouseEvent e) {

		// canvasButton.dispatchEvent(e);

		// IJ.write("mouseCLicked");
		// IJ.write("! " + e.getX() + "! " + e.getY() + "! " + ox + "! " + oy);
		int x = e.getX();
		int y = e.getY();

		// int key = IJ.getKeyDown();
		// if (key == KeyEvent.VK_ALT) IJ.write("AHA!! ALT");
		int result = 0;
		int button = mouseOverButton(x, y);

		if (button >= 0) {
			switch (button) {
			case BUTTON1LEFT:
				if (delKeyDown) {			// if (key == KeyEvent.VK_DELETE)
					analysisDialog.lockLeftRoi(storedRoi, false, false);	// deleteRois(JMConst.LEFT,MAIN);
				} else {
					if (altKeyDown) {		// if (key == KeyEvent.VK_ALT)
						analysisDialog.lockLeftRoi(storedRoi, true, true);	// setRoi(JMConst.LEFT,storedRoi);
					} else {
						result = showAddRoiMessage();
						if (result == this.ALL) {
							analysisDialog.lockLeftRoi(storedRoi, true, true);	// setRoi(JMConst.LEFT,storedRoi);

							// if ( (result < 0 || result != this.CANCEL) && (result != this.ALL) )
						}
						if (result < 0 || result == this.CURRENT) {
							setRoi(slice, JMConst.LEFT, storedRoi);
						}
					}

				}
				break;
			case BUTTON2LEFT:
				if (delKeyDown) {			// if (key == KeyEvent.VK_DELETE)
					deleteRois(JMConst.LEFT, JMConst.CORTEX);
				} else {
					if (altKeyDown) {		// if (key == KeyEvent.VK_ALT)
						addToRoiArray(JMConst.LEFT, JMConst.CORTEX, storedRoi);
					} else {
						result = showAddRoiMessage();
						if (result == this.ALL) {
							addToRoiArray(JMConst.LEFT, JMConst.CORTEX, storedRoi);
						}
						if ((result < 0 || result != this.CANCEL) && (result != this.ALL)) {
							addToRoiArray(slice, JMConst.LEFT, JMConst.CORTEX, storedRoi);
						}
					}
				}
				break;
			case BUTTON3LEFT:
				if (delKeyDown) {			// if (key == KeyEvent.VK_DELETE)
					deleteRois(JMConst.LEFT, JMConst.MEDULLA);
				} else {
					if (altKeyDown) {		// if (key == KeyEvent.VK_ALT)
						addToRoiArray(JMConst.LEFT, JMConst.MEDULLA, storedRoi);
					} else {
						result = showAddRoiMessage();
						if (result == this.ALL) {
							addToRoiArray(JMConst.LEFT, JMConst.MEDULLA, storedRoi);
						}
						if ((result < 0 || result != this.CANCEL) && (result != this.ALL)) {
							addToRoiArray(slice, JMConst.LEFT, JMConst.MEDULLA, storedRoi);
						}
					}
				}
				break;
			case BUTTON1RIGHT:
				if (delKeyDown) {			// if (key == KeyEvent.VK_DELETE)
					analysisDialog.lockRightRoi(storedRoi, false, false);		// deleteRois(JMConst.RIGHT,MAIN);
				} else {
					if (altKeyDown) {		// if (key == KeyEvent.VK_ALT)
						analysisDialog.lockRightRoi(storedRoi, true, true);		// setRoi(JMConst.RIGHT,storedRoi);
					} else {
						result = showAddRoiMessage();
						if (result == this.ALL) {
							analysisDialog.lockRightRoi(storedRoi, true, true);		// setRoi(JMConst.RIGHT,storedRoi);
						}
						if ((result < 0 || result != this.CANCEL) && (result != this.ALL)) {
							setRoi(slice, JMConst.RIGHT, storedRoi);
						}
					}
				}
				break;
			case BUTTON2RIGHT:
				if (delKeyDown) {			// if (key == KeyEvent.VK_DELETE)
					deleteRois(JMConst.RIGHT, JMConst.CORTEX);
				} else {

					// result = showAddRoiMessage();
					if (altKeyDown) {		// if (key == KeyEvent.VK_ALT)
						addToRoiArray(JMConst.RIGHT, JMConst.CORTEX, storedRoi);
					} else {
						result = showAddRoiMessage();
						if (result == this.ALL) {
							addToRoiArray(JMConst.RIGHT, JMConst.CORTEX, storedRoi);
						}
						if ((result < 0 || result != this.CANCEL) && (result != this.ALL)) {
							addToRoiArray(slice, JMConst.RIGHT, JMConst.CORTEX, storedRoi);
						}
					}
				}
				break;
			case BUTTON3RIGHT:
				if (delKeyDown) {			// if (key == KeyEvent.VK_DELETE)
					deleteRois(JMConst.RIGHT, JMConst.MEDULLA);
				} else {

					// result = showAddRoiMessage();
					if (altKeyDown) {		// if (key == KeyEvent.VK_ALT)
						addToRoiArray(JMConst.RIGHT, JMConst.MEDULLA, storedRoi);
					} else {
						result = showAddRoiMessage();
						if (result == this.ALL) {
							addToRoiArray(JMConst.RIGHT, JMConst.MEDULLA, storedRoi);
						}
						if ((result < 0 || result != this.CANCEL) && (result != this.ALL)) {
							addToRoiArray(slice, JMConst.RIGHT, JMConst.MEDULLA, storedRoi);
						}
					}
				}
				break;
			case SELECTORLEFT:
				if (delKeyDown) {			// if (key == KeyEvent.VK_DELETE)
					setManualSelector(JMConst.LEFT, false);
				} else {
					if (altKeyDown) {		// if (key == KeyEvent.VK_ALT)
						setManualSelector(JMConst.LEFT, true);
					} else {
						manualSelector[JMConst.LEFT][slice] = !(manualSelector[JMConst.LEFT][slice]);
					}
				}
				repaint();
				break;
			case SELECTORRIGHT:
				if (delKeyDown) {			// if (key == KeyEvent.VK_DELETE)
					setManualSelector(JMConst.RIGHT, false);
				} else {
					if (altKeyDown) {		// if (key == KeyEvent.VK_ALT)
						setManualSelector(JMConst.RIGHT, true);
					} else {
						manualSelector[JMConst.RIGHT][slice] = !(manualSelector[JMConst.RIGHT][slice]);
					}
				}
				repaint();
				break;
			case MOVELEFT:

				// IJ.error("nun linke Haelfte verschieben !!!");
				callAdjuster(JMConst.LEFT);
				repaint();
				break;
			case MOVERIGHT:

				// IJ.error("nun rechte Haelfte verschieben !!!");
				callAdjuster(JMConst.RIGHT);
				repaint();
				break;
			}
		} else {
			super.mouseClicked(e);
			if (e.getClickCount() == 2) {
				Roi roi = getClickedRoi(e);

				if (roi != null) {
					imagePlus.setRoi(roi);

					// repaint();
				}
			}
		}

		// repaint();
		// if (e.getModifiers() == e.BUTTON1_MASK) super.mouseClicked(e);
		// if (e.getModifiers() == e.BUTTON2_MASK) super.mouseClicked(e);
		// if (e.getModifiers() == e.BUTTON3_MASK) super.mouseClicked(e);
	}


	/**
	 * Ruft den Dialog zur manuellen Justierung einzelner Halbbilder auf.
	 * @see   jm.kidney.ManualMover
	 * @param int Bestimmt die Bildhaelfte (0 = links, 1 = rechts)
	 */
	private void callAdjuster(int half) {
		ManualMover mm = new ManualMover(imagePlus, slice, half, imagePlus.getWindow().getBounds());
	}


	/**
	 * Ruft den Frage-Dialog bei der Arretierung von ROIs auf.
	 * @see   jm.extension.AddRoiDailog
	 * @return int Wird durch die vom Benutzer geklickte Taste beim Verlassen des Dialoges bestimmt.
	 */
	private int showAddRoiMessage() {
		if (!dontAskAgain) {
			AddRoiDialog	dlg = new AddRoiDialog(imagePlus.getWindow(), "ADD ROI", "Add this roi for all slices or\nonly for the current slice ?\n   \nNote:\nALT-Key + Mouseclick:\n      adds a roi for all slices\nDEL-Key  + Mouseclick:\n      deletes all rois of the selected Type");

			dlg.setVisible(true);
			if (dlg.dontAskAgain == true) {
				dontAskAgain = true;
			}
			if (dlg.result == dlg.ALL) {
				dlg = null;
				return ALL;
			}
			if (dlg.result == dlg.CURRENT) {
				dlg = null;
				return CURRENT;
			}
			if (dlg.result == dlg.CANCEL) {
				dlg = null;
				return CANCEL;
			}
		}
		return -1;
	}


	/**
	 * Berechnet, welche Roi sich an der Position des Canvas befindet, auf deren
	 * Koordinaten der Benutzer doppelt geklickt hat.
	 * @return Roi Die angeklickte Roi. Null, wenn keine Roi mit dem Doppelklick getroffen wurde.
	 */
	private Roi getClickedRoi(MouseEvent e) {
		Roi			result = null;
		Roi[]		mainRoi = null;
		Roi[][] cortexRoi = null;
		Roi[][] medullaRoi = null;
		int			bestPosArray = -1;
		int			bestType = -1;

		int			x = offScreenX(e.getX());
		int			y = offScreenY(e.getY());

		if (imp.sCalibrated) {
			x = (int) (x * imp.pixelWidth);
			y = (int) (y * imp.pixelWidth);
		}

		// Vergroesserung beachten !
		// x = (int)((double)x / this.getMagnification());
		// y = (int)((double)y / this.getMagnification());
		// int x = ox;
		// int y = oy;

		if (x < imagePlus.getWidth() / 2) {
			mainRoi = leftRoi;
			cortexRoi = leftRoiCortex;
			medullaRoi = leftRoiMedulla;
		} else {
			mainRoi = rightRoi;
			cortexRoi = rightRoiCortex;
			medullaRoi = rightRoiMedulla;
		}

		if (storedRoi == null) {
			boolean		roiClicked = false;
			Roi				roi;
			Rectangle rect;
			int				rx, ry, j;

			double		minDistance = Double.MAX_VALUE;

			roi = mainRoi[slice];
			if (roi != null) {
				rect = roi.getBoundingRect();
				if ((x >= rect.x) && (x < rect.x + rect.width) && (y >= rect.y) && (y < rect.y + rect.height)) {
					double	dx = (double) (rect.x + (rect.width / 2) - x);
					double	dy = (double) (rect.y + (rect.height / 2) - y);
					double	d = Math.sqrt((dx * dx) + (dy * dy));

					if (d < minDistance) {
						minDistance = d;
						bestType = JMConst.MAIN;
					}
				}
			}
			j = 0;
			while (j < MAXROIS && cortexRoi[slice][j] != null) {
				roi = cortexRoi[slice][j];
				if (roi != null) {
					rect = roi.getBoundingRect();
					if ((x >= rect.x) && (x < rect.x + rect.width) && (y >= rect.y) && (y < rect.y + rect.height)) {
						double	dx = (double) (rect.x + (rect.width / 2) - x);
						double	dy = (double) (rect.y + (rect.height / 2) - y);
						double	d = Math.sqrt((dx * dx) + (dy * dy));

						if (d < minDistance) {
							minDistance = d;
							bestPosArray = j;
							bestType = JMConst.CORTEX;
						}
					}
				}
				j++;
			}

			j = 0;
			while (j < MAXROIS && medullaRoi[slice][j] != null) {
				roi = medullaRoi[slice][j];
				if (roi != null) {
					rect = roi.getBoundingRect();
					if ((x >= rect.x) && (x < rect.x + rect.width) && (y >= rect.y) && (y < rect.y + rect.height)) {
						double	dx = (double) (rect.x + (rect.width / 2) - x);
						double	dy = (double) (rect.y + (rect.height / 2) - y);
						double	d = Math.sqrt((dx * dx) + (dy * dy));

						if (d < minDistance) {
							minDistance = d;
							bestPosArray = j;
							bestType = JMConst.MEDULLA;
						}
					}
				}
				j++;
			}
		}

		if (bestType == JMConst.MAIN) {
			result = mainRoi[slice];
			mainRoi[slice] = null;
		}
		if (bestType == JMConst.MEDULLA) {
			result = medullaRoi[slice][bestPosArray];
			medullaRoi[slice][bestPosArray] = null;
			compressRoiArray(slice, medullaRoi);
		}
		if (bestType == JMConst.CORTEX) {
			result = cortexRoi[slice][bestPosArray];
			cortexRoi[slice][bestPosArray] = null;
			compressRoiArray(slice, cortexRoi);
		}
		return result;
	}


	/**
	 * Faengt Bewegungen der Maus ueber dem Canvas ab. Wird insbesondere zur korrekten
	 * Anzeige von ToolTips benoetigt.
	 * @param e MouseEvent, durch die Bewegungen der Maus verursacht.
	 */
	public void mouseMoved(MouseEvent e) {

		// canvasButton.dispatchEvent(e);

		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 3; j++) {
				buttonBorderColor[i][j] = Color.darkGray;
			}
		}

		xMouse = e.getX();
		yMouse = e.getY();


		lastRect.x = repaintRect.x;
		lastRect.y = repaintRect.y;
		lastRect.width = repaintRect.width;
		lastRect.height = repaintRect.height;

		int button = mouseOverButton(xMouse, yMouse);

		if (button >= 0) {
			ImageWindow win = imp.getWindow();

			if (win != null) {
				win.setCursor(defaultCursor); //win.setCursor(win.DEFAULT_CURSOR);

			}
			switch (button) {
			case BUTTON1LEFT:
				buttonBorderColor[JMConst.LEFT][0] = Color.lightGray;
				setToolTipText("lock main roi right");
				break;
			case BUTTON2LEFT:
				buttonBorderColor[JMConst.LEFT][1] = Color.lightGray;
				setToolTipText("lock cortex roi right");
				break;
			case BUTTON3LEFT:
				buttonBorderColor[JMConst.LEFT][2] = Color.lightGray;
				setToolTipText("lock medulla roi right");
				break;
			case BUTTON1RIGHT:
				buttonBorderColor[JMConst.RIGHT][0] = Color.lightGray;
				setToolTipText("lock main roi left");
				break;
			case BUTTON2RIGHT:
				buttonBorderColor[JMConst.RIGHT][1] = Color.lightGray;
				setToolTipText("lock cortex roi left");
				break;
			case BUTTON3RIGHT:
				buttonBorderColor[JMConst.RIGHT][2] = Color.lightGray;
				setToolTipText("lock medulla roi left");
				break;
			case SELECTORLEFT:
				setToolTipText("enable for SIT-Curves");
				break;
			case SELECTORRIGHT:
				setToolTipText("enable for SIT-Curves");
				break;
			case MOVELEFT:
				setToolTipText("adjust translation");
				break;
			case MOVERIGHT:
				setToolTipText("adjust translation");
				break;
			}
			repaintDone = false;
			if (lastRect.x != repaintRect.x) {
				repaint(lastRect.x, lastRect.y, lastRect.width, lastRect.height);
			}
			repaint(repaintRect.x, repaintRect.y, repaintRect.width, repaintRect.height);
		} else {
			super.mouseMoved(e);
			setToolTipText("");
			if (!repaintDone) {
				repaint(repaintRect.x, repaintRect.y, repaintRect.width, repaintRect.height);
				repaintDone = true;
			}
		}

		// super.mouseMoved(e);
		// this.repaint(buttonPos.x,buttonPos.y,buttonPos.x+(buttonWidth*3)+(1*3),buttonPos.y+buttonHeight);
		// this.repaint((width/2)+buttonPos.x,buttonPos.y,(width/2)+buttonPos.x+(buttonWidth*3)+(1*3),buttonPos.y+buttonHeight);
		// Roi roi = imagePlus.getRoi();
		// if (roi != null) IJ.write("ungleichnull");//this.repaint(roi.repaint();
	}


	/**
	 * Berechnet das Element der GUI (Canvas), ueber dem sich der Mauszeiger gerade
	 * befindet. Bekommt die aktuellen Koordinaten der Mausposition uebergeben.
	 * @param x x-Position der Maus
	 * @param y y-Position der Maus
	 * @return int Nummer der GUI-Elements, siehe Header dieser Klasse
	 */
	private int mouseOverButton(int x, int y) {

		// IJ.write("width in mouse OVer Button: "+width);

		if (y <= buttonPos.y + buttonHeight && y >= buttonPos.y) {
			repaintRect.width = buttonWidth;
			repaintRect.height = buttonHeight;
			if (x >= buttonPos.x && x <= buttonPos.x + buttonWidth) {
				repaintRect.x = buttonPos.x;
				repaintRect.y = buttonPos.y;
				return BUTTON1LEFT;
			}
			if (x >= buttonPos.x + (buttonWidth * 1) + (1 * 1) && x < buttonPos.x + (buttonWidth * 2) + (1 * 2)) {
				repaintRect.x = buttonPos.x + (buttonWidth * 1) + (1 * 1);
				repaintRect.y = buttonPos.y;
				return BUTTON2LEFT;
			}
			if (x >= buttonPos.x + (buttonWidth * 2) + (1 * 2) && x < buttonPos.x + (buttonWidth * 3) + (1 * 3)) {
				repaintRect.x = buttonPos.x + (buttonWidth * 2) + (1 * 2);
				repaintRect.y = buttonPos.y;
				return BUTTON3LEFT;
			}

			if (x >= widthDiv2 + buttonPos.x && x <= widthDiv2 + buttonPos.x + buttonWidth) {
				repaintRect.x = widthDiv2 + buttonPos.x;
				repaintRect.y = buttonPos.y;
				return BUTTON1RIGHT;
			}
			if (x >= widthDiv2 + buttonPos.x + (buttonWidth * 1) + (1 * 1) && x < widthDiv2 + buttonPos.x + (buttonWidth * 2) + (1 * 2)) {
				repaintRect.x = widthDiv2 + buttonPos.x + (buttonWidth * 1) + (1 * 1);
				repaintRect.y = buttonPos.y;
				return BUTTON2RIGHT;
			}
			if (x >= widthDiv2 + buttonPos.x + (buttonWidth * 2) + (1 * 2) && x < widthDiv2 + buttonPos.x + (buttonWidth * 3) + (1 * 3)) {
				repaintRect.x = widthDiv2 + buttonPos.x + (buttonWidth * 2) + (1 * 2);
				repaintRect.y = buttonPos.y;
				return BUTTON3RIGHT;
			}
		}

		if (y <= 9) {
			if (x >= 16 && x <= 25) {
				repaintRect.x = 16;
				repaintRect.y = 0;
				repaintRect.width = 10;
				repaintRect.height = 10;
				return SELECTORLEFT;
			}
			if (x >= widthDiv2 + 16 && x <= widthDiv2 + 25) {
				repaintRect.x = widthDiv2 + 16;
				repaintRect.y = 0;
				repaintRect.width = 10;
				repaintRect.height = 10;
				return SELECTORRIGHT;
			}

			int arrowButtonPos = buttonPos.x + (buttonWidth * 3) + (1 * 3) + 1;

			if (x >= arrowButtonPos && x <= arrowButtonPos + 9) {
				repaintRect.x = arrowButtonPos;
				repaintRect.y = 0;
				repaintRect.width = 10;
				repaintRect.height = 10;
				return MOVELEFT;
			}
			if (x >= arrowButtonPos + widthDiv2 && x <= arrowButtonPos + widthDiv2 + 9) {
				repaintRect.x = arrowButtonPos + widthDiv2;
				repaintRect.y = 0;
				repaintRect.width = 10;
				repaintRect.height = 10;
				return MOVERIGHT;
			}
		}
		return -1;
	}


	/**
	 * Faengt ComponentEvents ab. Dies ist noetig, um die aktuellen Ausmasse des Fensters
	 * zur Laufzeit immer zu kennen. Nur dann kann die GUI exakt upgedated werden.
	 * @param e ComponentEvent, durch Veraenderungen des Fensters ausgeloest
	 */
	public void componentHidden(ComponentEvent e) {

		// IJ.write("Comp evt");
		storeNextCanvasSize = true;
		this.repaint();
	}


	/**
	 * Faengt ComponentEvents ab. Dies ist noetig, um die aktuellen Ausmasse des Fensters
	 * zur Laufzeit immer zu kennen. Nur dann kann die GUI exakt upgedated werden.
	 * @param e ComponentEvent, durch Veraenderungen des Fensters ausgeloest
	 */
	public void componentShown(ComponentEvent e) {

		// IJ.write("Comp evt");
		storeNextCanvasSize = true;
		this.repaint();
	}


	/**
	 * Faengt ComponentEvents ab. Dies ist noetig, um die aktuellen Ausmasse des Fensters
	 * zur Laufzeit immer zu kennen. Nur dann kann die GUI exakt upgedated werden.
	 * @param e ComponentEvent, durch Veraenderungen des Fensters ausgeloest
	 */
	public void componentMoved(ComponentEvent e) {

		// IJ.write("Comp evt");
		storeNextCanvasSize = true;
		this.repaint();
	}


	/**
	 * Faengt ComponentEvents ab. Dies ist noetig, um die aktuellen Ausmasse des Fensters
	 * zur Laufzeit immer zu kennen. Nur dann kann die GUI exakt upgedated werden.
	 * @param e ComponentEvent, durch Veraenderungen des Fensters ausgeloest
	 */
	public void componentResized(ComponentEvent e) {

		// IJ.write("Comp evt");
		storeNextCanvasSize = true;
		this.repaint();
	}


	/**
	 * Faengt Eingaben von der Tastatur ab. Dies ist noetig, um abzufragen, ob die ALT-
	 * oder ENTF-Taste waehrend eines Mausklicks gedrueckt wurde.
	 * @param evt KeyEvent, durch Tastatureinagben ausgeloest.
	 */
	public void keyReleased(KeyEvent evt) {
		altKeyDown = false;
		delKeyDown = false;
	}


	/**
	 * Faengt Eingaben von der Tastatur ab. Dies ist noetig, um abzufragen, ob die ALT-
	 * oder ENTF-Taste waehrend eines Mausklicks gedrueckt wurde.
	 * @param evt KeyEvent, durch Tastatureinagben ausgeloest.
	 */
	public void keyPressed(KeyEvent evt) {
		int keyCode = evt.getKeyCode();

		altKeyDown = false;
		delKeyDown = false;
		if (keyCode == KeyEvent.VK_ALT) {
			altKeyDown = true;
		}
		if (keyCode == KeyEvent.VK_DELETE) {
			delKeyDown = true;
		}
	}


	/**
	 * Faengt Eingaben von der Tastatur ab. Dies ist noetig, um abzufragen, ob die ALT-
	 * oder ENTF-Taste waehrend eines Mausklicks gedrueckt wurde.
	 * @param evt KeyEvent, durch Tastatureinagben ausgeloest.
	 */
	public void keyTyped(KeyEvent evt) {}

        /**
	 * Beendet die laufenden Threads (AwtToolTip!)
	 * @return boolean true, wenn der Vorgang erfolgreich war.
	 */
	public boolean endThreads() {
		try {
			awtToolTip.setSourceClass(null);
                        awtToolTip = null;
		}
                catch (Exception e) {
                        IJ.write(e.toString());
			IJ.write("AWTToolTip-Thread laeuft immer noch !");
                  return false;
		}
		return true;
	}

}







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

