/*
* Copyright 2010-2015 Institut Pasteur.
*
* This file is part of Icy.
*
* Icy 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.
*
* Icy 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 Icy. If not, see <http://www.gnu.org/licenses/>.
*/
package icy.gui.component.sequence;
import icy.image.IcyBufferedImage;
import icy.image.IcyBufferedImageUtil;
import icy.sequence.SequenceModel;
import icy.sequence.SequenceModel.SequenceModelListener;
import icy.system.thread.ThreadUtil;
import icy.util.GraphicsUtil;
import icy.util.StringUtil;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class SequencePreviewPanel extends JPanel implements ChangeListener, SequenceModelListener
{
/**
*
*/
private static final long serialVersionUID = 4985194381532600393L;
private class CustomPanel extends JPanel implements Runnable
{
/**
*
*/
private static final long serialVersionUID = 6307431557815572470L;
private BufferedImage cache;
public CustomPanel()
{
super();
cache = null;
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
final int w = getWidth();
final int h = getHeight();
final Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2.setFont(g2.getFont().deriveFont(Font.BOLD, 22));
if (cache == null)
GraphicsUtil.drawCenteredString(g2, "No image", w / 2, h / 2, false);
else if ((w > 0) && (h > 0))
{
final int sw = getSizeX();
final int sh = getSizeY();
final int iw = cache.getWidth();
final int ih = cache.getHeight();
final int fiw;
final int fih;
if (fitToView)
{
final double ratio1 = Math.max((double) iw / (double) sw, (double) ih / (double) sh);
final double ratio2 = Math.max((double) sw / (double) w, (double) sh / (double) h);
fiw = (int) (iw / (ratio1 * ratio2));
fih = (int) (ih / (ratio1 * ratio2));
}
else
{
final double ratio = Math.max((double) sw / (double) w, (double) sh / (double) h);
fiw = (int) (iw / ratio);
fih = (int) (ih / ratio);
}
g2.drawImage(cache, (w - fiw) / 2, (h - fih) / 2, fiw, fih, null);
}
g2.dispose();
}
public void imageChanged()
{
// request rebuild cache
ThreadUtil.runSingle(this);
}
int getSizeX()
{
if (model != null)
return model.getSizeX();
if (cache != null)
return cache.getWidth();
return 0;
}
int getSizeY()
{
if (model != null)
return model.getSizeY();
if (cache != null)
return cache.getHeight();
return 0;
}
@Override
public void run()
{
// rebuild cache and repaint
final BufferedImage img = getImage();
if (img instanceof IcyBufferedImage)
cache = IcyBufferedImageUtil.toBufferedImage((IcyBufferedImage) img, BufferedImage.TYPE_INT_ARGB);
else
cache = img;
repaint();
}
}
protected boolean autoHideSliders;
protected boolean fitToView;
protected JSlider tSlider;
protected JSlider zSlider;
protected CustomPanel imagePanel;
protected SequenceModel model;
protected JLabel titleLabel;
protected JPanel mainPanel;
protected JPanel zPanel;
protected JPanel tPanel;
protected JLabel lblZ;
protected JLabel lblT;
protected JLabel lblZValue;
protected JLabel lblTValue;
/**
* Create the panel.
*/
public SequencePreviewPanel(String title, boolean autoHideSliders)
{
super();
this.autoHideSliders = autoHideSliders;
fitToView = true;
model = null;
initializeGui();
if (autoHideSliders)
{
zPanel.setVisible(false);
tPanel.setVisible(false);
}
setMaxZ(0);
setMaxT(0);
zSlider.addChangeListener(this);
tSlider.addChangeListener(this);
setTitle(title);
// setMinimumSize(new Dimension(320, 200));
setPreferredSize(new Dimension(280, 200));
validate();
}
/**
* Create the panel.
*/
public SequencePreviewPanel(boolean autoHideSliders)
{
this(null, autoHideSliders);
}
/**
* Create the panel.
*/
public SequencePreviewPanel(String title)
{
this(title, true);
}
/**
* Create the panel.
*/
public SequencePreviewPanel()
{
this(null, true);
}
private void initializeGui()
{
setLayout(new BorderLayout(0, 0));
titleLabel = new JLabel("Title");
titleLabel.setBorder(new EmptyBorder(2, 0, 4, 0));
titleLabel.setFont(new Font("Tahoma", Font.BOLD, 13));
titleLabel.setHorizontalAlignment(SwingConstants.CENTER);
add(titleLabel, BorderLayout.NORTH);
mainPanel = new JPanel();
add(mainPanel, BorderLayout.CENTER);
GridBagLayout gbl_mainPanel = new GridBagLayout();
gbl_mainPanel.columnWidths = new int[] {0, 0, 0};
gbl_mainPanel.rowHeights = new int[] {0, 0, 0};
gbl_mainPanel.columnWeights = new double[] {0.0, 1.0, Double.MIN_VALUE};
gbl_mainPanel.rowWeights = new double[] {1.0, 0.0, Double.MIN_VALUE};
mainPanel.setLayout(gbl_mainPanel);
imagePanel = new CustomPanel();
GridBagConstraints gbc_imagePanel = new GridBagConstraints();
gbc_imagePanel.insets = new Insets(0, 0, 5, 5);
gbc_imagePanel.fill = GridBagConstraints.BOTH;
gbc_imagePanel.gridx = 1;
gbc_imagePanel.gridy = 0;
mainPanel.add(imagePanel, gbc_imagePanel);
zPanel = new JPanel();
GridBagConstraints gbc_zPanel = new GridBagConstraints();
gbc_zPanel.insets = new Insets(0, 0, 5, 5);
gbc_zPanel.fill = GridBagConstraints.BOTH;
gbc_zPanel.gridx = 0;
gbc_zPanel.gridy = 0;
mainPanel.add(zPanel, gbc_zPanel);
GridBagLayout gbl_zPanel = new GridBagLayout();
gbl_zPanel.columnWidths = new int[] {0, 0};
gbl_zPanel.rowHeights = new int[] {0, 0, 0, 0};
gbl_zPanel.columnWeights = new double[] {0.0, Double.MIN_VALUE};
gbl_zPanel.rowWeights = new double[] {0.0, 1.0, 0.0, Double.MIN_VALUE};
zPanel.setLayout(gbl_zPanel);
lblZ = new JLabel("Z");
GridBagConstraints gbc_lblZ = new GridBagConstraints();
gbc_lblZ.fill = GridBagConstraints.BOTH;
gbc_lblZ.insets = new Insets(0, 0, 5, 0);
gbc_lblZ.gridx = 0;
gbc_lblZ.gridy = 0;
zPanel.add(lblZ, gbc_lblZ);
lblZ.setFont(new Font("Tahoma", Font.BOLD, 12));
lblZ.setHorizontalAlignment(SwingConstants.CENTER);
zSlider = new JSlider(SwingConstants.VERTICAL);
GridBagConstraints gbc_zSlider = new GridBagConstraints();
gbc_zSlider.fill = GridBagConstraints.BOTH;
gbc_zSlider.insets = new Insets(0, 0, 5, 0);
gbc_zSlider.gridx = 0;
gbc_zSlider.gridy = 1;
zPanel.add(zSlider, gbc_zSlider);
// zSlider.setFocusable(false);
lblZValue = new JLabel("0");
GridBagConstraints gbc_lblZValue = new GridBagConstraints();
gbc_lblZValue.fill = GridBagConstraints.BOTH;
gbc_lblZValue.gridx = 0;
gbc_lblZValue.gridy = 2;
zPanel.add(lblZValue, gbc_lblZValue);
lblZValue.setHorizontalAlignment(SwingConstants.CENTER);
lblZValue.setFont(new Font("Tahoma", Font.BOLD, 11));
tPanel = new JPanel();
GridBagConstraints gbc_tPanel = new GridBagConstraints();
gbc_tPanel.fill = GridBagConstraints.BOTH;
gbc_tPanel.gridx = 1;
gbc_tPanel.gridy = 1;
mainPanel.add(tPanel, gbc_tPanel);
GridBagLayout gbl_tPanel = new GridBagLayout();
gbl_tPanel.columnWidths = new int[] {0, 0, 0, 0};
gbl_tPanel.rowHeights = new int[] {0, 0};
gbl_tPanel.columnWeights = new double[] {0.0, 1.0, 0.0, Double.MIN_VALUE};
gbl_tPanel.rowWeights = new double[] {1.0, Double.MIN_VALUE};
tPanel.setLayout(gbl_tPanel);
lblTValue = new JLabel("0");
lblTValue.setMaximumSize(new Dimension(1000, 14));
lblTValue.setPreferredSize(new Dimension(20, 14));
lblTValue.setMinimumSize(new Dimension(20, 14));
GridBagConstraints gbc_lblTValue = new GridBagConstraints();
gbc_lblTValue.fill = GridBagConstraints.BOTH;
gbc_lblTValue.insets = new Insets(0, 0, 0, 5);
gbc_lblTValue.gridx = 0;
gbc_lblTValue.gridy = 0;
tPanel.add(lblTValue, gbc_lblTValue);
lblTValue.setHorizontalAlignment(SwingConstants.CENTER);
lblTValue.setFont(new Font("Tahoma", Font.BOLD, 11));
tSlider = new JSlider(SwingConstants.HORIZONTAL);
GridBagConstraints gbc_tSlider = new GridBagConstraints();
gbc_tSlider.fill = GridBagConstraints.BOTH;
gbc_tSlider.insets = new Insets(0, 0, 0, 5);
gbc_tSlider.gridx = 1;
gbc_tSlider.gridy = 0;
tPanel.add(tSlider, gbc_tSlider);
// tSlider.setFocusable(false);
lblT = new JLabel("T");
lblT.setPreferredSize(new Dimension(20, 14));
lblT.setMaximumSize(new Dimension(1000, 14));
lblT.setMinimumSize(new Dimension(20, 14));
GridBagConstraints gbc_lblT = new GridBagConstraints();
gbc_lblT.fill = GridBagConstraints.BOTH;
gbc_lblT.gridx = 2;
gbc_lblT.gridy = 0;
tPanel.add(lblT, gbc_lblT);
lblT.setFont(new Font("Tahoma", Font.BOLD, 12));
lblT.setHorizontalAlignment(SwingConstants.CENTER);
validate();
}
/**
* @return the main panel
*/
public JPanel getMainPanel()
{
return mainPanel;
}
/**
* @return the zPanel
*/
public JPanel getZPanel()
{
return zPanel;
}
/**
* @return the tPanel
*/
public JPanel getTPanel()
{
return tPanel;
}
public boolean getAutoHideSliders()
{
return autoHideSliders;
}
public void setAutoHideSliders(boolean value)
{
if (autoHideSliders != value)
{
autoHideSliders = value;
zPanel.setVisible((zSlider.getMaximum() > 0) && value);
tPanel.setVisible((tSlider.getMaximum() > 0) && value);
}
}
public void setFitToView(boolean value)
{
if (fitToView != value)
{
fitToView = value;
imagePanel.imageChanged();
}
}
public void setPositionZ(int z)
{
zSlider.setValue(z);
imageChanged();
}
public void setPositionT(int t)
{
tSlider.setValue(t);
imageChanged();
}
private void setMaxZ(int value)
{
zSlider.setMaximum(Math.max(0, value));
if (autoHideSliders)
zPanel.setVisible(value > 0);
}
private void setMaxT(int value)
{
tSlider.setMaximum(Math.max(0, value));
if (autoHideSliders)
tPanel.setVisible(value > 0);
}
/**
* @return the image provider
*/
public SequenceModel getModel()
{
return model;
}
public void setModel(SequenceModel model)
{
if (this.model != model)
{
if (this.model != null)
this.model.removeSequenceModelListener(this);
this.model = model;
if (model != null)
model.addSequenceModelListener(this);
dimensionChanged();
}
}
public void setTitle(String value)
{
if (!titleLabel.getText().equals(value))
{
titleLabel.setText(value);
titleLabel.setVisible(!StringUtil.isEmpty(value));
}
}
@Override
public void dimensionChanged()
{
if (model != null)
{
setMaxZ(model.getSizeZ() - 1);
setMaxT(model.getSizeT() - 1);
}
else
{
setMaxZ(0);
setMaxT(0);
}
imagePanel.imageChanged();
}
@Override
public void imageChanged()
{
imagePanel.imageChanged();
}
BufferedImage getImage()
{
if (model == null)
return null;
return model.getImage(tSlider.getValue(), zSlider.getValue());
}
@Override
public void stateChanged(ChangeEvent e)
{
imagePanel.imageChanged();
lblZValue.setText(Integer.toString(zSlider.getValue()));
lblTValue.setText(Integer.toString(tSlider.getValue()));
}
}