001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-2006, Geotools Project Managment Committee (PMC)
005: * (C) 2005, Institut de Recherche pour le Développement
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: */
017: package org.geotools.gui.swing.referencing;
018:
019: // J2SE dependencies
020: import java.util.List;
021: import java.util.ArrayList;
022: import java.util.Collection;
023: import java.util.Iterator;
024: import javax.swing.ComboBoxModel;
025: import javax.swing.AbstractListModel;
026:
027: // OpenGIS dependencies
028: import org.opengis.referencing.AuthorityFactory;
029: import org.opengis.referencing.FactoryException;
030:
031: /**
032: * A list of {@link Code}s. This implementation will try to fetch the codes only when
033: * first needed. Keep in mind that the collection provided to the constructor may be
034: * database backed (not a usual implementation from {@code java.util} package), so it
035: * is worth to do lazy loading here.
036: *
037: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/extension/widgets-swing/src/main/java/org/geotools/gui/swing/referencing/CodeList.java $
038: * @version $Id: CodeList.java 20883 2006-08-07 13:48:09Z jgarnett $
039: * @author Martin Desruisseaux
040: */
041: final class CodeList extends AbstractListModel implements ComboBoxModel {
042: /**
043: * The authority factory, or {@code null} if disposed.
044: */
045: private AuthorityFactory factory;
046:
047: /**
048: * The collection of authority codes, or {@code null} if disposed.
049: */
050: private Collection/*<String>*/codes;
051:
052: /**
053: * An iterator over the codes, or {@code null} if not yet created or disposed.
054: */
055: private Iterator iterator;
056:
057: /**
058: * The authority codes as {@link Code} objects.
059: */
060: private final List/*<Code>*/extracted = new ArrayList();
061:
062: /**
063: * The selected item, or {@code null} if none.
064: */
065: private Code selected;
066:
067: /**
068: * Creates a list for the given codes.
069: */
070: public CodeList(final AuthorityFactory factory, final Class type)
071: throws FactoryException {
072: this .factory = factory;
073: this .codes = factory.getAuthorityCodes(type);
074: if (!codes.isEmpty()) {
075: // Note: testing if (!isEmpty()) is much facter than if (size() > 0)
076: selected = (Code) getElementAt(0);
077: }
078: }
079:
080: /**
081: * Returns the length of the list.
082: */
083: public int getSize() {
084: return (codes != null) ? codes.size() : extracted.size();
085: }
086:
087: /**
088: * Returns the value at the specified index.
089: *
090: * @todo Change to return type to {@link Code} when we will be allowed to compile for J2SE 1.5.
091: */
092: public Object getElementAt(final int index) {
093: if (codes != null) {
094: if (iterator == null) {
095: iterator = codes.iterator();
096: }
097: int size;
098: while (index >= (size = extracted.size())) {
099: if (!iterator.hasNext()) {
100: assert extracted.size() == codes.size();
101: iterator = null;
102: codes = null;
103: factory = null;
104: break;
105: }
106: extracted.add(new Code(factory, (String) iterator
107: .next(), size));
108: }
109: }
110: return (index >= 0 && index < extracted.size()) ? extracted
111: .get(index) : null;
112: }
113:
114: /**
115: * Returns the selected item.
116: *
117: * @todo Change to return type to {@link Code} when we will be allowed to compile for J2SE 1.5.
118: */
119: public Object getSelectedItem() {
120: return selected;
121: }
122:
123: /**
124: * Set the selected item.
125: */
126: public void setSelectedItem(final Object code) {
127: selected = (Code) code;
128: int index = selected.index;
129: fireContentsChanged(this , index, index);
130: }
131:
132: /**
133: * Returns an item that can be used as a prototype in a combo box. This operation is
134: * expansive and should be run only once.
135: *
136: * @see javax.swing.JComboBox#setPrototypeDisplayValue
137: */
138: public String getPrototypeItem() {
139: final int size = getSize();
140: String prototype = "";
141: for (int i = 0; i < size; i++) {
142: final String candidate = getElementAt(i).toString();
143: if (candidate.length() > prototype.length()) {
144: prototype = candidate;
145: }
146: }
147: return prototype;
148: }
149: }
|