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

Last change on this file since 12647 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
RevLine 
[2512]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;
[11059]9import java.awt.event.MouseAdapter;
10import java.awt.event.MouseEvent;
[2512]11
12import javax.swing.BorderFactory;
13import javax.swing.JLabel;
14import javax.swing.JPanel;
[10053]15import javax.swing.UIManager;
[10210]16import javax.swing.event.ChangeEvent;
17import javax.swing.event.ChangeListener;
[2512]18
[9441]19import org.openstreetmap.gui.jmapviewer.JMapViewer;
20import org.openstreetmap.gui.jmapviewer.MapMarkerDot;
[11053]21import org.openstreetmap.gui.jmapviewer.tilesources.OsmTileSource;
[2512]22import org.openstreetmap.josm.data.coor.CoordinateFormat;
[5346]23import org.openstreetmap.josm.data.coor.LatLon;
[2512]24import org.openstreetmap.josm.data.osm.history.HistoryNode;
25import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
[4990]26import org.openstreetmap.josm.gui.NavigatableComponent;
[9223]27import org.openstreetmap.josm.gui.util.GuiHelper;
[10053]28import org.openstreetmap.josm.gui.widgets.JosmTextArea;
[2850]29import org.openstreetmap.josm.tools.CheckParameterUtil;
[9441]30import org.openstreetmap.josm.tools.Pair;
[2512]31
32/**
33 * An UI widget for displaying differences in the coordinates of two
[5266]34 * {@link HistoryNode}s.
[9454]35 * @since 2243
[2512]36 */
37public class CoordinateInfoViewer extends JPanel {
38
39 /** the model */
[8308]40 private transient HistoryBrowserModel model;
[2512]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;
[4990]49 /** the info panel for distance between the two coordinates */
50 private DistanceViewer distanceViewer;
[9441]51 /** the map panel showing the old+new coordinate */
52 private MapViewer mapViewer;
[2512]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;
[8510]65 gc.insets = new Insets(5, 5, 5, 0);
[2512]66 gc.fill = GridBagConstraints.HORIZONTAL;
67 gc.anchor = GridBagConstraints.FIRST_LINE_START;
68 referenceInfoPanel = new VersionInfoPanel(model, PointInTimeType.REFERENCE_POINT_IN_TIME);
[8510]69 add(referenceInfoPanel, gc);
[2512]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);
[8510]78 add(currentInfoPanel, gc);
[2512]79
80 // ---------------------------
81 // the two coordinate panels
82 gc.gridx = 0;
83 gc.gridy = 1;
84 gc.weightx = 0.5;
[9441]85 gc.weighty = 0.0;
86 gc.fill = GridBagConstraints.HORIZONTAL;
[2512]87 gc.anchor = GridBagConstraints.NORTHWEST;
[10179]88 referenceLatLonViewer = new LatLonViewer(model, PointInTimeType.REFERENCE_POINT_IN_TIME);
89 add(referenceLatLonViewer, gc);
[2512]90
91 gc.gridx = 1;
92 gc.gridy = 1;
93 gc.weightx = 0.5;
[9441]94 gc.weighty = 0.0;
95 gc.fill = GridBagConstraints.HORIZONTAL;
[2512]96 gc.anchor = GridBagConstraints.NORTHWEST;
[10179]97 currentLatLonViewer = new LatLonViewer(model, PointInTimeType.CURRENT_POINT_IN_TIME);
98 add(currentLatLonViewer, gc);
[4990]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;
[10179]108 distanceViewer = new DistanceViewer(model);
109 add(distanceViewer, gc);
[9441]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;
[10179]118 mapViewer = new MapViewer(model);
119 add(mapViewer, gc);
[9441]120 mapViewer.setZoomContolsVisible(false);
[2512]121 }
122
123 /**
[8372]124 * Constructs a new {@code CoordinateInfoViewer}.
[2512]125 * @param model the model. Must not be null.
[8291]126 * @throws IllegalArgumentException if model is null
[2512]127 */
[8291]128 public CoordinateInfoViewer(HistoryBrowserModel model) {
[2850]129 CheckParameterUtil.ensureParameterNotNull(model, "model");
[2512]130 setModel(model);
131 build();
[10210]132 registerAsChangeListener(model);
[2512]133 }
134
[10210]135 protected void unregisterAsChangeListener(HistoryBrowserModel model) {
[2512]136 if (currentInfoPanel != null) {
[10210]137 model.removeChangeListener(currentInfoPanel);
[2512]138 }
139 if (referenceInfoPanel != null) {
[10210]140 model.removeChangeListener(referenceInfoPanel);
[2512]141 }
142 if (currentLatLonViewer != null) {
[10210]143 model.removeChangeListener(currentLatLonViewer);
[2512]144 }
145 if (referenceLatLonViewer != null) {
[10210]146 model.removeChangeListener(referenceLatLonViewer);
[2512]147 }
[4990]148 if (distanceViewer != null) {
[10210]149 model.removeChangeListener(distanceViewer);
[4990]150 }
[9441]151 if (mapViewer != null) {
[10210]152 model.removeChangeListener(mapViewer);
[9441]153 }
[2512]154 }
155
[10210]156 protected void registerAsChangeListener(HistoryBrowserModel model) {
[2512]157 if (currentInfoPanel != null) {
[10210]158 model.addChangeListener(currentInfoPanel);
[2512]159 }
160 if (referenceInfoPanel != null) {
[10210]161 model.addChangeListener(referenceInfoPanel);
[2512]162 }
163 if (currentLatLonViewer != null) {
[10210]164 model.addChangeListener(currentLatLonViewer);
[2512]165 }
166 if (referenceLatLonViewer != null) {
[10210]167 model.addChangeListener(referenceLatLonViewer);
[2512]168 }
[4990]169 if (distanceViewer != null) {
[10210]170 model.addChangeListener(distanceViewer);
[4990]171 }
[9441]172 if (mapViewer != null) {
[10210]173 model.addChangeListener(mapViewer);
[9441]174 }
[2512]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) {
[10210]184 unregisterAsChangeListener(model);
[2512]185 }
186 this.model = model;
187 if (this.model != null) {
[10210]188 registerAsChangeListener(model);
[2512]189 }
190 }
191
[9453]192 /**
193 * Pans the map to the old+new coordinate
194 * @see JMapViewer#setDisplayToFitMapMarkers()
195 */
196 public void setDisplayToFitMapMarkers() {
197 mapViewer.setDisplayToFitMapMarkers();
198 }
199
[10053]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
[9441]210 private static class Updater {
[9977]211 private final HistoryBrowserModel model;
[9078]212 private final PointInTimeType role;
[2512]213
[9453]214 protected Updater(HistoryBrowserModel model, PointInTimeType role) {
[9441]215 this.model = model;
216 this.role = role;
217 }
[8372]218
[2512]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
[9441]231 protected final Pair<LatLon, LatLon> getCoordinates() {
232 HistoryOsmPrimitive p = getPrimitive();
[11878]233 if (!(p instanceof HistoryNode)) return null;
[9441]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 /**
[10053]244 * A UI widgets which displays the Lan/Lon-coordinates of a {@link HistoryNode}.
[9441]245 */
[10210]246 private static class LatLonViewer extends JPanel implements ChangeListener {
[9441]247
[10053]248 private final JosmTextArea lblLat = newTextArea();
249 private final JosmTextArea lblLon = newTextArea();
[10254]250 private final transient Updater updater;
[9441]251 private final Color modifiedColor;
252
[2512]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;
[8510]263 gc.insets = new Insets(5, 5, 5, 5);
[2512]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;
[10053]272 add(lblLat, gc);
[2512]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;
[10053]287 add(lblLon, gc);
[2512]288 }
289
290 /**
[10055]291 * Constructs a new {@code LatLonViewer}.
[2512]292 * @param model a model
293 * @param role the role for this viewer.
294 */
[8836]295 LatLonViewer(HistoryBrowserModel model, PointInTimeType role) {
[9441]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();
[2512]300 build();
301 }
302
[8372]303 protected void refresh() {
[9441]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;
[8372]308
[2512]309 // display the coordinates
[5356]310 lblLat.setText(coord != null ? coord.latToString(CoordinateFormat.DECIMAL_DEGREES) : tr("(none)"));
311 lblLon.setText(coord != null ? coord.lonToString(CoordinateFormat.DECIMAL_DEGREES) : tr("(none)"));
[2512]312
313 // update background color to reflect differences in the coordinates
[6070]314 if (coord == oppositeCoord ||
[5346]315 (coord != null && oppositeCoord != null && coord.lat() == oppositeCoord.lat())) {
[9223]316 GuiHelper.setBackgroundReadable(lblLat, Color.WHITE);
[2512]317 } else {
[9441]318 GuiHelper.setBackgroundReadable(lblLat, modifiedColor);
[2512]319 }
[6070]320 if (coord == oppositeCoord ||
[5346]321 (coord != null && oppositeCoord != null && coord.lon() == oppositeCoord.lon())) {
[9223]322 GuiHelper.setBackgroundReadable(lblLon, Color.WHITE);
[2512]323 } else {
[9441]324 GuiHelper.setBackgroundReadable(lblLon, modifiedColor);
[2512]325 }
326 }
327
[6084]328 @Override
[10210]329 public void stateChanged(ChangeEvent e) {
[2512]330 refresh();
331 }
332 }
[6070]333
[10210]334 private static class MapViewer extends JMapViewer implements ChangeListener {
[4990]335
[10254]336 private final transient Updater updater;
[9441]337
[9454]338 MapViewer(HistoryBrowserModel model) {
[9441]339 this.updater = new Updater(model, PointInTimeType.REFERENCE_POINT_IN_TIME);
[11053]340 setTileSource(new OsmTileSource.Mapnik()); // for attribution
[9441]341 setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
[11059]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 });
[9441]350 }
351
352 @Override
[10210]353 public void stateChanged(ChangeEvent e) {
[9441]354 final Pair<LatLon, LatLon> coordinates = updater.getCoordinates();
355 if (coordinates == null) {
356 return;
357 }
358
[9483]359 removeAllMapMarkers();
[9441]360
[9483]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
[9441]372 setDisplayToFitMapMarkers();
373 }
374 }
375
[10210]376 private static class DistanceViewer extends JPanel implements ChangeListener {
[9441]377
[10053]378 private final JosmTextArea lblDistance = newTextArea();
[10254]379 private final transient Updater updater;
[6070]380
[8836]381 DistanceViewer(HistoryBrowserModel model) {
[9441]382 this.updater = new Updater(model, PointInTimeType.REFERENCE_POINT_IN_TIME);
383 build();
[4990]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;
[8510]396 gc.insets = new Insets(5, 5, 5, 5);
[4990]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;
[10053]405 add(lblDistance, gc);
[4990]406 }
407
408 protected void refresh() {
[9441]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;
[4990]413
414 // update distance
415 //
[5346]416 if (coord != null && oppositeCoord != null) {
417 double distance = coord.greatCircleDistance(oppositeCoord);
[9441]418 GuiHelper.setBackgroundReadable(lblDistance, distance > 0
419 ? TwoColumnDiff.Item.DiffItemType.CHANGED.getColor()
420 : Color.WHITE);
[5346]421 lblDistance.setText(NavigatableComponent.getDistText(distance));
[4990]422 } else {
[9441]423 GuiHelper.setBackgroundReadable(lblDistance, coord != oppositeCoord
424 ? TwoColumnDiff.Item.DiffItemType.CHANGED.getColor()
425 : Color.WHITE);
[5356]426 lblDistance.setText(tr("(none)"));
[4990]427 }
428 }
[9441]429
430 @Override
[10210]431 public void stateChanged(ChangeEvent e) {
[9441]432 refresh();
433 }
[4990]434 }
[2512]435}
Note: See TracBrowser for help on using the repository browser.