// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.turnrestrictions.list;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.AbstractListModel;
import javax.swing.DefaultListSelectionModel;
import org.openstreetmap.josm.data.osm.NameFormatter;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.data.osm.Relation;
import org.openstreetmap.josm.gui.DefaultNameFormatter;
/**
* This is a list model for a list of turn restrictions.
*
*/
public class TurnRestrictionsListModel extends AbstractListModel<Relation> {
private final ArrayList<Relation> turnrestrictions = new ArrayList<>();
private DefaultListSelectionModel selectionModel;
/**
* Creates the model
*
* @param selectionModel the selection model used in the turn restriction list
*/
public TurnRestrictionsListModel(DefaultListSelectionModel selectionModel) {
this.selectionModel = selectionModel;
}
/**
* Replies the turn restriction at position {@code idx} in the list.
*
* @param idx the index
* @return the turn restriction at position {@code idx} in the list.
*/
public Relation getTurnRestriction(int idx) {
return turnrestrictions.get(idx);
}
/**
* Sorts the turn restrictions in this model
*/
public void sort() {
Collections.sort(
turnrestrictions,
new Comparator<Relation>() {
NameFormatter formatter = DefaultNameFormatter.getInstance();
@Override
public int compare(Relation r1, Relation r2) {
return r1.getDisplayName(formatter).compareTo(r2.getDisplayName(formatter));
}
}
);
}
protected boolean isValid(Relation r) {
return !r.isDeleted() && r.isVisible() && !r.isIncomplete();
}
/**
* Replies true if the primitive {@code primitive} represents
* an OSM turn restriction.
*
* @param primitive the primitive
* @return true if the primitive {@code primitive} represents
* an OSM turn restriction; false, otherwise
*/
protected boolean isTurnRestriction(OsmPrimitive primitive) {
if (primitive == null) return false;
if (!(primitive instanceof Relation)) return false;
String type = primitive.get("type");
if (type == null || !type.equals("restriction")) return false;
return true;
}
/**
* Populates the model with the turn restrictions in {@code turnrestrictions}.
*
* @param turnrestrictions the turn restrictions
*/
public void setTurnRestrictions(Collection<Relation> turnrestrictions) {
List<Relation> sel = getSelectedTurnRestrictions();
this.turnrestrictions.clear();
if (turnrestrictions == null) {
selectionModel.clearSelection();
fireContentsChanged(this, 0, getSize());
return;
}
for (Relation r: turnrestrictions) {
if (isValid(r) && isTurnRestriction(r)) {
this.turnrestrictions.add(r);
}
}
sort();
fireIntervalAdded(this, 0, getSize());
setSelectedTurnRestrictions(sel);
}
/**
* Add all turn restrictions in <code>addedPrimitives</code> to the model for the
* relation list dialog
*
* @param addedPrimitives the collection of added primitives. May include nodes,
* ways, and relations.
*/
public void addTurnRestrictions(Collection<? extends OsmPrimitive> addedPrimitives) {
boolean added = false;
for (OsmPrimitive p: addedPrimitives) {
if (!isTurnRestriction(p)) {
continue;
}
Relation r = (Relation) p;
if (!isValid(r)) continue;
if (turnrestrictions.contains(r)) {
continue;
}
turnrestrictions.add(r);
added = true;
}
if (added) {
List<Relation> sel = getSelectedTurnRestrictions();
sort();
fireIntervalAdded(this, 0, getSize());
setSelectedTurnRestrictions(sel);
}
}
/**
* Removes all turn restrictions in <code>removedPrimitives</code> from the model
*
* @param removedPrimitives the removed primitives. May include nodes, ways,
* and relations
*/
public void removeTurnRestrictions(Collection<? extends OsmPrimitive> removedPrimitives) {
if (removedPrimitives == null) return;
Set<Relation> removedTurnRestrictions = new HashSet<>();
for (OsmPrimitive p: removedPrimitives) {
if (!isTurnRestriction(p)) continue;
removedTurnRestrictions.add((Relation) p);
}
if (removedTurnRestrictions.isEmpty()) return;
int size = turnrestrictions.size();
turnrestrictions.removeAll(removedTurnRestrictions);
if (size != turnrestrictions.size()) {
List<Relation> sel = getSelectedTurnRestrictions();
sort();
fireContentsChanged(this, 0, getSize());
setSelectedTurnRestrictions(sel);
}
}
@Override
public Relation getElementAt(int index) {
return turnrestrictions.get(index);
}
@Override
public int getSize() {
return turnrestrictions.size();
}
/**
* Replies the list of selected, non-new relations. Empty list,
* if there are no selected, non-new relations.
*
* @return the list of selected, non-new relations.
*/
public List<Relation> getSelectedNonNewRelations() {
ArrayList<Relation> ret = new ArrayList<>();
for (int i = 0; i < getSize(); i++) {
if (!selectionModel.isSelectedIndex(i)) {
continue;
}
if (turnrestrictions.get(i).isNew()) {
continue;
}
ret.add(turnrestrictions.get(i));
}
return ret;
}
/**
* Replies the list of selected turn restrictions. Empty list,
* if there are no selected turn restrictions.
*
* @return the list of selected turn restrictions
*/
public List<Relation> getSelectedTurnRestrictions() {
ArrayList<Relation> ret = new ArrayList<>();
for (int i = 0; i < getSize(); i++) {
if (!selectionModel.isSelectedIndex(i)) {
continue;
}
ret.add(turnrestrictions.get(i));
}
return ret;
}
/**
* Sets the selected turn restrictions
*
* @return sel the list of selected turn restrictions
*/
public void setSelectedTurnRestrictions(List<Relation> sel) {
selectionModel.clearSelection();
if (sel == null || sel.isEmpty())
return;
for (Relation r: sel) {
int i = turnrestrictions.indexOf(r);
if (i < 0) {
continue;
}
selectionModel.addSelectionInterval(i, i);
}
}
/**
* Returns the index of a turn restriction
*
* @return index of relation (-1, if not found)
*/
public int getTurnRestrictionIndex(Relation tr) {
int i = turnrestrictions.indexOf(tr);
if (i < 0) return -1;
return i;
}
}