/* * #%L * BSD implementations of Bio-Formats readers and writers * %% * Copyright (C) 2005 - 2015 Open Microscopy Environment: * - Board of Regents of the University of Wisconsin-Madison * - Glencoe Software, Inc. * - University of Dundee * %% * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * #L% */ package loci.formats.gui; import java.lang.reflect.InvocationTargetException; import java.util.Vector; import javax.swing.JFileChooser; import javax.swing.SwingUtilities; import javax.swing.filechooser.FileFilter; import loci.formats.FileStitcher; import loci.formats.IFormatHandler; import loci.formats.IFormatReader; import loci.formats.IFormatWriter; import loci.formats.ImageReader; import loci.formats.ImageWriter; import loci.formats.ReaderWrapper; import loci.formats.WriterWrapper; /** * A utility class for working with graphical user interfaces. * * @author Curtis Rueden ctrueden at wisc.edu */ public final class GUITools { // -- Fields -- /** String to use for "all types" combination filter. */ private static final String ALL_TYPES = "All supported file types"; // -- Constructor -- private GUITools() { } // -- File chooser -- /** Constructs a list of file filters for the given file format handler. */ public static FileFilter[] buildFileFilters(IFormatHandler handler) { FileFilter[] filters = null; // unwrap reader while (true) { if (handler instanceof ReaderWrapper) { handler = ((ReaderWrapper) handler).getReader(); } else if (handler instanceof FileStitcher) { handler = ((FileStitcher) handler).getReader(); } else if (handler instanceof WriterWrapper) { handler = ((WriterWrapper) handler).getWriter(); } else break; } // handle special cases of ImageReader and ImageWriter if (handler instanceof ImageReader) { ImageReader imageReader = (ImageReader) handler; IFormatReader[] readers = imageReader.getReaders(); Vector filterList = new Vector(); Vector comboList = new Vector(); for (int i=0; i<readers.length; i++) { filterList.add(new FormatFileFilter(readers[i])); // NB: Some readers need to open a file to determine if it is the // proper type, when the extension alone is insufficient to // distinguish. This behavior is fine for individual filters, but not // for ImageReader's combination filter, because it makes the combo // filter too slow. So rather than composing the combo filter from // FormatFileFilters, we use faster but less accurate // ExtensionFileFilters instead. String[] suffixes = readers[i].getSuffixes(); String format = readers[i].getFormat(); comboList.add(new ExtensionFileFilter(suffixes, format)); } comboList.add(new NoExtensionFileFilter()); FileFilter combo = makeComboFilter(sortFilters(comboList)); if (combo != null) filterList.add(combo); filters = sortFilters(filterList); } else if (handler instanceof ImageWriter) { IFormatWriter[] writers = ((ImageWriter) handler).getWriters(); Vector filterList = new Vector(); for (int i=0; i<writers.length; i++) { String[] suffixes = writers[i].getSuffixes(); String format = writers[i].getFormat(); filterList.add(new ExtensionFileFilter(suffixes, format)); } filters = sortFilters(filterList); } // handle default reader and writer cases else if (handler instanceof IFormatReader) { IFormatReader reader = (IFormatReader) handler; filters = new FileFilter[] {new FormatFileFilter(reader)}; } else { String[] suffixes = handler.getSuffixes(); String format = handler.getFormat(); filters = new FileFilter[] {new ExtensionFileFilter(suffixes, format)}; } return filters; } /** Constructs a file chooser for the given file format handler. */ public static JFileChooser buildFileChooser(IFormatHandler handler) { return buildFileChooser(handler, true); } /** * Constructs a file chooser for the given file format handler. * If preview flag is set, chooser has an preview pane showing * a thumbnail and other information for the selected file. */ public static JFileChooser buildFileChooser(IFormatHandler handler, boolean preview) { return buildFileChooser(buildFileFilters(handler), preview); } /** * Builds a file chooser with the given file filters, * as well as an "All supported file types" combo filter. */ public static JFileChooser buildFileChooser(final FileFilter[] filters) { return buildFileChooser(filters, true); } /** * Builds a file chooser with the given file filters, as well as an "All * supported file types" combo filter, if one is not already specified. * @param preview If set, chooser has a preview pane showing a * thumbnail and other information for the selected file. */ public static JFileChooser buildFileChooser(final FileFilter[] filters, final boolean preview) { // NB: construct JFileChooser in the AWT worker thread, to avoid deadlocks final JFileChooser[] jfc = new JFileChooser[1]; Runnable r = new Runnable() { @Override public void run() { JFileChooser fc = new JFileChooser(System.getProperty("user.dir")); FileFilter[] ff = sortFilters(filters); FileFilter combo = null; if (ff.length > 0 && ff[0] instanceof ComboFileFilter) { // check for existing "All supported file types" filter ComboFileFilter cff = (ComboFileFilter) ff[0]; if (ALL_TYPES.equals(cff.getDescription())) combo = cff; } // make an "All supported file types" filter if we don't have one yet if (combo == null) { combo = makeComboFilter(ff); if (combo != null) fc.addChoosableFileFilter(combo); } for (int i=0; i<ff.length; i++) fc.addChoosableFileFilter(ff[i]); if (combo != null) fc.setFileFilter(combo); if (preview) new PreviewPane(fc); jfc[0] = fc; } }; if (Thread.currentThread().getName().startsWith("AWT-EventQueue")) { // current thread is the AWT event queue thread; just execute the code r.run(); } else { // execute the code with the AWT event thread try { SwingUtilities.invokeAndWait(r); } catch (InterruptedException exc) { return null; } catch (InvocationTargetException exc) { return null; } } return jfc[0]; } // -- Helper methods -- /** * Creates an "All supported file types" combo filter * encompassing all of the given filters. */ private static FileFilter makeComboFilter(FileFilter[] filters) { return filters.length > 1 ? new ComboFileFilter(filters, ALL_TYPES) : null; } /** * Sorts the given list of file filters, keeping the "All supported * file types" combo filter (if any) at the front of the list. */ private static FileFilter[] sortFilters(FileFilter[] filters) { filters = ComboFileFilter.sortFilters(filters); shuffleAllTypesToFront(filters); return filters; } /** * Sorts the given list of file filters, keeping the "All supported * file types" combo filter (if any) at the front of the list. */ private static FileFilter[] sortFilters(Vector filterList) { FileFilter[] filters = ComboFileFilter.sortFilters(filterList); shuffleAllTypesToFront(filters); return filters; } /** * Looks for an "All supported file types" combo filter * and shuffles it to the front of the list. */ private static void shuffleAllTypesToFront(FileFilter[] filters) { for (int i=0; i<filters.length; i++) { if (filters[i] instanceof ComboFileFilter) { if (ALL_TYPES.equals(filters[i].getDescription())) { FileFilter f = filters[i]; for (int j=i; j>=1; j--) filters[j] = filters[j - 1]; filters[0] = f; break; } } } } }