/*
* 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.sequence.tools;
import icy.gui.component.RangeComponent;
import icy.gui.component.sequence.SequencePreviewPanel;
import icy.sequence.DimensionId;
import icy.sequence.SequenceModel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.EventListener;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class SequenceDimensionAdjustPanel extends JPanel
{
/**
*
*/
private static final long serialVersionUID = 5670426025630944193L;
public interface RangeChangeListener extends EventListener
{
public void rangeChanged();
}
protected DimensionId dim;
// GUI
protected SequencePreviewPanel sequencePreviewPanel;
protected RangeComponent range;
private JPanel extractionRulePanel;
protected JSpinner extractSpinner;
protected JSpinner loopSpinner;
// internal
double oldLow;
double oldHigh;
/**
* Create the panel.
*/
public SequenceDimensionAdjustPanel(DimensionId dim)
{
super();
if ((dim != DimensionId.Z) && (dim != DimensionId.T))
throw new IllegalArgumentException("Only Z or T dimension allowed");
this.dim = dim;
initialize();
if (dim == DimensionId.Z)
{
sequencePreviewPanel.getMainPanel().setBorder(
new TitledBorder(null, "Select Z interval", TitledBorder.LEADING, TitledBorder.TOP, null, null));
range = new RangeComponent(SwingConstants.VERTICAL);
range.setToolTipText("Select Z interval");
}
else
{
sequencePreviewPanel.getMainPanel().setBorder(
new TitledBorder(null, "Select T interval", TitledBorder.LEADING, TitledBorder.TOP, null, null));
range = new RangeComponent(SwingConstants.HORIZONTAL);
range.setToolTipText("Select T interval");
}
range.setMinMaxStep(0, 0, 1);
range.setVisible(false);
range.addChangeListener(new ChangeListener()
{
@Override
public void stateChanged(ChangeEvent e)
{
final double low = range.getLow();
final double high = range.getHigh();
if (oldLow != low)
{
// low value changed
if (SequenceDimensionAdjustPanel.this.dim == DimensionId.Z)
sequencePreviewPanel.setPositionZ((int) low);
else
sequencePreviewPanel.setPositionT((int) low);
}
else if (oldHigh != high)
{
// high value changed
if (SequenceDimensionAdjustPanel.this.dim == DimensionId.Z)
sequencePreviewPanel.setPositionZ((int) high);
else
sequencePreviewPanel.setPositionT((int) high);
}
oldLow = low;
oldHigh = high;
fireRangeChangedEvent();
}
});
if (dim == DimensionId.Z)
{
// replace z slider by z range component
final JPanel panel = sequencePreviewPanel.getZPanel();
panel.removeAll();
panel.setLayout(new BorderLayout());
panel.add(range, BorderLayout.CENTER);
}
else
{
// replace t slider by t range component
final JPanel panel = sequencePreviewPanel.getTPanel();
panel.removeAll();
panel.setLayout(new BorderLayout());
panel.add(range, BorderLayout.CENTER);
}
extractSpinner.addChangeListener(new ChangeListener()
{
@Override
public void stateChanged(ChangeEvent e)
{
final SpinnerNumberModel model = (SpinnerNumberModel) loopSpinner.getModel();
final int currentValue = ((Integer) model.getValue()).intValue();
final int min = getExtractValue();
// adjust minimum value
loopSpinner.setModel(new SpinnerNumberModel(Math.max(min, currentValue), min, (int) range.getMax(), 1));
fireRangeChangedEvent();
}
});
loopSpinner.addChangeListener(new ChangeListener()
{
@Override
public void stateChanged(ChangeEvent e)
{
fireRangeChangedEvent();
}
});
}
private void initialize()
{
setLayout(new BorderLayout(0, 0));
sequencePreviewPanel = new SequencePreviewPanel();
add(sequencePreviewPanel, BorderLayout.CENTER);
extractionRulePanel = new JPanel();
extractionRulePanel.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "Extraction rule",
TitledBorder.LEADING, TitledBorder.TOP, null, new Color(0, 0, 0)));
add(extractionRulePanel, BorderLayout.SOUTH);
GridBagLayout gbl_extractionRulePanel = new GridBagLayout();
gbl_extractionRulePanel.columnWidths = new int[] {0, 0, 0, 0, 0, 0};
gbl_extractionRulePanel.rowHeights = new int[] {20, 0};
gbl_extractionRulePanel.columnWeights = new double[] {0.0, 1.0, 0.0, 1.0, 2.0, Double.MIN_VALUE};
gbl_extractionRulePanel.rowWeights = new double[] {0.0, Double.MIN_VALUE};
extractionRulePanel.setLayout(gbl_extractionRulePanel);
JLabel lblKeep = new JLabel("Keep");
GridBagConstraints gbc_lblKeep = new GridBagConstraints();
gbc_lblKeep.anchor = GridBagConstraints.EAST;
gbc_lblKeep.insets = new Insets(0, 0, 0, 5);
gbc_lblKeep.gridx = 0;
gbc_lblKeep.gridy = 0;
extractionRulePanel.add(lblKeep, gbc_lblKeep);
extractSpinner = new JSpinner();
extractSpinner.setModel(new SpinnerNumberModel(new Integer(1), new Integer(1), null, new Integer(1)));
extractSpinner
.setToolTipText("Number of frames to keep every N frames. 'Keep 1 every 2' means keep every other frame.");
GridBagConstraints gbc_extractSpinner = new GridBagConstraints();
gbc_extractSpinner.fill = GridBagConstraints.HORIZONTAL;
gbc_extractSpinner.anchor = GridBagConstraints.NORTH;
gbc_extractSpinner.insets = new Insets(0, 0, 0, 5);
gbc_extractSpinner.gridx = 1;
gbc_extractSpinner.gridy = 0;
extractionRulePanel.add(extractSpinner, gbc_extractSpinner);
JLabel lblEvery = new JLabel("every");
GridBagConstraints gbc_lblEvery = new GridBagConstraints();
gbc_lblEvery.anchor = GridBagConstraints.EAST;
gbc_lblEvery.insets = new Insets(0, 0, 0, 5);
gbc_lblEvery.gridx = 2;
gbc_lblEvery.gridy = 0;
extractionRulePanel.add(lblEvery, gbc_lblEvery);
loopSpinner = new JSpinner();
loopSpinner.setModel(new SpinnerNumberModel(new Integer(1), new Integer(1), null, new Integer(1)));
loopSpinner.setToolTipText("Size for the extraction rule loop.");
GridBagConstraints gbc_loopSpinner = new GridBagConstraints();
gbc_loopSpinner.fill = GridBagConstraints.HORIZONTAL;
gbc_loopSpinner.insets = new Insets(0, 0, 0, 5);
gbc_loopSpinner.anchor = GridBagConstraints.NORTH;
gbc_loopSpinner.gridx = 3;
gbc_loopSpinner.gridy = 0;
extractionRulePanel.add(loopSpinner, gbc_loopSpinner);
}
public DimensionId getDimensionId()
{
return dim;
}
public boolean isPreviewVisible()
{
return sequencePreviewPanel.isVisible();
}
public void setPreviewVisible(boolean value)
{
sequencePreviewPanel.setVisible(value);
}
private void setMax(int value)
{
range.setMinMaxStep(0, value, 1);
range.setLowHigh(0, value);
range.setVisible(value > 0);
extractSpinner.setModel(new SpinnerNumberModel(1, 1, Math.max(value, 1), 1));
loopSpinner.setModel(new SpinnerNumberModel(1, 1, Math.max(value, 1), 1));
}
public SequenceModel getModel()
{
return sequencePreviewPanel.getModel();
}
public void setModel(SequenceModel model)
{
if (getModel() != model)
{
sequencePreviewPanel.setModel(model);
dimensionChangedInternal();
}
}
public void dimensionChanged()
{
dimensionChangedInternal();
sequencePreviewPanel.dimensionChanged();
}
private void dimensionChangedInternal()
{
final SequenceModel model = getModel();
if (model != null)
{
if (dim == DimensionId.Z)
setMax(Math.max(0, model.getSizeZ() - 1));
else
setMax(Math.max(0, model.getSizeT() - 1));
}
else
setMax(0);
}
public void imageChanged()
{
sequencePreviewPanel.imageChanged();
}
public int getRangeLow()
{
return (int) range.getLow();
}
public int getRangeHigh()
{
return (int) range.getHigh();
}
public boolean isIndexSelected(int index)
{
if (index < getRangeLow())
return false;
if (index > getRangeHigh())
return false;
return ((index - getRangeLow()) % getLoopValue()) < getExtractValue();
}
public int getExtractValue()
{
return ((Integer) extractSpinner.getValue()).intValue();
}
public int getLoopValue()
{
return ((Integer) loopSpinner.getValue()).intValue();
}
protected void fireRangeChangedEvent()
{
for (RangeChangeListener listener : getListeners(RangeChangeListener.class))
listener.rangeChanged();
}
public void addRangeChangeListener(RangeChangeListener listener)
{
listenerList.add(RangeChangeListener.class, listener);
}
public void removeRangeChangeListener(RangeChangeListener listener)
{
listenerList.remove(RangeChangeListener.class, listener);
}
}