Changeset 31328 in osm for applications/editors/josm/plugins/mapillary/src/org
- Timestamp:
- 2015-07-01T22:11:56+02:00 (10 years ago)
- Location:
- applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary
- Files:
-
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryAbstractImage.java
r31311 r31328 6 6 import java.util.Calendar; 7 7 import java.util.TimeZone; 8 import java.util.concurrent.locks.Lock; 9 import java.util.concurrent.locks.ReentrantLock; 8 10 9 11 import org.openstreetmap.josm.Main; … … 18 20 */ 19 21 public abstract class MapillaryAbstractImage { 22 23 public static Lock lock = new ReentrantLock(); 20 24 21 25 private long capturedAt; … … 147 151 else 148 152 format += "dd/MM/yyyy"; 149 if (Main.pref.getBoolean("mapillary.display-hour", true)){ 153 if (Main.pref.getBoolean("mapillary.display-hour", true)) { 150 154 if (Main.pref.getBoolean("mapillary.format-24")) 151 155 format += " - HH:mm:ss (z)"; … … 177 181 return formatter.format(date); 178 182 } 179 183 180 184 public long getEpoch(String date, String format) { 181 185 182 186 SimpleDateFormat formatter = new SimpleDateFormat(format); 183 187 try { 184 188 Date dateTime = (Date) formatter.parse(date); 185 return dateTime.getTime(); 189 return dateTime.getTime(); 186 190 } catch (ParseException e) { 187 191 Main.error(e); … … 189 193 return currentTime(); 190 194 } 191 195 192 196 private long currentTime() { 193 197 Calendar cal = Calendar.getInstance(); -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java
r31315 r31328 20 20 */ 21 21 public class MapillaryData implements ICachedLoaderListener { 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 22 public volatile static MapillaryData INSTANCE; 23 public static boolean TEST_MODE = false; 24 25 private final List<MapillaryAbstractImage> images; 26 private MapillaryAbstractImage selectedImage; 27 private MapillaryAbstractImage hoveredImage; 28 private final List<MapillaryAbstractImage> multiSelectedImages; 29 30 private List<MapillaryDataListener> listeners = new ArrayList<>(); 31 32 public MapillaryData() { 33 images = new CopyOnWriteArrayList<>(); 34 multiSelectedImages = new ArrayList<>(); 35 selectedImage = null; 36 } 37 38 public static MapillaryData getInstance() { 39 if (INSTANCE == null) { 40 INSTANCE = new MapillaryData(); 41 } 42 return INSTANCE; 43 } 44 45 /** 46 * Adds a set of MapillaryImages to the object, and then repaints mapView. 47 * 48 * @param images 49 * The set of images to be added. 50 */ 51 public synchronized void add(List<MapillaryAbstractImage> images) { 52 for (MapillaryAbstractImage image : images) { 53 add(image); 54 } 55 } 56 57 /** 58 * Adds an MapillaryImage to the object, and then repaints mapView. 59 * 60 * @param image 61 * The image to be added. 62 */ 63 public synchronized void add(MapillaryAbstractImage image) { 64 if (!images.contains(image)) { 65 this.images.add(image); 66 } 67 dataUpdated(); 68 fireImagesAdded(); 69 } 70 71 public void addListener(MapillaryDataListener lis) { 72 listeners.add(lis); 73 } 74 75 public void removeListener(MapillaryDataListener lis) { 76 listeners.remove(lis); 77 } 78 79 /** 80 * Adds a set of MapillaryImages to the object, but doesn't repaint mapView. 81 * This is needed for concurrency. 82 * 83 * @param images 84 * The set of images to be added. 85 */ 86 public synchronized void addWithoutUpdate( 87 List<MapillaryAbstractImage> images) { 88 for (MapillaryAbstractImage image : images) { 89 addWithoutUpdate(image); 90 } 91 } 92 93 /** 94 * Sets the image under the mouse cursor. 95 * 96 * @param image 97 */ 98 public void setHoveredImage(MapillaryAbstractImage image) { 99 hoveredImage = image; 100 } 101 102 /** 103 * Returns the image under the mouse cursor. 104 * 105 * @return 106 */ 107 public MapillaryAbstractImage getHoveredImage() { 108 return hoveredImage; 109 } 110 111 /** 112 * Adds a MapillaryImage to the object, but doesn't repaint mapView. This is 113 * needed for concurrency. 114 * 115 * @param image 116 * The image to be added. 117 */ 118 public synchronized void addWithoutUpdate(MapillaryAbstractImage image) { 119 if (!images.contains(image)) { 120 this.images.add(image); 121 } 122 fireImagesAdded(); 123 } 124 125 /** 126 * Repaints mapView object. 127 */ 128 public synchronized void dataUpdated() { 129 if (!TEST_MODE) 130 Main.map.mapView.repaint(); 131 } 132 133 /** 134 * Returns a List containing all images. 135 * 136 * @return A List object containing all images. 137 */ 138 public List<MapillaryAbstractImage> getImages() { 139 return images; 140 } 141 142 /** 143 * Returns the MapillaryImage object that is currently selected. 144 * 145 * @return The selected MapillaryImage object. 146 */ 147 public MapillaryAbstractImage getSelectedImage() { 148 return selectedImage; 149 } 150 151 private void fireImagesAdded() { 152 if (listeners.isEmpty()) 153 return; 154 for (MapillaryDataListener lis : listeners) 155 lis.imagesAdded(); 156 } 157 158 /** 159 * If the selected MapillaryImage is part of a MapillarySequence then the 160 * following visible MapillaryImage is selected. In case there is none, does 161 * nothing. 162 */ 163 public void selectNext() { 164 if (getSelectedImage() instanceof MapillaryImage) { 165 if (getSelectedImage() == null) 166 return; 167 if (((MapillaryImage) getSelectedImage()).getSequence() == null) 168 return; 169 if (selectedImage instanceof MapillaryImage 170 && ((MapillaryImage) selectedImage).getSequence() != null) { 171 MapillaryImage tempImage = (MapillaryImage) selectedImage; 172 while (tempImage.next() != null) { 173 tempImage = tempImage.next(); 174 if (tempImage.isVisible()) { 175 setSelectedImage(tempImage, Main.pref.getBoolean( 176 "mapillary.move-to-picture", true)); 177 break; 178 } 179 } 180 } 181 } 182 } 183 184 /** 185 * If the selected MapillaryImage is part of a MapillarySequence then the 186 * previous visible MapillaryImage is selected. In case there is none, does 187 * nothing. 188 */ 189 public void selectPrevious() { 190 if (getSelectedImage() instanceof MapillaryImage) { 191 if (getSelectedImage() == null) 192 return; 193 if (((MapillaryImage) getSelectedImage()).getSequence() == null) 194 throw new IllegalStateException(); 195 if (selectedImage instanceof MapillaryImage 196 && ((MapillaryImage) selectedImage).getSequence() != null) { 197 MapillaryImage tempImage = (MapillaryImage) selectedImage; 198 while (tempImage.previous() != null) { 199 tempImage = tempImage.previous(); 200 if (tempImage.isVisible()) { 201 setSelectedImage(tempImage, Main.pref.getBoolean( 202 "mapillary.move-to-picture", true)); 203 break; 204 } 205 } 206 } 207 } 208 } 209 210 /** 211 * Selects a new image and then starts a new MapillaryImageDownloadThread 212 * thread in order to download its surrounding thumbnails. If the user does 213 * ctrl+click, this isn't triggered. 214 * 215 * @param image 216 * The MapillaryImage which is going to be selected 217 */ 218 public void setSelectedImage(MapillaryAbstractImage image) { 219 setSelectedImage(image, false); 220 } 221 222 /** 223 * Selects a new image and then starts a new MapillaryImageDownloadThread 224 * thread in order to download its surrounding thumbnails. If the user does 225 * ctrl+click, this isn't triggered. You can choose whether to center the 226 * view on the new image or not. 227 * 228 * @param image 229 * @param zoom 230 */ 231 public void setSelectedImage(MapillaryAbstractImage image, boolean zoom) { 232 MapillaryAbstractImage oldImage = selectedImage; 233 selectedImage = image; 234 multiSelectedImages.clear(); 235 multiSelectedImages.add(image); 236 if (image != null) { 237 if (image instanceof MapillaryImage) { 238 MapillaryImage mapillaryImage = (MapillaryImage) image; 239 if (mapillaryImage.next() != null) { 240 new MapillaryCache(mapillaryImage.next().getKey(), 241 MapillaryCache.Type.THUMBNAIL).submit(this, false); 242 if (mapillaryImage.next().next() != null) 243 new MapillaryCache(mapillaryImage.next().next() 244 .getKey(), MapillaryCache.Type.THUMBNAIL) 245 .submit(this, false); 246 } 247 if (mapillaryImage.previous() != null) { 248 new MapillaryCache(mapillaryImage.previous().getKey(), 249 MapillaryCache.Type.THUMBNAIL).submit(this, false); 250 if (mapillaryImage.previous().previous() != null) 251 new MapillaryCache(mapillaryImage.previous().previous() 252 .getKey(), MapillaryCache.Type.THUMBNAIL) 253 .submit(this, false); 254 } 255 } 256 } 257 if (zoom) 258 Main.map.mapView.zoomTo(MapillaryData.getInstance() 259 .getSelectedImage().getLatLon()); 260 if (Main.map != null) 261 Main.map.mapView.repaint(); 262 fireSelectedImageChanged(oldImage, selectedImage); 263 } 264 265 private void fireSelectedImageChanged(MapillaryAbstractImage oldImage, 266 MapillaryAbstractImage newImage) { 267 if (listeners.isEmpty()) 268 return; 269 for (MapillaryDataListener lis : listeners) 270 lis.selectedImageChanged(oldImage, newImage); 271 } 272 273 /** 274 * Adds a MapillaryImage object to the list of selected images, (when ctrl + 275 * click) 276 * 277 * @param image 278 * The MapillaryImage object to be added. 279 */ 280 public void addMultiSelectedImage(MapillaryAbstractImage image) { 281 if (!this.multiSelectedImages.contains(image)) { 282 if (this.getSelectedImage() != null) 283 this.multiSelectedImages.add(image); 284 else 285 this.setSelectedImage(image); 286 } 287 Main.map.mapView.repaint(); 288 } 289 290 /** 291 * Adds a set of MapillaryImage objects to the list of selected images. 292 * 293 * @param images 294 */ 295 public void addMultiSelectedImage(List<MapillaryAbstractImage> images) { 296 for (MapillaryAbstractImage image : images) 297 if (!this.multiSelectedImages.contains(image)) { 298 if (this.getSelectedImage() != null) 299 this.multiSelectedImages.add(image); 300 else 301 this.setSelectedImage(image); 302 } 303 Main.map.mapView.repaint(); 304 } 305 306 /** 307 * Returns a list containing all MapillaryImage objects selected with ctrl + 308 * click 309 * 310 * @return 311 */ 312 public List<MapillaryAbstractImage> getMultiSelectedImages() { 313 return multiSelectedImages; 314 } 315 316 /** 317 * This is empty because it is used just to make sure that certain images 318 * have already been downloaded. 319 */ 320 @Override 321 public void loadingFinished(CacheEntry data, 322 CacheEntryAttributes attributes, LoadResult result) { 323 // DO NOTHING 324 } 325 326 /** 327 * Returns the amount of images contained by this object. 328 * 329 * @return 330 */ 331 public int size() { 332 return images.size(); 333 } 334 334 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryDataListener.java
r31284 r31328 2 2 3 3 public interface MapillaryDataListener { 4 4 5 5 public void imagesAdded(); 6 6 7 7 /** 8 8 * Fired when the selected image is changed by something different from -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImage.java
r31322 r31328 12 12 */ 13 13 public class MapillaryImage extends MapillaryAbstractImage { 14 15 16 17 14 /** Unique identifier of the object */ 15 private final String key; 16 /** Sequence of pictures containing this object */ 17 private MapillarySequence sequence; 18 18 19 20 21 22 23 24 19 /** Epoch time when the image was taken. */ 20 /** The user that made the image */ 21 private String user; 22 /** Set of traffic signs in the image */ 23 private List<String> signs; 24 private String location; 25 25 26 27 28 26 public String getLocation() { 27 return location; 28 } 29 29 30 31 32 30 public void setLocation(String location) { 31 this.location = location; 32 } 33 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 34 /** 35 * Main contructor of the class MapillaryImage 36 * 37 * @param key 38 * The unique identifier of the image. 39 * @param lat 40 * The latitude where it is positioned. 41 * @param lon 42 * The longitude where it is positioned. 43 * @param ca 44 * The direction of the images in degrees, meaning 0 north. 45 */ 46 public MapillaryImage(String key, double lat, double lon, double ca) { 47 super(lat, lon, ca); 48 this.key = key; 49 this.signs = new ArrayList<>(); 50 } 51 51 52 53 54 55 56 57 58 59 52 /** 53 * Returns the unique identifier of the object. 54 * 55 * @return A String containing the unique identifier of the object. 56 */ 57 public String getKey() { 58 return this.key; 59 } 60 60 61 62 63 64 65 66 67 68 61 /** 62 * Adds a new sign to the set of signs. 63 * 64 * @param sign 65 */ 66 public void addSign(String sign) { 67 signs.add(sign); 68 } 69 69 70 71 72 70 public List<String> getSigns() { 71 return signs; 72 } 73 73 74 75 76 74 public void setUser(String user) { 75 this.user = user; 76 } 77 77 78 79 80 78 public String getUser() { 79 return user; 80 } 81 81 82 83 84 85 86 87 88 89 90 82 /** 83 * Sets the MapillarySequence object which contains the MapillaryImage. 84 * 85 * @param sequence 86 * The MapillarySequence that contains the MapillaryImage. 87 */ 88 public void setSequence(MapillarySequence sequence) { 89 this.sequence = sequence; 90 } 91 91 92 93 94 95 96 97 98 99 92 /** 93 * Returns the sequence which contains this image. 94 * 95 * @return The MapillarySequence object that contains this MapillaryImage. 96 */ 97 public MapillarySequence getSequence() { 98 return this.sequence; 99 } 100 100 101 102 103 104 101 public String toString() { 102 return "Image[key=" + this.key + ";lat=" + this.latLon.lat() + ";lon=" 103 + this.latLon.lon() + ";ca=" + this.ca + "]"; 104 } 105 105 106 /** 107 * If the MapillaryImage belongs to a MapillarySequence, returns the next 108 * MapillarySequence in it. 109 * 110 * @return The following MapillaryImage, or null if there is none. 111 */ 112 public MapillaryImage next() { 113 if (this.getSequence() == null) 114 return null; 115 return this.getSequence().next(this); 116 } 106 /** 107 * If the MapillaryImage belongs to a MapillarySequence, returns the next 108 * MapillarySequence in it. 109 * 110 * @return The following MapillaryImage, or null if there is none. 111 */ 112 public MapillaryImage next() { 113 synchronized (lock) { 114 if (this.getSequence() == null) 115 return null; 116 return this.getSequence().next(this); 117 } 118 } 117 119 118 /** 119 * If the MapillaryImage belongs to a MapillarySequence, returns the 120 * previous MapillarySequence in it. 121 * 122 * @return The previous MapillaryImage, or null if there is none. 123 */ 124 public MapillaryImage previous() { 125 if (this.getSequence() == null) 126 return null; 127 return this.getSequence().previous(this); 128 } 120 /** 121 * If the MapillaryImage belongs to a MapillarySequence, returns the 122 * previous MapillarySequence in it. 123 * 124 * @return The previous MapillaryImage, or null if there is none. 125 */ 126 public MapillaryImage previous() { 127 synchronized (lock) { 128 if (this.getSequence() == null) 129 return null; 130 return this.getSequence().previous(this); 131 } 132 } 129 133 130 131 132 133 134 135 134 @Override 135 public boolean equals(Object object) { 136 if (object instanceof MapillaryImage) 137 return this.key.equals(((MapillaryImage) object).getKey()); 138 return false; 139 } 136 140 137 138 139 140 141 @Override 142 public int hashCode() { 143 return this.key.hashCode(); 144 } 141 145 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImportedImage.java
r31319 r31328 16 16 protected File file; 17 17 public final long datetimeOriginal; 18 18 19 19 public MapillaryImportedImage(double lat, double lon, double ca, File file) { 20 20 this(lat, lon, ca, file, currentDate()); 21 21 } 22 22 … … 25 25 super(lat, lon, ca); 26 26 this.file = file; 27 this.datetimeOriginal = getEpoch(datetimeOriginal, "yyyy:MM:dd hh:mm:ss"); 27 this.datetimeOriginal = getEpoch(datetimeOriginal, 28 "yyyy:MM:dd hh:mm:ss"); 28 29 } 29 30 … … 53 54 return this.file.hashCode(); 54 55 } 55 56 56 57 private static String currentDate() { 57 58 Calendar cal = Calendar.getInstance(); -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java
r31322 r31328 59 59 60 60 public class MapillaryLayer extends AbstractModifiableLayer implements 61 DataSetListener, EditLayerChangeListener, LayerChangeListener { 62 63 public final static int SEQUENCE_MAX_JUMP_DISTANCE = Main.pref.getInteger( 64 "mapillary.sequence-max-jump-distance", 100); 65 66 public static MapillaryLayer INSTANCE; 67 public static CacheAccess<String, BufferedImageCacheEntry> CACHE; 68 public static MapillaryImage BLUE; 69 public static MapillaryImage RED; 70 71 public final MapillaryData data = MapillaryData.getInstance(); 72 73 public ArrayList<Bounds> bounds; 74 75 private MouseAdapter mouseAdapter; 76 77 private int highlightPointRadius = Main.pref.getInteger( 78 "mappaint.highlight.radius", 7); 79 private int highlightStep = Main.pref.getInteger("mappaint.highlight.step", 80 4); 81 82 private volatile TexturePaint hatched; 83 84 public MapillaryLayer() { 85 super(tr("Mapillary Images")); 86 bounds = new ArrayList<>(); 87 init(); 88 } 89 90 /** 91 * Initializes the Layer. 92 */ 93 private void init() { 94 MapillaryLayer.INSTANCE = this; 95 startMouseAdapter(); 96 try { 97 CACHE = JCSCacheManager.getCache("Mapillary"); 98 } catch (IOException e) { 99 Main.error(e); 100 } 101 if (Main.map != null && Main.map.mapView != null) { 102 Main.map.mapView.addMouseListener(mouseAdapter); 103 Main.map.mapView.addMouseMotionListener(mouseAdapter); 104 Main.map.mapView.addLayer(this); 105 MapView.addEditLayerChangeListener(this, false); 106 MapView.addLayerChangeListener(this); 107 if (Main.map.mapView.getEditLayer() != null) 108 Main.map.mapView.getEditLayer().data.addDataSetListener(this); 109 } 110 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, true); 111 if (!MapillaryToggleDialog.getInstance().isShowing()) 112 MapillaryToggleDialog.getInstance().getButton().doClick(); 113 createHatchTexture(); 114 data.dataUpdated(); 115 } 116 117 private void startMouseAdapter() { 118 mouseAdapter = new MapillaryMouseAdapter(); 119 } 120 121 public synchronized static MapillaryLayer getInstance() { 122 if (MapillaryLayer.INSTANCE == null) 123 MapillaryLayer.INSTANCE = new MapillaryLayer(); 124 return MapillaryLayer.INSTANCE; 125 } 126 127 /** 128 * Downloads all images of the area covered by the OSM data. This is only 129 * just for automatic download. 130 */ 131 public void download() { 132 checkBigAreas(); 133 if (Main.pref.getBoolean("mapillary.download-manually")) 134 return; 135 for (Bounds bounds : Main.map.mapView.getEditLayer().data 136 .getDataSourceBounds()) { 137 if (!this.bounds.contains(bounds)) { 138 this.bounds.add(bounds); 139 new MapillaryDownloader().getImages(bounds.getMin(), 140 bounds.getMax()); 141 } 142 } 143 } 144 145 /** 146 * Checks if the area of the OSM data is too big. This means that probably 147 * lots of Mapillary images are going to be downloaded, slowing down the 148 * program too much. To solve this the automatic is stopped, an alert is 149 * shown and you will have to download areas manually. 150 */ 151 private void checkBigAreas() { 152 double area = 0; 153 for (Bounds bounds : Main.map.mapView.getEditLayer().data 154 .getDataSourceBounds()) { 155 area += bounds.getArea(); 156 } 157 if (area > MapillaryDownloadViewAction.MAX_AREA) { 158 Main.pref.put("mapillary.download-manually", true); 159 JOptionPane 160 .showMessageDialog( 161 Main.parent, 162 tr("The downloaded OSM area is too big. Download mode has been change to manual. You can change this back to automatic in preferences settings.")); 163 } 164 } 165 166 /** 167 * Returns the MapillaryData object, which acts as the database of the 168 * Layer. 169 * 170 * @return 171 */ 172 public MapillaryData getMapillaryData() { 173 return data; 174 } 175 176 /** 177 * Method invoked when the layer is destroyed. 178 */ 179 @Override 180 public void destroy() { 181 MapillaryToggleDialog.getInstance().mapillaryImageDisplay 182 .setImage(null); 183 MapillaryToggleDialog.getInstance().updateImage(); 184 data.getImages().clear(); 185 MapillaryLayer.INSTANCE = null; 186 MapillaryData.INSTANCE = null; 187 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, false); 188 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.ZOOM_MENU, false); 189 Main.map.mapView.removeMouseListener(mouseAdapter); 190 Main.map.mapView.removeMouseMotionListener(mouseAdapter); 191 MapView.removeEditLayerChangeListener(this); 192 if (Main.map.mapView.getEditLayer() != null) 193 Main.map.mapView.getEditLayer().data.removeDataSetListener(this); 194 super.destroy(); 195 } 196 197 /** 198 * Returns true any of the images from the database has been modified. 199 */ 200 @Override 201 public boolean isModified() { 202 for (MapillaryAbstractImage image : data.getImages()) 203 if (image.isModified()) 204 return true; 205 return false; 206 } 207 208 @Override 209 public void setVisible(boolean visible) { 210 super.setVisible(visible); 211 for (MapillaryAbstractImage img : data.getImages()) 212 img.setVisible(visible); 213 MapillaryFilterDialog.getInstance().refresh(); 214 } 215 216 /** 217 * Replies background color for downloaded areas. 218 * 219 * @return background color for downloaded areas. Black by default 220 */ 221 private Color getBackgroundColor() { 222 return Main.pref.getColor(marktr("background"), Color.BLACK); 223 } 224 225 /** 226 * Replies background color for non-downloaded areas. 227 * 228 * @return background color for non-downloaded areas. Yellow by default 229 */ 230 private Color getOutsideColor() { 231 return Main.pref.getColor(marktr("outside downloaded area"), 232 Color.YELLOW); 233 } 234 235 /** 236 * Initialize the hatch pattern used to paint the non-downloaded area 237 */ 238 private void createHatchTexture() { 239 BufferedImage bi = new BufferedImage(15, 15, 240 BufferedImage.TYPE_INT_ARGB); 241 Graphics2D big = bi.createGraphics(); 242 big.setColor(getBackgroundColor()); 243 Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 244 0.3f); 245 big.setComposite(comp); 246 big.fillRect(0, 0, 15, 15); 247 big.setColor(getOutsideColor()); 248 big.drawLine(0, 15, 15, 0); 249 Rectangle r = new Rectangle(0, 0, 15, 15); 250 hatched = new TexturePaint(bi, r); 251 } 252 253 /** 254 * Paints the database in the map. 255 */ 256 @Override 257 public synchronized void paint(Graphics2D g, MapView mv, Bounds box) { 258 if (Main.map.mapView.getActiveLayer() == this) { 259 Rectangle b = mv.getBounds(); 260 // on some platforms viewport bounds seem to be offset from the 261 // left, 262 // over-grow it just to be sure 263 b.grow(100, 100); 264 Area a = new Area(b); 265 // now successively subtract downloaded areas 266 for (Bounds bounds : this.bounds) { 267 Point p1 = mv.getPoint(bounds.getMin()); 268 Point p2 = mv.getPoint(bounds.getMax()); 269 Rectangle r = new Rectangle(Math.min(p1.x, p2.x), Math.min( 270 p1.y, p2.y), Math.abs(p2.x - p1.x), Math.abs(p2.y 271 - p1.y)); 272 a.subtract(new Area(r)); 273 } 274 // paint remainder 275 g.setPaint(hatched); 276 g.fill(a); 277 } 278 279 // Draw colored lines 280 MapillaryLayer.BLUE = null; 281 MapillaryLayer.RED = null; 282 MapillaryToggleDialog.getInstance().blueButton.setEnabled(false); 283 MapillaryToggleDialog.getInstance().redButton.setEnabled(false); 284 285 // Sets blue and red lines and enables/disables the buttons 286 if (data.getSelectedImage() != null) { 287 MapillaryImage[] closestImages = getClosestImagesFromDifferentSequences(); 288 Point selected = mv.getPoint(data.getSelectedImage().getLatLon()); 289 if (closestImages[0] != null) { 290 MapillaryLayer.BLUE = closestImages[0]; 291 g.setColor(Color.BLUE); 292 g.drawLine(mv.getPoint(closestImages[0].getLatLon()).x, 293 mv.getPoint(closestImages[0].getLatLon()).y, 294 selected.x, selected.y); 295 MapillaryToggleDialog.getInstance().blueButton.setEnabled(true); 296 } 297 if (closestImages[1] != null) { 298 MapillaryLayer.RED = closestImages[1]; 299 g.setColor(Color.RED); 300 g.drawLine(mv.getPoint(closestImages[1].getLatLon()).x, 301 mv.getPoint(closestImages[1].getLatLon()).y, 302 selected.x, selected.y); 303 MapillaryToggleDialog.getInstance().redButton.setEnabled(true); 304 } 305 } 306 g.setColor(Color.WHITE); 307 for (MapillaryAbstractImage imageAbs : data.getImages()) { 308 if (!imageAbs.isVisible()) 309 continue; 310 Point p = mv.getPoint(imageAbs.getLatLon()); 311 if (imageAbs instanceof MapillaryImage) { 312 MapillaryImage image = (MapillaryImage) imageAbs; 313 Point nextp = null; 314 // Draw sequence line 315 if (image.getSequence() != null) { 316 MapillaryImage tempImage = image; 317 while (tempImage.next() != null) { 318 tempImage = tempImage.next(); 319 if (tempImage.isVisible()) { 320 nextp = mv.getPoint(tempImage.getLatLon()); 321 break; 322 } 323 } 324 if (nextp != null) 325 g.drawLine(p.x, p.y, nextp.x, nextp.y); 326 } 327 328 ImageIcon icon; 329 if (!data.getMultiSelectedImages().contains(image)) 330 icon = MapillaryPlugin.MAP_ICON; 331 else 332 icon = MapillaryPlugin.MAP_ICON_SELECTED; 333 draw(g, image, icon, p); 334 if (!image.getSigns().isEmpty()) { 335 g.drawImage(MapillaryPlugin.MAP_SIGN.getImage(), 336 p.x + icon.getIconWidth() / 2, 337 p.y - icon.getIconHeight() / 2, Main.map.mapView); 338 } 339 } else if (imageAbs instanceof MapillaryImportedImage) { 340 MapillaryImportedImage image = (MapillaryImportedImage) imageAbs; 341 ImageIcon icon; 342 if (!data.getMultiSelectedImages().contains(image)) 343 icon = MapillaryPlugin.MAP_ICON_IMPORTED; 344 else 345 icon = MapillaryPlugin.MAP_ICON_SELECTED; 346 draw(g, image, icon, p); 347 } 348 } 349 } 350 351 /** 352 * Draws the highlight of the icon. 353 * 354 * @param g 355 * @param p 356 * @param size 357 */ 358 private void drawPointHighlight(Graphics2D g, Point p, int size) { 359 Color oldColor = g.getColor(); 360 Color highlightColor = PaintColors.HIGHLIGHT.get(); 361 Color highlightColorTransparent = new Color(highlightColor.getRed(), 362 highlightColor.getGreen(), highlightColor.getBlue(), 100); 363 g.setColor(highlightColorTransparent); 364 int s = size + highlightPointRadius; 365 while (s >= size) { 366 int r = (int) Math.floor(s / 2d); 367 g.fillRoundRect(p.x - r, p.y - r, s, s, r, r); 368 s -= highlightStep; 369 } 370 g.setColor(oldColor); 371 } 372 373 /** 374 * Draws the given icon of an image. Also checks if the mouse is over the 375 * image. 376 * 377 * @param g 378 * @param image 379 * @param icon 380 * @param p 381 */ 382 private void draw(Graphics2D g, MapillaryAbstractImage image, 383 ImageIcon icon, Point p) { 384 Image imagetemp = icon.getImage(); 385 BufferedImage bi = (BufferedImage) imagetemp; 386 int width = icon.getIconWidth(); 387 int height = icon.getIconHeight(); 388 389 // Rotate the image 390 double rotationRequired = Math.toRadians(image.getCa()); 391 double locationX = width / 2; 392 double locationY = height / 2; 393 AffineTransform tx = AffineTransform.getRotateInstance( 394 rotationRequired, locationX, locationY); 395 AffineTransformOp op = new AffineTransformOp(tx, 396 AffineTransformOp.TYPE_BILINEAR); 397 398 g.drawImage(op.filter(bi, null), p.x - (width / 2), p.y - (height / 2), 399 Main.map.mapView); 400 if (data.getHoveredImage() == image) { 401 drawPointHighlight(g, p, 16); 402 } 403 } 404 405 @Override 406 public Icon getIcon() { 407 return MapillaryPlugin.ICON16; 408 } 409 410 @Override 411 public boolean isMergable(Layer other) { 412 return false; 413 } 414 415 @Override 416 public void mergeFrom(Layer from) { 417 throw new UnsupportedOperationException( 418 "This layer does not support merging yet"); 419 } 420 421 @Override 422 public Action[] getMenuEntries() { 423 List<Action> actions = new ArrayList<>(); 424 actions.add(LayerListDialog.getInstance().createShowHideLayerAction()); 425 actions.add(LayerListDialog.getInstance().createDeleteLayerAction()); 426 actions.add(new LayerListPopup.InfoAction(this)); 427 return actions.toArray(new Action[actions.size()]); 428 } 429 430 /** 431 * Returns the 2 closest images belonging to a different sequence. 432 * 433 * @return 434 */ 435 private MapillaryImage[] getClosestImagesFromDifferentSequences() { 436 if (!(data.getSelectedImage() instanceof MapillaryImage)) 437 return new MapillaryImage[2]; 438 MapillaryImage selected = (MapillaryImage) data.getSelectedImage(); 439 MapillaryImage[] ret = new MapillaryImage[2]; 440 double[] distances = { SEQUENCE_MAX_JUMP_DISTANCE, 441 SEQUENCE_MAX_JUMP_DISTANCE }; 442 LatLon selectedCoords = data.getSelectedImage().getLatLon(); 443 for (MapillaryAbstractImage imagePrev : data.getImages()) { 444 if (!(imagePrev instanceof MapillaryImage)) 445 continue; 446 if (!imagePrev.isVisible()) 447 continue; 448 MapillaryImage image = (MapillaryImage) imagePrev; 449 if (image.getLatLon().greatCircleDistance(selectedCoords) < SEQUENCE_MAX_JUMP_DISTANCE 450 && selected.getSequence() != image.getSequence()) { 451 if ((ret[0] == null && ret[1] == null) 452 || (image.getLatLon().greatCircleDistance( 453 selectedCoords) < distances[0] && (ret[1] == null || image 454 .getSequence() != ret[1].getSequence()))) { 455 ret[0] = image; 456 distances[0] = image.getLatLon().greatCircleDistance( 457 selectedCoords); 458 } else if ((ret[1] == null || image.getLatLon() 459 .greatCircleDistance(selectedCoords) < distances[1]) 460 && image.getSequence() != ret[0].getSequence()) { 461 ret[1] = image; 462 distances[1] = image.getLatLon().greatCircleDistance( 463 selectedCoords); 464 } 465 } 466 } 467 // Predownloads the thumbnails 468 if (ret[0] != null) 469 new MapillaryCache(ret[0].getKey(), MapillaryCache.Type.THUMBNAIL) 470 .submit(data, false); 471 if (ret[1] != null) 472 new MapillaryCache(ret[1].getKey(), MapillaryCache.Type.THUMBNAIL) 473 .submit(data, false); 474 return ret; 475 } 476 477 @Override 478 public Object getInfoComponent() { 479 StringBuilder sb = new StringBuilder(); 480 sb.append(tr("Mapillary layer")); 481 sb.append("\n"); 482 sb.append(tr("Total images:")); 483 sb.append(" "); 484 sb.append(data.size()); 485 sb.append("\n"); 486 return sb.toString(); 487 } 488 489 @Override 490 public String getToolTipText() { 491 return data.size() + " " + tr("images"); 492 } 493 494 // EditDataLayerChanged 495 @Override 496 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) { 497 if (oldLayer == null && newLayer != null) { 498 newLayer.data.addDataSetListener(this); 499 500 } else if (oldLayer != null && newLayer == null) { 501 oldLayer.data.removeDataSetListener(this); 502 } 503 } 504 505 /** 506 * When more data is downloaded, a delayed update is thrown, in order to 507 * wait for the data bounds to be set. 508 * 509 * @param event 510 */ 511 @Override 512 public void dataChanged(DataChangedEvent event) { 513 Main.worker.submit(new delayedDownload()); 514 } 515 516 private class delayedDownload extends Thread { 517 518 @Override 519 public void run() { 520 try { 521 sleep(1000); 522 } catch (InterruptedException e) { 523 Main.error(e); 524 } 525 MapillaryLayer.getInstance().download(); 526 } 527 } 528 529 @Override 530 public void primitivesAdded(PrimitivesAddedEvent event) { 531 } 532 533 @Override 534 public void primitivesRemoved(PrimitivesRemovedEvent event) { 535 } 536 537 @Override 538 public void tagsChanged(TagsChangedEvent event) { 539 } 540 541 @Override 542 public void nodeMoved(NodeMovedEvent event) { 543 } 544 545 @Override 546 public void wayNodesChanged(WayNodesChangedEvent event) { 547 } 548 549 @Override 550 public void relationMembersChanged(RelationMembersChangedEvent event) { 551 } 552 553 @Override 554 public void otherDatasetChange(AbstractDatasetChangedEvent event) { 555 } 556 557 @Override 558 public void visitBoundingBox(BoundingXYVisitor v) { 559 } 560 561 @Override 562 public void activeLayerChange(Layer oldLayer, Layer newLayer) { 563 if (newLayer == this) { 564 if (data.size() > 0) 565 Main.map.statusLine.setHelpText(tr("Total images: {0}", 566 data.size())); 567 else 568 Main.map.statusLine.setHelpText(tr("No images found")); 569 } 570 } 571 572 @Override 573 public void layerAdded(Layer newLayer) { 574 } 575 576 @Override 577 public void layerRemoved(Layer oldLayer) { 578 } 61 DataSetListener, EditLayerChangeListener, LayerChangeListener { 62 63 public final static int SEQUENCE_MAX_JUMP_DISTANCE = Main.pref.getInteger( 64 "mapillary.sequence-max-jump-distance", 100); 65 66 public static MapillaryLayer INSTANCE; 67 public static CacheAccess<String, BufferedImageCacheEntry> CACHE; 68 public static MapillaryImage BLUE; 69 public static MapillaryImage RED; 70 71 public final MapillaryData data = MapillaryData.getInstance(); 72 73 public ArrayList<Bounds> bounds; 74 75 private MouseAdapter mouseAdapter; 76 77 private int highlightPointRadius = Main.pref.getInteger( 78 "mappaint.highlight.radius", 7); 79 private int highlightStep = Main.pref.getInteger("mappaint.highlight.step", 80 4); 81 82 private volatile TexturePaint hatched; 83 84 public MapillaryLayer() { 85 super(tr("Mapillary Images")); 86 bounds = new ArrayList<>(); 87 init(); 88 } 89 90 /** 91 * Initializes the Layer. 92 */ 93 private void init() { 94 MapillaryLayer.INSTANCE = this; 95 startMouseAdapter(); 96 try { 97 CACHE = JCSCacheManager.getCache("Mapillary"); 98 } catch (IOException e) { 99 Main.error(e); 100 } 101 if (Main.map != null && Main.map.mapView != null) { 102 Main.map.mapView.addMouseListener(mouseAdapter); 103 Main.map.mapView.addMouseMotionListener(mouseAdapter); 104 Main.map.mapView.addLayer(this); 105 MapView.addEditLayerChangeListener(this, false); 106 MapView.addLayerChangeListener(this); 107 if (Main.map.mapView.getEditLayer() != null) 108 Main.map.mapView.getEditLayer().data.addDataSetListener(this); 109 } 110 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, true); 111 if (!MapillaryToggleDialog.getInstance().isShowing()) 112 MapillaryToggleDialog.getInstance().getButton().doClick(); 113 createHatchTexture(); 114 data.dataUpdated(); 115 } 116 117 private void startMouseAdapter() { 118 mouseAdapter = new MapillaryMouseAdapter(); 119 } 120 121 public synchronized static MapillaryLayer getInstance() { 122 if (MapillaryLayer.INSTANCE == null) 123 MapillaryLayer.INSTANCE = new MapillaryLayer(); 124 return MapillaryLayer.INSTANCE; 125 } 126 127 /** 128 * Downloads all images of the area covered by the OSM data. This is only 129 * just for automatic download. 130 */ 131 public void download() { 132 checkBigAreas(); 133 if (Main.pref.getBoolean("mapillary.download-manually")) 134 return; 135 for (Bounds bounds : Main.map.mapView.getEditLayer().data 136 .getDataSourceBounds()) { 137 if (!this.bounds.contains(bounds)) { 138 this.bounds.add(bounds); 139 new MapillaryDownloader().getImages(bounds.getMin(), 140 bounds.getMax()); 141 } 142 } 143 } 144 145 /** 146 * Checks if the area of the OSM data is too big. This means that probably 147 * lots of Mapillary images are going to be downloaded, slowing down the 148 * program too much. To solve this the automatic is stopped, an alert is 149 * shown and you will have to download areas manually. 150 */ 151 private void checkBigAreas() { 152 double area = 0; 153 for (Bounds bounds : Main.map.mapView.getEditLayer().data 154 .getDataSourceBounds()) { 155 area += bounds.getArea(); 156 } 157 if (area > MapillaryDownloadViewAction.MAX_AREA) { 158 Main.pref.put("mapillary.download-manually", true); 159 JOptionPane 160 .showMessageDialog( 161 Main.parent, 162 tr("The downloaded OSM area is too big. Download mode has been change to manual. You can change this back to automatic in preferences settings.")); 163 } 164 } 165 166 /** 167 * Returns the MapillaryData object, which acts as the database of the 168 * Layer. 169 * 170 * @return 171 */ 172 public MapillaryData getMapillaryData() { 173 return data; 174 } 175 176 /** 177 * Method invoked when the layer is destroyed. 178 */ 179 @Override 180 public void destroy() { 181 MapillaryToggleDialog.getInstance().setImage(null); 182 MapillaryToggleDialog.getInstance().updateImage(); 183 data.getImages().clear(); 184 MapillaryLayer.INSTANCE = null; 185 MapillaryData.INSTANCE = null; 186 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, false); 187 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.ZOOM_MENU, false); 188 Main.map.mapView.removeMouseListener(mouseAdapter); 189 Main.map.mapView.removeMouseMotionListener(mouseAdapter); 190 MapView.removeEditLayerChangeListener(this); 191 if (Main.map.mapView.getEditLayer() != null) 192 Main.map.mapView.getEditLayer().data.removeDataSetListener(this); 193 super.destroy(); 194 } 195 196 /** 197 * Returns true any of the images from the database has been modified. 198 */ 199 @Override 200 public boolean isModified() { 201 for (MapillaryAbstractImage image : data.getImages()) 202 if (image.isModified()) 203 return true; 204 return false; 205 } 206 207 @Override 208 public void setVisible(boolean visible) { 209 super.setVisible(visible); 210 for (MapillaryAbstractImage img : data.getImages()) 211 img.setVisible(visible); 212 MapillaryFilterDialog.getInstance().refresh(); 213 } 214 215 /** 216 * Replies background color for downloaded areas. 217 * 218 * @return background color for downloaded areas. Black by default 219 */ 220 private Color getBackgroundColor() { 221 return Main.pref.getColor(marktr("background"), Color.BLACK); 222 } 223 224 /** 225 * Replies background color for non-downloaded areas. 226 * 227 * @return background color for non-downloaded areas. Yellow by default 228 */ 229 private Color getOutsideColor() { 230 return Main.pref.getColor(marktr("outside downloaded area"), 231 Color.YELLOW); 232 } 233 234 /** 235 * Initialize the hatch pattern used to paint the non-downloaded area 236 */ 237 private void createHatchTexture() { 238 BufferedImage bi = new BufferedImage(15, 15, 239 BufferedImage.TYPE_INT_ARGB); 240 Graphics2D big = bi.createGraphics(); 241 big.setColor(getBackgroundColor()); 242 Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 243 0.3f); 244 big.setComposite(comp); 245 big.fillRect(0, 0, 15, 15); 246 big.setColor(getOutsideColor()); 247 big.drawLine(0, 15, 15, 0); 248 Rectangle r = new Rectangle(0, 0, 15, 15); 249 hatched = new TexturePaint(bi, r); 250 } 251 252 /** 253 * Paints the database in the map. 254 */ 255 @Override 256 public synchronized void paint(Graphics2D g, MapView mv, Bounds box) { 257 if (Main.map.mapView.getActiveLayer() == this) { 258 Rectangle b = mv.getBounds(); 259 // on some platforms viewport bounds seem to be offset from the 260 // left, 261 // over-grow it just to be sure 262 b.grow(100, 100); 263 Area a = new Area(b); 264 // now successively subtract downloaded areas 265 for (Bounds bounds : this.bounds) { 266 Point p1 = mv.getPoint(bounds.getMin()); 267 Point p2 = mv.getPoint(bounds.getMax()); 268 Rectangle r = new Rectangle(Math.min(p1.x, p2.x), Math.min( 269 p1.y, p2.y), Math.abs(p2.x - p1.x), Math.abs(p2.y 270 - p1.y)); 271 a.subtract(new Area(r)); 272 } 273 // paint remainder 274 g.setPaint(hatched); 275 g.fill(a); 276 } 277 278 // Draw colored lines 279 MapillaryLayer.BLUE = null; 280 MapillaryLayer.RED = null; 281 MapillaryToggleDialog.getInstance().blueButton.setEnabled(false); 282 MapillaryToggleDialog.getInstance().redButton.setEnabled(false); 283 284 // Sets blue and red lines and enables/disables the buttons 285 if (data.getSelectedImage() != null) { 286 MapillaryImage[] closestImages = getClosestImagesFromDifferentSequences(); 287 Point selected = mv.getPoint(data.getSelectedImage().getLatLon()); 288 if (closestImages[0] != null) { 289 MapillaryLayer.BLUE = closestImages[0]; 290 g.setColor(Color.BLUE); 291 g.drawLine(mv.getPoint(closestImages[0].getLatLon()).x, 292 mv.getPoint(closestImages[0].getLatLon()).y, 293 selected.x, selected.y); 294 MapillaryToggleDialog.getInstance().blueButton.setEnabled(true); 295 } 296 if (closestImages[1] != null) { 297 MapillaryLayer.RED = closestImages[1]; 298 g.setColor(Color.RED); 299 g.drawLine(mv.getPoint(closestImages[1].getLatLon()).x, 300 mv.getPoint(closestImages[1].getLatLon()).y, 301 selected.x, selected.y); 302 MapillaryToggleDialog.getInstance().redButton.setEnabled(true); 303 } 304 } 305 g.setColor(Color.WHITE); 306 for (MapillaryAbstractImage imageAbs : data.getImages()) { 307 if (!imageAbs.isVisible()) 308 continue; 309 Point p = mv.getPoint(imageAbs.getLatLon()); 310 if (imageAbs instanceof MapillaryImage) { 311 MapillaryImage image = (MapillaryImage) imageAbs; 312 Point nextp = null; 313 // Draw sequence line 314 if (image.getSequence() != null) { 315 MapillaryImage tempImage = image.next(); 316 while (tempImage != null) { 317 if (tempImage.isVisible()) { 318 nextp = mv.getPoint(tempImage.getLatLon()); 319 break; 320 } 321 tempImage = tempImage.next(); 322 } 323 if (nextp != null) 324 g.drawLine(p.x, p.y, nextp.x, nextp.y); 325 } 326 327 ImageIcon icon; 328 if (!data.getMultiSelectedImages().contains(image)) 329 icon = MapillaryPlugin.MAP_ICON; 330 else 331 icon = MapillaryPlugin.MAP_ICON_SELECTED; 332 draw(g, image, icon, p); 333 if (!image.getSigns().isEmpty()) { 334 g.drawImage(MapillaryPlugin.MAP_SIGN.getImage(), 335 p.x + icon.getIconWidth() / 2, 336 p.y - icon.getIconHeight() / 2, Main.map.mapView); 337 } 338 } else if (imageAbs instanceof MapillaryImportedImage) { 339 MapillaryImportedImage image = (MapillaryImportedImage) imageAbs; 340 ImageIcon icon; 341 if (!data.getMultiSelectedImages().contains(image)) 342 icon = MapillaryPlugin.MAP_ICON_IMPORTED; 343 else 344 icon = MapillaryPlugin.MAP_ICON_SELECTED; 345 draw(g, image, icon, p); 346 } 347 } 348 } 349 350 /** 351 * Draws the highlight of the icon. 352 * 353 * @param g 354 * @param p 355 * @param size 356 */ 357 private void drawPointHighlight(Graphics2D g, Point p, int size) { 358 Color oldColor = g.getColor(); 359 Color highlightColor = PaintColors.HIGHLIGHT.get(); 360 Color highlightColorTransparent = new Color(highlightColor.getRed(), 361 highlightColor.getGreen(), highlightColor.getBlue(), 100); 362 g.setColor(highlightColorTransparent); 363 int s = size + highlightPointRadius; 364 while (s >= size) { 365 int r = (int) Math.floor(s / 2d); 366 g.fillRoundRect(p.x - r, p.y - r, s, s, r, r); 367 s -= highlightStep; 368 } 369 g.setColor(oldColor); 370 } 371 372 /** 373 * Draws the given icon of an image. Also checks if the mouse is over the 374 * image. 375 * 376 * @param g 377 * @param image 378 * @param icon 379 * @param p 380 */ 381 private void draw(Graphics2D g, MapillaryAbstractImage image, 382 ImageIcon icon, Point p) { 383 Image imagetemp = icon.getImage(); 384 BufferedImage bi = (BufferedImage) imagetemp; 385 int width = icon.getIconWidth(); 386 int height = icon.getIconHeight(); 387 388 // Rotate the image 389 double rotationRequired = Math.toRadians(image.getCa()); 390 double locationX = width / 2; 391 double locationY = height / 2; 392 AffineTransform tx = AffineTransform.getRotateInstance( 393 rotationRequired, locationX, locationY); 394 AffineTransformOp op = new AffineTransformOp(tx, 395 AffineTransformOp.TYPE_BILINEAR); 396 397 g.drawImage(op.filter(bi, null), p.x - (width / 2), p.y - (height / 2), 398 Main.map.mapView); 399 if (data.getHoveredImage() == image) { 400 drawPointHighlight(g, p, 16); 401 } 402 } 403 404 @Override 405 public Icon getIcon() { 406 return MapillaryPlugin.ICON16; 407 } 408 409 @Override 410 public boolean isMergable(Layer other) { 411 return false; 412 } 413 414 @Override 415 public void mergeFrom(Layer from) { 416 throw new UnsupportedOperationException( 417 "This layer does not support merging yet"); 418 } 419 420 @Override 421 public Action[] getMenuEntries() { 422 List<Action> actions = new ArrayList<>(); 423 actions.add(LayerListDialog.getInstance().createShowHideLayerAction()); 424 actions.add(LayerListDialog.getInstance().createDeleteLayerAction()); 425 actions.add(new LayerListPopup.InfoAction(this)); 426 return actions.toArray(new Action[actions.size()]); 427 } 428 429 /** 430 * Returns the 2 closest images belonging to a different sequence. 431 * 432 * @return 433 */ 434 private MapillaryImage[] getClosestImagesFromDifferentSequences() { 435 if (!(data.getSelectedImage() instanceof MapillaryImage)) 436 return new MapillaryImage[2]; 437 MapillaryImage selected = (MapillaryImage) data.getSelectedImage(); 438 MapillaryImage[] ret = new MapillaryImage[2]; 439 double[] distances = { SEQUENCE_MAX_JUMP_DISTANCE, 440 SEQUENCE_MAX_JUMP_DISTANCE }; 441 LatLon selectedCoords = data.getSelectedImage().getLatLon(); 442 for (MapillaryAbstractImage imagePrev : data.getImages()) { 443 if (!(imagePrev instanceof MapillaryImage)) 444 continue; 445 if (!imagePrev.isVisible()) 446 continue; 447 MapillaryImage image = (MapillaryImage) imagePrev; 448 if (image.getLatLon().greatCircleDistance(selectedCoords) < SEQUENCE_MAX_JUMP_DISTANCE 449 && selected.getSequence() != image.getSequence()) { 450 if ((ret[0] == null && ret[1] == null) 451 || (image.getLatLon().greatCircleDistance( 452 selectedCoords) < distances[0] && (ret[1] == null || image 453 .getSequence() != ret[1].getSequence()))) { 454 ret[0] = image; 455 distances[0] = image.getLatLon().greatCircleDistance( 456 selectedCoords); 457 } else if ((ret[1] == null || image.getLatLon() 458 .greatCircleDistance(selectedCoords) < distances[1]) 459 && image.getSequence() != ret[0].getSequence()) { 460 ret[1] = image; 461 distances[1] = image.getLatLon().greatCircleDistance( 462 selectedCoords); 463 } 464 } 465 } 466 // Predownloads the thumbnails 467 if (ret[0] != null) 468 new MapillaryCache(ret[0].getKey(), MapillaryCache.Type.THUMBNAIL) 469 .submit(data, false); 470 if (ret[1] != null) 471 new MapillaryCache(ret[1].getKey(), MapillaryCache.Type.THUMBNAIL) 472 .submit(data, false); 473 return ret; 474 } 475 476 @Override 477 public Object getInfoComponent() { 478 StringBuilder sb = new StringBuilder(); 479 sb.append(tr("Mapillary layer")); 480 sb.append("\n"); 481 sb.append(tr("Total images:")); 482 sb.append(" "); 483 sb.append(data.size()); 484 sb.append("\n"); 485 return sb.toString(); 486 } 487 488 @Override 489 public String getToolTipText() { 490 return data.size() + " " + tr("images"); 491 } 492 493 // EditDataLayerChanged 494 @Override 495 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) { 496 if (oldLayer == null && newLayer != null) { 497 newLayer.data.addDataSetListener(this); 498 499 } else if (oldLayer != null && newLayer == null) { 500 oldLayer.data.removeDataSetListener(this); 501 } 502 } 503 504 /** 505 * When more data is downloaded, a delayed update is thrown, in order to 506 * wait for the data bounds to be set. 507 * 508 * @param event 509 */ 510 @Override 511 public void dataChanged(DataChangedEvent event) { 512 Main.worker.submit(new delayedDownload()); 513 } 514 515 private class delayedDownload extends Thread { 516 517 @Override 518 public void run() { 519 try { 520 sleep(1000); 521 } catch (InterruptedException e) { 522 Main.error(e); 523 } 524 MapillaryLayer.getInstance().download(); 525 } 526 } 527 528 @Override 529 public void primitivesAdded(PrimitivesAddedEvent event) { 530 } 531 532 @Override 533 public void primitivesRemoved(PrimitivesRemovedEvent event) { 534 } 535 536 @Override 537 public void tagsChanged(TagsChangedEvent event) { 538 } 539 540 @Override 541 public void nodeMoved(NodeMovedEvent event) { 542 } 543 544 @Override 545 public void wayNodesChanged(WayNodesChangedEvent event) { 546 } 547 548 @Override 549 public void relationMembersChanged(RelationMembersChangedEvent event) { 550 } 551 552 @Override 553 public void otherDatasetChange(AbstractDatasetChangedEvent event) { 554 } 555 556 @Override 557 public void visitBoundingBox(BoundingXYVisitor v) { 558 } 559 560 @Override 561 public void activeLayerChange(Layer oldLayer, Layer newLayer) { 562 if (newLayer == this) { 563 if (data.size() > 0) 564 Main.map.statusLine.setHelpText(tr("Total images: {0}", 565 data.size())); 566 else 567 Main.map.statusLine.setHelpText(tr("No images found")); 568 } 569 } 570 571 @Override 572 public void layerAdded(Layer newLayer) { 573 } 574 575 @Override 576 public void layerRemoved(Layer oldLayer) { 577 } 579 578 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java
r31319 r31328 33 33 public class MapillaryPlugin extends Plugin implements EditLayerChangeListener { 34 34 35 36 37 38 39 40 41 42 43 44 45 46 47 35 public static final ImageIcon ICON24 = new ImageProvider("icon24.png") 36 .get(); 37 public static final ImageIcon ICON16 = new ImageProvider("icon16.png") 38 .get(); 39 public static final ImageIcon MAP_ICON = new ImageProvider("mapicon.png") 40 .get(); 41 public static final ImageIcon MAP_ICON_SELECTED = new ImageProvider( 42 "mapiconselected.png").get(); 43 public static final ImageIcon MAP_ICON_IMPORTED = new ImageProvider( 44 "mapiconimported.png").get(); 45 public static final ImageIcon MAP_SIGN = new ImageProvider("sign.png") 46 .get(); 47 public static final int ICON_SIZE = 24; 48 48 49 49 public static CacheAccess<String, BufferedImageCacheEntry> CACHE; 50 50 51 52 53 54 55 51 private final MapillaryDownloadAction downloadAction; 52 private final MapillaryExportAction exportAction; 53 private final MapillaryImportAction importAction; 54 private final MapillaryZoomAction zoomAction; 55 private final MapillaryDownloadViewAction downloadViewAction; 56 56 57 58 59 60 61 57 public static JMenuItem DOWNLOAD_MENU; 58 public static JMenuItem EXPORT_MENU; 59 public static JMenuItem IMPORT_MENU; 60 public static JMenuItem ZOOM_MENU; 61 public static JMenuItem DOWNLOAD_VIEW_MENU; 62 62 63 64 65 66 67 68 69 63 public MapillaryPlugin(PluginInformation info) { 64 super(info); 65 downloadAction = new MapillaryDownloadAction(); 66 exportAction = new MapillaryExportAction(); 67 importAction = new MapillaryImportAction(); 68 zoomAction = new MapillaryZoomAction(); 69 downloadViewAction = new MapillaryDownloadViewAction(); 70 70 71 72 73 74 75 76 77 78 79 80 71 DOWNLOAD_MENU = MainMenu.add(Main.main.menu.imageryMenu, 72 downloadAction, false); 73 EXPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, exportAction, 74 false, 14); 75 IMPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, importAction, 76 false, 14); 77 ZOOM_MENU = MainMenu 78 .add(Main.main.menu.viewMenu, zoomAction, false, 15); 79 DOWNLOAD_VIEW_MENU = MainMenu.add(Main.main.menu.fileMenu, 80 downloadViewAction, false, 14); 81 81 82 83 84 85 86 82 EXPORT_MENU.setEnabled(false); 83 DOWNLOAD_MENU.setEnabled(false); 84 IMPORT_MENU.setEnabled(false); 85 ZOOM_MENU.setEnabled(false); 86 DOWNLOAD_VIEW_MENU.setEnabled(false); 87 87 88 89 90 91 92 93 94 95 88 MapView.addEditLayerChangeListener(this); 89 try { 90 CACHE = JCSCacheManager.getCache("mapillary", 10, 10000, 91 this.getPluginDir() + "/cache/"); 92 } catch (IOException e) { 93 Main.error(e); 94 } 95 } 96 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 97 /** 98 * Called when the JOSM map frame is created or destroyed. 99 */ 100 @Override 101 public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { 102 if (oldFrame == null && newFrame != null) { // map frame added 103 Main.map.addToggleDialog(MapillaryToggleDialog.getInstance(), false); 104 Main.map.addToggleDialog(MapillaryHistoryDialog.getInstance(), 105 false); 106 Main.map.addToggleDialog(MapillaryFilterDialog.getInstance(), false); 107 setMenuEnabled(DOWNLOAD_MENU, true); 108 if (Main.pref.getBoolean("mapillary.download-manually")) 109 setMenuEnabled(DOWNLOAD_VIEW_MENU, true); 110 setMenuEnabled(IMPORT_MENU, true); 111 } 112 if (oldFrame != null && newFrame == null) { // map frame destroyed 113 MapillaryToggleDialog.destroyInstance(); 114 MapillaryHistoryDialog.destroyInstance(); 115 MapillaryFilterDialog.destroyInstance(); 116 setMenuEnabled(DOWNLOAD_MENU, false); 117 setMenuEnabled(DOWNLOAD_VIEW_MENU, false); 118 setMenuEnabled(IMPORT_MENU, false); 119 } 120 } 121 121 122 123 124 125 122 public static void setMenuEnabled(JMenuItem menu, boolean value) { 123 menu.setEnabled(value); 124 menu.getAction().setEnabled(value); 125 } 126 126 127 128 129 130 127 @Override 128 public PreferenceSetting getPreferenceSetting() { 129 return new MapillaryPreferenceSetting(); 130 } 131 131 132 133 134 135 136 137 132 @Override 133 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) { 134 if (oldLayer == null && newLayer != null) { 135 } else if (oldLayer != null && newLayer == null) { 136 } 137 } 138 138 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadAction.java
r31319 r31328 23 23 public class MapillaryDownloadAction extends JosmAction { 24 24 25 26 27 28 29 30 31 32 25 public MapillaryDownloadAction() { 26 super(tr("Mapillary"), new ImageProvider("icon24.png"), 27 tr("Create Mapillary layer"), Shortcut.registerShortcut( 28 "Mapillary", tr("Start Mapillary layer"), 29 KeyEvent.VK_COMMA, Shortcut.SHIFT), false, 30 "mapillaryDownload", false); 31 this.setEnabled(false); 32 } 33 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 34 @Override 35 public void actionPerformed(ActionEvent arg0) { 36 if (MapillaryLayer.INSTANCE == null) { 37 if (Main.map.mapView.getEditLayer() != null) 38 MapillaryLayer.getInstance().download(); 39 } else { 40 if (Main.map.mapView.getActiveLayer() != MapillaryLayer 41 .getInstance()) 42 Main.map.mapView.setActiveLayer(MapillaryLayer.getInstance()); 43 else 44 Main.map.mapView 45 .setActiveLayer(Main.map.mapView.getEditLayer()); 46 } 47 } 48 48 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryImportAction.java
r31319 r31328 70 70 71 71 } else { 72 72 MapillaryLayer.getInstance(); 73 73 if (file.getPath().substring(file.getPath().length() - 4) 74 74 .equals(".jpg") -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/cache/MapillaryCache.java
r31306 r31328 11 11 12 12 public class MapillaryCache extends 13 13 JCSCachedTileLoaderJob<String, BufferedImageCacheEntry> { 14 14 15 16 15 private volatile URL url; 16 private volatile String key; 17 17 18 19 20 18 public static enum Type { 19 FULL_IMAGE, THUMBNAIL 20 } 21 21 22 23 24 25 26 27 28 29 30 22 public MapillaryCache(String key, Type type) { 23 super(MapillaryPlugin.CACHE, 50000, 50000, 24 new HashMap<String, String>()); 25 this.key = key; 26 try { 27 if (type == Type.FULL_IMAGE) { 28 url = new URL("https://d1cuyjsrcm0gby.cloudfront.net/" + key 29 + "/thumb-2048.jpg"); 30 this.key += ".FULL_IMAGE"; 31 31 32 33 34 35 36 37 38 39 40 32 } else if (type == Type.THUMBNAIL) { 33 url = new URL("https://d1cuyjsrcm0gby.cloudfront.net/" + key 34 + "/thumb-320.jpg"); 35 this.key += ".THUMBNAIL"; 36 } 37 } catch (MalformedURLException e) { 38 Main.error(e); 39 } 40 } 41 41 42 43 44 45 42 @Override 43 public String getCacheKey() { 44 return key; 45 } 46 46 47 48 49 50 47 @Override 48 public URL getUrl() { 49 return url; 50 } 51 51 52 53 54 55 52 @Override 53 protected BufferedImageCacheEntry createCacheEntry(byte[] content) { 54 return new BufferedImageCacheEntry(content); 55 } 56 56 57 58 59 60 61 62 63 57 @Override 58 protected boolean isObjectLoadable() { 59 if (cacheData == null) 60 return false; 61 byte[] content = cacheData.getContent(); 62 return content != null && content.length > 0; 63 } 64 64 65 66 67 68 65 // @Override 66 protected boolean handleNotFound() { 67 return false; 68 } 69 69 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryDownloader.java
r31322 r31328 18 18 public class MapillaryDownloader { 19 19 20 21 22 20 public final static String BASE_URL = "https://a.mapillary.com/v2/"; 21 public final static String CLIENT_ID = "NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1YTA2NmNlODhlNWMwOTBm"; 22 public final static Executor EXECUTOR = Executors.newSingleThreadExecutor(); 23 23 24 25 24 private String[] parameters = { "lat", "lon", "distance", "limit", 25 "min_lat", "min_lon", "max_lat", "max_lon" }; 26 26 27 28 27 public MapillaryDownloader() { 28 } 29 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 30 /** 31 * Gets all the images in a square. It downloads all the images of all the 32 * sequences that pass through the given rectangle. 33 * 34 * @param minLatLon 35 * The minimum latitude and longitude of the rectangle. 36 * @param maxLatLon 37 * The maximum latitude and longitude of the rectangle 38 */ 39 public void getImages(LatLon minLatLon, LatLon maxLatLon) { 40 String url1 = BASE_URL; 41 String url2 = BASE_URL; 42 String url3 = BASE_URL; 43 url1 += "search/im/"; 44 url2 += "search/s/"; 45 url3 += "search/im/or"; 46 ConcurrentHashMap<String, Double> hash = new ConcurrentHashMap<>(); 47 hash.put("min_lat", minLatLon.lat()); 48 hash.put("min_lon", minLatLon.lon()); 49 hash.put("max_lat", maxLatLon.lat()); 50 hash.put("max_lon", maxLatLon.lon()); 51 url1 += buildParameters(hash); 52 url2 += buildParameters(hash); 53 url3 += buildParameters(hash); 54 54 55 56 57 , url2,58 59 60 61 62 55 try { 56 Main.info("GET " + url2 + " (Mapillary plugin)"); 57 EXECUTOR.execute(new MapillarySquareDownloadManagerThread(url1, 58 url2, url3, MapillaryLayer.getInstance())); 59 } catch (Exception e) { 60 Main.error(e); 61 } 62 } 63 63 64 65 66 64 public void getImages(Bounds bounds) { 65 getImages(bounds.getMin(), bounds.getMax()); 66 } 67 67 68 69 70 71 72 73 74 68 private String buildParameters(ConcurrentHashMap<String, Double> hash) { 69 String ret = "?client_id=" + CLIENT_ID; 70 for (int i = 0; i < parameters.length; i++) 71 if (hash.get(parameters[i]) != null) 72 ret += "&" + parameters[i] + "=" + hash.get(parameters[i]); 73 return ret; 74 } 75 75 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportWriterThread.java
r31284 r31328 87 87 exifDirectory.add( 88 88 ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, 89 ((MapillaryImportedImage) mimg).getDate("yyyy/MM/dd hh:mm:ss")); 89 ((MapillaryImportedImage) mimg) 90 .getDate("yyyy/MM/dd hh:mm:ss")); 90 91 } else if (mimg instanceof MapillaryImage) 91 92 exifDirectory.add( -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryImageInfoDownloaderThread.java
r31319 r31328 25 25 */ 26 26 public class MapillaryImageInfoDownloaderThread implements Runnable { 27 28 29 27 private final String url; 28 private final ExecutorService ex; 29 private final MapillaryLayer layer; 30 30 31 32 33 34 35 36 31 public MapillaryImageInfoDownloaderThread(ExecutorService ex, String url, 32 MapillaryLayer layer) { 33 this.ex = ex; 34 this.url = url; 35 this.layer = layer; 36 } 37 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 38 public void run() { 39 try { 40 BufferedReader br = new BufferedReader(new InputStreamReader( 41 new URL(url).openStream())); 42 JsonObject jsonobj = Json.createReader(br).readObject(); 43 if (!jsonobj.getBoolean("more")) 44 ex.shutdown(); 45 JsonArray jsonarr = jsonobj.getJsonArray("ims"); 46 JsonObject data; 47 for (int i = 0; i < jsonarr.size(); i++) { 48 data = jsonarr.getJsonObject(i); 49 String key = data.getString("key"); 50 for (MapillaryAbstractImage image : layer.data.getImages()) { 51 if (image instanceof MapillaryImage) { 52 if (((MapillaryImage) image).getKey().equals(key) 53 && ((MapillaryImage) image).getUser() == null) { 54 ((MapillaryImage) image).setUser(data 55 .getString("user")); 56 ((MapillaryImage) image).setCapturedAt(data 57 .getJsonNumber("captured_at").longValue()); 58 } 59 } 60 } 61 } 62 } catch (MalformedURLException e) { 63 Main.error(e); 64 } catch (IOException e) { 65 Main.error(e); 66 } 67 } 68 68 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySequenceDownloadThread.java
r31326 r31328 90 90 91 91 boolean imagesAdded = false; 92 MapillaryImage.lock.lock(); 92 93 for (MapillaryImage img : finalImages) { 93 94 if (layer.data.getImages().contains(img)) { 95 sequence.add(img); 94 96 ((MapillaryImage) layer.data.getImages().get( 95 97 layer.data.getImages().indexOf(img))) … … 99 101 (MapillaryImage) layer.data.getImages().get( 100 102 layer.data.getImages().indexOf(img))); 101 sequence.add(img);102 103 } else { 103 104 img.setSequence(sequence); … … 106 107 } 107 108 } 109 MapillaryImage.lock.unlock(); 108 110 manager.imagesAdded = imagesAdded; 109 111 layer.data -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySignDownloaderThread.java
r31319 r31328 19 19 public class MapillarySignDownloaderThread implements Runnable { 20 20 21 22 23 21 private final String url; 22 private final ExecutorService ex; 23 private final MapillaryLayer layer; 24 24 25 26 27 28 29 30 25 public MapillarySignDownloaderThread(ExecutorService ex, String url, 26 MapillaryLayer layer) { 27 this.ex = ex; 28 this.url = url; 29 this.layer = layer; 30 } 31 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 32 @Override 33 public void run() { 34 BufferedReader br; 35 try { 36 br = new BufferedReader(new InputStreamReader( 37 new URL(url).openStream())); 38 JsonObject jsonobj = Json.createReader(br).readObject(); 39 if (!jsonobj.getBoolean("more")) { 40 ex.shutdown(); 41 } 42 JsonArray jsonarr = jsonobj.getJsonArray("ims"); 43 for (int i = 0; i < jsonarr.size(); i++) { 44 JsonArray rects = jsonarr.getJsonObject(i) 45 .getJsonArray("rects"); 46 JsonArray rectversions = jsonarr.getJsonObject(i).getJsonArray( 47 "rectversions"); 48 String key = jsonarr.getJsonObject(i).getString("key"); 49 if (rectversions != null) { 50 for (int j = 0; j < rectversions.size(); j++) { 51 rects = rectversions.getJsonObject(j).getJsonArray( 52 "rects"); 53 for (int k = 0; k < rects.size(); k++) { 54 JsonObject data = rects.getJsonObject(k); 55 for (MapillaryAbstractImage image : layer.data 56 .getImages()) 57 if (image instanceof MapillaryImage 58 && ((MapillaryImage) image).getKey() 59 .equals(key)) 60 ((MapillaryImage) image).addSign(data 61 .getString("type")); 62 } 63 } 64 } 65 65 66 // Just one sign on the picture 67 else if (rects != null) { 68 for (int j = 0; j < rects.size(); j++) { 69 JsonObject data = rects.getJsonObject(j); 70 for (MapillaryAbstractImage image : layer.data.getImages()) 71 if (image instanceof MapillaryImage 72 && ((MapillaryImage) image).getKey() 73 .equals(key)) 74 ((MapillaryImage) image).addSign(data 75 .getString("type")); 76 } 77 } 78 } 79 } catch (MalformedURLException e) { 80 Main.error(e); 81 } catch (IOException e) { 82 Main.error(e); 83 } 84 } 66 // Just one sign on the picture 67 else if (rects != null) { 68 for (int j = 0; j < rects.size(); j++) { 69 JsonObject data = rects.getJsonObject(j); 70 for (MapillaryAbstractImage image : layer.data 71 .getImages()) 72 if (image instanceof MapillaryImage 73 && ((MapillaryImage) image).getKey() 74 .equals(key)) 75 ((MapillaryImage) image).addSign(data 76 .getString("type")); 77 } 78 } 79 } 80 } catch (MalformedURLException e) { 81 Main.error(e); 82 } catch (IOException e) { 83 Main.error(e); 84 } 85 } 85 86 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySquareDownloadManagerThread.java
r31324 r31328 14 14 /** 15 15 * This Class is needed to create an indeterminate amount of downloads, because 16 * the Mapillary API has a param ameter called page which is needed when theamount of17 * requested images is quite big. 16 * the Mapillary API has a parameter called page which is needed when the 17 * amount of requested images is quite big. 18 18 * 19 19 * @author nokutu … … 23 23 public class MapillarySquareDownloadManagerThread implements Runnable { 24 24 25 private final String urlImages; 26 private final String urlSequences; 27 private final String urlSigns; 28 private final MapillaryLayer layer; 29 public boolean imagesAdded = false; 30 31 public MapillarySquareDownloadManagerThread(String urlImages, 32 String urlSequences, String urlSigns, MapillaryLayer layer) { 33 this.urlImages = urlImages; 34 this.urlSequences = urlSequences; 35 this.urlSigns = urlSigns; 36 this.layer = layer; 37 } 25 private final String urlImages; 26 private final String urlSequences; 27 private final String urlSigns; 28 private final MapillaryLayer layer; 29 public boolean imagesAdded = false; 38 30 39 public void run() { 40 Main.map.statusLine.setHelpText("Downloading images from Mapillary"); 41 try { 42 downloadSequences(); 43 if (imagesAdded) { 44 Main.map.statusLine 45 .setHelpText("Downloading image's information"); 46 completeImages(); 47 MapillaryToggleDialog.getInstance().updateTitle(); 48 Main.map.statusLine.setHelpText("Downloading signs"); 49 downloadSigns(); 50 } 51 } catch (InterruptedException e) { 52 Main.error(e); 53 } 54 if (layer.data.getImages().size() > 0) 55 Main.map.statusLine.setHelpText(tr("Total images: ") 56 + layer.data.getImages().size()); 57 else 58 Main.map.statusLine.setHelpText(tr("No images found")); 59 layer.data.dataUpdated(); 60 MapillaryFilterDialog.getInstance().refresh(); 61 MapillaryToggleDialog.getInstance().updateImage(); 62 } 31 public MapillarySquareDownloadManagerThread(String urlImages, 32 String urlSequences, String urlSigns, MapillaryLayer layer) { 33 this.urlImages = urlImages; 34 this.urlSequences = urlSequences; 35 this.urlSigns = urlSigns; 36 this.layer = layer; 37 } 63 38 64 private void downloadSequences() throws InterruptedException { 65 ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25, 66 TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5)); 67 int page = 0; 68 while (!ex.isShutdown()) { 69 ex.execute(new MapillarySequenceDownloadThread(ex, urlSequences 70 + "&page=" + page + "&limit=1", layer, this)); 71 while (ex.getQueue().remainingCapacity() == 0) 72 Thread.sleep(100); 73 page++; 74 } 75 ex.awaitTermination(15, TimeUnit.SECONDS); 76 layer.data.dataUpdated(); 77 } 39 public void run() { 40 Main.map.statusLine.setHelpText("Downloading images from Mapillary"); 41 try { 42 downloadSequences(); 43 if (imagesAdded) { 44 Main.map.statusLine 45 .setHelpText("Downloading image's information"); 46 completeImages(); 47 MapillaryToggleDialog.getInstance().updateTitle(); 48 Main.map.statusLine.setHelpText("Downloading signs"); 49 downloadSigns(); 50 } 51 } catch (InterruptedException e) { 52 Main.error(e); 53 } 54 if (layer.data.getImages().size() > 0) 55 Main.map.statusLine.setHelpText(tr("Total images: ") 56 + layer.data.getImages().size()); 57 else 58 Main.map.statusLine.setHelpText(tr("No images found")); 59 layer.data.dataUpdated(); 60 MapillaryFilterDialog.getInstance().refresh(); 61 MapillaryToggleDialog.getInstance().updateImage(); 62 } 78 63 79 private void completeImages() throws InterruptedException { 80 ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25, 81 TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5)); 82 int page = 0; 83 while (!ex.isShutdown()) { 84 ex.execute(new MapillaryImageInfoDownloaderThread(ex, urlImages 85 + "&page=" + page + "&limit=20", layer)); 86 while (ex.getQueue().remainingCapacity() == 0) 87 Thread.sleep(100); 88 page++; 89 } 90 ex.awaitTermination(15, TimeUnit.SECONDS); 91 } 64 private void downloadSequences() throws InterruptedException { 65 ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25, 66 TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5)); 67 int page = 0; 68 while (!ex.isShutdown()) { 69 ex.execute(new MapillarySequenceDownloadThread(ex, urlSequences 70 + "&page=" + page + "&limit=1", layer, this)); 71 while (ex.getQueue().remainingCapacity() == 0) 72 Thread.sleep(100); 73 page++; 74 } 75 ex.awaitTermination(15, TimeUnit.SECONDS); 76 layer.data.dataUpdated(); 77 } 92 78 93 private void downloadSigns() throws InterruptedException { 94 ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25, 95 TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5)); 96 int page = 0; 97 while (!ex.isShutdown()) { 98 ex.execute(new MapillarySignDownloaderThread(ex, urlSigns 99 + "&page=" + page + "&limit=20", layer)); 100 while (ex.getQueue().remainingCapacity() == 0) 101 Thread.sleep(100); 102 page++; 103 } 104 ex.awaitTermination(15, TimeUnit.SECONDS); 105 } 79 private void completeImages() throws InterruptedException { 80 ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25, 81 TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5)); 82 int page = 0; 83 while (!ex.isShutdown()) { 84 ex.execute(new MapillaryImageInfoDownloaderThread(ex, urlImages 85 + "&page=" + page + "&limit=20", layer)); 86 while (ex.getQueue().remainingCapacity() == 0) 87 Thread.sleep(100); 88 page++; 89 } 90 ex.awaitTermination(15, TimeUnit.SECONDS); 91 } 92 93 private void downloadSigns() throws InterruptedException { 94 ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25, 95 TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5)); 96 int page = 0; 97 while (!ex.isShutdown()) { 98 ex.execute(new MapillarySignDownloaderThread(ex, urlSigns 99 + "&page=" + page + "&limit=20", layer)); 100 while (ex.getQueue().remainingCapacity() == 0) 101 Thread.sleep(100); 102 page++; 103 } 104 ex.awaitTermination(15, TimeUnit.SECONDS); 105 } 106 106 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterChooseSigns.java
r31315 r31328 14 14 15 15 public class MapillaryFilterChooseSigns extends JPanel implements 16 16 ActionListener { 17 17 18 19 20 21 22 23 24 25 26 27 28 29 18 public final JCheckBox maxspeed = new JCheckBox(); 19 public final JCheckBox stop = new JCheckBox(); 20 public final JCheckBox giveWay = new JCheckBox(); 21 public final JCheckBox roundabout = new JCheckBox(); 22 public final JCheckBox access = new JCheckBox(); 23 public final JCheckBox intersection = new JCheckBox(); 24 public final JCheckBox direction = new JCheckBox(); 25 public final JCheckBox uneven = new JCheckBox(); 26 public final JCheckBox noParking = new JCheckBox(); 27 public final JCheckBox noOvertaking = new JCheckBox(); 28 public final JCheckBox crossing = new JCheckBox(); 29 public final JCheckBox noTurn = new JCheckBox(); 30 30 31 31 private static MapillaryFilterChooseSigns INSTANCE; 32 32 33 34 35 36 37 38 39 40 41 42 43 44 45 33 public MapillaryFilterChooseSigns() { 34 maxspeed.setSelected(true); 35 stop.setSelected(true); 36 giveWay.setSelected(true); 37 roundabout.setSelected(true); 38 access.setSelected(true); 39 intersection.setSelected(true); 40 direction.setSelected(true); 41 uneven.setSelected(true); 42 noParking.setSelected(true); 43 noOvertaking.setSelected(true); 44 crossing.setSelected(true); 45 noTurn.setSelected(true); 46 46 47 48 49 50 51 52 53 47 // Max speed sign 48 JPanel maxspeedPanel = new JPanel(); 49 JLabel maxspeedLabel = new JLabel(tr("Speed limit")); 50 maxspeedLabel.setIcon(new ImageProvider("signs/speed.png").get()); 51 maxspeedPanel.add(maxspeedLabel); 52 maxspeedPanel.add(maxspeed); 53 this.add(maxspeedPanel); 54 54 55 56 57 58 59 60 61 55 // Stop sign 56 JPanel stopPanel = new JPanel(); 57 JLabel stopLabel = new JLabel(tr("Stop")); 58 stopLabel.setIcon(new ImageProvider("signs/stop.png").get()); 59 stopPanel.add(stopLabel); 60 stopPanel.add(stop); 61 this.add(stopPanel); 62 62 63 64 65 66 67 68 69 63 // Give way sign 64 JPanel giveWayPanel = new JPanel(); 65 JLabel giveWayLabel = new JLabel(tr("Give way")); 66 giveWayLabel.setIcon(new ImageProvider("signs/right_of_way.png").get()); 67 giveWayPanel.add(giveWayLabel); 68 giveWayPanel.add(giveWay); 69 this.add(giveWayPanel); 70 70 71 72 73 74 75 76 77 78 71 // Roundabout sign 72 JPanel roundaboutPanel = new JPanel(); 73 JLabel roundaboutLabel = new JLabel(tr("Give way")); 74 roundaboutLabel.setIcon(new ImageProvider("signs/roundabout_right.png") 75 .get()); 76 roundaboutPanel.add(roundaboutLabel); 77 roundaboutPanel.add(roundabout); 78 this.add(roundaboutPanel); 79 79 80 81 82 83 84 85 86 80 // No entry sign 81 JPanel noEntryPanel = new JPanel(); 82 JLabel noEntryLabel = new JLabel(tr("No entry")); 83 noEntryLabel.setIcon(new ImageProvider("signs/no_entry.png").get()); 84 noEntryPanel.add(noEntryLabel); 85 noEntryPanel.add(access); 86 this.add(noEntryPanel); 87 87 88 89 90 91 92 93 94 95 88 // Danger intersection 89 JPanel intersectionPanel = new JPanel(); 90 JLabel intersectionLabel = new JLabel(tr("Intersection danger")); 91 intersectionLabel.setIcon(new ImageProvider( 92 "signs/intersection_danger.png").get()); 93 intersectionPanel.add(intersectionLabel); 94 intersectionPanel.add(intersection); 95 this.add(intersectionPanel); 96 96 97 98 99 100 101 102 103 104 97 // Mandatory direction 98 JPanel directionPanel = new JPanel(); 99 JLabel directionLabel = new JLabel(tr("Mandatory direction (any)")); 100 directionLabel.setIcon(new ImageProvider("signs/only_straight_on.png") 101 .get()); 102 directionPanel.add(directionLabel); 103 directionPanel.add(direction); 104 this.add(directionPanel); 105 105 106 107 108 109 110 111 112 106 // No turn 107 JPanel noTurnPanel = new JPanel(); 108 JLabel noTurnLabel = new JLabel(tr("No turn")); 109 noTurnLabel.setIcon(new ImageProvider("signs/no_turn.png").get()); 110 noTurnPanel.add(noTurnLabel); 111 noTurnPanel.add(noTurn); 112 this.add(noTurnPanel); 113 113 114 115 116 117 118 119 120 114 // Uneven road 115 JPanel unevenPanel = new JPanel(); 116 JLabel unevenLabel = new JLabel(tr("Uneven road")); 117 unevenLabel.setIcon(new ImageProvider("signs/uneaven.png").get()); 118 unevenPanel.add(unevenLabel); 119 unevenPanel.add(uneven); 120 this.add(unevenPanel); 121 121 122 123 124 125 126 127 128 122 // No parking 123 JPanel noParkingPanel = new JPanel(); 124 JLabel noParkingLabel = new JLabel(tr("No parking")); 125 noParkingLabel.setIcon(new ImageProvider("signs/no_parking.png").get()); 126 noParkingPanel.add(noParkingLabel); 127 noParkingPanel.add(noParking); 128 this.add(noParkingPanel); 129 129 130 131 132 133 134 135 136 137 130 // No overtaking 131 JPanel noOvertakingPanel = new JPanel(); 132 JLabel noOvertakingLabel = new JLabel(tr("No overtaking")); 133 noOvertakingLabel.setIcon(new ImageProvider("signs/no_overtaking.png") 134 .get()); 135 noOvertakingPanel.add(noOvertakingLabel); 136 noOvertakingPanel.add(noOvertaking); 137 this.add(noOvertakingPanel); 138 138 139 140 141 142 143 144 145 139 // Pedestrian crossing 140 JPanel crossingPanel = new JPanel(); 141 JLabel crossingLabel = new JLabel(tr("Pedestrian crossing")); 142 crossingLabel.setIcon(new ImageProvider("signs/crossing.png").get()); 143 crossingPanel.add(crossingLabel); 144 crossingPanel.add(crossing); 145 this.add(crossingPanel); 146 146 147 148 147 this.setPreferredSize(new Dimension(600, 150)); 148 } 149 149 150 151 152 153 154 150 public static MapillaryFilterChooseSigns getInstance() { 151 if (INSTANCE == null) 152 INSTANCE = new MapillaryFilterChooseSigns(); 153 return INSTANCE; 154 } 155 155 156 157 158 156 @Override 157 public void actionPerformed(ActionEvent arg0) { 158 // TODO Auto-generated method stub 159 159 160 160 } 161 161 162 162 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterDialog.java
r31319 r31328 37 37 */ 38 38 public class MapillaryFilterDialog extends ToggleDialog implements 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 39 MapillaryDataListener { 40 41 public static MapillaryFilterDialog INSTANCE; 42 43 private final static String[] TIME_LIST = { tr("All time"), 44 tr("This year"), tr("This month"), tr("This week") }; 45 46 private final static int ROWS = 0; 47 private final static int COLUMNS = 3; 48 49 private final JPanel panel = new JPanel(new GridLayout(ROWS, COLUMNS)); 50 51 public final JCheckBox imported = new JCheckBox("Imported images"); 52 public final JCheckBox downloaded = new JCheckBox( 53 new downloadCheckBoxAction()); 54 public final JCheckBox onlySigns = new JCheckBox(new OnlySignsAction()); 55 public final JComboBox<String> time; 56 public final JTextField user; 57 58 public final SideButton updateButton = new SideButton(new UpdateAction()); 59 public final SideButton resetButton = new SideButton(new ResetAction()); 60 public final JButton signChooser = new JButton(new SignChooserAction()); 61 62 public final MapillaryFilterChooseSigns signFilter = MapillaryFilterChooseSigns 63 .getInstance(); 64 65 private final String[] SIGN_TAGS = { "prohibitory_speed_limit", 66 "priority_stop", "other_give_way", "mandatory_roundabout", 67 "other_no_entry", "prohibitory_no_traffic_both_ways", 68 "danger_intersection", "mandatory_go", "mandatory_keep", 69 "danger_priority_next_intersection", "danger_uneven_road", 70 "prohibitory_no_parking", "prohibitory_on_overtaking", 71 "danger_pedestrian_crossing", "prohibitory_no_u_turn", 72 "prohibitory_noturn" }; 73 private final JCheckBox[] SIGN_CHECKBOXES = { signFilter.maxspeed, 74 signFilter.stop, signFilter.giveWay, signFilter.roundabout, 75 signFilter.access, signFilter.access, signFilter.intersection, 76 signFilter.direction, signFilter.direction, 77 signFilter.intersection, signFilter.uneven, signFilter.noParking, 78 signFilter.noOvertaking, signFilter.crossing, signFilter.noTurn, 79 signFilter.noTurn }; 80 81 public MapillaryFilterDialog() { 82 super(tr("Mapillary filter"), "mapillaryfilter.png", 83 tr("Open Mapillary filter dialog"), Shortcut.registerShortcut( 84 tr("Mapillary filter"), 85 tr("Open Mapillary filter dialog"), KeyEvent.VK_M, 86 Shortcut.NONE), 200); 87 88 signChooser.setEnabled(false); 89 JPanel signChooserPanel = new JPanel(); 90 signChooserPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); 91 signChooserPanel.add(signChooser); 92 93 JPanel fromPanel = new JPanel(); 94 fromPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); 95 fromPanel.add(new JLabel("From")); 96 time = new JComboBox<>(TIME_LIST); 97 fromPanel.add(time); 98 99 JPanel userSearchPanel = new JPanel(); 100 userSearchPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); 101 user = new JTextField(10); 102 user.addActionListener(new UpdateAction()); 103 userSearchPanel.add(new JLabel("User")); 104 userSearchPanel.add(user); 105 106 imported.setSelected(true); 107 downloaded.setSelected(true); 108 109 panel.add(downloaded); 110 panel.add(imported); 111 panel.add(onlySigns); 112 panel.add(fromPanel); 113 panel.add(userSearchPanel); 114 panel.add(signChooserPanel); 115 116 createLayout(panel, true, 117 Arrays.asList(new SideButton[] { updateButton, resetButton })); 118 } 119 120 public static MapillaryFilterDialog getInstance() { 121 if (INSTANCE == null) 122 INSTANCE = new MapillaryFilterDialog(); 123 return INSTANCE; 124 } 125 126 @Override 127 public void imagesAdded() { 128 refresh(); 129 } 130 131 @Override 132 public void selectedImageChanged(MapillaryAbstractImage oldImage, 133 MapillaryAbstractImage newImage) { 134 } 135 136 public void reset() { 137 imported.setSelected(true); 138 downloaded.setSelected(true); 139 onlySigns.setEnabled(true); 140 onlySigns.setSelected(false); 141 user.setText(""); 142 time.setSelectedItem(TIME_LIST[0]); 143 refresh(); 144 } 145 146 public synchronized void refresh() { 147 boolean imported = this.imported.isSelected(); 148 boolean downloaded = this.downloaded.isSelected(); 149 boolean onlySigns = this.onlySigns.isSelected(); 150 151 for (MapillaryAbstractImage img : MapillaryData.getInstance() 152 .getImages()) { 153 img.setVisible(true); 154 if (img instanceof MapillaryImportedImage) { 155 if (!imported) 156 img.setVisible(false); 157 continue; 158 } else if (img instanceof MapillaryImage) { 159 if (!downloaded) { 160 img.setVisible(false); 161 continue; 162 } 163 if (onlySigns) { 164 if (((MapillaryImage) img).getSigns().isEmpty()) { 165 img.setVisible(false); 166 continue; 167 } 168 if (!checkSigns((MapillaryImage) img)) { 169 img.setVisible(false); 170 continue; 171 } 172 } 173 if (!user.getText().equals("") 174 && !user.getText().equals( 175 ((MapillaryImage) img).getUser())) { 176 img.setVisible(false); 177 continue; 178 } 179 } 180 // Calculates the amount of days since the image was taken 181 Long currentTime = currentTime(); 182 if (time.getSelectedItem() == TIME_LIST[1]) { 183 if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 365) { 184 img.setVisible(false); 185 continue; 186 } 187 } 188 if (time.getSelectedItem() == TIME_LIST[2]) { 189 if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 30) { 190 img.setVisible(false); 191 continue; 192 } 193 } 194 if (time.getSelectedItem() == TIME_LIST[3]) { 195 if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 7) { 196 img.setVisible(false); 197 continue; 198 } 199 } 200 } 201 Main.map.repaint(); 202 } 203 204 private boolean checkSigns(MapillaryImage img) { 205 for (int i = 0; i < SIGN_TAGS.length; i++) { 206 if (checkSign(img, SIGN_CHECKBOXES[i], SIGN_TAGS[i])) 207 return true; 208 } 209 return false; 210 } 211 212 private boolean checkSign(MapillaryImage img, JCheckBox signCheckBox, 213 String singString) { 214 boolean contains = false; 215 for (String sign : img.getSigns()) { 216 if (sign.contains(singString)) 217 contains = true; 218 } 219 if (contains == signCheckBox.isSelected() && contains) 220 return true; 221 return false; 222 } 223 224 private long currentTime() { 225 Calendar cal = Calendar.getInstance(); 226 return cal.getTimeInMillis(); 227 } 228 229 private class downloadCheckBoxAction extends AbstractAction { 230 231 public downloadCheckBoxAction() { 232 putValue(NAME, tr("Downloaded images")); 233 } 234 235 @Override 236 public void actionPerformed(ActionEvent arg0) { 237 onlySigns.setEnabled(downloaded.isSelected()); 238 } 239 } 240 241 private class UpdateAction extends AbstractAction { 242 public UpdateAction() { 243 putValue(NAME, tr("Update")); 244 } 245 246 @Override 247 public void actionPerformed(ActionEvent arg0) { 248 MapillaryFilterDialog.getInstance().refresh(); 249 } 250 } 251 252 private class ResetAction extends AbstractAction { 253 public ResetAction() { 254 putValue(NAME, tr("Reset")); 255 } 256 257 @Override 258 public void actionPerformed(ActionEvent arg0) { 259 MapillaryFilterDialog.getInstance().reset(); 260 } 261 } 262 263 private class OnlySignsAction extends AbstractAction { 264 public OnlySignsAction() { 265 putValue(NAME, tr("Only images with signs")); 266 } 267 268 @Override 269 public void actionPerformed(ActionEvent arg0) { 270 signChooser.setEnabled(onlySigns.isSelected()); 271 } 272 } 273 274 /** 275 * Opens a new window where you can specifically filter signs. 276 * 277 * @author nokutu 278 * 279 */ 280 private class SignChooserAction extends AbstractAction { 281 public SignChooserAction() { 282 putValue(NAME, tr("Choose signs")); 283 } 284 285 @Override 286 public void actionPerformed(ActionEvent arg0) { 287 JPanel dialog = MapillaryFilterChooseSigns.getInstance(); 288 JOptionPane pane = new JOptionPane(dialog, 289 JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION); 290 JDialog dlg = pane.createDialog(Main.parent, tr("Choose signs")); 291 dlg.setVisible(true); 292 if ((int) pane.getValue() == JOptionPane.OK_OPTION) 293 MapillaryFilterDialog.getInstance().refresh(); 294 dlg.dispose(); 295 } 296 } 297 298 public static void destroyInstance() { 299 MapillaryFilterDialog.INSTANCE = null; 300 } 301 301 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryPreferenceSetting.java
r31313 r31328 20 20 private JCheckBox downloadMode = new JCheckBox( 21 21 tr("Download images manually")); 22 private JCheckBox displayHour = new JCheckBox(tr("Display hour when the picture was taken")); 22 private JCheckBox displayHour = new JCheckBox( 23 tr("Display hour when the picture was taken")); 23 24 private JCheckBox format24 = new JCheckBox(tr("Use 24 hour format")); 24 private JCheckBox moveTo = new JCheckBox(tr("Move to picture's location with next/previous buttons")); 25 private JCheckBox moveTo = new JCheckBox( 26 tr("Move to picture's location with next/previous buttons")); 25 27 26 28 @Override … … 37 39 downloadMode.setSelected(Main.pref 38 40 .getBoolean("mapillary.download-manually")); 39 displayHour.setSelected(Main.pref.getBoolean("mapillary.display-hour", true)); 41 displayHour.setSelected(Main.pref.getBoolean("mapillary.display-hour", 42 true)); 40 43 format24.setSelected(Main.pref.getBoolean("mapillary.format-24")); 41 moveTo.setSelected(Main.pref.getBoolean("mapillary.move-to-picture", true)); 44 moveTo.setSelected(Main.pref.getBoolean("mapillary.move-to-picture", 45 true)); 42 46 43 47 panel.setLayout(new FlowLayout(FlowLayout.LEFT)); … … 55 59 Main.pref.put("mapillary.reverse-buttons", reverseButtons.isSelected()); 56 60 Main.pref.put("mapillary.download-manually", downloadMode.isSelected()); 57 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.DOWNLOAD_VIEW_MENU, downloadMode.isSelected()); 58 61 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.DOWNLOAD_VIEW_MENU, 62 downloadMode.isSelected()); 63 59 64 Main.pref.put("mapillary.display-hour", displayHour.isSelected()); 60 65 Main.pref.put("mapillary.format-24", format24.isSelected());
Note:
See TracChangeset
for help on using the changeset viewer.