001 // License: GPL. For details, see LICENSE file.
002 package org.openstreetmap.josm.gui.dialogs.changeset;
003
004 import java.beans.PropertyChangeListener;
005 import java.beans.PropertyChangeSupport;
006 import java.util.ArrayList;
007 import java.util.Collection;
008 import java.util.Collections;
009 import java.util.Comparator;
010 import java.util.HashSet;
011 import java.util.List;
012 import java.util.Set;
013
014 import javax.swing.DefaultListSelectionModel;
015 import javax.swing.table.AbstractTableModel;
016
017 import org.openstreetmap.josm.data.osm.Changeset;
018 import org.openstreetmap.josm.data.osm.ChangesetCache;
019 import org.openstreetmap.josm.data.osm.ChangesetCacheEvent;
020 import org.openstreetmap.josm.data.osm.ChangesetCacheListener;
021
022 /**
023 * This is the model for the changeset cache manager dialog.
024 *
025 */
026 public class ChangesetCacheManagerModel extends AbstractTableModel implements ChangesetCacheListener{
027
028 /** the name of the property for the currently selected changeset in the detail view */
029 public final static String CHANGESET_IN_DETAIL_VIEW_PROP = ChangesetCacheManagerModel.class.getName() + ".changesetInDetailView";
030
031 private final ArrayList<Changeset> data = new ArrayList<Changeset>();
032 private DefaultListSelectionModel selectionModel;
033 private Changeset changesetInDetailView;
034 private final PropertyChangeSupport support = new PropertyChangeSupport(this);
035
036 public ChangesetCacheManagerModel(DefaultListSelectionModel selectionModel) {
037 this.selectionModel = selectionModel;
038 }
039
040 public void addPropertyChangeListener(PropertyChangeListener listener) {
041 support.addPropertyChangeListener(listener);
042 }
043
044 public void removePropertyChangeListener(PropertyChangeListener listener) {
045 support.removePropertyChangeListener(listener);
046 }
047
048 /**
049 * Sets the changeset currently displayed in the detail view. Fires a property change event
050 * for the property {@link #CHANGESET_IN_DETAIL_VIEW_PROP} if necessary.
051 *
052 * @param cs the changeset currently displayed in the detail view.
053 */
054 public void setChangesetInDetailView(Changeset cs) {
055 Changeset oldValue = changesetInDetailView;
056 changesetInDetailView = cs;
057 if (oldValue != cs) {
058 support.firePropertyChange(CHANGESET_IN_DETAIL_VIEW_PROP, oldValue, changesetInDetailView);
059 }
060 }
061
062 /**
063 * Replies true if there is at least one selected changeset
064 *
065 * @return true if there is at least one selected changeset
066 */
067 public boolean hasSelectedChangesets() {
068 return selectionModel.getMinSelectionIndex() >= 0;
069 }
070
071 /**
072 * Replies the list of selected changesets
073 *
074 * @return the list of selected changesets
075 */
076 public List<Changeset> getSelectedChangesets() {
077 ArrayList<Changeset> ret = new ArrayList<Changeset>();
078 for (int i =0; i< data.size();i++) {
079 Changeset cs = data.get(i);
080 if (selectionModel.isSelectedIndex(i)) {
081 ret.add(cs);
082 }
083 }
084 return ret;
085 }
086
087 /**
088 * Replies a set of ids of the selected changesets
089 *
090 * @return a set of ids of the selected changesets
091 */
092 public Set<Integer> getSelectedChangesetIds() {
093 Set<Integer> ret = new HashSet<Integer>();
094 for (Changeset cs: getSelectedChangesets()) {
095 ret.add(cs.getId());
096 }
097 return ret;
098 }
099
100 /**
101 * Selects the changesets in <code>selected</code>.
102 *
103 * @param selected the collection of changesets to select. Ignored if empty.
104 */
105 public void setSelectedChangesets(Collection<Changeset> selected) {
106 selectionModel.clearSelection();
107 if (selected == null || selected.isEmpty())
108 return;
109 for (Changeset cs: selected) {
110 int idx = data.indexOf(cs);
111 if (idx >= 0) {
112 selectionModel.addSelectionInterval(idx,idx);
113 }
114 }
115 }
116
117 /**
118 * Selects the changeset displayed at row <code>row</code>
119 *
120 * @param row the row. Ignored if < 0 or >= {@link #getRowCount()}
121 */
122 public void setSelectedByIdx(int row) {
123 if (row < 0 || row >= getRowCount()) return;
124 selectionModel.setSelectionInterval(row, row);
125 }
126
127 public int getColumnCount() {
128 return 5;
129 }
130
131 public int getRowCount() {
132 return data.size();
133 }
134
135 public Object getValueAt(int row, int column) {
136 return data.get(row);
137 }
138
139 public void init() {
140 ChangesetCache cc = ChangesetCache.getInstance();
141 List<Changeset> selected = getSelectedChangesets();
142 data.clear();
143 data.addAll(cc.getChangesets());
144 sort();
145 fireTableDataChanged();
146 setSelectedChangesets(selected);
147
148 cc.addChangesetCacheListener(this);
149 }
150
151 public void tearDown() {
152 ChangesetCache.getInstance().removeChangesetCacheListener(this);
153 }
154
155 public DefaultListSelectionModel getSelectionModel() {
156 return selectionModel;
157 }
158
159 protected void sort() {
160 Collections.sort(
161 this.data,
162 new Comparator<Changeset>() {
163 public int compare(Changeset o1, Changeset o2) {
164 if (o1.getId() < o2.getId()) return 1;
165 if (o1.getId() == o2.getId()) return 0;
166 return -1;
167 }
168 }
169 );
170 }
171
172 /* ------------------------------------------------------------------------------ */
173 /* interface ChangesetCacheListener */
174 /* ------------------------------------------------------------------------------ */
175 public void changesetCacheUpdated(ChangesetCacheEvent event) {
176 List<Changeset> selected = getSelectedChangesets();
177 for (Changeset cs: event.getAddedChangesets()) {
178 data.add(cs);
179 }
180 for (Changeset cs: event.getRemovedChangesets()) {
181 data.remove(cs);
182 }
183 for (Changeset cs: event.getUpdatedChangesets()) {
184 int idx = data.indexOf(cs);
185 if (idx >= 0) {
186 Changeset mine = data.get(idx);
187 if (mine != cs) {
188 mine.mergeFrom(cs);
189 }
190 }
191 }
192 sort();
193 fireTableDataChanged();
194 setSelectedChangesets(selected);
195 }
196 }