/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2005-2008, Open Source Geospatial Foundation (OSGeo) * * 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.geotools.gui.swing.referencing; // J2SE dependencies import java.util.List; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import javax.swing.ComboBoxModel; import javax.swing.AbstractListModel; // OpenGIS dependencies import org.opengis.referencing.AuthorityFactory; import org.opengis.referencing.FactoryException; /** * A list of {@link Code}s. This implementation will try to fetch the codes only when * first needed. Keep in mind that the collection provided to the constructor may be * database backed (not a usual implementation from {@code java.util} package), so it * is worth to do lazy loading here. * * @source $URL$ * @version $Id$ * @author Martin Desruisseaux (IRD) */ final class CodeList extends AbstractListModel implements ComboBoxModel { /** * The authority factory, or {@code null} if disposed. */ private AuthorityFactory factory; /** * The collection of authority codes, or {@code null} if disposed. */ private Collection/*<String>*/ codes; /** * An iterator over the codes, or {@code null} if not yet created or disposed. */ private Iterator iterator; /** * The authority codes as {@link Code} objects. */ private final List/*<Code>*/ extracted = new ArrayList(); /** * The selected item, or {@code null} if none. */ private Code selected; /** * Creates a list for the given codes. */ public CodeList(final AuthorityFactory factory, final Class type) throws FactoryException { this.factory = factory; this.codes = factory.getAuthorityCodes(type); if (!codes.isEmpty()) { // Note: testing if (!isEmpty()) is much facter than if (size() > 0) selected = (Code) getElementAt(0); } } /** * Returns the length of the list. */ public int getSize() { return (codes != null) ? codes.size() : extracted.size(); } /** * Returns the value at the specified index. * * @todo Change to return type to {@link Code} when we will be allowed to compile for J2SE 1.5. */ public Object getElementAt(final int index) { if (codes != null) { if (iterator == null) { iterator = codes.iterator(); } int size; while (index >= (size=extracted.size())) { if (!iterator.hasNext()) { assert extracted.size() == codes.size(); iterator = null; codes = null; factory = null; break; } extracted.add(new Code(factory, (String) iterator.next(), size)); } } return (index>=0 && index<extracted.size()) ? extracted.get(index) : null; } /** * Returns the selected item. * * @todo Change to return type to {@link Code} when we will be allowed to compile for J2SE 1.5. */ public Object getSelectedItem() { return selected; } /** * Set the selected item. */ public void setSelectedItem(final Object code) { selected = (Code) code; int index = selected.index; fireContentsChanged(this, index, index); } /** * Returns an item that can be used as a prototype in a combo box. This operation is * expansive and should be run only once. * * @see javax.swing.JComboBox#setPrototypeDisplayValue */ public String getPrototypeItem() { final int size = getSize(); String prototype = ""; for (int i=0; i<size; i++) { final String candidate = getElementAt(i).toString(); if (candidate.length() > prototype.length()) { prototype = candidate; } } return prototype; } }