/*
* Copyright 2010, 2011 Institut Pasteur.
*
* This file is part of NHerve Main Toolbox, which is an ICY plugin.
*
* NHerve Main Toolbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NHerve Main Toolbox 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 NHerve Main Toolbox. If not, see <http://www.gnu.org/licenses/>.
*/
package plugins.nherve.toolbox.genericgrid;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import plugins.nherve.toolbox.image.toolboxes.ImageTools;
import plugins.nherve.toolbox.plugin.PluginHelper;
public abstract class GridCell extends JComponent implements MouseListener, MouseMotionListener {
private static final long serialVersionUID = -3822419525699981741L;
private Color bckBorderColor;
private int bckZoomHeight;
private Point bckZoomLocation;
private int bckZoomWidth;
private int bckZoomZO;
private Color borderColor;
private float borderWidth;
private boolean displayName;
private String errorMessage;
private Font font;
private int heightForName;
private String name;
private boolean needCacheRedraw;
protected BufferedImage thumbnail;
private BufferedImage thumbnailCache;
@SuppressWarnings("rawtypes")
private ThumbnailProvider thumbnailProvider;
private WaitingAnimation wa;
private double zoomCenterX;
private double zoomCenterY;
private boolean zoomOnFocus;
private String ttt;
public GridCell() {
this(null);
}
public GridCell(String name) {
super();
setName(name);
setError(null);
setBorderWidth(1);
wa = new WaitingAnimation(this);
setBorderColor(null);
addMouseListener(this);
addMouseMotionListener(this);
}
void createThumbnailCache() {
if (thumbnail == null) {
this.thumbnailCache = null;
return;
}
thumbnailCache = ImageTools.resize(thumbnail, getWidth(), getHeight() - getHeightForName());
needCacheRedraw = false;
}
public Color getBorderColor() {
return borderColor;
}
public float getBorderWidth() {
return borderWidth;
}
public int getHeightForName() {
return heightForName;
}
public String getName() {
return name;
}
public boolean isError() {
return errorMessage != null;
}
public boolean isOnScreen() {
Rectangle r = getVisibleRect();
if (r == null) {
return false;
}
if ((r.height == 0) || (r.width == 0)) {
return false;
}
return true;
}
@Override
public void mouseDragged(MouseEvent arg0) {
}
@Override
public void mouseEntered(MouseEvent e) {
if (zoomOnFocus) {
bckZoomWidth = getWidth();
bckZoomHeight = getHeight();
bckZoomLocation = getLocation();
bckZoomZO = getParent().getComponentZOrder(this);
getParent().setComponentZOrder(this, 0);
Rectangle r = getBounds();
zoomCenterX = r.getCenterX();
zoomCenterY = r.getCenterY();
} else {
bckBorderColor = borderColor;
setBorderColor(Color.GREEN);
repaint();
}
}
@Override
public void mouseExited(MouseEvent e) {
if (zoomOnFocus) {
setLocation(bckZoomLocation);
setSize(bckZoomWidth, bckZoomHeight);
getParent().setComponentZOrder(this, bckZoomZO);
createThumbnailCache();
} else {
setBorderColor(bckBorderColor);
}
repaint();
}
@Override
public void mouseMoved(MouseEvent e) {
if (zoomOnFocus) {
e = SwingUtilities.convertMouseEvent(this, e, getParent());
int mX = e.getX();
int mY = e.getY();
double dX = zoomCenterX - mX;
double dY = zoomCenterY - mY;
double distToCenter = Math.sqrt(dX * dX + dY * dY);
distToCenter = Math.min(1d, distToCenter / (getWidth() / 2));
double zoomFactor = 1d + Math.exp(-distToCenter * distToCenter * distToCenter * distToCenter * 5d);
int nW = (int) (bckZoomWidth * zoomFactor);
int nH = (int) (bckZoomHeight * zoomFactor);
int nX = bckZoomLocation.x - (nW - bckZoomWidth) / 2;
int nY = bckZoomLocation.y - (nH - bckZoomHeight) / 2;
setSize(nW, nH);
setLocation(nX, nY);
createThumbnailCache();
repaint();
}
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
void notifyDisplayParametersChanged() {
needCacheRedraw = true;
}
@SuppressWarnings("unchecked")
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
int w = getWidth();
int h = getHeight();
if (isError()) {
SomeStandardThumbnails.paintError(g2, this);
} else if (thumbnail == null) {
if (!wa.isRunning()) {
wa.start();
}
thumbnailProvider.provideThumbnailFor(this);
} else if (needCacheRedraw) {
thumbnailProvider.createCacheFor(this);
}
if (wa.isRunning()) {
wa.paintAnimation(g2, this);
}
if (thumbnailCache != null) {
g2.drawImage(thumbnailCache, null, this);
}
if (displayName) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2.setColor(Color.BLACK);
g2.setFont(font);
FontMetrics fm = getGraphics().getFontMetrics(font);
String textToDraw = PluginHelper.clipString(fm, getWidth(), getName());
g2.drawString(textToDraw, 0, getHeight() - fm.getMaxDescent());
}
if (getBorderColor() != null) {
g2.setColor(getBorderColor());
Stroke s = g2.getStroke();
g2.setStroke(new BasicStroke(getBorderWidth()));
g2.drawRect(0, 0, w - 1, h - 1);
g2.setStroke(s);
}
}
public void removedFromGrid() {
wa.stop();
}
public void setBorderColor(Color borderColor) {
this.borderColor = borderColor;
}
public void setBorderWidth(float borderWidth) {
this.borderWidth = borderWidth;
}
void setDisplayName(boolean displayName) {
this.displayName = displayName;
}
public void setError(Throwable tw) {
if (tw != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
tw.printStackTrace(ps);
setErrorMessage(getName() + " - " + baos.toString());
ps.close();
wa.stop();
createThumbnailCache();
repaint();
} else {
setErrorMessage(null);
}
}
public void setErrorMessage(String error) {
this.errorMessage = error;
if (error != null) {
if (zoomOnFocus) {
setToolTipText(null);
} else {
setToolTipText(error);
}
}
}
public void setHeightForName(int heightForName) {
this.heightForName = heightForName;
}
public void setName(String name) {
this.name = name;
if (ttt == null) {
ttt = name;
}
}
void setNameFont(Font font) {
this.font = font;
}
public void setThumbnail(BufferedImage thumb) {
wa.stop();
if (thumb != null) {
this.thumbnail = thumb;
} else {
this.thumbnail = null;
}
createThumbnailCache();
repaint();
}
void setThumbnailProvider(@SuppressWarnings("rawtypes") ThumbnailProvider thumbnailProvider) {
this.thumbnailProvider = thumbnailProvider;
}
void setZoomOnFocus(boolean zoomOnFocus) {
this.zoomOnFocus = zoomOnFocus;
if (zoomOnFocus) {
setToolTipText(null);
} else {
setToolTipText(ttt);
}
}
public String getTtt() {
return ttt;
}
public void setTtt(String ttt) {
this.ttt = ttt;
}
}