/*
* #%L
* Bio-Formats Plugins for ImageJ: a collection of ImageJ plugins including the
* Bio-Formats Importer, Bio-Formats Exporter, Bio-Formats Macro Extensions,
* Data Browser and Stack Slicer.
* %%
* Copyright (C) 2006 - 2015 Open Microscopy Environment:
* - Board of Regents of the University of Wisconsin-Madison
* - Glencoe Software, Inc.
* - University of Dundee
* %%
* This program 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 2 of the
* License, or (at your option) any later version.
*
* This program 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 this program. If not, see
* <http://www.gnu.org/licenses/gpl-2.0.html>.
* #L%
*/
package loci.plugins.in;
import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import java.awt.Checkbox;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Label;
import java.awt.Panel;
import java.awt.event.ItemEvent;
import java.io.File;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Vector;
import javax.swing.Box;
import javax.swing.JPanel;
import ij.IJ;
import ij.gui.GenericDialog;
import loci.common.Location;
import loci.formats.FilePattern;
import loci.formats.FilePatternBlock;
/**
* Bio-Formats Importer file pattern dialog box.
*/
public class FilePatternDialog extends ImporterDialog {
// -- Fields --
private FilePattern fp;
private String originalID;
private int[] paddingZeros;
// -- Constructor --
/** Creates a file pattern dialog for the Bio-Formats Importer. */
public FilePatternDialog(ImportProcess process) {
super(process);
}
// -- ImporterDialog methods --
@Override
protected boolean needPrompt() {
return !process.isWindowless() && options.isGroupFiles();
}
@Override
protected GenericDialog constructDialog() {
// CTR - CHECK
Location idLoc = new Location(options.getId());
String id = FilePattern.findPattern(idLoc);
if (id == null) {
if (!options.isQuiet()) {
IJ.showMessage("Bio-Formats",
"Warning: Bio-Formats was unable to determine a grouping that\n" +
"includes the file you chose. The most common reason for this\n" +
"situation is that the folder contains extraneous files with\n" +
"similar names and numbers that confuse the detection algorithm.\n" +
" \n" +
"For example, if you have multiple datasets in the same folder\n" +
"named series1_z*_c*.tif, series2_z*_c*.tif, etc., Bio-Formats\n" +
"may try to group all such files into a single series.\n" +
" \n" +
"For best results, put each image series's files in their own\n" +
"folder, or type in a file pattern manually.\n");
}
id = idLoc.getAbsolutePath();
}
// construct dialog
GenericDialog gd = new GenericDialog("Bio-Formats File Stitching") {
@Override
public void itemStateChanged(ItemEvent e) {
super.itemStateChanged(e);
Object source = e.getSource();
if (!(source instanceof Checkbox)) {
return;
}
boolean selected = e.getStateChange() == ItemEvent.SELECTED;
Vector checkboxes = getCheckboxes();
for (Object checkbox : checkboxes) {
if (!checkbox.equals(source)) {
if (selected) {
((Checkbox) checkbox).setState(false);
}
}
else if (!selected && checkbox.equals(source)) {
((Checkbox) checkbox).setState(true);
}
}
}
};
gd.addMessage(
"The list of files to be grouped can be specified in one of the following ways:");
// option one
int len = id.length() + 1;
if (len > 80) len = 80;
originalID = id;
fp = new FilePattern(id);
String[] prefixes = fp.getPrefixes();
if (prefixes.length > 0) {
gd.addCheckbox("Dimensions", true);
int[] counts = fp.getCount();
paddingZeros = new int[counts.length];
String[][] elements = fp.getElements();
BigInteger[] first = fp.getFirst();
BigInteger[] step = fp.getStep();
for (int i=0; i<prefixes.length; i++) {
String prefix = "Axis_" + (i + 1);
gd.addStringField(prefix + "_number_of_images", "" + counts[i]);
gd.addStringField(prefix + "_axis_first_image", first[i].toString());
gd.addStringField(prefix + "_axis_increment", step[i].toString());
try {
paddingZeros[i] = elements[i][0].length() -
String.valueOf(Integer.parseInt(elements[i][0])).length();
}
catch (NumberFormatException e) { }
}
}
// option two
gd.addCheckbox("File_name", false);
gd.addStringField("contains", "");
// option three
gd.addCheckbox("Pattern", false);
gd.addStringField("name", id, len);
rebuild(gd);
return gd;
}
@Override
protected boolean harvestResults(GenericDialog gd) {
String[] counts = new String[fp.getPrefixes().length];
String[] firsts = new String[counts.length];
String[] increments = new String[counts.length];
int[] count = fp.getCount();
boolean useRanges = counts.length > 0 ? gd.getNextBoolean() : false;
boolean useRegex = gd.getNextBoolean();
for (int i=0; i<counts.length; i++) {
counts[i] = gd.getNextString();
firsts[i] = gd.getNextString();
increments[i] = gd.getNextString();
}
String contains = gd.getNextString();
String id = gd.getNextString();
if (useRegex) {
if (contains.trim().length() > 0) {
String dir =
originalID.substring(0, originalID.lastIndexOf(File.separator) + 1);
id = dir + ".*" + contains + ".*";
}
}
else if (useRanges) {
String pattern =
originalID.substring(0, originalID.lastIndexOf(File.separator) + 1);
for (int i=0; i<counts.length; i++) {
BigInteger first = new BigInteger(firsts[i]);
BigInteger fileCount = new BigInteger(counts[i]);
BigInteger increment = new BigInteger(increments[i]);
FilePatternBlock block = new FilePatternBlock(fp.getBlock(i));
fileCount = fileCount.subtract(BigInteger.ONE).multiply(increment);
pattern += fp.getPrefix(i);
pattern += "<";
int firstPadding = paddingZeros[i] - first.toString().length() + 1;
for (int zero=0; zero<firstPadding; zero++) {
pattern += "0";
}
pattern += first;
pattern += "-";
int lastPadding = paddingZeros[i] - fileCount.toString().length() + 1;
for (int zero=0; zero<lastPadding; zero++) {
pattern += "0";
}
pattern += fileCount;
pattern += ":";
pattern += increment;
pattern += ">";
}
id = pattern + fp.getSuffix();
}
options.setId(id);
return true;
}
private void rebuild(GenericDialog gd) {
// rebuild dialog to organize things more nicely
Vector checkboxes = gd.getCheckboxes();
Vector fields = gd.getStringFields();
final ArrayList<Label> labels = new ArrayList<Label>();
for (Component c : gd.getComponents()) {
if (c instanceof Label) {
labels.add((Label) c);
}
}
final String cols = "pref, 3dlu, pref, 3dlu, pref";
final StringBuilder sb = new StringBuilder("pref, 3dlu, pref");
for (int s=1; s<fields.size(); s++) {
sb.append(", 3dlu, pref");
}
final String rows = sb.toString();
final PanelBuilder builder = new PanelBuilder(new FormLayout(cols, rows));
final CellConstraints cc = new CellConstraints();
int row = 1;
if (checkboxes.size() > 2 && fields.size() > 2) {
builder.add((Component) labels.get(0), cc.xyw(1, row, 5));
row += 2;
builder.add((Component) checkboxes.get(0), cc.xy(1, row));
for (int i=0; i<fields.size()-2; i++) {
builder.add((Component) labels.get(i + 1), cc.xy(3, row));
builder.add((Component) fields.get(i), cc.xy(5, row));
row += 2;
}
}
builder.add((Component) checkboxes.get(checkboxes.size() - 2), cc.xy(1, row));
builder.add((Component) labels.get(labels.size() - 2), cc.xy(3, row));
builder.add((Component) fields.get(fields.size() - 2), cc.xy(5, row));
row += 2;
builder.add((Component) checkboxes.get(checkboxes.size() - 1), cc.xy(1, row));
builder.add((Component) labels.get(labels.size() - 1), cc.xy(3, row));
builder.add((Component) fields.get(fields.size() - 1), cc.xy(5, row));
row += 2;
final JPanel masterPanel = builder.getPanel();
gd.removeAll();
GridBagLayout gdl = (GridBagLayout) gd.getLayout();
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 3;
gbc.gridheight = fields.size();
gdl.setConstraints(masterPanel, gbc);
gd.add(masterPanel);
gd.setBackground(Color.white); // HACK: workaround for JPanel in a Dialog
}
}