/* * Geotoolkit.org - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2009-2012, Open Source Geospatial Foundation (OSGeo) * (C) 2009-2012, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library 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 * Lesser General Public License for more details. */ package org.geotoolkit.gui.swing.image; import java.util.Map; import java.util.Set; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Collection; import java.util.LinkedHashSet; import javax.swing.JComboBox; import javax.imageio.spi.IIORegistry; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.spi.ImageWriterSpi; import org.apache.sis.util.ArraysExt; /** * An element to be displayed in a list of image formats. A list of such elements is * created by the {@link #list} method. Those elements are designed for use in a Swing * combo box. * * @author Martin Desruisseaux (Geomatys) * @version 3.00 * * @since 3.00 * @module */ final class ImageFormatEntry implements Comparable<ImageFormatEntry> { /** * The image reader for this entry. */ private ImageReaderSpi reader; /** * The image reader for this entry. */ private ImageWriterSpi writer; /** * The file format. Also used as the description to be displayed in the combo box * in current version. */ private String format; /** * Creates a new entry. */ private ImageFormatEntry() { } /** * Creates a new list of entries in a combo box. This method returns elements * that describes formats available both for reading and for writing. * * @param defaultFormat The format to select by default (can not be {@code null}). */ static JComboBox<ImageFormatEntry> comboBox(final String defaultFormat) { final Set<ImageFormatEntry> preferred = new LinkedHashSet<>(); final JComboBox<ImageFormatEntry> formatChoices = new JComboBox<>(list(defaultFormat, preferred)); final Iterator<ImageFormatEntry> it = preferred.iterator(); if (it.hasNext()) { formatChoices.setSelectedItem(it.next()); // Select only one, ignore the other ones. } return formatChoices; } /** * Creates a new list of entries. This method returns elements that describes formats * available both for reading and for writing. * * @param defaultFormat The format to select by default (can not be {@code null}). * @param preferred Where to store the entry for the preferred format. */ private static ImageFormatEntry[] list(final String defaultFormat, final Set<ImageFormatEntry> preferred) { final Map<String,ImageFormatEntry> formatsDone = new HashMap<>(); final IIORegistry registry = IIORegistry.getDefaultInstance(); /* * Get the list of writers first, because they are typically less numerous * than readers (e.g. they were no GIF writers before the patent get expired). */ skip: for (final Iterator<ImageWriterSpi> it=registry.getServiceProviders(ImageWriterSpi.class, true); it.hasNext();) { final ImageWriterSpi spi = it.next(); final ImageFormatEntry entry = new ImageFormatEntry(); for (final String format : spi.getFormatNames()) { final ImageFormatEntry old = formatsDone.put(format, entry); if (old != null) { // Avoid declaring the same format twice (e.g. declaring // both the JSE and JAI ImageReaders for the PNG format). formatsDone.put(format, old); continue skip; } entry.addFormat(format); if (defaultFormat.equalsIgnoreCase(format)) { preferred.add(entry); } } entry.writer = spi; } /* * Associate a reader to the entries built in the previous step. */ skip: for (final Iterator<ImageReaderSpi> it=registry.getServiceProviders(ImageReaderSpi.class, true); it.hasNext();) { final ImageReaderSpi spi = it.next(); for (final String format : spi.getFormatNames()) { final ImageFormatEntry entry = formatsDone.get(format); if (entry != null) { if (entry.reader == null) { entry.reader = spi; } else if (entry.reader != spi) { // Avoid declaring the same format twice (e.g. declaring // both the JSE and JAI ImageReaders for the PNG format). continue skip; } entry.addFormat(format); } } } /* * Gets the array of entries, removing the one without readers. * We wraps in a HashSet in order to remove duplicated values. */ final Collection<ImageFormatEntry> entries = new HashSet<>(formatsDone.values()); ImageFormatEntry[] array = entries.toArray(new ImageFormatEntry[entries.size()]); int count = 0; for (int i=0; i<array.length; i++) { final ImageFormatEntry entry = array[i]; if (entry.reader != null) { array[count++] = entry; } } array = ArraysExt.resize(array, count); preferred.retainAll(Arrays.asList(array)); Arrays.sort(array); return array; } /** * If the given string is longer than the current {@linkplain #format}, * replaces the current description by that format. */ private void addFormat(final String format) { this.format = longest(this.format, format); } /** * Selects the longest format string. If two of them * have the same length, favor the one in upper case. * * @param current The previous longest format string, or {@code null} if none. * @param candidate The format string which may be longuer than the previous one. * @return The format string which is the longest one up to date. */ static String longest(final String current, final String candidate) { if (current != null) { final int dl = candidate.length() - current.length(); if (dl < 0 || (dl == 0 && candidate.compareTo(current) >= 0)) { return current; } } return candidate; } /** * Returns the image format. */ public String getFormat() { return format; } /** * Returns the image reader provider. */ public ImageReaderSpi getReader() { return reader; } /** * Returns the image writer provider. */ public ImageWriterSpi getWriter() { return writer; } /** * Compares this entry with the given one for order. This is used for sorting * the entries to be displayed in a combo box. */ @Override public int compareTo(final ImageFormatEntry other) { return format.compareTo(other.format); } /** * Returns the string to be displayed in the combo box. */ @Override public String toString() { return format; } }