// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.gui.dialogs.changeset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.DefaultListModel;
import javax.swing.DefaultListSelectionModel;
import org.openstreetmap.josm.data.osm.Changeset;
import org.openstreetmap.josm.data.osm.ChangesetCache;
import org.openstreetmap.josm.data.osm.ChangesetCacheEvent;
import org.openstreetmap.josm.data.osm.ChangesetCacheListener;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.data.osm.Storage;
public class ChangesetListModel extends DefaultListModel<Changeset> implements ChangesetCacheListener {
private final transient List<Changeset> data = new ArrayList<>();
private final transient Storage<Changeset> shownChangesets = new Storage<>(true);
private final DefaultListSelectionModel selectionModel;
public ChangesetListModel(DefaultListSelectionModel selectionModel) {
this.selectionModel = selectionModel;
}
public Set<Changeset> getSelectedChangesets() {
Set<Changeset> ret = new HashSet<>();
for (int i = 0; i < getSize(); i++) {
if (selectionModel.isSelectedIndex(i)) {
ret.add(data.get(i));
}
}
return ret;
}
public Set<Integer> getSelectedChangesetIds() {
Set<Integer> ret = new HashSet<>();
for (int i = 0; i < getSize(); i++) {
if (selectionModel.isSelectedIndex(i)) {
ret.add(data.get(i).getId());
}
}
return ret;
}
public void setSelectedChangesets(Collection<Changeset> changesets) {
selectionModel.setValueIsAdjusting(true);
selectionModel.clearSelection();
if (changesets != null) {
for (Changeset cs: changesets) {
int idx = data.indexOf(cs);
if (idx >= 0) {
selectionModel.addSelectionInterval(idx, idx);
}
}
}
selectionModel.setValueIsAdjusting(false);
}
protected void setChangesets(Collection<Changeset> changesets) {
shownChangesets.clear();
if (changesets != null) {
shownChangesets.addAll(changesets);
}
updateModel();
}
private void updateModel() {
Set<Changeset> sel = getSelectedChangesets();
data.clear();
data.addAll(shownChangesets);
ChangesetCache cache = ChangesetCache.getInstance();
for (Changeset cs: data) {
if (cache.contains(cs) && cache.get(cs.getId()) != cs) {
cs.mergeFrom(cache.get(cs.getId()));
}
}
sort();
fireIntervalAdded(this, 0, getSize());
setSelectedChangesets(sel);
}
public void initFromChangesetIds(Collection<Integer> ids) {
if (ids == null || ids.isEmpty()) {
setChangesets(null);
return;
}
Set<Changeset> changesets = new HashSet<>(ids.size());
for (int id: ids) {
if (id <= 0) {
continue;
}
changesets.add(new Changeset(id));
}
setChangesets(changesets);
}
public void initFromPrimitives(Collection<? extends OsmPrimitive> primitives) {
if (primitives == null) {
setChangesets(null);
return;
}
Set<Changeset> changesets = new HashSet<>();
for (OsmPrimitive p: primitives) {
if (p.getChangesetId() <= 0) {
continue;
}
changesets.add(new Changeset(p.getChangesetId()));
}
setChangesets(changesets);
}
public void initFromDataSet(DataSet ds) {
if (ds == null) {
setChangesets(null);
return;
}
Set<Changeset> changesets = new HashSet<>();
for (OsmPrimitive p: ds.allPrimitives()) {
if (p.getChangesetId() <= 0) {
continue;
}
changesets.add(new Changeset(p.getChangesetId()));
}
setChangesets(changesets);
}
@Override
public Changeset getElementAt(int idx) {
return data.get(idx);
}
@Override
public int getSize() {
return data.size();
}
protected void sort() {
data.sort(Comparator.comparingInt(Changeset::getId).reversed());
}
/**
* Replies true if there is at least one selected open changeset
*
* @return true if there is at least one selected open changeset
*/
public boolean hasSelectedOpenChangesets() {
return !getSelectedOpenChangesets().isEmpty();
}
/**
* Replies the selected open changesets
*
* @return the selected open changesets
*/
public List<Changeset> getSelectedOpenChangesets() {
List<Changeset> ret = new ArrayList<>();
for (int i = 0; i < getSize(); i++) {
if (selectionModel.isSelectedIndex(i)) {
Changeset cs = data.get(i);
if (cs.isOpen()) {
ret.add(cs);
}
}
}
return ret;
}
/* ---------------------------------------------------------------------------- */
/* Interface ChangesetCacheListener */
/* ---------------------------------------------------------------------------- */
@Override
public void changesetCacheUpdated(ChangesetCacheEvent event) {
Set<Changeset> sel = getSelectedChangesets();
for (Changeset cs: event.getAddedChangesets()) {
int idx = data.indexOf(cs);
if (idx >= 0 && data.get(idx) != cs) {
data.get(idx).mergeFrom(cs);
}
}
for (Changeset cs: event.getUpdatedChangesets()) {
int idx = data.indexOf(cs);
if (idx >= 0 && data.get(idx) != cs) {
data.get(idx).mergeFrom(cs);
}
}
for (Changeset cs: event.getRemovedChangesets()) {
int idx = data.indexOf(cs);
if (idx >= 0) {
// replace with an incomplete changeset
data.set(idx, new Changeset(cs.getId()));
}
}
fireContentsChanged(this, 0, getSize());
setSelectedChangesets(sel);
}
}