source: josm/trunk/src/org/openstreetmap/josm/gui/history/NodeListViewer.java@ 8291

Last change on this file since 8291 was 8285, checked in by Don-vip, 9 years ago

fix sonar squid:S2039 - Member variable visibility should be specified

  • Property svn:eol-style set to native
File size: 12.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.history;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.GridBagConstraints;
7import java.awt.GridBagLayout;
8import java.awt.Insets;
9import java.awt.Point;
10import java.awt.event.ActionEvent;
11import java.awt.event.MouseAdapter;
12import java.awt.event.MouseEvent;
13
14import javax.swing.AbstractAction;
15import javax.swing.JPanel;
16import javax.swing.JPopupMenu;
17import javax.swing.JScrollPane;
18import javax.swing.JTable;
19import javax.swing.ListSelectionModel;
20import javax.swing.event.TableModelEvent;
21import javax.swing.event.TableModelListener;
22import javax.swing.table.TableModel;
23
24import org.openstreetmap.josm.Main;
25import org.openstreetmap.josm.actions.AutoScaleAction;
26import org.openstreetmap.josm.data.osm.OsmPrimitive;
27import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
28import org.openstreetmap.josm.data.osm.PrimitiveId;
29import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
30import org.openstreetmap.josm.data.osm.history.History;
31import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
32import org.openstreetmap.josm.gui.layer.OsmDataLayer;
33import org.openstreetmap.josm.gui.util.AdjustmentSynchronizer;
34import org.openstreetmap.josm.gui.util.GuiHelper;
35import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
36import org.openstreetmap.josm.tools.ImageProvider;
37
38/**
39 * NodeListViewer is a UI component which displays the node list of two
40 * version of a {@link OsmPrimitive} in a {@link History}.
41 *
42 * <ul>
43 * <li>on the left, it displays the node list for the version at {@link PointInTimeType#REFERENCE_POINT_IN_TIME}</li>
44 * <li>on the right, it displays the node list for the version at {@link PointInTimeType#CURRENT_POINT_IN_TIME}</li>
45 * </ul>
46 *
47 */
48public class NodeListViewer extends JPanel {
49
50 private HistoryBrowserModel model;
51 private VersionInfoPanel referenceInfoPanel;
52 private VersionInfoPanel currentInfoPanel;
53 private AdjustmentSynchronizer adjustmentSynchronizer;
54 private SelectionSynchronizer selectionSynchronizer;
55 private NodeListPopupMenu popupMenu;
56
57 protected JScrollPane embeddInScrollPane(JTable table) {
58 JScrollPane pane = new JScrollPane(table);
59 adjustmentSynchronizer.participateInSynchronizedScrolling(pane.getVerticalScrollBar());
60 return pane;
61 }
62
63 protected JTable buildReferenceNodeListTable() {
64 final DiffTableModel tableModel = model.getNodeListTableModel(PointInTimeType.REFERENCE_POINT_IN_TIME);
65 final NodeListTableColumnModel columnModel = new NodeListTableColumnModel();
66 final JTable table = new JTable(tableModel, columnModel);
67 tableModel.addTableModelListener(newReversedChangeListener(table, columnModel));
68 table.setName("table.referencenodelisttable");
69 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
70 selectionSynchronizer.participateInSynchronizedSelection(table.getSelectionModel());
71 table.addMouseListener(new InternalPopupMenuLauncher());
72 table.addMouseListener(new DoubleClickAdapter(table));
73 return table;
74 }
75
76 protected JTable buildCurrentNodeListTable() {
77 final DiffTableModel tableModel = model.getNodeListTableModel(PointInTimeType.CURRENT_POINT_IN_TIME);
78 final NodeListTableColumnModel columnModel = new NodeListTableColumnModel();
79 final JTable table = new JTable(tableModel, columnModel);
80 tableModel.addTableModelListener(newReversedChangeListener(table, columnModel));
81 table.setName("table.currentnodelisttable");
82 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
83 selectionSynchronizer.participateInSynchronizedSelection(table.getSelectionModel());
84 table.addMouseListener(new InternalPopupMenuLauncher());
85 table.addMouseListener(new DoubleClickAdapter(table));
86 return table;
87 }
88
89 protected TableModelListener newReversedChangeListener(final JTable table, final NodeListTableColumnModel columnModel) {
90 return new TableModelListener() {
91 private Boolean reversed = null;
92 private final String nonReversedText = tr("Nodes") + (table.getFont().canDisplay('\u25bc') ? " \u25bc" : " (1-n)");
93 private final String reversedText = tr("Nodes") + (table.getFont().canDisplay('\u25b2') ? " \u25b2" : " (n-1)");
94
95 @Override
96 public void tableChanged(TableModelEvent e) {
97 if (e.getSource() instanceof DiffTableModel) {
98 final DiffTableModel model = (DiffTableModel) e.getSource();
99 if (reversed == null || reversed != model.isReversed()) {
100 reversed = model.isReversed();
101 columnModel.getColumn(0).setHeaderValue(reversed ? reversedText : nonReversedText);
102 table.getTableHeader().repaint();
103 }
104 }
105 }
106 };
107 }
108
109 protected void build() {
110 setLayout(new GridBagLayout());
111 GridBagConstraints gc = new GridBagConstraints();
112
113 // ---------------------------
114 gc.gridx = 0;
115 gc.gridy = 0;
116 gc.gridwidth = 1;
117 gc.gridheight = 1;
118 gc.weightx = 0.5;
119 gc.weighty = 0.0;
120 gc.insets = new Insets(5,5,5,0);
121 gc.fill = GridBagConstraints.HORIZONTAL;
122 gc.anchor = GridBagConstraints.FIRST_LINE_START;
123 referenceInfoPanel = new VersionInfoPanel(model, PointInTimeType.REFERENCE_POINT_IN_TIME);
124 add(referenceInfoPanel,gc);
125
126 gc.gridx = 1;
127 gc.gridy = 0;
128 gc.gridwidth = 1;
129 gc.gridheight = 1;
130 gc.fill = GridBagConstraints.HORIZONTAL;
131 gc.weightx = 0.5;
132 gc.weighty = 0.0;
133 gc.anchor = GridBagConstraints.FIRST_LINE_START;
134 currentInfoPanel = new VersionInfoPanel(model, PointInTimeType.CURRENT_POINT_IN_TIME);
135 add(currentInfoPanel,gc);
136
137 adjustmentSynchronizer = new AdjustmentSynchronizer();
138 selectionSynchronizer = new SelectionSynchronizer();
139
140 popupMenu = new NodeListPopupMenu();
141
142 // ---------------------------
143 gc.gridx = 0;
144 gc.gridy = 1;
145 gc.gridwidth = 1;
146 gc.gridheight = 1;
147 gc.weightx = 0.5;
148 gc.weighty = 1.0;
149 gc.fill = GridBagConstraints.BOTH;
150 gc.anchor = GridBagConstraints.NORTHWEST;
151 add(embeddInScrollPane(buildReferenceNodeListTable()),gc);
152
153 gc.gridx = 1;
154 gc.gridy = 1;
155 gc.gridwidth = 1;
156 gc.gridheight = 1;
157 gc.weightx = 0.5;
158 gc.weighty = 1.0;
159 gc.fill = GridBagConstraints.BOTH;
160 gc.anchor = GridBagConstraints.NORTHWEST;
161 add(embeddInScrollPane(buildCurrentNodeListTable()),gc);
162 }
163
164 public NodeListViewer(HistoryBrowserModel model) {
165 setModel(model);
166 build();
167 }
168
169 protected void unregisterAsObserver(HistoryBrowserModel model) {
170 if (currentInfoPanel != null) {
171 model.deleteObserver(currentInfoPanel);
172 }
173 if (referenceInfoPanel != null) {
174 model.deleteObserver(referenceInfoPanel);
175 }
176 }
177 protected void registerAsObserver(HistoryBrowserModel model) {
178 if (currentInfoPanel != null) {
179 model.addObserver(currentInfoPanel);
180 }
181 if (referenceInfoPanel != null) {
182 model.addObserver(referenceInfoPanel);
183 }
184 }
185
186 public void setModel(HistoryBrowserModel model) {
187 if (this.model != null) {
188 unregisterAsObserver(model);
189 }
190 this.model = model;
191 if (this.model != null) {
192 registerAsObserver(model);
193 }
194 }
195
196 static class NodeListPopupMenu extends JPopupMenu {
197 private final ZoomToNodeAction zoomToNodeAction;
198 private final ShowHistoryAction showHistoryAction;
199
200 public NodeListPopupMenu() {
201 zoomToNodeAction = new ZoomToNodeAction();
202 add(zoomToNodeAction);
203 showHistoryAction = new ShowHistoryAction();
204 add(showHistoryAction);
205 }
206
207 public void prepare(PrimitiveId pid){
208 zoomToNodeAction.setPrimitiveId(pid);
209 zoomToNodeAction.updateEnabledState();
210
211 showHistoryAction.setPrimitiveId(pid);
212 showHistoryAction.updateEnabledState();
213 }
214 }
215
216 static class ZoomToNodeAction extends AbstractAction {
217 private PrimitiveId primitiveId;
218
219 public ZoomToNodeAction() {
220 putValue(NAME, tr("Zoom to node"));
221 putValue(SHORT_DESCRIPTION, tr("Zoom to this node in the current data layer"));
222 putValue(SMALL_ICON, ImageProvider.get("dialogs", "zoomin"));
223 }
224
225 @Override
226 public void actionPerformed(ActionEvent e) {
227 if (!isEnabled()) return;
228 OsmPrimitive p = getPrimitiveToZoom();
229 if (p != null) {
230 OsmDataLayer editLayer = Main.main.getEditLayer();
231 if (editLayer != null) {
232 editLayer.data.setSelected(p.getPrimitiveId());
233 AutoScaleAction.autoScale("selection");
234 }
235 }
236 }
237
238 public void setPrimitiveId(PrimitiveId pid) {
239 this.primitiveId = pid;
240 updateEnabledState();
241 }
242
243 protected OsmPrimitive getPrimitiveToZoom() {
244 if (primitiveId == null) return null;
245 OsmDataLayer editLayer = Main.main.getEditLayer();
246 if (editLayer == null) return null;
247 return editLayer.data.getPrimitiveById(primitiveId);
248 }
249
250 public void updateEnabledState() {
251 if (!Main.main.hasEditLayer()) {
252 setEnabled(false);
253 return;
254 }
255 setEnabled(getPrimitiveToZoom() != null);
256 }
257 }
258
259 static class ShowHistoryAction extends AbstractAction {
260 private PrimitiveId primitiveId;
261
262 public ShowHistoryAction() {
263 putValue(NAME, tr("Show history"));
264 putValue(SHORT_DESCRIPTION, tr("Open a history browser with the history of this node"));
265 putValue(SMALL_ICON, ImageProvider.get("dialogs", "history"));
266 }
267
268 @Override
269 public void actionPerformed(ActionEvent e) {
270 if (!isEnabled()) return;
271 run();
272 }
273
274 public void setPrimitiveId(PrimitiveId pid) {
275 this.primitiveId = pid;
276 updateEnabledState();
277 }
278
279 public void run() {
280 if (HistoryDataSet.getInstance().getHistory(primitiveId) == null) {
281 Main.worker.submit(new HistoryLoadTask().add(primitiveId));
282 }
283 Runnable r = new Runnable() {
284 @Override
285 public void run() {
286 final History h = HistoryDataSet.getInstance().getHistory(primitiveId);
287 if (h == null)
288 return;
289 GuiHelper.runInEDT(new Runnable() {
290 @Override public void run() {
291 HistoryBrowserDialogManager.getInstance().show(h);
292 }
293 });
294 }
295 };
296 Main.worker.submit(r);
297 }
298
299 public void updateEnabledState() {
300 setEnabled(primitiveId != null && !primitiveId.isNew());
301 }
302 }
303
304 private static PrimitiveId primitiveIdAtRow(TableModel model, int row) {
305 DiffTableModel castedModel = (DiffTableModel) model;
306 Long id = (Long)castedModel.getValueAt(row, 0).value;
307 if(id == null) return null;
308 return new SimplePrimitiveId(id, OsmPrimitiveType.NODE);
309 }
310
311 class InternalPopupMenuLauncher extends PopupMenuLauncher {
312 public InternalPopupMenuLauncher() {
313 super(popupMenu);
314 }
315
316 @Override protected int checkTableSelection(JTable table, Point p) {
317 int row = super.checkTableSelection(table, p);
318 popupMenu.prepare(primitiveIdAtRow(table.getModel(), row));
319 return row;
320 }
321 }
322
323 static class DoubleClickAdapter extends MouseAdapter {
324 private JTable table;
325 private ShowHistoryAction showHistoryAction;
326
327 public DoubleClickAdapter(JTable table) {
328 this.table = table;
329 showHistoryAction = new ShowHistoryAction();
330 }
331
332 @Override
333 public void mouseClicked(MouseEvent e) {
334 if (e.getClickCount() < 2) return;
335 int row = table.rowAtPoint(e.getPoint());
336 if(row <= 0) return;
337 PrimitiveId pid = primitiveIdAtRow(table.getModel(), row);
338 if (pid == null || pid.isNew())
339 return;
340 showHistoryAction.setPrimitiveId(pid);
341 showHistoryAction.run();
342 }
343 }
344}
Note: See TracBrowser for help on using the repository browser.