Changeset 34333 in osm for applications/editors/josm/plugins/MicrosoftStreetside/src
- Timestamp:
- 2018-06-20T22:09:16+02:00 (7 years ago)
- Location:
- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideData.java
r34329 r34333 290 290 throw new IllegalStateException(); 291 291 } 292 StreetsideAbstractImage tempImage = selectedImage; 292 StreetsideAbstractImage tempImage = this.selectedImage; 293 293 while (tempImage.previous() != null) { 294 294 tempImage = tempImage.previous(); -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideImage.java
r34325 r34333 2 2 package org.openstreetmap.josm.plugins.streetside; 3 3 4 import java.util.ArrayList; 5 import java.util.Collection; 6 import java.util.Collections; 4 7 import java.util.List; 5 8 … … 7 10 import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils; 8 11 import org.openstreetmap.josm.plugins.streetside.model.UserProfile; 12 import org.openstreetmap.josm.tools.Logging; 13 14 import org.openstreetmap.josm.plugins.streetside.model.ImageDetection; 9 15 10 16 /** … … 59 65 /** 60 66 * Set of traffic signs in the image. 61 */ /*67 */ 62 68 private final List<ImageDetection> detections = Collections.synchronizedList(new ArrayList<>()); 63 */ 69 64 70 /** 65 71 * Main constructor of the class StreetsideImage … … 100 106 } 101 107 102 /*public List<ImageDetection> getDetections() {108 public List<ImageDetection> getDetections() { 103 109 return detections; 104 } */105 106 /*public void setAllDetections(Collection<ImageDetection> newDetections) {110 } 111 112 public void setAllDetections(Collection<ImageDetection> newDetections) { 107 113 Logging.debug("Add {0} detections to image {1}", newDetections.size(), getId()); 108 114 synchronized (detections) { … … 110 116 detections.addAll(newDetections); 111 117 } 112 } */118 } 113 119 114 120 public UserProfile getUser() { … … 119 125 public String toString() { 120 126 return String.format( 121 // TODO: format date cd (Gradle build error command line)122 127 "Image[id=%s,lat=%f,lon=%f,he=%f,user=%s]", 123 128 id, latLon.lat(), latLon.lon(), he, "null"//, cd -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideLayer.java
r34329 r34333 81 81 ) / 3; 82 82 83 private static final DataSetListenerAdapter DATASET_LISTENER = 84 new DataSetListenerAdapter(e -> { 85 if (e instanceof DataChangedEvent && StreetsideDownloader.getMode() == DOWNLOAD_MODE.OSM_AREA) { 86 // When more data is downloaded, a delayed update is thrown, in order to 87 // wait for the data bounds to be set. 88 MainApplication.worker.execute(StreetsideDownloader::downloadOSMArea); 89 } 90 }); 83 private static final DataSetListenerAdapter DATASET_LISTENER = new DataSetListenerAdapter(e -> { 84 if (e instanceof DataChangedEvent && StreetsideDownloader.getMode() == DOWNLOAD_MODE.OSM_AREA) { 85 // When more data is downloaded, a delayed update is thrown, in order to 86 // wait for the data bounds to be set. 87 MainApplication.worker.execute(StreetsideDownloader::downloadOSMArea); 88 } 89 }); 91 90 92 91 /** Unique instance of the class. */ … … 207 206 */ 208 207 public StreetsideData getData() { 209 return this.data;208 return data; 210 209 } 211 210 … … 259 258 260 259 261 260 @Override 262 261 public boolean isModified() { 263 return this.data.getImages().parallelStream().anyMatch(StreetsideAbstractImage::isModified);262 return data.getImages().parallelStream().anyMatch(StreetsideAbstractImage::isModified); 264 263 } 265 264 … … 286 285 big.drawLine(0, 15, 15, 0); 287 286 Rectangle r = new Rectangle(0, 0, 15, 15); 288 this.hatched = new TexturePaint(bi, r);287 hatched = new TexturePaint(bi, r); 289 288 } 290 289 … … 295 294 // paint remainder 296 295 g.setPaint(hatched); 297 g.fill(MapViewGeometryUtil.getNonDownloadedArea(mv, this.data.getBounds()));296 g.fill(MapViewGeometryUtil.getNonDownloadedArea(mv, data.getBounds())); 298 297 } 299 298 … … 314 313 315 314 // Draw sequence line 316 g.setStroke(new BasicStroke(2)); 315 // TODO: reimplement sequence lines for Streetside 316 /*g.setStroke(new BasicStroke(2)); 317 317 final StreetsideAbstractImage selectedImage = getData().getSelectedImage(); 318 318 for (StreetsideSequence seq : getData().getSequences()) { … … 327 327 } 328 328 g.draw(MapViewGeometryUtil.getSequencePath(mv, seq)); 329 } 330 for (StreetsideAbstractImage imageAbs : this.data.getImages()) {329 }*/ 330 for (StreetsideAbstractImage imageAbs : data.getImages()) { 331 331 if (imageAbs.isVisible() && mv != null && mv.contains(mv.getPoint(imageAbs.getMovingLatLon()))) { 332 332 drawImageMarker(g, imageAbs); 333 333 } 334 334 } 335 if ( this.mode instanceof JoinMode) {336 this.mode.paint(g, mv, box);335 if (mode instanceof JoinMode) { 336 mode.paint(g, mv, box); 337 337 } 338 338 } … … 392 392 393 393 394 /*if (img instanceof StreetsideImage && !((StreetsideImage) img).getDetections().isEmpty()) {395 finalPath2D trafficSign = new Path2D.Double();394 if (img instanceof StreetsideImage && !((StreetsideImage) img).getDetections().isEmpty()) { 395 Path2D trafficSign = new Path2D.Double(); 396 396 trafficSign.moveTo(p.getX() - StreetsideLayer.TRAFFIC_SIGN_SIZE / 2d, p.getY() - StreetsideLayer.TRAFFIC_SIGN_HEIGHT_3RD); 397 397 trafficSign.lineTo(p.getX() + StreetsideLayer.TRAFFIC_SIGN_SIZE / 2d, p.getY() - StreetsideLayer.TRAFFIC_SIGN_HEIGHT_3RD); … … 403 403 g.setColor(Color.RED); 404 404 g.draw(trafficSign); 405 } */405 } 406 406 } 407 407 -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsidePlugin.java
r34329 r34333 26 26 import org.openstreetmap.josm.tools.ImageProvider; 27 27 28 import org.openstreetmap.josm.plugins.streetside.gui.StreetsideChangesetDialog; 29 28 30 /** 29 31 * This is the main class of the Streetside plugin. … … 48 50 MainMenu.add(MainApplication.getMenu().dataMenu, new StreetsideJoinAction(), false); 49 51 MainMenu.add(MainApplication.getMenu().moreToolsMenu, WALK_ACTION, false); 50 //MainMenu.add(MainApplication.getMenu().imagerySubMenu, new MapObjectLayerAction(), false);51 52 //MainMenu.add(MainApplication.getMenu().imagerySubMenu, new MapObjectLayerAction(), false); 52 53 } … … 75 76 * @return the {@link StreetsideWalkAction} for the plugin 76 77 */ 77 public static StreetsideWalkAction get StreetsideWalkAction() {78 public static StreetsideWalkAction getWalkAction() { 78 79 return WALK_ACTION; 79 80 } … … 91 92 MainApplication.getMap().addToggleDialog(StreetsideViewerDialog.getInstance(), false); 92 93 //MainApplication.getMap().addToggleDialog(StreetsideHistoryDialog.getInstance(), false); 93 //MainApplication.getMap().addToggleDialog(StreetsideChangesetDialog.getInstance(), false);94 MainApplication.getMap().addToggleDialog(StreetsideChangesetDialog.getInstance(), false); 94 95 //MainApplication.getMap().addToggleDialog(StreetsideFilterDialog.getInstance(), false); 95 96 } … … 97 98 StreetsideMainDialog.destroyInstance(); 98 99 //StreetsideHistoryDialog.destroyInstance(); 99 //StreetsideChangesetDialog.destroyInstance();100 StreetsideChangesetDialog.destroyInstance(); 100 101 //StreetsideFilterDialog.destroyInstance(); 101 102 ImageInfoPanel.destroyInstance(); … … 131 132 * @return the {@link StreetsideZoomAction} for the plugin 132 133 */ 133 /*public static StreetsideZoomAction getZoomAction() {134 public static StreetsideZoomAction getZoomAction() { 134 135 return ZOOM_ACTION; 135 }*/136 136 } 137 138 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/WalkThread.java
r34317 r34333 2 2 package org.openstreetmap.josm.plugins.streetside.actions; 3 3 4 import java.awt.image.BufferedImage;5 6 4 import javax.swing.SwingUtilities; 7 5 6 import org.openstreetmap.josm.gui.Notification; 8 7 import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage; 9 8 import org.openstreetmap.josm.plugins.streetside.StreetsideData; 10 9 import org.openstreetmap.josm.plugins.streetside.StreetsideDataListener; 10 import org.openstreetmap.josm.plugins.streetside.StreetsideLayer; 11 import org.openstreetmap.josm.plugins.streetside.StreetsidePlugin; 12 import org.openstreetmap.josm.plugins.streetside.cache.CacheUtils; 13 import org.openstreetmap.josm.plugins.streetside.cache.StreetsideCache; 14 import org.openstreetmap.josm.plugins.streetside.gui.StreetsideMainDialog; 15 import org.openstreetmap.josm.tools.I18n; 16 import org.openstreetmap.josm.tools.Logging; 17 11 18 import org.openstreetmap.josm.plugins.streetside.StreetsideImage; 12 import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;13 import org.openstreetmap.josm.plugins.streetside.cache.CacheUtils;14 import org.openstreetmap.josm.plugins.streetside.gui.StreetsideMainDialog;15 16 19 17 20 /** … … 27 30 private final boolean followSelected; 28 31 private final boolean goForward; 29 private BufferedImage lastImage;30 32 private volatile boolean paused; 31 33 … … 52 54 public void run() { 53 55 try { 54 while (!end && data.getSelectedImage().next() != null) { 55 StreetsideAbstractImage image = data.getSelectedImage(); 56 if (image != null && image.next() instanceof StreetsideImage) { 57 // Predownload next 10 thumbnails. 58 preDownloadImages((StreetsideImage) image.next(), 10, CacheUtils.PICTURE.THUMBNAIL); 59 // TODO: WalkThread for cubemaps? @rrh 60 //preDownloadCubemaps((StreetsideImage) image.next(), 10, CacheUtils.PICTURE.CUBEMAP); 61 if (waitForFullQuality) { 62 // Start downloading 3 next full images. 63 StreetsideAbstractImage currentImage = image.next(); 64 preDownloadImages((StreetsideImage) currentImage, 3, CacheUtils.PICTURE.FULL_IMAGE); 65 // TODO: WalkThread for cubemaps? @rrh 66 /*if (StreetsideProperties.PREDOWNLOAD_CUBEMAPS.get().booleanValue()) { 67 preDownloadCubemaps((StreetsideImage) currentImage, 3, CacheUtils.PICTURE.CUBEMAP); 68 }*/ 69 } 56 StreetsideAbstractImage curSelection; 57 StreetsideImage curImage; 58 while ( 59 !end && 60 (curSelection = data.getSelectedImage().next()) != null && 61 (curImage = curSelection instanceof StreetsideImage ? (StreetsideImage) curSelection : null) != null 62 ) { 63 // Predownload next 10 thumbnails. 64 preDownloadImages(curImage, 10, CacheUtils.PICTURE.THUMBNAIL, goForward); 65 if (waitForFullQuality) { 66 // Start downloading 3 next full images. 67 preDownloadImages(curImage, 3, CacheUtils.PICTURE.FULL_IMAGE, goForward); 70 68 } 71 69 try { 72 // Waits for full quality picture. 73 final BufferedImage displayImage = StreetsideMainDialog.getInstance().getStreetsideImageDisplay().getImage(); 74 if (waitForFullQuality && image instanceof StreetsideImage) { 75 while (displayImage == lastImage || displayImage == null || displayImage.getWidth() < 2048) { 76 Thread.sleep(100); 77 } 78 } else { // Waits for thumbnail. 79 while (displayImage == lastImage || displayImage == null || displayImage.getWidth() < 320) { 80 Thread.sleep(100); 70 // Wait for picture for 1 minute. 71 final StreetsideCache cache = new StreetsideCache(curImage.getId(), waitForFullQuality ? StreetsideCache.Type.FULL_IMAGE : StreetsideCache.Type.THUMBNAIL); 72 int limit = 240; // 240 * 250 = 60000 ms 73 while (cache.get() == null) { 74 Thread.sleep(250); 75 if (limit-- < 0) { 76 new Notification(I18n.tr("Walk mode: Waiting for next image takes too long! Exiting walk mode…")) 77 .setIcon(StreetsidePlugin.LOGO.get()) 78 .show(); 79 end(); 80 return; 81 81 } 82 82 } … … 84 84 Thread.sleep(100); 85 85 } 86 wait(interval);86 Thread.sleep(interval); 87 87 while (paused) { 88 88 Thread.sleep(100); 89 89 } 90 lastImage = StreetsideMainDialog.getInstance().getStreetsideImageDisplay().getImage();91 90 if (goForward) { 92 91 data.selectNext(followSelected); … … 95 94 } 96 95 } catch (InterruptedException e) { 96 end(); 97 97 return; 98 98 } 99 99 100 } 100 101 // TODO: WalkThread for cubemaps? @rrh102 /*while (!end && data.getSelectedImage().next() != null) {103 StreetsideAbstractImage cubemap = data.getSelectedImage();104 if (cubemap != null && cubemap.next() instanceof StreetsideCubemap) {105 if (waitForFullQuality) {106 // Start downloading 3 next full images.107 108 // TODO: cubemap handling @rrh109 preDownloadCubemaps((StreetsideCubemap) cubemap.next(), 6, CacheUtils.PICTURE.CUBEMAP);110 }111 }112 try {113 // Waits for full quality picture.114 final BufferedImage[] displayCubemap = StreetsideMainDialog.getInstance().streetsideViewerDisplay.getCubemap();115 if (waitForFullQuality && cubemap instanceof StreetsideCubemap) {116 // TODO: handle cubemap width? @rrh117 while (displayCubemap == lastCubemap || displayCubemap == null || displayCubemap.getWidth() < 2048) {118 Thread.sleep(100);119 }120 } else { // Waits for thumbnail.121 // TODO: handle cubemap width? @rrh122 while (displayCubemap == lastCubemap || displayCubemap == null || displayCubemap.getWidth() < 320) {123 Thread.sleep(100);124 }125 }126 while (paused) {127 Thread.sleep(100);128 }129 wait(interval);130 while (paused) {131 Thread.sleep(100);132 }133 lastCubemap = StreetsideMainDialog.getInstance().streetsideViewerDisplay.getCubemap();134 // TODO: forward / previous for cubemap? @rrh135 if (goForward) {136 data.selectNext(followSelected);137 } else {138 data.selectPrevious(followSelected);139 }140 } catch (InterruptedException e) {141 return;142 }143 }*/144 101 } catch (NullPointerException e) { 102 Logging.warn(e); 103 end(); 145 104 // TODO: Avoid NPEs instead of waiting until they are thrown and then catching them 146 105 return; … … 149 108 } 150 109 151 private void preDownloadCubemaps(StreetsideImage startImage, int n, CacheUtils.PICTURE type) { 152 if (n >= 1 && startImage != null) { 153 154 for (int i = 0; i < 6; i++) { 155 for (int j = 0; j < 4; j++) { 156 for (int k = 0; k < 4; k++) { 157 158 CacheUtils.downloadPicture(startImage, type); 159 if (startImage.next() instanceof StreetsideImage && n >= 2) { 160 preDownloadImages((StreetsideImage) startImage.next(), n - 1, type); 161 } 162 } 163 } 164 } 165 } 166 } 167 168 /** 110 /** 169 111 * Downloads n images into the cache beginning from the supplied start-image (including the start-image itself). 170 112 * … … 172 114 * @param n the number of images to download 173 115 * @param type the quality of the image (full or thumbnail) 116 * @param goForward true if the next images, false if the previous ones should be downloaded 174 117 */ 175 private static void preDownloadImages(StreetsideImage startImage, int n, CacheUtils.PICTURE type) { 118 private static void preDownloadImages(StreetsideImage startImage, int n, CacheUtils.PICTURE type, final boolean goForward) { 176 119 if (n >= 1 && startImage != null) { 177 120 CacheUtils.downloadPicture(startImage, type); 178 if (startImage.next() instanceof StreetsideImage && n >= 2) { 179 preDownloadImages((StreetsideImage) startImage.next(), n - 1, type); 121 final StreetsideAbstractImage nextImg = goForward ? startImage.next() : startImage.previous(); 122 if (nextImg instanceof StreetsideImage && n >= 2) { 123 preDownloadImages((StreetsideImage) nextImg, n - 1, type, goForward); 180 124 } 181 125 } … … 224 168 * Called when the walk stops by itself of forcefully. 225 169 */ 226 p ublicvoid end() {170 private void end() { 227 171 if (SwingUtilities.isEventDispatchThread()) { 228 172 end = true; … … 232 176 SwingUtilities.invokeLater(this::end); 233 177 } 234 // TODO: WalkThread for Cubemaps? @rrh235 /*if (Platform.isEventDispatchThread()) {236 end = true;237 data.removeListener(this);238 StreetsideViewerDialog.getInstance().setMode(StreetsideViewerDialog.MODE.NORMAL);239 } else {240 Platform.invokeLater(this::end);241 }*/242 178 } 243 179 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideExportDialog.java
r34317 r34333 134 134 135 135 private static final long serialVersionUID = 1035332841101190301L; 136 137 private String lastPath; 136 private String lastPath; 138 137 private final StreetsideExportDialog dlg; 139 138 -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideImageDisplay.java
r34317 r34333 39 39 * 40 40 * @author nokutu 41 * @author renerr18 42 * 41 43 * @see StreetsideImageDisplay 42 44 * @see StreetsideMainDialog … … 80 82 visibleRect = StreetsideImageDisplay.this.visibleRect; 81 83 } 82 mouseIsDragging = false; 84 this.mouseIsDragging = false; 83 85 selectedRect = null; 84 86 if (image != null && Math.min(getSize().getWidth(), getSize().getHeight()) > 0) { … … 89 91 // borders, this point is not calculated 90 92 // again if there was less than 1.5seconds since the last event. 91 if (e.getWhen() - lastTimeForMousePoint > 1500 || mousePointInImg == null) { 92 lastTimeForMousePoint = e.getWhen(); 93 mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY()); 93 if (e.getWhen() - this.lastTimeForMousePoint > 1500 || this.mousePointInImg == null) { 94 this.lastTimeForMousePoint = e.getWhen(); 95 this.mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY()); 94 96 } 95 97 // Set the zoom to the visible rectangle in image coordinates … … 121 123 // cursor doesn't move on the image. 122 124 Rectangle drawRect = calculateDrawImageRectangle(visibleRect); 123 visibleRect.x = mousePointInImg.x 125 visibleRect.x = this.mousePointInImg.x 124 126 + ((drawRect.x - e.getX()) * visibleRect.width) / drawRect.width; 125 visibleRect.y = mousePointInImg.y 127 visibleRect.y = this.mousePointInImg.y 126 128 + ((drawRect.y - e.getY()) * visibleRect.height) / drawRect.height; 127 129 // The position is also limited by the image size … … 185 187 public void mousePressed(MouseEvent e) { 186 188 if (getImage() == null) { 187 mouseIsDragging = false; 188 189 this.mouseIsDragging = false; 190 StreetsideImageDisplay.this.selectedRect = null; 189 191 return; 190 192 } … … 198 200 return; 199 201 if (e.getButton() == StreetsideProperties.PICTURE_DRAG_BUTTON.get()) { 200 mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY()); 201 mouseIsDragging = true; 202 selectedRect = null; 202 this.mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY()); 203 this.mouseIsDragging = true; 204 StreetsideImageDisplay.this.selectedRect = null; 203 205 } else if (e.getButton() == StreetsideProperties.PICTURE_ZOOM_BUTTON.get()) { 204 206 mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY()); 205 checkPointInVisibleRect(mousePointInImg, visibleRect); 206 mouseIsDragging = false; 207 selectedRect = new Rectangle(mousePointInImg.x, mousePointInImg.y, 0, 0); 207 checkPointInVisibleRect(this.mousePointInImg, visibleRect); 208 this.mouseIsDragging = false; 209 StreetsideImageDisplay.this.selectedRect = new Rectangle(mousePointInImg.x, mousePointInImg.y, 0, 0); 208 210 StreetsideImageDisplay.this.repaint(); 209 211 } else { 210 mouseIsDragging = false; 211 selectedRect = null; 212 this.mouseIsDragging = false; 213 StreetsideImageDisplay.this.selectedRect = null; 212 214 } 213 215 } … … 215 217 @Override 216 218 public void mouseDragged(MouseEvent e) { 217 if (!mouseIsDragging && selectedRect == null) 219 if (!this.mouseIsDragging && StreetsideImageDisplay.this.selectedRect == null) 218 220 return; 219 221 Image image; … … 224 226 } 225 227 if (image == null) { 226 mouseIsDragging = false; 227 selectedRect = null; 228 this.mouseIsDragging = false; 229 StreetsideImageDisplay.this.selectedRect = null; 228 230 return; 229 231 } 230 if (mouseIsDragging) { 232 if (this.mouseIsDragging) { 231 233 Point p = comp2imgCoord(visibleRect, e.getX(), e.getY()); 232 visibleRect.x += mousePointInImg.x - p.x; 233 visibleRect.y += mousePointInImg.y - p.y; 234 visibleRect.x += this.mousePointInImg.x - p.x; 235 visibleRect.y += this.mousePointInImg.y - p.y; 234 236 checkVisibleRectPos(image, visibleRect); 235 237 synchronized (StreetsideImageDisplay.this) { … … 237 239 } 238 240 StreetsideImageDisplay.this.repaint(); 239 } else if (selectedRect != null) { 241 } else if (StreetsideImageDisplay.this.selectedRect != null) { 240 242 Point p = comp2imgCoord(visibleRect, e.getX(), e.getY()); 241 243 checkPointInVisibleRect(p, visibleRect); 242 Rectangle rect = new Rectangle(p.x < mousePointInImg.x ? p.x 243 : mousePointInImg.x, p.y < mousePointInImg.y ? p.y 244 : mousePointInImg.y, p.x < mousePointInImg.x ? mousePointInImg.x 245 - p.x : p.x - mousePointInImg.x, 246 p.y < mousePointInImg.y ? mousePointInImg.y - p.y : p.y 247 - mousePointInImg.y); 244 Rectangle rect = new Rectangle(p.x < this.mousePointInImg.x ? p.x 245 : this.mousePointInImg.x, p.y < this.mousePointInImg.y ? p.y 246 : this.mousePointInImg.y, p.x < this.mousePointInImg.x ? this.mousePointInImg.x 247 - p.x : p.x - this.mousePointInImg.x, 248 p.y < this.mousePointInImg.y ? this.mousePointInImg.y - p.y : p.y 249 - this.mousePointInImg.y); 248 250 checkVisibleRectSize(image, rect); 249 251 checkVisibleRectPos(image, rect); 250 selectedRect = rect; 252 StreetsideImageDisplay.this.selectedRect = rect; 251 253 StreetsideImageDisplay.this.repaint(); 252 254 } … … 255 257 @Override 256 258 public void mouseReleased(MouseEvent e) { 257 if (!mouseIsDragging && selectedRect == null) 259 if (!this.mouseIsDragging && StreetsideImageDisplay.this.selectedRect == null) 258 260 return; 259 261 Image image; … … 262 264 } 263 265 if (image == null) { 264 mouseIsDragging = false; 265 selectedRect = null; 266 this.mouseIsDragging = false; 267 StreetsideImageDisplay.this.selectedRect = null; 266 268 return; 267 269 } 268 if (mouseIsDragging) { 269 mouseIsDragging = false; 270 } else if (selectedRect != null) { 271 int oldWidth = selectedRect.width; 272 int oldHeight = selectedRect.height; 270 if (this.mouseIsDragging) { 271 this.mouseIsDragging = false; 272 } else if (StreetsideImageDisplay.this.selectedRect != null) { 273 int oldWidth = StreetsideImageDisplay.this.selectedRect.width; 274 int oldHeight = StreetsideImageDisplay.this.selectedRect.height; 273 275 // Check that the zoom doesn't exceed 2:1 274 if (selectedRect.width < getSize().width / 2) { 275 selectedRect.width = getSize().width / 2; 276 } 277 if (selectedRect.height < getSize().height / 2) { 278 selectedRect.height = getSize().height / 2; 276 if (StreetsideImageDisplay.this.selectedRect.width < getSize().width / 2) { 277 StreetsideImageDisplay.this.selectedRect.width = getSize().width / 2; 278 } 279 if (StreetsideImageDisplay.this.selectedRect.height < getSize().height / 2) { 280 StreetsideImageDisplay.this.selectedRect.height = getSize().height / 2; 279 281 } 280 282 // Set the same ratio for the visible rectangle and the display 281 283 // area 282 int hFact = selectedRect.height * getSize().width; 283 int wFact = selectedRect.width * getSize().height; 284 int hFact = StreetsideImageDisplay.this.selectedRect.height * getSize().width; 285 int wFact = StreetsideImageDisplay.this.selectedRect.width * getSize().height; 284 286 if (hFact > wFact) { 285 287 StreetsideImageDisplay.this.selectedRect.width = hFact / getSize().height; 286 288 } else { 287 289 StreetsideImageDisplay.this.selectedRect.height = wFact / getSize().width; 288 290 } 289 291 // Keep the center of the selection 290 if (selectedRect.width != oldWidth) { 291 selectedRect.x -= (selectedRect.width - oldWidth) / 2; 292 } 293 if (selectedRect.height != oldHeight) { 294 selectedRect.y -= (selectedRect.height - oldHeight) / 2; 295 } 296 checkVisibleRectSize(image, selectedRect); 297 checkVisibleRectPos(image, selectedRect); 292 if (StreetsideImageDisplay.this.selectedRect.width != oldWidth) { 293 StreetsideImageDisplay.this.selectedRect.x -= (StreetsideImageDisplay.this.selectedRect.width - oldWidth) / 2; 294 } 295 if (StreetsideImageDisplay.this.selectedRect.height != oldHeight) { 296 StreetsideImageDisplay.this.selectedRect.y -= (StreetsideImageDisplay.this.selectedRect.height - oldHeight) / 2; 297 } 298 checkVisibleRectSize(image, StreetsideImageDisplay.this.selectedRect); 299 checkVisibleRectPos(image, StreetsideImageDisplay.this.selectedRect); 298 300 synchronized (StreetsideImageDisplay.this) { 299 visibleRect = selectedRect; 300 } 301 selectedRect = null; 301 StreetsideImageDisplay.this.visibleRect = StreetsideImageDisplay.this.selectedRect; 302 } 303 StreetsideImageDisplay.this.selectedRect = null; 302 304 StreetsideImageDisplay.this.repaint(); 303 305 } … … 360 362 this.detections.addAll(detections); 361 363 } 362 selectedRect = null; 364 this.selectedRect = null; 363 365 if (image != null) 364 visibleRect = new Rectangle(0, 0, image.getWidth(null), 366 this.visibleRect = new Rectangle(0, 0, image.getWidth(null), 365 367 image.getHeight(null)); 366 368 } … … 374 376 */ 375 377 public BufferedImage getImage() { 376 return image; 378 return this.image; 377 379 } 378 380 … … 402 404 + target.height, visibleRect.x, visibleRect.y, visibleRect.x 403 405 + visibleRect.width, visibleRect.y + visibleRect.height, null); 404 if (selectedRect != null) { 405 Point topLeft = img2compCoord(visibleRect, selectedRect.x, 406 selectedRect.y); 407 Point bottomRight = img2compCoord(visibleRect, selectedRect.x 408 + selectedRect.width, selectedRect.y + selectedRect.height); 406 if (this.selectedRect != null) { 407 Point topLeft = img2compCoord(visibleRect, this.selectedRect.x, 408 this.selectedRect.y); 409 Point bottomRight = img2compCoord(visibleRect, this.selectedRect.x 410 + this.selectedRect.width, this.selectedRect.y + this.selectedRect.height); 409 411 g.setColor(new Color(128, 128, 128, 180)); 410 412 g.fillRect(target.x, target.y, target.width, topLeft.y - target.y); -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideMainDialog.java
r34317 r34333 1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.plugins.streetside.gui; 3 4 import static org.openstreetmap.josm.tools.I18n.marktr; 5 import static org.openstreetmap.josm.tools.I18n.tr; 6 import static org.openstreetmap.josm.tools.I18n.trc; 3 7 4 8 import java.awt.BorderLayout; … … 14 18 import javax.imageio.ImageIO; 15 19 import javax.swing.AbstractAction; 16 import javax.swing.Action;17 20 import javax.swing.JComponent; 18 21 import javax.swing.KeyStroke; … … 34 37 import org.openstreetmap.josm.plugins.streetside.cache.StreetsideCache; 35 38 import org.openstreetmap.josm.plugins.streetside.gui.imageinfo.ImageInfoHelpPopup; 36 import org.openstreetmap.josm.plugins.streetside. gui.imageinfo.StreetsideViewerHelpPopup;39 import org.openstreetmap.josm.plugins.streetside.model.UserProfile; 37 40 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties; 38 import org.openstreetmap.josm.tools.I18n;39 41 import org.openstreetmap.josm.tools.ImageProvider; 40 42 import org.openstreetmap.josm.tools.Logging; … … 44 46 * 45 47 * @author nokutu 46 * @author renerr1847 48 */ 48 49 public final class StreetsideMainDialog extends ToggleDialog implements 49 ICachedLoaderListener, StreetsideDataListener { 50 51 private static final long serialVersionUID = 2645654786827812861L; 52 53 public static final String BASE_TITLE = I18n.marktr("Microsoft Streetside image"); 54 private static final String MESSAGE_SEPARATOR = " — "; 55 56 private static StreetsideMainDialog instance; 57 58 private volatile StreetsideAbstractImage image; 59 60 public final SideButton nextButton = new SideButton(new NextPictureAction()); 61 public final SideButton previousButton = new SideButton(new PreviousPictureAction()); 62 /** 63 * Button used to jump to the image following the red line 64 */ 65 public final SideButton redButton = new SideButton(new RedAction()); 66 /** 67 * Button used to jump to the image following the blue line 68 */ 69 public final SideButton blueButton = new SideButton(new BlueAction()); 70 71 private final SideButton playButton = new SideButton(new PlayAction()); 72 private final SideButton pauseButton = new SideButton(new PauseAction()); 73 private final SideButton stopButton = new SideButton(new StopAction()); 74 75 private ImageInfoHelpPopup imageInfoHelp; 76 77 private StreetsideViewerHelpPopup streetsideViewerHelp; 78 79 /** 80 * Buttons mode. 81 * 82 * @author nokutu 83 */ 84 public enum MODE { 85 /** 86 * Standard mode to view pictures. 87 */ 88 NORMAL, 89 /** 90 * Mode when in walk. 91 */ 92 WALK 93 } 94 95 /** 96 * Object containing the shown image and that handles zoom and drag 97 */ 98 public StreetsideImageDisplay streetsideImageDisplay; 99 100 private StreetsideCache imageCache; 101 public StreetsideCache thumbnailCache; 102 103 private StreetsideMainDialog() { 104 super(I18n.tr(StreetsideMainDialog.BASE_TITLE), "streetside-main", I18n.tr("Open Streetside window"), null, 200, 105 true, StreetsidePreferenceSetting.class); 106 addShortcuts(); 107 108 streetsideImageDisplay = new StreetsideImageDisplay(); 109 110 blueButton.setForeground(Color.BLUE); 111 redButton.setForeground(Color.RED); 112 113 // TODO: Modes for cubemaps? @rrh 114 setMode(MODE.NORMAL); 115 } 116 117 /** 118 * Adds the shortcuts to the buttons. 119 */ 120 private void addShortcuts() { 121 nextButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( 122 KeyStroke.getKeyStroke("PAGE_DOWN"), "next"); 123 nextButton.getActionMap().put("next", new NextPictureAction()); 124 previousButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( 125 KeyStroke.getKeyStroke("PAGE_UP"), "previous"); 126 previousButton.getActionMap().put("previous", 127 new PreviousPictureAction()); 128 blueButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( 129 KeyStroke.getKeyStroke("control PAGE_UP"), "blue"); 130 blueButton.getActionMap().put("blue", new BlueAction()); 131 redButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( 132 KeyStroke.getKeyStroke("control PAGE_DOWN"), "red"); 133 redButton.getActionMap().put("red", new RedAction()); 134 } 135 136 /** 137 * Returns the unique instance of the class. 138 * 139 * @return The unique instance of the class. 140 */ 141 public static synchronized StreetsideMainDialog getInstance() { 142 if (StreetsideMainDialog.instance == null) { 143 StreetsideMainDialog.instance = new StreetsideMainDialog(); 144 } 145 return StreetsideMainDialog.instance; 146 } 147 148 /** 149 * @return true, iff the singleton instance is present 150 */ 151 public static boolean hasInstance() { 152 return StreetsideMainDialog.instance != null; 153 } 154 155 public synchronized void setImageInfoHelp(ImageInfoHelpPopup popup) { 156 imageInfoHelp = popup; 157 } 158 159 public synchronized void setStreetsideViewerHelp(StreetsideViewerHelpPopup popup) { 160 streetsideViewerHelp = popup; 161 } 162 163 /** 164 * @return the streetsideViewerHelp 165 */ 166 public StreetsideViewerHelpPopup getStreetsideViewerHelp() { 167 return streetsideViewerHelp; 168 } 169 170 /** 171 * Sets a new mode for the dialog. 172 * 173 * @param mode The mode to be set. Must not be {@code null}. 174 */ 175 public void setMode(MODE mode) { 176 switch (mode) { 177 case WALK: 178 createLayout( 179 streetsideImageDisplay, 180 Arrays.asList(playButton, pauseButton, stopButton) 181 ); 182 case NORMAL: 183 default: 184 createLayout( 185 streetsideImageDisplay, 186 Arrays.asList(blueButton, previousButton, nextButton, redButton) 187 ); 188 } 189 disableAllButtons(); 190 if (MODE.NORMAL.equals(mode)) { 191 updateImage(); 192 } } 193 194 /** 195 * Destroys the unique instance of the class. 196 */ 197 public static synchronized void destroyInstance() { 198 StreetsideMainDialog.instance = null; 199 } 200 201 /** 202 * Downloads the full quality picture of the selected StreetsideImage and sets 203 * in the StreetsideImageDisplay object. 204 */ 205 public synchronized void updateImage() { 206 updateImage(true); 207 } 208 209 /** 210 * Downloads the picture of the selected StreetsideImage and sets in the 211 * StreetsideImageDisplay object. 212 * 213 * @param fullQuality If the full quality picture must be downloaded or just the 214 * thumbnail. 215 */ 216 public synchronized void updateImage(boolean fullQuality) { 217 if (!SwingUtilities.isEventDispatchThread()) { 218 SwingUtilities.invokeLater(this::updateImage); 219 } else { 220 if (!StreetsideLayer.hasInstance()) { 221 return; 222 } 223 if (image == null) { 224 streetsideImageDisplay.setImage(null, null); 225 setTitle(I18n.tr(StreetsideMainDialog.BASE_TITLE)); 226 disableAllButtons(); 227 return; 228 } 229 230 // TODO: help for cubemaps? @rrh 231 if (imageInfoHelp != null && StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.get() > 0 && imageInfoHelp.showPopup()) { 232 // Count down the number of times the popup will be displayed 233 StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.put(StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.get() - 1); 234 } 235 236 // Enables/disables next/previous buttons 237 nextButton.setEnabled(false); 238 previousButton.setEnabled(false); 239 if (image.getSequence() != null) { 240 StreetsideAbstractImage tempImage = image; 241 while (tempImage.next() != null) { 242 tempImage = tempImage.next(); 243 if (tempImage.isVisible()) { 244 nextButton.setEnabled(true); 245 break; 246 } 247 } 248 } 249 if (image.getSequence() != null) { 250 StreetsideAbstractImage tempImage = image; 251 while (tempImage.previous() != null) { 252 tempImage = tempImage.previous(); 253 if (tempImage.isVisible()) { 254 previousButton.setEnabled(true); 255 break; 256 } 257 } 258 } 259 if (image instanceof StreetsideImage) { 260 final StreetsideImage streetsideImage = (StreetsideImage) image; 261 // Downloads the thumbnail. 262 streetsideImageDisplay.setImage(null, null); 263 if (thumbnailCache != null) { 264 thumbnailCache.cancelOutstandingTasks(); 265 } 266 thumbnailCache = new StreetsideCache(streetsideImage.getId(), 267 StreetsideCache.Type.THUMBNAIL); 268 try { 269 thumbnailCache.submit(this, false); 270 } catch (final IOException e) { 271 Logging.error(e); 272 } 273 274 // Downloads the full resolution image. 275 if (fullQuality || new StreetsideCache(streetsideImage.getId(), 276 StreetsideCache.Type.FULL_IMAGE).get() != null) { 277 if (imageCache != null) { 278 imageCache.cancelOutstandingTasks(); 279 } 280 imageCache = new StreetsideCache(streetsideImage.getId(), 281 StreetsideCache.Type.FULL_IMAGE); 282 try { 283 imageCache.submit(this, false); 284 } catch (final IOException e) { 285 Logging.error(e); 286 } 287 } 288 // TODO: handle/convert/remove "imported images" 289 } /*else if (image instanceof StreetsideImportedImage) { 290 final StreetsideImportedImage streetsideImage = (StreetsideImportedImage) image; 291 try { 292 streetsideImageDisplay.setImage(streetsideImage.getImage(), null); 293 } catch (final IOException e) { 294 Logging.error(e); 295 } 296 }*/ 297 updateTitle(); 298 } 299 } 300 301 /** 302 * Disables all the buttons in the dialog 303 */ 304 public /*private*/ void disableAllButtons() { 305 nextButton.setEnabled(false); 306 previousButton.setEnabled(false); 307 blueButton.setEnabled(false); 308 redButton.setEnabled(false); 309 } 310 311 /** 312 * Sets a new StreetsideImage to be shown. 313 * 314 * @param image The image to be shown. 315 */ 316 public synchronized void setImage(StreetsideAbstractImage image) { 317 this.image = image; 318 } 319 320 /** 321 * Updates the title of the dialog. 322 */ 323 // TODO: update title for 360 degree viewer? @rrh 324 public synchronized void updateTitle() { 325 if (!SwingUtilities.isEventDispatchThread()) { 326 SwingUtilities.invokeLater(this::updateTitle); 327 } else if (image != null) { 328 final StringBuilder title = new StringBuilder(I18n.tr(StreetsideMainDialog.BASE_TITLE)); 329 if (image instanceof StreetsideImage) { 330 final StreetsideImage streetsideImage = (StreetsideImage) image; 331 if (streetsideImage.getCd() != 0) { 332 title.append(StreetsideMainDialog.MESSAGE_SEPARATOR).append(streetsideImage.getDate()); 333 } 334 setTitle(title.toString()); 335 } else if (image instanceof StreetsideImportedImage) { 336 final StreetsideImportedImage mapillaryImportedImage = (StreetsideImportedImage) image; 337 title.append(StreetsideMainDialog.MESSAGE_SEPARATOR).append(mapillaryImportedImage.getFile().getName()); 338 title.append(StreetsideMainDialog.MESSAGE_SEPARATOR).append(mapillaryImportedImage.getDate()); 339 setTitle(title.toString()); 340 } 341 } 342 } 343 344 /** 345 * Returns the {@link StreetsideAbstractImage} object which is being shown. 346 * 347 * @return The {@link StreetsideAbstractImage} object which is being shown. 348 */ 349 public synchronized StreetsideAbstractImage getImage() { 350 return image; 351 } 352 353 /** 354 * Action class form the next image button. 355 * 356 * @author nokutu 357 */ 358 private static class NextPictureAction extends AbstractAction { 359 360 private static final long serialVersionUID = 6333692154558730392L; 361 362 /** 363 * Constructs a normal NextPictureAction 364 */ 365 NextPictureAction() { 366 super(I18n.tr("Next picture")); 367 putValue(Action.SHORT_DESCRIPTION, I18n.tr("Shows the next picture in the sequence")); 368 new ImageProvider("help", "next").getResource().attachImageIcon(this, true); 369 } 370 371 @Override 372 public void actionPerformed(ActionEvent e) { 373 StreetsideLayer.getInstance().getData().selectNext(); 374 } 375 } 376 377 /** 378 * Action class for the previous image button. 379 * 380 * @author nokutu 381 */ 382 private static class PreviousPictureAction extends AbstractAction { 383 384 private static final long serialVersionUID = 4390593660514657107L; 385 386 /** 387 * Constructs a normal PreviousPictureAction 388 */ 389 PreviousPictureAction() { 390 super(I18n.tr("Previous picture")); 391 putValue(Action.SHORT_DESCRIPTION, I18n.tr("Shows the previous picture in the sequence")); 392 new ImageProvider("help", "previous").getResource().attachImageIcon(this, true); 393 } 394 395 @Override 396 public void actionPerformed(ActionEvent e) { 397 StreetsideLayer.getInstance().getData().selectPrevious(); 398 } 399 } 400 401 /** 402 * Action class to jump to the image following the red line. 403 * 404 * @author nokutu 405 */ 406 private static class RedAction extends AbstractAction { 407 408 private static final long serialVersionUID = -1244456062285831231L; 409 410 /** 411 * Constructs a normal RedAction 412 */ 413 RedAction() { 414 putValue(Action.NAME, I18n.tr("Jump to red")); 415 putValue(Action.SHORT_DESCRIPTION, 416 I18n.tr("Jumps to the picture at the other side of the red line")); 417 new ImageProvider("dialogs", "red").getResource().attachImageIcon(this, true); 418 } 419 420 // TODO: RedAction for cubemaps? @rrh 421 @Override 422 public void actionPerformed(ActionEvent e) { 423 if (StreetsideMainDialog.getInstance().getImage() != null) { 424 StreetsideLayer.getInstance().getData() 425 .setSelectedImage(StreetsideLayer.getInstance().getNNearestImage(1), true); 426 } 427 } 428 } 429 430 /** 431 * Action class to jump to the image following the blue line. 432 * 433 * @author nokutu 434 */ 435 private static class BlueAction extends AbstractAction { 436 437 private static final long serialVersionUID = 5951233534212838780L; 438 439 /** 440 * Constructs a normal BlueAction 441 */ 442 BlueAction() { 443 putValue(Action.NAME, I18n.tr("Jump to blue")); 444 putValue(Action.SHORT_DESCRIPTION, 445 I18n.tr("Jumps to the picture at the other side of the blue line")); 446 new ImageProvider("dialogs", "blue").getResource().attachImageIcon(this, true); 447 } 448 449 // TODO: BlueAction for cubemaps? 450 @Override 451 public void actionPerformed(ActionEvent e) { 452 if (StreetsideMainDialog.getInstance().getImage() != null) { 453 StreetsideLayer.getInstance().getData() 454 .setSelectedImage(StreetsideLayer.getInstance().getNNearestImage(2), true); 455 } 456 } 457 } 458 459 private static class StopAction extends AbstractAction implements WalkListener { 460 461 private static final long serialVersionUID = 8789972456611625341L; 462 463 private WalkThread thread; 464 465 /** 466 * Constructs a normal StopAction 467 */ 468 StopAction() { 469 putValue(Action.NAME, I18n.tr("Stop")); 470 putValue(Action.SHORT_DESCRIPTION, I18n.tr("Stops the walk.")); 471 new ImageProvider("dialogs/streetsideStop.png").getResource().attachImageIcon(this, true); 472 StreetsidePlugin.getStreetsideWalkAction().addListener(this); 473 } 474 475 @Override 476 public void actionPerformed(ActionEvent e) { 477 if (thread != null) { 478 thread.stopWalk(); 479 } 480 } 481 482 @Override 483 public void walkStarted(WalkThread thread) { 484 this.thread = thread; 485 } 486 } 487 488 private static class PlayAction extends AbstractAction implements WalkListener { 489 490 private static final long serialVersionUID = -1572747020946842769L; 491 492 private transient WalkThread thread; 493 494 /** 495 * Constructs a normal PlayAction 496 */ 497 PlayAction() { 498 putValue(Action.NAME, I18n.tr("Play")); 499 putValue(Action.SHORT_DESCRIPTION, I18n.tr("Continues with the paused walk.")); 500 new ImageProvider("dialogs/streetsidePlay.png").getResource().attachImageIcon(this, true); 501 StreetsidePlugin.getStreetsideWalkAction().addListener(this); 502 } 503 504 @Override 505 public void actionPerformed(ActionEvent e) { 506 if (thread != null) { 507 thread.play(); 508 } 509 } 510 511 @Override 512 public void walkStarted(WalkThread thread) { 513 if (thread != null) { 514 this.thread = thread; 515 } 516 } 517 } 518 519 private static class PauseAction extends AbstractAction implements WalkListener { 520 521 /** 522 * 523 */ 524 private static final long serialVersionUID = -8758326399460817222L; 525 private WalkThread thread; 526 527 /** 528 * Constructs a normal PauseAction 529 */ 530 PauseAction() { 531 putValue(Action.NAME, I18n.tr("Pause")); 532 putValue(Action.SHORT_DESCRIPTION, I18n.tr("Pauses the walk.")); 533 new ImageProvider("dialogs/streetsidePause.png").getResource().attachImageIcon(this, true); 534 StreetsidePlugin.getStreetsideWalkAction().addListener(this); 535 } 536 537 @Override 538 public void actionPerformed(ActionEvent e) { 539 thread.pause(); 540 } 541 542 @Override 543 public void walkStarted(WalkThread thread) { 544 this.thread = thread; 545 } 546 } 547 548 /** 549 * When the pictures are returned from the cache, they are set in the 550 * {@link StreetsideImageDisplay} object. 551 */ 552 @Override 553 public void loadingFinished(final CacheEntry data, final CacheEntryAttributes attributes, final LoadResult result) { 554 if (!SwingUtilities.isEventDispatchThread()) { 555 SwingUtilities.invokeLater(() -> loadingFinished(data, attributes, result)); 556 557 } else if (data != null && result == LoadResult.SUCCESS) { 558 try { 559 final BufferedImage img = ImageIO.read(new ByteArrayInputStream(data.getContent())); 560 if (img == null) { 561 return; 562 } 563 if ( 564 streetsideImageDisplay.getImage() == null 565 || img.getHeight() > streetsideImageDisplay.getImage().getHeight() 566 ) { 567 //final StreetsideAbstractImage mai = getImage(); 568 streetsideImageDisplay.setImage( 569 img, 570 //mai instanceof StreetsideImage ? ((StreetsideImage) getImage()).getDetections() : null 571 null); 572 } 573 } catch (final IOException e) { 574 Logging.error(e); 575 } 576 } 577 } 578 579 580 /** 581 * Creates the layout of the dialog. 582 * 583 * @param data The content of the dialog 584 * @param buttons The buttons where you can click 585 */ 586 public void createLayout(Component data, List<SideButton> buttons) { 587 removeAll(); 588 createLayout(data, true, buttons); 589 add(titleBar, BorderLayout.NORTH); 590 } 591 592 @Override 593 public void selectedImageChanged(StreetsideAbstractImage oldImage, StreetsideAbstractImage newImage) { 594 setImage(newImage); 595 updateImage(); 596 } 597 598 @Override 599 public void imagesAdded() { 600 // This method is enforced by StreetsideDataListener, but only selectedImageChanged() is needed 601 } 602 603 /** 604 * @return the streetsideImageDisplay 605 */ 606 public StreetsideImageDisplay getStreetsideImageDisplay() { 607 return streetsideImageDisplay; 608 } 609 610 /** 611 * @param streetsideImageDisplay the streetsideImageDisplay to set 612 */ 613 public void setStreetsideImageDisplay(StreetsideImageDisplay streetsideImageDisplay) { 614 this.streetsideImageDisplay = streetsideImageDisplay; 615 } 616 617 /** 618 * @return the streetsideImageDisplay 619 */ 620 /*public StreetsideViewerDisplay getStreetsideViewerDisplay() { 621 return streetsideViewerDisplay; 622 }*/ 623 624 /** 625 * @param streetsideImageDisplay the streetsideImageDisplay to set 626 */ 627 /*public void setStreetsideViewerDisplay(StreetsideViewerDisplay streetsideViewerDisplay) { 628 streetsideViewerDisplay = streetsideViewerDisplay; 629 }*/ 630 631 /*private StreetsideViewerDisplay initStreetsideViewerDisplay() { 632 StreetsideViewerDisplay res = new StreetsideViewerDisplay(); 633 //this.add(streetsideViewerDisplay); 634 635 636 Platform.runLater(new Runnable() { 637 @Override 638 public void run() { 639 Scene scene; 640 try { 641 scene = StreetsideViewerDisplay.createScene(); 642 res.setScene(scene); 643 } catch (NonInvertibleTransformException e) { 644 // TODO Auto-generated catch block 645 e.printStackTrace(); 646 } 647 } 648 }); 649 return res; 650 }*/ 50 ICachedLoaderListener, StreetsideDataListener { 51 52 private static final long serialVersionUID = 6856496736429480600L; 53 54 private static final String BASE_TITLE = marktr("Streetside image"); 55 private static final String MESSAGE_SEPARATOR = " — "; 56 57 private static StreetsideMainDialog instance; 58 59 private volatile StreetsideAbstractImage image; 60 61 private final SideButton nextButton = new SideButton(new NextPictureAction()); 62 private final SideButton previousButton = new SideButton(new PreviousPictureAction()); 63 /** 64 * Button used to jump to the image following the red line 65 */ 66 public final SideButton redButton = new SideButton(new RedAction()); 67 /** 68 * Button used to jump to the image following the blue line 69 */ 70 public final SideButton blueButton = new SideButton(new BlueAction()); 71 72 private final SideButton playButton = new SideButton(new PlayAction()); 73 private final SideButton pauseButton = new SideButton(new PauseAction()); 74 private final SideButton stopButton = new SideButton(new StopAction()); 75 76 private ImageInfoHelpPopup imageInfoHelp; 77 78 /** 79 * Buttons mode. 80 * 81 * @author nokutu 82 */ 83 public enum MODE { 84 /** 85 * Standard mode to view pictures. 86 */ 87 NORMAL, 88 /** 89 * Mode when in walk. 90 */ 91 WALK 92 } 93 94 /** 95 * Object containing the shown image and that handles zoom and drag 96 */ 97 public final StreetsideImageDisplay streetsideImageDisplay; 98 99 private StreetsideCache imageCache; 100 private StreetsideCache thumbnailCache; 101 102 private StreetsideMainDialog() { 103 super(tr(BASE_TITLE), "streetside-main", tr("Open Streetside window"), null, 200, 104 true, StreetsidePreferenceSetting.class); 105 addShortcuts(); 106 streetsideImageDisplay = new StreetsideImageDisplay(); 107 108 blueButton.setForeground(Color.BLUE); 109 redButton.setForeground(Color.RED); 110 111 setMode(MODE.NORMAL); 112 } 113 114 /** 115 * Adds the shortcuts to the buttons. 116 */ 117 private void addShortcuts() { 118 nextButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( 119 KeyStroke.getKeyStroke("PAGE_DOWN"), "next"); 120 nextButton.getActionMap().put("next", new NextPictureAction()); 121 previousButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( 122 KeyStroke.getKeyStroke("PAGE_UP"), "previous"); 123 previousButton.getActionMap().put("previous", 124 new PreviousPictureAction()); 125 blueButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( 126 KeyStroke.getKeyStroke("control PAGE_UP"), "blue"); 127 blueButton.getActionMap().put("blue", new BlueAction()); 128 redButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( 129 KeyStroke.getKeyStroke("control PAGE_DOWN"), "red"); 130 redButton.getActionMap().put("red", new RedAction()); 131 } 132 133 /** 134 * Returns the unique instance of the class. 135 * 136 * @return The unique instance of the class. 137 */ 138 public static synchronized StreetsideMainDialog getInstance() { 139 if (instance == null) 140 instance = new StreetsideMainDialog(); 141 return instance; 142 } 143 144 /** 145 * @return true, iff the singleton instance is present 146 */ 147 public static boolean hasInstance() { 148 return instance != null; 149 } 150 151 public synchronized void setImageInfoHelp(ImageInfoHelpPopup popup) { 152 imageInfoHelp = popup; 153 } 154 155 /** 156 * Sets a new mode for the dialog. 157 * 158 * @param mode The mode to be set. Must not be {@code null}. 159 */ 160 public void setMode(MODE mode) { 161 switch (mode) { 162 case WALK: 163 createLayout( 164 streetsideImageDisplay, 165 Arrays.asList(playButton, pauseButton, stopButton) 166 ); 167 break; 168 case NORMAL: 169 default: 170 createLayout( 171 streetsideImageDisplay, 172 Arrays.asList(blueButton, previousButton, nextButton, redButton) 173 ); 174 break; 175 } 176 disableAllButtons(); 177 if (MODE.NORMAL.equals(mode)) { 178 updateImage(); 179 } 180 revalidate(); 181 repaint(); 182 } 183 184 /** 185 * Destroys the unique instance of the class. 186 */ 187 public static synchronized void destroyInstance() { 188 instance = null; 189 } 190 191 /** 192 * Downloads the full quality picture of the selected StreetsideImage and sets 193 * in the StreetsideImageDisplay object. 194 */ 195 public synchronized void updateImage() { 196 updateImage(true); 197 } 198 199 /** 200 * Downloads the picture of the selected StreetsideImage and sets in the 201 * StreetsideImageDisplay object. 202 * 203 * @param fullQuality If the full quality picture must be downloaded or just the 204 * thumbnail. 205 */ 206 public synchronized void updateImage(boolean fullQuality) { 207 if (!SwingUtilities.isEventDispatchThread()) { 208 SwingUtilities.invokeLater(this::updateImage); 209 } else { 210 if (!StreetsideLayer.hasInstance()) { 211 return; 212 } 213 if (image == null) { 214 streetsideImageDisplay.setImage(null, null); 215 setTitle(tr(BASE_TITLE)); 216 disableAllButtons(); 217 return; 218 } 219 220 if (imageInfoHelp != null && StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.get() > 0 && imageInfoHelp.showPopup()) { 221 // Count down the number of times the popup will be displayed 222 StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.put(StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.get() - 1); 223 } 224 225 // Enables/disables next/previous buttons 226 nextButton.setEnabled(false); 227 previousButton.setEnabled(false); 228 if (image.getSequence() != null) { 229 StreetsideAbstractImage tempImage = image; 230 while (tempImage.next() != null) { 231 tempImage = tempImage.next(); 232 if (tempImage.isVisible()) { 233 nextButton.setEnabled(true); 234 break; 235 } 236 } 237 } 238 if (image.getSequence() != null) { 239 StreetsideAbstractImage tempImage = image; 240 while (tempImage.previous() != null) { 241 tempImage = tempImage.previous(); 242 if (tempImage.isVisible()) { 243 previousButton.setEnabled(true); 244 break; 245 } 246 } 247 } 248 if (image instanceof StreetsideImage) { 249 StreetsideImage streetsideImage = (StreetsideImage) image; 250 // Downloads the thumbnail. 251 streetsideImageDisplay.setImage(null, null); 252 if (thumbnailCache != null) 253 thumbnailCache.cancelOutstandingTasks(); 254 thumbnailCache = new StreetsideCache(streetsideImage.getId(), 255 StreetsideCache.Type.THUMBNAIL); 256 try { 257 thumbnailCache.submit(this, false); 258 } catch (IOException e) { 259 Logging.error(e); 260 } 261 262 // Downloads the full resolution image. 263 if (fullQuality || new StreetsideCache(streetsideImage.getId(), 264 StreetsideCache.Type.FULL_IMAGE).get() != null) { 265 if (imageCache != null) 266 imageCache.cancelOutstandingTasks(); 267 imageCache = new StreetsideCache(streetsideImage.getId(), 268 StreetsideCache.Type.FULL_IMAGE); 269 try { 270 imageCache.submit(this, false); 271 } catch (IOException e) { 272 Logging.error(e); 273 } 274 } 275 } else if (image instanceof StreetsideImportedImage) { 276 StreetsideImportedImage streetsideImage = (StreetsideImportedImage) image; 277 try { 278 streetsideImageDisplay.setImage(streetsideImage.getImage(), null); 279 } catch (IOException e) { 280 Logging.error(e); 281 } 282 } 283 updateTitle(); 284 } 285 286 } 287 288 /** 289 * Disables all the buttons in the dialog 290 */ 291 private void disableAllButtons() { 292 nextButton.setEnabled(false); 293 previousButton.setEnabled(false); 294 blueButton.setEnabled(false); 295 redButton.setEnabled(false); 296 } 297 298 /** 299 * Sets a new StreetsideImage to be shown. 300 * 301 * @param image The image to be shown. 302 */ 303 public synchronized void setImage(StreetsideAbstractImage image) { 304 this.image = image; 305 } 306 307 /** 308 * Updates the title of the dialog. 309 */ 310 public synchronized void updateTitle() { 311 if (!SwingUtilities.isEventDispatchThread()) { 312 SwingUtilities.invokeLater(this::updateTitle); 313 } else if (image != null) { 314 StringBuilder title = new StringBuilder(tr(BASE_TITLE)); 315 if (image instanceof StreetsideImage) { 316 StreetsideImage streetsideImage = (StreetsideImage) image; 317 UserProfile user = streetsideImage.getUser(); 318 if (user != null) { 319 title.append(MESSAGE_SEPARATOR).append(user.getUsername()); 320 } 321 if (streetsideImage.getCd() != 0) { 322 title.append(MESSAGE_SEPARATOR).append(streetsideImage.getDate()); 323 } 324 setTitle(title.toString()); 325 } else if (image instanceof StreetsideImportedImage) { 326 StreetsideImportedImage streetsideImportedImage = (StreetsideImportedImage) image; 327 title.append(MESSAGE_SEPARATOR).append(streetsideImportedImage.getFile().getName()); 328 title.append(MESSAGE_SEPARATOR).append(streetsideImportedImage.getDate()); 329 setTitle(title.toString()); 330 } 331 } 332 } 333 334 /** 335 * Returns the {@link StreetsideAbstractImage} object which is being shown. 336 * 337 * @return The {@link StreetsideAbstractImage} object which is being shown. 338 */ 339 public synchronized StreetsideAbstractImage getImage() { 340 return image; 341 } 342 343 /** 344 * Action class form the next image button. 345 * 346 * @author nokutu 347 */ 348 private static class NextPictureAction extends AbstractAction { 349 350 private static final long serialVersionUID = 3023827221453154340L; 351 352 /** 353 * Constructs a normal NextPictureAction 354 */ 355 NextPictureAction() { 356 super(tr("Next picture")); 357 putValue(SHORT_DESCRIPTION, tr("Shows the next picture in the sequence")); 358 new ImageProvider("dialogs", "next").getResource().attachImageIcon(this, true); 359 } 360 361 @Override 362 public void actionPerformed(ActionEvent e) { 363 StreetsideLayer.getInstance().getData().selectNext(); 364 } 365 } 366 367 /** 368 * Action class for the previous image button. 369 * 370 * @author nokutu 371 */ 372 private static class PreviousPictureAction extends AbstractAction { 373 374 private static final long serialVersionUID = -6420511632957956012L; 375 376 /** 377 * Constructs a normal PreviousPictureAction 378 */ 379 PreviousPictureAction() { 380 super(tr("Previous picture")); 381 putValue(SHORT_DESCRIPTION, tr("Shows the previous picture in the sequence")); 382 new ImageProvider("dialogs", "previous").getResource().attachImageIcon(this, true); 383 } 384 385 @Override 386 public void actionPerformed(ActionEvent e) { 387 StreetsideLayer.getInstance().getData().selectPrevious(); 388 } 389 } 390 391 /** 392 * Action class to jump to the image following the red line. 393 * 394 * @author nokutu 395 */ 396 private static class RedAction extends AbstractAction { 397 398 private static final long serialVersionUID = -6480229431481386376L; 399 400 /** 401 * Constructs a normal RedAction 402 */ 403 RedAction() { 404 putValue(NAME, tr("Jump to red")); 405 putValue(SHORT_DESCRIPTION, 406 tr("Jumps to the picture at the other side of the red line")); 407 new ImageProvider("dialogs", "red").getResource().attachImageIcon(this, true); 408 } 409 410 @Override 411 public void actionPerformed(ActionEvent e) { 412 if (StreetsideMainDialog.getInstance().getImage() != null) { 413 StreetsideLayer.getInstance().getData() 414 .setSelectedImage(StreetsideLayer.getInstance().getNNearestImage(1), true); 415 } 416 } 417 } 418 419 /** 420 * Action class to jump to the image following the blue line. 421 * 422 * @author nokutu 423 */ 424 private static class BlueAction extends AbstractAction { 425 426 private static final long serialVersionUID = 6250690644594703314L; 427 428 /** 429 * Constructs a normal BlueAction 430 */ 431 BlueAction() { 432 putValue(NAME, tr("Jump to blue")); 433 putValue(SHORT_DESCRIPTION, 434 tr("Jumps to the picture at the other side of the blue line")); 435 new ImageProvider("dialogs", "blue").getResource().attachImageIcon(this, true); 436 } 437 438 @Override 439 public void actionPerformed(ActionEvent e) { 440 if (StreetsideMainDialog.getInstance().getImage() != null) { 441 StreetsideLayer.getInstance().getData() 442 .setSelectedImage(StreetsideLayer.getInstance().getNNearestImage(2), true); 443 } 444 } 445 } 446 447 private static class StopAction extends AbstractAction implements WalkListener { 448 449 private static final long serialVersionUID = -6561451575815789198L; 450 451 private WalkThread thread; 452 453 /** 454 * Constructs a normal StopAction 455 */ 456 StopAction() { 457 putValue(NAME, trc("as synonym to halt or stand still", "Stop")); 458 putValue(SHORT_DESCRIPTION, tr("Stops the walk.")); 459 new ImageProvider("dialogs/streetsideStop.png").getResource().attachImageIcon(this, true); 460 StreetsidePlugin.getWalkAction().addListener(this); 461 } 462 463 @Override 464 public void actionPerformed(ActionEvent e) { 465 if (thread != null) 466 thread.stopWalk(); 467 } 468 469 @Override 470 public void walkStarted(WalkThread thread) { 471 this.thread = thread; 472 } 473 } 474 475 private static class PlayAction extends AbstractAction implements WalkListener { 476 477 private static final long serialVersionUID = -17943404752082788L; 478 private transient WalkThread thread; 479 480 /** 481 * Constructs a normal PlayAction 482 */ 483 PlayAction() { 484 putValue(NAME, tr("Play")); 485 putValue(SHORT_DESCRIPTION, tr("Continues with the paused walk.")); 486 new ImageProvider("dialogs/streetsidePlay.png").getResource().attachImageIcon(this, true); 487 StreetsidePlugin.getWalkAction().addListener(this); 488 } 489 490 @Override 491 public void actionPerformed(ActionEvent e) { 492 if (thread != null) 493 thread.play(); 494 } 495 496 @Override 497 public void walkStarted(WalkThread thread) { 498 if (thread != null) 499 this.thread = thread; 500 } 501 } 502 503 private static class PauseAction extends AbstractAction implements WalkListener { 504 505 private static final long serialVersionUID = 4400240686337741192L; 506 507 private WalkThread thread; 508 509 /** 510 * Constructs a normal PauseAction 511 */ 512 PauseAction() { 513 putValue(NAME, tr("Pause")); 514 putValue(SHORT_DESCRIPTION, tr("Pauses the walk.")); 515 new ImageProvider("dialogs/streetsidePause.png").getResource().attachImageIcon(this, true); 516 StreetsidePlugin.getWalkAction().addListener(this); 517 } 518 519 @Override 520 public void actionPerformed(ActionEvent e) { 521 thread.pause(); 522 } 523 524 @Override 525 public void walkStarted(WalkThread thread) { 526 this.thread = thread; 527 } 528 } 529 530 /** 531 * When the pictures are returned from the cache, they are set in the 532 * {@link StreetsideImageDisplay} object. 533 */ 534 /*@Override 535 public void loadingFinished(final CacheEntry data, final CacheEntryAttributes attributes, final LoadResult result) { 536 if (!SwingUtilities.isEventDispatchThread()) { 537 SwingUtilities.invokeLater(() -> loadingFinished(data, attributes, result)); 538 } else if (data != null && result == LoadResult.SUCCESS) { 539 try { 540 BufferedImage img = ImageIO.read(new ByteArrayInputStream(data.getContent())); 541 if (img == null) { 542 return; 543 } 544 if ( 545 streetsideImageDisplay.getImage() == null 546 || img.getHeight() > this.streetsideImageDisplay.getImage().getHeight() 547 ) { 548 final StreetsideAbstractImage mai = getImage(); 549 this.streetsideImageDisplay.setImage( 550 img, 551 mai instanceof StreetsideImage ? ((StreetsideImage) getImage()).getDetections() : null 552 ); 553 } 554 } catch (IOException e) { 555 Logging.error(e); 556 } 557 } 558 }*/ 559 560 /** 561 * When the pictures are returned from the cache, they are set in the 562 * {@link StreetsideImageDisplay} object. 563 */ 564 @Override 565 public void loadingFinished(final CacheEntry data, final CacheEntryAttributes attributes, final LoadResult result) { 566 if (!SwingUtilities.isEventDispatchThread()) { 567 SwingUtilities.invokeLater(() -> loadingFinished(data, attributes, result)); 568 569 } else if (data != null && result == LoadResult.SUCCESS) { 570 try { 571 final BufferedImage img = ImageIO.read(new ByteArrayInputStream(data.getContent())); 572 if (img == null) { 573 return; 574 } 575 if ( 576 streetsideImageDisplay.getImage() == null 577 || img.getHeight() > streetsideImageDisplay.getImage().getHeight() 578 ) { 579 //final StreetsideAbstractImage mai = getImage(); 580 streetsideImageDisplay.setImage( 581 img, 582 //mai instanceof StreetsideImage ? ((StreetsideImage) getImage()).getDetections() : null 583 null); 584 } 585 } catch (final IOException e) { 586 Logging.error(e); 587 } 588 } 589 } 590 591 /** 592 * Creates the layout of the dialog. 593 * 594 * @param data The content of the dialog 595 * @param buttons The buttons where you can click 596 */ 597 public void createLayout(Component data, List<SideButton> buttons) { 598 removeAll(); 599 createLayout(data, true, buttons); 600 add(titleBar, BorderLayout.NORTH); 601 } 602 603 @Override 604 public void selectedImageChanged(StreetsideAbstractImage oldImage, StreetsideAbstractImage newImage) { 605 setImage(newImage); 606 updateImage(); 607 } 608 609 @Override 610 public void imagesAdded() { 611 // This method is enforced by StreetsideDataListener, but only selectedImageChanged() is needed 612 } 613 651 614 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/StreetsideViewerPanel.java
r34325 r34333 84 84 checkPanel.add(privacyLink, BorderLayout.PAGE_END); 85 85 86 add(checkPanel, BorderLayout. PAGE_START);86 add(checkPanel, BorderLayout.SOUTH); 87 87 add(threeSixtyDegreeViewerPanel, BorderLayout.CENTER); 88 88 -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/SequenceDownloadRunnable.java
r34317 r34333 48 48 } 49 49 50 StreetsideSequence seq = new StreetsideSequence(StreetsideSequenceIdGenerator.generateId()); 50 StreetsideSequence seq = new StreetsideSequence(null); 51 // TODO: re-add sequenceID 52 //StreetsideSequence seq = new StreetsideSequence(StreetsideSequenceIdGenerator.generateId()); 51 53 52 54 // TODO: how can LatLon and heading / camera angles (he attribute) be set for a sequence?
Note:
See TracChangeset
for help on using the changeset viewer.