source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetCacheManagerModel.java

Last change on this file was 18338, checked in by Don-vip, 2 years ago

fix #21655 - fix selection of changesets after sorting the table

  • Property svn:eol-style set to native
File size: 6.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.changeset;
3
4import java.beans.PropertyChangeListener;
5import java.beans.PropertyChangeSupport;
6import java.util.ArrayList;
7import java.util.Arrays;
8import java.util.Collection;
9import java.util.Comparator;
10import java.util.List;
11import java.util.Set;
12import java.util.stream.Collectors;
13import java.util.stream.IntStream;
14
15import javax.swing.DefaultListSelectionModel;
16import javax.swing.table.AbstractTableModel;
17
18import org.openstreetmap.josm.data.osm.Changeset;
19import org.openstreetmap.josm.data.osm.ChangesetCache;
20import org.openstreetmap.josm.data.osm.ChangesetCacheEvent;
21import org.openstreetmap.josm.data.osm.ChangesetCacheListener;
22import org.openstreetmap.josm.gui.util.GuiHelper;
23import org.openstreetmap.josm.gui.util.TableHelper;
24
25/**
26 * This is the model for the changeset cache manager dialog.
27 */
28public class ChangesetCacheManagerModel extends AbstractTableModel implements ChangesetCacheListener {
29
30 /** the name of the property for the currently selected changeset in the detail view */
31 public static final String CHANGESET_IN_DETAIL_VIEW_PROP = ChangesetCacheManagerModel.class.getName() + ".changesetInDetailView";
32
33 private final transient List<Changeset> data = new ArrayList<>();
34 private final DefaultListSelectionModel selectionModel;
35 private transient ChangesetCacheTableRowSorter sorter;
36 private transient Changeset changesetInDetailView;
37 private final PropertyChangeSupport support = new PropertyChangeSupport(this);
38
39 /**
40 * Creates a new ChangesetCacheManagerModel that is based on the selectionModel
41 * @param selectionModel A new selection model that should be used.
42 */
43 public ChangesetCacheManagerModel(DefaultListSelectionModel selectionModel) {
44 this.selectionModel = selectionModel;
45 }
46
47 /**
48 * Adds a property change listener to this model.
49 * @param listener The listener
50 */
51 public void addPropertyChangeListener(PropertyChangeListener listener) {
52 support.addPropertyChangeListener(listener);
53 }
54
55 /**
56 * Removes a property change listener from this model.
57 * @param listener The listener
58 */
59 public void removePropertyChangeListener(PropertyChangeListener listener) {
60 support.removePropertyChangeListener(listener);
61 }
62
63 /**
64 * Sets the changeset currently displayed in the detail view. Fires a property change event
65 * for the property {@link #CHANGESET_IN_DETAIL_VIEW_PROP} if necessary.
66 *
67 * @param cs the changeset currently displayed in the detail view.
68 */
69 public void setChangesetInDetailView(Changeset cs) {
70 Changeset oldValue = changesetInDetailView;
71 changesetInDetailView = cs;
72 if (oldValue != cs) {
73 support.firePropertyChange(CHANGESET_IN_DETAIL_VIEW_PROP, oldValue, changesetInDetailView);
74 }
75 }
76
77 /**
78 * Replies true if there is at least one selected changeset
79 *
80 * @return true if there is at least one selected changeset
81 */
82 public boolean hasSelectedChangesets() {
83 return selectionModel.getMinSelectionIndex() >= 0;
84 }
85
86 /**
87 * Replies the list of selected changesets
88 *
89 * @return the list of selected changesets
90 */
91 public List<Changeset> getSelectedChangesets() {
92 return Arrays.stream(TableHelper.getSelectedIndices(selectionModel))
93 .map(sorter::convertRowIndexToModel).mapToObj(data::get).collect(Collectors.toList());
94 }
95
96 /**
97 * Replies a set of ids of the selected changesets
98 *
99 * @return a set of ids of the selected changesets
100 */
101 public Set<Integer> getSelectedChangesetIds() {
102 return getSelectedChangesets().stream().map(Changeset::getId).collect(Collectors.toSet());
103 }
104
105 /**
106 * Selects the changesets in <code>selected</code>.
107 *
108 * @param selected the collection of changesets to select. Ignored if empty.
109 */
110 public void setSelectedChangesets(Collection<Changeset> selected) {
111 GuiHelper.runInEDTAndWait(() -> TableHelper.setSelectedIndices(selectionModel,
112 selected != null ? selected.stream().mapToInt(data::indexOf) : IntStream.empty()));
113 }
114
115 @Override
116 public int getColumnCount() {
117 return 8;
118 }
119
120 @Override
121 public int getRowCount() {
122 return data.size();
123 }
124
125 @Override
126 public Changeset getValueAt(int row, int column) {
127 return data.get(row);
128 }
129
130 /**
131 * Initializes the data that is displayed using the changeset cache.
132 */
133 public void init() {
134 ChangesetCache cc = ChangesetCache.getInstance();
135 List<Changeset> selected = getSelectedChangesets();
136 data.clear();
137 data.addAll(cc.getChangesets());
138 sort();
139 fireTableDataChanged();
140 setSelectedChangesets(selected);
141
142 cc.addChangesetCacheListener(this);
143 }
144
145 /**
146 * Destroys and unregisters this model.
147 */
148 public void tearDown() {
149 ChangesetCache.getInstance().removeChangesetCacheListener(this);
150 }
151
152 /**
153 * Gets the selection model this table is based on.
154 * @return The selection model.
155 */
156 public DefaultListSelectionModel getSelectionModel() {
157 return selectionModel;
158 }
159
160 protected void sort() {
161 data.sort(Comparator.comparingInt(Changeset::getId).reversed());
162 }
163
164 void setChangesetCacheTableRowSorter(ChangesetCacheTableRowSorter sorter) {
165 this.sorter = sorter;
166 }
167
168 /* ------------------------------------------------------------------------------ */
169 /* interface ChangesetCacheListener */
170 /* ------------------------------------------------------------------------------ */
171 @Override
172 public void changesetCacheUpdated(ChangesetCacheEvent event) {
173 List<Changeset> selected = getSelectedChangesets();
174 data.addAll(event.getAddedChangesets());
175 data.removeAll(event.getRemovedChangesets());
176 for (Changeset cs: event.getUpdatedChangesets()) {
177 int idx = data.indexOf(cs);
178 if (idx >= 0) {
179 Changeset mine = data.get(idx);
180 if (mine != cs) {
181 mine.mergeFrom(cs);
182 }
183 }
184 }
185 GuiHelper.runInEDT(() -> {
186 sort();
187 fireTableDataChanged();
188 setSelectedChangesets(selected);
189 });
190 }
191}
Note: See TracBrowser for help on using the repository browser.