Changeset 31350 in osm for applications
- Timestamp:
- 2015-07-07T16:07:45+02:00 (9 years ago)
- Location:
- applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary
- Files:
-
- 38 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryAbstractImage.java
r31333 r31350 5 5 import java.text.SimpleDateFormat; 6 6 import java.util.Calendar; 7 import java.util.TimeZone;8 7 import java.util.concurrent.locks.Lock; 9 8 import java.util.concurrent.locks.ReentrantLock; … … 15 14 * Abstract superclass for all image objects. At the moment there is just 2, 16 15 * {@code MapillaryImportedImage} and {@code MapillaryImage}. 17 * 16 * 18 17 * @author nokutu 19 18 * … … 21 20 public abstract class MapillaryAbstractImage { 22 21 23 public static Lock lock = new ReentrantLock(); 24 25 /** The time the image was captured, in Epoch format */ 26 private long capturedAt; 27 /** Position of the picture */ 28 public final LatLon latLon; 29 /** Direction of the picture */ 30 public final double ca; 31 public boolean isModified = false; 32 /** Temporal position of the picture until it is uploaded */ 33 public LatLon tempLatLon; 34 /** 35 * When the object is being dragged in the map, the temporal position is 36 * stored here 37 */ 38 public LatLon movingLatLon; 39 /** Temporal direction of the picture until it is uploaded */ 40 public double tempCa; 41 /** 42 * When the object direction is being moved in the map, the temporal 43 * direction is stored here 44 */ 45 protected double movingCa; 46 private boolean visible; 47 48 public MapillaryAbstractImage(double lat, double lon, double ca) { 49 this.latLon = new LatLon(lat, lon); 50 this.tempLatLon = this.latLon; 51 this.movingLatLon = this.latLon; 52 this.ca = ca; 53 this.tempCa = ca; 54 this.movingCa = ca; 55 this.visible = true; 22 public static Lock lock = new ReentrantLock(); 23 24 /** The time the image was captured, in Epoch format */ 25 private long capturedAt; 26 /** Position of the picture */ 27 public final LatLon latLon; 28 /** Direction of the picture */ 29 public final double ca; 30 public boolean isModified = false; 31 /** Temporal position of the picture until it is uploaded */ 32 public LatLon tempLatLon; 33 /** 34 * When the object is being dragged in the map, the temporal position is 35 * stored here 36 */ 37 public LatLon movingLatLon; 38 /** Temporal direction of the picture until it is uploaded */ 39 public double tempCa; 40 /** 41 * When the object direction is being moved in the map, the temporal direction 42 * is stored here 43 */ 44 protected double movingCa; 45 private boolean visible; 46 47 public MapillaryAbstractImage(double lat, double lon, double ca) { 48 this.latLon = new LatLon(lat, lon); 49 this.tempLatLon = this.latLon; 50 this.movingLatLon = this.latLon; 51 this.ca = ca; 52 this.tempCa = ca; 53 this.movingCa = ca; 54 this.visible = true; 55 } 56 57 /** 58 * Returns whether the object has been modified or not. 59 * 60 * @return true if the object has been modified; false otherwise. 61 */ 62 public boolean isModified() { 63 return this.isModified; 64 } 65 66 /** 67 * Returns a LatLon object containing the current coordinates of the object. 68 * When you are dragging the image this changes. 69 * 70 * @return The LatLon object with the position of the object. 71 */ 72 public LatLon getLatLon() { 73 return movingLatLon; 74 } 75 76 /** 77 * Returns whether the image is visible on the map or not. 78 * 79 * @return True if the image is visible; false otherwise. 80 */ 81 public boolean isVisible() { 82 return visible; 83 } 84 85 public void setVisible(boolean visible) { 86 this.visible = visible; 87 } 88 89 /** 90 * Returns the last fixed coordinates of the object. 91 * 92 * @return A LatLon object containing. 93 */ 94 public LatLon getTempLatLon() { 95 return tempLatLon; 96 } 97 98 /** 99 * Moves the image temporally to another position 100 * 101 * @param x 102 * The movement of the image in longitude units. 103 * @param y 104 * The movement of the image in latitude units. 105 */ 106 public void move(double x, double y) { 107 this.movingLatLon = new LatLon(this.tempLatLon.getY() + y, 108 this.tempLatLon.getX() + x); 109 this.isModified = true; 110 } 111 112 /** 113 * Turns the image direction. 114 * 115 * @param ca 116 * The angle the image is moving. 117 */ 118 public void turn(double ca) { 119 this.movingCa = this.tempCa + ca; 120 this.isModified = true; 121 } 122 123 /** 124 * Called when the mouse button is released, meaning that the picture has 125 * stopped being dragged. 126 */ 127 public void stopMoving() { 128 this.tempLatLon = this.movingLatLon; 129 this.tempCa = this.movingCa; 130 } 131 132 /** 133 * Returns the direction towards the image has been taken. 134 * 135 * @return The direction of the image (0 means north and goes clockwise). 136 */ 137 public double getCa() { 138 return movingCa; 139 } 140 141 /** 142 * Returns the last fixed direction of the object. 143 * 144 * @return The last fixed direction of the object. 0 means north. 145 */ 146 public double getTempCa() { 147 return tempCa; 148 } 149 150 /** 151 * Returns the date the picture was taken in DMY format. 152 * 153 * @return A String object containing the date when the picture was taken. 154 */ 155 public String getDate() { 156 String format = ""; 157 if (Main.pref.getBoolean("iso.dates")) 158 format += "yyyy-MM-dd"; 159 else 160 format += "dd/MM/yyyy"; 161 if (Main.pref.getBoolean("mapillary.display-hour", true)) { 162 if (Main.pref.getBoolean("mapillary.format-24")) 163 format += " - HH:mm:ss (z)"; 164 else 165 format += " - h:mm:ss a (z)"; 56 166 } 57 58 /** 59 * Returns whether the object has been modified or not. 60 * 61 * @return true if the object has been modified; false otherwise. 62 */ 63 public boolean isModified() { 64 return this.isModified; 167 return getDate(format); 168 } 169 170 public void setCapturedAt(long capturedAt) { 171 this.capturedAt = capturedAt; 172 } 173 174 public long getCapturedAt() { 175 return capturedAt; 176 } 177 178 /** 179 * Returns the date the picture was taken in the given format. 180 * 181 * @param format 182 * @return 183 */ 184 public String getDate(String format) { 185 Date date = new Date(getCapturedAt()); 186 187 SimpleDateFormat formatter = new SimpleDateFormat(format); 188 formatter.setTimeZone(Calendar.getInstance().getTimeZone()); 189 return formatter.format(date); 190 } 191 192 /** 193 * Parses a string with a given format and returns the Epoch time. 194 * 195 * @param date 196 * The string containing the date. 197 * @param format 198 * The format of the date. 199 * @return The date in Epoch format. 200 */ 201 public long getEpoch(String date, String format) { 202 203 SimpleDateFormat formatter = new SimpleDateFormat(format); 204 try { 205 Date dateTime = (Date) formatter.parse(date); 206 return dateTime.getTime(); 207 } catch (ParseException e) { 208 Main.error(e); 65 209 } 66 67 /** 68 * Returns a LatLon object containing the current coordinates of the object. 69 * When you are dragging the image this changes. 70 * 71 * @return The LatLon object with the position of the object. 72 */ 73 public LatLon getLatLon() { 74 return movingLatLon; 75 } 76 77 /** 78 * Returns whether the image is visible on the map or not. 79 * 80 * @return True if the image is visible; false otherwise. 81 */ 82 public boolean isVisible() { 83 return visible; 84 } 85 86 public void setVisible(boolean visible) { 87 this.visible = visible; 88 } 89 90 /** 91 * Returns the last fixed coordinates of the object. 92 * 93 * @return A LatLon object containing. 94 */ 95 public LatLon getTempLatLon() { 96 return tempLatLon; 97 } 98 99 /** 100 * Moves the image temporally to another position 101 * 102 * @param x 103 * The movement of the image in longitude units. 104 * @param y 105 * The movement of the image in latitude units. 106 */ 107 public void move(double x, double y) { 108 this.movingLatLon = new LatLon(this.tempLatLon.getY() + y, 109 this.tempLatLon.getX() + x); 110 this.isModified = true; 111 } 112 113 /** 114 * Turns the image direction. 115 * 116 * @param ca 117 * The angle the image is moving. 118 */ 119 public void turn(double ca) { 120 this.movingCa = this.tempCa + ca; 121 this.isModified = true; 122 } 123 124 /** 125 * Called when the mouse button is released, meaning that the picture has 126 * stopped being dragged. 127 */ 128 public void stopMoving() { 129 this.tempLatLon = this.movingLatLon; 130 this.tempCa = this.movingCa; 131 } 132 133 /** 134 * Returns the direction towards the image has been taken. 135 * 136 * @return The direction of the image (0 means north and goes clockwise). 137 */ 138 public double getCa() { 139 return movingCa; 140 } 141 142 /** 143 * Returns the last fixed direction of the object. 144 * 145 * @return The last fixed direction of the object. 0 means north. 146 */ 147 public double getTempCa() { 148 return tempCa; 149 } 150 151 /** 152 * Returns the date the picture was taken in DMY format. 153 * 154 * @return A String object containing the date when the picture was taken. 155 */ 156 public String getDate() { 157 String format = ""; 158 if (Main.pref.getBoolean("iso.dates")) 159 format += "yyyy-MM-dd"; 160 else 161 format += "dd/MM/yyyy"; 162 if (Main.pref.getBoolean("mapillary.display-hour", true)) { 163 if (Main.pref.getBoolean("mapillary.format-24")) 164 format += " - HH:mm:ss (z)"; 165 else 166 format += " - h:mm:ss a (z)"; 167 } 168 return getDate(format); 169 } 170 171 public void setCapturedAt(long capturedAt) { 172 this.capturedAt = capturedAt; 173 } 174 175 public long getCapturedAt() { 176 return capturedAt; 177 } 178 179 /** 180 * Returns the date the picture was taken in the given format. 181 * 182 * @param format 183 * @return 184 */ 185 public String getDate(String format) { 186 Date date = new Date(getCapturedAt()); 187 188 SimpleDateFormat formatter = new SimpleDateFormat(format); 189 formatter.setTimeZone(TimeZone.getTimeZone("GMT")); 190 return formatter.format(date); 191 } 192 193 /** 194 * Parses a string with a given format and returns the Epoch time. 195 * 196 * @param date 197 * The string containing the date. 198 * @param format 199 * The format of the date. 200 * @return The date in Epoch format. 201 */ 202 public long getEpoch(String date, String format) { 203 204 SimpleDateFormat formatter = new SimpleDateFormat(format); 205 try { 206 Date dateTime = (Date) formatter.parse(date); 207 return dateTime.getTime(); 208 } catch (ParseException e) { 209 Main.error(e); 210 } 211 return currentTime(); 212 } 213 214 /** 215 * Returns current time in Epoch format 216 * 217 * @return The current date in Epoch format. 218 */ 219 private long currentTime() { 220 Calendar cal = Calendar.getInstance(); 221 return cal.getTimeInMillis(); 222 } 210 return currentTime(); 211 } 212 213 /** 214 * Returns current time in Epoch format 215 * 216 * @return The current date in Epoch format. 217 */ 218 private long currentTime() { 219 Calendar cal = Calendar.getInstance(); 220 return cal.getTimeInMillis(); 221 } 223 222 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java
r31341 r31350 20 20 */ 21 21 public class MapillaryData implements ICachedLoaderListener { 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 /** The image under the cursor */ 28 private MapillaryAbstractImage highlightedImage; 29 private final List<MapillaryAbstractImage> multiSelectedImages; 30 31 private List<MapillaryDataListener> listeners = new ArrayList<>(); 32 33 public MapillaryData() { 34 images = new CopyOnWriteArrayList<>(); 35 multiSelectedImages = new ArrayList<>(); 36 selectedImage = null; 37 } 38 39 public static MapillaryData getInstance() { 40 if (INSTANCE == null) { 41 INSTANCE = new MapillaryData(); 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 /** The image under the cursor */ 28 private MapillaryAbstractImage highlightedImage; 29 private final List<MapillaryAbstractImage> multiSelectedImages; 30 31 private List<MapillaryDataListener> listeners = new ArrayList<>(); 32 33 public MapillaryData() { 34 images = new CopyOnWriteArrayList<>(); 35 multiSelectedImages = new ArrayList<>(); 36 selectedImage = null; 37 } 38 39 public static MapillaryData getInstance() { 40 if (INSTANCE == null) { 41 INSTANCE = new MapillaryData(); 42 } 43 return INSTANCE; 44 } 45 46 /** 47 * Adds a set of MapillaryImages to the object, and then repaints mapView. 48 * 49 * @param images 50 * The set of images to be added. 51 */ 52 public synchronized void add(List<MapillaryAbstractImage> images) { 53 for (MapillaryAbstractImage image : images) { 54 add(image); 55 } 56 } 57 58 /** 59 * Adds an MapillaryImage to the object, and then repaints mapView. 60 * 61 * @param image 62 * The image to be added. 63 */ 64 public synchronized void add(MapillaryAbstractImage image) { 65 if (!images.contains(image)) { 66 this.images.add(image); 67 } 68 dataUpdated(); 69 fireImagesAdded(); 70 } 71 72 public void addListener(MapillaryDataListener lis) { 73 listeners.add(lis); 74 } 75 76 public void removeListener(MapillaryDataListener lis) { 77 listeners.remove(lis); 78 } 79 80 /** 81 * Adds a set of MapillaryImages to the object, but doesn't repaint mapView. 82 * This is needed for concurrency. 83 * 84 * @param images 85 * The set of images to be added. 86 */ 87 public synchronized void addWithoutUpdate(List<MapillaryAbstractImage> images) { 88 for (MapillaryAbstractImage image : images) { 89 addWithoutUpdate(image); 90 } 91 } 92 93 /** 94 * Highlights the image under the cursor. 95 * 96 * @param image 97 * The image under the cursor. 98 */ 99 public void setHighlightedImage(MapillaryAbstractImage image) { 100 highlightedImage = image; 101 } 102 103 /** 104 * Returns the image under the mouse cursor. 105 * 106 * @return The image under the mouse cursor. 107 */ 108 public MapillaryAbstractImage getHoveredImage() { 109 return highlightedImage; 110 } 111 112 /** 113 * Adds a MapillaryImage to the object, but doesn't repaint mapView. This is 114 * needed for concurrency. 115 * 116 * @param image 117 * The image to be added. 118 */ 119 public synchronized void addWithoutUpdate(MapillaryAbstractImage image) { 120 if (!images.contains(image)) { 121 this.images.add(image); 122 } 123 fireImagesAdded(); 124 } 125 126 /** 127 * Repaints mapView object. 128 */ 129 public synchronized void dataUpdated() { 130 if (!TEST_MODE) 131 Main.map.mapView.repaint(); 132 } 133 134 /** 135 * Returns a List containing all images. 136 * 137 * @return A List object containing all images. 138 */ 139 public List<MapillaryAbstractImage> getImages() { 140 return images; 141 } 142 143 /** 144 * Returns the MapillaryImage object that is currently selected. 145 * 146 * @return The selected MapillaryImage object. 147 */ 148 public MapillaryAbstractImage getSelectedImage() { 149 return selectedImage; 150 } 151 152 private void fireImagesAdded() { 153 if (listeners.isEmpty()) 154 return; 155 for (MapillaryDataListener lis : listeners) 156 lis.imagesAdded(); 157 } 158 159 /** 160 * If the selected MapillaryImage is part of a MapillarySequence then the 161 * following visible MapillaryImage is selected. In case there is none, does 162 * nothing. 163 */ 164 public void selectNext() { 165 if (getSelectedImage() instanceof MapillaryImage) { 166 if (getSelectedImage() == null) 167 return; 168 if (((MapillaryImage) getSelectedImage()).getSequence() == null) 169 return; 170 if (selectedImage instanceof MapillaryImage 171 && ((MapillaryImage) selectedImage).getSequence() != null) { 172 MapillaryImage tempImage = (MapillaryImage) selectedImage; 173 while (tempImage.next() != null) { 174 tempImage = tempImage.next(); 175 if (tempImage.isVisible()) { 176 setSelectedImage(tempImage, 177 Main.pref.getBoolean("mapillary.move-to-picture", true)); 178 break; 179 } 42 180 } 43 return INSTANCE; 44 } 45 46 /** 47 * Adds a set of MapillaryImages to the object, and then repaints mapView. 48 * 49 * @param images 50 * The set of images to be added. 51 */ 52 public synchronized void add(List<MapillaryAbstractImage> images) { 53 for (MapillaryAbstractImage image : images) { 54 add(image); 181 } 182 } 183 } 184 185 /** 186 * If the selected MapillaryImage is part of a MapillarySequence then the 187 * previous visible MapillaryImage is selected. In case there is none, does 188 * nothing. 189 */ 190 public void selectPrevious() { 191 if (getSelectedImage() instanceof MapillaryImage) { 192 if (getSelectedImage() == null) 193 return; 194 if (((MapillaryImage) getSelectedImage()).getSequence() == null) 195 throw new IllegalStateException(); 196 if (selectedImage instanceof MapillaryImage 197 && ((MapillaryImage) selectedImage).getSequence() != null) { 198 MapillaryImage tempImage = (MapillaryImage) selectedImage; 199 while (tempImage.previous() != null) { 200 tempImage = tempImage.previous(); 201 if (tempImage.isVisible()) { 202 setSelectedImage(tempImage, 203 Main.pref.getBoolean("mapillary.move-to-picture", true)); 204 break; 205 } 55 206 } 56 } 57 58 /** 59 * Adds an MapillaryImage to the object, and then repaints mapView. 60 * 61 * @param image 62 * The image to be added. 63 */ 64 public synchronized void add(MapillaryAbstractImage image) { 65 if (!images.contains(image)) { 66 this.images.add(image); 207 } 208 } 209 } 210 211 /** 212 * Selects a new image and then starts a new 213 * {@link MapillaryImageDownloadThread} thread in order to download its 214 * surrounding thumbnails. If the user does ctrl+click, this isn't triggered. 215 * 216 * @param image 217 * The MapillaryImage which is going to be selected 218 */ 219 public void setSelectedImage(MapillaryAbstractImage image) { 220 setSelectedImage(image, false); 221 } 222 223 /** 224 * Selects a new image and then starts a new 225 * {@link MapillaryImageDownloadThread} thread in order to download its 226 * surrounding thumbnails. If the user does ctrl+click, this isn't triggered. 227 * You can choose whether to center the view on the new image or not. 228 * 229 * @param image 230 * The {@link MapillaryImage} which is going to be selected. 231 * @param zoom 232 * True if the view must be centered on the image; false otherwise. 233 */ 234 public void setSelectedImage(MapillaryAbstractImage image, boolean zoom) { 235 MapillaryAbstractImage oldImage = selectedImage; 236 selectedImage = image; 237 multiSelectedImages.clear(); 238 multiSelectedImages.add(image); 239 if (image != null) { 240 if (image instanceof MapillaryImage) { 241 MapillaryImage mapillaryImage = (MapillaryImage) image; 242 // Donwloadins thumbnails of surrounding pictures. 243 if (mapillaryImage.next() != null) { 244 new MapillaryCache(mapillaryImage.next().getKey(), 245 MapillaryCache.Type.THUMBNAIL).submit(this, false); 246 if (mapillaryImage.next().next() != null) 247 new MapillaryCache(mapillaryImage.next().next().getKey(), 248 MapillaryCache.Type.THUMBNAIL).submit(this, false); 67 249 } 68 dataUpdated(); 69 fireImagesAdded(); 70 } 71 72 public void addListener(MapillaryDataListener lis) { 73 listeners.add(lis); 74 } 75 76 public void removeListener(MapillaryDataListener lis) { 77 listeners.remove(lis); 78 } 79 80 /** 81 * Adds a set of MapillaryImages to the object, but doesn't repaint mapView. 82 * This is needed for concurrency. 83 * 84 * @param images 85 * The set of images to be added. 86 */ 87 public synchronized void addWithoutUpdate( 88 List<MapillaryAbstractImage> images) { 89 for (MapillaryAbstractImage image : images) { 90 addWithoutUpdate(image); 250 if (mapillaryImage.previous() != null) { 251 new MapillaryCache(mapillaryImage.previous().getKey(), 252 MapillaryCache.Type.THUMBNAIL).submit(this, false); 253 if (mapillaryImage.previous().previous() != null) 254 new MapillaryCache(mapillaryImage.previous().previous().getKey(), 255 MapillaryCache.Type.THUMBNAIL).submit(this, false); 91 256 } 92 } 93 94 /** 95 * Highlights the image under the cursor. 96 * 97 * @param image 98 * The image under the cursor. 99 */ 100 public void setHighlightedImage(MapillaryAbstractImage image) { 101 highlightedImage = image; 102 } 103 104 /** 105 * Returns the image under the mouse cursor. 106 * 107 * @return The image under the mouse cursor. 108 */ 109 public MapillaryAbstractImage getHoveredImage() { 110 return highlightedImage; 111 } 112 113 /** 114 * Adds a MapillaryImage to the object, but doesn't repaint mapView. This is 115 * needed for concurrency. 116 * 117 * @param image 118 * The image to be added. 119 */ 120 public synchronized void addWithoutUpdate(MapillaryAbstractImage image) { 121 if (!images.contains(image)) { 122 this.images.add(image); 123 } 124 fireImagesAdded(); 125 } 126 127 /** 128 * Repaints mapView object. 129 */ 130 public synchronized void dataUpdated() { 131 if (!TEST_MODE) 132 Main.map.mapView.repaint(); 133 } 134 135 /** 136 * Returns a List containing all images. 137 * 138 * @return A List object containing all images. 139 */ 140 public List<MapillaryAbstractImage> getImages() { 141 return images; 142 } 143 144 /** 145 * Returns the MapillaryImage object that is currently selected. 146 * 147 * @return The selected MapillaryImage object. 148 */ 149 public MapillaryAbstractImage getSelectedImage() { 150 return selectedImage; 151 } 152 153 private void fireImagesAdded() { 154 if (listeners.isEmpty()) 155 return; 156 for (MapillaryDataListener lis : listeners) 157 lis.imagesAdded(); 158 } 159 160 /** 161 * If the selected MapillaryImage is part of a MapillarySequence then the 162 * following visible MapillaryImage is selected. In case there is none, does 163 * nothing. 164 */ 165 public void selectNext() { 166 if (getSelectedImage() instanceof MapillaryImage) { 167 if (getSelectedImage() == null) 168 return; 169 if (((MapillaryImage) getSelectedImage()).getSequence() == null) 170 return; 171 if (selectedImage instanceof MapillaryImage 172 && ((MapillaryImage) selectedImage).getSequence() != null) { 173 MapillaryImage tempImage = (MapillaryImage) selectedImage; 174 while (tempImage.next() != null) { 175 tempImage = tempImage.next(); 176 if (tempImage.isVisible()) { 177 setSelectedImage(tempImage, Main.pref.getBoolean( 178 "mapillary.move-to-picture", true)); 179 break; 180 } 181 } 182 } 183 } 184 } 185 186 /** 187 * If the selected MapillaryImage is part of a MapillarySequence then the 188 * previous visible MapillaryImage is selected. In case there is none, does 189 * nothing. 190 */ 191 public void selectPrevious() { 192 if (getSelectedImage() instanceof MapillaryImage) { 193 if (getSelectedImage() == null) 194 return; 195 if (((MapillaryImage) getSelectedImage()).getSequence() == null) 196 throw new IllegalStateException(); 197 if (selectedImage instanceof MapillaryImage 198 && ((MapillaryImage) selectedImage).getSequence() != null) { 199 MapillaryImage tempImage = (MapillaryImage) selectedImage; 200 while (tempImage.previous() != null) { 201 tempImage = tempImage.previous(); 202 if (tempImage.isVisible()) { 203 setSelectedImage(tempImage, Main.pref.getBoolean( 204 "mapillary.move-to-picture", true)); 205 break; 206 } 207 } 208 } 209 } 210 } 211 212 /** 213 * Selects a new image and then starts a new 214 * {@link MapillaryImageDownloadThread} thread in order to download its 215 * surrounding thumbnails. If the user does ctrl+click, this isn't 216 * triggered. 217 * 218 * @param image 219 * The MapillaryImage which is going to be selected 220 */ 221 public void setSelectedImage(MapillaryAbstractImage image) { 222 setSelectedImage(image, false); 223 } 224 225 /** 226 * Selects a new image and then starts a new 227 * {@link MapillaryImageDownloadThread} thread in order to download its 228 * surrounding thumbnails. If the user does ctrl+click, this isn't 229 * triggered. You can choose whether to center the view on the new image or 230 * not. 231 * 232 * @param image 233 * The {@link MapillaryImage} which is going to be selected. 234 * @param zoom 235 * True if the view must be centered on the image; false 236 * otherwise. 237 */ 238 public void setSelectedImage(MapillaryAbstractImage image, boolean zoom) { 239 MapillaryAbstractImage oldImage = selectedImage; 240 selectedImage = image; 241 multiSelectedImages.clear(); 242 multiSelectedImages.add(image); 243 if (image != null) { 244 if (image instanceof MapillaryImage) { 245 MapillaryImage mapillaryImage = (MapillaryImage) image; 246 // Donwloadins thumbnails of surrounding pictures. 247 if (mapillaryImage.next() != null) { 248 new MapillaryCache(mapillaryImage.next().getKey(), 249 MapillaryCache.Type.THUMBNAIL).submit(this, false); 250 if (mapillaryImage.next().next() != null) 251 new MapillaryCache(mapillaryImage.next().next() 252 .getKey(), MapillaryCache.Type.THUMBNAIL) 253 .submit(this, false); 254 } 255 if (mapillaryImage.previous() != null) { 256 new MapillaryCache(mapillaryImage.previous().getKey(), 257 MapillaryCache.Type.THUMBNAIL).submit(this, false); 258 if (mapillaryImage.previous().previous() != null) 259 new MapillaryCache(mapillaryImage.previous().previous() 260 .getKey(), MapillaryCache.Type.THUMBNAIL) 261 .submit(this, false); 262 } 263 } 264 } 265 if (zoom) 266 Main.map.mapView.zoomTo(MapillaryData.getInstance() 267 .getSelectedImage().getLatLon()); 268 if (Main.map != null) 269 Main.map.mapView.repaint(); 270 fireSelectedImageChanged(oldImage, selectedImage); 271 } 272 273 private void fireSelectedImageChanged(MapillaryAbstractImage oldImage, 274 MapillaryAbstractImage newImage) { 275 if (listeners.isEmpty()) 276 return; 277 for (MapillaryDataListener lis : listeners) 278 lis.selectedImageChanged(oldImage, newImage); 279 } 280 281 /** 282 * Adds a MapillaryImage object to the list of selected images, (when ctrl + 283 * click) 284 * 285 * @param image 286 * The MapillaryImage object to be added. 287 */ 288 public void addMultiSelectedImage(MapillaryAbstractImage image) { 289 if (!this.multiSelectedImages.contains(image)) { 290 if (this.getSelectedImage() != null) 291 this.multiSelectedImages.add(image); 292 else 293 this.setSelectedImage(image); 294 } 295 Main.map.mapView.repaint(); 296 } 297 298 /** 299 * Adds a set of {@code MapillaryAbstractImage} objects to the list of 300 * selected images. 301 * 302 * @param images 303 * A List object containing the set of images to be added. 304 */ 305 public void addMultiSelectedImage(List<MapillaryAbstractImage> images) { 306 for (MapillaryAbstractImage image : images) 307 if (!this.multiSelectedImages.contains(image)) { 308 if (this.getSelectedImage() != null) 309 this.multiSelectedImages.add(image); 310 else 311 this.setSelectedImage(image); 312 } 313 Main.map.mapView.repaint(); 314 } 315 316 /** 317 * Returns a List containing all {@code MapillaryAbstractImage} objects 318 * selected with ctrl + click 319 * 320 * @return A List object containing all the images selected. 321 */ 322 public List<MapillaryAbstractImage> getMultiSelectedImages() { 323 return multiSelectedImages; 324 } 325 326 /** 327 * This is empty because it is used just to make sure that certain images 328 * have already been downloaded. 329 */ 330 @Override 331 public void loadingFinished(CacheEntry data, 332 CacheEntryAttributes attributes, LoadResult result) { 333 // DO NOTHING 334 } 335 336 /** 337 * Returns the amount of images contained by this object. 338 * 339 * @return The amount of images in stored. 340 */ 341 public int size() { 342 return images.size(); 343 } 257 } 258 } 259 if (zoom) 260 Main.map.mapView.zoomTo(MapillaryData.getInstance().getSelectedImage() 261 .getLatLon()); 262 if (Main.map != null) 263 Main.map.mapView.repaint(); 264 fireSelectedImageChanged(oldImage, selectedImage); 265 } 266 267 private void fireSelectedImageChanged(MapillaryAbstractImage oldImage, 268 MapillaryAbstractImage newImage) { 269 if (listeners.isEmpty()) 270 return; 271 for (MapillaryDataListener lis : listeners) 272 lis.selectedImageChanged(oldImage, newImage); 273 } 274 275 /** 276 * Adds a MapillaryImage object to the list of selected images, (when ctrl + 277 * click) 278 * 279 * @param image 280 * The MapillaryImage object to be added. 281 */ 282 public void addMultiSelectedImage(MapillaryAbstractImage image) { 283 if (!this.multiSelectedImages.contains(image)) { 284 if (this.getSelectedImage() != null) 285 this.multiSelectedImages.add(image); 286 else 287 this.setSelectedImage(image); 288 } 289 Main.map.mapView.repaint(); 290 } 291 292 /** 293 * Adds a set of {@code MapillaryAbstractImage} objects to the list of 294 * selected images. 295 * 296 * @param images 297 * A List object containing the set of images to be added. 298 */ 299 public void addMultiSelectedImage(List<MapillaryAbstractImage> images) { 300 for (MapillaryAbstractImage image : images) 301 if (!this.multiSelectedImages.contains(image)) { 302 if (this.getSelectedImage() != null) 303 this.multiSelectedImages.add(image); 304 else 305 this.setSelectedImage(image); 306 } 307 Main.map.mapView.repaint(); 308 } 309 310 /** 311 * Returns a List containing all {@code MapillaryAbstractImage} objects 312 * selected with ctrl + click 313 * 314 * @return A List object containing all the images selected. 315 */ 316 public List<MapillaryAbstractImage> getMultiSelectedImages() { 317 return multiSelectedImages; 318 } 319 320 /** 321 * This is empty because it is used just to make sure that certain images have 322 * already been downloaded. 323 */ 324 @Override 325 public void loadingFinished(CacheEntry data, CacheEntryAttributes attributes, 326 LoadResult result) { 327 // DO NOTHING 328 } 329 330 /** 331 * Returns the amount of images contained by this object. 332 * 333 * @return The amount of images in stored. 334 */ 335 public int size() { 336 return images.size(); 337 } 344 338 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryDataListener.java
r31333 r31350 3 3 public interface MapillaryDataListener { 4 4 5 6 7 8 5 /** 6 * Fired when any image is added to the database. 7 */ 8 public void imagesAdded(); 9 9 10 11 12 13 14 15 10 /** 11 * Fired when the selected image is changed by something different from 12 * manually clicking on the icon. 13 */ 14 public void selectedImageChanged(MapillaryAbstractImage oldImage, 15 MapillaryAbstractImage newImage); 16 16 17 17 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImage.java
r31333 r31350 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 19 /** The user that made the image */ 20 private String user; 21 /** Set of traffic signs in the image */ 22 private List<String> signs; 23 private String location; 24 24 25 public String getLocation() { 26 return location; 25 public String getLocation() { 26 return location; 27 } 28 29 public void setLocation(String location) { 30 this.location = location; 31 } 32 33 /** 34 * Main contructor of the class MapillaryImage 35 * 36 * @param key 37 * The unique identifier of the image. 38 * @param lat 39 * The latitude where it is positioned. 40 * @param lon 41 * The longitude where it is positioned. 42 * @param ca 43 * The direction of the images in degrees, meaning 0 north. 44 */ 45 public MapillaryImage(String key, double lat, double lon, double ca) { 46 super(lat, lon, ca); 47 this.key = key; 48 this.signs = new ArrayList<>(); 49 } 50 51 /** 52 * Returns the unique identifier of the object. 53 * 54 * @return A String containing the unique identifier of the object. 55 */ 56 public String getKey() { 57 return this.key; 58 } 59 60 /** 61 * Adds a new sign to the set of signs. 62 * 63 * @param sign 64 * A String that identifies the type of sign. 65 */ 66 public void addSign(String sign) { 67 signs.add(sign); 68 } 69 70 /** 71 * Returns a List containing the signs assigned to this image. 72 * 73 * @return A List object containing the signs assigned to this image. 74 */ 75 public List<String> getSigns() { 76 return signs; 77 } 78 79 /** 80 * Sets the username of the person who took the image. 81 * 82 * @param user 83 * A String containing the username of the person who took the image. 84 */ 85 public void setUser(String user) { 86 this.user = user; 87 } 88 89 public String getUser() { 90 return user; 91 } 92 93 /** 94 * Sets the MapillarySequence object which contains the MapillaryImage. 95 * 96 * @param sequence 97 * The MapillarySequence that contains the MapillaryImage. 98 */ 99 public void setSequence(MapillarySequence sequence) { 100 this.sequence = sequence; 101 } 102 103 /** 104 * Returns the sequence which contains this image. 105 * 106 * @return The MapillarySequence object that contains this MapillaryImage. 107 */ 108 public MapillarySequence getSequence() { 109 return this.sequence; 110 } 111 112 public String toString() { 113 return "Image[key=" + this.key + ";lat=" + this.latLon.lat() + ";lon=" 114 + this.latLon.lon() + ";ca=" + this.ca + "]"; 115 } 116 117 /** 118 * If the MapillaryImage belongs to a MapillarySequence, returns the next 119 * MapillarySequence in it. 120 * 121 * @return The following MapillaryImage, or null if there is none. 122 */ 123 public MapillaryImage next() { 124 synchronized (lock) { 125 if (this.getSequence() == null) 126 return null; 127 return this.getSequence().next(this); 27 128 } 129 } 28 130 29 public void setLocation(String location) { 30 this.location = location; 131 /** 132 * If the MapillaryImage belongs to a MapillarySequence, returns the previous 133 * MapillarySequence in it. 134 * 135 * @return The previous MapillaryImage, or null if there is none. 136 */ 137 public MapillaryImage previous() { 138 synchronized (lock) { 139 if (this.getSequence() == null) 140 return null; 141 return this.getSequence().previous(this); 31 142 } 143 } 32 144 33 /** 34 * Main contructor of the class MapillaryImage 35 * 36 * @param key 37 * The unique identifier of the image. 38 * @param lat 39 * The latitude where it is positioned. 40 * @param lon 41 * The longitude where it is positioned. 42 * @param ca 43 * The direction of the images in degrees, meaning 0 north. 44 */ 45 public MapillaryImage(String key, double lat, double lon, double ca) { 46 super(lat, lon, ca); 47 this.key = key; 48 this.signs = new ArrayList<>(); 49 } 145 @Override 146 public boolean equals(Object object) { 147 if (object instanceof MapillaryImage) 148 return this.key.equals(((MapillaryImage) object).getKey()); 149 return false; 150 } 50 151 51 /** 52 * Returns the unique identifier of the object. 53 * 54 * @return A String containing the unique identifier of the object. 55 */ 56 public String getKey() { 57 return this.key; 58 } 59 60 /** 61 * Adds a new sign to the set of signs. 62 * 63 * @param sign 64 * A String that identifies the type of sign. 65 */ 66 public void addSign(String sign) { 67 signs.add(sign); 68 } 69 70 /** 71 * Returns a List containing the signs assigned to this image. 72 * 73 * @return A List object containing the signs assigned to this image. 74 */ 75 public List<String> getSigns() { 76 return signs; 77 } 78 79 /** 80 * Sets the username of the person who took the image. 81 * @param user A String containing the username of the person who took the image. 82 */ 83 public void setUser(String user) { 84 this.user = user; 85 } 86 87 public String getUser() { 88 return user; 89 } 90 91 /** 92 * Sets the MapillarySequence object which contains the MapillaryImage. 93 * 94 * @param sequence 95 * The MapillarySequence that contains the MapillaryImage. 96 */ 97 public void setSequence(MapillarySequence sequence) { 98 this.sequence = sequence; 99 } 100 101 /** 102 * Returns the sequence which contains this image. 103 * 104 * @return The MapillarySequence object that contains this MapillaryImage. 105 */ 106 public MapillarySequence getSequence() { 107 return this.sequence; 108 } 109 110 public String toString() { 111 return "Image[key=" + this.key + ";lat=" + this.latLon.lat() + ";lon=" 112 + this.latLon.lon() + ";ca=" + this.ca + "]"; 113 } 114 115 /** 116 * If the MapillaryImage belongs to a MapillarySequence, returns the next 117 * MapillarySequence in it. 118 * 119 * @return The following MapillaryImage, or null if there is none. 120 */ 121 public MapillaryImage next() { 122 synchronized (lock) { 123 if (this.getSequence() == null) 124 return null; 125 return this.getSequence().next(this); 126 } 127 } 128 129 /** 130 * If the MapillaryImage belongs to a MapillarySequence, returns the 131 * previous MapillarySequence in it. 132 * 133 * @return The previous MapillaryImage, or null if there is none. 134 */ 135 public MapillaryImage previous() { 136 synchronized (lock) { 137 if (this.getSequence() == null) 138 return null; 139 return this.getSequence().previous(this); 140 } 141 } 142 143 @Override 144 public boolean equals(Object object) { 145 if (object instanceof MapillaryImage) 146 return this.key.equals(((MapillaryImage) object).getKey()); 147 return false; 148 } 149 150 @Override 151 public int hashCode() { 152 return this.key.hashCode(); 153 } 152 @Override 153 public int hashCode() { 154 return this.key.hashCode(); 155 } 154 156 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImportedImage.java
r31348 r31350 11 11 public class MapillaryImportedImage extends MapillaryAbstractImage { 12 12 13 14 15 16 17 13 /** 14 * The picture file. 15 */ 16 protected File file; 17 public final long datetimeOriginal; 18 18 19 20 21 19 public MapillaryImportedImage(double lat, double lon, double ca, File file) { 20 this(lat, lon, ca, file, currentDate()); 21 } 22 22 23 public MapillaryImportedImage(double lat, double lon, double ca, File file, 24 String datetimeOriginal) { 25 super(lat, lon, ca); 26 this.file = file; 27 this.datetimeOriginal = getEpoch(datetimeOriginal, 28 "yyyy:MM:dd hh:mm:ss"); 29 } 23 public MapillaryImportedImage(double lat, double lon, double ca, File file, 24 String datetimeOriginal) { 25 super(lat, lon, ca); 26 this.file = file; 27 this.datetimeOriginal = getEpoch(datetimeOriginal, "yyyy:MM:dd hh:mm:ss"); 28 } 30 29 31 /** 32 * Returns the pictures of the file. 33 * 34 * @return A BufferedImage object containing the pictures. 35 * @throws IOException 36 * @throws IllegalArgumentException if file is currently set to null 37 */ 38 public BufferedImage getImage() throws IOException { 39 return ImageIO.read(file); 40 } 30 /** 31 * Returns the pictures of the file. 32 * 33 * @return A BufferedImage object containing the pictures. 34 * @throws IOException 35 * @throws IllegalArgumentException 36 * if file is currently set to null 37 */ 38 public BufferedImage getImage() throws IOException { 39 return ImageIO.read(file); 40 } 41 41 42 /** 43 * Returns the File object where the picture is located. 44 * @return The File object where the picture is located. 45 */ 46 public File getFile() { 47 return file; 48 } 42 /** 43 * Returns the File object where the picture is located. 44 * 45 * @return The File object where the picture is located. 46 */ 47 public File getFile() { 48 return file; 49 } 49 50 50 51 52 53 54 55 51 @Override 52 public boolean equals(Object object) { 53 if (object instanceof MapillaryImportedImage) 54 return this.file.equals(((MapillaryImportedImage) object).file); 55 return false; 56 } 56 57 57 58 59 60 58 @Override 59 public int hashCode() { 60 return this.file.hashCode(); 61 } 61 62 62 63 63 private static String currentDate() { 64 Calendar cal = Calendar.getInstance(); 64 65 65 66 66 SimpleDateFormat formatter = new SimpleDateFormat("yyyy:MM:dd hh:mm:ss"); 67 return formatter.format(cal.getTime()); 67 68 68 69 } 69 70 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java
r31347 r31350 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 private boolean TEMP_MANUAL = false; 67 68 public static MapillaryLayer INSTANCE; 69 public static CacheAccess<String, BufferedImageCacheEntry> CACHE; 70 public static MapillaryImage BLUE; 71 public static MapillaryImage RED; 72 73 public final MapillaryData data = MapillaryData.getInstance(); 74 75 public ArrayList<Bounds> bounds; 76 77 private MouseAdapter mouseAdapter; 78 79 private int highlightPointRadius = Main.pref.getInteger( 80 "mappaint.highlight.radius", 7); 81 private int highlightStep = Main.pref.getInteger("mappaint.highlight.step", 82 4); 83 84 private volatile TexturePaint hatched; 85 86 private MapillaryLayer() { 87 super(tr("Mapillary Images")); 88 bounds = new ArrayList<>(); 89 init(); 90 } 91 92 /** 93 * Initializes the Layer. 94 */ 95 private void init() { 96 mouseAdapter = new MapillaryMouseAdapter(); 97 try { 98 CACHE = JCSCacheManager.getCache("Mapillary"); 99 } catch (IOException e) { 100 Main.error(e); 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 private boolean TEMP_MANUAL = false; 67 68 public static MapillaryLayer INSTANCE; 69 public static CacheAccess<String, BufferedImageCacheEntry> CACHE; 70 public static MapillaryImage BLUE; 71 public static MapillaryImage RED; 72 73 public final MapillaryData data = MapillaryData.getInstance(); 74 75 public ArrayList<Bounds> bounds; 76 77 private MouseAdapter mouseAdapter; 78 79 private int highlightPointRadius = Main.pref.getInteger( 80 "mappaint.highlight.radius", 7); 81 private int highlightStep = Main.pref 82 .getInteger("mappaint.highlight.step", 4); 83 84 private volatile TexturePaint hatched; 85 86 private MapillaryLayer() { 87 super(tr("Mapillary Images")); 88 bounds = new ArrayList<>(); 89 init(); 90 } 91 92 /** 93 * Initializes the Layer. 94 */ 95 private void init() { 96 mouseAdapter = new MapillaryMouseAdapter(); 97 try { 98 CACHE = JCSCacheManager.getCache("Mapillary"); 99 } catch (IOException e) { 100 Main.error(e); 101 } 102 if (Main.map != null && Main.map.mapView != null) { 103 Main.map.mapView.addMouseListener(mouseAdapter); 104 Main.map.mapView.addMouseMotionListener(mouseAdapter); 105 Main.map.mapView.addLayer(this); 106 MapView.addEditLayerChangeListener(this, false); 107 MapView.addLayerChangeListener(this); 108 if (Main.map.mapView.getEditLayer() != null) 109 Main.map.mapView.getEditLayer().data.addDataSetListener(this); 110 } 111 if (MapillaryPlugin.EXPORT_MENU != null) { // Does not execute when in 112 // headless mode 113 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, true); 114 if (!MapillaryMainDialog.getInstance().isShowing()) 115 MapillaryMainDialog.getInstance().getButton().doClick(); 116 } 117 118 createHatchTexture(); 119 data.dataUpdated(); 120 } 121 122 public synchronized static MapillaryLayer getInstance() { 123 if (MapillaryLayer.INSTANCE == null) 124 MapillaryLayer.INSTANCE = new MapillaryLayer(); 125 return MapillaryLayer.INSTANCE; 126 } 127 128 /** 129 * Downloads all images of the area covered by the OSM data. This is only just 130 * for automatic download. 131 */ 132 public void download() { 133 checkAreaTooBig(); 134 if (Main.pref.getBoolean("mapillary.download-manually") || TEMP_MANUAL) 135 return; 136 for (Bounds bounds : Main.map.mapView.getEditLayer().data 137 .getDataSourceBounds()) { 138 if (!this.bounds.contains(bounds)) { 139 this.bounds.add(bounds); 140 new MapillaryDownloader().getImages(bounds.getMin(), 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 shown 149 * and you will have to download areas manually. 150 */ 151 private void checkAreaTooBig() { 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 TEMP_MANUAL = true; 159 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.DOWNLOAD_VIEW_MENU, true); 160 JOptionPane 161 .showMessageDialog( 162 Main.parent, 163 tr("The downloaded OSM area is too big. Download mode has been changed to manual until the layer is restarted.")); 164 } 165 } 166 167 /** 168 * Returns the MapillaryData object, which acts as the database of the 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 MapillaryMainDialog.getInstance().setImage(null); 182 MapillaryMainDialog.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"), Color.YELLOW); 231 } 232 233 /** 234 * Initialize the hatch pattern used to paint the non-downloaded area 235 */ 236 private void createHatchTexture() { 237 BufferedImage bi = new BufferedImage(15, 15, BufferedImage.TYPE_INT_ARGB); 238 Graphics2D big = bi.createGraphics(); 239 big.setColor(getBackgroundColor()); 240 Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f); 241 big.setComposite(comp); 242 big.fillRect(0, 0, 15, 15); 243 big.setColor(getOutsideColor()); 244 big.drawLine(0, 15, 15, 0); 245 Rectangle r = new Rectangle(0, 0, 15, 15); 246 hatched = new TexturePaint(bi, r); 247 } 248 249 /** 250 * Paints the database in the map. 251 */ 252 @Override 253 public synchronized void paint(Graphics2D g, MapView mv, Bounds box) { 254 if (Main.map.mapView.getActiveLayer() == this) { 255 Rectangle b = mv.getBounds(); 256 // on some platforms viewport bounds seem to be offset from the 257 // left, 258 // over-grow it just to be sure 259 b.grow(100, 100); 260 Area a = new Area(b); 261 // now successively subtract downloaded areas 262 for (Bounds bounds : this.bounds) { 263 Point p1 = mv.getPoint(bounds.getMin()); 264 Point p2 = mv.getPoint(bounds.getMax()); 265 Rectangle r = new Rectangle(Math.min(p1.x, p2.x), Math.min(p1.y, p2.y), 266 Math.abs(p2.x - p1.x), Math.abs(p2.y - p1.y)); 267 a.subtract(new Area(r)); 268 } 269 // paint remainder 270 g.setPaint(hatched); 271 g.fill(a); 272 } 273 274 // Draw colored lines 275 MapillaryLayer.BLUE = null; 276 MapillaryLayer.RED = null; 277 MapillaryMainDialog.getInstance().blueButton.setEnabled(false); 278 MapillaryMainDialog.getInstance().redButton.setEnabled(false); 279 280 // Sets blue and red lines and enables/disables the buttons 281 if (data.getSelectedImage() != null) { 282 MapillaryImage[] closestImages = getClosestImagesFromDifferentSequences(); 283 Point selected = mv.getPoint(data.getSelectedImage().getLatLon()); 284 if (closestImages[0] != null) { 285 MapillaryLayer.BLUE = closestImages[0]; 286 g.setColor(Color.BLUE); 287 g.drawLine(mv.getPoint(closestImages[0].getLatLon()).x, 288 mv.getPoint(closestImages[0].getLatLon()).y, selected.x, selected.y); 289 MapillaryMainDialog.getInstance().blueButton.setEnabled(true); 290 } 291 if (closestImages[1] != null) { 292 MapillaryLayer.RED = closestImages[1]; 293 g.setColor(Color.RED); 294 g.drawLine(mv.getPoint(closestImages[1].getLatLon()).x, 295 mv.getPoint(closestImages[1].getLatLon()).y, selected.x, selected.y); 296 MapillaryMainDialog.getInstance().redButton.setEnabled(true); 297 } 298 } 299 g.setColor(Color.WHITE); 300 for (MapillaryAbstractImage imageAbs : data.getImages()) { 301 if (!imageAbs.isVisible()) 302 continue; 303 Point p = mv.getPoint(imageAbs.getLatLon()); 304 if (imageAbs instanceof MapillaryImage) { 305 MapillaryImage image = (MapillaryImage) imageAbs; 306 Point nextp = null; 307 // Draw sequence line 308 if (image.getSequence() != null) { 309 MapillaryImage tempImage = image.next(); 310 while (tempImage != null) { 311 if (tempImage.isVisible()) { 312 nextp = mv.getPoint(tempImage.getLatLon()); 313 break; 314 } 315 tempImage = tempImage.next(); 316 } 317 if (nextp != null) 318 g.drawLine(p.x, p.y, nextp.x, nextp.y); 101 319 } 102 if (Main.map != null && Main.map.mapView != null) { 103 Main.map.mapView.addMouseListener(mouseAdapter); 104 Main.map.mapView.addMouseMotionListener(mouseAdapter); 105 Main.map.mapView.addLayer(this); 106 MapView.addEditLayerChangeListener(this, false); 107 MapView.addLayerChangeListener(this); 108 if (Main.map.mapView.getEditLayer() != null) 109 Main.map.mapView.getEditLayer().data.addDataSetListener(this); 320 321 ImageIcon icon; 322 if (!data.getMultiSelectedImages().contains(image)) 323 icon = MapillaryPlugin.MAP_ICON; 324 else 325 icon = MapillaryPlugin.MAP_ICON_SELECTED; 326 draw(g, image, icon, p); 327 if (!image.getSigns().isEmpty()) { 328 g.drawImage(MapillaryPlugin.MAP_SIGN.getImage(), 329 p.x + icon.getIconWidth() / 2, p.y - icon.getIconHeight() / 2, 330 Main.map.mapView); 110 331 } 111 if (MapillaryPlugin.EXPORT_MENU != null) { // Does not execute when in headless mode 112 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, true); 113 if (!MapillaryMainDialog.getInstance().isShowing()) 114 MapillaryMainDialog.getInstance().getButton().doClick(); 332 } else if (imageAbs instanceof MapillaryImportedImage) { 333 MapillaryImportedImage image = (MapillaryImportedImage) imageAbs; 334 ImageIcon icon; 335 if (!data.getMultiSelectedImages().contains(image)) 336 icon = MapillaryPlugin.MAP_ICON_IMPORTED; 337 else 338 icon = MapillaryPlugin.MAP_ICON_SELECTED; 339 draw(g, image, icon, p); 340 } 341 } 342 } 343 344 /** 345 * Draws the highlight of the icon. 346 * 347 * @param g 348 * @param p 349 * @param size 350 */ 351 private void drawPointHighlight(Graphics2D g, Point p, int size) { 352 Color oldColor = g.getColor(); 353 Color highlightColor = PaintColors.HIGHLIGHT.get(); 354 Color highlightColorTransparent = new Color(highlightColor.getRed(), 355 highlightColor.getGreen(), highlightColor.getBlue(), 100); 356 g.setColor(highlightColorTransparent); 357 int s = size + highlightPointRadius; 358 while (s >= size) { 359 int r = (int) Math.floor(s / 2d); 360 g.fillRoundRect(p.x - r, p.y - r, s, s, r, r); 361 s -= highlightStep; 362 } 363 g.setColor(oldColor); 364 } 365 366 /** 367 * Draws the given icon of an image. Also checks if the mouse is over the 368 * image. 369 * 370 * @param g 371 * @param image 372 * @param icon 373 * @param p 374 */ 375 private void draw(Graphics2D g, MapillaryAbstractImage image, ImageIcon icon, 376 Point p) { 377 Image imagetemp = icon.getImage(); 378 BufferedImage bi = (BufferedImage) imagetemp; 379 int width = icon.getIconWidth(); 380 int height = icon.getIconHeight(); 381 382 // Rotate the image 383 double rotationRequired = Math.toRadians(image.getCa()); 384 double locationX = width / 2; 385 double locationY = height / 2; 386 AffineTransform tx = AffineTransform.getRotateInstance(rotationRequired, 387 locationX, locationY); 388 AffineTransformOp op = new AffineTransformOp(tx, 389 AffineTransformOp.TYPE_BILINEAR); 390 391 g.drawImage(op.filter(bi, null), p.x - (width / 2), p.y - (height / 2), 392 Main.map.mapView); 393 if (data.getHoveredImage() == image) { 394 drawPointHighlight(g, p, 16); 395 } 396 } 397 398 @Override 399 public Icon getIcon() { 400 return MapillaryPlugin.ICON16; 401 } 402 403 @Override 404 public boolean isMergable(Layer other) { 405 return false; 406 } 407 408 @Override 409 public void mergeFrom(Layer from) { 410 throw new UnsupportedOperationException( 411 "This layer does not support merging yet"); 412 } 413 414 @Override 415 public Action[] getMenuEntries() { 416 List<Action> actions = new ArrayList<>(); 417 actions.add(LayerListDialog.getInstance().createShowHideLayerAction()); 418 actions.add(LayerListDialog.getInstance().createDeleteLayerAction()); 419 actions.add(new LayerListPopup.InfoAction(this)); 420 return actions.toArray(new Action[actions.size()]); 421 } 422 423 /** 424 * Returns the 2 closest images belonging to a different sequence. 425 * 426 * @return 427 */ 428 private MapillaryImage[] getClosestImagesFromDifferentSequences() { 429 if (!(data.getSelectedImage() instanceof MapillaryImage)) 430 return new MapillaryImage[2]; 431 MapillaryImage selected = (MapillaryImage) data.getSelectedImage(); 432 MapillaryImage[] ret = new MapillaryImage[2]; 433 double[] distances = { SEQUENCE_MAX_JUMP_DISTANCE, 434 SEQUENCE_MAX_JUMP_DISTANCE }; 435 LatLon selectedCoords = data.getSelectedImage().getLatLon(); 436 for (MapillaryAbstractImage imagePrev : data.getImages()) { 437 if (!(imagePrev instanceof MapillaryImage)) 438 continue; 439 if (!imagePrev.isVisible()) 440 continue; 441 MapillaryImage image = (MapillaryImage) imagePrev; 442 if (image.getLatLon().greatCircleDistance(selectedCoords) < SEQUENCE_MAX_JUMP_DISTANCE 443 && selected.getSequence() != image.getSequence()) { 444 if ((ret[0] == null && ret[1] == null) 445 || (image.getLatLon().greatCircleDistance(selectedCoords) < distances[0] && (ret[1] == null || image 446 .getSequence() != ret[1].getSequence()))) { 447 ret[0] = image; 448 distances[0] = image.getLatLon().greatCircleDistance(selectedCoords); 449 } else if ((ret[1] == null || image.getLatLon().greatCircleDistance( 450 selectedCoords) < distances[1]) 451 && image.getSequence() != ret[0].getSequence()) { 452 ret[1] = image; 453 distances[1] = image.getLatLon().greatCircleDistance(selectedCoords); 115 454 } 116 117 createHatchTexture(); 118 data.dataUpdated(); 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 checkAreaTooBig(); 133 if (Main.pref.getBoolean("mapillary.download-manually") || TEMP_MANUAL) 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 checkAreaTooBig() { 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 TEMP_MANUAL = true; 159 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.DOWNLOAD_VIEW_MENU, 160 true); 161 JOptionPane 162 .showMessageDialog( 163 Main.parent, 164 tr("The downloaded OSM area is too big. Download mode has been changed to manual until the layer is restarted.")); 165 } 166 } 167 168 /** 169 * Returns the MapillaryData object, which acts as the database of the 170 * Layer. 171 * 172 * @return 173 */ 174 public MapillaryData getMapillaryData() { 175 return data; 176 } 177 178 /** 179 * Method invoked when the layer is destroyed. 180 */ 455 } 456 } 457 // Predownloads the thumbnails 458 if (ret[0] != null) 459 new MapillaryCache(ret[0].getKey(), MapillaryCache.Type.THUMBNAIL) 460 .submit(data, false); 461 if (ret[1] != null) 462 new MapillaryCache(ret[1].getKey(), MapillaryCache.Type.THUMBNAIL) 463 .submit(data, false); 464 return ret; 465 } 466 467 @Override 468 public Object getInfoComponent() { 469 StringBuilder sb = new StringBuilder(); 470 sb.append(tr("Mapillary layer")); 471 sb.append("\n"); 472 sb.append(tr("Total images:")); 473 sb.append(" "); 474 sb.append(data.size()); 475 sb.append("\n"); 476 return sb.toString(); 477 } 478 479 @Override 480 public String getToolTipText() { 481 return data.size() + " " + tr("images"); 482 } 483 484 // EditDataLayerChanged 485 @Override 486 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) { 487 if (oldLayer == null && newLayer != null) { 488 newLayer.data.addDataSetListener(this); 489 490 } else if (oldLayer != null && newLayer == null) { 491 oldLayer.data.removeDataSetListener(this); 492 } 493 } 494 495 /** 496 * When more data is downloaded, a delayed update is thrown, in order to wait 497 * for the data bounds to be set. 498 * 499 * @param event 500 */ 501 @Override 502 public void dataChanged(DataChangedEvent event) { 503 Main.worker.submit(new delayedDownload()); 504 } 505 506 private class delayedDownload extends Thread { 507 181 508 @Override 182 public void destroy() { 183 MapillaryMainDialog.getInstance().setImage(null); 184 MapillaryMainDialog.getInstance().updateImage(); 185 data.getImages().clear(); 186 MapillaryLayer.INSTANCE = null; 187 MapillaryData.INSTANCE = null; 188 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, false); 189 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.ZOOM_MENU, false); 190 Main.map.mapView.removeMouseListener(mouseAdapter); 191 Main.map.mapView.removeMouseMotionListener(mouseAdapter); 192 MapView.removeEditLayerChangeListener(this); 193 if (Main.map.mapView.getEditLayer() != null) 194 Main.map.mapView.getEditLayer().data.removeDataSetListener(this); 195 super.destroy(); 196 } 197 198 /** 199 * Returns true any of the images from the database has been modified. 200 */ 201 @Override 202 public boolean isModified() { 203 for (MapillaryAbstractImage image : data.getImages()) 204 if (image.isModified()) 205 return true; 206 return false; 207 } 208 209 @Override 210 public void setVisible(boolean visible) { 211 super.setVisible(visible); 212 for (MapillaryAbstractImage img : data.getImages()) 213 img.setVisible(visible); 214 MapillaryFilterDialog.getInstance().refresh(); 215 } 216 217 /** 218 * Replies background color for downloaded areas. 219 * 220 * @return background color for downloaded areas. Black by default 221 */ 222 private Color getBackgroundColor() { 223 return Main.pref.getColor(marktr("background"), Color.BLACK); 224 } 225 226 /** 227 * Replies background color for non-downloaded areas. 228 * 229 * @return background color for non-downloaded areas. Yellow by default 230 */ 231 private Color getOutsideColor() { 232 return Main.pref.getColor(marktr("outside downloaded area"), 233 Color.YELLOW); 234 } 235 236 /** 237 * Initialize the hatch pattern used to paint the non-downloaded area 238 */ 239 private void createHatchTexture() { 240 BufferedImage bi = new BufferedImage(15, 15, 241 BufferedImage.TYPE_INT_ARGB); 242 Graphics2D big = bi.createGraphics(); 243 big.setColor(getBackgroundColor()); 244 Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 245 0.3f); 246 big.setComposite(comp); 247 big.fillRect(0, 0, 15, 15); 248 big.setColor(getOutsideColor()); 249 big.drawLine(0, 15, 15, 0); 250 Rectangle r = new Rectangle(0, 0, 15, 15); 251 hatched = new TexturePaint(bi, r); 252 } 253 254 /** 255 * Paints the database in the map. 256 */ 257 @Override 258 public synchronized void paint(Graphics2D g, MapView mv, Bounds box) { 259 if (Main.map.mapView.getActiveLayer() == this) { 260 Rectangle b = mv.getBounds(); 261 // on some platforms viewport bounds seem to be offset from the 262 // left, 263 // over-grow it just to be sure 264 b.grow(100, 100); 265 Area a = new Area(b); 266 // now successively subtract downloaded areas 267 for (Bounds bounds : this.bounds) { 268 Point p1 = mv.getPoint(bounds.getMin()); 269 Point p2 = mv.getPoint(bounds.getMax()); 270 Rectangle r = new Rectangle(Math.min(p1.x, p2.x), Math.min( 271 p1.y, p2.y), Math.abs(p2.x - p1.x), Math.abs(p2.y 272 - p1.y)); 273 a.subtract(new Area(r)); 274 } 275 // paint remainder 276 g.setPaint(hatched); 277 g.fill(a); 278 } 279 280 // Draw colored lines 281 MapillaryLayer.BLUE = null; 282 MapillaryLayer.RED = null; 283 MapillaryMainDialog.getInstance().blueButton.setEnabled(false); 284 MapillaryMainDialog.getInstance().redButton.setEnabled(false); 285 286 // Sets blue and red lines and enables/disables the buttons 287 if (data.getSelectedImage() != null) { 288 MapillaryImage[] closestImages = getClosestImagesFromDifferentSequences(); 289 Point selected = mv.getPoint(data.getSelectedImage().getLatLon()); 290 if (closestImages[0] != null) { 291 MapillaryLayer.BLUE = closestImages[0]; 292 g.setColor(Color.BLUE); 293 g.drawLine(mv.getPoint(closestImages[0].getLatLon()).x, 294 mv.getPoint(closestImages[0].getLatLon()).y, 295 selected.x, selected.y); 296 MapillaryMainDialog.getInstance().blueButton.setEnabled(true); 297 } 298 if (closestImages[1] != null) { 299 MapillaryLayer.RED = closestImages[1]; 300 g.setColor(Color.RED); 301 g.drawLine(mv.getPoint(closestImages[1].getLatLon()).x, 302 mv.getPoint(closestImages[1].getLatLon()).y, 303 selected.x, selected.y); 304 MapillaryMainDialog.getInstance().redButton.setEnabled(true); 305 } 306 } 307 g.setColor(Color.WHITE); 308 for (MapillaryAbstractImage imageAbs : data.getImages()) { 309 if (!imageAbs.isVisible()) 310 continue; 311 Point p = mv.getPoint(imageAbs.getLatLon()); 312 if (imageAbs instanceof MapillaryImage) { 313 MapillaryImage image = (MapillaryImage) imageAbs; 314 Point nextp = null; 315 // Draw sequence line 316 if (image.getSequence() != null) { 317 MapillaryImage tempImage = image.next(); 318 while (tempImage != null) { 319 if (tempImage.isVisible()) { 320 nextp = mv.getPoint(tempImage.getLatLon()); 321 break; 322 } 323 tempImage = tempImage.next(); 324 } 325 if (nextp != null) 326 g.drawLine(p.x, p.y, nextp.x, nextp.y); 327 } 328 329 ImageIcon icon; 330 if (!data.getMultiSelectedImages().contains(image)) 331 icon = MapillaryPlugin.MAP_ICON; 332 else 333 icon = MapillaryPlugin.MAP_ICON_SELECTED; 334 draw(g, image, icon, p); 335 if (!image.getSigns().isEmpty()) { 336 g.drawImage(MapillaryPlugin.MAP_SIGN.getImage(), 337 p.x + icon.getIconWidth() / 2, 338 p.y - icon.getIconHeight() / 2, Main.map.mapView); 339 } 340 } else if (imageAbs instanceof MapillaryImportedImage) { 341 MapillaryImportedImage image = (MapillaryImportedImage) imageAbs; 342 ImageIcon icon; 343 if (!data.getMultiSelectedImages().contains(image)) 344 icon = MapillaryPlugin.MAP_ICON_IMPORTED; 345 else 346 icon = MapillaryPlugin.MAP_ICON_SELECTED; 347 draw(g, image, icon, p); 348 } 349 } 350 } 351 352 /** 353 * Draws the highlight of the icon. 354 * 355 * @param g 356 * @param p 357 * @param size 358 */ 359 private void drawPointHighlight(Graphics2D g, Point p, int size) { 360 Color oldColor = g.getColor(); 361 Color highlightColor = PaintColors.HIGHLIGHT.get(); 362 Color highlightColorTransparent = new Color(highlightColor.getRed(), 363 highlightColor.getGreen(), highlightColor.getBlue(), 100); 364 g.setColor(highlightColorTransparent); 365 int s = size + highlightPointRadius; 366 while (s >= size) { 367 int r = (int) Math.floor(s / 2d); 368 g.fillRoundRect(p.x - r, p.y - r, s, s, r, r); 369 s -= highlightStep; 370 } 371 g.setColor(oldColor); 372 } 373 374 /** 375 * Draws the given icon of an image. Also checks if the mouse is over the 376 * image. 377 * 378 * @param g 379 * @param image 380 * @param icon 381 * @param p 382 */ 383 private void draw(Graphics2D g, MapillaryAbstractImage image, 384 ImageIcon icon, Point p) { 385 Image imagetemp = icon.getImage(); 386 BufferedImage bi = (BufferedImage) imagetemp; 387 int width = icon.getIconWidth(); 388 int height = icon.getIconHeight(); 389 390 // Rotate the image 391 double rotationRequired = Math.toRadians(image.getCa()); 392 double locationX = width / 2; 393 double locationY = height / 2; 394 AffineTransform tx = AffineTransform.getRotateInstance( 395 rotationRequired, locationX, locationY); 396 AffineTransformOp op = new AffineTransformOp(tx, 397 AffineTransformOp.TYPE_BILINEAR); 398 399 g.drawImage(op.filter(bi, null), p.x - (width / 2), p.y - (height / 2), 400 Main.map.mapView); 401 if (data.getHoveredImage() == image) { 402 drawPointHighlight(g, p, 16); 403 } 404 } 405 406 @Override 407 public Icon getIcon() { 408 return MapillaryPlugin.ICON16; 409 } 410 411 @Override 412 public boolean isMergable(Layer other) { 413 return false; 414 } 415 416 @Override 417 public void mergeFrom(Layer from) { 418 throw new UnsupportedOperationException( 419 "This layer does not support merging yet"); 420 } 421 422 @Override 423 public Action[] getMenuEntries() { 424 List<Action> actions = new ArrayList<>(); 425 actions.add(LayerListDialog.getInstance().createShowHideLayerAction()); 426 actions.add(LayerListDialog.getInstance().createDeleteLayerAction()); 427 actions.add(new LayerListPopup.InfoAction(this)); 428 return actions.toArray(new Action[actions.size()]); 429 } 430 431 /** 432 * Returns the 2 closest images belonging to a different sequence. 433 * 434 * @return 435 */ 436 private MapillaryImage[] getClosestImagesFromDifferentSequences() { 437 if (!(data.getSelectedImage() instanceof MapillaryImage)) 438 return new MapillaryImage[2]; 439 MapillaryImage selected = (MapillaryImage) data.getSelectedImage(); 440 MapillaryImage[] ret = new MapillaryImage[2]; 441 double[] distances = { SEQUENCE_MAX_JUMP_DISTANCE, 442 SEQUENCE_MAX_JUMP_DISTANCE }; 443 LatLon selectedCoords = data.getSelectedImage().getLatLon(); 444 for (MapillaryAbstractImage imagePrev : data.getImages()) { 445 if (!(imagePrev instanceof MapillaryImage)) 446 continue; 447 if (!imagePrev.isVisible()) 448 continue; 449 MapillaryImage image = (MapillaryImage) imagePrev; 450 if (image.getLatLon().greatCircleDistance(selectedCoords) < SEQUENCE_MAX_JUMP_DISTANCE 451 && selected.getSequence() != image.getSequence()) { 452 if ((ret[0] == null && ret[1] == null) 453 || (image.getLatLon().greatCircleDistance( 454 selectedCoords) < distances[0] && (ret[1] == null || image 455 .getSequence() != ret[1].getSequence()))) { 456 ret[0] = image; 457 distances[0] = image.getLatLon().greatCircleDistance( 458 selectedCoords); 459 } else if ((ret[1] == null || image.getLatLon() 460 .greatCircleDistance(selectedCoords) < distances[1]) 461 && image.getSequence() != ret[0].getSequence()) { 462 ret[1] = image; 463 distances[1] = image.getLatLon().greatCircleDistance( 464 selectedCoords); 465 } 466 } 467 } 468 // Predownloads the thumbnails 469 if (ret[0] != null) 470 new MapillaryCache(ret[0].getKey(), MapillaryCache.Type.THUMBNAIL) 471 .submit(data, false); 472 if (ret[1] != null) 473 new MapillaryCache(ret[1].getKey(), MapillaryCache.Type.THUMBNAIL) 474 .submit(data, false); 475 return ret; 476 } 477 478 @Override 479 public Object getInfoComponent() { 480 StringBuilder sb = new StringBuilder(); 481 sb.append(tr("Mapillary layer")); 482 sb.append("\n"); 483 sb.append(tr("Total images:")); 484 sb.append(" "); 485 sb.append(data.size()); 486 sb.append("\n"); 487 return sb.toString(); 488 } 489 490 @Override 491 public String getToolTipText() { 492 return data.size() + " " + tr("images"); 493 } 494 495 // EditDataLayerChanged 496 @Override 497 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) { 498 if (oldLayer == null && newLayer != null) { 499 newLayer.data.addDataSetListener(this); 500 501 } else if (oldLayer != null && newLayer == null) { 502 oldLayer.data.removeDataSetListener(this); 503 } 504 } 505 506 /** 507 * When more data is downloaded, a delayed update is thrown, in order to 508 * wait for the data bounds to be set. 509 * 510 * @param event 511 */ 512 @Override 513 public void dataChanged(DataChangedEvent event) { 514 Main.worker.submit(new delayedDownload()); 515 } 516 517 private class delayedDownload extends Thread { 518 519 @Override 520 public void run() { 521 try { 522 sleep(1000); 523 } catch (InterruptedException e) { 524 Main.error(e); 525 } 526 MapillaryLayer.getInstance().download(); 527 } 528 } 529 530 @Override 531 public void primitivesAdded(PrimitivesAddedEvent event) { 532 } 533 534 @Override 535 public void primitivesRemoved(PrimitivesRemovedEvent event) { 536 } 537 538 @Override 539 public void tagsChanged(TagsChangedEvent event) { 540 } 541 542 @Override 543 public void nodeMoved(NodeMovedEvent event) { 544 } 545 546 @Override 547 public void wayNodesChanged(WayNodesChangedEvent event) { 548 } 549 550 @Override 551 public void relationMembersChanged(RelationMembersChangedEvent event) { 552 } 553 554 @Override 555 public void otherDatasetChange(AbstractDatasetChangedEvent event) { 556 } 557 558 @Override 559 public void visitBoundingBox(BoundingXYVisitor v) { 560 } 561 562 @Override 563 public void activeLayerChange(Layer oldLayer, Layer newLayer) { 564 if (newLayer == this) { 565 if (data.size() > 0) 566 Main.map.statusLine.setHelpText(tr("Total images: {0}", 567 data.size())); 568 else 569 Main.map.statusLine.setHelpText(tr("No images found")); 570 } 571 } 572 573 @Override 574 public void layerAdded(Layer newLayer) { 575 } 576 577 @Override 578 public void layerRemoved(Layer oldLayer) { 579 } 509 public void run() { 510 try { 511 sleep(1000); 512 } catch (InterruptedException e) { 513 Main.error(e); 514 } 515 MapillaryLayer.getInstance().download(); 516 } 517 } 518 519 @Override 520 public void primitivesAdded(PrimitivesAddedEvent event) { 521 } 522 523 @Override 524 public void primitivesRemoved(PrimitivesRemovedEvent event) { 525 } 526 527 @Override 528 public void tagsChanged(TagsChangedEvent event) { 529 } 530 531 @Override 532 public void nodeMoved(NodeMovedEvent event) { 533 } 534 535 @Override 536 public void wayNodesChanged(WayNodesChangedEvent event) { 537 } 538 539 @Override 540 public void relationMembersChanged(RelationMembersChangedEvent event) { 541 } 542 543 @Override 544 public void otherDatasetChange(AbstractDatasetChangedEvent event) { 545 } 546 547 @Override 548 public void visitBoundingBox(BoundingXYVisitor v) { 549 } 550 551 @Override 552 public void activeLayerChange(Layer oldLayer, Layer newLayer) { 553 if (newLayer == this) { 554 if (data.size() > 0) 555 Main.map.statusLine.setHelpText(tr("Total images: {0}", data.size())); 556 else 557 Main.map.statusLine.setHelpText(tr("No images found")); 558 } 559 } 560 561 @Override 562 public void layerAdded(Layer newLayer) { 563 } 564 565 @Override 566 public void layerRemoved(Layer oldLayer) { 567 } 580 568 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryMouseAdapter.java
r31333 r31350 22 22 */ 23 23 public class MapillaryMouseAdapter extends MouseAdapter { 24 private Point start; 25 private int lastButton; 26 private MapillaryAbstractImage closest; 27 private MapillaryAbstractImage lastClicked; 28 private MapillaryData mapillaryData; 29 private MapillaryRecord record; 30 31 private boolean nothingHighlighted; 32 private boolean imageHighlighted = false; 33 34 public MapillaryMouseAdapter() { 35 mapillaryData = MapillaryData.getInstance(); 36 record = MapillaryRecord.getInstance(); 37 } 38 39 @Override 40 public void mousePressed(MouseEvent e) { 41 lastButton = e.getButton(); 42 if (e.getButton() != MouseEvent.BUTTON1) 43 return; 44 MapillaryAbstractImage closestTemp = getClosest(e.getPoint()); 45 if (Main.map.mapView.getActiveLayer() instanceof OsmDataLayer 46 && closestTemp != null 47 && Main.map.mapMode == Main.map.mapModeSelect) { 48 this.lastClicked = this.closest; 49 MapillaryData.getInstance().setSelectedImage(closestTemp); 50 return; 51 } else if (Main.map.mapView.getActiveLayer() != MapillaryLayer 52 .getInstance()) 53 return; 54 if (closestTemp instanceof MapillaryImage || closestTemp == null) { 55 MapillaryImage closest = (MapillaryImage) closestTemp; 56 // Doube click 57 if (e.getClickCount() == 2 58 && mapillaryData.getSelectedImage() != null 59 && closest != null) { 60 for (MapillaryAbstractImage img : closest.getSequence() 61 .getImages()) { 62 mapillaryData.addMultiSelectedImage(img); 63 } 64 } 65 this.start = e.getPoint(); 66 this.lastClicked = this.closest; 67 this.closest = closest; 68 if (mapillaryData.getMultiSelectedImages().contains(closest)) 69 return; 70 // ctrl+click 71 if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.CTRL_MASK) 72 && closest != null) 73 mapillaryData.addMultiSelectedImage(closest); 74 // shift + click 75 else if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.SHIFT_MASK) 76 && this.closest instanceof MapillaryImage 77 && this.lastClicked instanceof MapillaryImage) { 78 if (this.closest != null 79 && this.lastClicked != null 80 && ((MapillaryImage) this.closest).getSequence() == ((MapillaryImage) this.lastClicked) 81 .getSequence()) { 82 int i = ((MapillaryImage) this.closest).getSequence() 83 .getImages().indexOf(this.closest); 84 int j = ((MapillaryImage) this.lastClicked).getSequence() 85 .getImages().indexOf(this.lastClicked); 86 if (i < j) 87 mapillaryData 88 .addMultiSelectedImage(new ArrayList<MapillaryAbstractImage>( 89 ((MapillaryImage) this.closest) 90 .getSequence().getImages() 91 .subList(i, j + 1))); 92 else 93 mapillaryData 94 .addMultiSelectedImage(new ArrayList<MapillaryAbstractImage>( 95 ((MapillaryImage) this.closest) 96 .getSequence().getImages() 97 .subList(j, i + 1))); 98 } 99 // click 100 } else 101 mapillaryData.setSelectedImage(closest); 102 // If you select an imported image 103 } else if (closestTemp instanceof MapillaryImportedImage) { 104 MapillaryImportedImage closest = (MapillaryImportedImage) closestTemp; 105 this.start = e.getPoint(); 106 this.lastClicked = this.closest; 107 this.closest = closest; 108 if (mapillaryData.getMultiSelectedImages().contains(closest)) 109 return; 110 if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.CTRL_MASK) 111 && closest != null) 112 mapillaryData.addMultiSelectedImage(closest); 113 else 114 mapillaryData.setSelectedImage(closest); 115 } 116 } 117 118 private MapillaryAbstractImage getClosest(Point clickPoint) { 119 double snapDistance = 10; 120 double minDistance = Double.MAX_VALUE; 121 MapillaryAbstractImage closest = null; 122 for (MapillaryAbstractImage image : mapillaryData.getImages()) { 123 Point imagePoint = Main.map.mapView.getPoint(image.getLatLon()); 124 imagePoint.setLocation(imagePoint.getX(), imagePoint.getY()); 125 double dist = clickPoint.distanceSq(imagePoint); 126 if (minDistance > dist 127 && clickPoint.distance(imagePoint) < snapDistance 128 && image.isVisible()) { 129 minDistance = dist; 130 closest = image; 131 } 132 } 133 return closest; 134 } 135 136 @Override 137 public void mouseDragged(MouseEvent e) { 138 if (Main.map.mapView.getActiveLayer() != MapillaryLayer.getInstance()) 139 return; 140 141 if (!Main.pref.getBoolean("mapillary.developer")) 142 for (MapillaryAbstractImage img : MapillaryData.getInstance() 143 .getMultiSelectedImages()) { 144 if (img instanceof MapillaryImage) 145 return; 146 } 147 if (MapillaryData.getInstance().getSelectedImage() != null) { 148 if (lastButton == MouseEvent.BUTTON1 && !e.isShiftDown()) { 149 LatLon to = Main.map.mapView.getLatLon(e.getX(), e.getY()); 150 LatLon from = Main.map.mapView.getLatLon(start.getX(), 151 start.getY()); 152 for (MapillaryAbstractImage img : MapillaryData.getInstance() 153 .getMultiSelectedImages()) { 154 155 img.move(to.getX() - from.getX(), to.getY() - from.getY()); 156 } 157 Main.map.repaint(); 158 } else if (lastButton == MouseEvent.BUTTON1 && e.isShiftDown()) { 159 this.closest.turn(Math.toDegrees(Math.atan2( 160 (e.getX() - start.x), -(e.getY() - start.y))) 161 - closest.getTempCa()); 162 for (MapillaryAbstractImage img : MapillaryData.getInstance() 163 .getMultiSelectedImages()) { 164 img.turn(Math.toDegrees(Math.atan2((e.getX() - start.x), 165 -(e.getY() - start.y))) - closest.getTempCa()); 166 } 167 Main.map.repaint(); 168 } 169 } 170 } 171 172 @Override 173 public void mouseReleased(MouseEvent e) { 174 if (mapillaryData.getSelectedImage() == null) 175 return; 176 if (mapillaryData.getSelectedImage().getTempCa() != mapillaryData 177 .getSelectedImage().getCa()) { 178 double from = mapillaryData.getSelectedImage().getTempCa(); 179 double to = mapillaryData.getSelectedImage().getCa(); 180 record.addCommand(new CommandTurnImage(mapillaryData 181 .getMultiSelectedImages(), to - from)); 182 } else if (mapillaryData.getSelectedImage().getTempLatLon() != mapillaryData 183 .getSelectedImage().getLatLon()) { 184 LatLon from = mapillaryData.getSelectedImage().getTempLatLon(); 185 LatLon to = mapillaryData.getSelectedImage().getLatLon(); 186 record.addCommand(new CommandMoveImage(mapillaryData 187 .getMultiSelectedImages(), to.getX() - from.getX(), to 188 .getY() - from.getY())); 189 } 190 for (MapillaryAbstractImage img : mapillaryData 191 .getMultiSelectedImages()) { 192 if (img != null) 193 img.stopMoving(); 194 } 195 } 196 197 /** 198 * Checks if the mouse is over pictures. 199 */ 200 @Override 201 public void mouseMoved(MouseEvent e) { 202 MapillaryAbstractImage closestTemp = getClosest(e.getPoint()); 203 if (Main.map.mapView.getActiveLayer() instanceof OsmDataLayer 204 && Main.map.mapMode != Main.map.mapModeSelect) 205 return; 206 if (closestTemp != null 207 && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer 208 && !imageHighlighted) { 209 Main.map.mapMode.putValue("active", Boolean.FALSE); 210 imageHighlighted = true; 211 212 } else if (closestTemp == null 213 && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer 214 && imageHighlighted && nothingHighlighted) { 215 nothingHighlighted = false; 216 Main.map.mapMode.putValue("active", Boolean.TRUE); 217 218 } else if (imageHighlighted && !nothingHighlighted 219 && Main.map.mapView != null 220 && Main.map.mapView.getEditLayer().data != null 221 && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer) { 222 223 for (OsmPrimitive primivitive : Main.map.mapView.getEditLayer().data 224 .allPrimitives()) { 225 primivitive.setHighlighted(false); 226 } 227 imageHighlighted = false; 228 nothingHighlighted = true; 229 } 230 231 if (MapillaryData.getInstance().getHoveredImage() != closestTemp 232 && closestTemp != null) { 233 MapillaryData.getInstance().setHighlightedImage(closestTemp); 234 MapillaryMainDialog.getInstance().setImage(closestTemp); 235 MapillaryMainDialog.getInstance().updateImage(); 236 } else if (MapillaryData.getInstance().getHoveredImage() != closestTemp 237 && closestTemp == null) { 238 MapillaryData.getInstance().setHighlightedImage(null); 239 MapillaryMainDialog.getInstance().setImage( 240 MapillaryData.getInstance().getSelectedImage()); 241 MapillaryMainDialog.getInstance().updateImage(); 242 } 243 MapillaryData.getInstance().dataUpdated(); 244 } 24 private Point start; 25 private int lastButton; 26 private MapillaryAbstractImage closest; 27 private MapillaryAbstractImage lastClicked; 28 private MapillaryData mapillaryData; 29 private MapillaryRecord record; 30 31 private boolean nothingHighlighted; 32 private boolean imageHighlighted = false; 33 34 public MapillaryMouseAdapter() { 35 mapillaryData = MapillaryData.getInstance(); 36 record = MapillaryRecord.getInstance(); 37 } 38 39 @Override 40 public void mousePressed(MouseEvent e) { 41 lastButton = e.getButton(); 42 if (e.getButton() != MouseEvent.BUTTON1) 43 return; 44 MapillaryAbstractImage closestTemp = getClosest(e.getPoint()); 45 if (Main.map.mapView.getActiveLayer() instanceof OsmDataLayer 46 && closestTemp != null && Main.map.mapMode == Main.map.mapModeSelect) { 47 this.lastClicked = this.closest; 48 MapillaryData.getInstance().setSelectedImage(closestTemp); 49 return; 50 } else if (Main.map.mapView.getActiveLayer() != MapillaryLayer 51 .getInstance()) 52 return; 53 if (closestTemp instanceof MapillaryImage || closestTemp == null) { 54 MapillaryImage closest = (MapillaryImage) closestTemp; 55 // Doube click 56 if (e.getClickCount() == 2 && mapillaryData.getSelectedImage() != null 57 && closest != null) { 58 for (MapillaryAbstractImage img : closest.getSequence().getImages()) { 59 mapillaryData.addMultiSelectedImage(img); 60 } 61 } 62 this.start = e.getPoint(); 63 this.lastClicked = this.closest; 64 this.closest = closest; 65 if (mapillaryData.getMultiSelectedImages().contains(closest)) 66 return; 67 // ctrl+click 68 if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.CTRL_MASK) 69 && closest != null) 70 mapillaryData.addMultiSelectedImage(closest); 71 // shift + click 72 else if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.SHIFT_MASK) 73 && this.closest instanceof MapillaryImage 74 && this.lastClicked instanceof MapillaryImage) { 75 if (this.closest != null 76 && this.lastClicked != null 77 && ((MapillaryImage) this.closest).getSequence() == ((MapillaryImage) this.lastClicked) 78 .getSequence()) { 79 int i = ((MapillaryImage) this.closest).getSequence().getImages() 80 .indexOf(this.closest); 81 int j = ((MapillaryImage) this.lastClicked).getSequence().getImages() 82 .indexOf(this.lastClicked); 83 if (i < j) 84 mapillaryData 85 .addMultiSelectedImage(new ArrayList<MapillaryAbstractImage>( 86 ((MapillaryImage) this.closest).getSequence().getImages() 87 .subList(i, j + 1))); 88 else 89 mapillaryData 90 .addMultiSelectedImage(new ArrayList<MapillaryAbstractImage>( 91 ((MapillaryImage) this.closest).getSequence().getImages() 92 .subList(j, i + 1))); 93 } 94 // click 95 } else 96 mapillaryData.setSelectedImage(closest); 97 // If you select an imported image 98 } else if (closestTemp instanceof MapillaryImportedImage) { 99 MapillaryImportedImage closest = (MapillaryImportedImage) closestTemp; 100 this.start = e.getPoint(); 101 this.lastClicked = this.closest; 102 this.closest = closest; 103 if (mapillaryData.getMultiSelectedImages().contains(closest)) 104 return; 105 if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.CTRL_MASK) 106 && closest != null) 107 mapillaryData.addMultiSelectedImage(closest); 108 else 109 mapillaryData.setSelectedImage(closest); 110 } 111 } 112 113 private MapillaryAbstractImage getClosest(Point clickPoint) { 114 double snapDistance = 10; 115 double minDistance = Double.MAX_VALUE; 116 MapillaryAbstractImage closest = null; 117 for (MapillaryAbstractImage image : mapillaryData.getImages()) { 118 Point imagePoint = Main.map.mapView.getPoint(image.getLatLon()); 119 imagePoint.setLocation(imagePoint.getX(), imagePoint.getY()); 120 double dist = clickPoint.distanceSq(imagePoint); 121 if (minDistance > dist && clickPoint.distance(imagePoint) < snapDistance 122 && image.isVisible()) { 123 minDistance = dist; 124 closest = image; 125 } 126 } 127 return closest; 128 } 129 130 @Override 131 public void mouseDragged(MouseEvent e) { 132 if (Main.map.mapView.getActiveLayer() != MapillaryLayer.getInstance()) 133 return; 134 135 if (!Main.pref.getBoolean("mapillary.developer")) 136 for (MapillaryAbstractImage img : MapillaryData.getInstance() 137 .getMultiSelectedImages()) { 138 if (img instanceof MapillaryImage) 139 return; 140 } 141 if (MapillaryData.getInstance().getSelectedImage() != null) { 142 if (lastButton == MouseEvent.BUTTON1 && !e.isShiftDown()) { 143 LatLon to = Main.map.mapView.getLatLon(e.getX(), e.getY()); 144 LatLon from = Main.map.mapView.getLatLon(start.getX(), start.getY()); 145 for (MapillaryAbstractImage img : MapillaryData.getInstance() 146 .getMultiSelectedImages()) { 147 148 img.move(to.getX() - from.getX(), to.getY() - from.getY()); 149 } 150 Main.map.repaint(); 151 } else if (lastButton == MouseEvent.BUTTON1 && e.isShiftDown()) { 152 this.closest.turn(Math.toDegrees(Math.atan2((e.getX() - start.x), 153 -(e.getY() - start.y))) 154 - closest.getTempCa()); 155 for (MapillaryAbstractImage img : MapillaryData.getInstance() 156 .getMultiSelectedImages()) { 157 img.turn(Math.toDegrees(Math.atan2((e.getX() - start.x), 158 -(e.getY() - start.y))) - closest.getTempCa()); 159 } 160 Main.map.repaint(); 161 } 162 } 163 } 164 165 @Override 166 public void mouseReleased(MouseEvent e) { 167 if (mapillaryData.getSelectedImage() == null) 168 return; 169 if (mapillaryData.getSelectedImage().getTempCa() != mapillaryData 170 .getSelectedImage().getCa()) { 171 double from = mapillaryData.getSelectedImage().getTempCa(); 172 double to = mapillaryData.getSelectedImage().getCa(); 173 record.addCommand(new CommandTurnImage(mapillaryData 174 .getMultiSelectedImages(), to - from)); 175 } else if (mapillaryData.getSelectedImage().getTempLatLon() != mapillaryData 176 .getSelectedImage().getLatLon()) { 177 LatLon from = mapillaryData.getSelectedImage().getTempLatLon(); 178 LatLon to = mapillaryData.getSelectedImage().getLatLon(); 179 record.addCommand(new CommandMoveImage(mapillaryData 180 .getMultiSelectedImages(), to.getX() - from.getX(), to.getY() 181 - from.getY())); 182 } 183 for (MapillaryAbstractImage img : mapillaryData.getMultiSelectedImages()) { 184 if (img != null) 185 img.stopMoving(); 186 } 187 } 188 189 /** 190 * Checks if the mouse is over pictures. 191 */ 192 @Override 193 public void mouseMoved(MouseEvent e) { 194 MapillaryAbstractImage closestTemp = getClosest(e.getPoint()); 195 if (Main.map.mapView.getActiveLayer() instanceof OsmDataLayer 196 && Main.map.mapMode != Main.map.mapModeSelect) 197 return; 198 if (closestTemp != null 199 && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer 200 && !imageHighlighted) { 201 Main.map.mapMode.putValue("active", Boolean.FALSE); 202 imageHighlighted = true; 203 204 } else if (closestTemp == null 205 && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer 206 && imageHighlighted && nothingHighlighted) { 207 nothingHighlighted = false; 208 Main.map.mapMode.putValue("active", Boolean.TRUE); 209 210 } else if (imageHighlighted && !nothingHighlighted 211 && Main.map.mapView != null 212 && Main.map.mapView.getEditLayer().data != null 213 && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer) { 214 215 for (OsmPrimitive primivitive : Main.map.mapView.getEditLayer().data 216 .allPrimitives()) { 217 primivitive.setHighlighted(false); 218 } 219 imageHighlighted = false; 220 nothingHighlighted = true; 221 } 222 223 if (MapillaryData.getInstance().getHoveredImage() != closestTemp 224 && closestTemp != null) { 225 MapillaryData.getInstance().setHighlightedImage(closestTemp); 226 MapillaryMainDialog.getInstance().setImage(closestTemp); 227 MapillaryMainDialog.getInstance().updateImage(); 228 } else if (MapillaryData.getInstance().getHoveredImage() != closestTemp 229 && closestTemp == null) { 230 MapillaryData.getInstance().setHighlightedImage(null); 231 MapillaryMainDialog.getInstance().setImage( 232 MapillaryData.getInstance().getSelectedImage()); 233 MapillaryMainDialog.getInstance().updateImage(); 234 } 235 MapillaryData.getInstance().dataUpdated(); 236 } 245 237 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java
r31347 r31350 33 33 public class MapillaryPlugin extends Plugin implements EditLayerChangeListener { 34 34 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; 35 public static final ImageIcon ICON24 = new ImageProvider("icon24.png").get(); 36 public static final ImageIcon ICON16 = new ImageProvider("icon16.png").get(); 37 public static final ImageIcon MAP_ICON = new ImageProvider("mapicon.png") 38 .get(); 39 public static final ImageIcon MAP_ICON_SELECTED = new ImageProvider( 40 "mapiconselected.png").get(); 41 public static final ImageIcon MAP_ICON_IMPORTED = new ImageProvider( 42 "mapiconimported.png").get(); 43 public static final ImageIcon MAP_SIGN = new ImageProvider("sign.png").get(); 44 public static final int ICON_SIZE = 24; 48 45 49 46 public static CacheAccess<String, BufferedImageCacheEntry> CACHE; 50 47 51 52 53 54 55 48 private final MapillaryDownloadAction downloadAction; 49 private final MapillaryExportAction exportAction; 50 private final MapillaryImportAction importAction; 51 private final MapillaryZoomAction zoomAction; 52 private final MapillaryDownloadViewAction downloadViewAction; 56 53 57 58 59 60 61 54 public static JMenuItem DOWNLOAD_MENU; 55 public static JMenuItem EXPORT_MENU; 56 public static JMenuItem IMPORT_MENU; 57 public static JMenuItem ZOOM_MENU; 58 public static JMenuItem DOWNLOAD_VIEW_MENU; 62 59 63 64 65 66 67 68 69 60 public MapillaryPlugin(PluginInformation info) { 61 super(info); 62 downloadAction = new MapillaryDownloadAction(); 63 exportAction = new MapillaryExportAction(); 64 importAction = new MapillaryImportAction(); 65 zoomAction = new MapillaryZoomAction(); 66 downloadViewAction = new MapillaryDownloadViewAction(); 70 67 71 if (Main.main != null) { // important for headless mode 72 DOWNLOAD_MENU = MainMenu.add(Main.main.menu.imageryMenu, 73 downloadAction, false); 74 EXPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, exportAction, 75 false, 14); 76 IMPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, importAction, 77 false, 14); 78 ZOOM_MENU = MainMenu 79 .add(Main.main.menu.viewMenu, zoomAction, false, 15); 80 DOWNLOAD_VIEW_MENU = MainMenu.add(Main.main.menu.fileMenu, 81 downloadViewAction, false, 14); 82 } 83 84 EXPORT_MENU.setEnabled(false); 85 DOWNLOAD_MENU.setEnabled(false); 86 IMPORT_MENU.setEnabled(false); 87 ZOOM_MENU.setEnabled(false); 88 DOWNLOAD_VIEW_MENU.setEnabled(false); 89 90 MapView.addEditLayerChangeListener(this); 91 try { 92 CACHE = JCSCacheManager.getCache("mapillary", 10, 10000, 93 this.getPluginDir() + "/cache/"); 94 } catch (IOException e) { 95 Main.error(e); 96 } 68 if (Main.main != null) { // important for headless mode 69 DOWNLOAD_MENU = MainMenu.add(Main.main.menu.imageryMenu, downloadAction, 70 false); 71 EXPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, exportAction, false, 72 14); 73 IMPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, importAction, false, 74 14); 75 ZOOM_MENU = MainMenu.add(Main.main.menu.viewMenu, zoomAction, false, 15); 76 DOWNLOAD_VIEW_MENU = MainMenu.add(Main.main.menu.fileMenu, 77 downloadViewAction, false, 14); 97 78 } 98 79 99 /** 100 * Called when the JOSM map frame is created or destroyed. 101 */ 102 @Override 103 public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { 104 if (oldFrame == null && newFrame != null) { // map frame added 105 Main.map.addToggleDialog(MapillaryMainDialog.getInstance(), false); 106 Main.map.addToggleDialog(MapillaryHistoryDialog.getInstance(), 107 false); 108 Main.map.addToggleDialog(MapillaryFilterDialog.getInstance(), false); 109 setMenuEnabled(DOWNLOAD_MENU, true); 110 if (Main.pref.getBoolean("mapillary.download-manually")) 111 setMenuEnabled(DOWNLOAD_VIEW_MENU, true); 112 setMenuEnabled(IMPORT_MENU, true); 113 } 114 if (oldFrame != null && newFrame == null) { // map frame destroyed 115 MapillaryMainDialog.destroyInstance(); 116 MapillaryHistoryDialog.destroyInstance(); 117 MapillaryFilterDialog.destroyInstance(); 118 setMenuEnabled(DOWNLOAD_MENU, false); 119 setMenuEnabled(DOWNLOAD_VIEW_MENU, false); 120 setMenuEnabled(IMPORT_MENU, false); 121 } 80 EXPORT_MENU.setEnabled(false); 81 DOWNLOAD_MENU.setEnabled(false); 82 IMPORT_MENU.setEnabled(false); 83 ZOOM_MENU.setEnabled(false); 84 DOWNLOAD_VIEW_MENU.setEnabled(false); 85 86 MapView.addEditLayerChangeListener(this); 87 try { 88 CACHE = JCSCacheManager.getCache("mapillary", 10, 10000, 89 this.getPluginDir() + "/cache/"); 90 } catch (IOException e) { 91 Main.error(e); 122 92 } 93 } 123 94 124 public static void setMenuEnabled(JMenuItem menu, boolean value) { 125 menu.setEnabled(value); 126 menu.getAction().setEnabled(value); 95 /** 96 * Called when the JOSM map frame is created or destroyed. 97 */ 98 @Override 99 public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { 100 if (oldFrame == null && newFrame != null) { // map frame added 101 Main.map.addToggleDialog(MapillaryMainDialog.getInstance(), false); 102 Main.map.addToggleDialog(MapillaryHistoryDialog.getInstance(), false); 103 Main.map.addToggleDialog(MapillaryFilterDialog.getInstance(), false); 104 setMenuEnabled(DOWNLOAD_MENU, true); 105 if (Main.pref.getBoolean("mapillary.download-manually")) 106 setMenuEnabled(DOWNLOAD_VIEW_MENU, true); 107 setMenuEnabled(IMPORT_MENU, true); 127 108 } 109 if (oldFrame != null && newFrame == null) { // map frame destroyed 110 MapillaryMainDialog.destroyInstance(); 111 MapillaryHistoryDialog.destroyInstance(); 112 MapillaryFilterDialog.destroyInstance(); 113 setMenuEnabled(DOWNLOAD_MENU, false); 114 setMenuEnabled(DOWNLOAD_VIEW_MENU, false); 115 setMenuEnabled(IMPORT_MENU, false); 116 } 117 } 128 118 129 @Override 130 public PreferenceSetting getPreferenceSetting() { 131 return new MapillaryPreferenceSetting(); 119 public static void setMenuEnabled(JMenuItem menu, boolean value) { 120 menu.setEnabled(value); 121 menu.getAction().setEnabled(value); 122 } 123 124 @Override 125 public PreferenceSetting getPreferenceSetting() { 126 return new MapillaryPreferenceSetting(); 127 } 128 129 @Override 130 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) { 131 if (oldLayer == null && newLayer != null) { 132 } else if (oldLayer != null && newLayer == null) { 132 133 } 133 134 @Override 135 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) { 136 if (oldLayer == null && newLayer != null) { 137 } else if (oldLayer != null && newLayer == null) { 138 } 139 } 134 } 140 135 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillarySequence.java
r31278 r31350 12 12 */ 13 13 public class MapillarySequence { 14 15 16 14 private final List<MapillaryImage> images; 15 private final String key; 16 private final long created_at; 17 17 18 19 20 21 22 18 public MapillarySequence(String key, long created_at) { 19 this.images = new ArrayList<>(); 20 this.key = key; 21 this.created_at = created_at; 22 } 23 23 24 25 26 27 28 29 30 31 24 /** 25 * Returns all MapillaryImages objects contained by this object. 26 * 27 * @return 28 */ 29 public List<MapillaryImage> getImages() { 30 return this.images; 31 } 32 32 33 34 35 33 public long getCreatedAt() { 34 return created_at; 35 } 36 36 37 38 39 40 41 42 43 44 37 /** 38 * Adds a new MapillaryImage object to this object. 39 * 40 * @param image 41 */ 42 public synchronized void add(MapillaryImage image) { 43 this.images.add(image); 44 } 45 45 46 47 48 46 public String getKey() { 47 return this.key; 48 } 49 49 50 51 52 53 54 55 56 57 58 50 /** 51 * Adds a set of MapillaryImage objects to this object. 52 * 53 * @param images 54 */ 55 public synchronized void add(List<MapillaryImage> images) { 56 for (MapillaryImage image : images) 57 add(image); 58 } 59 59 60 61 62 63 64 65 66 67 60 /** 61 * Removes a MapillaryImage object from this object. 62 * 63 * @param image 64 */ 65 public void remove(MapillaryImage image) { 66 this.images.remove(image); 67 } 68 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 69 /** 70 * Returns the next MapillaryImage in the sequence. 71 * 72 * @param image 73 * @return 74 */ 75 public MapillaryImage next(MapillaryImage image) { 76 if (!images.contains(image)) 77 throw new IllegalArgumentException(); 78 int i = images.indexOf(image); 79 if (i == images.size() - 1) 80 return null; 81 else 82 return images.get(i + 1); 83 } 84 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 85 /** 86 * Returns the previous MapillaryImage in the sequence. 87 * 88 * @param image 89 * @return 90 */ 91 public MapillaryImage previous(MapillaryImage image) { 92 if (!images.contains(image)) 93 throw new IllegalArgumentException(); 94 int i = images.indexOf(image); 95 if (i == 0) 96 return null; 97 else 98 return images.get(i - 1); 99 } 100 100 101 /** 102 * Returns the difference of index between two MapillaryImage objects 103 * belonging to the same MapillarySequence. 104 * 105 * @param image1 106 * @param image2 107 * @return 108 */ 109 public int getDistance(MapillaryImage image1, MapillaryImage image2) { 110 if (!this.images.contains(image1) || !this.images.contains(image2)) 111 throw new IllegalArgumentException(); 112 return Math.abs(this.images.indexOf(image1) 113 - this.images.indexOf(image2)); 114 } 101 /** 102 * Returns the difference of index between two MapillaryImage objects 103 * belonging to the same MapillarySequence. 104 * 105 * @param image1 106 * @param image2 107 * @return 108 */ 109 public int getDistance(MapillaryImage image1, MapillaryImage image2) { 110 if (!this.images.contains(image1) || !this.images.contains(image2)) 111 throw new IllegalArgumentException(); 112 return Math.abs(this.images.indexOf(image1) - this.images.indexOf(image2)); 113 } 115 114 116 117 118 119 120 121 115 @Override 116 public boolean equals(Object obj) { 117 if (obj instanceof MapillarySequence) 118 return this.getKey().equals(((MapillarySequence) obj).getKey()); 119 return false; 120 } 122 121 123 124 125 126 122 @Override 123 public int hashCode() { 124 return this.key.hashCode(); 125 } 127 126 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadAction.java
r31331 r31350 18 18 * Action that triggers the plugin. If in automatic mode, it will automatically 19 19 * download the images in the areas where there is OSM data. 20 * 20 * 21 21 * @author nokutu 22 22 * … … 24 24 public class MapillaryDownloadAction extends JosmAction { 25 25 26 public MapillaryDownloadAction() { 27 super(tr("Mapillary"), new ImageProvider("icon24.png"), 28 tr("Create Mapillary layer"), Shortcut.registerShortcut( 29 "Mapillary", tr("Start Mapillary layer"), 30 KeyEvent.VK_COMMA, Shortcut.SHIFT), false, 31 "mapillaryDownload", false); 32 this.setEnabled(false); 26 public MapillaryDownloadAction() { 27 super(tr("Mapillary"), new ImageProvider("icon24.png"), 28 tr("Create Mapillary layer"), Shortcut.registerShortcut("Mapillary", 29 tr("Start Mapillary layer"), KeyEvent.VK_COMMA, Shortcut.SHIFT), 30 false, "mapillaryDownload", false); 31 this.setEnabled(false); 32 } 33 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.getInstance()) 41 Main.map.mapView.setActiveLayer(MapillaryLayer.getInstance()); 42 else 43 Main.map.mapView.setActiveLayer(Main.map.mapView.getEditLayer()); 33 44 } 34 35 @Override 36 public void actionPerformed(ActionEvent arg0) { 37 if (MapillaryLayer.INSTANCE == null) { 38 if (Main.map.mapView.getEditLayer() != null) 39 MapillaryLayer.getInstance().download(); 40 } else { 41 if (Main.map.mapView.getActiveLayer() != MapillaryLayer 42 .getInstance()) 43 Main.map.mapView.setActiveLayer(MapillaryLayer.getInstance()); 44 else 45 Main.map.mapView 46 .setActiveLayer(Main.map.mapView.getEditLayer()); 47 } 48 } 45 } 49 46 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadViewAction.java
r31341 r31350 23 23 public class MapillaryDownloadViewAction extends JosmAction { 24 24 25 26 25 public static final double MAX_AREA = Main.pref.getDouble( 26 "mapillary.max-download-area", 0.020); 27 27 28 public MapillaryDownloadViewAction() { 29 super(tr("Download Mapillary images in current view"), 30 new ImageProvider("icon24.png"), 31 tr("Download Mapillary images in current view"), 32 Shortcut.registerShortcut("Mapillary area", 33 tr("Download Mapillary images in current view"), 34 KeyEvent.VK_PERIOD, Shortcut.SHIFT), false, 35 "mapillaryArea", false); 36 this.setEnabled(false); 28 public MapillaryDownloadViewAction() { 29 super(tr("Download Mapillary images in current view"), new ImageProvider( 30 "icon24.png"), tr("Download Mapillary images in current view"), 31 Shortcut.registerShortcut("Mapillary area", 32 tr("Download Mapillary images in current view"), 33 KeyEvent.VK_PERIOD, Shortcut.SHIFT), false, "mapillaryArea", false); 34 this.setEnabled(false); 35 } 36 37 @Override 38 public void actionPerformed(ActionEvent arg0) { 39 MapillaryLayer.getInstance().bounds.add(Main.map.mapView.getRealBounds()); 40 if (Main.map.mapView.getRealBounds().getArea() <= MAX_AREA) { 41 new MapillaryDownloader().getImages(Main.map.mapView.getRealBounds()); 42 } else { 43 JOptionPane.showMessageDialog(Main.parent, 44 tr("This area is too big to be downloaded")); 37 45 } 38 39 @Override 40 public void actionPerformed(ActionEvent arg0) { 41 MapillaryLayer.getInstance().bounds.add(Main.map.mapView 42 .getRealBounds()); 43 if (Main.map.mapView.getRealBounds().getArea() <= MAX_AREA) { 44 new MapillaryDownloader().getImages(Main.map.mapView 45 .getRealBounds()); 46 } else { 47 JOptionPane.showMessageDialog(Main.parent, 48 tr("This area is too big to be downloaded")); 49 } 50 } 46 } 51 47 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryExportAction.java
r31331 r31350 32 32 public class MapillaryExportAction extends JosmAction { 33 33 34 34 MapillaryExportDialog dialog; 35 35 36 public MapillaryExportAction() { 37 super(tr("Export pictures"), new ImageProvider("icon24.png"), 38 tr("Export pictures"), Shortcut.registerShortcut( 39 "Export Mapillary", tr("Export Mapillary pictures"), 40 KeyEvent.CHAR_UNDEFINED, Shortcut.NONE), false, 41 "mapillaryExport", false); 42 this.setEnabled(false); 36 public MapillaryExportAction() { 37 super(tr("Export pictures"), new ImageProvider("icon24.png"), 38 tr("Export pictures"), Shortcut.registerShortcut("Export Mapillary", 39 tr("Export Mapillary pictures"), KeyEvent.CHAR_UNDEFINED, 40 Shortcut.NONE), false, "mapillaryExport", false); 41 this.setEnabled(false); 42 } 43 44 @Override 45 public void actionPerformed(ActionEvent e) { 46 dialog = new MapillaryExportDialog(); 47 JOptionPane pane = new JOptionPane(dialog, JOptionPane.PLAIN_MESSAGE, 48 JOptionPane.OK_CANCEL_OPTION); 49 JDialog dlg = pane.createDialog(Main.parent, tr("Export images")); 50 dlg.setMinimumSize(new Dimension(400, 150)); 51 dlg.setVisible(true); 52 53 // Checks if the inputs are correct and starts the export process. 54 if (pane.getValue() != null 55 && (int) pane.getValue() == JOptionPane.OK_OPTION 56 && dialog.chooser != null) { 57 if (dialog.group.isSelected(dialog.all.getModel())) { 58 export(MapillaryData.getInstance().getImages()); 59 } else if (dialog.group.isSelected(dialog.sequence.getModel())) { 60 ArrayList<MapillaryAbstractImage> images = new ArrayList<>(); 61 for (MapillaryAbstractImage image : MapillaryData.getInstance() 62 .getMultiSelectedImages()) 63 if (image instanceof MapillaryImage) { 64 if (!images.contains(image)) 65 images.addAll(((MapillaryImage) image).getSequence().getImages()); 66 } else 67 images.add(image); 68 export(images); 69 } else if (dialog.group.isSelected(dialog.selected.getModel())) { 70 export(MapillaryData.getInstance().getMultiSelectedImages()); 71 } 72 // This option ignores the selected directory. 73 } else if (dialog.group.isSelected(dialog.rewrite.getModel())) { 74 ArrayList<MapillaryImportedImage> images = new ArrayList<>(); 75 for (MapillaryAbstractImage image : MapillaryData.getInstance() 76 .getImages()) 77 if (image instanceof MapillaryImportedImage) { 78 images.add(((MapillaryImportedImage) image)); 79 } 80 try { 81 Main.worker.submit(new Thread(new MapillaryExportManager(images))); 82 } catch (IOException e1) { 83 Main.error(e1); 84 } 43 85 } 86 dlg.dispose(); 87 } 44 88 45 @Override 46 public void actionPerformed(ActionEvent e) { 47 dialog = new MapillaryExportDialog(); 48 JOptionPane pane = new JOptionPane(dialog, JOptionPane.PLAIN_MESSAGE, 49 JOptionPane.OK_CANCEL_OPTION); 50 JDialog dlg = pane.createDialog(Main.parent, tr("Export images")); 51 dlg.setMinimumSize(new Dimension(400, 150)); 52 dlg.setVisible(true); 53 54 // Checks if the inputs are correct and starts the export process. 55 if (pane.getValue() != null 56 && (int) pane.getValue() == JOptionPane.OK_OPTION 57 && dialog.chooser != null) { 58 if (dialog.group.isSelected(dialog.all.getModel())) { 59 export(MapillaryData.getInstance().getImages()); 60 } else if (dialog.group.isSelected(dialog.sequence.getModel())) { 61 ArrayList<MapillaryAbstractImage> images = new ArrayList<>(); 62 for (MapillaryAbstractImage image : MapillaryData.getInstance() 63 .getMultiSelectedImages()) 64 if (image instanceof MapillaryImage) { 65 if (!images.contains(image)) 66 images.addAll(((MapillaryImage) image) 67 .getSequence().getImages()); 68 } else 69 images.add(image); 70 export(images); 71 } else if (dialog.group.isSelected(dialog.selected.getModel())) { 72 export(MapillaryData.getInstance().getMultiSelectedImages()); 73 } 74 // This option ignores the selected directory. 75 } else if (dialog.group.isSelected(dialog.rewrite.getModel())) { 76 ArrayList<MapillaryImportedImage> images = new ArrayList<>(); 77 for (MapillaryAbstractImage image : MapillaryData.getInstance() 78 .getImages()) 79 if (image instanceof MapillaryImportedImage) { 80 images.add(((MapillaryImportedImage) image)); 81 } 82 try { 83 Main.worker.submit(new Thread( 84 new MapillaryExportManager(images))); 85 } catch (IOException e1) { 86 Main.error(e1); 87 } 88 } 89 dlg.dispose(); 90 } 91 92 /** 93 * Exports the given images from the database. 94 */ 95 public void export(List<MapillaryAbstractImage> images) { 96 Main.worker.submit(new Thread(new MapillaryExportManager(images, 97 dialog.chooser.getSelectedFile().toString()))); 98 } 89 /** 90 * Exports the given images from the database. 91 */ 92 public void export(List<MapillaryAbstractImage> images) { 93 Main.worker.submit(new Thread(new MapillaryExportManager(images, 94 dialog.chooser.getSelectedFile().toString()))); 95 } 99 96 100 97 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryImportAction.java
r31328 r31350 30 30 /** 31 31 * Imports a set of picture files into JOSM. They must be in jpg or png format. 32 * 32 * 33 33 * @author nokutu 34 34 * … … 36 36 public class MapillaryImportAction extends JosmAction { 37 37 38 38 public JFileChooser chooser; 39 39 40 41 42 43 40 /** 41 * Amount of pictures without the proper EXIF tags. 42 */ 43 private int noTagsPics = 0; 44 44 45 public MapillaryImportAction() { 46 super(tr("Import pictures"), new ImageProvider("icon24.png"), 47 tr("Import local pictures"), Shortcut.registerShortcut( 48 "Import Mapillary", 49 tr("Import pictures into Mapillary layer"), 50 KeyEvent.CHAR_UNDEFINED, Shortcut.NONE), false, 51 "mapillaryImport", false); 52 this.setEnabled(false); 45 public MapillaryImportAction() { 46 super(tr("Import pictures"), new ImageProvider("icon24.png"), 47 tr("Import local pictures"), Shortcut.registerShortcut( 48 "Import Mapillary", tr("Import pictures into Mapillary layer"), 49 KeyEvent.CHAR_UNDEFINED, Shortcut.NONE), false, "mapillaryImport", 50 false); 51 this.setEnabled(false); 52 } 53 54 @Override 55 public void actionPerformed(ActionEvent e) { 56 chooser = new JFileChooser(); 57 chooser.setCurrentDirectory(new java.io.File(System 58 .getProperty("user.home"))); 59 chooser.setDialogTitle(tr("Select pictures")); 60 chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); 61 chooser.setAcceptAllFileFilterUsed(false); 62 chooser.addChoosableFileFilter(new FileNameExtensionFilter("images", "jpg", 63 "jpeg", "png")); 64 chooser.setMultiSelectionEnabled(true); 65 if (chooser.showOpenDialog(Main.parent) == JFileChooser.APPROVE_OPTION) { 66 for (int i = 0; i < chooser.getSelectedFiles().length; i++) { 67 File file = chooser.getSelectedFiles()[i]; 68 if (file.isDirectory()) { 69 70 } else { 71 MapillaryLayer.getInstance(); 72 if (file.getPath().substring(file.getPath().length() - 4) 73 .equals(".jpg") 74 || file.getPath().substring(file.getPath().length() - 5) 75 .equals(".jpeg")) { 76 try { 77 readJPG(file); 78 } catch (ImageReadException ex) { 79 Main.error(ex); 80 } catch (IOException ex) { 81 Main.error(ex); 82 } 83 } else if (file.getPath().substring(file.getPath().length() - 4) 84 .equals(".png")) { 85 readPNG(file); 86 } 87 } 88 } 53 89 } 90 } 54 91 55 @Override 56 public void actionPerformed(ActionEvent e) { 57 chooser = new JFileChooser(); 58 chooser.setCurrentDirectory(new java.io.File(System 59 .getProperty("user.home"))); 60 chooser.setDialogTitle(tr("Select pictures")); 61 chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); 62 chooser.setAcceptAllFileFilterUsed(false); 63 chooser.addChoosableFileFilter(new FileNameExtensionFilter("images", 64 "jpg", "jpeg", "png")); 65 chooser.setMultiSelectionEnabled(true); 66 if (chooser.showOpenDialog(Main.parent) == JFileChooser.APPROVE_OPTION) { 67 for (int i = 0; i < chooser.getSelectedFiles().length; i++) { 68 File file = chooser.getSelectedFiles()[i]; 69 if (file.isDirectory()) { 92 /** 93 * Reads a jpg pictures that contains the needed GPS information (position and 94 * direction) and creates a new icon in that position. 95 * 96 * @param file 97 * @throws ImageReadException 98 * @throws IOException 99 */ 100 public void readJPG(File file) throws ImageReadException, IOException { 101 final ImageMetadata metadata = Imaging.getMetadata(file); 102 if (metadata instanceof JpegImageMetadata) { 103 final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata; 104 final TiffField lat_ref = jpegMetadata 105 .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF); 106 final TiffField lat = jpegMetadata 107 .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LATITUDE); 108 final TiffField lon_ref = jpegMetadata 109 .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LONGITUDE_REF); 110 final TiffField lon = jpegMetadata 111 .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LONGITUDE); 112 final TiffField ca = jpegMetadata 113 .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION); 114 final TiffField datetimeOriginal = jpegMetadata 115 .findEXIFValueWithExactMatch(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL); 116 if (lat_ref == null || lat == null || lon == null || lon_ref == null) { 117 readNoTags(file); 118 return; 119 } 120 double latValue = 0; 121 double lonValue = 0; 122 double caValue = 0; 123 if (lat != null && lat.getValue() instanceof RationalNumber[]) 124 latValue = DegMinSecToDouble((RationalNumber[]) lat.getValue(), lat_ref 125 .getValue().toString()); 126 if (lon != null && lon.getValue() instanceof RationalNumber[]) 127 lonValue = DegMinSecToDouble((RationalNumber[]) lon.getValue(), lon_ref 128 .getValue().toString()); 129 if (ca != null && ca.getValue() instanceof RationalNumber) 130 caValue = ((RationalNumber) ca.getValue()).doubleValue(); 131 if (lat_ref.getValue().toString().equals("S")) 132 latValue = -latValue; 133 if (lon_ref.getValue().toString().equals("W")) 134 lonValue = -lonValue; 135 if (datetimeOriginal != null) 136 MapillaryData.getInstance().add( 137 new MapillaryImportedImage(latValue, lonValue, caValue, file, 138 datetimeOriginal.getStringValue())); 139 else 140 MapillaryData.getInstance().add( 141 new MapillaryImportedImage(latValue, lonValue, caValue, file)); 142 } 143 } 70 144 71 } else { 72 MapillaryLayer.getInstance(); 73 if (file.getPath().substring(file.getPath().length() - 4) 74 .equals(".jpg") 75 || file.getPath() 76 .substring(file.getPath().length() - 5) 77 .equals(".jpeg")) { 78 try { 79 readJPG(file); 80 } catch (ImageReadException ex) { 81 Main.error(ex); 82 } catch (IOException ex) { 83 Main.error(ex); 84 } 85 } else if (file.getPath() 86 .substring(file.getPath().length() - 4) 87 .equals(".png")) { 88 readPNG(file); 89 } 90 } 91 } 92 } 93 } 145 /** 146 * Reads a image file that doesn't contain the needed GPS information. And 147 * creates a new icon in the middle of the map. 148 * 149 * @param file 150 */ 151 private void readNoTags(File file) { 152 double HORIZONTAL_DISTANCE = 0.0001; 153 double horDev; 154 if (noTagsPics % 2 == 0) 155 horDev = HORIZONTAL_DISTANCE * noTagsPics / 2; 156 else 157 horDev = -HORIZONTAL_DISTANCE * ((noTagsPics + 1) / 2); 158 LatLon pos = Main.map.mapView.getProjection().eastNorth2latlon( 159 Main.map.mapView.getCenter()); 160 MapillaryData.getInstance().add( 161 new MapillaryImportedImage(pos.lat(), pos.lon() + horDev, 0, file)); 162 noTagsPics++; 163 } 94 164 95 /** 96 * Reads a jpg pictures that contains the needed GPS information (position 97 * and direction) and creates a new icon in that position. 98 * 99 * @param file 100 * @throws ImageReadException 101 * @throws IOException 102 */ 103 public void readJPG(File file) throws ImageReadException, IOException { 104 final ImageMetadata metadata = Imaging.getMetadata(file); 105 if (metadata instanceof JpegImageMetadata) { 106 final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata; 107 final TiffField lat_ref = jpegMetadata 108 .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF); 109 final TiffField lat = jpegMetadata 110 .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LATITUDE); 111 final TiffField lon_ref = jpegMetadata 112 .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LONGITUDE_REF); 113 final TiffField lon = jpegMetadata 114 .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LONGITUDE); 115 final TiffField ca = jpegMetadata 116 .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION); 117 final TiffField datetimeOriginal = jpegMetadata 118 .findEXIFValueWithExactMatch(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL); 119 if (lat_ref == null || lat == null || lon == null 120 || lon_ref == null) { 121 readNoTags(file); 122 return; 123 } 124 double latValue = 0; 125 double lonValue = 0; 126 double caValue = 0; 127 if (lat != null && lat.getValue() instanceof RationalNumber[]) 128 latValue = DegMinSecToDouble((RationalNumber[]) lat.getValue(), 129 lat_ref.getValue().toString()); 130 if (lon != null && lon.getValue() instanceof RationalNumber[]) 131 lonValue = DegMinSecToDouble((RationalNumber[]) lon.getValue(), 132 lon_ref.getValue().toString()); 133 if (ca != null && ca.getValue() instanceof RationalNumber) 134 caValue = ((RationalNumber) ca.getValue()).doubleValue(); 135 if (lat_ref.getValue().toString().equals("S")) 136 latValue = -latValue; 137 if (lon_ref.getValue().toString().equals("W")) 138 lonValue = -lonValue; 139 if (datetimeOriginal != null) 140 MapillaryData.getInstance().add( 141 new MapillaryImportedImage(latValue, lonValue, caValue, 142 file, datetimeOriginal.getStringValue())); 143 else 144 MapillaryData.getInstance().add( 145 new MapillaryImportedImage(latValue, lonValue, caValue, 146 file)); 147 } 148 } 165 private void readPNG(File file) { 166 readNoTags(file); 167 } 149 168 150 /** 151 * Reads a image file that doesn't contain the needed GPS information. And 152 * creates a new icon in the middle of the map. 153 * 154 * @param file 155 */ 156 private void readNoTags(File file) { 157 double HORIZONTAL_DISTANCE = 0.0001; 158 double horDev; 159 if (noTagsPics % 2 == 0) 160 horDev = HORIZONTAL_DISTANCE * noTagsPics / 2; 161 else 162 horDev = -HORIZONTAL_DISTANCE * ((noTagsPics + 1) / 2); 163 LatLon pos = Main.map.mapView.getProjection().eastNorth2latlon( 164 Main.map.mapView.getCenter()); 165 MapillaryData.getInstance().add( 166 new MapillaryImportedImage(pos.lat(), pos.lon() + horDev, 0, 167 file)); 168 noTagsPics++; 169 } 170 171 private void readPNG(File file) { 172 readNoTags(file); 173 } 174 175 private double DegMinSecToDouble(RationalNumber[] degMinSec, String ref) { 176 RationalNumber deg = degMinSec[0]; 177 RationalNumber min = degMinSec[1]; 178 RationalNumber sec = degMinSec[2]; 179 return deg.doubleValue() + min.doubleValue() / 60 + sec.doubleValue() 180 / 3600; 181 } 169 private double DegMinSecToDouble(RationalNumber[] degMinSec, String ref) { 170 RationalNumber deg = degMinSec[0]; 171 RationalNumber min = degMinSec[1]; 172 RationalNumber sec = degMinSec[2]; 173 return deg.doubleValue() + min.doubleValue() / 60 + sec.doubleValue() 174 / 3600; 175 } 182 176 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryZoomAction.java
r31313 r31350 22 22 */ 23 23 public class MapillaryZoomAction extends JosmAction implements 24 24 MapillaryDataListener { 25 25 26 27 28 29 30 31 KeyEvent.CHAR_UNDEFINED, Shortcut.NONE), false,32 "mapillaryZoom",false);33 34 35 26 public MapillaryZoomAction() { 27 super(tr("Zoom to selected image"), new ImageProvider("icon24.png"), 28 tr("Zoom to selected image"), Shortcut.registerShortcut( 29 "Zoom Mapillary", 30 tr("Zoom to the currently selected Mapillary image"), 31 KeyEvent.CHAR_UNDEFINED, Shortcut.NONE), false, "mapillaryZoom", 32 false); 33 MapillaryData.getInstance().addListener(this); 34 this.setEnabled(false); 35 } 36 36 37 38 39 40 41 42 43 37 @Override 38 public void actionPerformed(ActionEvent arg0) { 39 if (MapillaryData.getInstance().getSelectedImage() == null) 40 throw new IllegalStateException(); 41 Main.map.mapView.zoomTo(MapillaryData.getInstance().getSelectedImage() 42 .getLatLon()); 43 } 44 44 45 46 47 48 49 50 51 52 45 @Override 46 public void selectedImageChanged(MapillaryAbstractImage oldImage, 47 MapillaryAbstractImage newImage) { 48 if (oldImage == null && newImage != null) 49 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.ZOOM_MENU, true); 50 else if (oldImage != null && newImage == null) 51 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.ZOOM_MENU, false); 52 } 53 53 54 55 56 54 @Override 55 public void imagesAdded() { 56 } 57 57 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/cache/MapillaryCache.java
r31328 r31350 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 public static enum Type { 19 FULL_IMAGE, THUMBNAIL 18 public static enum Type { 19 FULL_IMAGE, THUMBNAIL 20 } 21 22 public MapillaryCache(String key, Type type) { 23 super(MapillaryPlugin.CACHE, 50000, 50000, new HashMap<String, String>()); 24 this.key = key; 25 try { 26 if (type == Type.FULL_IMAGE) { 27 url = new URL("https://d1cuyjsrcm0gby.cloudfront.net/" + key 28 + "/thumb-2048.jpg"); 29 this.key += ".FULL_IMAGE"; 30 31 } else if (type == Type.THUMBNAIL) { 32 url = new URL("https://d1cuyjsrcm0gby.cloudfront.net/" + key 33 + "/thumb-320.jpg"); 34 this.key += ".THUMBNAIL"; 35 } 36 } catch (MalformedURLException e) { 37 Main.error(e); 20 38 } 39 } 21 40 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"; 41 @Override 42 public String getCacheKey() { 43 return key; 44 } 31 45 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 } 46 @Override 47 public URL getUrl() { 48 return url; 49 } 41 50 42 43 public String getCacheKey() {44 return key;45 51 @Override 52 protected BufferedImageCacheEntry createCacheEntry(byte[] content) { 53 return new BufferedImageCacheEntry(content); 54 } 46 55 47 @Override 48 public URL getUrl() { 49 return url; 50 } 56 @Override 57 protected boolean isObjectLoadable() { 58 if (cacheData == null) 59 return false; 60 byte[] content = cacheData.getContent(); 61 return content != null && content.length > 0; 62 } 51 63 52 @Override 53 protected BufferedImageCacheEntry createCacheEntry(byte[] content) { 54 return new BufferedImageCacheEntry(content); 55 } 56 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 65 // @Override 66 protected boolean handleNotFound() { 67 return false; 68 } 64 // @Override 65 protected boolean handleNotFound() { 66 return false; 67 } 69 68 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/CommandMoveImage.java
r31317 r31350 16 16 */ 17 17 public class CommandMoveImage extends MapillaryCommand { 18 19 18 private double x; 19 private double y; 20 20 21 public CommandMoveImage(List<MapillaryAbstractImage> images, double x, 22 double y) { 23 this.images = new ArrayList<>(images); 24 this.x = x; 25 this.y = y; 21 public CommandMoveImage(List<MapillaryAbstractImage> images, double x, 22 double y) { 23 this.images = new ArrayList<>(images); 24 this.x = x; 25 this.y = y; 26 } 27 28 @Override 29 public void undo() { 30 for (MapillaryAbstractImage image : images) { 31 image.move(-x, -y); 32 image.stopMoving(); 26 33 } 34 checkModified(); 35 Main.map.repaint(); 36 } 27 37 28 @Override 29 public void undo() { 30 for (MapillaryAbstractImage image : images) { 31 image.move(-x, -y); 32 image.stopMoving(); 33 } 34 checkModified(); 35 Main.map.repaint(); 38 @Override 39 public void redo() { 40 for (MapillaryAbstractImage image : images) { 41 image.move(x, y); 42 image.stopMoving(); 36 43 } 44 checkModified(); 45 Main.map.repaint(); 46 } 37 47 38 @Override 39 public void redo() { 40 for (MapillaryAbstractImage image : images) { 41 image.move(x, y); 42 image.stopMoving(); 43 } 44 checkModified(); 45 Main.map.repaint(); 48 public String toString() { 49 return trn("Moved {0} image", "Moved {0} images", images.size(), 50 images.size()); 51 } 52 53 @Override 54 public void sum(MapillaryCommand command) { 55 if (command instanceof CommandMoveImage) { 56 this.x += ((CommandMoveImage) command).x; 57 this.y += ((CommandMoveImage) command).y; 46 58 } 47 48 public String toString() { 49 return trn("Moved {0} image", "Moved {0} images", images.size(), 50 images.size()); 51 } 52 53 @Override 54 public void sum(MapillaryCommand command) { 55 if (command instanceof CommandMoveImage) { 56 this.x += ((CommandMoveImage) command).x; 57 this.y += ((CommandMoveImage) command).y; 58 } 59 } 59 } 60 60 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/CommandTurnImage.java
r31331 r31350 16 16 */ 17 17 public class CommandTurnImage extends MapillaryCommand { 18 18 private double ca; 19 19 20 public CommandTurnImage(List<MapillaryAbstractImage> images, double ca) { 21 this.images = new ArrayList<>(images); 22 this.ca = ca; 20 public CommandTurnImage(List<MapillaryAbstractImage> images, double ca) { 21 this.images = new ArrayList<>(images); 22 this.ca = ca; 23 } 24 25 @Override 26 public void undo() { 27 for (MapillaryAbstractImage image : images) { 28 image.turn(-ca); 29 image.stopMoving(); 23 30 } 31 checkModified(); 32 Main.map.repaint(); 33 } 24 34 25 @Override 26 public void undo() { 27 for (MapillaryAbstractImage image : images) { 28 image.turn(-ca); 29 image.stopMoving(); 30 } 31 checkModified(); 32 Main.map.repaint(); 35 @Override 36 public void redo() { 37 for (MapillaryAbstractImage image : images) { 38 image.turn(ca); 39 image.stopMoving(); 33 40 } 41 checkModified(); 42 Main.map.repaint(); 43 } 34 44 35 @Override 36 public void redo() { 37 for (MapillaryAbstractImage image : images) { 38 image.turn(ca); 39 image.stopMoving(); 40 } 41 checkModified(); 42 Main.map.repaint(); 45 public String toString() { 46 return trn("Turned {0} image", "Turned {0} images", this.images.size(), 47 this.images.size()); 48 } 49 50 @Override 51 public void sum(MapillaryCommand command) { 52 if (command instanceof CommandTurnImage) { 53 this.ca += ((CommandTurnImage) command).ca; 43 54 } 44 45 public String toString() { 46 return trn("Turned {0} image", "Turned {0} images", this.images.size(), 47 this.images.size()); 48 } 49 50 @Override 51 public void sum(MapillaryCommand command) { 52 if (command instanceof CommandTurnImage) { 53 this.ca += ((CommandTurnImage) command).ca; 54 } 55 } 55 } 56 56 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/MapillaryCommand.java
r31278 r31350 12 12 */ 13 13 public abstract class MapillaryCommand { 14 14 protected List<MapillaryAbstractImage> images; 15 15 16 16 public abstract void undo(); 17 17 18 18 public abstract void redo(); 19 19 20 21 * If two equal commands are applied consecutively to the same set of22 * images,they are summed in order to reduce them to just one command.23 24 25 26 20 /** 21 * If two equal commands are applied consecutively to the same set of images, 22 * they are summed in order to reduce them to just one command. 23 * 24 * @param command 25 */ 26 public abstract void sum(MapillaryCommand command); 27 27 28 /** 29 * Checks if the image has been modified, compairing with its original 30 * values. 31 */ 32 public void checkModified() { 33 for (MapillaryAbstractImage image : images) 34 image.isModified = (image.tempLatLon == image.latLon || image.tempCa == image.ca); 35 } 28 /** 29 * Checks if the image has been modified, compairing with its original values. 30 */ 31 public void checkModified() { 32 for (MapillaryAbstractImage image : images) 33 image.isModified = (image.tempLatLon == image.latLon || image.tempCa == image.ca); 34 } 36 35 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/MapillaryRecord.java
r31331 r31350 12 12 */ 13 13 public class MapillaryRecord { 14 14 public static MapillaryRecord INSTANCE; 15 15 16 16 private ArrayList<MapillaryRecordListener> listeners; 17 17 18 19 20 18 public ArrayList<MapillaryCommand> commandList; 19 /** Last written command */ 20 public int position; 21 21 22 public MapillaryRecord() { 23 commandList = new ArrayList<>(); 24 position = -1; 25 listeners = new ArrayList<>(); 22 public MapillaryRecord() { 23 commandList = new ArrayList<>(); 24 position = -1; 25 listeners = new ArrayList<>(); 26 } 27 28 public static synchronized MapillaryRecord getInstance() { 29 if (MapillaryRecord.INSTANCE == null) 30 MapillaryRecord.INSTANCE = new MapillaryRecord(); 31 return MapillaryRecord.INSTANCE; 32 } 33 34 public void addListener(MapillaryRecordListener lis) { 35 this.listeners.add(lis); 36 } 37 38 public void removeListener(MapillaryRecordListener lis) { 39 this.listeners.remove(lis); 40 } 41 42 /** 43 * Adds a new command to the list. 44 * 45 * @param command 46 */ 47 public void addCommand(MapillaryCommand command) { 48 // Checks if it is a continuation of last command 49 if (position != -1) { 50 boolean equalSets = true; 51 for (MapillaryAbstractImage img : commandList.get(position).images) 52 if (!command.images.contains(img)) 53 equalSets = false; 54 if (equalSets 55 && commandList.get(position).getClass() == command.getClass()) { 56 commandList.get(position).sum(command); 57 fireRecordChanged(); 58 return; 59 } 26 60 } 61 // Adds the command to the las position of the list. 62 commandList.add(position + 1, command); 63 position++; 64 while (commandList.size() > position + 1) { 65 commandList.remove(position + 1); 66 } 67 fireRecordChanged(); 68 } 27 69 28 public static synchronized MapillaryRecord getInstance() { 29 if (MapillaryRecord.INSTANCE == null) 30 MapillaryRecord.INSTANCE = new MapillaryRecord(); 31 return MapillaryRecord.INSTANCE; 32 } 70 /** 71 * Undo latest command. 72 */ 73 public void undo() { 74 if (position == -1) 75 return; 76 commandList.get(position).undo(); 77 position--; 78 fireRecordChanged(); 79 } 33 80 34 public void addListener(MapillaryRecordListener lis) { 35 this.listeners.add(lis); 36 } 81 /** 82 * Redo latest undoed action. 83 */ 84 public void redo() { 85 if (position + 1 >= commandList.size()) 86 return; 87 position++; 88 commandList.get(position).redo(); 89 fireRecordChanged(); 90 } 37 91 38 public void removeListener(MapillaryRecordListener lis) { 39 this.listeners.remove(lis); 40 } 41 42 /** 43 * Adds a new command to the list. 44 * 45 * @param command 46 */ 47 public void addCommand(MapillaryCommand command) { 48 // Checks if it is a continuation of last command 49 if (position != -1) { 50 boolean equalSets = true; 51 for (MapillaryAbstractImage img : commandList.get(position).images) 52 if (!command.images.contains(img)) 53 equalSets = false; 54 if (equalSets 55 && commandList.get(position).getClass() == command 56 .getClass()) { 57 commandList.get(position).sum(command); 58 fireRecordChanged(); 59 return; 60 } 61 } 62 // Adds the command to the las position of the list. 63 commandList.add(position + 1, command); 64 position++; 65 while (commandList.size() > position + 1) { 66 commandList.remove(position + 1); 67 } 68 fireRecordChanged(); 69 } 70 71 /** 72 * Undo latest command. 73 */ 74 public void undo() { 75 if (position == -1) 76 return; 77 commandList.get(position).undo(); 78 position--; 79 fireRecordChanged(); 80 } 81 82 /** 83 * Redo latest undoed action. 84 */ 85 public void redo() { 86 if (position + 1 >= commandList.size()) 87 return; 88 position++; 89 commandList.get(position).redo(); 90 fireRecordChanged(); 91 } 92 93 private void fireRecordChanged() { 94 for (MapillaryRecordListener lis : listeners) 95 if (lis != null) 96 lis.recordChanged(); 97 } 92 private void fireRecordChanged() { 93 for (MapillaryRecordListener lis : listeners) 94 if (lis != null) 95 lis.recordChanged(); 96 } 98 97 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/MapillaryRecordListener.java
r31278 r31350 2 2 3 3 public interface MapillaryRecordListener { 4 4 public void recordChanged(); 5 5 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryDownloader.java
r31331 r31350 19 19 public class MapillaryDownloader { 20 20 21 22 23 21 public final static String BASE_URL = "https://a.mapillary.com/v2/"; 22 public final static String CLIENT_ID = "NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1YTA2NmNlODhlNWMwOTBm"; 23 public final static Executor EXECUTOR = Executors.newSingleThreadExecutor(); 24 24 25 private String[] parameters = { "lat", "lon", "distance", "limit",26 "min_lat","min_lon", "max_lat", "max_lon" };25 private String[] parameters = { "lat", "lon", "distance", "limit", "min_lat", 26 "min_lon", "max_lat", "max_lon" }; 27 27 28 public MapillaryDownloader() { 28 public MapillaryDownloader() { 29 } 30 31 /** 32 * Gets all the images in a square. It downloads all the images of all the 33 * sequences that pass through the given rectangle. 34 * 35 * @param minLatLon 36 * The minimum latitude and longitude of the rectangle. 37 * @param maxLatLon 38 * The maximum latitude and longitude of the rectangle 39 */ 40 public void getImages(LatLon minLatLon, LatLon maxLatLon) { 41 String url1 = BASE_URL; 42 String url2 = BASE_URL; 43 String url3 = BASE_URL; 44 url1 += "search/im/"; 45 url2 += "search/s/"; 46 url3 += "search/im/or"; 47 ConcurrentHashMap<String, Double> hash = new ConcurrentHashMap<>(); 48 hash.put("min_lat", minLatLon.lat()); 49 hash.put("min_lon", minLatLon.lon()); 50 hash.put("max_lat", maxLatLon.lat()); 51 hash.put("max_lon", maxLatLon.lon()); 52 url1 += buildParameters(hash); 53 url2 += buildParameters(hash); 54 url3 += buildParameters(hash); 55 56 try { 57 Main.info("GET " + url2 + " (Mapillary plugin)"); 58 EXECUTOR.execute(new MapillarySquareDownloadManagerThread(url1, url2, 59 url3, MapillaryLayer.getInstance())); 60 } catch (Exception e) { 61 Main.error(e); 29 62 } 63 } 30 64 31 /** 32 * Gets all the images in a square. It downloads all the images of all the 33 * sequences that pass through the given rectangle. 34 * 35 * @param minLatLon 36 * The minimum latitude and longitude of the rectangle. 37 * @param maxLatLon 38 * The maximum latitude and longitude of the rectangle 39 */ 40 public void getImages(LatLon minLatLon, LatLon maxLatLon) { 41 String url1 = BASE_URL; 42 String url2 = BASE_URL; 43 String url3 = BASE_URL; 44 url1 += "search/im/"; 45 url2 += "search/s/"; 46 url3 += "search/im/or"; 47 ConcurrentHashMap<String, Double> hash = new ConcurrentHashMap<>(); 48 hash.put("min_lat", minLatLon.lat()); 49 hash.put("min_lon", minLatLon.lon()); 50 hash.put("max_lat", maxLatLon.lat()); 51 hash.put("max_lon", maxLatLon.lon()); 52 url1 += buildParameters(hash); 53 url2 += buildParameters(hash); 54 url3 += buildParameters(hash); 65 /** 66 * Gets the images within the given bounds. 67 * 68 * @param bounds 69 */ 70 public void getImages(Bounds bounds) { 71 getImages(bounds.getMin(), bounds.getMax()); 72 } 55 73 56 try { 57 Main.info("GET " + url2 + " (Mapillary plugin)"); 58 EXECUTOR.execute(new MapillarySquareDownloadManagerThread(url1, 59 url2, url3, MapillaryLayer.getInstance())); 60 } catch (Exception e) { 61 Main.error(e); 62 } 63 } 64 65 /** 66 * Gets the images within the given bounds. 67 * 68 * @param bounds 69 */ 70 public void getImages(Bounds bounds) { 71 getImages(bounds.getMin(), bounds.getMax()); 72 } 73 74 private String buildParameters(ConcurrentHashMap<String, Double> hash) { 75 String ret = "?client_id=" + CLIENT_ID; 76 for (int i = 0; i < parameters.length; i++) 77 if (hash.get(parameters[i]) != null) 78 ret += "&" + parameters[i] + "=" + hash.get(parameters[i]); 79 return ret; 80 } 74 private String buildParameters(ConcurrentHashMap<String, Double> hash) { 75 String ret = "?client_id=" + CLIENT_ID; 76 for (int i = 0; i < parameters.length; i++) 77 if (hash.get(parameters[i]) != null) 78 ret += "&" + parameters[i] + "=" + hash.get(parameters[i]); 79 return ret; 80 } 81 81 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportDownloadThread.java
r31331 r31350 25 25 */ 26 26 public class MapillaryExportDownloadThread extends Thread implements 27 27 ICachedLoaderListener { 28 28 29 30 31 29 String url; 30 ArrayBlockingQueue<BufferedImage> queue; 31 ArrayBlockingQueue<MapillaryAbstractImage> queueImages; 32 32 33 34 33 ProgressMonitor monitor; 34 MapillaryImage image; 35 35 36 public MapillaryExportDownloadThread(MapillaryImage image, 37 ArrayBlockingQueue<BufferedImage> queue, 38 ArrayBlockingQueue<MapillaryAbstractImage> queueImages) { 39 url = "https://d1cuyjsrcm0gby.cloudfront.net/" + image.getKey() 40 + "/thumb-2048.jpg"; 41 this.queue = queue; 42 this.image = image; 43 this.queueImages = queueImages; 36 public MapillaryExportDownloadThread(MapillaryImage image, 37 ArrayBlockingQueue<BufferedImage> queue, 38 ArrayBlockingQueue<MapillaryAbstractImage> queueImages) { 39 url = "https://d1cuyjsrcm0gby.cloudfront.net/" + image.getKey() 40 + "/thumb-2048.jpg"; 41 this.queue = queue; 42 this.image = image; 43 this.queueImages = queueImages; 44 } 45 46 @Override 47 public void run() { 48 new MapillaryCache(image.getKey(), MapillaryCache.Type.FULL_IMAGE).submit( 49 this, false); 50 } 51 52 @Override 53 public void loadingFinished(CacheEntry data, CacheEntryAttributes attributes, 54 LoadResult result) { 55 try { 56 queue.put(ImageIO.read(new ByteArrayInputStream(data.getContent()))); 57 queueImages.put(image); 58 59 } catch (InterruptedException e) { 60 Main.error(e); 61 } catch (IOException e) { 62 Main.error(e); 44 63 } 45 46 @Override 47 public void run() { 48 new MapillaryCache(image.getKey(), MapillaryCache.Type.FULL_IMAGE) 49 .submit(this, false); 50 } 51 52 @Override 53 public void loadingFinished(CacheEntry data, 54 CacheEntryAttributes attributes, LoadResult result) { 55 try { 56 queue.put(ImageIO.read(new ByteArrayInputStream(data.getContent()))); 57 queueImages.put(image); 58 59 } catch (InterruptedException e) { 60 Main.error(e); 61 } catch (IOException e) { 62 Main.error(e); 63 } 64 } 64 } 65 65 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportManager.java
r31331 r31350 32 32 public class MapillaryExportManager extends PleaseWaitRunnable { 33 33 34 35 34 ArrayBlockingQueue<BufferedImage> queue; 35 ArrayBlockingQueue<MapillaryAbstractImage> queueImages; 36 36 37 final int amount; 38 List<MapillaryAbstractImage> images; 39 String path; 40 41 private Thread writer; 42 private ThreadPoolExecutor ex; 37 final int amount; 38 List<MapillaryAbstractImage> images; 39 String path; 43 40 44 public MapillaryExportManager(List<MapillaryAbstractImage> images, 45 String path) { 46 super(tr("Downloading") + "...", new PleaseWaitProgressMonitor( 47 "Exporting Mapillary Images"), true); 48 queue = new ArrayBlockingQueue<>(10); 49 queueImages = new ArrayBlockingQueue<>(10); 41 private Thread writer; 42 private ThreadPoolExecutor ex; 50 43 51 this.images = images; 52 amount = images.size(); 53 this.path = path; 44 public MapillaryExportManager(List<MapillaryAbstractImage> images, String path) { 45 super(tr("Downloading") + "...", new PleaseWaitProgressMonitor( 46 "Exporting Mapillary Images"), true); 47 queue = new ArrayBlockingQueue<>(10); 48 queueImages = new ArrayBlockingQueue<>(10); 49 50 this.images = images; 51 amount = images.size(); 52 this.path = path; 53 } 54 55 /** 56 * Constructor used to rewrite imported images. 57 * 58 * @param images 59 * @throws IOException 60 */ 61 public MapillaryExportManager(List<MapillaryImportedImage> images) 62 throws IOException { 63 super(tr("Downloading") + "...", new PleaseWaitProgressMonitor( 64 "Exporting Mapillary Images"), true); 65 queue = new ArrayBlockingQueue<>(10); 66 queueImages = new ArrayBlockingQueue<>(10); 67 for (MapillaryImportedImage image : images) { 68 queue.add(image.getImage()); 69 queueImages.add(image); 70 } 71 amount = images.size(); 72 } 73 74 @Override 75 protected void cancel() { 76 writer.interrupt(); 77 ex.shutdown(); 78 } 79 80 @Override 81 protected void realRun() throws SAXException, IOException, 82 OsmTransferException { 83 // Starts a writer thread in order to write the pictures on the disk. 84 writer = new MapillaryExportWriterThread(path, queue, queueImages, amount, 85 this.getProgressMonitor()); 86 writer.start(); 87 if (path == null) { 88 try { 89 writer.join(); 90 } catch (InterruptedException e) { 91 Main.error(e); 92 } 93 return; 94 } 95 ex = new ThreadPoolExecutor(20, 35, 25, TimeUnit.SECONDS, 96 new ArrayBlockingQueue<Runnable>(10)); 97 for (MapillaryAbstractImage image : images) { 98 if (image instanceof MapillaryImage) { 99 try { 100 ex.execute(new MapillaryExportDownloadThread((MapillaryImage) image, 101 queue, queueImages)); 102 } catch (Exception e) { 103 Main.error(e); 104 } 105 } else if (image instanceof MapillaryImportedImage) { 106 try { 107 queue.put(((MapillaryImportedImage) image).getImage()); 108 queueImages.put((MapillaryImportedImage) image); 109 } catch (InterruptedException e) { 110 Main.error(e); 111 } 112 } 113 try { 114 // If the queue is full, waits for it to have more space 115 // available before executing anything else. 116 while (ex.getQueue().remainingCapacity() == 0) 117 Thread.sleep(100); 118 } catch (Exception e) { 119 Main.error(e); 120 } 121 } 122 try { 123 writer.join(); 124 } catch (InterruptedException e) { 125 Main.error(e); 54 126 } 55 127 56 /** 57 * Constructor used to rewrite imported images. 58 * 59 * @param images 60 * @throws IOException 61 */ 62 public MapillaryExportManager(List<MapillaryImportedImage> images) 63 throws IOException { 64 super(tr("Downloading") + "...", new PleaseWaitProgressMonitor( 65 "Exporting Mapillary Images"), true); 66 queue = new ArrayBlockingQueue<>(10); 67 queueImages = new ArrayBlockingQueue<>(10); 68 for (MapillaryImportedImage image : images) { 69 queue.add(image.getImage()); 70 queueImages.add(image); 71 } 72 amount = images.size(); 73 } 128 } 74 129 75 @Override 76 protected void cancel() { 77 writer.interrupt(); 78 ex.shutdown(); 79 } 80 81 @Override 82 protected void realRun() throws SAXException, IOException, 83 OsmTransferException { 84 // Starts a writer thread in order to write the pictures on the disk. 85 writer = new MapillaryExportWriterThread(path, queue, 86 queueImages, amount, this.getProgressMonitor()); 87 writer.start(); 88 if (path == null) { 89 try { 90 writer.join(); 91 } catch (InterruptedException e) { 92 Main.error(e); 93 } 94 return; 95 } 96 ex = new ThreadPoolExecutor(20, 35, 25, 97 TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10)); 98 for (MapillaryAbstractImage image : images) { 99 if (image instanceof MapillaryImage) { 100 try { 101 ex.execute(new MapillaryExportDownloadThread( 102 (MapillaryImage) image, queue, queueImages)); 103 } catch (Exception e) { 104 Main.error(e); 105 } 106 } else if (image instanceof MapillaryImportedImage) { 107 try { 108 queue.put(((MapillaryImportedImage) image).getImage()); 109 queueImages.put((MapillaryImportedImage) image); 110 } catch (InterruptedException e) { 111 Main.error(e); 112 } 113 } 114 try { 115 // If the queue is full, waits for it to have more space 116 // available before executing anything else. 117 while (ex.getQueue().remainingCapacity() == 0) 118 Thread.sleep(100); 119 } catch (Exception e) { 120 Main.error(e); 121 } 122 } 123 try { 124 writer.join(); 125 } catch (InterruptedException e) { 126 Main.error(e); 127 } 128 129 } 130 131 @Override 132 protected void finish() { 133 // TODO Auto-generated method stub 134 } 130 @Override 131 protected void finish() { 132 // TODO Auto-generated method stub 133 } 135 134 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportWriterThread.java
r31331 r31350 34 34 public class MapillaryExportWriterThread extends Thread { 35 35 36 37 38 39 40 36 private final String path; 37 private final ArrayBlockingQueue<BufferedImage> queue; 38 private final ArrayBlockingQueue<MapillaryAbstractImage> queueImages; 39 private final int amount; 40 private final ProgressMonitor monitor; 41 41 42 public MapillaryExportWriterThread(String path, 43 ArrayBlockingQueue<BufferedImage> queue, 44 ArrayBlockingQueue<MapillaryAbstractImage> queueImages, int amount, 45 ProgressMonitor monitor) { 46 this.path = path; 47 this.queue = queue; 48 this.queueImages = queueImages; 49 this.amount = amount; 50 this.monitor = monitor; 42 public MapillaryExportWriterThread(String path, 43 ArrayBlockingQueue<BufferedImage> queue, 44 ArrayBlockingQueue<MapillaryAbstractImage> queueImages, int amount, 45 ProgressMonitor monitor) { 46 this.path = path; 47 this.queue = queue; 48 this.queueImages = queueImages; 49 this.amount = amount; 50 this.monitor = monitor; 51 } 52 53 @Override 54 public void run() { 55 monitor.setCustomText("Downloaded 0/" + amount); 56 File tempFile = null; 57 BufferedImage img; 58 MapillaryAbstractImage mimg = null; 59 String finalPath = ""; 60 for (int i = 0; i < amount; i++) { 61 try { 62 img = queue.take(); 63 mimg = queueImages.take(); 64 if (path == null && mimg instanceof MapillaryImportedImage) { 65 String path = ((MapillaryImportedImage) mimg).getFile().getPath(); 66 finalPath = path.substring(0, path.lastIndexOf('.')); 67 } else if (mimg instanceof MapillaryImage) 68 finalPath = path + "/" + ((MapillaryImage) mimg).getKey(); 69 else 70 finalPath = path + "/" + i; 71 // Creates a temporal file that is going to be deleted after 72 // writing the EXIF tags. 73 tempFile = new File(finalPath + ".tmp"); 74 ImageIO.write(img, "jpg", tempFile); 75 76 // Write EXIF tags 77 TiffOutputSet outputSet = new TiffOutputSet(); 78 TiffOutputDirectory exifDirectory = outputSet 79 .getOrCreateExifDirectory(); 80 exifDirectory.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF, 81 GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF_VALUE_TRUE_NORTH); 82 exifDirectory.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION, 83 RationalNumber.valueOf(mimg.getCa())); 84 if (mimg instanceof MapillaryImportedImage) { 85 exifDirectory.add(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, 86 ((MapillaryImportedImage) mimg).getDate("yyyy/MM/dd hh:mm:ss")); 87 } else if (mimg instanceof MapillaryImage) 88 exifDirectory.add(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, 89 ((MapillaryImage) mimg).getDate("yyyy/MM/dd hh/mm/ss")); 90 outputSet.setGPSInDegrees(mimg.getLatLon().lon(), mimg.getLatLon() 91 .lat()); 92 OutputStream os = new BufferedOutputStream(new FileOutputStream( 93 finalPath + ".jpg")); 94 new ExifRewriter().updateExifMetadataLossless(tempFile, os, outputSet); 95 tempFile.delete(); 96 os.close(); 97 } catch (InterruptedException e) { 98 Main.info("Mapillary export cancelled"); 99 return; 100 } catch (IOException e) { 101 Main.error(e); 102 } catch (ImageWriteException e) { 103 Main.error(e); 104 } catch (ImageReadException e) { 105 Main.error(e); 106 } 107 108 // Increases the progress bar. 109 monitor.worked(PleaseWaitProgressMonitor.PROGRESS_BAR_MAX / amount); 110 monitor.setCustomText("Downloaded " + (i + 1) + "/" + amount); 51 111 } 52 53 @Override 54 public void run() { 55 monitor.setCustomText("Downloaded 0/" + amount); 56 File tempFile = null; 57 BufferedImage img; 58 MapillaryAbstractImage mimg = null; 59 String finalPath = ""; 60 for (int i = 0; i < amount; i++) { 61 try { 62 img = queue.take(); 63 mimg = queueImages.take(); 64 if (path == null && mimg instanceof MapillaryImportedImage) { 65 String path = ((MapillaryImportedImage) mimg).getFile() 66 .getPath(); 67 finalPath = path.substring(0, path.lastIndexOf('.')); 68 } else if (mimg instanceof MapillaryImage) 69 finalPath = path + "/" + ((MapillaryImage) mimg).getKey(); 70 else 71 finalPath = path + "/" + i; 72 // Creates a temporal file that is going to be deleted after 73 // writing the EXIF tags. 74 tempFile = new File(finalPath + ".tmp"); 75 ImageIO.write(img, "jpg", tempFile); 76 77 // Write EXIF tags 78 TiffOutputSet outputSet = new TiffOutputSet(); 79 TiffOutputDirectory exifDirectory = outputSet 80 .getOrCreateExifDirectory(); 81 exifDirectory 82 .add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF, 83 GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF_VALUE_TRUE_NORTH); 84 exifDirectory.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION, 85 RationalNumber.valueOf(mimg.getCa())); 86 if (mimg instanceof MapillaryImportedImage) { 87 exifDirectory.add( 88 ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, 89 ((MapillaryImportedImage) mimg) 90 .getDate("yyyy/MM/dd hh:mm:ss")); 91 } else if (mimg instanceof MapillaryImage) 92 exifDirectory.add( 93 ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, 94 ((MapillaryImage) mimg) 95 .getDate("yyyy/MM/dd hh/mm/ss")); 96 outputSet.setGPSInDegrees(mimg.getLatLon().lon(), mimg 97 .getLatLon().lat()); 98 OutputStream os = new BufferedOutputStream( 99 new FileOutputStream(finalPath + ".jpg")); 100 new ExifRewriter().updateExifMetadataLossless(tempFile, os, 101 outputSet); 102 tempFile.delete(); 103 os.close(); 104 } catch (InterruptedException e) { 105 Main.info("Mapillary export cancelled"); 106 return; 107 } catch (IOException e) { 108 Main.error(e); 109 } catch (ImageWriteException e) { 110 Main.error(e); 111 } catch (ImageReadException e) { 112 Main.error(e); 113 } 114 115 // Increases the progress bar. 116 monitor.worked(PleaseWaitProgressMonitor.PROGRESS_BAR_MAX / amount); 117 monitor.setCustomText("Downloaded " + (i + 1) + "/" + amount); 118 } 119 } 112 } 120 113 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryImageInfoDownloaderThread.java
r31341 r31350 25 25 */ 26 26 public class MapillaryImageInfoDownloaderThread extends Thread { 27 28 29 27 private final String url; 28 private final ExecutorService ex; 29 private final MapillaryLayer layer; 30 30 31 public MapillaryImageInfoDownloaderThread(ExecutorService ex, String url, 32 MapillaryLayer layer) { 33 this.ex = ex; 34 this.url = url; 35 this.layer = layer; 31 public MapillaryImageInfoDownloaderThread(ExecutorService ex, String url, 32 MapillaryLayer layer) { 33 this.ex = ex; 34 this.url = url; 35 this.layer = layer; 36 } 37 38 public void run() { 39 try { 40 BufferedReader br = new BufferedReader(new InputStreamReader( 41 new URL(url).openStream(), "UTF-8")); 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.getString("user")); 55 ((MapillaryImage) image).setCapturedAt(data.getJsonNumber( 56 "captured_at").longValue()); 57 } 58 } 59 } 60 } 61 } catch (MalformedURLException e) { 62 Main.error(e); 63 } catch (IOException e) { 64 Main.error(e); 36 65 } 37 38 public void run() { 39 try { 40 BufferedReader br = new BufferedReader(new InputStreamReader( 41 new URL(url).openStream(), "UTF-8")); 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 } 66 } 68 67 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySequenceDownloadThread.java
r31346 r31350 31 31 public class MapillarySequenceDownloadThread extends Thread { 32 32 33 34 35 36 37 33 private final String url; 34 private final ExecutorService ex; 35 private final List<Bounds> bounds; 36 private final MapillaryLayer layer; 37 private final MapillarySquareDownloadManagerThread manager; 38 38 39 public MapillarySequenceDownloadThread(ExecutorService ex, String url, 40 MapillaryLayer layer, MapillarySquareDownloadManagerThread manager) { 41 this.url = url; 42 this.ex = ex; 43 this.bounds = layer.bounds; 44 this.layer = layer; 45 this.manager = manager; 39 public MapillarySequenceDownloadThread(ExecutorService ex, String url, 40 MapillaryLayer layer, MapillarySquareDownloadManagerThread manager) { 41 this.url = url; 42 this.ex = ex; 43 this.bounds = layer.bounds; 44 this.layer = layer; 45 this.manager = manager; 46 } 47 48 public void run() { 49 try { 50 BufferedReader br; 51 br = new BufferedReader(new InputStreamReader(new URL(url).openStream(), 52 "UTF-8")); 53 JsonObject jsonall = Json.createReader(br).readObject(); 54 55 if (!jsonall.getBoolean("more") && !ex.isShutdown()) 56 ex.shutdown(); 57 JsonArray jsonseq = jsonall.getJsonArray("ss"); 58 boolean isSequenceWrong = false; 59 for (int i = 0; i < jsonseq.size(); i++) { 60 JsonObject jsonobj = jsonseq.getJsonObject(i); 61 JsonArray cas = jsonobj.getJsonArray("cas"); 62 JsonArray coords = jsonobj.getJsonArray("coords"); 63 JsonArray keys = jsonobj.getJsonArray("keys"); 64 ArrayList<MapillaryImage> images = new ArrayList<>(); 65 for (int j = 0; j < cas.size(); j++) { 66 try { 67 images.add(new MapillaryImage(keys.getString(j), coords 68 .getJsonArray(j).getJsonNumber(1).doubleValue(), coords 69 .getJsonArray(j).getJsonNumber(0).doubleValue(), cas 70 .getJsonNumber(j).doubleValue())); 71 } catch (IndexOutOfBoundsException e) { 72 Main.warn("Mapillary bug at " + url); 73 isSequenceWrong = true; 74 } 75 } 76 if (isSequenceWrong) 77 break; 78 MapillarySequence sequence = new MapillarySequence( 79 jsonobj.getString("key"), jsonobj.getJsonNumber("captured_at") 80 .longValue()); 81 82 List<MapillaryImage> finalImages = new ArrayList<>(images); 83 // Here it gets only those images which are in the downloaded 84 // area. 85 for (MapillaryAbstractImage img : images) { 86 if (!isInside(img)) 87 finalImages.remove(img); 88 } 89 90 boolean imagesAdded = false; 91 MapillaryImage.lock.lock(); 92 for (MapillaryImage img : finalImages) { 93 if (layer.data.getImages().contains(img)) { 94 sequence.add(img); 95 ((MapillaryImage) layer.data.getImages().get( 96 layer.data.getImages().indexOf(img))).setSequence(sequence); 97 finalImages.set( 98 finalImages.indexOf(img), 99 (MapillaryImage) layer.data.getImages().get( 100 layer.data.getImages().indexOf(img))); 101 } else { 102 img.setSequence(sequence); 103 imagesAdded = true; 104 sequence.add(img); 105 } 106 } 107 MapillaryImage.lock.unlock(); 108 if (manager != null) { 109 manager.imagesAdded = imagesAdded; 110 } 111 layer.data.addWithoutUpdate(new ArrayList<MapillaryAbstractImage>( 112 finalImages)); 113 } 114 } catch (IOException e) { 115 Main.error("Error reading the url " + url 116 + " might be a Mapillary problem."); 46 117 } 118 } 47 119 48 public void run() { 49 try { 50 BufferedReader br; 51 br = new BufferedReader(new InputStreamReader( 52 new URL(url).openStream(), "UTF-8")); 53 JsonObject jsonall = Json.createReader(br).readObject(); 54 55 if (!jsonall.getBoolean("more") && !ex.isShutdown()) 56 ex.shutdown(); 57 JsonArray jsonseq = jsonall.getJsonArray("ss"); 58 boolean isSequenceWrong = false; 59 for (int i = 0; i < jsonseq.size(); i++) { 60 JsonObject jsonobj = jsonseq.getJsonObject(i); 61 JsonArray cas = jsonobj.getJsonArray("cas"); 62 JsonArray coords = jsonobj.getJsonArray("coords"); 63 JsonArray keys = jsonobj.getJsonArray("keys"); 64 ArrayList<MapillaryImage> images = new ArrayList<>(); 65 for (int j = 0; j < cas.size(); j++) { 66 try { 67 images.add(new MapillaryImage(keys.getString(j), 68 coords.getJsonArray(j).getJsonNumber(1) 69 .doubleValue(), coords.getJsonArray(j) 70 .getJsonNumber(0).doubleValue(), cas 71 .getJsonNumber(j).doubleValue())); 72 } catch (IndexOutOfBoundsException e) { 73 Main.warn("Mapillary bug at " + url); 74 isSequenceWrong = true; 75 } 76 } 77 if (isSequenceWrong) 78 break; 79 MapillarySequence sequence = new MapillarySequence( 80 jsonobj.getString("key"), jsonobj.getJsonNumber( 81 "captured_at").longValue()); 82 83 List<MapillaryImage> finalImages = new ArrayList<>(images); 84 // Here it gets only those images which are in the downloaded 85 // area. 86 for (MapillaryAbstractImage img : images) { 87 if (!isInside(img)) 88 finalImages.remove(img); 89 } 90 91 boolean imagesAdded = false; 92 MapillaryImage.lock.lock(); 93 for (MapillaryImage img : finalImages) { 94 if (layer.data.getImages().contains(img)) { 95 sequence.add(img); 96 ((MapillaryImage) layer.data.getImages().get( 97 layer.data.getImages().indexOf(img))) 98 .setSequence(sequence); 99 finalImages.set( 100 finalImages.indexOf(img), 101 (MapillaryImage) layer.data.getImages().get( 102 layer.data.getImages().indexOf(img))); 103 } else { 104 img.setSequence(sequence); 105 imagesAdded = true; 106 sequence.add(img); 107 } 108 } 109 MapillaryImage.lock.unlock(); 110 if (manager != null) { 111 manager.imagesAdded = imagesAdded; 112 } 113 layer.data 114 .addWithoutUpdate(new ArrayList<MapillaryAbstractImage>( 115 finalImages)); 116 } 117 } catch (IOException e) { 118 Main.error("Error reading the url " + url 119 + " might be a Mapillary problem."); 120 } 121 } 122 123 private boolean isInside(MapillaryAbstractImage image) { 124 for (int i = 0; i < bounds.size(); i++) 125 if (bounds.get(i).contains(image.getLatLon())) 126 return true; 127 return false; 128 } 120 private boolean isInside(MapillaryAbstractImage image) { 121 for (int i = 0; i < bounds.size(); i++) 122 if (bounds.get(i).contains(image.getLatLon())) 123 return true; 124 return false; 125 } 129 126 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySignDownloaderThread.java
r31341 r31350 19 19 public class MapillarySignDownloaderThread extends Thread { 20 20 21 22 23 21 private final String url; 22 private final ExecutorService ex; 23 private final MapillaryLayer layer; 24 24 25 public MapillarySignDownloaderThread(ExecutorService ex, String url, 26 MapillaryLayer layer) { 27 this.ex = ex; 28 this.url = url; 29 this.layer = layer; 25 public MapillarySignDownloaderThread(ExecutorService ex, String url, 26 MapillaryLayer layer) { 27 this.ex = ex; 28 this.url = url; 29 this.layer = layer; 30 } 31 32 @Override 33 public void run() { 34 BufferedReader br; 35 try { 36 br = new BufferedReader(new InputStreamReader(new URL(url).openStream(), 37 "UTF-8")); 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).getJsonArray("rects"); 45 JsonArray rectversions = jsonarr.getJsonObject(i).getJsonArray( 46 "rectversions"); 47 String key = jsonarr.getJsonObject(i).getString("key"); 48 if (rectversions != null) { 49 for (int j = 0; j < rectversions.size(); j++) { 50 rects = rectversions.getJsonObject(j).getJsonArray("rects"); 51 for (int k = 0; k < rects.size(); k++) { 52 JsonObject data = rects.getJsonObject(k); 53 for (MapillaryAbstractImage image : layer.data.getImages()) 54 if (image instanceof MapillaryImage 55 && ((MapillaryImage) image).getKey().equals(key)) 56 ((MapillaryImage) image).addSign(data.getString("type")); 57 } 58 } 59 } 60 61 // Just one sign on the picture 62 else if (rects != null) { 63 for (int j = 0; j < rects.size(); j++) { 64 JsonObject data = rects.getJsonObject(j); 65 for (MapillaryAbstractImage image : layer.data.getImages()) 66 if (image instanceof MapillaryImage 67 && ((MapillaryImage) image).getKey().equals(key)) 68 ((MapillaryImage) image).addSign(data.getString("type")); 69 } 70 } 71 } 72 } catch (MalformedURLException e) { 73 Main.error(e); 74 } catch (IOException e) { 75 Main.error(e); 30 76 } 31 32 @Override 33 public void run() { 34 BufferedReader br; 35 try { 36 br = new BufferedReader(new InputStreamReader( 37 new URL(url).openStream(), "UTF-8")); 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 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 } 77 } 86 78 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySquareDownloadManagerThread.java
r31346 r31350 14 14 /** 15 15 * This Class is needed to create an indeterminate amount of downloads, because 16 * the Mapillary API has a parameter called page which is needed when the 17 * amountof requested images is quite big.16 * the Mapillary API has a parameter called page which is needed when the amount 17 * of requested images is quite big. 18 18 * 19 19 * @author nokutu … … 23 23 public class MapillarySquareDownloadManagerThread extends Thread { 24 24 25 26 27 28 29 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 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; 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 } 38 39 public void run() { 40 Main.map.statusLine.setHelpText("Downloading images from Mapillary"); 41 try { 42 downloadSequences(); 43 if (imagesAdded) { 44 Main.map.statusLine.setHelpText("Downloading image's information"); 45 completeImages(); 46 MapillaryMainDialog.getInstance().updateTitle(); 47 Main.map.statusLine.setHelpText("Downloading signs"); 48 downloadSigns(); 49 } 50 } catch (InterruptedException e) { 51 Main.error(e); 37 52 } 53 if (layer.data.getImages().size() > 0) 54 Main.map.statusLine.setHelpText(tr("Total images: ") 55 + layer.data.getImages().size()); 56 else 57 Main.map.statusLine.setHelpText(tr("No images found")); 58 layer.data.dataUpdated(); 59 MapillaryFilterDialog.getInstance().refresh(); 60 MapillaryMainDialog.getInstance().updateImage(); 61 } 38 62 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 MapillaryMainDialog.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 MapillaryMainDialog.getInstance().updateImage(); 63 private void downloadSequences() throws InterruptedException { 64 ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25, TimeUnit.SECONDS, 65 new ArrayBlockingQueue<Runnable>(5)); 66 int page = 0; 67 while (!ex.isShutdown()) { 68 ex.execute(new MapillarySequenceDownloadThread(ex, urlSequences 69 + "&page=" + page + "&limit=10", layer, this)); 70 while (ex.getQueue().remainingCapacity() == 0) 71 Thread.sleep(500); 72 page++; 62 73 } 74 ex.awaitTermination(15, TimeUnit.SECONDS); 75 layer.data.dataUpdated(); 76 } 63 77 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=10", layer, this)); 71 while (ex.getQueue().remainingCapacity() == 0) 72 Thread.sleep(500); 73 page++; 74 } 75 ex.awaitTermination(15, TimeUnit.SECONDS); 76 layer.data.dataUpdated(); 78 private void completeImages() throws InterruptedException { 79 ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25, TimeUnit.SECONDS, 80 new ArrayBlockingQueue<Runnable>(5)); 81 int page = 0; 82 while (!ex.isShutdown()) { 83 ex.execute(new MapillaryImageInfoDownloaderThread(ex, urlImages 84 + "&page=" + page + "&limit=20", layer)); 85 while (ex.getQueue().remainingCapacity() == 0) 86 Thread.sleep(100); 87 page++; 77 88 } 89 ex.awaitTermination(15, TimeUnit.SECONDS); 90 } 78 91 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); 92 private void downloadSigns() throws InterruptedException { 93 ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25, TimeUnit.SECONDS, 94 new ArrayBlockingQueue<Runnable>(5)); 95 int page = 0; 96 while (!ex.isShutdown()) { 97 ex.execute(new MapillarySignDownloaderThread(ex, urlSigns + "&page=" 98 + page + "&limit=20", layer)); 99 while (ex.getQueue().remainingCapacity() == 0) 100 Thread.sleep(100); 101 page++; 91 102 } 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 } 103 ex.awaitTermination(15, TimeUnit.SECONDS); 104 } 106 105 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/HyperlinkLabel.java
r31278 r31350 21 21 public class HyperlinkLabel extends JLabel implements ActionListener { 22 22 23 24 23 private String text; 24 private URL url; 25 25 26 27 28 29 30 31 32 26 /** 27 * Creates a new HyperlinlLabel. 28 */ 29 public HyperlinkLabel() { 30 super(tr("View in website"), SwingUtilities.RIGHT); 31 this.addActionListener(this); 32 setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); 33 33 34 enableEvents(MouseEvent.MOUSE_EVENT_MASK); 34 enableEvents(MouseEvent.MOUSE_EVENT_MASK); 35 } 36 37 /** 38 * Sets the text of the label. 39 */ 40 public void setText(String text) { 41 super 42 .setText("<html><font color=\"#0000CF\" size=\"2\">" + text + "</font></html>"); //$NON-NLS-1$ //$NON-NLS-2$ 43 this.text = text; 44 } 45 46 /** 47 * Sets a new URL, just pass the key of the image or null if there is none. 48 * 49 * @param key 50 */ 51 public void setURL(String key) { 52 if (key == null) { 53 this.url = null; 54 return; 35 55 } 56 try { 57 this.url = new URL("http://www.mapillary.com/map/im/" + key); 58 } catch (MalformedURLException e) { 59 Main.error(e); 60 } 61 } 36 62 37 /** 38 * Sets the text of the label. 39 */ 40 public void setText(String text) { 41 super.setText("<html><font color=\"#0000CF\" size=\"2\">" + text + "</font></html>"); //$NON-NLS-1$ //$NON-NLS-2$ 42 this.text = text; 63 /** 64 * Returns the text set by the user. 65 */ 66 public String getNormalText() { 67 return text; 68 } 69 70 /** 71 * Processes mouse events and responds to clicks. 72 */ 73 protected void processMouseEvent(MouseEvent evt) { 74 super.processMouseEvent(evt); 75 if (evt.getID() == MouseEvent.MOUSE_CLICKED) 76 fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, 77 getNormalText())); 78 } 79 80 /** 81 * Adds an ActionListener to the list of listeners receiving notifications 82 * when the label is clicked. 83 */ 84 public void addActionListener(ActionListener listener) { 85 listenerList.add(ActionListener.class, listener); 86 } 87 88 /** 89 * Removes the given ActionListener from the list of listeners receiving 90 * notifications when the label is clicked. 91 */ 92 public void removeActionListener(ActionListener listener) { 93 listenerList.remove(ActionListener.class, listener); 94 } 95 96 /** 97 * Fires an ActionEvent to all interested listeners. 98 */ 99 protected void fireActionPerformed(ActionEvent evt) { 100 Object[] listeners = listenerList.getListenerList(); 101 for (int i = 0; i < listeners.length; i += 2) { 102 if (listeners[i] == ActionListener.class) { 103 ActionListener listener = (ActionListener) listeners[i + 1]; 104 listener.actionPerformed(evt); 105 } 43 106 } 107 } 44 108 45 /** 46 * Sets a new URL, just pass the key of the image or null if there is none. 47 * 48 * @param key 49 */ 50 public void setURL(String key) { 51 if (key == null) { 52 this.url = null; 53 return; 54 } 55 try { 56 this.url = new URL("http://www.mapillary.com/map/im/" + key); 57 } catch (MalformedURLException e) { 58 Main.error(e); 59 } 109 @Override 110 public void actionPerformed(ActionEvent e) { 111 if (this.url == null) 112 return; 113 Desktop desktop = Desktop.getDesktop(); 114 try { 115 desktop.browse(url.toURI()); 116 } catch (IOException | URISyntaxException ex) { 117 ex.printStackTrace(); 118 } catch (UnsupportedOperationException ex) { 119 Runtime runtime = Runtime.getRuntime(); 120 try { 121 runtime.exec("xdg-open " + url); 122 } catch (IOException exc) { 123 exc.printStackTrace(); 124 } 60 125 } 61 62 /** 63 * Returns the text set by the user. 64 */ 65 public String getNormalText() { 66 return text; 67 } 68 69 /** 70 * Processes mouse events and responds to clicks. 71 */ 72 protected void processMouseEvent(MouseEvent evt) { 73 super.processMouseEvent(evt); 74 if (evt.getID() == MouseEvent.MOUSE_CLICKED) 75 fireActionPerformed(new ActionEvent(this, 76 ActionEvent.ACTION_PERFORMED, getNormalText())); 77 } 78 79 /** 80 * Adds an ActionListener to the list of listeners receiving notifications 81 * when the label is clicked. 82 */ 83 public void addActionListener(ActionListener listener) { 84 listenerList.add(ActionListener.class, listener); 85 } 86 87 /** 88 * Removes the given ActionListener from the list of listeners receiving 89 * notifications when the label is clicked. 90 */ 91 public void removeActionListener(ActionListener listener) { 92 listenerList.remove(ActionListener.class, listener); 93 } 94 95 /** 96 * Fires an ActionEvent to all interested listeners. 97 */ 98 protected void fireActionPerformed(ActionEvent evt) { 99 Object[] listeners = listenerList.getListenerList(); 100 for (int i = 0; i < listeners.length; i += 2) { 101 if (listeners[i] == ActionListener.class) { 102 ActionListener listener = (ActionListener) listeners[i + 1]; 103 listener.actionPerformed(evt); 104 } 105 } 106 } 107 108 @Override 109 public void actionPerformed(ActionEvent e) { 110 if (this.url == null) 111 return; 112 Desktop desktop = Desktop.getDesktop(); 113 try { 114 desktop.browse(url.toURI()); 115 } catch (IOException | URISyntaxException ex) { 116 ex.printStackTrace(); 117 } catch (UnsupportedOperationException ex) { 118 Runtime runtime = Runtime.getRuntime(); 119 try { 120 runtime.exec("xdg-open " + url); 121 } catch (IOException exc) { 122 exc.printStackTrace(); 123 } 124 } 125 } 126 } 126 127 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryExportDialog.java
r31331 r31350 30 30 public class MapillaryExportDialog extends JPanel implements ActionListener { 31 31 32 protected JOptionPane optionPane; 33 /** Button to export all downloaded images. */ 34 public JRadioButton all; 35 /** 36 * Button to export all images in the sequence of the selected 37 * MapillaryImage. 38 */ 39 public JRadioButton sequence; 40 /** 41 * Button to export all images belonging to the selected MapillaryImage 42 * objects. 43 */ 44 public JRadioButton selected; 45 public JRadioButton rewrite; 46 public ButtonGroup group; 47 protected JButton choose; 48 protected JLabel path; 49 public JFileChooser chooser; 50 protected String exportDirectory; 32 protected JOptionPane optionPane; 33 /** Button to export all downloaded images. */ 34 public JRadioButton all; 35 /** 36 * Button to export all images in the sequence of the selected MapillaryImage. 37 */ 38 public JRadioButton sequence; 39 /** 40 * Button to export all images belonging to the selected MapillaryImage 41 * objects. 42 */ 43 public JRadioButton selected; 44 public JRadioButton rewrite; 45 public ButtonGroup group; 46 protected JButton choose; 47 protected JLabel path; 48 public JFileChooser chooser; 49 protected String exportDirectory; 51 50 52 public MapillaryExportDialog() { 53 setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); 54 55 RewriteButtonAction action = new RewriteButtonAction(this); 56 group = new ButtonGroup(); 57 all = new JRadioButton(action); 58 all.setText(tr("Export all images")); 59 sequence = new JRadioButton(action); 60 sequence.setText(tr("Export selected sequence")); 61 selected = new JRadioButton(action); 62 selected.setText(tr("Export selected images")); 63 rewrite = new JRadioButton(action); 64 rewrite.setText(tr("Rewrite imported images")); 65 group.add(all); 66 group.add(sequence); 67 group.add(selected); 68 group.add(rewrite); 69 // Some options are disabled depending on the circumstances 70 if (MapillaryData.getInstance().getSelectedImage() == null 71 || !(MapillaryData.getInstance().getSelectedImage() instanceof MapillaryImage && ((MapillaryImage) MapillaryData 72 .getInstance().getSelectedImage()).getSequence() != null)) { 73 sequence.setEnabled(false); 74 } 75 if (MapillaryData.getInstance().getMultiSelectedImages().isEmpty()) { 76 selected.setEnabled(false); 77 } 78 rewrite.setEnabled(false); 79 for (MapillaryAbstractImage img : MapillaryData.getInstance().getImages()) 80 if (img instanceof MapillaryImportedImage) 81 rewrite.setEnabled(true); 82 83 path = new JLabel(tr("Select a folder")); 84 choose = new JButton(tr("Explore")); 85 choose.addActionListener(this); 51 public MapillaryExportDialog() { 52 setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); 86 53 87 // All options belong to the same jpanel so the are in line. 88 JPanel jpanel = new JPanel(); 89 jpanel.setLayout(new BoxLayout(jpanel, BoxLayout.PAGE_AXIS)); 90 jpanel.add(all); 91 jpanel.add(sequence); 92 jpanel.add(selected); 93 jpanel.add(rewrite); 94 jpanel.setAlignmentX(Component.CENTER_ALIGNMENT); 95 path.setAlignmentX(Component.CENTER_ALIGNMENT); 96 choose.setAlignmentX(Component.CENTER_ALIGNMENT); 54 RewriteButtonAction action = new RewriteButtonAction(this); 55 group = new ButtonGroup(); 56 all = new JRadioButton(action); 57 all.setText(tr("Export all images")); 58 sequence = new JRadioButton(action); 59 sequence.setText(tr("Export selected sequence")); 60 selected = new JRadioButton(action); 61 selected.setText(tr("Export selected images")); 62 rewrite = new JRadioButton(action); 63 rewrite.setText(tr("Rewrite imported images")); 64 group.add(all); 65 group.add(sequence); 66 group.add(selected); 67 group.add(rewrite); 68 // Some options are disabled depending on the circumstances 69 if (MapillaryData.getInstance().getSelectedImage() == null 70 || !(MapillaryData.getInstance().getSelectedImage() instanceof MapillaryImage && ((MapillaryImage) MapillaryData 71 .getInstance().getSelectedImage()).getSequence() != null)) { 72 sequence.setEnabled(false); 73 } 74 if (MapillaryData.getInstance().getMultiSelectedImages().isEmpty()) { 75 selected.setEnabled(false); 76 } 77 rewrite.setEnabled(false); 78 for (MapillaryAbstractImage img : MapillaryData.getInstance().getImages()) 79 if (img instanceof MapillaryImportedImage) 80 rewrite.setEnabled(true); 97 81 98 add(jpanel); 99 add(path); 100 add(choose); 82 path = new JLabel(tr("Select a folder")); 83 choose = new JButton(tr("Explore")); 84 choose.addActionListener(this); 85 86 // All options belong to the same jpanel so the are in line. 87 JPanel jpanel = new JPanel(); 88 jpanel.setLayout(new BoxLayout(jpanel, BoxLayout.PAGE_AXIS)); 89 jpanel.add(all); 90 jpanel.add(sequence); 91 jpanel.add(selected); 92 jpanel.add(rewrite); 93 jpanel.setAlignmentX(Component.CENTER_ALIGNMENT); 94 path.setAlignmentX(Component.CENTER_ALIGNMENT); 95 choose.setAlignmentX(Component.CENTER_ALIGNMENT); 96 97 add(jpanel); 98 add(path); 99 add(choose); 100 } 101 102 /** 103 * Creates the folder choser GUI. 104 */ 105 @Override 106 public void actionPerformed(ActionEvent e) { 107 chooser = new JFileChooser(); 108 chooser.setCurrentDirectory(new java.io.File(System 109 .getProperty("user.home"))); 110 chooser.setDialogTitle(tr("Select a directory")); 111 chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 112 chooser.setAcceptAllFileFilterUsed(false); 113 114 if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { 115 path.setText(chooser.getSelectedFile().toString()); 116 this.updateUI(); 117 } 118 } 119 120 public class RewriteButtonAction extends AbstractAction { 121 122 private String lastPath; 123 private MapillaryExportDialog dlg; 124 125 public RewriteButtonAction(MapillaryExportDialog dlg) { 126 this.dlg = dlg; 101 127 } 102 128 103 /**104 * Creates the folder choser GUI.105 */106 129 @Override 107 public void actionPerformed(ActionEvent e) { 108 chooser = new JFileChooser(); 109 chooser.setCurrentDirectory(new java.io.File(System 110 .getProperty("user.home"))); 111 chooser.setDialogTitle(tr("Select a directory")); 112 chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 113 chooser.setAcceptAllFileFilterUsed(false); 130 public void actionPerformed(ActionEvent arg0) { 131 choose.setEnabled(!rewrite.isSelected()); 132 if (rewrite.isSelected()) { 133 lastPath = dlg.path.getText(); 134 dlg.path.setText(" "); 135 } else if (lastPath != null) { 136 dlg.path.setText(lastPath); 137 } 114 138 115 if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {116 path.setText(chooser.getSelectedFile().toString());117 this.updateUI();118 }119 139 } 120 121 public class RewriteButtonAction extends AbstractAction {122 140 123 private String lastPath; 124 private MapillaryExportDialog dlg; 125 126 public RewriteButtonAction(MapillaryExportDialog dlg) { 127 this.dlg = dlg; 128 } 129 130 @Override 131 public void actionPerformed(ActionEvent arg0) { 132 choose.setEnabled(!rewrite.isSelected()); 133 if (rewrite.isSelected()) { 134 lastPath = dlg.path.getText(); 135 dlg.path.setText(" "); 136 } 137 else if (lastPath != null){ 138 dlg.path.setText(lastPath); 139 } 140 141 } 142 143 } 141 } 144 142 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterChooseSigns.java
r31328 r31350 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 intersectionLabel.setIcon(new ImageProvider(92 93 94 95 88 // Danger intersection 89 JPanel intersectionPanel = new JPanel(); 90 JLabel intersectionLabel = new JLabel(tr("Intersection danger")); 91 intersectionLabel 92 .setIcon(new ImageProvider("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
r31334 r31350 38 38 */ 39 39 public class MapillaryFilterDialog extends ToggleDialog implements 40 MapillaryDataListener { 41 42 public static MapillaryFilterDialog INSTANCE; 43 44 private final static String[] TIME_LIST = { tr("All time"), 45 tr("This year"), tr("This month"), tr("This week") }; 46 47 private final static int ROWS = 0; 48 private final static int COLUMNS = 3; 49 50 private final JPanel panel = new JPanel(new GridLayout(ROWS, COLUMNS)); 51 52 public final JCheckBox imported = new JCheckBox("Imported images"); 53 public final JCheckBox downloaded = new JCheckBox( 54 new downloadCheckBoxAction()); 55 public final JCheckBox onlySigns = new JCheckBox(new OnlySignsAction()); 56 public final JComboBox<String> time; 57 public final JTextField user; 58 59 public final SideButton updateButton = new SideButton(new UpdateAction()); 60 public final SideButton resetButton = new SideButton(new ResetAction()); 61 public final JButton signChooser = new JButton(new SignChooserAction()); 62 63 public final MapillaryFilterChooseSigns signFilter = MapillaryFilterChooseSigns 64 .getInstance(); 65 66 /** The list of sign names */ 67 private final String[] SIGN_TAGS = { "prohibitory_speed_limit", 68 "priority_stop", "other_give_way", "mandatory_roundabout", 69 "other_no_entry", "prohibitory_no_traffic_both_ways", 70 "danger_intersection", "mandatory_go", "mandatory_keep", 71 "danger_priority_next_intersection", "danger_uneven_road", 72 "prohibitory_no_parking", "prohibitory_on_overtaking", 73 "danger_pedestrian_crossing", "prohibitory_no_u_turn", 74 "prohibitory_noturn" }; 75 /** The the {@link JCheckBox} where the respective tag should be searched */ 76 private final JCheckBox[] SIGN_CHECKBOXES = { signFilter.maxspeed, 77 signFilter.stop, signFilter.giveWay, signFilter.roundabout, 78 signFilter.access, signFilter.access, signFilter.intersection, 79 signFilter.direction, signFilter.direction, 80 signFilter.intersection, signFilter.uneven, signFilter.noParking, 81 signFilter.noOvertaking, signFilter.crossing, signFilter.noTurn, 82 signFilter.noTurn }; 83 84 public MapillaryFilterDialog() { 85 super(tr("Mapillary filter"), "mapillaryfilter.png", 86 tr("Open Mapillary filter dialog"), Shortcut.registerShortcut( 87 tr("Mapillary filter"), 88 tr("Open Mapillary filter dialog"), KeyEvent.VK_M, 89 Shortcut.NONE), 200); 90 91 signChooser.setEnabled(false); 92 JPanel signChooserPanel = new JPanel(); 93 signChooserPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); 94 signChooserPanel.add(signChooser); 95 96 JPanel fromPanel = new JPanel(); 97 fromPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); 98 fromPanel.add(new JLabel("From")); 99 time = new JComboBox<>(TIME_LIST); 100 fromPanel.add(time); 101 102 JPanel userSearchPanel = new JPanel(); 103 userSearchPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); 104 user = new JTextField(10); 105 user.addActionListener(new UpdateAction()); 106 userSearchPanel.add(new JLabel("User")); 107 userSearchPanel.add(user); 108 109 imported.setSelected(true); 110 downloaded.setSelected(true); 111 112 panel.add(downloaded); 113 panel.add(imported); 114 panel.add(onlySigns); 115 panel.add(fromPanel); 116 panel.add(userSearchPanel); 117 panel.add(signChooserPanel); 118 119 createLayout(panel, true, 120 Arrays.asList(new SideButton[] { updateButton, resetButton })); 121 } 122 123 public static MapillaryFilterDialog getInstance() { 124 if (INSTANCE == null) 125 INSTANCE = new MapillaryFilterDialog(); 126 return INSTANCE; 127 } 128 129 @Override 130 public void imagesAdded() { 131 refresh(); 132 } 133 134 @Override 135 public void selectedImageChanged(MapillaryAbstractImage oldImage, 136 MapillaryAbstractImage newImage) { 137 } 138 139 /** 140 * Resets the dialog to its default state. 141 */ 142 public void reset() { 143 imported.setSelected(true); 144 downloaded.setSelected(true); 145 onlySigns.setEnabled(true); 146 onlySigns.setSelected(false); 147 user.setText(""); 148 time.setSelectedItem(TIME_LIST[0]); 149 refresh(); 150 } 151 152 /** 153 * Applies the selected filter. 154 */ 155 public synchronized void refresh() { 156 boolean imported = this.imported.isSelected(); 157 boolean downloaded = this.downloaded.isSelected(); 158 boolean onlySigns = this.onlySigns.isSelected(); 159 160 for (MapillaryAbstractImage img : MapillaryData.getInstance() 161 .getImages()) { 162 img.setVisible(true); 163 if (img instanceof MapillaryImportedImage) { 164 if (!imported) 165 img.setVisible(false); 166 continue; 167 } else if (img instanceof MapillaryImage) { 168 if (!downloaded) { 169 img.setVisible(false); 170 continue; 171 } 172 if (onlySigns) { 173 if (((MapillaryImage) img).getSigns().isEmpty()) { 174 img.setVisible(false); 175 continue; 176 } 177 if (!checkSigns((MapillaryImage) img)) { 178 img.setVisible(false); 179 continue; 180 } 181 } 182 if (!user.getText().equals("") 183 && !user.getText().equals( 184 ((MapillaryImage) img).getUser())) { 185 img.setVisible(false); 186 continue; 187 } 188 } 189 // Calculates the amount of days since the image was taken 190 Long currentTime = currentTime(); 191 if (time.getSelectedItem() == TIME_LIST[1]) { 192 if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 365) { 193 img.setVisible(false); 194 continue; 195 } 196 } 197 if (time.getSelectedItem() == TIME_LIST[2]) { 198 if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 30) { 199 img.setVisible(false); 200 continue; 201 } 202 } 203 if (time.getSelectedItem() == TIME_LIST[3]) { 204 if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 7) { 205 img.setVisible(false); 206 continue; 207 } 208 } 209 } 210 Main.map.repaint(); 211 } 212 213 /** 214 * Checks if the image fulfills the sign conditions. 215 * 216 * @param img 217 * The {@link MapillaryAbstractImage} object that is going to be 218 * checked. 219 * @return {@code true} if it fulfills the conditions; {@code false} 220 * otherwise. 221 */ 222 private boolean checkSigns(MapillaryImage img) { 223 for (int i = 0; i < SIGN_TAGS.length; i++) { 224 if (checkSign(img, SIGN_CHECKBOXES[i], SIGN_TAGS[i])) 225 return true; 226 } 227 return false; 228 } 229 230 private boolean checkSign(MapillaryImage img, JCheckBox signCheckBox, 231 String singString) { 232 boolean contains = false; 233 for (String sign : img.getSigns()) { 234 if (sign.contains(singString)) 235 contains = true; 236 } 237 if (contains == signCheckBox.isSelected() && contains) 238 return true; 239 return false; 240 } 241 242 private long currentTime() { 243 Calendar cal = Calendar.getInstance(); 244 return cal.getTimeInMillis(); 245 } 246 247 private class downloadCheckBoxAction extends AbstractAction { 248 249 public downloadCheckBoxAction() { 250 putValue(NAME, tr("Downloaded images")); 251 } 252 253 @Override 254 public void actionPerformed(ActionEvent arg0) { 255 onlySigns.setEnabled(downloaded.isSelected()); 256 } 257 } 258 259 private class UpdateAction extends AbstractAction { 260 public UpdateAction() { 261 putValue(NAME, tr("Update")); 262 } 263 264 @Override 265 public void actionPerformed(ActionEvent arg0) { 266 MapillaryFilterDialog.getInstance().refresh(); 267 } 268 } 269 270 private class ResetAction extends AbstractAction { 271 public ResetAction() { 272 putValue(NAME, tr("Reset")); 273 } 274 275 @Override 276 public void actionPerformed(ActionEvent arg0) { 277 MapillaryFilterDialog.getInstance().reset(); 278 } 279 } 280 281 private class OnlySignsAction extends AbstractAction { 282 public OnlySignsAction() { 283 putValue(NAME, tr("Only images with signs")); 284 } 285 286 @Override 287 public void actionPerformed(ActionEvent arg0) { 288 signChooser.setEnabled(onlySigns.isSelected()); 289 } 290 } 291 292 /** 293 * Opens a new window where you can specifically filter signs. 294 * 295 * @author nokutu 296 * 297 */ 298 private class SignChooserAction extends AbstractAction { 299 public SignChooserAction() { 300 putValue(NAME, tr("Choose signs")); 301 } 302 303 @Override 304 public void actionPerformed(ActionEvent arg0) { 305 JPanel dialog = MapillaryFilterChooseSigns.getInstance(); 306 JOptionPane pane = new JOptionPane(dialog, 307 JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION); 308 JDialog dlg = pane.createDialog(Main.parent, tr("Choose signs")); 309 dlg.setVisible(true); 310 if ((int) pane.getValue() == JOptionPane.OK_OPTION) 311 MapillaryFilterDialog.getInstance().refresh(); 312 dlg.dispose(); 313 } 314 } 315 316 public static void destroyInstance() { 317 MapillaryFilterDialog.INSTANCE = null; 318 } 40 MapillaryDataListener { 41 42 public static MapillaryFilterDialog INSTANCE; 43 44 private final static String[] TIME_LIST = { tr("All time"), tr("This year"), 45 tr("This month"), tr("This week") }; 46 47 private final static int ROWS = 0; 48 private final static int COLUMNS = 3; 49 50 private final JPanel panel = new JPanel(new GridLayout(ROWS, COLUMNS)); 51 52 public final JCheckBox imported = new JCheckBox("Imported images"); 53 public final JCheckBox downloaded = new JCheckBox( 54 new downloadCheckBoxAction()); 55 public final JCheckBox onlySigns = new JCheckBox(new OnlySignsAction()); 56 public final JComboBox<String> time; 57 public final JTextField user; 58 59 public final SideButton updateButton = new SideButton(new UpdateAction()); 60 public final SideButton resetButton = new SideButton(new ResetAction()); 61 public final JButton signChooser = new JButton(new SignChooserAction()); 62 63 public final MapillaryFilterChooseSigns signFilter = MapillaryFilterChooseSigns 64 .getInstance(); 65 66 /** The list of sign names */ 67 private final String[] SIGN_TAGS = { "prohibitory_speed_limit", 68 "priority_stop", "other_give_way", "mandatory_roundabout", 69 "other_no_entry", "prohibitory_no_traffic_both_ways", 70 "danger_intersection", "mandatory_go", "mandatory_keep", 71 "danger_priority_next_intersection", "danger_uneven_road", 72 "prohibitory_no_parking", "prohibitory_on_overtaking", 73 "danger_pedestrian_crossing", "prohibitory_no_u_turn", 74 "prohibitory_noturn" }; 75 /** The the {@link JCheckBox} where the respective tag should be searched */ 76 private final JCheckBox[] SIGN_CHECKBOXES = { signFilter.maxspeed, 77 signFilter.stop, signFilter.giveWay, signFilter.roundabout, 78 signFilter.access, signFilter.access, signFilter.intersection, 79 signFilter.direction, signFilter.direction, signFilter.intersection, 80 signFilter.uneven, signFilter.noParking, signFilter.noOvertaking, 81 signFilter.crossing, signFilter.noTurn, signFilter.noTurn }; 82 83 public MapillaryFilterDialog() { 84 super(tr("Mapillary filter"), "mapillaryfilter.png", 85 tr("Open Mapillary filter dialog"), Shortcut.registerShortcut( 86 tr("Mapillary filter"), tr("Open Mapillary filter dialog"), 87 KeyEvent.VK_M, Shortcut.NONE), 200); 88 89 signChooser.setEnabled(false); 90 JPanel signChooserPanel = new JPanel(); 91 signChooserPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); 92 signChooserPanel.add(signChooser); 93 94 JPanel fromPanel = new JPanel(); 95 fromPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); 96 fromPanel.add(new JLabel("From")); 97 time = new JComboBox<>(TIME_LIST); 98 fromPanel.add(time); 99 100 JPanel userSearchPanel = new JPanel(); 101 userSearchPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); 102 user = new JTextField(10); 103 user.addActionListener(new UpdateAction()); 104 userSearchPanel.add(new JLabel("User")); 105 userSearchPanel.add(user); 106 107 imported.setSelected(true); 108 downloaded.setSelected(true); 109 110 panel.add(downloaded); 111 panel.add(imported); 112 panel.add(onlySigns); 113 panel.add(fromPanel); 114 panel.add(userSearchPanel); 115 panel.add(signChooserPanel); 116 117 createLayout(panel, true, 118 Arrays.asList(new SideButton[] { updateButton, resetButton })); 119 } 120 121 public static MapillaryFilterDialog getInstance() { 122 if (INSTANCE == null) 123 INSTANCE = new MapillaryFilterDialog(); 124 return INSTANCE; 125 } 126 127 @Override 128 public void imagesAdded() { 129 refresh(); 130 } 131 132 @Override 133 public void selectedImageChanged(MapillaryAbstractImage oldImage, 134 MapillaryAbstractImage newImage) { 135 } 136 137 /** 138 * Resets the dialog to its default state. 139 */ 140 public void reset() { 141 imported.setSelected(true); 142 downloaded.setSelected(true); 143 onlySigns.setEnabled(true); 144 onlySigns.setSelected(false); 145 user.setText(""); 146 time.setSelectedItem(TIME_LIST[0]); 147 refresh(); 148 } 149 150 /** 151 * Applies the selected filter. 152 */ 153 public synchronized void refresh() { 154 boolean imported = this.imported.isSelected(); 155 boolean downloaded = this.downloaded.isSelected(); 156 boolean onlySigns = this.onlySigns.isSelected(); 157 158 for (MapillaryAbstractImage img : MapillaryData.getInstance().getImages()) { 159 img.setVisible(true); 160 if (img instanceof MapillaryImportedImage) { 161 if (!imported) 162 img.setVisible(false); 163 continue; 164 } else if (img instanceof MapillaryImage) { 165 if (!downloaded) { 166 img.setVisible(false); 167 continue; 168 } 169 if (onlySigns) { 170 if (((MapillaryImage) img).getSigns().isEmpty()) { 171 img.setVisible(false); 172 continue; 173 } 174 if (!checkSigns((MapillaryImage) img)) { 175 img.setVisible(false); 176 continue; 177 } 178 } 179 if (!user.getText().equals("") 180 && !user.getText().equals(((MapillaryImage) img).getUser())) { 181 img.setVisible(false); 182 continue; 183 } 184 } 185 // Calculates the amount of days since the image was taken 186 Long currentTime = currentTime(); 187 if (time.getSelectedItem() == TIME_LIST[1]) { 188 if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 365) { 189 img.setVisible(false); 190 continue; 191 } 192 } 193 if (time.getSelectedItem() == TIME_LIST[2]) { 194 if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 30) { 195 img.setVisible(false); 196 continue; 197 } 198 } 199 if (time.getSelectedItem() == TIME_LIST[3]) { 200 if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 7) { 201 img.setVisible(false); 202 continue; 203 } 204 } 205 } 206 Main.map.repaint(); 207 } 208 209 /** 210 * Checks if the image fulfills the sign conditions. 211 * 212 * @param img 213 * The {@link MapillaryAbstractImage} object that is going to be 214 * checked. 215 * @return {@code true} if it fulfills the conditions; {@code false} 216 * otherwise. 217 */ 218 private boolean checkSigns(MapillaryImage img) { 219 for (int i = 0; i < SIGN_TAGS.length; i++) { 220 if (checkSign(img, SIGN_CHECKBOXES[i], SIGN_TAGS[i])) 221 return true; 222 } 223 return false; 224 } 225 226 private boolean checkSign(MapillaryImage img, JCheckBox signCheckBox, 227 String singString) { 228 boolean contains = false; 229 for (String sign : img.getSigns()) { 230 if (sign.contains(singString)) 231 contains = true; 232 } 233 if (contains == signCheckBox.isSelected() && contains) 234 return true; 235 return false; 236 } 237 238 private long currentTime() { 239 Calendar cal = Calendar.getInstance(); 240 return cal.getTimeInMillis(); 241 } 242 243 private class downloadCheckBoxAction extends AbstractAction { 244 245 public downloadCheckBoxAction() { 246 putValue(NAME, tr("Downloaded images")); 247 } 248 249 @Override 250 public void actionPerformed(ActionEvent arg0) { 251 onlySigns.setEnabled(downloaded.isSelected()); 252 } 253 } 254 255 private class UpdateAction extends AbstractAction { 256 public UpdateAction() { 257 putValue(NAME, tr("Update")); 258 } 259 260 @Override 261 public void actionPerformed(ActionEvent arg0) { 262 MapillaryFilterDialog.getInstance().refresh(); 263 } 264 } 265 266 private class ResetAction extends AbstractAction { 267 public ResetAction() { 268 putValue(NAME, tr("Reset")); 269 } 270 271 @Override 272 public void actionPerformed(ActionEvent arg0) { 273 MapillaryFilterDialog.getInstance().reset(); 274 } 275 } 276 277 private class OnlySignsAction extends AbstractAction { 278 public OnlySignsAction() { 279 putValue(NAME, tr("Only images with signs")); 280 } 281 282 @Override 283 public void actionPerformed(ActionEvent arg0) { 284 signChooser.setEnabled(onlySigns.isSelected()); 285 } 286 } 287 288 /** 289 * Opens a new window where you can specifically filter signs. 290 * 291 * @author nokutu 292 * 293 */ 294 private class SignChooserAction extends AbstractAction { 295 public SignChooserAction() { 296 putValue(NAME, tr("Choose signs")); 297 } 298 299 @Override 300 public void actionPerformed(ActionEvent arg0) { 301 JPanel dialog = MapillaryFilterChooseSigns.getInstance(); 302 JOptionPane pane = new JOptionPane(dialog, JOptionPane.PLAIN_MESSAGE, 303 JOptionPane.OK_CANCEL_OPTION); 304 JDialog dlg = pane.createDialog(Main.parent, tr("Choose signs")); 305 dlg.setVisible(true); 306 if ((int) pane.getValue() == JOptionPane.OK_OPTION) 307 MapillaryFilterDialog.getInstance().refresh(); 308 dlg.dispose(); 309 } 310 } 311 312 public static void destroyInstance() { 313 MapillaryFilterDialog.INSTANCE = null; 314 } 319 315 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryHistoryDialog.java
r31334 r31350 31 31 32 32 /** 33 * Toggle dialog that shows you the latest {@link MapillaryCommand} done and allows the user to34 * revert them.33 * Toggle dialog that shows you the latest {@link MapillaryCommand} done and 34 * allows the user to revert them. 35 35 * 36 36 * @see MapillaryRecord … … 40 40 */ 41 41 public class MapillaryHistoryDialog extends ToggleDialog implements 42 42 MapillaryRecordListener { 43 43 44 44 public static MapillaryHistoryDialog INSTANCE; 45 45 46 47 48 49 50 51 46 private final DefaultTreeModel undoTreeModel = new DefaultTreeModel( 47 new DefaultMutableTreeNode()); 48 private final DefaultTreeModel redoTreeModel = new DefaultTreeModel( 49 new DefaultMutableTreeNode()); 50 private final JTree undoTree = new JTree(undoTreeModel); 51 private final JTree redoTree = new JTree(redoTreeModel); 52 52 53 54 53 private JSeparator separator = new JSeparator(); 54 private Component spacer = Box.createRigidArea(new Dimension(0, 3)); 55 55 56 57 56 private SideButton undoButton; 57 private SideButton redoButton; 58 58 59 public MapillaryHistoryDialog() { 60 super(tr("Mapillary history"), "mapillaryhistory.png", 61 tr("Open Mapillary history dialog"), Shortcut.registerShortcut( 62 tr("Mapillary history"), 63 tr("Open Mapillary history dialog"), KeyEvent.VK_M, 64 Shortcut.NONE), 200); 59 public MapillaryHistoryDialog() { 60 super(tr("Mapillary history"), "mapillaryhistory.png", 61 tr("Open Mapillary history dialog"), Shortcut.registerShortcut( 62 tr("Mapillary history"), tr("Open Mapillary history dialog"), 63 KeyEvent.VK_M, Shortcut.NONE), 200); 65 64 66 65 MapillaryRecord.getInstance().addListener(this); 67 66 68 69 70 71 72 73 74 75 67 undoTree.expandRow(0); 68 undoTree.setShowsRootHandles(true); 69 undoTree.setRootVisible(false); 70 undoTree.setCellRenderer(new MapillaryCellRenderer()); 71 redoTree.expandRow(0); 72 redoTree.setCellRenderer(new MapillaryCellRenderer()); 73 redoTree.setShowsRootHandles(true); 74 redoTree.setRootVisible(false); 76 75 77 78 79 80 81 82 83 84 treesPanel.add(Box.createRigidArea(new Dimension(0, 0)), GBC.std()85 86 76 JPanel treesPanel = new JPanel(new GridBagLayout()); 77 treesPanel.add(spacer, GBC.eol()); 78 spacer.setVisible(false); 79 treesPanel.add(undoTree, GBC.eol().fill(GBC.HORIZONTAL)); 80 separator.setVisible(false); 81 treesPanel.add(separator, GBC.eol().fill(GBC.HORIZONTAL)); 82 treesPanel.add(redoTree, GBC.eol().fill(GBC.HORIZONTAL)); 83 treesPanel.add(Box.createRigidArea(new Dimension(0, 0)), 84 GBC.std().weight(0, 1)); 85 treesPanel.setBackground(redoTree.getBackground()); 87 86 88 89 87 undoButton = new SideButton(new UndoAction()); 88 redoButton = new SideButton(new RedoAction()); 90 89 91 createLayout(treesPanel, true, 92 Arrays.asList(new SideButton[] { undoButton, redoButton })); 90 createLayout(treesPanel, true, 91 Arrays.asList(new SideButton[] { undoButton, redoButton })); 92 } 93 94 public static MapillaryHistoryDialog getInstance() { 95 if (INSTANCE == null) 96 INSTANCE = new MapillaryHistoryDialog(); 97 return INSTANCE; 98 } 99 100 private void buildTree() { 101 redoButton.setEnabled(true); 102 undoButton.setEnabled(true); 103 ArrayList<MapillaryCommand> commands = MapillaryRecord.getInstance().commandList; 104 int position = MapillaryRecord.getInstance().position; 105 ArrayList<MapillaryCommand> undoCommands = new ArrayList<>(); 106 if (position >= 0) 107 undoCommands = new ArrayList<>(commands.subList(0, position + 1)); 108 else 109 undoButton.setEnabled(false); 110 ArrayList<MapillaryCommand> redoCommands = new ArrayList<>(); 111 if (commands.size() > 0 && position + 1 < commands.size()) 112 redoCommands = new ArrayList<>(commands.subList(position + 1, 113 commands.size())); 114 else 115 redoButton.setEnabled(false); 116 117 DefaultMutableTreeNode redoRoot = new DefaultMutableTreeNode(); 118 DefaultMutableTreeNode undoRoot = new DefaultMutableTreeNode(); 119 120 for (MapillaryCommand command : undoCommands) { 121 if (command != null) 122 undoRoot.add(new DefaultMutableTreeNode(command.toString())); 123 } 124 for (MapillaryCommand command : redoCommands) { 125 if (command != null) 126 redoRoot.add(new DefaultMutableTreeNode(command.toString())); 93 127 } 94 128 95 public static MapillaryHistoryDialog getInstance() { 96 if (INSTANCE == null) 97 INSTANCE = new MapillaryHistoryDialog(); 98 return INSTANCE; 99 } 129 separator.setVisible(!undoCommands.isEmpty() || !redoCommands.isEmpty()); 130 spacer.setVisible(undoCommands.isEmpty() && !redoCommands.isEmpty()); 100 131 101 private void buildTree() { 102 redoButton.setEnabled(true); 103 undoButton.setEnabled(true); 104 ArrayList<MapillaryCommand> commands = MapillaryRecord.getInstance().commandList; 105 int position = MapillaryRecord.getInstance().position; 106 ArrayList<MapillaryCommand> undoCommands = new ArrayList<>(); 107 if (position >= 0) 108 undoCommands = new ArrayList<>(commands.subList(0, position + 1)); 109 else 110 undoButton.setEnabled(false); 111 ArrayList<MapillaryCommand> redoCommands = new ArrayList<>(); 112 if (commands.size() > 0 && position + 1 < commands.size()) 113 redoCommands = new ArrayList<>(commands.subList(position + 1, 114 commands.size())); 115 else 116 redoButton.setEnabled(false); 132 undoTreeModel.setRoot(undoRoot); 133 redoTreeModel.setRoot(redoRoot); 134 } 117 135 118 DefaultMutableTreeNode redoRoot = new DefaultMutableTreeNode(); 119 DefaultMutableTreeNode undoRoot = new DefaultMutableTreeNode(); 136 @Override 137 public void recordChanged() { 138 buildTree(); 139 } 120 140 121 for (MapillaryCommand command : undoCommands) { 122 if (command != null) 123 undoRoot.add(new DefaultMutableTreeNode(command.toString())); 124 } 125 for (MapillaryCommand command : redoCommands) { 126 if (command != null) 127 redoRoot.add(new DefaultMutableTreeNode(command.toString())); 128 } 141 private class UndoAction extends AbstractAction { 129 142 130 separator 131 .setVisible(!undoCommands.isEmpty() || !redoCommands.isEmpty()); 132 spacer.setVisible(undoCommands.isEmpty() && !redoCommands.isEmpty()); 133 134 undoTreeModel.setRoot(undoRoot); 135 redoTreeModel.setRoot(redoRoot); 143 public UndoAction() { 144 putValue(NAME, tr("Undo")); 145 putValue(SMALL_ICON, ImageProvider.get("undo")); 136 146 } 137 147 138 148 @Override 139 public void recordChanged() {140 buildTree();149 public void actionPerformed(ActionEvent arg0) { 150 MapillaryRecord.getInstance().undo(); 141 151 } 142 152 143 private class UndoAction extends AbstractAction {153 } 144 154 145 public UndoAction() { 146 putValue(NAME, tr("Undo")); 147 putValue(SMALL_ICON, ImageProvider.get("undo")); 148 } 149 150 @Override 151 public void actionPerformed(ActionEvent arg0) { 152 MapillaryRecord.getInstance().undo(); 153 } 154 155 private class RedoAction extends AbstractAction { 156 public RedoAction() { 157 putValue(NAME, tr("Redo")); 158 putValue(SMALL_ICON, ImageProvider.get("redo")); 155 159 } 156 160 157 private class RedoAction extends AbstractAction { 158 public RedoAction() { 159 putValue(NAME, tr("Redo")); 160 putValue(SMALL_ICON, ImageProvider.get("redo")); 161 } 162 163 @Override 164 public void actionPerformed(ActionEvent arg0) { 165 MapillaryRecord.getInstance().redo(); 166 } 167 161 @Override 162 public void actionPerformed(ActionEvent arg0) { 163 MapillaryRecord.getInstance().redo(); 168 164 } 169 165 170 private static class MapillaryCellRenderer extends DefaultTreeCellRenderer {171 @Override 172 public Component getTreeCellRendererComponent(JTree tree, Object value,173 boolean sel, boolean expanded, boolean leaf, int row,174 boolean hasFocus) {175 super.getTreeCellRendererComponent(tree, value, sel, expanded,176 leaf, row, hasFocus);177 setIcon(ImageProvider.get("data/node.png"));178 return this;179 }166 } 167 168 private static class MapillaryCellRenderer extends DefaultTreeCellRenderer { 169 @Override 170 public Component getTreeCellRendererComponent(JTree tree, Object value, 171 boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { 172 super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, 173 hasFocus); 174 setIcon(ImageProvider.get("data/node.png")); 175 return this; 180 176 } 177 } 181 178 182 183 184 179 public static void destroyInstance() { 180 MapillaryHistoryDialog.INSTANCE = null; 181 } 185 182 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryImageDisplay.java
r31334 r31350 33 33 public class MapillaryImageDisplay extends JComponent { 34 34 35 private static final int DRAG_BUTTON = Main.pref.getInteger( 36 "mapillary.picture-drag-button", 3); 37 private static final int OPTION_BUTTON = Main.pref.getInteger( 38 "mapillary.picture-option-button", 2); 39 private static final int ZOOM_BUTTON = Main.pref.getInteger( 40 "mapillary.picture-zoom-button", 1); 41 42 /** The image currently displayed */ 43 private transient BufferedImage image = null; 35 private static final int DRAG_BUTTON = Main.pref.getInteger( 36 "mapillary.picture-drag-button", 3); 37 private static final int OPTION_BUTTON = Main.pref.getInteger( 38 "mapillary.picture-option-button", 2); 39 private static final int ZOOM_BUTTON = Main.pref.getInteger( 40 "mapillary.picture-zoom-button", 1); 41 42 /** The image currently displayed */ 43 private transient BufferedImage image = null; 44 45 /** 46 * The rectangle (in image coordinates) of the image that is visible. This 47 * rectangle is calculated each time the zoom is modified 48 */ 49 private Rectangle visibleRect = null; 50 51 /** 52 * When a selection is done, the rectangle of the selection (in image 53 * coordinates) 54 */ 55 private Rectangle selectedRect = null; 56 57 public HyperlinkLabel hyperlink; 58 59 private class ImgDisplayMouseListener implements MouseListener, 60 MouseWheelListener, MouseMotionListener { 61 private boolean mouseIsDragging = false; 62 private long lastTimeForMousePoint = 0L; 63 private Point mousePointInImg = null; 44 64 45 65 /** 46 * The rectangle (in image coordinates) of the image that is visible. This47 * rectangle is calculated each time the zoom is modified66 * Zoom in and out, trying to preserve the point of the image that was under 67 * the mouse cursor at the same place 48 68 */ 49 private Rectangle visibleRect = null; 69 @Override 70 public void mouseWheelMoved(MouseWheelEvent e) { 71 Image image; 72 Rectangle visibleRect; 73 synchronized (MapillaryImageDisplay.this) { 74 image = MapillaryImageDisplay.this.image; 75 visibleRect = MapillaryImageDisplay.this.visibleRect; 76 } 77 mouseIsDragging = false; 78 selectedRect = null; 79 if (image == null) 80 return; 81 // Calculate the mouse cursor position in image coordinates, so that 82 // we can center the zoom 83 // on that mouse position. 84 // To avoid issues when the user tries to zoom in on the image 85 // borders, this point is not calculated 86 // again if there was less than 1.5seconds since the last event. 87 if (e.getWhen() - lastTimeForMousePoint > 1500 || mousePointInImg == null) { 88 lastTimeForMousePoint = e.getWhen(); 89 mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY()); 90 } 91 // Applicate the zoom to the visible rectangle in image coordinates 92 if (e.getWheelRotation() > 0) { 93 visibleRect.width = visibleRect.width * 3 / 2; 94 visibleRect.height = visibleRect.height * 3 / 2; 95 } else { 96 visibleRect.width = visibleRect.width * 2 / 3; 97 visibleRect.height = visibleRect.height * 2 / 3; 98 } 99 // Check that the zoom doesn't exceed 2:1 100 if (visibleRect.width < getSize().width / 2) { 101 visibleRect.width = getSize().width / 2; 102 } 103 if (visibleRect.height < getSize().height / 2) { 104 visibleRect.height = getSize().height / 2; 105 } 106 // Set the same ratio for the visible rectangle and the display area 107 int hFact = visibleRect.height * getSize().width; 108 int wFact = visibleRect.width * getSize().height; 109 if (hFact > wFact) { 110 visibleRect.width = hFact / getSize().height; 111 } else { 112 visibleRect.height = wFact / getSize().width; 113 } 114 // The size of the visible rectangle is limited by the image size. 115 checkVisibleRectSize(image, visibleRect); 116 // Set the position of the visible rectangle, so that the mouse 117 // cursor doesn't move on the image. 118 Rectangle drawRect = calculateDrawImageRectangle(visibleRect); 119 visibleRect.x = mousePointInImg.x 120 + ((drawRect.x - e.getX()) * visibleRect.width) / drawRect.width; 121 visibleRect.y = mousePointInImg.y 122 + ((drawRect.y - e.getY()) * visibleRect.height) / drawRect.height; 123 // The position is also limited by the image size 124 checkVisibleRectPos(image, visibleRect); 125 synchronized (MapillaryImageDisplay.this) { 126 MapillaryImageDisplay.this.visibleRect = visibleRect; 127 } 128 MapillaryImageDisplay.this.repaint(); 129 } 130 131 /** Center the display on the point that has been clicked */ 132 @Override 133 public void mouseClicked(MouseEvent e) { 134 // Move the center to the clicked point. 135 Image image; 136 Rectangle visibleRect; 137 synchronized (MapillaryImageDisplay.this) { 138 image = MapillaryImageDisplay.this.image; 139 visibleRect = MapillaryImageDisplay.this.visibleRect; 140 } 141 if (image == null) 142 return; 143 if (e.getButton() == OPTION_BUTTON) { 144 if (!MapillaryImageDisplay.this.visibleRect.equals(new Rectangle(0, 0, 145 image.getWidth(null), image.getHeight(null)))) 146 // Zooms to 1:1 147 MapillaryImageDisplay.this.visibleRect = new Rectangle(0, 0, 148 image.getWidth(null), image.getHeight(null)); 149 else 150 // Zooms to best fit. 151 MapillaryImageDisplay.this.visibleRect = new Rectangle(0, 152 (image.getHeight(null) - (image.getWidth(null) * getHeight()) 153 / getWidth()) / 2, image.getWidth(null), 154 (image.getWidth(null) * getHeight()) / getWidth()); 155 MapillaryImageDisplay.this.repaint(); 156 return; 157 } else if (e.getButton() != DRAG_BUTTON) 158 return; 159 // Calculate the translation to set the clicked point the center of 160 // the view. 161 Point click = comp2imgCoord(visibleRect, e.getX(), e.getY()); 162 Point center = getCenterImgCoord(visibleRect); 163 visibleRect.x += click.x - center.x; 164 visibleRect.y += click.y - center.y; 165 checkVisibleRectPos(image, visibleRect); 166 synchronized (MapillaryImageDisplay.this) { 167 MapillaryImageDisplay.this.visibleRect = visibleRect; 168 } 169 MapillaryImageDisplay.this.repaint(); 170 } 50 171 51 172 /** 52 * When a selection is done, the rectangle of the selection (in image53 * coordinates)173 * Initialize the dragging, either with button 1 (simple dragging) or button 174 * 3 (selection of a picture part) 54 175 */ 55 private Rectangle selectedRect = null; 56 57 public HyperlinkLabel hyperlink; 58 59 private class ImgDisplayMouseListener implements MouseListener, 60 MouseWheelListener, MouseMotionListener { 61 private boolean mouseIsDragging = false; 62 private long lastTimeForMousePoint = 0L; 63 private Point mousePointInImg = null; 64 65 /** 66 * Zoom in and out, trying to preserve the point of the image that was 67 * under the mouse cursor at the same place 68 */ 69 @Override 70 public void mouseWheelMoved(MouseWheelEvent e) { 71 Image image; 72 Rectangle visibleRect; 73 synchronized (MapillaryImageDisplay.this) { 74 image = MapillaryImageDisplay.this.image; 75 visibleRect = MapillaryImageDisplay.this.visibleRect; 76 } 77 mouseIsDragging = false; 78 selectedRect = null; 79 if (image == null) 80 return; 81 // Calculate the mouse cursor position in image coordinates, so that 82 // we can center the zoom 83 // on that mouse position. 84 // To avoid issues when the user tries to zoom in on the image 85 // borders, this point is not calculated 86 // again if there was less than 1.5seconds since the last event. 87 if (e.getWhen() - lastTimeForMousePoint > 1500 88 || mousePointInImg == null) { 89 lastTimeForMousePoint = e.getWhen(); 90 mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY()); 91 } 92 // Applicate the zoom to the visible rectangle in image coordinates 93 if (e.getWheelRotation() > 0) { 94 visibleRect.width = visibleRect.width * 3 / 2; 95 visibleRect.height = visibleRect.height * 3 / 2; 96 } else { 97 visibleRect.width = visibleRect.width * 2 / 3; 98 visibleRect.height = visibleRect.height * 2 / 3; 99 } 100 // Check that the zoom doesn't exceed 2:1 101 if (visibleRect.width < getSize().width / 2) { 102 visibleRect.width = getSize().width / 2; 103 } 104 if (visibleRect.height < getSize().height / 2) { 105 visibleRect.height = getSize().height / 2; 106 } 107 // Set the same ratio for the visible rectangle and the display area 108 int hFact = visibleRect.height * getSize().width; 109 int wFact = visibleRect.width * getSize().height; 110 if (hFact > wFact) { 111 visibleRect.width = hFact / getSize().height; 112 } else { 113 visibleRect.height = wFact / getSize().width; 114 } 115 // The size of the visible rectangle is limited by the image size. 116 checkVisibleRectSize(image, visibleRect); 117 // Set the position of the visible rectangle, so that the mouse 118 // cursor doesn't move on the image. 119 Rectangle drawRect = calculateDrawImageRectangle(visibleRect); 120 visibleRect.x = mousePointInImg.x 121 + ((drawRect.x - e.getX()) * visibleRect.width) 122 / drawRect.width; 123 visibleRect.y = mousePointInImg.y 124 + ((drawRect.y - e.getY()) * visibleRect.height) 125 / drawRect.height; 126 // The position is also limited by the image size 127 checkVisibleRectPos(image, visibleRect); 128 synchronized (MapillaryImageDisplay.this) { 129 MapillaryImageDisplay.this.visibleRect = visibleRect; 130 } 131 MapillaryImageDisplay.this.repaint(); 132 } 133 134 /** Center the display on the point that has been clicked */ 135 @Override 136 public void mouseClicked(MouseEvent e) { 137 // Move the center to the clicked point. 138 Image image; 139 Rectangle visibleRect; 140 synchronized (MapillaryImageDisplay.this) { 141 image = MapillaryImageDisplay.this.image; 142 visibleRect = MapillaryImageDisplay.this.visibleRect; 143 } 144 if (image == null) 145 return; 146 if (e.getButton() == OPTION_BUTTON) { 147 if (!MapillaryImageDisplay.this.visibleRect 148 .equals(new Rectangle(0, 0, image.getWidth(null), image 149 .getHeight(null)))) 150 // Zooms to 1:1 151 MapillaryImageDisplay.this.visibleRect = new Rectangle(0, 152 0, image.getWidth(null), image.getHeight(null)); 153 else 154 // Zooms to best fit. 155 MapillaryImageDisplay.this.visibleRect = new Rectangle( 156 0, 157 (image.getHeight(null) - (image.getWidth(null) * getHeight()) 158 / getWidth()) / 2, image.getWidth(null), 159 (image.getWidth(null) * getHeight()) / getWidth()); 160 MapillaryImageDisplay.this.repaint(); 161 return; 162 } else if (e.getButton() != DRAG_BUTTON) 163 return; 164 // Calculate the translation to set the clicked point the center of 165 // the view. 166 Point click = comp2imgCoord(visibleRect, e.getX(), e.getY()); 167 Point center = getCenterImgCoord(visibleRect); 168 visibleRect.x += click.x - center.x; 169 visibleRect.y += click.y - center.y; 170 checkVisibleRectPos(image, visibleRect); 171 synchronized (MapillaryImageDisplay.this) { 172 MapillaryImageDisplay.this.visibleRect = visibleRect; 173 } 174 MapillaryImageDisplay.this.repaint(); 175 } 176 177 /** 178 * Initialize the dragging, either with button 1 (simple dragging) or 179 * button 3 (selection of a picture part) 180 */ 181 @Override 182 public void mousePressed(MouseEvent e) { 183 if (image == null) { 184 mouseIsDragging = false; 185 selectedRect = null; 186 return; 187 } 188 Image image; 189 Rectangle visibleRect; 190 synchronized (MapillaryImageDisplay.this) { 191 image = MapillaryImageDisplay.this.image; 192 visibleRect = MapillaryImageDisplay.this.visibleRect; 193 } 194 if (image == null) 195 return; 196 if (e.getButton() == DRAG_BUTTON) { 197 mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY()); 198 mouseIsDragging = true; 199 selectedRect = null; 200 } else if (e.getButton() == ZOOM_BUTTON) { 201 mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY()); 202 checkPointInVisibleRect(mousePointInImg, visibleRect); 203 mouseIsDragging = false; 204 selectedRect = new Rectangle(mousePointInImg.x, 205 mousePointInImg.y, 0, 0); 206 MapillaryImageDisplay.this.repaint(); 207 } else { 208 mouseIsDragging = false; 209 selectedRect = null; 210 } 211 } 212 213 @Override 214 public void mouseDragged(MouseEvent e) { 215 if (!mouseIsDragging && selectedRect == null) 216 return; 217 Image image; 218 Rectangle visibleRect; 219 synchronized (MapillaryImageDisplay.this) { 220 image = MapillaryImageDisplay.this.image; 221 visibleRect = MapillaryImageDisplay.this.visibleRect; 222 } 223 if (image == null) { 224 mouseIsDragging = false; 225 selectedRect = null; 226 return; 227 } 228 if (mouseIsDragging) { 229 Point p = comp2imgCoord(visibleRect, e.getX(), e.getY()); 230 visibleRect.x += mousePointInImg.x - p.x; 231 visibleRect.y += mousePointInImg.y - p.y; 232 checkVisibleRectPos(image, visibleRect); 233 synchronized (MapillaryImageDisplay.this) { 234 MapillaryImageDisplay.this.visibleRect = visibleRect; 235 } 236 MapillaryImageDisplay.this.repaint(); 237 } else if (selectedRect != null) { 238 Point p = comp2imgCoord(visibleRect, e.getX(), e.getY()); 239 checkPointInVisibleRect(p, visibleRect); 240 Rectangle rect = new Rectangle(p.x < mousePointInImg.x ? p.x 241 : mousePointInImg.x, p.y < mousePointInImg.y ? p.y 242 : mousePointInImg.y, 243 p.x < mousePointInImg.x ? mousePointInImg.x - p.x : p.x 244 - mousePointInImg.x, 245 p.y < mousePointInImg.y ? mousePointInImg.y - p.y : p.y 246 - mousePointInImg.y); 247 checkVisibleRectSize(image, rect); 248 checkVisibleRectPos(image, rect); 249 MapillaryImageDisplay.this.selectedRect = rect; 250 MapillaryImageDisplay.this.repaint(); 251 } 252 } 253 254 @Override 255 public void mouseReleased(MouseEvent e) { 256 if (!mouseIsDragging && selectedRect == null) 257 return; 258 Image image; 259 synchronized (MapillaryImageDisplay.this) { 260 image = MapillaryImageDisplay.this.image; 261 } 262 if (image == null) { 263 mouseIsDragging = false; 264 selectedRect = null; 265 return; 266 } 267 if (mouseIsDragging) { 268 mouseIsDragging = false; 269 } else if (selectedRect != null) { 270 int oldWidth = selectedRect.width; 271 int oldHeight = selectedRect.height; 272 // Check that the zoom doesn't exceed 2:1 273 if (selectedRect.width < getSize().width / 2) { 274 selectedRect.width = getSize().width / 2; 275 } 276 if (selectedRect.height < getSize().height / 2) { 277 selectedRect.height = getSize().height / 2; 278 } 279 // Set the same ratio for the visible rectangle and the display 280 // area 281 int hFact = selectedRect.height * getSize().width; 282 int wFact = selectedRect.width * getSize().height; 283 if (hFact > wFact) { 284 selectedRect.width = hFact / getSize().height; 285 } else { 286 selectedRect.height = wFact / getSize().width; 287 } 288 // Keep the center of the selection 289 if (selectedRect.width != oldWidth) { 290 selectedRect.x -= (selectedRect.width - oldWidth) / 2; 291 } 292 if (selectedRect.height != oldHeight) { 293 selectedRect.y -= (selectedRect.height - oldHeight) / 2; 294 } 295 checkVisibleRectSize(image, selectedRect); 296 checkVisibleRectPos(image, selectedRect); 297 synchronized (MapillaryImageDisplay.this) { 298 MapillaryImageDisplay.this.visibleRect = selectedRect; 299 } 300 selectedRect = null; 301 MapillaryImageDisplay.this.repaint(); 302 } 303 } 304 305 @Override 306 public void mouseEntered(MouseEvent e) { 307 } 308 309 @Override 310 public void mouseExited(MouseEvent e) { 311 } 312 313 @Override 314 public void mouseMoved(MouseEvent e) { 315 } 316 317 private void checkPointInVisibleRect(Point p, Rectangle visibleRect) { 318 if (p.x < visibleRect.x) { 319 p.x = visibleRect.x; 320 } 321 if (p.x > visibleRect.x + visibleRect.width) { 322 p.x = visibleRect.x + visibleRect.width; 323 } 324 if (p.y < visibleRect.y) { 325 p.y = visibleRect.y; 326 } 327 if (p.y > visibleRect.y + visibleRect.height) { 328 p.y = visibleRect.y + visibleRect.height; 329 } 330 } 331 } 332 333 public MapillaryImageDisplay() { 334 ImgDisplayMouseListener mouseListener = new ImgDisplayMouseListener(); 335 addMouseListener(mouseListener); 336 addMouseWheelListener(mouseListener); 337 addMouseMotionListener(mouseListener); 338 this.setLayout(new BorderLayout()); 339 JPanel southPanel = new JPanel(); 340 southPanel.setLayout(new BorderLayout()); 341 hyperlink = new HyperlinkLabel(); 342 southPanel.add(hyperlink, BorderLayout.EAST); 343 southPanel.setOpaque(false); 344 345 add(southPanel, BorderLayout.SOUTH); 346 } 347 348 /** 349 * Sets a new picture to be displayed. 350 * 351 * @param image 352 */ 353 public void setImage(BufferedImage image) { 354 synchronized (this) { 355 this.image = image; 356 selectedRect = null; 357 if (image != null) 358 this.visibleRect = new Rectangle(0, 0, image.getWidth(null), 359 image.getHeight(null)); 360 } 361 repaint(); 362 } 363 364 /** 365 * Returns the picture that is being displayerd 366 * 367 * @return 368 */ 369 public BufferedImage getImage() { 370 return this.image; 371 } 372 373 /** 374 * Paints the visible part of the picture. 375 */ 376 public void paintComponent(Graphics g) { 377 Image image; 378 Rectangle visibleRect; 379 synchronized (this) { 380 image = this.image; 381 visibleRect = this.visibleRect; 382 } 383 if (image == null) { 384 g.setColor(Color.black); 385 String noImageStr = tr("No image"); 386 Rectangle2D noImageSize = g.getFontMetrics(g.getFont()) 387 .getStringBounds(noImageStr, g); 388 Dimension size = getSize(); 389 g.drawString(noImageStr, 390 (int) ((size.width - noImageSize.getWidth()) / 2), 391 (int) ((size.height - noImageSize.getHeight()) / 2)); 176 @Override 177 public void mousePressed(MouseEvent e) { 178 if (image == null) { 179 mouseIsDragging = false; 180 selectedRect = null; 181 return; 182 } 183 Image image; 184 Rectangle visibleRect; 185 synchronized (MapillaryImageDisplay.this) { 186 image = MapillaryImageDisplay.this.image; 187 visibleRect = MapillaryImageDisplay.this.visibleRect; 188 } 189 if (image == null) 190 return; 191 if (e.getButton() == DRAG_BUTTON) { 192 mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY()); 193 mouseIsDragging = true; 194 selectedRect = null; 195 } else if (e.getButton() == ZOOM_BUTTON) { 196 mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY()); 197 checkPointInVisibleRect(mousePointInImg, visibleRect); 198 mouseIsDragging = false; 199 selectedRect = new Rectangle(mousePointInImg.x, mousePointInImg.y, 0, 0); 200 MapillaryImageDisplay.this.repaint(); 201 } else { 202 mouseIsDragging = false; 203 selectedRect = null; 204 } 205 } 206 207 @Override 208 public void mouseDragged(MouseEvent e) { 209 if (!mouseIsDragging && selectedRect == null) 210 return; 211 Image image; 212 Rectangle visibleRect; 213 synchronized (MapillaryImageDisplay.this) { 214 image = MapillaryImageDisplay.this.image; 215 visibleRect = MapillaryImageDisplay.this.visibleRect; 216 } 217 if (image == null) { 218 mouseIsDragging = false; 219 selectedRect = null; 220 return; 221 } 222 if (mouseIsDragging) { 223 Point p = comp2imgCoord(visibleRect, e.getX(), e.getY()); 224 visibleRect.x += mousePointInImg.x - p.x; 225 visibleRect.y += mousePointInImg.y - p.y; 226 checkVisibleRectPos(image, visibleRect); 227 synchronized (MapillaryImageDisplay.this) { 228 MapillaryImageDisplay.this.visibleRect = visibleRect; 229 } 230 MapillaryImageDisplay.this.repaint(); 231 } else if (selectedRect != null) { 232 Point p = comp2imgCoord(visibleRect, e.getX(), e.getY()); 233 checkPointInVisibleRect(p, visibleRect); 234 Rectangle rect = new Rectangle(p.x < mousePointInImg.x ? p.x 235 : mousePointInImg.x, p.y < mousePointInImg.y ? p.y 236 : mousePointInImg.y, p.x < mousePointInImg.x ? mousePointInImg.x 237 - p.x : p.x - mousePointInImg.x, 238 p.y < mousePointInImg.y ? mousePointInImg.y - p.y : p.y 239 - mousePointInImg.y); 240 checkVisibleRectSize(image, rect); 241 checkVisibleRectPos(image, rect); 242 MapillaryImageDisplay.this.selectedRect = rect; 243 MapillaryImageDisplay.this.repaint(); 244 } 245 } 246 247 @Override 248 public void mouseReleased(MouseEvent e) { 249 if (!mouseIsDragging && selectedRect == null) 250 return; 251 Image image; 252 synchronized (MapillaryImageDisplay.this) { 253 image = MapillaryImageDisplay.this.image; 254 } 255 if (image == null) { 256 mouseIsDragging = false; 257 selectedRect = null; 258 return; 259 } 260 if (mouseIsDragging) { 261 mouseIsDragging = false; 262 } else if (selectedRect != null) { 263 int oldWidth = selectedRect.width; 264 int oldHeight = selectedRect.height; 265 // Check that the zoom doesn't exceed 2:1 266 if (selectedRect.width < getSize().width / 2) { 267 selectedRect.width = getSize().width / 2; 268 } 269 if (selectedRect.height < getSize().height / 2) { 270 selectedRect.height = getSize().height / 2; 271 } 272 // Set the same ratio for the visible rectangle and the display 273 // area 274 int hFact = selectedRect.height * getSize().width; 275 int wFact = selectedRect.width * getSize().height; 276 if (hFact > wFact) { 277 selectedRect.width = hFact / getSize().height; 392 278 } else { 393 Rectangle target = calculateDrawImageRectangle(visibleRect); 394 g.drawImage(image, target.x, target.y, target.x + target.width, 395 target.y + target.height, visibleRect.x, visibleRect.y, 396 visibleRect.x + visibleRect.width, visibleRect.y 397 + visibleRect.height, null); 398 if (selectedRect != null) { 399 Point topLeft = img2compCoord(visibleRect, selectedRect.x, 400 selectedRect.y); 401 Point bottomRight = img2compCoord(visibleRect, selectedRect.x 402 + selectedRect.width, selectedRect.y 403 + selectedRect.height); 404 g.setColor(new Color(128, 128, 128, 180)); 405 g.fillRect(target.x, target.y, target.width, topLeft.y 406 - target.y); 407 g.fillRect(target.x, target.y, topLeft.x - target.x, 408 target.height); 409 g.fillRect(bottomRight.x, target.y, target.x + target.width 410 - bottomRight.x, target.height); 411 g.fillRect(target.x, bottomRight.y, target.width, target.y 412 + target.height - bottomRight.y); 413 g.setColor(Color.black); 414 g.drawRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x, 415 bottomRight.y - topLeft.y); 416 } 417 } 418 } 419 420 private final Point img2compCoord(Rectangle visibleRect, int xImg, int yImg) { 421 Rectangle drawRect = calculateDrawImageRectangle(visibleRect); 422 return new Point(drawRect.x + ((xImg - visibleRect.x) * drawRect.width) 423 / visibleRect.width, drawRect.y 424 + ((yImg - visibleRect.y) * drawRect.height) 425 / visibleRect.height); 426 } 427 428 private final Point comp2imgCoord(Rectangle visibleRect, int xComp, 429 int yComp) { 430 Rectangle drawRect = calculateDrawImageRectangle(visibleRect); 431 return new Point(visibleRect.x 432 + ((xComp - drawRect.x) * visibleRect.width) / drawRect.width, 433 visibleRect.y + ((yComp - drawRect.y) * visibleRect.height) 434 / drawRect.height); 435 } 436 437 private final Point getCenterImgCoord(Rectangle visibleRect) { 438 return new Point(visibleRect.x + visibleRect.width / 2, visibleRect.y 439 + visibleRect.height / 2); 440 } 441 442 private Rectangle calculateDrawImageRectangle(Rectangle visibleRect) { 443 return calculateDrawImageRectangle(visibleRect, new Rectangle(0, 0, 444 getSize().width, getSize().height)); 445 } 446 447 /** 448 * calculateDrawImageRectangle 449 * 450 * @param imgRect 451 * the part of the image that should be drawn (in image 452 * coordinates) 453 * @param compRect 454 * the part of the component where the image should be drawn (in 455 * component coordinates) 456 * @return the part of compRect with the same width/height ratio as the 457 * image 458 */ 459 static Rectangle calculateDrawImageRectangle(Rectangle imgRect, 460 Rectangle compRect) { 461 int x, y, w, h; 462 x = 0; 463 y = 0; 464 w = compRect.width; 465 h = compRect.height; 466 int wFact = w * imgRect.height; 467 int hFact = h * imgRect.width; 468 if (wFact != hFact) { 469 if (wFact > hFact) { 470 w = hFact / imgRect.height; 471 x = (compRect.width - w) / 2; 472 } else { 473 h = wFact / imgRect.width; 474 y = (compRect.height - h) / 2; 475 } 476 } 477 return new Rectangle(x + compRect.x, y + compRect.y, w, h); 478 } 479 480 /** 481 * Zooms to 1:1 and, if it is already in 1:1, to best fit. 482 */ 483 public void zoomBestFitOrOne() { 484 Image image; 485 Rectangle visibleRect; 486 synchronized (this) { 487 image = MapillaryImageDisplay.this.image; 488 visibleRect = MapillaryImageDisplay.this.visibleRect; 489 } 490 if (image == null) 491 return; 492 if (visibleRect.width != image.getWidth(null) 493 || visibleRect.height != image.getHeight(null)) { 494 // The display is not at best fit. => Zoom to best fit 495 visibleRect = new Rectangle(0, 0, image.getWidth(null), 496 image.getHeight(null)); 497 } else { 498 // The display is at best fit => zoom to 1:1 499 Point center = getCenterImgCoord(visibleRect); 500 visibleRect = new Rectangle(center.x - getWidth() / 2, center.y 501 - getHeight() / 2, getWidth(), getHeight()); 502 checkVisibleRectPos(image, visibleRect); 503 } 504 synchronized (this) { 505 this.visibleRect = visibleRect; 506 } 507 repaint(); 508 } 509 510 private final void checkVisibleRectPos(Image image, Rectangle visibleRect) { 511 if (visibleRect.x < 0) { 512 visibleRect.x = 0; 513 } 514 if (visibleRect.y < 0) { 515 visibleRect.y = 0; 516 } 517 if (visibleRect.x + visibleRect.width > image.getWidth(null)) { 518 visibleRect.x = image.getWidth(null) - visibleRect.width; 519 } 520 if (visibleRect.y + visibleRect.height > image.getHeight(null)) { 521 visibleRect.y = image.getHeight(null) - visibleRect.height; 522 } 523 } 524 525 private void checkVisibleRectSize(Image image, Rectangle visibleRect) { 526 if (visibleRect.width > image.getWidth(null)) { 527 visibleRect.width = image.getWidth(null); 528 } 529 if (visibleRect.height > image.getHeight(null)) { 530 visibleRect.height = image.getHeight(null); 531 } 532 } 279 selectedRect.height = wFact / getSize().width; 280 } 281 // Keep the center of the selection 282 if (selectedRect.width != oldWidth) { 283 selectedRect.x -= (selectedRect.width - oldWidth) / 2; 284 } 285 if (selectedRect.height != oldHeight) { 286 selectedRect.y -= (selectedRect.height - oldHeight) / 2; 287 } 288 checkVisibleRectSize(image, selectedRect); 289 checkVisibleRectPos(image, selectedRect); 290 synchronized (MapillaryImageDisplay.this) { 291 MapillaryImageDisplay.this.visibleRect = selectedRect; 292 } 293 selectedRect = null; 294 MapillaryImageDisplay.this.repaint(); 295 } 296 } 297 298 @Override 299 public void mouseEntered(MouseEvent e) { 300 } 301 302 @Override 303 public void mouseExited(MouseEvent e) { 304 } 305 306 @Override 307 public void mouseMoved(MouseEvent e) { 308 } 309 310 private void checkPointInVisibleRect(Point p, Rectangle visibleRect) { 311 if (p.x < visibleRect.x) { 312 p.x = visibleRect.x; 313 } 314 if (p.x > visibleRect.x + visibleRect.width) { 315 p.x = visibleRect.x + visibleRect.width; 316 } 317 if (p.y < visibleRect.y) { 318 p.y = visibleRect.y; 319 } 320 if (p.y > visibleRect.y + visibleRect.height) { 321 p.y = visibleRect.y + visibleRect.height; 322 } 323 } 324 } 325 326 public MapillaryImageDisplay() { 327 ImgDisplayMouseListener mouseListener = new ImgDisplayMouseListener(); 328 addMouseListener(mouseListener); 329 addMouseWheelListener(mouseListener); 330 addMouseMotionListener(mouseListener); 331 this.setLayout(new BorderLayout()); 332 JPanel southPanel = new JPanel(); 333 southPanel.setLayout(new BorderLayout()); 334 hyperlink = new HyperlinkLabel(); 335 southPanel.add(hyperlink, BorderLayout.EAST); 336 southPanel.setOpaque(false); 337 338 add(southPanel, BorderLayout.SOUTH); 339 } 340 341 /** 342 * Sets a new picture to be displayed. 343 * 344 * @param image 345 */ 346 public void setImage(BufferedImage image) { 347 synchronized (this) { 348 this.image = image; 349 selectedRect = null; 350 if (image != null) 351 this.visibleRect = new Rectangle(0, 0, image.getWidth(null), 352 image.getHeight(null)); 353 } 354 repaint(); 355 } 356 357 /** 358 * Returns the picture that is being displayerd 359 * 360 * @return 361 */ 362 public BufferedImage getImage() { 363 return this.image; 364 } 365 366 /** 367 * Paints the visible part of the picture. 368 */ 369 public void paintComponent(Graphics g) { 370 Image image; 371 Rectangle visibleRect; 372 synchronized (this) { 373 image = this.image; 374 visibleRect = this.visibleRect; 375 } 376 if (image == null) { 377 g.setColor(Color.black); 378 String noImageStr = tr("No image"); 379 Rectangle2D noImageSize = g.getFontMetrics(g.getFont()).getStringBounds( 380 noImageStr, g); 381 Dimension size = getSize(); 382 g.drawString(noImageStr, 383 (int) ((size.width - noImageSize.getWidth()) / 2), 384 (int) ((size.height - noImageSize.getHeight()) / 2)); 385 } else { 386 Rectangle target = calculateDrawImageRectangle(visibleRect); 387 g.drawImage(image, target.x, target.y, target.x + target.width, target.y 388 + target.height, visibleRect.x, visibleRect.y, visibleRect.x 389 + visibleRect.width, visibleRect.y + visibleRect.height, null); 390 if (selectedRect != null) { 391 Point topLeft = img2compCoord(visibleRect, selectedRect.x, 392 selectedRect.y); 393 Point bottomRight = img2compCoord(visibleRect, selectedRect.x 394 + selectedRect.width, selectedRect.y + selectedRect.height); 395 g.setColor(new Color(128, 128, 128, 180)); 396 g.fillRect(target.x, target.y, target.width, topLeft.y - target.y); 397 g.fillRect(target.x, target.y, topLeft.x - target.x, target.height); 398 g.fillRect(bottomRight.x, target.y, target.x + target.width 399 - bottomRight.x, target.height); 400 g.fillRect(target.x, bottomRight.y, target.width, target.y 401 + target.height - bottomRight.y); 402 g.setColor(Color.black); 403 g.drawRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x, 404 bottomRight.y - topLeft.y); 405 } 406 } 407 } 408 409 private final Point img2compCoord(Rectangle visibleRect, int xImg, int yImg) { 410 Rectangle drawRect = calculateDrawImageRectangle(visibleRect); 411 return new Point(drawRect.x + ((xImg - visibleRect.x) * drawRect.width) 412 / visibleRect.width, drawRect.y 413 + ((yImg - visibleRect.y) * drawRect.height) / visibleRect.height); 414 } 415 416 private final Point comp2imgCoord(Rectangle visibleRect, int xComp, int yComp) { 417 Rectangle drawRect = calculateDrawImageRectangle(visibleRect); 418 return new Point(visibleRect.x + ((xComp - drawRect.x) * visibleRect.width) 419 / drawRect.width, visibleRect.y 420 + ((yComp - drawRect.y) * visibleRect.height) / drawRect.height); 421 } 422 423 private final Point getCenterImgCoord(Rectangle visibleRect) { 424 return new Point(visibleRect.x + visibleRect.width / 2, visibleRect.y 425 + visibleRect.height / 2); 426 } 427 428 private Rectangle calculateDrawImageRectangle(Rectangle visibleRect) { 429 return calculateDrawImageRectangle(visibleRect, new Rectangle(0, 0, 430 getSize().width, getSize().height)); 431 } 432 433 /** 434 * calculateDrawImageRectangle 435 * 436 * @param imgRect 437 * the part of the image that should be drawn (in image coordinates) 438 * @param compRect 439 * the part of the component where the image should be drawn (in 440 * component coordinates) 441 * @return the part of compRect with the same width/height ratio as the image 442 */ 443 static Rectangle calculateDrawImageRectangle(Rectangle imgRect, 444 Rectangle compRect) { 445 int x, y, w, h; 446 x = 0; 447 y = 0; 448 w = compRect.width; 449 h = compRect.height; 450 int wFact = w * imgRect.height; 451 int hFact = h * imgRect.width; 452 if (wFact != hFact) { 453 if (wFact > hFact) { 454 w = hFact / imgRect.height; 455 x = (compRect.width - w) / 2; 456 } else { 457 h = wFact / imgRect.width; 458 y = (compRect.height - h) / 2; 459 } 460 } 461 return new Rectangle(x + compRect.x, y + compRect.y, w, h); 462 } 463 464 /** 465 * Zooms to 1:1 and, if it is already in 1:1, to best fit. 466 */ 467 public void zoomBestFitOrOne() { 468 Image image; 469 Rectangle visibleRect; 470 synchronized (this) { 471 image = MapillaryImageDisplay.this.image; 472 visibleRect = MapillaryImageDisplay.this.visibleRect; 473 } 474 if (image == null) 475 return; 476 if (visibleRect.width != image.getWidth(null) 477 || visibleRect.height != image.getHeight(null)) { 478 // The display is not at best fit. => Zoom to best fit 479 visibleRect = new Rectangle(0, 0, image.getWidth(null), 480 image.getHeight(null)); 481 } else { 482 // The display is at best fit => zoom to 1:1 483 Point center = getCenterImgCoord(visibleRect); 484 visibleRect = new Rectangle(center.x - getWidth() / 2, center.y 485 - getHeight() / 2, getWidth(), getHeight()); 486 checkVisibleRectPos(image, visibleRect); 487 } 488 synchronized (this) { 489 this.visibleRect = visibleRect; 490 } 491 repaint(); 492 } 493 494 private final void checkVisibleRectPos(Image image, Rectangle visibleRect) { 495 if (visibleRect.x < 0) { 496 visibleRect.x = 0; 497 } 498 if (visibleRect.y < 0) { 499 visibleRect.y = 0; 500 } 501 if (visibleRect.x + visibleRect.width > image.getWidth(null)) { 502 visibleRect.x = image.getWidth(null) - visibleRect.width; 503 } 504 if (visibleRect.y + visibleRect.height > image.getHeight(null)) { 505 visibleRect.y = image.getHeight(null) - visibleRect.height; 506 } 507 } 508 509 private void checkVisibleRectSize(Image image, Rectangle visibleRect) { 510 if (visibleRect.width > image.getWidth(null)) { 511 visibleRect.width = image.getWidth(null); 512 } 513 if (visibleRect.height > image.getHeight(null)) { 514 visibleRect.height = image.getHeight(null); 515 } 516 } 533 517 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryMainDialog.java
r31334 r31350 45 45 */ 46 46 public class MapillaryMainDialog extends ToggleDialog implements 47 ICachedLoaderListener, MapillaryDataListener { 48 49 public final static String BASE_TITLE = "Mapillary picture"; 50 51 public static MapillaryMainDialog INSTANCE; 52 53 public volatile MapillaryAbstractImage image; 54 55 public final SideButton nextButton = new SideButton(new nextPictureAction()); 56 public final SideButton previousButton = new SideButton( 57 new previousPictureAction()); 58 public final SideButton redButton = new SideButton(new redAction()); 59 public final SideButton blueButton = new SideButton(new blueAction()); 60 61 private JPanel buttonsPanel; 62 63 public MapillaryImageDisplay mapillaryImageDisplay; 64 65 private MapillaryCache imageCache; 66 private MapillaryCache thumbnailCache; 67 68 public MapillaryMainDialog() { 69 super(tr(BASE_TITLE), "mapillary.png", tr("Open Mapillary window"), 70 Shortcut.registerShortcut(tr("Mapillary dialog"), 71 tr("Open Mapillary main dialog"), KeyEvent.VK_M, 72 Shortcut.NONE), 200, false, 73 MapillaryPreferenceSetting.class); 74 MapillaryData.getInstance().addListener(this); 75 addShortcuts(); 76 mapillaryImageDisplay = new MapillaryImageDisplay(); 77 78 blueButton.setForeground(Color.BLUE); 79 redButton.setForeground(Color.RED); 80 81 createLayout( 82 mapillaryImageDisplay, 83 Arrays.asList(new SideButton[] { blueButton, previousButton, 84 nextButton, redButton }), 85 Main.pref.getBoolean("mapillary.reverse-buttons")); 47 ICachedLoaderListener, MapillaryDataListener { 48 49 public final static String BASE_TITLE = "Mapillary picture"; 50 51 public static MapillaryMainDialog INSTANCE; 52 53 public volatile MapillaryAbstractImage image; 54 55 public final SideButton nextButton = new SideButton(new nextPictureAction()); 56 public final SideButton previousButton = new SideButton( 57 new previousPictureAction()); 58 public final SideButton redButton = new SideButton(new redAction()); 59 public final SideButton blueButton = new SideButton(new blueAction()); 60 61 private JPanel buttonsPanel; 62 63 public MapillaryImageDisplay mapillaryImageDisplay; 64 65 private MapillaryCache imageCache; 66 private MapillaryCache thumbnailCache; 67 68 public MapillaryMainDialog() { 69 super(tr(BASE_TITLE), "mapillary.png", tr("Open Mapillary window"), 70 Shortcut.registerShortcut(tr("Mapillary dialog"), 71 tr("Open Mapillary main dialog"), KeyEvent.VK_M, Shortcut.NONE), 72 200, false, MapillaryPreferenceSetting.class); 73 MapillaryData.getInstance().addListener(this); 74 addShortcuts(); 75 mapillaryImageDisplay = new MapillaryImageDisplay(); 76 77 blueButton.setForeground(Color.BLUE); 78 redButton.setForeground(Color.RED); 79 80 createLayout( 81 mapillaryImageDisplay, 82 Arrays.asList(new SideButton[] { blueButton, previousButton, 83 nextButton, redButton }), 84 Main.pref.getBoolean("mapillary.reverse-buttons")); 85 disableAllButtons(); 86 87 } 88 89 /** 90 * Adds the shortcuts to the buttons. 91 */ 92 private void addShortcuts() { 93 nextButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( 94 KeyStroke.getKeyStroke("PAGE_DOWN"), "next"); 95 nextButton.getActionMap().put("next", new nextPictureAction()); 96 previousButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( 97 KeyStroke.getKeyStroke("PAGE_UP"), "previous"); 98 previousButton.getActionMap().put("previous", new previousPictureAction()); 99 blueButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( 100 KeyStroke.getKeyStroke("control PAGE_UP"), "blue"); 101 blueButton.getActionMap().put("blue", new blueAction()); 102 redButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( 103 KeyStroke.getKeyStroke("control PAGE_DOWN"), "red"); 104 redButton.getActionMap().put("red", new redAction()); 105 } 106 107 public static MapillaryMainDialog getInstance() { 108 if (INSTANCE == null) 109 INSTANCE = new MapillaryMainDialog(); 110 return INSTANCE; 111 } 112 113 public static void destroyInstance() { 114 INSTANCE = null; 115 } 116 117 /** 118 * Downloads the image of the selected MapillaryImage and sets in the 119 * MapillaryImageDisplay object. 120 */ 121 public synchronized void updateImage() { 122 if (!SwingUtilities.isEventDispatchThread()) { 123 SwingUtilities.invokeLater(new Runnable() { 124 @Override 125 public void run() { 126 updateImage(); 127 } 128 }); 129 } else { 130 if (MapillaryLayer.INSTANCE == null) { 131 return; 132 } 133 if (this.image == null) { 134 mapillaryImageDisplay.setImage(null); 135 setTitle(tr(BASE_TITLE)); 86 136 disableAllButtons(); 87 88 } 89 90 /** 91 * Adds the shortcuts to the buttons. 92 */ 93 private void addShortcuts() { 94 nextButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( 95 KeyStroke.getKeyStroke("PAGE_DOWN"), "next"); 96 nextButton.getActionMap().put("next", new nextPictureAction()); 97 previousButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( 98 KeyStroke.getKeyStroke("PAGE_UP"), "previous"); 99 previousButton.getActionMap().put("previous", 100 new previousPictureAction()); 101 blueButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( 102 KeyStroke.getKeyStroke("control PAGE_UP"), "blue"); 103 blueButton.getActionMap().put("blue", new blueAction()); 104 redButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( 105 KeyStroke.getKeyStroke("control PAGE_DOWN"), "red"); 106 redButton.getActionMap().put("red", new redAction()); 107 } 108 109 public static MapillaryMainDialog getInstance() { 110 if (INSTANCE == null) 111 INSTANCE = new MapillaryMainDialog(); 112 return INSTANCE; 113 } 114 115 public static void destroyInstance() { 116 INSTANCE = null; 117 } 118 119 /** 120 * Downloads the image of the selected MapillaryImage and sets in the 121 * MapillaryImageDisplay object. 122 */ 123 public synchronized void updateImage() { 124 if (!SwingUtilities.isEventDispatchThread()) { 125 SwingUtilities.invokeLater(new Runnable() { 126 @Override 127 public void run() { 128 updateImage(); 129 } 130 }); 131 } else { 132 if (MapillaryLayer.INSTANCE == null) { 133 return; 137 return; 138 } 139 if (image instanceof MapillaryImage) { 140 mapillaryImageDisplay.hyperlink.setVisible(true); 141 MapillaryImage mapillaryImage = (MapillaryImage) this.image; 142 updateTitle(); 143 // Enables/disables next/previous buttons 144 this.nextButton.setEnabled(false); 145 this.previousButton.setEnabled(false); 146 if (((MapillaryImage) image).getSequence() != null) { 147 MapillaryImage tempImage = (MapillaryImage) image; 148 while (tempImage.next() != null) { 149 tempImage = tempImage.next(); 150 if (tempImage.isVisible()) { 151 this.nextButton.setEnabled(true); 152 break; 134 153 } 135 if (this.image == null) { 136 mapillaryImageDisplay.setImage(null); 137 setTitle(tr(BASE_TITLE)); 138 disableAllButtons(); 139 return; 154 } 155 } 156 if (((MapillaryImage) image).getSequence() != null) { 157 MapillaryImage tempImage = (MapillaryImage) image; 158 while (tempImage.previous() != null) { 159 tempImage = tempImage.previous(); 160 if (tempImage.isVisible()) { 161 this.previousButton.setEnabled(true); 162 break; 140 163 } 141 if (image instanceof MapillaryImage) { 142 mapillaryImageDisplay.hyperlink.setVisible(true); 143 MapillaryImage mapillaryImage = (MapillaryImage) this.image; 144 updateTitle(); 145 // Enables/disables next/previous buttons 146 this.nextButton.setEnabled(false); 147 this.previousButton.setEnabled(false); 148 if (((MapillaryImage) image).getSequence() != null) { 149 MapillaryImage tempImage = (MapillaryImage) image; 150 while (tempImage.next() != null) { 151 tempImage = tempImage.next(); 152 if (tempImage.isVisible()) { 153 this.nextButton.setEnabled(true); 154 break; 155 } 156 } 157 } 158 if (((MapillaryImage) image).getSequence() != null) { 159 MapillaryImage tempImage = (MapillaryImage) image; 160 while (tempImage.previous() != null) { 161 tempImage = tempImage.previous(); 162 if (tempImage.isVisible()) { 163 this.previousButton.setEnabled(true); 164 break; 165 } 166 } 167 } 168 169 mapillaryImageDisplay.hyperlink.setURL(mapillaryImage.getKey()); 170 // Downloads the thumbnail. 171 this.mapillaryImageDisplay.setImage(null); 172 if (thumbnailCache != null) 173 thumbnailCache.cancelOutstandingTasks(); 174 thumbnailCache = new MapillaryCache(mapillaryImage.getKey(), 175 MapillaryCache.Type.THUMBNAIL); 176 thumbnailCache.submit(this, false); 177 178 // Downloads the full resolution image. 179 if (imageCache != null) 180 imageCache.cancelOutstandingTasks(); 181 imageCache = new MapillaryCache(mapillaryImage.getKey(), 182 MapillaryCache.Type.FULL_IMAGE); 183 imageCache.submit(this, false); 184 } else if (image instanceof MapillaryImportedImage) { 185 mapillaryImageDisplay.hyperlink.setVisible(false); 186 this.nextButton.setEnabled(false); 187 this.previousButton.setEnabled(false); 188 MapillaryImportedImage mapillaryImage = (MapillaryImportedImage) this.image; 189 try { 190 mapillaryImageDisplay.setImage(mapillaryImage.getImage()); 191 } catch (IOException e) { 192 Main.error(e); 193 } 194 mapillaryImageDisplay.hyperlink.setURL(null); 195 } 196 } 197 } 198 199 private void disableAllButtons() { 200 nextButton.setEnabled(false); 201 previousButton.setEnabled(false); 202 blueButton.setEnabled(false); 203 redButton.setEnabled(false); 164 } 165 } 166 167 mapillaryImageDisplay.hyperlink.setURL(mapillaryImage.getKey()); 168 // Downloads the thumbnail. 169 this.mapillaryImageDisplay.setImage(null); 170 if (thumbnailCache != null) 171 thumbnailCache.cancelOutstandingTasks(); 172 thumbnailCache = new MapillaryCache(mapillaryImage.getKey(), 173 MapillaryCache.Type.THUMBNAIL); 174 thumbnailCache.submit(this, false); 175 176 // Downloads the full resolution image. 177 if (imageCache != null) 178 imageCache.cancelOutstandingTasks(); 179 imageCache = new MapillaryCache(mapillaryImage.getKey(), 180 MapillaryCache.Type.FULL_IMAGE); 181 imageCache.submit(this, false); 182 } else if (image instanceof MapillaryImportedImage) { 204 183 mapillaryImageDisplay.hyperlink.setVisible(false); 205 } 206 207 /** 208 * Sets a new MapillaryImage to be shown. 209 * 210 * @param image 211 */ 212 public synchronized void setImage(MapillaryAbstractImage image) { 213 this.image = image; 214 } 215 216 /** 217 * Updates the title of the dialog. 218 */ 219 public synchronized void updateTitle() { 220 if (!SwingUtilities.isEventDispatchThread()) { 221 SwingUtilities.invokeLater(new Runnable() { 222 @Override 223 public void run() { 224 updateTitle(); 225 } 226 }); 227 } else { 228 if (this.image != null) { 229 MapillaryImage mapillaryImage = (MapillaryImage) this.image; 230 String title = tr(BASE_TITLE); 231 if (mapillaryImage.getUser() != null) 232 title += " -- " + mapillaryImage.getUser(); 233 if (mapillaryImage.getCapturedAt() != 0) 234 title += " -- " + mapillaryImage.getDate(); 235 setTitle(title); 236 } 237 } 238 } 239 240 /** 241 * Returns the MapillaryImage objects which is being shown. 242 * 243 * @return 244 */ 245 public synchronized MapillaryAbstractImage getImage() { 246 return this.image; 247 } 248 249 /** 250 * Action class form the next image button. 251 * 252 * @author Jorge 253 * 254 */ 255 class nextPictureAction extends AbstractAction { 256 public nextPictureAction() { 257 putValue(NAME, tr("Next picture")); 258 putValue(SHORT_DESCRIPTION, 259 tr("Shows the next picture in the sequence")); 260 } 261 184 this.nextButton.setEnabled(false); 185 this.previousButton.setEnabled(false); 186 MapillaryImportedImage mapillaryImage = (MapillaryImportedImage) this.image; 187 try { 188 mapillaryImageDisplay.setImage(mapillaryImage.getImage()); 189 } catch (IOException e) { 190 Main.error(e); 191 } 192 mapillaryImageDisplay.hyperlink.setURL(null); 193 } 194 } 195 } 196 197 private void disableAllButtons() { 198 nextButton.setEnabled(false); 199 previousButton.setEnabled(false); 200 blueButton.setEnabled(false); 201 redButton.setEnabled(false); 202 mapillaryImageDisplay.hyperlink.setVisible(false); 203 } 204 205 /** 206 * Sets a new MapillaryImage to be shown. 207 * 208 * @param image 209 */ 210 public synchronized void setImage(MapillaryAbstractImage image) { 211 this.image = image; 212 } 213 214 /** 215 * Updates the title of the dialog. 216 */ 217 public synchronized void updateTitle() { 218 if (!SwingUtilities.isEventDispatchThread()) { 219 SwingUtilities.invokeLater(new Runnable() { 262 220 @Override 263 public void actionPerformed(ActionEvent e) { 264 if (MapillaryMainDialog.getInstance().getImage() != null) { 265 MapillaryData.getInstance().selectNext(); 266 } 267 } 268 } 269 270 /** 271 * Action class for the previous image button. 272 * 273 * @author Jorge 274 * 275 */ 276 class previousPictureAction extends AbstractAction { 277 public previousPictureAction() { 278 putValue(NAME, tr("Previous picture")); 279 putValue(SHORT_DESCRIPTION, 280 tr("Shows the previous picture in the sequence")); 281 } 282 221 public void run() { 222 updateTitle(); 223 } 224 }); 225 } else { 226 if (this.image != null) { 227 MapillaryImage mapillaryImage = (MapillaryImage) this.image; 228 String title = tr(BASE_TITLE); 229 if (mapillaryImage.getUser() != null) 230 title += " -- " + mapillaryImage.getUser(); 231 if (mapillaryImage.getCapturedAt() != 0) 232 title += " -- " + mapillaryImage.getDate(); 233 setTitle(title); 234 } 235 } 236 } 237 238 /** 239 * Returns the MapillaryImage objects which is being shown. 240 * 241 * @return 242 */ 243 public synchronized MapillaryAbstractImage getImage() { 244 return this.image; 245 } 246 247 /** 248 * Action class form the next image button. 249 * 250 * @author Jorge 251 * 252 */ 253 class nextPictureAction extends AbstractAction { 254 public nextPictureAction() { 255 putValue(NAME, tr("Next picture")); 256 putValue(SHORT_DESCRIPTION, tr("Shows the next picture in the sequence")); 257 } 258 259 @Override 260 public void actionPerformed(ActionEvent e) { 261 if (MapillaryMainDialog.getInstance().getImage() != null) { 262 MapillaryData.getInstance().selectNext(); 263 } 264 } 265 } 266 267 /** 268 * Action class for the previous image button. 269 * 270 * @author Jorge 271 * 272 */ 273 class previousPictureAction extends AbstractAction { 274 public previousPictureAction() { 275 putValue(NAME, tr("Previous picture")); 276 putValue(SHORT_DESCRIPTION, 277 tr("Shows the previous picture in the sequence")); 278 } 279 280 @Override 281 public void actionPerformed(ActionEvent e) { 282 if (MapillaryMainDialog.getInstance().getImage() != null) { 283 MapillaryData.getInstance().selectPrevious(); 284 } 285 } 286 } 287 288 /** 289 * Action class to jump to the image following the red line. 290 * 291 * @author nokutu 292 * 293 */ 294 class redAction extends AbstractAction { 295 public redAction() { 296 putValue(NAME, tr("Jump to red")); 297 putValue(SHORT_DESCRIPTION, 298 tr("Jumps to the picture at the other side of the red line")); 299 } 300 301 @Override 302 public void actionPerformed(ActionEvent e) { 303 if (MapillaryMainDialog.getInstance().getImage() != null) { 304 MapillaryData.getInstance().setSelectedImage(MapillaryLayer.RED, true); 305 } 306 } 307 } 308 309 /** 310 * Action class to jump to the image following the blue line. 311 * 312 * @author nokutu 313 * 314 */ 315 class blueAction extends AbstractAction { 316 public blueAction() { 317 putValue(NAME, tr("Jump to blue")); 318 putValue(SHORT_DESCRIPTION, 319 tr("Jumps to the picture at the other side of the blue line")); 320 } 321 322 @Override 323 public void actionPerformed(ActionEvent e) { 324 if (MapillaryMainDialog.getInstance().getImage() != null) { 325 MapillaryData.getInstance().setSelectedImage(MapillaryLayer.BLUE, true); 326 } 327 } 328 } 329 330 /** 331 * When the pictures are returned from the cache, they are set in the 332 * {@link MapillaryImageDisplay} object. 333 */ 334 @Override 335 public void loadingFinished(final CacheEntry data, 336 final CacheEntryAttributes attributes, final LoadResult result) { 337 if (!SwingUtilities.isEventDispatchThread()) { 338 SwingUtilities.invokeLater(new Runnable() { 283 339 @Override 284 public void actionPerformed(ActionEvent e) { 285 if (MapillaryMainDialog.getInstance().getImage() != null) { 286 MapillaryData.getInstance().selectPrevious(); 287 } 288 } 289 } 290 291 /** 292 * Action class to jump to the image following the red line. 293 * 294 * @author nokutu 295 * 296 */ 297 class redAction extends AbstractAction { 298 public redAction() { 299 putValue(NAME, tr("Jump to red")); 300 putValue( 301 SHORT_DESCRIPTION, 302 tr("Jumps to the picture at the other side of the red line")); 303 } 304 305 @Override 306 public void actionPerformed(ActionEvent e) { 307 if (MapillaryMainDialog.getInstance().getImage() != null) { 308 MapillaryData.getInstance().setSelectedImage( 309 MapillaryLayer.RED, true); 310 } 311 } 312 } 313 314 /** 315 * Action class to jump to the image following the blue line. 316 * 317 * @author nokutu 318 * 319 */ 320 class blueAction extends AbstractAction { 321 public blueAction() { 322 putValue(NAME, tr("Jump to blue")); 323 putValue( 324 SHORT_DESCRIPTION, 325 tr("Jumps to the picture at the other side of the blue line")); 326 } 327 328 @Override 329 public void actionPerformed(ActionEvent e) { 330 if (MapillaryMainDialog.getInstance().getImage() != null) { 331 MapillaryData.getInstance().setSelectedImage( 332 MapillaryLayer.BLUE, true); 333 } 334 } 335 } 336 337 /** 338 * When the pictures are returned from the cache, they are set in the 339 * {@link MapillaryImageDisplay} object. 340 */ 341 @Override 342 public void loadingFinished(final CacheEntry data, 343 final CacheEntryAttributes attributes, final LoadResult result) { 344 if (!SwingUtilities.isEventDispatchThread()) { 345 SwingUtilities.invokeLater(new Runnable() { 346 @Override 347 public void run() { 348 loadingFinished(data, attributes, result); 349 } 350 }); 351 } else if (data != null && result == LoadResult.SUCCESS) { 352 try { 353 BufferedImage img = ImageIO.read(new ByteArrayInputStream(data 354 .getContent())); 355 if (img == null) 356 return; 357 if (this.mapillaryImageDisplay.getImage() == null) 358 mapillaryImageDisplay.setImage(img); 359 else if (img.getHeight() > this.mapillaryImageDisplay 360 .getImage().getHeight()) { 361 mapillaryImageDisplay.setImage(img); 362 } 363 } catch (IOException e) { 364 Main.error(e); 365 } 366 } 367 } 368 369 /** 370 * Creates the layout of the dialog. 371 * 372 * @param data 373 * The content of the dialog 374 * @param buttons 375 * The buttons where you can click 376 * @param reverse 377 * {@code true} if the buttons should go at the top; 378 * {@code false} otherwise. 379 */ 380 public void createLayout(Component data, List<SideButton> buttons, 381 boolean reverse) { 382 this.removeAll(); 383 JPanel panel = new JPanel(); 384 panel.setLayout(new BorderLayout()); 385 panel.add(data, BorderLayout.CENTER); 386 if (reverse) { 387 buttonsPanel = new JPanel(new GridLayout(1, 1)); 388 if (!buttons.isEmpty() && buttons.get(0) != null) { 389 final JPanel buttonRowPanel = new JPanel(Main.pref.getBoolean( 390 "dialog.align.left", false) ? new FlowLayout( 391 FlowLayout.LEFT) : new GridLayout(1, buttons.size())); 392 buttonsPanel.add(buttonRowPanel); 393 for (SideButton button : buttons) 394 buttonRowPanel.add(button); 395 } 396 panel.add(buttonsPanel, BorderLayout.NORTH); 397 createLayout(panel, true, null); 398 } else 399 createLayout(panel, true, buttons); 400 this.add(titleBar, BorderLayout.NORTH); 401 } 402 403 @Override 404 public void selectedImageChanged(MapillaryAbstractImage oldImage, 405 MapillaryAbstractImage newImage) { 406 setImage(MapillaryData.getInstance().getSelectedImage()); 407 updateImage(); 408 } 409 410 @Override 411 public void imagesAdded() { 412 } 340 public void run() { 341 loadingFinished(data, attributes, result); 342 } 343 }); 344 } else if (data != null && result == LoadResult.SUCCESS) { 345 try { 346 BufferedImage img = ImageIO.read(new ByteArrayInputStream(data 347 .getContent())); 348 if (img == null) 349 return; 350 if (this.mapillaryImageDisplay.getImage() == null) 351 mapillaryImageDisplay.setImage(img); 352 else if (img.getHeight() > this.mapillaryImageDisplay.getImage() 353 .getHeight()) { 354 mapillaryImageDisplay.setImage(img); 355 } 356 } catch (IOException e) { 357 Main.error(e); 358 } 359 } 360 } 361 362 /** 363 * Creates the layout of the dialog. 364 * 365 * @param data 366 * The content of the dialog 367 * @param buttons 368 * The buttons where you can click 369 * @param reverse 370 * {@code true} if the buttons should go at the top; {@code false} 371 * otherwise. 372 */ 373 public void createLayout(Component data, List<SideButton> buttons, 374 boolean reverse) { 375 this.removeAll(); 376 JPanel panel = new JPanel(); 377 panel.setLayout(new BorderLayout()); 378 panel.add(data, BorderLayout.CENTER); 379 if (reverse) { 380 buttonsPanel = new JPanel(new GridLayout(1, 1)); 381 if (!buttons.isEmpty() && buttons.get(0) != null) { 382 final JPanel buttonRowPanel = new JPanel(Main.pref.getBoolean( 383 "dialog.align.left", false) ? new FlowLayout(FlowLayout.LEFT) 384 : new GridLayout(1, buttons.size())); 385 buttonsPanel.add(buttonRowPanel); 386 for (SideButton button : buttons) 387 buttonRowPanel.add(button); 388 } 389 panel.add(buttonsPanel, BorderLayout.NORTH); 390 createLayout(panel, true, null); 391 } else 392 createLayout(panel, true, buttons); 393 this.add(titleBar, BorderLayout.NORTH); 394 } 395 396 @Override 397 public void selectedImageChanged(MapillaryAbstractImage oldImage, 398 MapillaryAbstractImage newImage) { 399 setImage(MapillaryData.getInstance().getSelectedImage()); 400 updateImage(); 401 } 402 403 @Override 404 public void imagesAdded() { 405 } 413 406 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryOAuthUI.java
r31342 r31350 20 20 public class MapillaryOAuthUI extends JPanel { 21 21 22 22 private static final Token EMPTY_TOKEN = null; 23 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 24 public MapillaryOAuthUI() { 25 Scanner in = new Scanner(System.in); 26 OAuthService service = new ServiceBuilder() 27 .provider(MapillaryOAuthApi.class) 28 .apiKey("NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1YTA2NmNlODhlNWMwOTBm") 29 .apiSecret("Secret").build(); 30 String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN); 31 this.add(new JLabel("Login")); 32 System.out.println("Fetching the Authorization URL..."); 33 System.out.println("Got the Authorization URL!"); 34 System.out.println("Now go and authorize Scribe here:"); 35 System.out.println(authorizationUrl); 36 System.out.println("And paste the authorization code here"); 37 System.out.print(">>"); 38 Verifier verifier = new Verifier(in.nextLine()); 39 System.out.println(); 40 } 41 41 42 42 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryPreferenceSetting.java
r31340 r31350 21 21 public class MapillaryPreferenceSetting implements SubPreferenceSetting { 22 22 23 private JCheckBox reverseButtons = new JCheckBox( 24 tr("Reverse buttons position when displaying images.")); 25 private JCheckBox downloadMode = new JCheckBox( 26 tr("Download images manually")); 27 private JCheckBox displayHour = new JCheckBox( 28 tr("Display hour when the picture was taken")); 29 private JCheckBox format24 = new JCheckBox(tr("Use 24 hour format")); 30 private JCheckBox moveTo = new JCheckBox( 31 tr("Move to picture's location with next/previous buttons")); 23 private JCheckBox reverseButtons = new JCheckBox( 24 tr("Reverse buttons position when displaying images.")); 25 private JCheckBox downloadMode = new JCheckBox(tr("Download images manually")); 26 private JCheckBox displayHour = new JCheckBox( 27 tr("Display hour when the picture was taken")); 28 private JCheckBox format24 = new JCheckBox(tr("Use 24 hour format")); 29 private JCheckBox moveTo = new JCheckBox( 30 tr("Move to picture's location with next/previous buttons")); 31 32 @Override 33 public TabPreferenceSetting getTabPreferenceSetting(PreferenceTabbedPane gui) { 34 return gui.getDisplayPreference(); 35 } 36 37 @Override 38 public void addGui(PreferenceTabbedPane gui) { 39 JPanel panel = new JPanel(); 40 41 reverseButtons.setSelected(Main.pref 42 .getBoolean("mapillary.reverse-buttons")); 43 downloadMode.setSelected(Main.pref 44 .getBoolean("mapillary.download-manually")); 45 displayHour.setSelected(Main.pref 46 .getBoolean("mapillary.display-hour", true)); 47 format24.setSelected(Main.pref.getBoolean("mapillary.format-24")); 48 moveTo.setSelected(Main.pref.getBoolean("mapillary.move-to-picture", true)); 49 50 panel.setLayout(new FlowLayout(FlowLayout.LEFT)); 51 panel.add(reverseButtons); 52 panel.add(downloadMode); 53 panel.add(displayHour); 54 panel.add(format24); 55 panel.add(moveTo); 56 JButton oauth = new JButton(new OAuthAction()); 57 oauth.setText("Login"); 58 panel.add(oauth); 59 gui.getDisplayPreference().addSubTab(this, "Mapillary", panel); 60 } 61 62 @Override 63 public boolean ok() { 64 boolean mod = false; 65 Main.pref.put("mapillary.reverse-buttons", reverseButtons.isSelected()); 66 Main.pref.put("mapillary.download-manually", downloadMode.isSelected()); 67 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.DOWNLOAD_VIEW_MENU, 68 downloadMode.isSelected()); 69 70 Main.pref.put("mapillary.display-hour", displayHour.isSelected()); 71 Main.pref.put("mapillary.format-24", format24.isSelected()); 72 Main.pref.put("mapillary.move-to-picture", moveTo.isSelected()); 73 return mod; 74 } 75 76 @Override 77 public boolean isExpert() { 78 return false; 79 } 80 81 public class OAuthAction extends AbstractAction { 32 82 33 83 @Override 34 public TabPreferenceSetting getTabPreferenceSetting(PreferenceTabbedPane gui) { 35 return gui.getDisplayPreference(); 84 public void actionPerformed(ActionEvent arg0) { 85 JButton login = new JButton(); 86 JButton cancel = new JButton(); 87 JOptionPane pane = new JOptionPane(new MapillaryOAuthUI(), 88 JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION, null, 89 new JButton[] { login, cancel }); 90 login.setAction(new LoginAction(pane)); 91 cancel.setAction(new CancelAction(pane)); 92 JDialog dlg = pane.createDialog(Main.parent, tr("Login")); 93 dlg.setVisible(true); 94 dlg.dispose(); 95 } 96 } 97 98 private class LoginAction extends AbstractAction { 99 private JOptionPane pane; 100 101 public LoginAction(JOptionPane pane) { 102 putValue(NAME, tr("Login")); 103 this.pane = pane; 36 104 } 37 105 38 106 @Override 39 public void addGui(PreferenceTabbedPane gui) { 40 JPanel panel = new JPanel(); 107 public void actionPerformed(ActionEvent e) { 108 pane.setValue(JOptionPane.OK_OPTION); 109 } 110 } 41 111 42 reverseButtons.setSelected(Main.pref 43 .getBoolean("mapillary.reverse-buttons")); 44 downloadMode.setSelected(Main.pref 45 .getBoolean("mapillary.download-manually")); 46 displayHour.setSelected(Main.pref.getBoolean("mapillary.display-hour", 47 true)); 48 format24.setSelected(Main.pref.getBoolean("mapillary.format-24")); 49 moveTo.setSelected(Main.pref.getBoolean("mapillary.move-to-picture", 50 true)); 112 private class CancelAction extends AbstractAction { 113 private JOptionPane pane; 51 114 52 panel.setLayout(new FlowLayout(FlowLayout.LEFT)); 53 panel.add(reverseButtons); 54 panel.add(downloadMode); 55 panel.add(displayHour); 56 panel.add(format24); 57 panel.add(moveTo); 58 JButton oauth = new JButton(new OAuthAction()); 59 oauth.setText("Login"); 60 panel.add(oauth); 61 gui.getDisplayPreference().addSubTab(this, "Mapillary", panel); 115 public CancelAction(JOptionPane pane) { 116 putValue(NAME, tr("Cancel")); 117 this.pane = pane; 62 118 } 63 119 64 120 @Override 65 public boolean ok() { 66 boolean mod = false; 67 Main.pref.put("mapillary.reverse-buttons", reverseButtons.isSelected()); 68 Main.pref.put("mapillary.download-manually", downloadMode.isSelected()); 69 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.DOWNLOAD_VIEW_MENU, 70 downloadMode.isSelected()); 71 72 Main.pref.put("mapillary.display-hour", displayHour.isSelected()); 73 Main.pref.put("mapillary.format-24", format24.isSelected()); 74 Main.pref.put("mapillary.move-to-picture", moveTo.isSelected()); 75 return mod; 121 public void actionPerformed(ActionEvent e) { 122 pane.setValue(JOptionPane.CANCEL_OPTION); 76 123 } 77 78 @Override 79 public boolean isExpert() { 80 return false; 81 } 82 83 public class OAuthAction extends AbstractAction { 84 85 @Override 86 public void actionPerformed(ActionEvent arg0) { 87 JButton login = new JButton(); 88 JButton cancel = new JButton(); 89 JOptionPane pane = new JOptionPane(new MapillaryOAuthUI(), 90 JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION, 91 null, new JButton[] { login, cancel }); 92 login.setAction(new LoginAction(pane)); 93 cancel.setAction(new CancelAction(pane)); 94 JDialog dlg = pane.createDialog(Main.parent, tr("Login")); 95 dlg.setVisible(true); 96 dlg.dispose(); 97 } 98 } 99 100 private class LoginAction extends AbstractAction { 101 private JOptionPane pane; 102 103 public LoginAction(JOptionPane pane) { 104 putValue(NAME, tr("Login")); 105 this.pane = pane; 106 } 107 108 @Override 109 public void actionPerformed(ActionEvent e) { 110 pane.setValue(JOptionPane.OK_OPTION); 111 } 112 } 113 114 private class CancelAction extends AbstractAction { 115 private JOptionPane pane; 116 117 public CancelAction(JOptionPane pane) { 118 putValue(NAME, tr("Cancel")); 119 this.pane = pane; 120 } 121 122 @Override 123 public void actionPerformed(ActionEvent e) { 124 pane.setValue(JOptionPane.CANCEL_OPTION); 125 } 126 } 124 } 127 125 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/oauth/MapillaryOAuthApi.java
r31342 r31350 13 13 public class MapillaryOAuthApi extends DefaultApi20 { 14 14 15 16 17 18 15 @Override 16 public String getAccessTokenEndpoint() { 17 return "https://a.mapillary.com/v2/oauth/token"; 18 } 19 19 20 21 22 23 20 @Override 21 public String getAuthorizationUrl(OAuthConfig config) { 22 return "http://www.mapillary.io/connect?client_id=MkJKbDA0bnZuZlcxeTJHTmFqN3g1dzplZTlkZjQyYjYyZTczOTdi&redirect_uri=https:%2F%2Fjosm.openstreetmap.de%2F&response_type=token&scope=upload"; 23 } 24 24 25 26 27 28 25 @Override 26 public Verb getAccessTokenVerb() { 27 return Verb.POST; 28 } 29 29 }
Note:
See TracChangeset
for help on using the changeset viewer.