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

Last change on this file since 10755 was 10254, checked in by Don-vip, 8 years ago

sonar - squid:S1948 - Fields in a "Serializable" class should either be transient or serializable

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