source: josm/trunk/src/org/openstreetmap/josm/gui/history/CoordinateInfoViewer.java@ 12713

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

findbugs - EI_EXPOSE_REP2 + javadoc

  • Property svn:eol-style set to native
File size: 15.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.history;
3import static org.openstreetmap.josm.tools.I18n.tr;
4
5import java.awt.Color;
6import java.awt.GridBagConstraints;
7import java.awt.GridBagLayout;
8import java.awt.Insets;
9import java.awt.event.MouseAdapter;
10import java.awt.event.MouseEvent;
11
12import javax.swing.BorderFactory;
13import javax.swing.JLabel;
14import javax.swing.JPanel;
15import javax.swing.UIManager;
16import javax.swing.event.ChangeEvent;
17import javax.swing.event.ChangeListener;
18
19import org.openstreetmap.gui.jmapviewer.JMapViewer;
20import org.openstreetmap.gui.jmapviewer.MapMarkerDot;
21import org.openstreetmap.gui.jmapviewer.tilesources.OsmTileSource;
22import org.openstreetmap.josm.data.coor.CoordinateFormat;
23import org.openstreetmap.josm.data.coor.LatLon;
24import org.openstreetmap.josm.data.osm.history.HistoryNode;
25import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
26import org.openstreetmap.josm.gui.NavigatableComponent;
27import org.openstreetmap.josm.gui.util.GuiHelper;
28import org.openstreetmap.josm.gui.widgets.JosmTextArea;
29import org.openstreetmap.josm.tools.CheckParameterUtil;
30import org.openstreetmap.josm.tools.Pair;
31
32/**
33 * An UI widget for displaying differences in the coordinates of two
34 * {@link HistoryNode}s.
35 * @since 2243
36 */
37public class CoordinateInfoViewer extends JPanel {
38
39 /** the model */
40 private transient HistoryBrowserModel model;
41 /** the common info panel for the history node in role REFERENCE_POINT_IN_TIME */
42 private VersionInfoPanel referenceInfoPanel;
43 /** the common info panel for the history node in role CURRENT_POINT_IN_TIME */
44 private VersionInfoPanel currentInfoPanel;
45 /** the info panel for coordinates for the node in role REFERENCE_POINT_IN_TIME */
46 private LatLonViewer referenceLatLonViewer;
47 /** the info panel for coordinates for the node in role CURRENT_POINT_IN_TIME */
48 private LatLonViewer currentLatLonViewer;
49 /** the info panel for distance between the two coordinates */
50 private DistanceViewer distanceViewer;
51 /** the map panel showing the old+new coordinate */
52 private MapViewer mapViewer;
53
54 protected void build() {
55 setLayout(new GridBagLayout());
56 GridBagConstraints gc = new GridBagConstraints();
57
58 // ---------------------------
59 gc.gridx = 0;
60 gc.gridy = 0;
61 gc.gridwidth = 1;
62 gc.gridheight = 1;
63 gc.weightx = 0.5;
64 gc.weighty = 0.0;
65 gc.insets = new Insets(5, 5, 5, 0);
66 gc.fill = GridBagConstraints.HORIZONTAL;
67 gc.anchor = GridBagConstraints.FIRST_LINE_START;
68 referenceInfoPanel = new VersionInfoPanel(model, PointInTimeType.REFERENCE_POINT_IN_TIME);
69 add(referenceInfoPanel, gc);
70
71 gc.gridx = 1;
72 gc.gridy = 0;
73 gc.fill = GridBagConstraints.HORIZONTAL;
74 gc.weightx = 0.5;
75 gc.weighty = 0.0;
76 gc.anchor = GridBagConstraints.FIRST_LINE_START;
77 currentInfoPanel = new VersionInfoPanel(model, PointInTimeType.CURRENT_POINT_IN_TIME);
78 add(currentInfoPanel, gc);
79
80 // ---------------------------
81 // the two coordinate panels
82 gc.gridx = 0;
83 gc.gridy = 1;
84 gc.weightx = 0.5;
85 gc.weighty = 0.0;
86 gc.fill = GridBagConstraints.HORIZONTAL;
87 gc.anchor = GridBagConstraints.NORTHWEST;
88 referenceLatLonViewer = new LatLonViewer(model, PointInTimeType.REFERENCE_POINT_IN_TIME);
89 add(referenceLatLonViewer, gc);
90
91 gc.gridx = 1;
92 gc.gridy = 1;
93 gc.weightx = 0.5;
94 gc.weighty = 0.0;
95 gc.fill = GridBagConstraints.HORIZONTAL;
96 gc.anchor = GridBagConstraints.NORTHWEST;
97 currentLatLonViewer = new LatLonViewer(model, PointInTimeType.CURRENT_POINT_IN_TIME);
98 add(currentLatLonViewer, gc);
99
100 // --------------------
101 // the distance panel
102 gc.gridx = 0;
103 gc.gridy = 2;
104 gc.gridwidth = 2;
105 gc.fill = GridBagConstraints.HORIZONTAL;
106 gc.weightx = 1.0;
107 gc.weighty = 0.0;
108 distanceViewer = new DistanceViewer(model);
109 add(distanceViewer, gc);
110
111 // the map panel
112 gc.gridx = 0;
113 gc.gridy = 3;
114 gc.gridwidth = 2;
115 gc.fill = GridBagConstraints.BOTH;
116 gc.weightx = 1.0;
117 gc.weighty = 1.0;
118 mapViewer = new MapViewer(model);
119 add(mapViewer, gc);
120 mapViewer.setZoomContolsVisible(false);
121 }
122
123 /**
124 * Constructs a new {@code CoordinateInfoViewer}.
125 * @param model the model. Must not be null.
126 * @throws IllegalArgumentException if model is null
127 */
128 public CoordinateInfoViewer(HistoryBrowserModel model) {
129 CheckParameterUtil.ensureParameterNotNull(model, "model");
130 setModel(model);
131 build();
132 registerAsChangeListener(model);
133 }
134
135 protected void unregisterAsChangeListener(HistoryBrowserModel model) {
136 if (currentInfoPanel != null) {
137 model.removeChangeListener(currentInfoPanel);
138 }
139 if (referenceInfoPanel != null) {
140 model.removeChangeListener(referenceInfoPanel);
141 }
142 if (currentLatLonViewer != null) {
143 model.removeChangeListener(currentLatLonViewer);
144 }
145 if (referenceLatLonViewer != null) {
146 model.removeChangeListener(referenceLatLonViewer);
147 }
148 if (distanceViewer != null) {
149 model.removeChangeListener(distanceViewer);
150 }
151 if (mapViewer != null) {
152 model.removeChangeListener(mapViewer);
153 }
154 }
155
156 protected void registerAsChangeListener(HistoryBrowserModel model) {
157 if (currentInfoPanel != null) {
158 model.addChangeListener(currentInfoPanel);
159 }
160 if (referenceInfoPanel != null) {
161 model.addChangeListener(referenceInfoPanel);
162 }
163 if (currentLatLonViewer != null) {
164 model.addChangeListener(currentLatLonViewer);
165 }
166 if (referenceLatLonViewer != null) {
167 model.addChangeListener(referenceLatLonViewer);
168 }
169 if (distanceViewer != null) {
170 model.addChangeListener(distanceViewer);
171 }
172 if (mapViewer != null) {
173 model.addChangeListener(mapViewer);
174 }
175 }
176
177 /**
178 * Sets the model for this viewer
179 *
180 * @param model the model.
181 */
182 public void setModel(HistoryBrowserModel model) {
183 if (this.model != null) {
184 unregisterAsChangeListener(model);
185 }
186 this.model = model;
187 if (this.model != null) {
188 registerAsChangeListener(model);
189 }
190 }
191
192 /**
193 * Pans the map to the old+new coordinate
194 * @see JMapViewer#setDisplayToFitMapMarkers()
195 */
196 public void setDisplayToFitMapMarkers() {
197 mapViewer.setDisplayToFitMapMarkers();
198 }
199
200 private static JosmTextArea newTextArea() {
201 JosmTextArea area = new JosmTextArea();
202 GuiHelper.setBackgroundReadable(area, Color.WHITE);
203 area.setEditable(false);
204 area.setOpaque(true);
205 area.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
206 area.setFont(UIManager.getFont("Label.font"));
207 return area;
208 }
209
210 private static class Updater {
211 private final HistoryBrowserModel model;
212 private final PointInTimeType role;
213
214 protected Updater(HistoryBrowserModel model, PointInTimeType role) {
215 this.model = model;
216 this.role = role;
217 }
218
219 protected HistoryOsmPrimitive getPrimitive() {
220 if (model == null || role == null)
221 return null;
222 return model.getPointInTime(role);
223 }
224
225 protected HistoryOsmPrimitive getOppositePrimitive() {
226 if (model == null || role == null)
227 return null;
228 return model.getPointInTime(role.opposite());
229 }
230
231 protected final Pair<LatLon, LatLon> getCoordinates() {
232 HistoryOsmPrimitive p = getPrimitive();
233 if (!(p instanceof HistoryNode)) return null;
234 HistoryOsmPrimitive opposite = getOppositePrimitive();
235 if (!(opposite instanceof HistoryNode)) return null;
236 HistoryNode node = (HistoryNode) p;
237 HistoryNode oppositeNode = (HistoryNode) opposite;
238
239 return Pair.create(node.getCoords(), oppositeNode.getCoords());
240 }
241 }
242
243 /**
244 * A UI widgets which displays the Lan/Lon-coordinates of a {@link HistoryNode}.
245 */
246 private static class LatLonViewer extends JPanel implements ChangeListener {
247
248 private final JosmTextArea lblLat = newTextArea();
249 private final JosmTextArea lblLon = newTextArea();
250 private final transient Updater updater;
251 private final Color modifiedColor;
252
253 protected void build() {
254 setLayout(new GridBagLayout());
255 setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
256 GridBagConstraints gc = new GridBagConstraints();
257
258 // --------
259 gc.gridx = 0;
260 gc.gridy = 0;
261 gc.fill = GridBagConstraints.NONE;
262 gc.weightx = 0.0;
263 gc.insets = new Insets(5, 5, 5, 5);
264 gc.anchor = GridBagConstraints.NORTHWEST;
265 add(new JLabel(tr("Latitude: ")), gc);
266
267 // --------
268 gc.gridx = 1;
269 gc.gridy = 0;
270 gc.fill = GridBagConstraints.HORIZONTAL;
271 gc.weightx = 1.0;
272 add(lblLat, gc);
273
274 // --------
275 gc.gridx = 0;
276 gc.gridy = 1;
277 gc.fill = GridBagConstraints.NONE;
278 gc.weightx = 0.0;
279 gc.anchor = GridBagConstraints.NORTHWEST;
280 add(new JLabel(tr("Longitude: ")), gc);
281
282 // --------
283 gc.gridx = 1;
284 gc.gridy = 1;
285 gc.fill = GridBagConstraints.HORIZONTAL;
286 gc.weightx = 1.0;
287 add(lblLon, gc);
288 }
289
290 /**
291 * Constructs a new {@code LatLonViewer}.
292 * @param model a model
293 * @param role the role for this viewer.
294 */
295 LatLonViewer(HistoryBrowserModel model, PointInTimeType role) {
296 this.updater = new Updater(model, role);
297 this.modifiedColor = PointInTimeType.CURRENT_POINT_IN_TIME.equals(role)
298 ? TwoColumnDiff.Item.DiffItemType.INSERTED.getColor()
299 : TwoColumnDiff.Item.DiffItemType.DELETED.getColor();
300 build();
301 }
302
303 protected void refresh() {
304 final Pair<LatLon, LatLon> coordinates = updater.getCoordinates();
305 if (coordinates == null) return;
306 final LatLon coord = coordinates.a;
307 final LatLon oppositeCoord = coordinates.b;
308
309 // display the coordinates
310 lblLat.setText(coord != null ? coord.latToString(CoordinateFormat.DECIMAL_DEGREES) : tr("(none)"));
311 lblLon.setText(coord != null ? coord.lonToString(CoordinateFormat.DECIMAL_DEGREES) : tr("(none)"));
312
313 // update background color to reflect differences in the coordinates
314 if (coord == oppositeCoord ||
315 (coord != null && oppositeCoord != null && coord.lat() == oppositeCoord.lat())) {
316 GuiHelper.setBackgroundReadable(lblLat, Color.WHITE);
317 } else {
318 GuiHelper.setBackgroundReadable(lblLat, modifiedColor);
319 }
320 if (coord == oppositeCoord ||
321 (coord != null && oppositeCoord != null && coord.lon() == oppositeCoord.lon())) {
322 GuiHelper.setBackgroundReadable(lblLon, Color.WHITE);
323 } else {
324 GuiHelper.setBackgroundReadable(lblLon, modifiedColor);
325 }
326 }
327
328 @Override
329 public void stateChanged(ChangeEvent e) {
330 refresh();
331 }
332 }
333
334 private static class MapViewer extends JMapViewer implements ChangeListener {
335
336 private final transient Updater updater;
337
338 MapViewer(HistoryBrowserModel model) {
339 this.updater = new Updater(model, PointInTimeType.REFERENCE_POINT_IN_TIME);
340 setTileSource(new OsmTileSource.Mapnik()); // for attribution
341 setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
342 addMouseListener(new MouseAdapter() {
343 @Override
344 public void mouseClicked(MouseEvent e) {
345 if (e.getButton() == MouseEvent.BUTTON1) {
346 getAttribution().handleAttribution(e.getPoint(), true);
347 }
348 }
349 });
350 }
351
352 @Override
353 public void stateChanged(ChangeEvent e) {
354 final Pair<LatLon, LatLon> coordinates = updater.getCoordinates();
355 if (coordinates == null) {
356 return;
357 }
358
359 removeAllMapMarkers();
360
361 if (coordinates.a != null) {
362 final MapMarkerDot oldMarker = new MapMarkerDot(coordinates.a.lat(), coordinates.a.lon());
363 oldMarker.setBackColor(TwoColumnDiff.Item.DiffItemType.DELETED.getColor());
364 addMapMarker(oldMarker);
365 }
366 if (coordinates.b != null) {
367 final MapMarkerDot newMarker = new MapMarkerDot(coordinates.b.lat(), coordinates.b.lon());
368 newMarker.setBackColor(TwoColumnDiff.Item.DiffItemType.INSERTED.getColor());
369 addMapMarker(newMarker);
370 }
371
372 setDisplayToFitMapMarkers();
373 }
374 }
375
376 private static class DistanceViewer extends JPanel implements ChangeListener {
377
378 private final JosmTextArea lblDistance = newTextArea();
379 private final transient Updater updater;
380
381 DistanceViewer(HistoryBrowserModel model) {
382 this.updater = new Updater(model, PointInTimeType.REFERENCE_POINT_IN_TIME);
383 build();
384 }
385
386 protected void build() {
387 setLayout(new GridBagLayout());
388 setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
389 GridBagConstraints gc = new GridBagConstraints();
390
391 // --------
392 gc.gridx = 0;
393 gc.gridy = 0;
394 gc.fill = GridBagConstraints.NONE;
395 gc.weightx = 0.0;
396 gc.insets = new Insets(5, 5, 5, 5);
397 gc.anchor = GridBagConstraints.NORTHWEST;
398 add(new JLabel(tr("Distance: ")), gc);
399
400 // --------
401 gc.gridx = 1;
402 gc.gridy = 0;
403 gc.fill = GridBagConstraints.HORIZONTAL;
404 gc.weightx = 1.0;
405 add(lblDistance, gc);
406 }
407
408 protected void refresh() {
409 final Pair<LatLon, LatLon> coordinates = updater.getCoordinates();
410 if (coordinates == null) return;
411 final LatLon coord = coordinates.a;
412 final LatLon oppositeCoord = coordinates.b;
413
414 // update distance
415 //
416 if (coord != null && oppositeCoord != null) {
417 double distance = coord.greatCircleDistance(oppositeCoord);
418 GuiHelper.setBackgroundReadable(lblDistance, distance > 0
419 ? TwoColumnDiff.Item.DiffItemType.CHANGED.getColor()
420 : Color.WHITE);
421 lblDistance.setText(NavigatableComponent.getDistText(distance));
422 } else {
423 GuiHelper.setBackgroundReadable(lblDistance, coord != oppositeCoord
424 ? TwoColumnDiff.Item.DiffItemType.CHANGED.getColor()
425 : Color.WHITE);
426 lblDistance.setText(tr("(none)"));
427 }
428 }
429
430 @Override
431 public void stateChanged(ChangeEvent e) {
432 refresh();
433 }
434 }
435}
Note: See TracBrowser for help on using the repository browser.