/* * 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.dialog; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.Rectangle2D; import java.io.IOException; import java.util.List; import java.util.concurrent.Callable; import javax.swing.BorderFactory; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.border.Border; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import icy.common.exception.UnsupportedFormatException; import icy.file.Loader; import icy.file.SequenceFileImporter; import icy.gui.component.RangeComponent; import icy.gui.component.Region2DComponent; import icy.gui.component.SpecialValueSpinner; import icy.gui.component.ThumbnailComponent; import icy.gui.component.model.SpecialValueSpinnerModel; import icy.resource.ResourceUtil; import icy.sequence.MetaDataUtil; import icy.system.thread.ThreadUtil; import icy.util.StringUtil; import loci.formats.ome.OMEXMLMetadataImpl; public class LoaderOptionPanel extends JPanel { private class PreviewUpdater extends Thread { final String fileId; int z; int t; int c; boolean imageChangeOnly; public PreviewUpdater(String fileId, int z, int t, int c) { super("Image preview"); this.fileId = fileId; this.z = z; this.t = t; this.c = c; // on first preview update, we should have Z,T,C set to -1 imageChangeOnly = (z != -1) || (t != -1) || (c != -1); } public PreviewUpdater(String fileId) { super("Image preview"); this.fileId = fileId; // on first preview update, we should have Z,T,C set to -1 imageChangeOnly = false; } @Override public void run() { // interrupt process if (isInterrupted()) return; // only need to update image if (imageChangeOnly) { try { // use last - 1 resolution final int res = Math.max(0, resolutionSlider.getMaximum() - 1); // not defined --> use middle if (z == -1) z = MetaDataUtil.getSizeZ(metadata, 0) / 2; // not defined --> use middle if (t == -1) t = MetaDataUtil.getSizeT(metadata, 0) / 2; final List<SequenceFileImporter> importers = Loader.getSequenceFileImporters(fileId); for (SequenceFileImporter importer : importers) { // interrupt process if (isInterrupted()) break; try { if (importer.open(fileId, 0)) { try { // default position --> use thumbnail if ((z == 0) && (t == 0) && (c == -1)) preview.setImage(importer.getThumbnail(0)); // all channel else if (c == -1) preview.setImage(importer.getImage(0, res, z, t)); // specific channel else preview.setImage(importer.getImage(0, res, z, t, c)); } finally { importer.close(); } } } catch (UnsupportedFormatException e) { // try next importer... } catch (RuntimeException e) { // try next importer... } catch (IOException e) { // try next importer... } // done break; } } catch (Throwable t) { // ignore System.out.println("truc"); } // image updated return; } boolean metaDataDone = false; boolean thumbnailDone = false; metadata = null; if (StringUtil.isEmpty(fileId)) { preview.setImage(null); preview.setInfos(""); metadata = new OMEXMLMetadataImpl(); metaDataDone = true; thumbnailDone = true; return; } preview.setImage(ResourceUtil.ICON_WAIT); preview.setInfos("loading..."); try { // use Callable as we can get interrupted here... ThreadUtil.invokeNow(new Callable<Boolean>() { @Override public Boolean call() throws Exception { // update panel updatePanel(); return Boolean.TRUE; } }); final List<SequenceFileImporter> importers = Loader.getSequenceFileImporters(fileId); for (SequenceFileImporter importer : importers) { // interrupt process if (isInterrupted()) break; try { if (importer.open(fileId, 0)) { // interrupt process if (isInterrupted()) break; try { if (!metaDataDone) { metadata = importer.getMetaData(); // update it as soon as possible (use Callable as we can get interrupted here...) ThreadUtil.invokeNow(new Callable<Boolean>() { @Override public Boolean call() throws Exception { // update panel updatePanel(); return Boolean.TRUE; } }); // now the different "metadata" fields are up to date metadataFieldsOk = true; // initial preview --> update default range and channel positions pZMin = getZMin(); pZMax = getZMax(); pTMin = getTMin(); pTMax = getTMax(); pCh = getChannel(); final int sizeC = MetaDataUtil.getSizeC(metadata, 0); // load metadata first preview.setInfos(MetaDataUtil.getSizeX(metadata, 0) + " x " + MetaDataUtil.getSizeY(metadata, 0) + " - " + MetaDataUtil.getSizeZ(metadata, 0) + "Z x " + MetaDataUtil.getSizeT(metadata, 0) + "T - " + sizeC + " ch (" + MetaDataUtil.getDataType(metadata, 0) + ")"); metaDataDone = true; } // interrupt process if (isInterrupted()) break; if (!thumbnailDone) { // initial preview --> use thumbnail preview.setImage(importer.getThumbnail(0)); thumbnailDone = true; } } finally { importer.close(); } } } catch (UnsupportedFormatException e) { // try next importer... } catch (RuntimeException e) { // try next importer... } catch (IOException e) { // try next importer... } // we correctly loaded both metadata and thumbnail --> exit if (metaDataDone && thumbnailDone) break; } } catch (InterruptedException t) { // no need to do more here... return; } catch (Throwable t) { // ignore } try { // cannot read metadata if (!metaDataDone) { preview.setInfos("Cannot read file"); // use Callable as we can get interrupted here... ThreadUtil.invokeNow(new Callable<Boolean>() { @Override public Boolean call() throws Exception { // update panel updatePanel(); return Boolean.TRUE; } }); } // cannot get thumbnail if (!thumbnailDone) preview.setImage(ResourceUtil.ICON_DELETE); } catch (Throwable t) { // probably interrupted... } } } /** * */ private static final long serialVersionUID = 4180367632912879286L; /** * GUI */ protected ThumbnailComponent preview; protected JPanel optionsPanel; protected JLabel resolutionLevelLabel; protected JLabel loadInSeparatedLabel; protected JLabel autoOrderLabel; protected JCheckBox separateSeqCheck; protected JCheckBox autoOrderCheck; protected JSlider resolutionSlider; protected JLabel zRangeLabel; protected JLabel tRangeLabel; protected JLabel channelLabel; protected RangeComponent zRangeComp; protected RangeComponent tRangeComp; protected SpecialValueSpinner channelSpinner; protected JLabel resolutionFixLabel; protected JLabel xyRegionLabel; protected Region2DComponent xyRegionComp; protected JCheckBox xyRegionLoadingCheck; // internals protected boolean autoOrderEnable; protected boolean metadataFieldsOk; protected PreviewUpdater previewThread; protected OMEXMLMetadataImpl metadata; protected int pZMin; protected int pZMax; protected int pTMin; protected int pTMax; protected int pCh; protected boolean multiFile; protected boolean updatingPanel; /** * Create the panel. */ public LoaderOptionPanel(boolean separate, boolean autoOrder) { super(); autoOrderEnable = true; previewThread = null; metadataFieldsOk = false; metadata = null; pZMin = -1; pZMax = -1; pTMin = -1; pTMax = -1; pCh = -1; updatingPanel = false; initialize(separate, autoOrder); // default multiFile = true; setMultiFile(false); updatePanel(); } private void initialize(boolean separate, boolean autoOrder) { setBorder(BorderFactory.createTitledBorder((Border) null)); setLayout(new BorderLayout()); preview = new ThumbnailComponent(false); preview.setShortDisplay(true); add(preview, BorderLayout.CENTER); optionsPanel = new JPanel(); add(optionsPanel, BorderLayout.SOUTH); GridBagLayout gbl_optionsPanel = new GridBagLayout(); gbl_optionsPanel.columnWidths = new int[] {0, 50, 0, 0, 0}; gbl_optionsPanel.rowHeights = new int[] {0, 0, 0, 0, 0, 0, 0, 0}; gbl_optionsPanel.columnWeights = new double[] {0.0, 1.0, 1.0, 0.0, Double.MIN_VALUE}; gbl_optionsPanel.rowWeights = new double[] {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE}; optionsPanel.setLayout(gbl_optionsPanel); GridBagConstraints gbc_loadInSeparatedLabel = new GridBagConstraints(); gbc_loadInSeparatedLabel.gridwidth = 3; gbc_loadInSeparatedLabel.anchor = GridBagConstraints.WEST; gbc_loadInSeparatedLabel.insets = new Insets(0, 0, 5, 5); gbc_loadInSeparatedLabel.gridx = 0; gbc_loadInSeparatedLabel.gridy = 0; loadInSeparatedLabel = new JLabel("Load in separated sequences"); loadInSeparatedLabel.setToolTipText("All images are opened in its own sequence"); optionsPanel.add(loadInSeparatedLabel, gbc_loadInSeparatedLabel); // setting GUI separateSeqCheck = new JCheckBox(); separateSeqCheck.setToolTipText("All images are opened in its own sequence"); loadInSeparatedLabel.setLabelFor(separateSeqCheck); separateSeqCheck.setSelected(separate); separateSeqCheck.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { updateAutoOrderEnableState(); } }); GridBagConstraints gbc_separateSeqCheck = new GridBagConstraints(); gbc_separateSeqCheck.insets = new Insets(0, 0, 5, 0); gbc_separateSeqCheck.anchor = GridBagConstraints.NORTHEAST; gbc_separateSeqCheck.gridx = 3; gbc_separateSeqCheck.gridy = 0; optionsPanel.add(separateSeqCheck, gbc_separateSeqCheck); autoOrderLabel = new JLabel("Automatic ordering"); autoOrderLabel.setToolTipText("Try to automatically set Z, T, C position of an image from their file name"); GridBagConstraints gbc_autoOrderLabel = new GridBagConstraints(); gbc_autoOrderLabel.gridwidth = 3; gbc_autoOrderLabel.anchor = GridBagConstraints.WEST; gbc_autoOrderLabel.insets = new Insets(0, 0, 5, 5); gbc_autoOrderLabel.gridx = 0; gbc_autoOrderLabel.gridy = 1; optionsPanel.add(autoOrderLabel, gbc_autoOrderLabel); autoOrderCheck = new JCheckBox(""); autoOrderCheck.setToolTipText("Try to automatically set Z, T, C position of an image from their file name"); autoOrderLabel.setLabelFor(autoOrderCheck); autoOrderCheck.setSelected(autoOrder); GridBagConstraints gbc_autoOrderCheck = new GridBagConstraints(); gbc_autoOrderCheck.anchor = GridBagConstraints.EAST; gbc_autoOrderCheck.insets = new Insets(0, 0, 5, 0); gbc_autoOrderCheck.gridx = 3; gbc_autoOrderCheck.gridy = 1; optionsPanel.add(autoOrderCheck, gbc_autoOrderCheck); resolutionFixLabel = new JLabel("Resolution"); resolutionFixLabel.setToolTipText("Select resolution level to open"); GridBagConstraints gbc_resolutionFixLabel = new GridBagConstraints(); gbc_resolutionFixLabel.anchor = GridBagConstraints.WEST; gbc_resolutionFixLabel.insets = new Insets(0, 0, 5, 5); gbc_resolutionFixLabel.gridx = 0; gbc_resolutionFixLabel.gridy = 2; optionsPanel.add(resolutionFixLabel, gbc_resolutionFixLabel); resolutionLevelLabel = new JLabel(""); resolutionLevelLabel.setToolTipText("Select resolution level to open"); GridBagConstraints gbc_resolutionLevelLabel = new GridBagConstraints(); gbc_resolutionLevelLabel.anchor = GridBagConstraints.WEST; gbc_resolutionLevelLabel.insets = new Insets(0, 0, 5, 5); gbc_resolutionLevelLabel.gridx = 1; gbc_resolutionLevelLabel.gridy = 2; optionsPanel.add(resolutionLevelLabel, gbc_resolutionLevelLabel); resolutionSlider = new JSlider(); resolutionSlider.setSnapToTicks(true); resolutionSlider.setMinimumSize(new Dimension(36, 22)); resolutionSlider.setMaximumSize(new Dimension(100, 22)); resolutionSlider.setPreferredSize(new Dimension(100, 22)); resolutionSlider.setToolTipText("Select resolution level to open"); resolutionSlider.setValue(0); resolutionSlider.setMaximum(10); resolutionSlider.setFocusable(false); resolutionSlider.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { updateFinaleResolution(); } }); GridBagConstraints gbc_resolutionSlider = new GridBagConstraints(); gbc_resolutionSlider.fill = GridBagConstraints.BOTH; gbc_resolutionSlider.gridwidth = 2; gbc_resolutionSlider.insets = new Insets(0, 0, 5, 0); gbc_resolutionSlider.gridx = 2; gbc_resolutionSlider.gridy = 2; optionsPanel.add(resolutionSlider, gbc_resolutionSlider); xyRegionLabel = new JLabel("XY region"); xyRegionLabel.setToolTipText("Rectangular region to load (X,Y,W,H) in original resolution coordinates (pixel)"); GridBagConstraints gbc_xyRegionLabel = new GridBagConstraints(); gbc_xyRegionLabel.anchor = GridBagConstraints.WEST; gbc_xyRegionLabel.insets = new Insets(0, 0, 5, 5); gbc_xyRegionLabel.gridx = 0; gbc_xyRegionLabel.gridy = 3; optionsPanel.add(xyRegionLabel, gbc_xyRegionLabel); xyRegionComp = new Region2DComponent(); xyRegionComp.setInteger(true); xyRegionComp.setToolTipText("Rectangular region to load (X,Y,W,H) in original resolution coordinates"); GridBagConstraints gbc_xyRegionComp = new GridBagConstraints(); gbc_xyRegionComp.gridwidth = 2; gbc_xyRegionComp.insets = new Insets(0, 0, 5, 5); gbc_xyRegionComp.fill = GridBagConstraints.HORIZONTAL; gbc_xyRegionComp.gridx = 1; gbc_xyRegionComp.gridy = 3; optionsPanel.add(xyRegionComp, gbc_xyRegionComp); xyRegionLoadingCheck = new JCheckBox(""); xyRegionLoadingCheck.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { xyRegionComp.setEnabled(xyRegionLoadingCheck.isSelected()); } }); xyRegionLoadingCheck.setToolTipText("Enable region loading"); GridBagConstraints gbc_xyRegionLoadingCheck = new GridBagConstraints(); gbc_xyRegionLoadingCheck.insets = new Insets(0, 0, 5, 0); gbc_xyRegionLoadingCheck.gridx = 3; gbc_xyRegionLoadingCheck.gridy = 3; optionsPanel.add(xyRegionLoadingCheck, gbc_xyRegionLoadingCheck); zRangeLabel = new JLabel("Z range "); zRangeLabel.setToolTipText("Z interval to load"); GridBagConstraints gbc_zRangeLabel = new GridBagConstraints(); gbc_zRangeLabel.anchor = GridBagConstraints.WEST; gbc_zRangeLabel.insets = new Insets(0, 0, 5, 5); gbc_zRangeLabel.gridx = 0; gbc_zRangeLabel.gridy = 4; optionsPanel.add(zRangeLabel, gbc_zRangeLabel); zRangeComp = new RangeComponent(); zRangeComp.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { rangeChanged(); } }); zRangeComp.setToolTipText("Z interval to load"); zRangeComp.setMinimumSize(new Dimension(130, 22)); zRangeComp.setMaximumSize(new Dimension(180, 22)); zRangeComp.getHighSpinner().setPreferredSize(new Dimension(50, 20)); zRangeComp.getHighSpinner().setMaximumSize(new Dimension(50, 20)); zRangeComp.getLowSpinner().setMaximumSize(new Dimension(50, 20)); zRangeComp.getLowSpinner().setPreferredSize(new Dimension(50, 20)); zRangeComp.setPreferredSize(new Dimension(180, 22)); zRangeComp.getSlider().setPreferredSize(new Dimension(100, 22)); zRangeComp.setSliderVisible(true); GridBagConstraints gbc_zRangeComp = new GridBagConstraints(); gbc_zRangeComp.gridwidth = 3; gbc_zRangeComp.insets = new Insets(0, 0, 5, 0); gbc_zRangeComp.fill = GridBagConstraints.BOTH; gbc_zRangeComp.gridx = 1; gbc_zRangeComp.gridy = 4; optionsPanel.add(zRangeComp, gbc_zRangeComp); tRangeLabel = new JLabel("T range "); tRangeLabel.setToolTipText("T interval to load"); GridBagConstraints gbc_tRangeLabel = new GridBagConstraints(); gbc_tRangeLabel.anchor = GridBagConstraints.WEST; gbc_tRangeLabel.insets = new Insets(0, 0, 5, 5); gbc_tRangeLabel.gridx = 0; gbc_tRangeLabel.gridy = 5; optionsPanel.add(tRangeLabel, gbc_tRangeLabel); tRangeComp = new RangeComponent(); tRangeComp.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { rangeChanged(); } }); tRangeComp.setToolTipText("T interval to load"); tRangeComp.setMinimumSize(new Dimension(130, 22)); tRangeComp.setMaximumSize(new Dimension(180, 22)); tRangeComp.getLowSpinner().setPreferredSize(new Dimension(50, 20)); tRangeComp.getHighSpinner().setPreferredSize(new Dimension(50, 20)); tRangeComp.getHighSpinner().setMaximumSize(new Dimension(50, 20)); tRangeComp.getLowSpinner().setMaximumSize(new Dimension(50, 20)); tRangeComp.setPreferredSize(new Dimension(180, 22)); tRangeComp.getSlider().setPreferredSize(new Dimension(100, 22)); tRangeComp.setSliderVisible(true); GridBagConstraints gbc_tRangeComp = new GridBagConstraints(); gbc_tRangeComp.gridwidth = 3; gbc_tRangeComp.insets = new Insets(0, 0, 5, 0); gbc_tRangeComp.fill = GridBagConstraints.BOTH; gbc_tRangeComp.gridx = 1; gbc_tRangeComp.gridy = 5; optionsPanel.add(tRangeComp, gbc_tRangeComp); channelLabel = new JLabel("Channel "); channelLabel.setToolTipText("Channel to load"); GridBagConstraints gbc_channelLabel = new GridBagConstraints(); gbc_channelLabel.anchor = GridBagConstraints.WEST; gbc_channelLabel.insets = new Insets(0, 0, 0, 5); gbc_channelLabel.gridx = 0; gbc_channelLabel.gridy = 6; optionsPanel.add(channelLabel, gbc_channelLabel); channelSpinner = new SpecialValueSpinner(new SpecialValueSpinnerModel(-1, -1, 0, 1, -1, "ALL")); channelSpinner.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { rangeChanged(); } }); channelSpinner.setToolTipText("Channel to load"); channelSpinner.setPreferredSize(new Dimension(50, 22)); channelSpinner.setMinimumSize(new Dimension(50, 22)); channelSpinner.setMaximumSize(new Dimension(50, 22)); GridBagConstraints gbc_channelSpinner = new GridBagConstraints(); gbc_channelSpinner.gridwidth = 2; gbc_channelSpinner.fill = GridBagConstraints.VERTICAL; gbc_channelSpinner.anchor = GridBagConstraints.EAST; gbc_channelSpinner.gridx = 2; gbc_channelSpinner.gridy = 6; optionsPanel.add(channelSpinner, gbc_channelSpinner); } protected void rangeChanged() { if (updatingPanel) return; int v; int z = -1; int t = -1; int c = -1; // detect change on z, t, c position in preview v = getZMin(); if (pZMin != v) { z = v; pZMin = v; } v = getZMax(); if (pZMax != v) { z = v; pZMax = v; } v = getTMin(); if (pTMin != v) { t = v; pTMin = v; } v = getTMax(); if (pTMax != v) { t = v; pTMax = v; } v = getChannel(); if (pCh != v) { c = v; pCh = v; } // changed ? --> update preview... if ((z != -1) || (t != -1) || (c != -1)) updatePreview(z, t, c); } void updateAutoOrderEnableState() { autoOrderCheck.setEnabled(autoOrderEnable && !isSeparateSequenceSelected()); } void updateXYRegion() { if (metadata != null) { final Rectangle2D r = xyRegionComp.getRegion(); final int sizeX = MetaDataUtil.getSizeX(metadata, 0); final int sizeY = MetaDataUtil.getSizeY(metadata, 0); xyRegionLoadingCheck.setEnabled(true); // xyRegionLoadingCheck.setSelected(false); xyRegionComp.setEnabled(xyRegionLoadingCheck.isSelected()); // re-init region if out of bounds if ((r.getMaxX() > sizeX) || (r.getMaxY() > sizeY)) xyRegionComp.setRegion(0, 0, sizeX, sizeY); } else { xyRegionComp.setEnabled(false); xyRegionLoadingCheck.setEnabled(false); } } void updateZRange() { if (metadata != null) { final int sizeZ = Math.max(MetaDataUtil.getSizeZ(metadata, 0), 1); zRangeComp.setMinMaxStep(0d, sizeZ - 1d, 1d); zRangeComp.setLowHigh(0d, sizeZ - 1d); zRangeComp.setEnabled(sizeZ > 1); } else { zRangeComp.setMinMaxStep(0d, 0d, 1d); zRangeComp.setEnabled(false); } } void updateTRange() { if (metadata != null) { final int sizeT = Math.max(MetaDataUtil.getSizeT(metadata, 0), 1); tRangeComp.setMinMaxStep(0d, sizeT - 1d, 1d); tRangeComp.setLowHigh(0d, sizeT - 1d); tRangeComp.setEnabled(sizeT > 1); } else { tRangeComp.setMinMaxStep(0d, 0d, 1d); tRangeComp.setEnabled(false); } } void updateChannelRange() { if (metadata != null) { final int sizeC = Math.max(MetaDataUtil.getSizeC(metadata, 0), 1); channelSpinner.setModel(new SpecialValueSpinnerModel(-1, -1, sizeC - 1, 1, -1, "ALL")); channelSpinner.setEnabled(sizeC > 1); } else { channelSpinner.setModel(new SpecialValueSpinnerModel(-1, -1, 0, 1, -1, "ALL")); channelSpinner.setEnabled(false); } } void updateResolutionSlider() { // min sub resolution to open (full resolution by default) int minRes = 0; // max sub resolution to open int maxRes = 0; if (metadata != null) { long sizeXY; // // size of XY plane // sizeXY = (long) MetaDataUtil.getSizeX(metadata, 0) * (long) MetaDataUtil.getSizeY(metadata, 0); // // // we can't handle that plane size // while (sizeXY > Integer.MAX_VALUE) // { // // reduce resolution until XY plane size is acceptable // minRes++; // sizeXY /= 4; // } // size of XY plane sizeXY = (long) MetaDataUtil.getSizeX(metadata, 0) * (long) MetaDataUtil.getSizeY(metadata, 0); // no need to get lower than 128x128 while (sizeXY > 16384) { // increase max sub resolution until XY plane is too low maxRes++; sizeXY /= 4; } } // apply resolutionSlider.setMinimum(minRes); resolutionSlider.setMaximum(maxRes); resolutionSlider.setValue(minRes); // no need to enable it resolutionSlider.setEnabled(maxRes > 0); updateFinaleResolution(); } void updateFinaleResolution() { if (metadata != null) { final int res = resolutionSlider.getValue(); final int baseX = MetaDataUtil.getSizeX(metadata, 0); final int baseY = MetaDataUtil.getSizeY(metadata, 0); final double diviser = Math.pow(2d, res); resolutionLevelLabel.setText(res + " (" + Integer.toString((int) (baseX / diviser)) + " x " + Integer.toString((int) (baseY / diviser)) + ")"); } else resolutionLevelLabel.setText(""); } void updatePanel() { updatingPanel = true; try { updateResolutionSlider(); updateXYRegion(); updateTRange(); updateZRange(); updateChannelRange(); } finally { updatingPanel = false; } } void setAutoOrderEnabled(boolean value) { autoOrderEnable = value; updateAutoOrderEnableState(); } public boolean isSeparateSequenceSelected() { return separateSeqCheck.isVisible() && separateSeqCheck.isSelected(); } public boolean isAutoOrderSelected() { return autoOrderCheck.isVisible() && autoOrderCheck.isSelected(); } public int getResolutionLevel() { if (resolutionSlider.isVisible()) return resolutionSlider.getValue(); return 0; } public Rectangle getXYRegion() { if (xyRegionComp.isVisible() && xyRegionComp.isEnabled()) return (Rectangle) xyRegionComp.getRegion(); return null; } public void setXYRegion(Rectangle region) { // enable region loading xyRegionLoadingCheck.setSelected(true); xyRegionComp.setEnabled(true); xyRegionComp.setRegion(region); } public int getZMin() { if (zRangeComp.isVisible()) return (int) zRangeComp.getLow(); return 0; } public int getZMax() { if (zRangeComp.isVisible()) return (int) zRangeComp.getHigh(); return 0; } public int getTMin() { if (tRangeComp.isVisible()) return (int) tRangeComp.getLow(); return 0; } public int getTMax() { if (tRangeComp.isVisible()) return (int) tRangeComp.getHigh(); return 0; } public int getChannel() { if (channelSpinner.isVisible()) return ((Integer) channelSpinner.getValue()).intValue(); // all by default return -1; } /** * Asynchronous image preview refresh only ({@link #updatePreview(String)} should have be called once before to give * the fileId) */ public void updatePreview(int z, int t, int c) { // interrupt previous preview refresh cancelPreview(); // only if we had a previous load if (previewThread != null) { previewThread = new PreviewUpdater(previewThread.fileId, z, t, c); previewThread.start(); } } /** * Asynchronous preview refresh */ public void updatePreview(String fileId) { // interrupt previous preview refresh cancelPreview(); metadata = null; metadataFieldsOk = false; previewThread = new PreviewUpdater(fileId); previewThread.start(); } /** * Cancel preview refresh */ public void cancelPreview() { // brutal interruption of previous execution if (previewThread != null) previewThread.interrupt(); } public boolean isMultiFile() { // we can use visible state for this one return separateSeqCheck.isVisible(); } /** * Enable multi file mode for option panel */ public void setMultiFile(boolean value) { // no change if (multiFile == value) return; multiFile = value; final GridBagLayout layout = (GridBagLayout) optionsPanel.getLayout(); final int margin = value ? 5 : 0; // layout modification layout.getConstraints(loadInSeparatedLabel).insets.bottom = margin; layout.getConstraints(separateSeqCheck).insets.bottom = margin; layout.getConstraints(autoOrderLabel).insets.bottom = margin; layout.getConstraints(autoOrderCheck).insets.bottom = margin; layout.getConstraints(resolutionFixLabel).insets.bottom = 5 - margin; layout.getConstraints(resolutionLevelLabel).insets.bottom = 5 - margin; layout.getConstraints(resolutionSlider).insets.bottom = 5 - margin; layout.getConstraints(xyRegionLabel).insets.bottom = 5 - margin; layout.getConstraints(xyRegionComp).insets.bottom = 5 - margin; layout.getConstraints(xyRegionLoadingCheck).insets.bottom = 5 - margin; layout.getConstraints(zRangeLabel).insets.bottom = 5 - margin; layout.getConstraints(zRangeComp).insets.bottom = 5 - margin; layout.getConstraints(tRangeLabel).insets.bottom = 5 - margin; layout.getConstraints(tRangeComp).insets.bottom = 5 - margin; layout.getConstraints(channelLabel).insets.bottom = 5 - margin; layout.getConstraints(channelSpinner).insets.bottom = 5 - margin; loadInSeparatedLabel.setVisible(value); separateSeqCheck.setVisible(value); autoOrderLabel.setVisible(value); autoOrderCheck.setVisible(value); resolutionFixLabel.setVisible(!value); resolutionLevelLabel.setVisible(!value); resolutionSlider.setVisible(!value); xyRegionLabel.setVisible(!value); xyRegionComp.setVisible(!value); xyRegionLoadingCheck.setVisible(!value); zRangeLabel.setVisible(!value); zRangeComp.setVisible(!value); tRangeLabel.setVisible(!value); tRangeComp.setVisible(!value); channelLabel.setVisible(!value); channelSpinner.setVisible(!value); // by default we enable auto ordering with multi file setAutoOrderEnabled(value); // multiple file --> no preview if (value) { cancelPreview(); metadata = null; metadataFieldsOk = true; if (previewThread != null) { try { previewThread.join(); } catch (InterruptedException e) { // ignore } } preview.setImage(ResourceUtil.ICON_PICTURE); preview.setInfos("Multiple selection..."); } } /** * We are closing the Open Dialog. * Ensure metadata are correctly loaded (it's important that this method is called from EDT) */ public void closingFromEDT() { if (previewThread == null) return; // interrupt process from thread previewThread.interrupt(); // need update metadata fields if (!metadataFieldsOk) { // get fileId final String fileId = previewThread.fileId; final List<SequenceFileImporter> importers = Loader.getSequenceFileImporters(fileId); for (SequenceFileImporter importer : importers) { try { if (importer.open(fileId, 0)) { try { metadata = importer.getMetaData(); // update panel (we are on EDT) updatePanel(); // done return; } finally { importer.close(); } } } catch (UnsupportedFormatException e) { // try next importer... } catch (RuntimeException e) { // try next importer... } catch (IOException e) { // try next importer... } // next importer } } } }