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 }