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

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

fix #12652 - Do not ...snip... bug report messages after 6000 characters (patch by michael2402, modified)

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