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

Last change on this file since 11365 was 11365, checked in by Don-vip, 7 years ago

fix #14090 - use DefaultListSelectionModel adjusting selection mode to avoid too much costly listener calls

  • Property svn:eol-style set to native
File size: 5.9 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.Collection;
8import java.util.Comparator;
9import java.util.HashSet;
10import java.util.List;
11import java.util.Set;
12
13import javax.swing.DefaultListSelectionModel;
14import javax.swing.table.AbstractTableModel;
15
16import org.openstreetmap.josm.data.osm.Changeset;
17import org.openstreetmap.josm.data.osm.ChangesetCache;
18import org.openstreetmap.josm.data.osm.ChangesetCacheEvent;
19import org.openstreetmap.josm.data.osm.ChangesetCacheListener;
20import org.openstreetmap.josm.gui.util.GuiHelper;
21
22/**
23 * This is the model for the changeset cache manager dialog.
24 *
25 */
26public class ChangesetCacheManagerModel extends AbstractTableModel implements ChangesetCacheListener {
27
28 /** the name of the property for the currently selected changeset in the detail view */
29 public static final String CHANGESET_IN_DETAIL_VIEW_PROP = ChangesetCacheManagerModel.class.getName() + ".changesetInDetailView";
30
31 private final transient List<Changeset> data = new ArrayList<>();
32 private final DefaultListSelectionModel selectionModel;
33 private transient Changeset changesetInDetailView;
34 private final PropertyChangeSupport support = new PropertyChangeSupport(this);
35
36 public ChangesetCacheManagerModel(DefaultListSelectionModel selectionModel) {
37 this.selectionModel = selectionModel;
38 }
39
40 public void addPropertyChangeListener(PropertyChangeListener listener) {
41 support.addPropertyChangeListener(listener);
42 }
43
44 public void removePropertyChangeListener(PropertyChangeListener listener) {
45 support.removePropertyChangeListener(listener);
46 }
47
48 /**
49 * Sets the changeset currently displayed in the detail view. Fires a property change event
50 * for the property {@link #CHANGESET_IN_DETAIL_VIEW_PROP} if necessary.
51 *
52 * @param cs the changeset currently displayed in the detail view.
53 */
54 public void setChangesetInDetailView(Changeset cs) {
55 Changeset oldValue = changesetInDetailView;
56 changesetInDetailView = cs;
57 if (oldValue != cs) {
58 support.firePropertyChange(CHANGESET_IN_DETAIL_VIEW_PROP, oldValue, changesetInDetailView);
59 }
60 }
61
62 /**
63 * Replies true if there is at least one selected changeset
64 *
65 * @return true if there is at least one selected changeset
66 */
67 public boolean hasSelectedChangesets() {
68 return selectionModel.getMinSelectionIndex() >= 0;
69 }
70
71 /**
72 * Replies the list of selected changesets
73 *
74 * @return the list of selected changesets
75 */
76 public List<Changeset> getSelectedChangesets() {
77 List<Changeset> ret = new ArrayList<>();
78 for (int i = 0; i < data.size(); i++) {
79 Changeset cs = data.get(i);
80 if (selectionModel.isSelectedIndex(i)) {
81 ret.add(cs);
82 }
83 }
84 return ret;
85 }
86
87 /**
88 * Replies a set of ids of the selected changesets
89 *
90 * @return a set of ids of the selected changesets
91 */
92 public Set<Integer> getSelectedChangesetIds() {
93 Set<Integer> ret = new HashSet<>();
94 for (Changeset cs: getSelectedChangesets()) {
95 ret.add(cs.getId());
96 }
97 return ret;
98 }
99
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.setValueIsAdjusting(true);
107 selectionModel.clearSelection();
108 if (selected != null) {
109 for (Changeset cs: selected) {
110 final int idx = data.indexOf(cs);
111 if (idx >= 0) {
112 selectionModel.addSelectionInterval(idx, idx);
113 }
114 }
115 }
116 GuiHelper.runInEDTAndWait(() -> selectionModel.setValueIsAdjusting(false));
117 }
118
119 @Override
120 public int getColumnCount() {
121 return 5;
122 }
123
124 @Override
125 public int getRowCount() {
126 return data.size();
127 }
128
129 @Override
130 public Object getValueAt(int row, int column) {
131 return data.get(row);
132 }
133
134 public void init() {
135 ChangesetCache cc = ChangesetCache.getInstance();
136 List<Changeset> selected = getSelectedChangesets();
137 data.clear();
138 data.addAll(cc.getChangesets());
139 sort();
140 fireTableDataChanged();
141 setSelectedChangesets(selected);
142
143 cc.addChangesetCacheListener(this);
144 }
145
146 public void tearDown() {
147 ChangesetCache.getInstance().removeChangesetCacheListener(this);
148 }
149
150 public DefaultListSelectionModel getSelectionModel() {
151 return selectionModel;
152 }
153
154 protected void sort() {
155 data.sort(Comparator.comparingInt(Changeset::getId).reversed());
156 }
157
158 /* ------------------------------------------------------------------------------ */
159 /* interface ChangesetCacheListener */
160 /* ------------------------------------------------------------------------------ */
161 @Override
162 public void changesetCacheUpdated(ChangesetCacheEvent event) {
163 List<Changeset> selected = getSelectedChangesets();
164 for (Changeset cs: event.getAddedChangesets()) {
165 data.add(cs);
166 }
167 for (Changeset cs: event.getRemovedChangesets()) {
168 data.remove(cs);
169 }
170 for (Changeset cs: event.getUpdatedChangesets()) {
171 int idx = data.indexOf(cs);
172 if (idx >= 0) {
173 Changeset mine = data.get(idx);
174 if (mine != cs) {
175 mine.mergeFrom(cs);
176 }
177 }
178 }
179 sort();
180 fireTableDataChanged();
181 setSelectedChangesets(selected);
182 }
183}
Note: See TracBrowser for help on using the repository browser.