source: josm/trunk/src/org/openstreetmap/josm/data/imagery/OffsetBookmark.java@ 13798

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

see #13937 - code cleanup

  • Property svn:eol-style set to native
File size: 14.3 KB
RevLine 
[3719]1// License: GPL. For details, see LICENSE file.
[3715]2package org.openstreetmap.josm.data.imagery;
3
4import java.util.ArrayList;
5import java.util.Collections;
6import java.util.List;
[3734]7import java.util.ListIterator;
[12134]8import java.util.Map;
[13797]9import java.util.Objects;
10import java.util.stream.Collectors;
[3715]11
12import org.openstreetmap.josm.Main;
[12851]13import org.openstreetmap.josm.data.StructUtils;
14import org.openstreetmap.josm.data.StructUtils.StructEntry;
15import org.openstreetmap.josm.data.StructUtils.WriteExplicitly;
[12084]16import org.openstreetmap.josm.data.coor.EastNorth;
[13243]17import org.openstreetmap.josm.data.coor.ILatLon;
[3775]18import org.openstreetmap.josm.data.coor.LatLon;
[12093]19import org.openstreetmap.josm.data.projection.Projection;
20import org.openstreetmap.josm.data.projection.Projections;
[12630]21import org.openstreetmap.josm.gui.MainApplication;
[10742]22import org.openstreetmap.josm.gui.layer.AbstractTileSourceLayer;
[3715]23import org.openstreetmap.josm.gui.layer.ImageryLayer;
[12846]24import org.openstreetmap.josm.spi.preferences.Config;
[12620]25import org.openstreetmap.josm.tools.Logging;
[3715]26
[12093]27/**
28 * Class to save a displacement of background imagery as a bookmark.
29 *
30 * Known offset bookmarks will be stored in the preferences and can be
31 * restored by the user in later sessions.
32 */
[3715]33public class OffsetBookmark {
[11651]34 private static final List<OffsetBookmark> allBookmarks = new ArrayList<>();
[3715]35
[12851]36 @StructEntry private String projection_code;
[13797]37 @StructEntry private String imagery_id;
38 /** Imagery localized name. Locale insensitive {@link #imagery_id} is preferred. */
[12851]39 @StructEntry private String imagery_name;
40 @StructEntry private String name;
41 @StructEntry @WriteExplicitly private double dx, dy;
42 @StructEntry private double center_lon, center_lat;
[3715]43
[13243]44 /**
45 * Test if an image is usable for the given imagery layer.
46 * @param layer The layer to use the image at
47 * @return <code>true</code> if it is usable on the projection of the layer and the imagery name matches.
48 */
[3715]49 public boolean isUsable(ImageryLayer layer) {
[12084]50 if (projection_code == null) return false;
[12093]51 if (!Main.getProjection().toCode().equals(projection_code) && !hasCenter()) return false;
[13797]52 ImageryInfo info = layer.getInfo();
53 return imagery_id != null ? Objects.equals(info.getId(), imagery_id) : Objects.equals(info.getName(), imagery_name);
[3715]54 }
[3775]55
[12084]56 /**
57 * Construct new empty OffsetBookmark.
58 *
59 * Only used for preferences handling.
60 */
61 public OffsetBookmark() {
62 // do nothing
[3775]63 }
64
[13243]65 /**
66 * Create a new {@link OffsetBookmark} object using (0, 0) as center
67 * <p>
[13797]68 * The use of the {@link #OffsetBookmark(String, String, String, String, EastNorth, ILatLon)} constructor is preferred.
[13243]69 * @param projectionCode The projection for which this object was created
[13797]70 * @param imageryId The id of the imagery on the layer (locale insensitive)
71 * @param imageryName The name of the imagery on the layer (locale sensitive)
[13243]72 * @param name The name of the new bookmark
73 * @param dx The x displacement
74 * @param dy The y displacement
[13797]75 * @since 13797
[13243]76 */
[13797]77 public OffsetBookmark(String projectionCode, String imageryId, String imageryName, String name, double dx, double dy) {
78 this(projectionCode, imageryId, imageryName, name, dx, dy, 0, 0);
[12084]79 }
80
[13243]81 /**
82 * Create a new {@link OffsetBookmark} object
83 * @param projectionCode The projection for which this object was created
[13797]84 * @param imageryId The id of the imagery on the layer (locale insensitive)
85 * @param imageryName The name of the imagery on the layer (locale sensitive)
[13243]86 * @param name The name of the new bookmark
87 * @param displacement The displacement in east/north space.
88 * @param center The point on earth that was used as reference to align the image.
[13797]89 * @since 13797
[13243]90 */
[13797]91 public OffsetBookmark(String projectionCode, String imageryId, String imageryName, String name, EastNorth displacement, ILatLon center) {
92 this(projectionCode, imageryId, imageryName, name, displacement.east(), displacement.north(), center.lon(), center.lat());
[13243]93 }
94
95 /**
96 * Create a new {@link OffsetBookmark} by specifying all values.
97 * <p>
[13797]98 * The use of the {@link #OffsetBookmark(String, String, String, String, EastNorth, ILatLon)} constructor is preferred.
[13243]99 * @param projectionCode The projection for which this object was created
[13797]100 * @param imageryId The id of the imagery on the layer (locale insensitive)
101 * @param imageryName The name of the imagery on the layer (locale sensitive)
[13243]102 * @param name The name of the new bookmark
103 * @param dx The x displacement
104 * @param dy The y displacement
105 * @param centerLon The point on earth that was used as reference to align the image.
106 * @param centerLat The point on earth that was used as reference to align the image.
[13797]107 * @since 13797
[13243]108 */
[13797]109 public OffsetBookmark(String projectionCode, String imageryId, String imageryName, String name,
110 double dx, double dy, double centerLon, double centerLat) {
[12084]111 this.projection_code = projectionCode;
[13797]112 this.imagery_id = imageryId;
[12084]113 this.imagery_name = imageryName;
[3715]114 this.name = name;
115 this.dx = dx;
116 this.dy = dy;
[12084]117 this.center_lon = centerLon;
118 this.center_lat = centerLat;
[3715]119 }
120
[13243]121 /**
122 * Get the projection code for which this bookmark was created.
123 * @return The projection.
124 */
[12084]125 public String getProjectionCode() {
126 return projection_code;
127 }
128
[13243]129 /**
130 * Get the name of this bookmark. This name can e.g. be displayed in menus.
131 * @return The name
132 */
[12084]133 public String getName() {
134 return name;
135 }
136
[13243]137 /**
[13797]138 * Get the id of the imagery for which this bookmark was created. It is used to match the bookmark to the right layers.
139 * @return The imagery identifier
140 * @since 13797
141 */
142 public String getImageryId() {
143 return imagery_id;
144 }
145
146 /**
147 * Get the name of the imagery for which this bookmark was created.
148 * It is used to match the bookmark to the right layers if id is missing.
[13243]149 * @return The name
150 */
[12084]151 public String getImageryName() {
152 return imagery_name;
153 }
154
[12093]155 /**
156 * Get displacement in EastNorth coordinates of the original projection.
157 *
[12118]158 * @return the displacement
[12093]159 * @see #getProjectionCode()
160 */
161 public EastNorth getDisplacement() {
[12084]162 return new EastNorth(dx, dy);
163 }
164
[12093]165 /**
166 * Get displacement in EastNorth coordinates of a given projection.
167 *
168 * Displacement will be converted to the given projection, with respect to the
169 * center (reference point) of this bookmark.
170 * @param proj the projection
171 * @return the displacement, converted to that projection
172 */
173 public EastNorth getDisplacement(Projection proj) {
174 if (proj.toCode().equals(projection_code)) {
175 return getDisplacement();
176 }
177 LatLon center = getCenter();
178 Projection offsetProj = Projections.getProjectionByCode(projection_code);
[12163]179 EastNorth centerEN = center.getEastNorth(offsetProj);
[12093]180 EastNorth shiftedEN = centerEN.add(getDisplacement());
181 LatLon shifted = offsetProj.eastNorth2latlon(shiftedEN);
[12163]182 EastNorth centerEN2 = center.getEastNorth(proj);
183 EastNorth shiftedEN2 = shifted.getEastNorth(proj);
[12093]184 return shiftedEN2.subtract(centerEN2);
185 }
186
187 /**
188 * Get center/reference point of the bookmark.
189 *
190 * Basically this is the place where it was created and is valid.
[12118]191 * The center may be unrecorded (see {@link #hasCenter()}, in which
[12093]192 * case a dummy center (0,0) will be returned.
193 * @return the center
194 */
[12084]195 public LatLon getCenter() {
196 return new LatLon(center_lat, center_lon);
197 }
198
[12093]199 /**
200 * Check if bookmark has a valid center.
201 * @return true if bookmark has a valid center
202 */
203 public boolean hasCenter() {
204 return center_lat != 0 || center_lon != 0;
205 }
206
[13243]207 /**
208 * Set the projection code for which this bookmark was created
209 * @param projectionCode The projection
210 */
[12084]211 public void setProjectionCode(String projectionCode) {
212 this.projection_code = projectionCode;
213 }
214
[13243]215 /**
216 * Set the name of the bookmark
217 * @param name The name
218 * @see #getName()
219 */
[12084]220 public void setName(String name) {
221 this.name = name;
222 }
223
[13243]224 /**
225 * Sets the name of the imagery
226 * @param imageryName The name
227 * @see #getImageryName()
228 */
[12084]229 public void setImageryName(String imageryName) {
230 this.imagery_name = imageryName;
231 }
232
[13243]233 /**
[13797]234 * Sets the id of the imagery
235 * @param imageryId The identifier
236 * @see #getImageryId()
[13798]237 * @since 13797
[13797]238 */
239 public void setImageryId(String imageryId) {
240 this.imagery_id = imageryId;
241 }
242
243 /**
[13243]244 * Update the displacement of this imagery.
245 * @param displacement The displacement
246 */
[12093]247 public void setDisplacement(EastNorth displacement) {
248 this.dx = displacement.east();
249 this.dy = displacement.north();
[12084]250 }
251
[13243]252 /**
253 * Load the global list of bookmarks from preferences.
254 */
[12084]255 public static void loadBookmarks() {
[12851]256 List<OffsetBookmark> bookmarks = StructUtils.getListOfStructs(
257 Config.getPref(), "imagery.offsetbookmarks", null, OffsetBookmark.class);
[13798]258 if (bookmarks != null) {
[13797]259 sanitizeBookmarks(bookmarks);
[12084]260 allBookmarks.addAll(bookmarks);
[3779]261 }
[3715]262 }
263
[13797]264 static void sanitizeBookmarks(List<OffsetBookmark> bookmarks) {
265 // Retrieve layer id from layer name (it was not available before #13937)
266 bookmarks.stream().filter(b -> b.getImageryId() == null).forEach(b -> {
267 List<ImageryInfo> candidates = ImageryLayerInfo.instance.getLayers().stream()
268 .filter(l -> Objects.equals(l.getName(), b.getImageryName()))
269 .collect(Collectors.toList());
270 // Make sure there is no ambiguity
271 if (candidates.size() == 1) {
272 b.setImageryId(candidates.get(0).getId());
273 } else {
274 Logging.warn("Not a single layer for the name '" + b.getImageryName() + "': " + candidates);
275 }
276 });
277 // Update layer name (locale sensitive) if the locale has changed
278 bookmarks.stream().filter(b -> b.getImageryId() != null).forEach(b -> {
279 ImageryInfo info = ImageryLayerInfo.instance.getLayer(b.getImageryId());
280 if (info != null && !Objects.equals(info.getName(), b.getImageryName())) {
281 b.setImageryName(info.getName());
282 }
283 });
[3715]284 }
285
[13243]286 /**
287 * Stores the bookmakrs in the settings.
288 */
[3715]289 public static void saveBookmarks() {
[12851]290 StructUtils.putListOfStructs(Config.getPref(), "imagery.offsetbookmarks", allBookmarks, OffsetBookmark.class);
[3715]291 }
292
[11651]293 /**
294 * Returns all bookmarks.
295 * @return all bookmarks (unmodifiable collection)
296 * @since 11651
297 */
298 public static List<OffsetBookmark> getBookmarks() {
299 return Collections.unmodifiableList(allBookmarks);
300 }
301
302 /**
303 * Returns the number of bookmarks.
304 * @return the number of bookmarks
305 * @since 11651
306 */
307 public static int getBookmarksSize() {
308 return allBookmarks.size();
309 }
310
311 /**
312 * Adds a bookmark.
313 * @param ob bookmark to add
314 * @return {@code true}
315 * @since 11651
316 */
317 public static boolean addBookmark(OffsetBookmark ob) {
318 return allBookmarks.add(ob);
319 }
320
321 /**
322 * Removes a bookmark.
323 * @param ob bookmark to remove
324 * @return {@code true} if this list contained the specified element
325 * @since 11651
326 */
327 public static boolean removeBookmark(OffsetBookmark ob) {
328 return allBookmarks.remove(ob);
329 }
330
331 /**
332 * Returns the bookmark at the given index.
333 * @param index bookmark index
334 * @return the bookmark at the given index
335 * @throws IndexOutOfBoundsException if the index is out of range
[13493]336 * (<code>index &lt; 0 || index &gt;= size()</code>)
[11651]337 * @since 11651
338 */
339 public static OffsetBookmark getBookmarkByIndex(int index) {
340 return allBookmarks.get(index);
341 }
342
[13243]343 /**
344 * Gets a bookmark that is usable on the given layer by it's name.
345 * @param layer The layer to use the bookmark at
346 * @param name The name of the bookmark
347 * @return The bookmark if found, <code>null</code> if not.
348 */
[3734]349 public static OffsetBookmark getBookmarkByName(ImageryLayer layer, String name) {
350 for (OffsetBookmark b : allBookmarks) {
351 if (b.isUsable(layer) && name.equals(b.name))
352 return b;
353 }
354 return null;
355 }
356
[13243]357 /**
358 * Add a bookmark for the displacement of that layer
359 * @param name The bookmark name
360 * @param layer The layer to store the bookmark for
361 */
362 public static void bookmarkOffset(String name, AbstractTileSourceLayer<?> layer) {
[3775]363 LatLon center;
[12630]364 if (MainApplication.isDisplayingMapView()) {
365 center = Main.getProjection().eastNorth2latlon(MainApplication.getMap().mapView.getCenter());
[3775]366 } else {
[9214]367 center = LatLon.ZERO;
[3775]368 }
[3734]369 OffsetBookmark nb = new OffsetBookmark(
[13797]370 Main.getProjection().toCode(), layer.getInfo().getId(), layer.getInfo().getName(),
[13243]371 name, layer.getDisplaySettings().getDisplacement(), center);
[8510]372 for (ListIterator<OffsetBookmark> it = allBookmarks.listIterator(); it.hasNext();) {
[3734]373 OffsetBookmark b = it.next();
374 if (b.isUsable(layer) && name.equals(b.name)) {
375 it.set(nb);
376 saveBookmarks();
377 return;
378 }
379 }
380 allBookmarks.add(nb);
381 saveBookmarks();
382 }
[12134]383
384 /**
385 * Converts the offset bookmark to a properties map.
386 *
387 * The map contains all the information to restore the offset bookmark.
388 * @return properties map of all data
[12139]389 * @see #fromPropertiesMap(java.util.Map)
[12134]390 * @since 12134
391 */
392 public Map<String, String> toPropertiesMap() {
[12851]393 return StructUtils.serializeStruct(this, OffsetBookmark.class);
[12134]394 }
395
396 /**
397 * Creates an offset bookmark from a properties map.
398 * @param properties the properties map
399 * @return corresponding offset bookmark
[12139]400 * @see #toPropertiesMap()
[12134]401 * @since 12134
402 */
403 public static OffsetBookmark fromPropertiesMap(Map<String, String> properties) {
[12851]404 return StructUtils.deserializeStruct(properties, OffsetBookmark.class);
[12134]405 }
[3715]406}
Note: See TracBrowser for help on using the repository browser.