// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.plugins.czechaddress.proposal; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.swing.JTree; import javax.swing.ListModel; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import org.openstreetmap.josm.data.osm.OsmPrimitive; import org.openstreetmap.josm.plugins.czechaddress.CzechAddressPlugin; import org.openstreetmap.josm.plugins.czechaddress.PrimUtils; /** * Class encapsulating an {@link OsmPrimitive} and a list of proposed * {@link Proposal}. * * List of these objects are usually stored in a {@link ProposalDatabase}, * which also provides means of displaying is in a {@link JTree}. * * @author Radomír Černoch radomir.cernoch@gmail.com * @see ProposalDatabase * @see OsmPrimitive * @see Proposal */ public class ProposalContainer implements ListModel<Proposal>, Comparable<ProposalContainer> { /** * List of listeners for implementing the {@code ListModel}. */ private List<ListDataListener> listeners = new ArrayList<>(); /** * The internal reference to an {@link OsmPrimitive}, to which the * proposals shall be applied. */ protected OsmPrimitive target; /** * Default constructor setting the internal reference to target * {@code OsmPrimitive}. */ public ProposalContainer(OsmPrimitive target) { this.target = target; } /** * Sets a new target, to which the {@link Proposal}s should be applied. */ public void setTarget(OsmPrimitive newTarget) { this.target = newTarget; } /** * Returns the target, to which the {@link Proposal}s should be applied. */ public OsmPrimitive getTarget() { return target; } //============================================================================== /** * The list of proposals to be applied to encapsulated primitive. */ protected List<Proposal> proposals = new ArrayList<>(); /** * Adds a new {@link Proposal}. * @param a new alternation to be added */ public void addProposal(Proposal a) { proposals.add(a); ListDataEvent evt = new ListDataEvent( this, ListDataEvent.INTERVAL_ADDED, proposals.size()-1, proposals.size()-1); for (ListDataListener l : listeners) { l.contentsChanged(evt); } } /** * Adds a new set of {@link Proposal}s. * @param a collection of proposals to be added */ public void addProposals(Collection<Proposal> a) { int index1 = proposals.size(); proposals.addAll(a); int index2 = proposals.size()-1; ListDataEvent evt = new ListDataEvent( this, ListDataEvent.INTERVAL_ADDED, index1, index2); for (ListDataListener l : listeners) { l.contentsChanged(evt); } } /** * Removes the give proposal from the list of proposals. * @param proposal the proposal to be removed */ public void removeProposal(Proposal proposal) { int index = proposals.indexOf(proposal); if (index == -1) return; proposals.remove(index); ListDataEvent evt = new ListDataEvent( this, ListDataEvent.INTERVAL_REMOVED, index, index); for (ListDataListener l : listeners) { l.contentsChanged(evt); } } /** * Replaces the internal list of proposals with the given one. * @param a collection of proposals to be added */ public void setProposals(List<Proposal> proposals) { this.proposals = proposals; ListDataEvent evt = new ListDataEvent( this, ListDataEvent.CONTENTS_CHANGED, 0, proposals.size()-1); for (ListDataListener l : listeners) { l.contentsChanged(evt); } } /** * @return the list of proposed proposals. */ public List<Proposal> getProposals() { return proposals; } /** * Removes all proposals. */ public void clear() { ListDataEvent evt = new ListDataEvent( this, ListDataEvent.INTERVAL_REMOVED, 0, proposals.size()-1); proposals.clear(); for (ListDataListener l : listeners) { l.contentsChanged(evt); } } /** * Applies all stored {@link Proposal}s to the target {@link OsmPrimitive}. */ public void applyAll() { for (Proposal proposal : proposals) { proposal.apply(target); } } //============================================================================== /** * Tries to decode the name of the referenced primitive. Otherwise * it returns the ID of that primitive. * * Currently the string is in Czech language (see {@link CzechAddressPlugin}). */ @Override public String toString() { return target.toString(); } @Override public int getSize() { return proposals.size(); } @Override public Proposal getElementAt(int index) { return proposals.get(index); } @Override public void addListDataListener(ListDataListener l) { listeners.add(l); } @Override public void removeListDataListener(ListDataListener l) { listeners.remove(l); } @Override public int compareTo(ProposalContainer o) { return PrimUtils.comparator.compare(this.target, o.target); } }