001 // License: GPL. For details, see LICENSE file.
002 package org.openstreetmap.josm.gui.dialogs.changeset;
003
004 import java.util.ArrayList;
005 import java.util.Collection;
006 import java.util.Collections;
007 import java.util.Comparator;
008 import java.util.HashSet;
009 import java.util.List;
010 import java.util.Set;
011
012 import javax.swing.DefaultListModel;
013 import javax.swing.DefaultListSelectionModel;
014
015 import org.openstreetmap.josm.data.osm.Changeset;
016 import org.openstreetmap.josm.data.osm.ChangesetCache;
017 import org.openstreetmap.josm.data.osm.ChangesetCacheEvent;
018 import org.openstreetmap.josm.data.osm.ChangesetCacheListener;
019 import org.openstreetmap.josm.data.osm.DataSet;
020 import org.openstreetmap.josm.data.osm.OsmPrimitive;
021 import org.openstreetmap.josm.data.osm.Storage;
022
023 public class ChangesetListModel extends DefaultListModel implements ChangesetCacheListener{
024 private final List<Changeset> data = new ArrayList<Changeset>();
025 private final Storage<Changeset> shownChangesets = new Storage<Changeset>(true);
026 private DefaultListSelectionModel selectionModel;
027
028 public ChangesetListModel(DefaultListSelectionModel selectionModel) {
029 this.selectionModel = selectionModel;
030 }
031
032 public Set<Changeset> getSelectedChangesets() {
033 Set<Changeset> ret = new HashSet<Changeset>();
034 for (int i=0; i < getSize(); i++) {
035 if (selectionModel.isSelectedIndex(i)) {
036 ret.add(data.get(i));
037 }
038 }
039 return ret;
040 }
041
042 public Set<Integer> getSelectedChangesetIds() {
043 Set<Integer> ret = new HashSet<Integer>();
044 for (int i=0; i < getSize(); i++) {
045 if (selectionModel.isSelectedIndex(i)) {
046 ret.add(data.get(i).getId());
047 }
048 }
049 return ret;
050 }
051
052 public void setSelectedChangesets(Collection<Changeset> changesets) {
053 selectionModel.clearSelection();
054 if (changesets == null) return;
055 for (Changeset cs: changesets) {
056 int idx = data.indexOf(cs);
057 if (idx < 0) {
058 continue;
059 }
060 selectionModel.addSelectionInterval(idx,idx);
061 }
062 }
063
064 protected void setChangesets(Collection<Changeset> changesets) {
065 shownChangesets.clear();
066 if (changesets != null) {
067 shownChangesets.addAll(changesets);
068 }
069 updateModel();
070 }
071
072 private void updateModel() {
073 Set<Changeset> sel = getSelectedChangesets();
074 data.clear();
075 data.addAll(shownChangesets);
076 ChangesetCache cache = ChangesetCache.getInstance();
077 for (Changeset cs: data) {
078 if (cache.contains(cs) && cache.get(cs.getId()) != cs) {
079 cs.mergeFrom(cache.get(cs.getId()));
080 }
081 }
082 sort();
083 fireIntervalAdded(this, 0, getSize());
084 setSelectedChangesets(sel);
085 }
086
087 public void initFromChangesetIds(Collection<Integer> ids) {
088 if (ids == null || ids.isEmpty()) {
089 setChangesets(null);
090 return;
091 }
092 Set<Changeset> changesets = new HashSet<Changeset>(ids.size());
093 for (int id: ids) {
094 if (id <= 0) {
095 continue;
096 }
097 changesets.add(new Changeset(id));
098 }
099 setChangesets(changesets);
100 }
101
102 public void initFromPrimitives(Collection<? extends OsmPrimitive> primitives) {
103 if (primitives == null) {
104 setChangesets(null);
105 return;
106 }
107 Set<Changeset> changesets = new HashSet<Changeset>();
108 for (OsmPrimitive p: primitives) {
109 if (p.getChangesetId() <= 0) {
110 continue;
111 }
112 changesets.add(new Changeset(p.getChangesetId()));
113 }
114 setChangesets(changesets);
115 }
116
117 public void initFromDataSet(DataSet ds) {
118 if (ds == null) {
119 setChangesets(null);
120 return;
121 }
122 Set<Changeset> changesets = new HashSet<Changeset>();
123 for (OsmPrimitive p: ds.allPrimitives()) {
124 if (p.getChangesetId() <=0 ) {
125 continue;
126 }
127 changesets.add(new Changeset(p.getChangesetId()));
128 }
129 setChangesets(changesets);
130 }
131
132 @Override
133 public Object getElementAt(int idx) {
134 return data.get(idx);
135 }
136
137 @Override
138 public int getSize() {
139 return data.size();
140 }
141
142 protected void sort() {
143 Collections.sort(
144 data,
145 new Comparator<Changeset>() {
146 public int compare(Changeset cs1, Changeset cs2) {
147 if (cs1.getId() > cs2.getId()) return -1;
148 if (cs1.getId() == cs2.getId()) return 0;
149 return 1;
150 }
151 }
152 );
153 }
154
155 /**
156 * Replies true if there is at least one selected open changeset
157 *
158 * @return true if there is at least one selected open changeset
159 */
160 public boolean hasSelectedOpenChangesets() {
161 return !getSelectedOpenChangesets().isEmpty();
162 }
163
164 /**
165 * Replies the selected open changesets
166 *
167 * @return the selected open changesets
168 */
169 public List<Changeset> getSelectedOpenChangesets() {
170 List<Changeset> ret = new ArrayList<Changeset>();
171 for (int i=0; i< getSize(); i++) {
172 if (selectionModel.isSelectedIndex(i)) {
173 Changeset cs = data.get(i);
174 if (cs.isOpen()) {
175 ret.add(cs);
176 }
177 }
178 }
179 return ret;
180 }
181
182 /* ---------------------------------------------------------------------------- */
183 /* Interface ChangesetCacheListener */
184 /* ---------------------------------------------------------------------------- */
185 public void changesetCacheUpdated(ChangesetCacheEvent event) {
186 Set<Changeset> sel = getSelectedChangesets();
187 for(Changeset cs: event.getAddedChangesets()) {
188 int idx = data.indexOf(cs);
189 if (idx >= 0 && data.get(idx) != cs) {
190 data.get(idx).mergeFrom(cs);
191 }
192 }
193 for(Changeset cs: event.getUpdatedChangesets()) {
194 int idx = data.indexOf(cs);
195 if (idx >= 0 && data.get(idx) != cs) {
196 data.get(idx).mergeFrom(cs);
197 }
198 }
199 for(Changeset cs: event.getRemovedChangesets()) {
200 int idx = data.indexOf(cs);
201 if (idx >= 0) {
202 // replace with an incomplete changeset
203 data.set(idx, new Changeset(cs.getId()));
204 }
205 }
206 fireContentsChanged(this, 0, getSize());
207 setSelectedChangesets(sel);
208 }
209 }