001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as 007 * published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 008 * 009 * Icy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 011 * 012 * You should have received a copy of the GNU General Public License along with Icy. If not, see 013 * <http://www.gnu.org/licenses/>. 014 */ 015package icy.gui.sequence.tools; 016 017import icy.gui.component.RangeComponent; 018import icy.gui.component.sequence.SequencePreviewPanel; 019import icy.sequence.DimensionId; 020import icy.sequence.SequenceModel; 021 022import java.awt.BorderLayout; 023import java.awt.Color; 024import java.awt.GridBagConstraints; 025import java.awt.GridBagLayout; 026import java.awt.Insets; 027import java.util.EventListener; 028 029import javax.swing.JLabel; 030import javax.swing.JPanel; 031import javax.swing.JSpinner; 032import javax.swing.SpinnerNumberModel; 033import javax.swing.SwingConstants; 034import javax.swing.UIManager; 035import javax.swing.border.TitledBorder; 036import javax.swing.event.ChangeEvent; 037import javax.swing.event.ChangeListener; 038 039public class SequenceDimensionAdjustPanel extends JPanel 040{ 041 /** 042 * 043 */ 044 private static final long serialVersionUID = 5670426025630944193L; 045 046 public interface RangeChangeListener extends EventListener 047 { 048 public void rangeChanged(); 049 } 050 051 protected DimensionId dim; 052 053 // GUI 054 protected SequencePreviewPanel sequencePreviewPanel; 055 protected RangeComponent range; 056 private JPanel extractionRulePanel; 057 protected JSpinner extractSpinner; 058 protected JSpinner loopSpinner; 059 060 // internal 061 double oldLow; 062 double oldHigh; 063 064 /** 065 * Create the panel. 066 */ 067 public SequenceDimensionAdjustPanel(DimensionId dim) 068 { 069 super(); 070 071 if ((dim != DimensionId.Z) && (dim != DimensionId.T)) 072 throw new IllegalArgumentException("Only Z or T dimension allowed"); 073 074 this.dim = dim; 075 076 initialize(); 077 078 if (dim == DimensionId.Z) 079 { 080 sequencePreviewPanel.getMainPanel().setBorder( 081 new TitledBorder(null, "Select Z interval", TitledBorder.LEADING, TitledBorder.TOP, null, null)); 082 range = new RangeComponent(SwingConstants.VERTICAL); 083 range.setToolTipText("Select Z interval"); 084 } 085 else 086 { 087 sequencePreviewPanel.getMainPanel().setBorder( 088 new TitledBorder(null, "Select T interval", TitledBorder.LEADING, TitledBorder.TOP, null, null)); 089 range = new RangeComponent(SwingConstants.HORIZONTAL); 090 range.setToolTipText("Select T interval"); 091 } 092 093 range.setMinMaxStep(0, 0, 1); 094 range.setVisible(false); 095 range.addChangeListener(new ChangeListener() 096 { 097 @Override 098 public void stateChanged(ChangeEvent e) 099 { 100 final double low = range.getLow(); 101 final double high = range.getHigh(); 102 103 if (oldLow != low) 104 { 105 // low value changed 106 if (SequenceDimensionAdjustPanel.this.dim == DimensionId.Z) 107 sequencePreviewPanel.setPositionZ((int) low); 108 else 109 sequencePreviewPanel.setPositionT((int) low); 110 } 111 else if (oldHigh != high) 112 { 113 // high value changed 114 if (SequenceDimensionAdjustPanel.this.dim == DimensionId.Z) 115 sequencePreviewPanel.setPositionZ((int) high); 116 else 117 sequencePreviewPanel.setPositionT((int) high); 118 } 119 120 oldLow = low; 121 oldHigh = high; 122 123 fireRangeChangedEvent(); 124 } 125 }); 126 127 if (dim == DimensionId.Z) 128 { 129 // replace z slider by z range component 130 final JPanel panel = sequencePreviewPanel.getZPanel(); 131 panel.removeAll(); 132 panel.setLayout(new BorderLayout()); 133 panel.add(range, BorderLayout.CENTER); 134 } 135 else 136 { 137 // replace t slider by t range component 138 final JPanel panel = sequencePreviewPanel.getTPanel(); 139 panel.removeAll(); 140 panel.setLayout(new BorderLayout()); 141 panel.add(range, BorderLayout.CENTER); 142 } 143 144 extractSpinner.addChangeListener(new ChangeListener() 145 { 146 @Override 147 public void stateChanged(ChangeEvent e) 148 { 149 final SpinnerNumberModel model = (SpinnerNumberModel) loopSpinner.getModel(); 150 final int currentValue = ((Integer) model.getValue()).intValue(); 151 final int min = getExtractValue(); 152 153 // adjust minimum value 154 loopSpinner.setModel(new SpinnerNumberModel(Math.max(min, currentValue), min, (int) range.getMax(), 1)); 155 156 fireRangeChangedEvent(); 157 } 158 }); 159 loopSpinner.addChangeListener(new ChangeListener() 160 { 161 @Override 162 public void stateChanged(ChangeEvent e) 163 { 164 fireRangeChangedEvent(); 165 } 166 }); 167 } 168 169 private void initialize() 170 { 171 setLayout(new BorderLayout(0, 0)); 172 173 sequencePreviewPanel = new SequencePreviewPanel(); 174 add(sequencePreviewPanel, BorderLayout.CENTER); 175 176 extractionRulePanel = new JPanel(); 177 extractionRulePanel.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "Extraction rule", 178 TitledBorder.LEADING, TitledBorder.TOP, null, new Color(0, 0, 0))); 179 add(extractionRulePanel, BorderLayout.SOUTH); 180 GridBagLayout gbl_extractionRulePanel = new GridBagLayout(); 181 gbl_extractionRulePanel.columnWidths = new int[] {0, 0, 0, 0, 0, 0}; 182 gbl_extractionRulePanel.rowHeights = new int[] {20, 0}; 183 gbl_extractionRulePanel.columnWeights = new double[] {0.0, 1.0, 0.0, 1.0, 2.0, Double.MIN_VALUE}; 184 gbl_extractionRulePanel.rowWeights = new double[] {0.0, Double.MIN_VALUE}; 185 extractionRulePanel.setLayout(gbl_extractionRulePanel); 186 187 JLabel lblKeep = new JLabel("Keep"); 188 GridBagConstraints gbc_lblKeep = new GridBagConstraints(); 189 gbc_lblKeep.anchor = GridBagConstraints.EAST; 190 gbc_lblKeep.insets = new Insets(0, 0, 0, 5); 191 gbc_lblKeep.gridx = 0; 192 gbc_lblKeep.gridy = 0; 193 extractionRulePanel.add(lblKeep, gbc_lblKeep); 194 195 extractSpinner = new JSpinner(); 196 extractSpinner.setModel(new SpinnerNumberModel(new Integer(1), new Integer(1), null, new Integer(1))); 197 extractSpinner 198 .setToolTipText("Number of frames to keep every N frames. 'Keep 1 every 2' means keep every other frame."); 199 GridBagConstraints gbc_extractSpinner = new GridBagConstraints(); 200 gbc_extractSpinner.fill = GridBagConstraints.HORIZONTAL; 201 gbc_extractSpinner.anchor = GridBagConstraints.NORTH; 202 gbc_extractSpinner.insets = new Insets(0, 0, 0, 5); 203 gbc_extractSpinner.gridx = 1; 204 gbc_extractSpinner.gridy = 0; 205 extractionRulePanel.add(extractSpinner, gbc_extractSpinner); 206 207 JLabel lblEvery = new JLabel("every"); 208 GridBagConstraints gbc_lblEvery = new GridBagConstraints(); 209 gbc_lblEvery.anchor = GridBagConstraints.EAST; 210 gbc_lblEvery.insets = new Insets(0, 0, 0, 5); 211 gbc_lblEvery.gridx = 2; 212 gbc_lblEvery.gridy = 0; 213 extractionRulePanel.add(lblEvery, gbc_lblEvery); 214 215 loopSpinner = new JSpinner(); 216 loopSpinner.setModel(new SpinnerNumberModel(new Integer(1), new Integer(1), null, new Integer(1))); 217 loopSpinner.setToolTipText("Size for the extraction rule loop."); 218 GridBagConstraints gbc_loopSpinner = new GridBagConstraints(); 219 gbc_loopSpinner.fill = GridBagConstraints.HORIZONTAL; 220 gbc_loopSpinner.insets = new Insets(0, 0, 0, 5); 221 gbc_loopSpinner.anchor = GridBagConstraints.NORTH; 222 gbc_loopSpinner.gridx = 3; 223 gbc_loopSpinner.gridy = 0; 224 extractionRulePanel.add(loopSpinner, gbc_loopSpinner); 225 } 226 227 public DimensionId getDimensionId() 228 { 229 return dim; 230 } 231 232 public boolean isPreviewVisible() 233 { 234 return sequencePreviewPanel.isVisible(); 235 } 236 237 public void setPreviewVisible(boolean value) 238 { 239 sequencePreviewPanel.setVisible(value); 240 } 241 242 private void setMax(int value) 243 { 244 range.setMinMaxStep(0, value, 1); 245 range.setLowHigh(0, value); 246 range.setVisible(value > 0); 247 248 extractSpinner.setModel(new SpinnerNumberModel(1, 1, Math.max(value, 1), 1)); 249 loopSpinner.setModel(new SpinnerNumberModel(1, 1, Math.max(value, 1), 1)); 250 } 251 252 public SequenceModel getModel() 253 { 254 return sequencePreviewPanel.getModel(); 255 256 } 257 258 public void setModel(SequenceModel model) 259 { 260 if (getModel() != model) 261 { 262 sequencePreviewPanel.setModel(model); 263 dimensionChangedInternal(); 264 } 265 } 266 267 public void dimensionChanged() 268 { 269 dimensionChangedInternal(); 270 sequencePreviewPanel.dimensionChanged(); 271 } 272 273 private void dimensionChangedInternal() 274 { 275 final SequenceModel model = getModel(); 276 277 if (model != null) 278 { 279 if (dim == DimensionId.Z) 280 setMax(Math.max(0, model.getSizeZ() - 1)); 281 else 282 setMax(Math.max(0, model.getSizeT() - 1)); 283 } 284 else 285 setMax(0); 286 } 287 288 public void imageChanged() 289 { 290 sequencePreviewPanel.imageChanged(); 291 } 292 293 public int getRangeLow() 294 { 295 return (int) range.getLow(); 296 } 297 298 public int getRangeHigh() 299 { 300 return (int) range.getHigh(); 301 } 302 303 public boolean isIndexSelected(int index) 304 { 305 if (index < getRangeLow()) 306 return false; 307 if (index > getRangeHigh()) 308 return false; 309 310 return ((index - getRangeLow()) % getLoopValue()) < getExtractValue(); 311 } 312 313 public int getExtractValue() 314 { 315 return ((Integer) extractSpinner.getValue()).intValue(); 316 } 317 318 public int getLoopValue() 319 { 320 return ((Integer) loopSpinner.getValue()).intValue(); 321 } 322 323 protected void fireRangeChangedEvent() 324 { 325 for (RangeChangeListener listener : getListeners(RangeChangeListener.class)) 326 listener.rangeChanged(); 327 } 328 329 public void addRangeChangeListener(RangeChangeListener listener) 330 { 331 listenerList.add(RangeChangeListener.class, listener); 332 } 333 334 public void removeRangeChangeListener(RangeChangeListener listener) 335 { 336 listenerList.remove(RangeChangeListener.class, listener); 337 } 338}