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

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

fix #12620 - minor layout issue in node coordinate history tab

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