Changeset 31298 in osm for applications/editors/josm/plugins
- Timestamp:
- 2015-06-23T12:17:27+02:00 (9 years ago)
- Location:
- applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary
- Files:
-
- 1 deleted
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java
r31297 r31298 2 2 3 3 import static org.openstreetmap.josm.tools.I18n.tr; 4 import static org.openstreetmap.josm.tools.I18n.marktr; 4 5 5 6 import org.apache.commons.jcs.access.CacheAccess; … … 34 35 import org.openstreetmap.josm.data.osm.event.DataSetListener; 35 36 37 import java.awt.AlphaComposite; 36 38 import java.awt.Color; 39 import java.awt.Composite; 37 40 import java.awt.Graphics2D; 38 41 import java.awt.Image; 39 42 import java.awt.Point; 43 import java.awt.Rectangle; 44 import java.awt.TexturePaint; 40 45 import java.awt.event.MouseAdapter; 41 46 import java.awt.geom.AffineTransform; 47 import java.awt.geom.Area; 42 48 import java.awt.image.AffineTransformOp; 43 49 import java.awt.image.BufferedImage; … … 53 59 54 60 public class MapillaryLayer extends AbstractModifiableLayer implements 55 DataSetListener, EditLayerChangeListener, LayerChangeListener { 56 57 public final static int SEQUENCE_MAX_JUMP_DISTANCE = Main.pref.getInteger( 58 "mapillary.sequence-max-jump-distance", 100); 59 60 public static MapillaryLayer INSTANCE; 61 public static CacheAccess<String, BufferedImageCacheEntry> CACHE; 62 public static MapillaryImage BLUE; 63 public static MapillaryImage RED; 64 65 private final MapillaryData data = MapillaryData.getInstance(); 66 67 public List<Bounds> bounds; 68 69 70 private MouseAdapter mouseAdapter; 71 72 private int highlightPointRadius = Main.pref.getInteger( 73 "mappaint.highlight.radius", 7); 74 private int highlightStep = Main.pref.getInteger("mappaint.highlight.step", 75 4); 76 77 public MapillaryLayer() { 78 super(tr("Mapillary Images")); 79 bounds = new ArrayList<>(); 80 init(); 81 } 82 83 /** 84 * Initializes the Layer. 85 */ 86 private void init() { 87 MapillaryLayer.INSTANCE = this; 88 startMouseAdapter(); 89 try { 90 CACHE = JCSCacheManager.getCache("Mapillary"); 91 } catch (IOException e) { 92 Main.error(e); 93 } 94 if (Main.map != null && Main.map.mapView != null) { 95 Main.map.mapView.addMouseListener(mouseAdapter); 96 Main.map.mapView.addMouseMotionListener(mouseAdapter); 97 Main.map.mapView.addLayer(this); 98 MapView.addEditLayerChangeListener(this, false); 99 MapView.addLayerChangeListener(this); 100 Main.map.mapView.getEditLayer().data.addDataSetListener(this); 101 } 102 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, true); 103 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.SIGN_MENU, true); 104 Main.map.mapView.setActiveLayer(this); 105 Main.map.repaint(); 106 } 107 108 private void startMouseAdapter() { 109 mouseAdapter = new MapillaryMouseAdapter(); 110 } 111 112 public synchronized static MapillaryLayer getInstance() { 113 if (MapillaryLayer.INSTANCE == null) 114 MapillaryLayer.INSTANCE = new MapillaryLayer(); 115 return MapillaryLayer.INSTANCE; 116 } 117 118 /** 119 * Downloads all images of the area covered by the OSM data. This is only 120 * just for automatic download. 121 */ 122 public void download() { 123 checkBigAreas(); 124 if (Main.pref.getBoolean("mapillary.download-manually")) 125 return; 126 for (Bounds bounds : Main.map.mapView.getEditLayer().data 127 .getDataSourceBounds()) { 128 if (!this.bounds.contains(bounds)) { 129 this.bounds.add(bounds); 130 new MapillaryDownloader().getImages(bounds.getMin(), 131 bounds.getMax()); 132 } 133 } 134 } 135 136 /** 137 * Checks if the area of the OSM data is too big. This means that probably 138 * lots of Mapillary images are going to be downloaded, slowing down the 139 * program too much. To solve this the automatic is stopped, an alert is 140 * shown and you will have to download areas manually. 141 */ 142 private void checkBigAreas() { 143 double area = 0; 144 for (Bounds bounds : Main.map.mapView.getEditLayer().data 145 .getDataSourceBounds()) { 146 area += bounds.getArea(); 147 } 148 if (area > MapillaryDownloadViewAction.MAX_AREA) { 149 Main.pref.put("mapillary.download-manually", true); 150 JOptionPane 151 .showMessageDialog( 152 Main.parent, 153 tr("The downloaded OSM area is too big. Download mode has been change to manual. You can change this back to automatic in preferences settings.")); 154 } 155 } 156 157 /** 158 * Returns the MapillaryData object, which acts as the database of the 159 * Layer. 160 * 161 * @return 162 */ 163 public MapillaryData getMapillaryData() { 164 return data; 165 } 166 167 /** 168 * Method invoked when the layer is destroyed. 169 */ 170 @Override 171 public void destroy() { 172 MapillaryToggleDialog.getInstance().mapillaryImageDisplay 173 .setImage(null); 174 data.getImages().clear(); 175 MapillaryLayer.INSTANCE = null; 176 MapillaryData.INSTANCE = null; 177 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, false); 178 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.SIGN_MENU, false); 179 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.ZOOM_MENU, false); 180 Main.map.mapView.removeMouseListener(mouseAdapter); 181 Main.map.mapView.removeMouseMotionListener(mouseAdapter); 182 MapView.removeEditLayerChangeListener(this); 183 if (Main.map.mapView.getEditLayer() != null) 184 Main.map.mapView.getEditLayer().data.removeDataSetListener(this); 185 super.destroy(); 186 } 187 188 /** 189 * Returns true any of the images from the database has been modified. 190 */ 191 @Override 192 public boolean isModified() { 193 for (MapillaryAbstractImage image : data.getImages()) 194 if (image.isModified()) 195 return true; 196 return false; 197 } 198 199 @Override 200 public void setVisible(boolean visible) { 201 super.setVisible(visible); 202 for (MapillaryAbstractImage img : data.getImages()) 203 img.setVisible(visible); 204 MapillaryFilterDialog.getInstance().refresh(); 205 } 206 207 /** 208 * Paints the database in the map. 209 */ 210 @Override 211 public void paint(Graphics2D g, MapView mv, Bounds box) { 212 synchronized (this) { 213 // Draw colored lines 214 MapillaryLayer.BLUE = null; 215 MapillaryLayer.RED = null; 216 MapillaryToggleDialog.getInstance().blueButton.setEnabled(false); 217 MapillaryToggleDialog.getInstance().redButton.setEnabled(false); 218 219 // Sets blue and red lines and enables/disables the buttons 220 if (data.getSelectedImage() != null) { 221 MapillaryImage[] closestImages = getClosestImagesFromDifferentSequences(); 222 Point selected = mv.getPoint(data.getSelectedImage() 223 .getLatLon()); 224 if (closestImages[0] != null) { 225 MapillaryLayer.BLUE = closestImages[0]; 226 g.setColor(Color.BLUE); 227 g.drawLine(mv.getPoint(closestImages[0].getLatLon()).x, 228 mv.getPoint(closestImages[0].getLatLon()).y, 229 selected.x, selected.y); 230 MapillaryToggleDialog.getInstance().blueButton 231 .setEnabled(true); 232 } 233 if (closestImages[1] != null) { 234 MapillaryLayer.RED = closestImages[1]; 235 g.setColor(Color.RED); 236 g.drawLine(mv.getPoint(closestImages[1].getLatLon()).x, 237 mv.getPoint(closestImages[1].getLatLon()).y, 238 selected.x, selected.y); 239 MapillaryToggleDialog.getInstance().redButton 240 .setEnabled(true); 241 } 242 } 243 g.setColor(Color.WHITE); 244 for (MapillaryAbstractImage imageAbs : data.getImages()) { 245 if (!imageAbs.isVisible()) 246 continue; 247 Point p = mv.getPoint(imageAbs.getLatLon()); 248 if (imageAbs instanceof MapillaryImage) { 249 MapillaryImage image = (MapillaryImage) imageAbs; 250 Point nextp; 251 // Draw sequence line 252 if (image.getSequence() != null 253 && image.next() != null && image.next().isVisible()) { 254 nextp = mv.getPoint(image.getSequence().next(image) 255 .getLatLon()); 256 g.drawLine(p.x, p.y, nextp.x, nextp.y); 257 } 258 259 ImageIcon icon; 260 if (!data.getMultiSelectedImages().contains(image)) 261 icon = MapillaryPlugin.MAP_ICON; 262 else 263 icon = MapillaryPlugin.MAP_ICON_SELECTED; 264 draw(g, image, icon, p); 265 if (!image.getSigns().isEmpty()) { 266 g.drawImage(MapillaryPlugin.MAP_SIGN.getImage(), p.x 267 + icon.getIconWidth() / 2, 268 p.y - icon.getIconHeight() / 2, 269 Main.map.mapView); 270 } 271 } else if (imageAbs instanceof MapillaryImportedImage) { 272 MapillaryImportedImage image = (MapillaryImportedImage) imageAbs; 273 ImageIcon icon; 274 if (!data.getMultiSelectedImages().contains(image)) 275 icon = MapillaryPlugin.MAP_ICON_IMPORTED; 276 else 277 icon = MapillaryPlugin.MAP_ICON_SELECTED; 278 draw(g, image, icon, p); 279 } 280 } 281 } 282 } 283 284 /** 285 * Draws the highlight of the icon. 286 * 287 * @param g 288 * @param p 289 * @param size 290 */ 291 private void drawPointHighlight(Graphics2D g, Point p, int size) { 292 Color oldColor = g.getColor(); 293 Color highlightColor = PaintColors.HIGHLIGHT.get(); 294 Color highlightColorTransparent = new Color(highlightColor.getRed(), 295 highlightColor.getGreen(), highlightColor.getBlue(), 100); 296 g.setColor(highlightColorTransparent); 297 int s = size + highlightPointRadius; 298 while (s >= size) { 299 int r = (int) Math.floor(s / 2d); 300 g.fillRoundRect(p.x - r, p.y - r, s, s, r, r); 301 s -= highlightStep; 302 } 303 g.setColor(oldColor); 304 } 305 306 /** 307 * Draws the given icon of an image. Also checks if the mouse is over the 308 * image. 309 * 310 * @param g 311 * @param image 312 * @param icon 313 * @param p 314 */ 315 private void draw(Graphics2D g, MapillaryAbstractImage image, 316 ImageIcon icon, Point p) { 317 Image imagetemp = icon.getImage(); 318 BufferedImage bi = (BufferedImage) imagetemp; 319 int width = icon.getIconWidth(); 320 int height = icon.getIconHeight(); 321 322 // Rotate the image 323 double rotationRequired = Math.toRadians(image.getCa()); 324 double locationX = width / 2; 325 double locationY = height / 2; 326 AffineTransform tx = AffineTransform.getRotateInstance( 327 rotationRequired, locationX, locationY); 328 AffineTransformOp op = new AffineTransformOp(tx, 329 AffineTransformOp.TYPE_BILINEAR); 330 331 g.drawImage(op.filter(bi, null), p.x - (width / 2), p.y - (height / 2), 332 Main.map.mapView); 333 if (data.getHoveredImage() == image) { 334 drawPointHighlight(g, p, 16); 335 } 336 } 337 338 @Override 339 public Icon getIcon() { 340 return MapillaryPlugin.ICON16; 341 } 342 343 @Override 344 public boolean isMergable(Layer other) { 345 return false; 346 } 347 348 @Override 349 public void mergeFrom(Layer from) { 350 throw new UnsupportedOperationException( 351 "This layer does not support merging yet"); 352 } 353 354 @Override 355 public Action[] getMenuEntries() { 356 List<Action> actions = new ArrayList<>(); 357 actions.add(LayerListDialog.getInstance().createShowHideLayerAction()); 358 actions.add(LayerListDialog.getInstance().createDeleteLayerAction()); 359 actions.add(new LayerListPopup.InfoAction(this)); 360 return actions.toArray(new Action[actions.size()]); 361 } 362 363 /** 364 * Returns the 2 closest images belonging to a different sequence. 365 * 366 * @return 367 */ 368 private MapillaryImage[] getClosestImagesFromDifferentSequences() { 369 if (!(data.getSelectedImage() instanceof MapillaryImage)) 370 return new MapillaryImage[2]; 371 MapillaryImage selected = (MapillaryImage) data 372 .getSelectedImage(); 373 MapillaryImage[] ret = new MapillaryImage[2]; 374 double[] distances = { SEQUENCE_MAX_JUMP_DISTANCE, 375 SEQUENCE_MAX_JUMP_DISTANCE }; 376 LatLon selectedCoords = data.getSelectedImage().getLatLon(); 377 for (MapillaryAbstractImage imagePrev : data.getImages()) { 378 if (!(imagePrev instanceof MapillaryImage)) 379 continue; 380 if (!imagePrev.isVisible()) 381 continue; 382 MapillaryImage image = (MapillaryImage) imagePrev; 383 if (image.getLatLon().greatCircleDistance(selectedCoords) < SEQUENCE_MAX_JUMP_DISTANCE 384 && selected.getSequence() != image.getSequence()) { 385 if ((ret[0] == null && ret[1] == null) 386 || (image.getLatLon().greatCircleDistance( 387 selectedCoords) < distances[0] && (ret[1] == null || image 388 .getSequence() != ret[1].getSequence()))) { 389 ret[0] = image; 390 distances[0] = image.getLatLon().greatCircleDistance( 391 selectedCoords); 392 } else if ((ret[1] == null || image.getLatLon() 393 .greatCircleDistance(selectedCoords) < distances[1]) 394 && image.getSequence() != ret[0].getSequence()) { 395 ret[1] = image; 396 distances[1] = image.getLatLon().greatCircleDistance( 397 selectedCoords); 398 } 399 } 400 } 401 // Predownloads the thumbnails 402 if (ret[0] != null) 403 new MapillaryCache(ret[0].getKey(), MapillaryCache.Type.THUMBNAIL) 404 .submit(data, false); 405 if (ret[1] != null) 406 new MapillaryCache(ret[1].getKey(), MapillaryCache.Type.THUMBNAIL) 407 .submit(data, false); 408 return ret; 409 } 410 411 @Override 412 public Object getInfoComponent() { 413 StringBuilder sb = new StringBuilder(); 414 sb.append(tr("Mapillary layer")); 415 sb.append("\n"); 416 sb.append(tr("Total images:")); 417 sb.append(" "); 418 sb.append(data.size()); 419 sb.append("\n"); 420 return sb.toString(); 421 } 422 423 @Override 424 public String getToolTipText() { 425 return data.size() + " " + tr("images"); 426 } 427 428 // EditDataLayerChanged 429 @Override 430 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) { 431 } 432 433 /** 434 * When more data is downloaded, a delayed update is thrown, in order to 435 * wait for the data bounds to be set. 436 * 437 * @param event 438 */ 439 @Override 440 public void dataChanged(DataChangedEvent event) { 441 Main.worker.submit(new delayedDownload()); 442 } 443 444 private class delayedDownload extends Thread { 445 446 @Override 447 public void run() { 448 try { 449 sleep(1000); 450 } catch (InterruptedException e) { 451 Main.error(e); 452 } 453 MapillaryLayer.getInstance().download(); 454 } 455 } 456 457 @Override 458 public void primitivesAdded(PrimitivesAddedEvent event) { 459 } 460 461 @Override 462 public void primitivesRemoved(PrimitivesRemovedEvent event) { 463 } 464 465 @Override 466 public void tagsChanged(TagsChangedEvent event) { 467 } 468 469 @Override 470 public void nodeMoved(NodeMovedEvent event) { 471 } 472 473 @Override 474 public void wayNodesChanged(WayNodesChangedEvent event) { 475 } 476 477 @Override 478 public void relationMembersChanged(RelationMembersChangedEvent event) { 479 } 480 481 @Override 482 public void otherDatasetChange(AbstractDatasetChangedEvent event) { 483 } 484 485 @Override 486 public void visitBoundingBox(BoundingXYVisitor v) { 487 } 488 489 @Override 490 public void activeLayerChange(Layer oldLayer, Layer newLayer) { 491 if (newLayer == this) { 492 if (data.size() > 0) 493 Main.map.statusLine.setHelpText(tr("Total images: {0}", 494 data.size())); 495 else 496 Main.map.statusLine.setHelpText(tr("No images found")); 497 } 498 } 499 500 @Override 501 public void layerAdded(Layer newLayer) { 502 } 503 504 @Override 505 public void layerRemoved(Layer oldLayer) { 506 } 61 DataSetListener, EditLayerChangeListener, LayerChangeListener { 62 63 public final static int SEQUENCE_MAX_JUMP_DISTANCE = Main.pref.getInteger( 64 "mapillary.sequence-max-jump-distance", 100); 65 66 public static MapillaryLayer INSTANCE; 67 public static CacheAccess<String, BufferedImageCacheEntry> CACHE; 68 public static MapillaryImage BLUE; 69 public static MapillaryImage RED; 70 71 private final MapillaryData data = MapillaryData.getInstance(); 72 73 public ArrayList<Bounds> bounds; 74 75 private MouseAdapter mouseAdapter; 76 77 private int highlightPointRadius = Main.pref.getInteger( 78 "mappaint.highlight.radius", 7); 79 private int highlightStep = Main.pref.getInteger("mappaint.highlight.step", 80 4); 81 82 private volatile TexturePaint hatched; 83 84 public MapillaryLayer() { 85 super(tr("Mapillary Images")); 86 bounds = new ArrayList<>(); 87 init(); 88 } 89 90 /** 91 * Initializes the Layer. 92 */ 93 private void init() { 94 MapillaryLayer.INSTANCE = this; 95 startMouseAdapter(); 96 try { 97 CACHE = JCSCacheManager.getCache("Mapillary"); 98 } catch (IOException e) { 99 Main.error(e); 100 } 101 if (Main.map != null && Main.map.mapView != null) { 102 Main.map.mapView.addMouseListener(mouseAdapter); 103 Main.map.mapView.addMouseMotionListener(mouseAdapter); 104 Main.map.mapView.addLayer(this); 105 MapView.addEditLayerChangeListener(this, false); 106 MapView.addLayerChangeListener(this); 107 Main.map.mapView.getEditLayer().data.addDataSetListener(this); 108 } 109 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, true); 110 Main.map.mapView.setActiveLayer(this); 111 createHatchTexture(); 112 Main.map.repaint(); 113 } 114 115 private void startMouseAdapter() { 116 mouseAdapter = new MapillaryMouseAdapter(); 117 } 118 119 public synchronized static MapillaryLayer getInstance() { 120 if (MapillaryLayer.INSTANCE == null) 121 MapillaryLayer.INSTANCE = new MapillaryLayer(); 122 return MapillaryLayer.INSTANCE; 123 } 124 125 /** 126 * Downloads all images of the area covered by the OSM data. This is only 127 * just for automatic download. 128 */ 129 public void download() { 130 checkBigAreas(); 131 if (Main.pref.getBoolean("mapillary.download-manually")) 132 return; 133 for (Bounds bounds : Main.map.mapView.getEditLayer().data 134 .getDataSourceBounds()) { 135 if (!this.bounds.contains(bounds)) { 136 this.bounds.add(bounds); 137 new MapillaryDownloader().getImages(bounds.getMin(), 138 bounds.getMax()); 139 } 140 } 141 } 142 143 /** 144 * Checks if the area of the OSM data is too big. This means that probably 145 * lots of Mapillary images are going to be downloaded, slowing down the 146 * program too much. To solve this the automatic is stopped, an alert is 147 * shown and you will have to download areas manually. 148 */ 149 private void checkBigAreas() { 150 double area = 0; 151 for (Bounds bounds : Main.map.mapView.getEditLayer().data 152 .getDataSourceBounds()) { 153 area += bounds.getArea(); 154 } 155 if (area > MapillaryDownloadViewAction.MAX_AREA) { 156 Main.pref.put("mapillary.download-manually", true); 157 JOptionPane 158 .showMessageDialog( 159 Main.parent, 160 tr("The downloaded OSM area is too big. Download mode has been change to manual. You can change this back to automatic in preferences settings.")); 161 } 162 } 163 164 /** 165 * Returns the MapillaryData object, which acts as the database of the 166 * Layer. 167 * 168 * @return 169 */ 170 public MapillaryData getMapillaryData() { 171 return data; 172 } 173 174 /** 175 * Method invoked when the layer is destroyed. 176 */ 177 @Override 178 public void destroy() { 179 MapillaryToggleDialog.getInstance().mapillaryImageDisplay 180 .setImage(null); 181 data.getImages().clear(); 182 MapillaryLayer.INSTANCE = null; 183 MapillaryData.INSTANCE = null; 184 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, false); 185 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.ZOOM_MENU, false); 186 Main.map.mapView.removeMouseListener(mouseAdapter); 187 Main.map.mapView.removeMouseMotionListener(mouseAdapter); 188 MapView.removeEditLayerChangeListener(this); 189 if (Main.map.mapView.getEditLayer() != null) 190 Main.map.mapView.getEditLayer().data.removeDataSetListener(this); 191 super.destroy(); 192 } 193 194 /** 195 * Returns true any of the images from the database has been modified. 196 */ 197 @Override 198 public boolean isModified() { 199 for (MapillaryAbstractImage image : data.getImages()) 200 if (image.isModified()) 201 return true; 202 return false; 203 } 204 205 @Override 206 public void setVisible(boolean visible) { 207 super.setVisible(visible); 208 for (MapillaryAbstractImage img : data.getImages()) 209 img.setVisible(visible); 210 MapillaryFilterDialog.getInstance().refresh(); 211 } 212 213 /** 214 * Replies background color for downloaded areas. 215 * 216 * @return background color for downloaded areas. Black by default 217 */ 218 private Color getBackgroundColor() { 219 return Main.pref.getColor(marktr("background"), Color.BLACK); 220 } 221 222 /** 223 * Replies background color for non-downloaded areas. 224 * 225 * @return background color for non-downloaded areas. Yellow by default 226 */ 227 private Color getOutsideColor() { 228 return Main.pref.getColor(marktr("outside downloaded area"), 229 Color.YELLOW); 230 } 231 232 /** 233 * Initialize the hatch pattern used to paint the non-downloaded area 234 */ 235 private void createHatchTexture() { 236 BufferedImage bi = new BufferedImage(15, 15, 237 BufferedImage.TYPE_INT_ARGB); 238 Graphics2D big = bi.createGraphics(); 239 big.setColor(getBackgroundColor()); 240 Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 241 0.3f); 242 big.setComposite(comp); 243 big.fillRect(0, 0, 15, 15); 244 big.setColor(getOutsideColor()); 245 big.drawLine(0, 15, 15, 0); 246 Rectangle r = new Rectangle(0, 0, 15, 15); 247 hatched = new TexturePaint(bi, r); 248 } 249 250 /** 251 * Paints the database in the map. 252 */ 253 @Override 254 public void paint(Graphics2D g, MapView mv, Bounds box) { 255 synchronized (this) { 256 if (Main.map.mapView.getActiveLayer() == this) { 257 Rectangle b = mv.getBounds(); 258 // on some platforms viewport bounds seem to be offset from the 259 // left, 260 // over-grow it just to be sure 261 b.grow(100, 100); 262 Area a = new Area(b); 263 // now successively subtract downloaded areas 264 for (Bounds bounds : this.bounds) { 265 Point p1 = mv.getPoint(bounds.getMin()); 266 Point p2 = mv.getPoint(bounds.getMax()); 267 Rectangle r = new Rectangle(Math.min(p1.x, p2.x), Math.min( 268 p1.y, p2.y), Math.abs(p2.x - p1.x), Math.abs(p2.y 269 - p1.y)); 270 a.subtract(new Area(r)); 271 } 272 // paint remainder 273 g.setPaint(hatched); 274 g.fill(a); 275 } 276 277 // Draw colored lines 278 MapillaryLayer.BLUE = null; 279 MapillaryLayer.RED = null; 280 MapillaryToggleDialog.getInstance().blueButton.setEnabled(false); 281 MapillaryToggleDialog.getInstance().redButton.setEnabled(false); 282 283 // Sets blue and red lines and enables/disables the buttons 284 if (data.getSelectedImage() != null) { 285 MapillaryImage[] closestImages = getClosestImagesFromDifferentSequences(); 286 Point selected = mv.getPoint(data.getSelectedImage() 287 .getLatLon()); 288 if (closestImages[0] != null) { 289 MapillaryLayer.BLUE = closestImages[0]; 290 g.setColor(Color.BLUE); 291 g.drawLine(mv.getPoint(closestImages[0].getLatLon()).x, 292 mv.getPoint(closestImages[0].getLatLon()).y, 293 selected.x, selected.y); 294 MapillaryToggleDialog.getInstance().blueButton 295 .setEnabled(true); 296 } 297 if (closestImages[1] != null) { 298 MapillaryLayer.RED = closestImages[1]; 299 g.setColor(Color.RED); 300 g.drawLine(mv.getPoint(closestImages[1].getLatLon()).x, 301 mv.getPoint(closestImages[1].getLatLon()).y, 302 selected.x, selected.y); 303 MapillaryToggleDialog.getInstance().redButton 304 .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; 315 // Draw sequence line 316 if (image.getSequence() != null && image.next() != null 317 && image.next().isVisible()) { 318 nextp = mv.getPoint(image.getSequence().next(image) 319 .getLatLon()); 320 g.drawLine(p.x, p.y, nextp.x, nextp.y); 321 } 322 323 ImageIcon icon; 324 if (!data.getMultiSelectedImages().contains(image)) 325 icon = MapillaryPlugin.MAP_ICON; 326 else 327 icon = MapillaryPlugin.MAP_ICON_SELECTED; 328 draw(g, image, icon, p); 329 if (!image.getSigns().isEmpty()) { 330 g.drawImage(MapillaryPlugin.MAP_SIGN.getImage(), p.x 331 + icon.getIconWidth() / 2, 332 p.y - icon.getIconHeight() / 2, 333 Main.map.mapView); 334 } 335 } else if (imageAbs instanceof MapillaryImportedImage) { 336 MapillaryImportedImage image = (MapillaryImportedImage) imageAbs; 337 ImageIcon icon; 338 if (!data.getMultiSelectedImages().contains(image)) 339 icon = MapillaryPlugin.MAP_ICON_IMPORTED; 340 else 341 icon = MapillaryPlugin.MAP_ICON_SELECTED; 342 draw(g, image, icon, p); 343 } 344 } 345 } 346 } 347 348 /** 349 * Draws the highlight of the icon. 350 * 351 * @param g 352 * @param p 353 * @param size 354 */ 355 private void drawPointHighlight(Graphics2D g, Point p, int size) { 356 Color oldColor = g.getColor(); 357 Color highlightColor = PaintColors.HIGHLIGHT.get(); 358 Color highlightColorTransparent = new Color(highlightColor.getRed(), 359 highlightColor.getGreen(), highlightColor.getBlue(), 100); 360 g.setColor(highlightColorTransparent); 361 int s = size + highlightPointRadius; 362 while (s >= size) { 363 int r = (int) Math.floor(s / 2d); 364 g.fillRoundRect(p.x - r, p.y - r, s, s, r, r); 365 s -= highlightStep; 366 } 367 g.setColor(oldColor); 368 } 369 370 /** 371 * Draws the given icon of an image. Also checks if the mouse is over the 372 * image. 373 * 374 * @param g 375 * @param image 376 * @param icon 377 * @param p 378 */ 379 private void draw(Graphics2D g, MapillaryAbstractImage image, 380 ImageIcon icon, Point p) { 381 Image imagetemp = icon.getImage(); 382 BufferedImage bi = (BufferedImage) imagetemp; 383 int width = icon.getIconWidth(); 384 int height = icon.getIconHeight(); 385 386 // Rotate the image 387 double rotationRequired = Math.toRadians(image.getCa()); 388 double locationX = width / 2; 389 double locationY = height / 2; 390 AffineTransform tx = AffineTransform.getRotateInstance( 391 rotationRequired, locationX, locationY); 392 AffineTransformOp op = new AffineTransformOp(tx, 393 AffineTransformOp.TYPE_BILINEAR); 394 395 g.drawImage(op.filter(bi, null), p.x - (width / 2), p.y - (height / 2), 396 Main.map.mapView); 397 if (data.getHoveredImage() == image) { 398 drawPointHighlight(g, p, 16); 399 } 400 } 401 402 @Override 403 public Icon getIcon() { 404 return MapillaryPlugin.ICON16; 405 } 406 407 @Override 408 public boolean isMergable(Layer other) { 409 return false; 410 } 411 412 @Override 413 public void mergeFrom(Layer from) { 414 throw new UnsupportedOperationException( 415 "This layer does not support merging yet"); 416 } 417 418 @Override 419 public Action[] getMenuEntries() { 420 List<Action> actions = new ArrayList<>(); 421 actions.add(LayerListDialog.getInstance().createShowHideLayerAction()); 422 actions.add(LayerListDialog.getInstance().createDeleteLayerAction()); 423 actions.add(new LayerListPopup.InfoAction(this)); 424 return actions.toArray(new Action[actions.size()]); 425 } 426 427 /** 428 * Returns the 2 closest images belonging to a different sequence. 429 * 430 * @return 431 */ 432 private MapillaryImage[] getClosestImagesFromDifferentSequences() { 433 if (!(data.getSelectedImage() instanceof MapillaryImage)) 434 return new MapillaryImage[2]; 435 MapillaryImage selected = (MapillaryImage) data.getSelectedImage(); 436 MapillaryImage[] ret = new MapillaryImage[2]; 437 double[] distances = { SEQUENCE_MAX_JUMP_DISTANCE, 438 SEQUENCE_MAX_JUMP_DISTANCE }; 439 LatLon selectedCoords = data.getSelectedImage().getLatLon(); 440 for (MapillaryAbstractImage imagePrev : data.getImages()) { 441 if (!(imagePrev instanceof MapillaryImage)) 442 continue; 443 if (!imagePrev.isVisible()) 444 continue; 445 MapillaryImage image = (MapillaryImage) imagePrev; 446 if (image.getLatLon().greatCircleDistance(selectedCoords) < SEQUENCE_MAX_JUMP_DISTANCE 447 && selected.getSequence() != image.getSequence()) { 448 if ((ret[0] == null && ret[1] == null) 449 || (image.getLatLon().greatCircleDistance( 450 selectedCoords) < distances[0] && (ret[1] == null || image 451 .getSequence() != ret[1].getSequence()))) { 452 ret[0] = image; 453 distances[0] = image.getLatLon().greatCircleDistance( 454 selectedCoords); 455 } else if ((ret[1] == null || image.getLatLon() 456 .greatCircleDistance(selectedCoords) < distances[1]) 457 && image.getSequence() != ret[0].getSequence()) { 458 ret[1] = image; 459 distances[1] = image.getLatLon().greatCircleDistance( 460 selectedCoords); 461 } 462 } 463 } 464 // Predownloads the thumbnails 465 if (ret[0] != null) 466 new MapillaryCache(ret[0].getKey(), MapillaryCache.Type.THUMBNAIL) 467 .submit(data, false); 468 if (ret[1] != null) 469 new MapillaryCache(ret[1].getKey(), MapillaryCache.Type.THUMBNAIL) 470 .submit(data, false); 471 return ret; 472 } 473 474 @Override 475 public Object getInfoComponent() { 476 StringBuilder sb = new StringBuilder(); 477 sb.append(tr("Mapillary layer")); 478 sb.append("\n"); 479 sb.append(tr("Total images:")); 480 sb.append(" "); 481 sb.append(data.size()); 482 sb.append("\n"); 483 return sb.toString(); 484 } 485 486 @Override 487 public String getToolTipText() { 488 return data.size() + " " + tr("images"); 489 } 490 491 // EditDataLayerChanged 492 @Override 493 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) { 494 } 495 496 /** 497 * When more data is downloaded, a delayed update is thrown, in order to 498 * wait for the data bounds to be set. 499 * 500 * @param event 501 */ 502 @Override 503 public void dataChanged(DataChangedEvent event) { 504 Main.worker.submit(new delayedDownload()); 505 } 506 507 private class delayedDownload extends Thread { 508 509 @Override 510 public void run() { 511 try { 512 sleep(1000); 513 } catch (InterruptedException e) { 514 Main.error(e); 515 } 516 MapillaryLayer.getInstance().download(); 517 } 518 } 519 520 @Override 521 public void primitivesAdded(PrimitivesAddedEvent event) { 522 } 523 524 @Override 525 public void primitivesRemoved(PrimitivesRemovedEvent event) { 526 } 527 528 @Override 529 public void tagsChanged(TagsChangedEvent event) { 530 } 531 532 @Override 533 public void nodeMoved(NodeMovedEvent event) { 534 } 535 536 @Override 537 public void wayNodesChanged(WayNodesChangedEvent event) { 538 } 539 540 @Override 541 public void relationMembersChanged(RelationMembersChangedEvent event) { 542 } 543 544 @Override 545 public void otherDatasetChange(AbstractDatasetChangedEvent event) { 546 } 547 548 @Override 549 public void visitBoundingBox(BoundingXYVisitor v) { 550 } 551 552 @Override 553 public void activeLayerChange(Layer oldLayer, Layer newLayer) { 554 if (newLayer == this) { 555 if (data.size() > 0) 556 Main.map.statusLine.setHelpText(tr("Total images: {0}", 557 data.size())); 558 else 559 Main.map.statusLine.setHelpText(tr("No images found")); 560 } 561 } 562 563 @Override 564 public void layerAdded(Layer newLayer) { 565 } 566 567 @Override 568 public void layerRemoved(Layer oldLayer) { 569 } 507 570 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryMouseAdapter.java
r31284 r31298 7 7 8 8 import org.openstreetmap.josm.Main; 9 import org.openstreetmap.josm.actions.mapmode.MapMode; 9 10 import org.openstreetmap.josm.data.coor.LatLon; 10 11 import org.openstreetmap.josm.data.osm.OsmPrimitive; … … 22 23 */ 23 24 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 33 public MapillaryMouseAdapter() { 34 mapillaryData = MapillaryData.getInstance(); 35 record = MapillaryRecord.getInstance(); 36 } 37 38 @Override 39 public void mousePressed(MouseEvent e) { 40 lastButton = e.getButton(); 41 if (e.getButton() != MouseEvent.BUTTON1) 42 return; 43 MapillaryAbstractImage closestTemp = getClosest(e.getPoint()); 44 if (Main.map.mapView.getActiveLayer() instanceof OsmDataLayer 45 && closestTemp != null) { 46 this.lastClicked = this.closest; 47 MapillaryData.getInstance().setSelectedImage(closestTemp); 48 return; 49 } else if (Main.map.mapView.getActiveLayer() != MapillaryLayer 50 .getInstance()) 51 return; 52 if (closestTemp instanceof MapillaryImage || closestTemp == null) { 53 MapillaryImage closest = (MapillaryImage) closestTemp; 54 // Doube click 55 if (e.getClickCount() == 2 56 && mapillaryData.getSelectedImage() != null 57 && closest != null) { 58 for (MapillaryAbstractImage img : closest.getSequence() 59 .getImages()) { 60 mapillaryData.addMultiSelectedImage(img); 61 } 62 } 63 this.start = e.getPoint(); 64 this.lastClicked = this.closest; 65 this.closest = closest; 66 if (mapillaryData.getMultiSelectedImages().contains(closest)) 67 return; 68 // ctrl+click 69 if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.CTRL_MASK) 70 && closest != null) 71 mapillaryData.addMultiSelectedImage(closest); 72 // shift + click 73 else if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.SHIFT_MASK) 74 && this.closest instanceof MapillaryImage 75 && this.lastClicked instanceof MapillaryImage) { 76 if (this.closest != null 77 && this.lastClicked != null 78 && ((MapillaryImage) this.closest).getSequence() == ((MapillaryImage) this.lastClicked) 79 .getSequence()) { 80 int i = ((MapillaryImage) this.closest).getSequence() 81 .getImages().indexOf(this.closest); 82 int j = ((MapillaryImage) this.lastClicked).getSequence() 83 .getImages().indexOf(this.lastClicked); 84 if (i < j) 85 mapillaryData 86 .addMultiSelectedImage(new ArrayList<MapillaryAbstractImage>( 87 ((MapillaryImage) this.closest) 88 .getSequence().getImages() 89 .subList(i, j + 1))); 90 else 91 mapillaryData 92 .addMultiSelectedImage(new ArrayList<MapillaryAbstractImage>( 93 ((MapillaryImage) this.closest) 94 .getSequence().getImages() 95 .subList(j, i + 1))); 96 } 97 // click 98 } else 99 mapillaryData.setSelectedImage(closest); 100 // If you select an imported image 101 } else if (closestTemp instanceof MapillaryImportedImage) { 102 MapillaryImportedImage closest = (MapillaryImportedImage) closestTemp; 103 this.start = e.getPoint(); 104 this.lastClicked = this.closest; 105 this.closest = closest; 106 if (mapillaryData.getMultiSelectedImages().contains(closest)) 107 return; 108 if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.CTRL_MASK) 109 && closest != null) 110 mapillaryData.addMultiSelectedImage(closest); 111 else 112 mapillaryData.setSelectedImage(closest); 113 } 114 } 115 116 private MapillaryAbstractImage getClosest(Point clickPoint) { 117 double snapDistance = 10; 118 double minDistance = Double.MAX_VALUE; 119 MapillaryAbstractImage closest = null; 120 for (MapillaryAbstractImage image : mapillaryData.getImages()) { 121 Point imagePoint = Main.map.mapView.getPoint(image.getLatLon()); 122 imagePoint.setLocation(imagePoint.getX(), imagePoint.getY()); 123 double dist = clickPoint.distanceSq(imagePoint); 124 if (minDistance > dist 125 && clickPoint.distance(imagePoint) < snapDistance) { 126 minDistance = dist; 127 closest = image; 128 } 129 } 130 return closest; 131 } 132 133 @Override 134 public void mouseDragged(MouseEvent e) { 135 if (Main.map.mapView.getActiveLayer() != MapillaryLayer.getInstance()) 136 return; 137 138 if (!Main.pref.getBoolean("mapillary.developer")) 139 for (MapillaryAbstractImage img : MapillaryData.getInstance() 140 .getMultiSelectedImages()) { 141 if (img instanceof MapillaryImage) 142 return; 143 } 144 if (MapillaryData.getInstance().getSelectedImage() != null) { 145 if (lastButton == MouseEvent.BUTTON1 && !e.isShiftDown()) { 146 LatLon to = Main.map.mapView.getLatLon(e.getX(), e.getY()); 147 LatLon from = Main.map.mapView.getLatLon(start.getX(), 148 start.getY()); 149 for (MapillaryAbstractImage img : MapillaryData.getInstance() 150 .getMultiSelectedImages()) { 151 152 img.move(to.getX() - from.getX(), to.getY() - from.getY()); 153 } 154 Main.map.repaint(); 155 } else if (lastButton == MouseEvent.BUTTON1 && e.isShiftDown()) { 156 this.closest.turn(Math.toDegrees(Math.atan2( 157 (e.getX() - start.x), -(e.getY() - start.y))) 158 - closest.getTempCa()); 159 for (MapillaryAbstractImage img : MapillaryData.getInstance() 160 .getMultiSelectedImages()) { 161 img.turn(Math.toDegrees(Math.atan2((e.getX() - start.x), 162 -(e.getY() - start.y))) - closest.getTempCa()); 163 } 164 Main.map.repaint(); 165 } 166 } 167 } 168 169 @Override 170 public void mouseReleased(MouseEvent e) { 171 if (mapillaryData.getSelectedImage() == null) 172 return; 173 if (mapillaryData.getSelectedImage().getTempCa() != mapillaryData 174 .getSelectedImage().getCa()) { 175 double from = mapillaryData.getSelectedImage().getTempCa(); 176 double to = mapillaryData.getSelectedImage().getCa(); 177 record.addCommand(new CommandTurnImage(mapillaryData 178 .getMultiSelectedImages(), to - from)); 179 } else if (mapillaryData.getSelectedImage().getTempLatLon() != mapillaryData 180 .getSelectedImage().getLatLon()) { 181 LatLon from = mapillaryData.getSelectedImage().getTempLatLon(); 182 LatLon to = mapillaryData.getSelectedImage().getLatLon(); 183 record.addCommand(new CommandMoveImage(mapillaryData 184 .getMultiSelectedImages(), to.getX() - from.getX(), to 185 .getY() - from.getY())); 186 } 187 for (MapillaryAbstractImage img : mapillaryData 188 .getMultiSelectedImages()) { 189 if (img != null) 190 img.stopMoving(); 191 } 192 } 193 194 /** 195 * Checks if the mouse is over pictures. 196 */ 197 @Override 198 public void mouseMoved(MouseEvent e) { 199 MapillaryAbstractImage closestTemp = getClosest(e.getPoint()); 200 201 if (closestTemp != null 202 && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer 203 && Main.map.mapModeSelect.getValue("active") == Boolean.TRUE) { 204 Main.map.mapModeSelect.exitMode(); 205 } else if (closestTemp == null 206 && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer 207 && Main.map.mapModeSelect.getValue("active") == Boolean.FALSE) { 208 Main.map.mapModeSelect.enterMode(); 209 nothingHighlighted = false; 210 } else if (Main.map.mapModeSelect.getValue("active") == Boolean.FALSE 211 && !nothingHighlighted && Main.map.mapView != null 212 && Main.map.mapView.getEditLayer().data != null) { 213 for (OsmPrimitive primivitive : Main.map.mapView.getEditLayer().data 214 .allPrimitives()) { 215 primivitive.setHighlighted(false); 216 } 217 nothingHighlighted = true; 218 } 219 220 // TODO check if it is possible to do this while the OSM data layer is 221 // selected. 222 if (MapillaryData.getInstance().getHoveredImage() != closestTemp 223 && closestTemp != null) { 224 MapillaryData.getInstance().setHoveredImage(closestTemp); 225 MapillaryToggleDialog.getInstance().setImage(closestTemp); 226 MapillaryToggleDialog.getInstance().updateImage(); 227 } else if (MapillaryData.getInstance().getHoveredImage() != closestTemp 228 && closestTemp == null) { 229 MapillaryData.getInstance().setHoveredImage(null); 230 MapillaryToggleDialog.getInstance().setImage( 231 MapillaryData.getInstance().getSelectedImage()); 232 MapillaryToggleDialog.getInstance().updateImage(); 233 } 234 MapillaryData.getInstance().dataUpdated(); 235 } 25 private Point start; 26 private int lastButton; 27 private MapillaryAbstractImage closest; 28 private MapillaryAbstractImage lastClicked; 29 private MapillaryData mapillaryData; 30 private MapillaryRecord record; 31 32 private boolean nothingHighlighted; 33 private boolean imageHighlighted = false; 34 35 public MapillaryMouseAdapter() { 36 mapillaryData = MapillaryData.getInstance(); 37 record = MapillaryRecord.getInstance(); 38 } 39 40 @Override 41 public void mousePressed(MouseEvent e) { 42 lastButton = e.getButton(); 43 if (e.getButton() != MouseEvent.BUTTON1) 44 return; 45 MapillaryAbstractImage closestTemp = getClosest(e.getPoint()); 46 if (Main.map.mapView.getActiveLayer() instanceof OsmDataLayer 47 && closestTemp != null 48 && Main.map.mapMode == Main.map.mapModeSelect) { 49 this.lastClicked = this.closest; 50 MapillaryData.getInstance().setSelectedImage(closestTemp); 51 return; 52 } else if (Main.map.mapView.getActiveLayer() != MapillaryLayer 53 .getInstance()) 54 return; 55 if (closestTemp instanceof MapillaryImage || closestTemp == null) { 56 MapillaryImage closest = (MapillaryImage) closestTemp; 57 // Doube click 58 if (e.getClickCount() == 2 59 && mapillaryData.getSelectedImage() != null 60 && closest != null) { 61 for (MapillaryAbstractImage img : closest.getSequence() 62 .getImages()) { 63 mapillaryData.addMultiSelectedImage(img); 64 } 65 } 66 this.start = e.getPoint(); 67 this.lastClicked = this.closest; 68 this.closest = closest; 69 if (mapillaryData.getMultiSelectedImages().contains(closest)) 70 return; 71 // ctrl+click 72 if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.CTRL_MASK) 73 && closest != null) 74 mapillaryData.addMultiSelectedImage(closest); 75 // shift + click 76 else if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.SHIFT_MASK) 77 && this.closest instanceof MapillaryImage 78 && this.lastClicked instanceof MapillaryImage) { 79 if (this.closest != null 80 && this.lastClicked != null 81 && ((MapillaryImage) this.closest).getSequence() == ((MapillaryImage) this.lastClicked) 82 .getSequence()) { 83 int i = ((MapillaryImage) this.closest).getSequence() 84 .getImages().indexOf(this.closest); 85 int j = ((MapillaryImage) this.lastClicked).getSequence() 86 .getImages().indexOf(this.lastClicked); 87 if (i < j) 88 mapillaryData 89 .addMultiSelectedImage(new ArrayList<MapillaryAbstractImage>( 90 ((MapillaryImage) this.closest) 91 .getSequence().getImages() 92 .subList(i, j + 1))); 93 else 94 mapillaryData 95 .addMultiSelectedImage(new ArrayList<MapillaryAbstractImage>( 96 ((MapillaryImage) this.closest) 97 .getSequence().getImages() 98 .subList(j, i + 1))); 99 } 100 // click 101 } else 102 mapillaryData.setSelectedImage(closest); 103 // If you select an imported image 104 } else if (closestTemp instanceof MapillaryImportedImage) { 105 MapillaryImportedImage closest = (MapillaryImportedImage) closestTemp; 106 this.start = e.getPoint(); 107 this.lastClicked = this.closest; 108 this.closest = closest; 109 if (mapillaryData.getMultiSelectedImages().contains(closest)) 110 return; 111 if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.CTRL_MASK) 112 && closest != null) 113 mapillaryData.addMultiSelectedImage(closest); 114 else 115 mapillaryData.setSelectedImage(closest); 116 } 117 } 118 119 private MapillaryAbstractImage getClosest(Point clickPoint) { 120 double snapDistance = 10; 121 double minDistance = Double.MAX_VALUE; 122 MapillaryAbstractImage closest = null; 123 for (MapillaryAbstractImage image : mapillaryData.getImages()) { 124 Point imagePoint = Main.map.mapView.getPoint(image.getLatLon()); 125 imagePoint.setLocation(imagePoint.getX(), imagePoint.getY()); 126 double dist = clickPoint.distanceSq(imagePoint); 127 if (minDistance > dist 128 && clickPoint.distance(imagePoint) < snapDistance) { 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 System.out.println("1"); 212 213 } else if (closestTemp == null 214 && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer 215 && imageHighlighted && nothingHighlighted) { 216 nothingHighlighted = false; 217 Main.map.mapMode.putValue("active", Boolean.TRUE); 218 System.out.println("2"); 219 220 } else if (imageHighlighted && !nothingHighlighted 221 && Main.map.mapView != null 222 && Main.map.mapView.getEditLayer().data != null 223 && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer) { 224 System.out.println("3"); 225 226 for (OsmPrimitive primivitive : Main.map.mapView.getEditLayer().data 227 .allPrimitives()) { 228 primivitive.setHighlighted(false); 229 } 230 imageHighlighted = false; 231 nothingHighlighted = true; 232 } 233 234 // TODO check if it is possible to do this while the OSM data layer is 235 // selected. 236 if (MapillaryData.getInstance().getHoveredImage() != closestTemp 237 && closestTemp != null) { 238 MapillaryData.getInstance().setHoveredImage(closestTemp); 239 MapillaryToggleDialog.getInstance().setImage(closestTemp); 240 MapillaryToggleDialog.getInstance().updateImage(); 241 } else if (MapillaryData.getInstance().getHoveredImage() != closestTemp 242 && closestTemp == null) { 243 MapillaryData.getInstance().setHoveredImage(null); 244 MapillaryToggleDialog.getInstance().setImage( 245 MapillaryData.getInstance().getSelectedImage()); 246 MapillaryToggleDialog.getInstance().updateImage(); 247 } 248 MapillaryData.getInstance().dataUpdated(); 249 } 236 250 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java
r31297 r31298 33 33 public class MapillaryPlugin extends Plugin implements EditLayerChangeListener { 34 34 35 36 37 38 39 40 41 42 43 44 45 46 47 35 public static final ImageIcon ICON24 = new ImageProvider("icon24.png") 36 .get(); 37 public static final ImageIcon ICON16 = new ImageProvider("icon16.png") 38 .get(); 39 public static final ImageIcon MAP_ICON = new ImageProvider("mapicon.png") 40 .get(); 41 public static final ImageIcon MAP_ICON_SELECTED = new ImageProvider( 42 "mapiconselected.png").get(); 43 public static final ImageIcon MAP_ICON_IMPORTED = new ImageProvider( 44 "mapiconimported.png").get(); 45 public static final ImageIcon MAP_SIGN = new ImageProvider("sign.png") 46 .get(); 47 public static final int ICON_SIZE = 24; 48 48 49 49 public static CacheAccess<String, BufferedImageCacheEntry> CACHE; 50 50 51 private final MapillaryDownloadAction downloadAction; 52 private final MapillaryExportAction exportAction; 53 private final MapillaryImportAction importAction; 54 private final MapillarySignAction signAction; 55 private final MapillaryZoomAction zoomAction; 56 private final MapillaryDownloadViewAction downloadViewAction; 51 private final MapillaryDownloadAction downloadAction; 52 private final MapillaryExportAction exportAction; 53 private final MapillaryImportAction importAction; 54 private final MapillaryZoomAction zoomAction; 55 private final MapillaryDownloadViewAction downloadViewAction; 57 56 58 public static JMenuItem DOWNLOAD_MENU; 59 public static JMenuItem EXPORT_MENU; 60 public static JMenuItem IMPORT_MENU; 61 public static JMenuItem SIGN_MENU; 62 public static JMenuItem ZOOM_MENU; 63 public static JMenuItem DOWNLOAD_VIEW_MENU; 57 public static JMenuItem DOWNLOAD_MENU; 58 public static JMenuItem EXPORT_MENU; 59 public static JMenuItem IMPORT_MENU; 60 public static JMenuItem ZOOM_MENU; 61 public static JMenuItem DOWNLOAD_VIEW_MENU; 64 62 65 public MapillaryPlugin(PluginInformation info) { 66 super(info); 67 downloadAction = new MapillaryDownloadAction(); 68 exportAction = new MapillaryExportAction(); 69 importAction = new MapillaryImportAction(); 70 signAction = new MapillarySignAction(); 71 zoomAction = new MapillaryZoomAction(); 72 downloadViewAction = new MapillaryDownloadViewAction(); 63 public MapillaryPlugin(PluginInformation info) { 64 super(info); 65 downloadAction = new MapillaryDownloadAction(); 66 exportAction = new MapillaryExportAction(); 67 importAction = new MapillaryImportAction(); 68 zoomAction = new MapillaryZoomAction(); 69 downloadViewAction = new MapillaryDownloadViewAction(); 73 70 74 DOWNLOAD_MENU = MainMenu.add(Main.main.menu.imageryMenu, 75 downloadAction, false); 76 EXPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, exportAction, 77 false, 14); 78 IMPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, importAction, 79 false, 14); 80 SIGN_MENU = MainMenu.add(Main.main.menu.dataMenu, signAction, false); 81 ZOOM_MENU = MainMenu 82 .add(Main.main.menu.viewMenu, zoomAction, false, 15); 83 DOWNLOAD_VIEW_MENU = MainMenu.add(Main.main.menu.fileMenu, 84 downloadViewAction, false, 14); 71 DOWNLOAD_MENU = MainMenu.add(Main.main.menu.imageryMenu, 72 downloadAction, false); 73 EXPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, exportAction, 74 false, 14); 75 IMPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, importAction, 76 false, 14); 77 ZOOM_MENU = MainMenu 78 .add(Main.main.menu.viewMenu, zoomAction, false, 15); 79 DOWNLOAD_VIEW_MENU = MainMenu.add(Main.main.menu.fileMenu, 80 downloadViewAction, false, 14); 85 81 86 EXPORT_MENU.setEnabled(false); 87 DOWNLOAD_MENU.setEnabled(false); 88 IMPORT_MENU.setEnabled(false); 89 SIGN_MENU.setEnabled(false); 90 ZOOM_MENU.setEnabled(false); 91 DOWNLOAD_VIEW_MENU.setEnabled(false); 82 EXPORT_MENU.setEnabled(false); 83 DOWNLOAD_MENU.setEnabled(false); 84 IMPORT_MENU.setEnabled(false); 85 ZOOM_MENU.setEnabled(false); 86 DOWNLOAD_VIEW_MENU.setEnabled(false); 92 87 93 94 95 96 97 98 99 100 88 MapView.addEditLayerChangeListener(this); 89 try { 90 CACHE = JCSCacheManager.getCache("mapillary", 10, 10000, 91 this.getPluginDir() + "/cache/"); 92 } catch (IOException e) { 93 Main.error(e); 94 } 95 } 101 96 102 /** 103 * Called when the JOSM map frame is created or destroyed. 104 */ 105 @Override 106 public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { 107 if (oldFrame == null && newFrame != null) { // map frame added 108 Main.map.addToggleDialog(MapillaryToggleDialog.getInstance(), false); 109 Main.map.addToggleDialog(MapillaryHistoryDialog.getInstance(), false); 110 Main.map.addToggleDialog(MapillaryFilterDialog.getInstance(), false); 111 } 112 if (oldFrame != null && newFrame == null) { // map frame destroyed 113 MapillaryToggleDialog.destroyInstance(); 114 MapillaryHistoryDialog.destroyInstance(); 115 MapillaryFilterDialog.destroyInstance(); 116 } 117 } 97 /** 98 * Called when the JOSM map frame is created or destroyed. 99 */ 100 @Override 101 public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { 102 if (oldFrame == null && newFrame != null) { // map frame added 103 Main.map.addToggleDialog(MapillaryToggleDialog.getInstance(), false); 104 Main.map.addToggleDialog(MapillaryHistoryDialog.getInstance(), 105 false); 106 Main.map.addToggleDialog(MapillaryFilterDialog.getInstance(), false); 107 } 108 if (oldFrame != null && newFrame == null) { // map frame destroyed 109 MapillaryToggleDialog.destroyInstance(); 110 MapillaryHistoryDialog.destroyInstance(); 111 MapillaryFilterDialog.destroyInstance(); 112 } 113 } 118 114 119 public static void setMenuEnabled(JMenuItem menu, boolean value) { 120 menu.setEnabled(value); 121 } 115 public static void setMenuEnabled(JMenuItem menu, boolean value) { 116 menu.setEnabled(value); 117 menu.getAction().setEnabled(value); 118 } 122 119 123 124 125 126 120 @Override 121 public PreferenceSetting getPreferenceSetting() { 122 return new MapillaryPreferenceSetting(); 123 } 127 124 128 @Override 129 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) { 130 if (oldLayer == null && newLayer != null) { 131 setMenuEnabled(DOWNLOAD_MENU, true); 132 setMenuEnabled(IMPORT_MENU, true); 133 setMenuEnabled(DOWNLOAD_VIEW_MENU, true); 134 } else if (oldLayer != null && newLayer == null) { 135 setMenuEnabled(DOWNLOAD_MENU, false); 136 setMenuEnabled(IMPORT_MENU, false); 137 setMenuEnabled(DOWNLOAD_VIEW_MENU, false); 138 } 139 } 125 @Override 126 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) { 127 if (oldLayer == null && newLayer != null) { 128 setMenuEnabled(DOWNLOAD_MENU, true); 129 if (Main.pref.getBoolean("mapillary.download-manually")) 130 setMenuEnabled(IMPORT_MENU, true); 131 setMenuEnabled(DOWNLOAD_VIEW_MENU, true); 132 } else if (oldLayer != null && newLayer == null) { 133 setMenuEnabled(DOWNLOAD_MENU, false); 134 setMenuEnabled(IMPORT_MENU, false); 135 setMenuEnabled(DOWNLOAD_VIEW_MENU, false); 136 } 137 } 140 138 } -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySequenceDownloadThread.java
r31278 r31298 79 79 "captured_at").longValue()); 80 80 81 int first = -1; 82 int last = -1; 83 int pos = 0; 81 84 82 83 List<MapillaryImage> finalImages = new ArrayList<>(images); 85 84 // Here it gets only those images which are in the downloaded 86 85 // area. 87 86 for (MapillaryAbstractImage img : images) { 88 if (first == -1 && isInside(img)) 89 first = pos; 90 else if (first != -1 && last == -1 && !isInside(img)) 91 last = pos; 92 else if (last != -1 && isInside(img)) 93 last = -1; 94 pos++; 87 if (!isInside(img)) 88 finalImages.remove(img); 95 89 } 96 if (last == -1) { 97 last = pos; 98 } 99 if (first == -1) 100 continue; 101 List<MapillaryImage> finalImages = images.subList(first, last); 90 102 91 for (MapillaryImage img : finalImages) { 103 92 MapillaryData.getInstance().getImages().remove(img); -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryPreferenceSetting.java
r31296 r31298 12 12 import org.openstreetmap.josm.gui.preferences.SubPreferenceSetting; 13 13 import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting; 14 import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; 14 15 15 16 public class MapillaryPreferenceSetting implements SubPreferenceSetting { … … 51 52 Main.pref.put("mapillary.reverse-buttons", reverseButtons.isSelected()); 52 53 Main.pref.put("mapillary.download-manually", downloadMode.isSelected()); 54 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.DOWNLOAD_VIEW_MENU, downloadMode.isSelected()); 55 53 56 Main.pref.put("mapillary.display-hour", displayHour.isSelected()); 54 57 Main.pref.put("mapillary.format-24", format24.isSelected()); -
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryToggleDialog.java
r31284 r31298 43 43 */ 44 44 public class MapillaryToggleDialog extends ToggleDialog implements 45 ICachedLoaderListener, MapillaryDataListener { 46 47 public final static int NORMAL_MODE = 0; 48 public final static int SIGN_MODE = 1; 49 50 public final static String BASE_TITLE = "Mapillary picture"; 51 52 public static MapillaryToggleDialog INSTANCE; 53 54 public volatile MapillaryAbstractImage image; 55 56 public final SideButton nextButton = new SideButton(new nextPictureAction()); 57 public final SideButton previousButton = new SideButton( 58 new previousPictureAction()); 59 public final SideButton redButton = new SideButton(new redAction()); 60 public final SideButton blueButton = new SideButton(new blueAction()); 61 private List<SideButton> normalMode; 62 63 public final SideButton nextSignButton = new SideButton( 64 new NextSignAction()); 65 public final SideButton previousSignButton = new SideButton( 66 new PreviousSignAction()); 67 private List<SideButton> signMode; 68 69 private int mode; 70 71 private JPanel buttonsPanel; 72 73 public MapillaryImageDisplay mapillaryImageDisplay; 74 75 private MapillaryCache imageCache; 76 private MapillaryCache thumbnailCache; 77 78 public MapillaryToggleDialog() { 79 super(tr(BASE_TITLE), "mapillary.png", tr("Open Mapillary window"), 80 Shortcut.registerShortcut(tr("Mapillary dialog"), 81 tr("Open Mapillary main dialog"), KeyEvent.VK_M, 82 Shortcut.NONE), 200); 83 MapillaryData.getInstance().addListener(this); 84 85 mapillaryImageDisplay = new MapillaryImageDisplay(); 86 87 blueButton.setForeground(Color.BLUE); 88 redButton.setForeground(Color.RED); 89 90 normalMode = Arrays.asList(new SideButton[] { blueButton, 91 previousButton, nextButton, redButton }); 92 signMode = Arrays.asList(new SideButton[] { previousSignButton, 93 nextSignButton }); 94 95 mode = NORMAL_MODE; 96 97 createLayout(mapillaryImageDisplay, normalMode, 98 Main.pref.getBoolean("mapillary.reverse-buttons")); 99 disableAllButtons(); 100 } 101 102 public static MapillaryToggleDialog getInstance() { 103 if (INSTANCE == null) 104 INSTANCE = new MapillaryToggleDialog(); 105 return INSTANCE; 106 } 107 108 public static void destroyInstance() { 109 INSTANCE = null; 110 } 111 112 /** 113 * Switches from one mode to the other one. 114 */ 115 public void switchMode() { 116 this.removeAll(); 117 List<SideButton> list = null; 118 if (mode == NORMAL_MODE) { 119 list = signMode; 120 mode = SIGN_MODE; 121 } else if (mode == SIGN_MODE) { 122 list = normalMode; 123 mode = NORMAL_MODE; 124 } 125 126 createLayout(mapillaryImageDisplay, list, 127 Main.pref.getBoolean("mapillary.reverse-buttons")); 128 disableAllButtons(); 129 updateImage(); 130 } 131 132 /** 133 * Downloads the image of the selected MapillaryImage and sets in the 134 * MapillaryImageDisplay object. 135 */ 136 public synchronized void updateImage() { 137 if (!SwingUtilities.isEventDispatchThread()) { 138 SwingUtilities.invokeLater(new Runnable() { 139 @Override 140 public void run() { 141 updateImage(); 142 } 143 }); 144 } else { 145 if (MapillaryLayer.INSTANCE == null) { 146 return; 147 } 148 if (this.image == null) { 149 mapillaryImageDisplay.setImage(null); 150 setTitle(tr(BASE_TITLE)); 151 disableAllButtons(); 152 return; 153 } 154 if (image instanceof MapillaryImage) { 155 mapillaryImageDisplay.hyperlink.setVisible(true); 156 MapillaryImage mapillaryImage = (MapillaryImage) this.image; 157 String title = tr(BASE_TITLE); 158 if (mapillaryImage.getUser() != null) 159 title += " -- " + mapillaryImage.getUser(); 160 if (mapillaryImage.getCapturedAt() != 0) 161 title += " -- " + mapillaryImage.getDate(); 162 setTitle(title); 163 if (mode == NORMAL_MODE) { 164 this.nextButton.setEnabled(true); 165 this.previousButton.setEnabled(true); 166 if (mapillaryImage.next() == null || !mapillaryImage.next().isVisible()) 167 this.nextButton.setEnabled(false); 168 if (mapillaryImage.previous() == null || !mapillaryImage.previous().isVisible()) 169 this.previousButton.setEnabled(false); 170 } else if (mode == SIGN_MODE) { 171 previousSignButton.setEnabled(true); 172 nextSignButton.setEnabled(true); 173 int i = MapillaryData 174 .getInstance() 175 .getImages() 176 .indexOf( 177 MapillaryData.getInstance() 178 .getSelectedImage()); 179 int first = -1; 180 int last = -1; 181 int c = 0; 182 for (MapillaryAbstractImage img : MapillaryData 183 .getInstance().getImages()) { 184 if (img instanceof MapillaryImage) 185 if (!((MapillaryImage) img).getSigns().isEmpty()) { 186 if (first == -1) 187 first = c; 188 last = c; 189 } 190 c++; 191 } 192 if (first >= i) 193 previousSignButton.setEnabled(false); 194 if (last <= i) 195 nextSignButton.setEnabled(false); 196 } 197 198 mapillaryImageDisplay.hyperlink.setURL(mapillaryImage.getKey()); 199 // Downloads the thumbnail. 200 this.mapillaryImageDisplay.setImage(null); 201 if (thumbnailCache != null) 202 thumbnailCache.cancelOutstandingTasks(); 203 thumbnailCache = new MapillaryCache(mapillaryImage.getKey(), 204 MapillaryCache.Type.THUMBNAIL); 205 thumbnailCache.submit(this, false); 206 207 // Downloads the full resolution image. 208 if (imageCache != null) 209 imageCache.cancelOutstandingTasks(); 210 imageCache = new MapillaryCache(mapillaryImage.getKey(), 211 MapillaryCache.Type.FULL_IMAGE); 212 imageCache.submit(this, false); 213 } else if (image instanceof MapillaryImportedImage) { 214 mapillaryImageDisplay.hyperlink.setVisible(false); 215 this.nextButton.setEnabled(false); 216 this.previousButton.setEnabled(false); 217 MapillaryImportedImage mapillaryImage = (MapillaryImportedImage) this.image; 218 try { 219 mapillaryImageDisplay.setImage(mapillaryImage.getImage()); 220 } catch (IOException e) { 221 Main.error(e); 222 } 223 mapillaryImageDisplay.hyperlink.setURL(null); 224 } 225 } 226 } 227 228 private void disableAllButtons() { 229 nextButton.setEnabled(false); 230 previousButton.setEnabled(false); 231 blueButton.setEnabled(false); 232 redButton.setEnabled(false); 233 nextSignButton.setEnabled(false); 234 previousSignButton.setEnabled(false); 235 mapillaryImageDisplay.hyperlink.setVisible(false); 236 } 237 238 /** 239 * Sets a new MapillaryImage to be shown. 240 * 241 * @param image 242 */ 243 public synchronized void setImage(MapillaryAbstractImage image) { 244 this.image = image; 245 } 246 247 /** 248 * Returns the MapillaryImage objects which is being shown. 249 * 250 * @return 251 */ 252 public synchronized MapillaryAbstractImage getImage() { 253 return this.image; 254 } 255 256 /** 257 * Action class form the next image button. 258 * 259 * @author Jorge 260 * 261 */ 262 class nextPictureAction extends AbstractAction { 263 public nextPictureAction() { 264 putValue(NAME, tr("Next picture")); 265 putValue(SHORT_DESCRIPTION, 266 tr("Shows the next picture in the sequence")); 267 } 268 269 @Override 270 public void actionPerformed(ActionEvent e) { 271 if (MapillaryToggleDialog.getInstance().getImage() != null) { 272 MapillaryData.getInstance().selectNext(); 273 } 274 } 275 } 276 277 /** 278 * Action class for the previous image button. 279 * 280 * @author Jorge 281 * 282 */ 283 class previousPictureAction extends AbstractAction { 284 public previousPictureAction() { 285 putValue(NAME, tr("Previous picture")); 286 putValue(SHORT_DESCRIPTION, 287 tr("Shows the previous picture in the sequence")); 288 } 289 290 @Override 291 public void actionPerformed(ActionEvent e) { 292 if (MapillaryToggleDialog.getInstance().getImage() != null) { 293 MapillaryData.getInstance().selectPrevious(); 294 } 295 } 296 } 297 298 /** 299 * Action class to jump to the image following the red line. 300 * 301 * @author nokutu 302 * 303 */ 304 class redAction extends AbstractAction { 305 public redAction() { 306 putValue(NAME, tr("Jump to red")); 307 putValue( 308 SHORT_DESCRIPTION, 309 tr("Jumps to the picture at the other side of the red line")); 310 } 311 312 @Override 313 public void actionPerformed(ActionEvent e) { 314 if (MapillaryToggleDialog.getInstance().getImage() != null) { 315 MapillaryData.getInstance().setSelectedImage( 316 MapillaryLayer.RED, true); 317 } 318 } 319 } 320 321 /** 322 * Action class to jump to the image following the blue line. 323 * 324 * @author nokutu 325 * 326 */ 327 class blueAction extends AbstractAction { 328 public blueAction() { 329 putValue(NAME, tr("Jump to blue")); 330 putValue( 331 SHORT_DESCRIPTION, 332 tr("Jumps to the picture at the other side of the blue line")); 333 } 334 335 @Override 336 public void actionPerformed(ActionEvent e) { 337 if (MapillaryToggleDialog.getInstance().getImage() != null) { 338 MapillaryData.getInstance().setSelectedImage( 339 MapillaryLayer.BLUE, true); 340 } 341 } 342 } 343 344 /** 345 * When the pictures are returned from the cache, they are set in the 346 * {@link MapillaryImageDisplay} object. 347 */ 348 @Override 349 public void loadingFinished(CacheEntry data, 350 CacheEntryAttributes attributes, LoadResult result) { 351 if (!SwingUtilities.isEventDispatchThread()) { 352 SwingUtilities.invokeLater(new Runnable() { 353 @Override 354 public void run() { 355 updateImage(); 356 } 357 }); 358 } else if (data != null && result == LoadResult.SUCCESS) { 359 try { 360 BufferedImage img = ImageIO.read(new ByteArrayInputStream(data 361 .getContent())); 362 if (this.mapillaryImageDisplay.getImage() == null) 363 mapillaryImageDisplay.setImage(img); 364 else if (img.getHeight() > this.mapillaryImageDisplay 365 .getImage().getHeight()) { 366 mapillaryImageDisplay.setImage(img); 367 } 368 } catch (IOException e) { 369 Main.error(e); 370 } 371 } 372 } 373 374 /** 375 * Creates the layout of the dialog. 376 * 377 * @param data 378 * The content of the dialog 379 * @param buttons 380 * The buttons where you can click 381 * @param reverse 382 * {@code true} if the buttons should go at the top; 383 * {@code false} otherwise. 384 */ 385 public void createLayout(Component data, List<SideButton> buttons, 386 boolean reverse) { 387 this.removeAll(); 388 JPanel panel = new JPanel(); 389 panel.setLayout(new BorderLayout()); 390 panel.add(data, BorderLayout.CENTER); 391 if (reverse) { 392 buttonsPanel = new JPanel(new GridLayout(1, 1)); 393 if (!buttons.isEmpty() && buttons.get(0) != null) { 394 final JPanel buttonRowPanel = new JPanel(Main.pref.getBoolean( 395 "dialog.align.left", false) ? new FlowLayout( 396 FlowLayout.LEFT) : new GridLayout(1, buttons.size())); 397 buttonsPanel.add(buttonRowPanel); 398 for (SideButton button : buttons) 399 buttonRowPanel.add(button); 400 } 401 panel.add(buttonsPanel, BorderLayout.NORTH); 402 createLayout(panel, true, null); 403 } else 404 createLayout(panel, true, buttons); 405 this.add(titleBar, BorderLayout.NORTH); 406 } 407 408 @Override 409 public void selectedImageChanged(MapillaryAbstractImage oldImage, 410 MapillaryAbstractImage newImage) { 411 setImage(MapillaryData.getInstance().getSelectedImage()); 412 updateImage(); 413 } 414 415 /** 416 * Action class to jump to the next picture containing a sign. 417 * 418 * @author nokutu 419 * 420 */ 421 class NextSignAction extends AbstractAction { 422 public NextSignAction() { 423 putValue(NAME, tr("Next Sign")); 424 putValue(SHORT_DESCRIPTION, 425 tr("Jumps to the next picture that contains a sign")); 426 } 427 428 @Override 429 public void actionPerformed(ActionEvent e) { 430 if (MapillaryToggleDialog.getInstance().getImage() != null) { 431 int i = MapillaryData 432 .getInstance() 433 .getImages() 434 .indexOf(MapillaryData.getInstance().getSelectedImage()); 435 for (int j = i + 1; j < MapillaryData.getInstance().getImages() 436 .size(); j++) { 437 MapillaryAbstractImage img = MapillaryData.getInstance() 438 .getImages().get(j); 439 if (img instanceof MapillaryImage) 440 if (!((MapillaryImage) img).getSigns().isEmpty()) { 441 MapillaryData.getInstance().setSelectedImage(img, 442 true); 443 return; 444 } 445 } 446 } 447 } 448 } 449 450 /** 451 * Action class to jump to the previous picture containing a sign. 452 * 453 * @author nokutu 454 * 455 */ 456 class PreviousSignAction extends AbstractAction { 457 public PreviousSignAction() { 458 putValue(NAME, tr("Previous Sign")); 459 putValue(SHORT_DESCRIPTION, 460 tr("Jumps to the previous picture that contains a sign")); 461 } 462 463 @Override 464 public void actionPerformed(ActionEvent e) { 465 if (MapillaryToggleDialog.getInstance().getImage() != null) { 466 int i = MapillaryData 467 .getInstance() 468 .getImages() 469 .indexOf(MapillaryData.getInstance().getSelectedImage()); 470 for (int j = i - 1; j >= 0; j--) { 471 MapillaryAbstractImage img = MapillaryData.getInstance() 472 .getImages().get(j); 473 if (img instanceof MapillaryImage) 474 if (!((MapillaryImage) img).getSigns().isEmpty()) { 475 MapillaryData.getInstance().setSelectedImage(img, 476 true); 477 return; 478 } 479 } 480 } 481 } 482 } 483 484 @Override 485 public void imagesAdded() { 486 } 45 ICachedLoaderListener, MapillaryDataListener { 46 47 public final static String BASE_TITLE = "Mapillary picture"; 48 49 public static MapillaryToggleDialog INSTANCE; 50 51 public volatile MapillaryAbstractImage image; 52 53 public final SideButton nextButton = new SideButton(new nextPictureAction()); 54 public final SideButton previousButton = new SideButton( 55 new previousPictureAction()); 56 public final SideButton redButton = new SideButton(new redAction()); 57 public final SideButton blueButton = new SideButton(new blueAction()); 58 59 private JPanel buttonsPanel; 60 61 public MapillaryImageDisplay mapillaryImageDisplay; 62 63 private MapillaryCache imageCache; 64 private MapillaryCache thumbnailCache; 65 66 public MapillaryToggleDialog() { 67 super(tr(BASE_TITLE), "mapillary.png", tr("Open Mapillary window"), 68 Shortcut.registerShortcut(tr("Mapillary dialog"), 69 tr("Open Mapillary main dialog"), KeyEvent.VK_M, 70 Shortcut.NONE), 200); 71 MapillaryData.getInstance().addListener(this); 72 73 mapillaryImageDisplay = new MapillaryImageDisplay(); 74 75 blueButton.setForeground(Color.BLUE); 76 redButton.setForeground(Color.RED); 77 78 createLayout( 79 mapillaryImageDisplay, 80 Arrays.asList(new SideButton[] { blueButton, previousButton, 81 nextButton, redButton }), 82 Main.pref.getBoolean("mapillary.reverse-buttons")); 83 disableAllButtons(); 84 } 85 86 public static MapillaryToggleDialog getInstance() { 87 if (INSTANCE == null) 88 INSTANCE = new MapillaryToggleDialog(); 89 return INSTANCE; 90 } 91 92 public static void destroyInstance() { 93 INSTANCE = null; 94 } 95 96 /** 97 * Downloads the image of the selected MapillaryImage and sets in the 98 * MapillaryImageDisplay object. 99 */ 100 public synchronized void updateImage() { 101 if (!SwingUtilities.isEventDispatchThread()) { 102 SwingUtilities.invokeLater(new Runnable() { 103 @Override 104 public void run() { 105 updateImage(); 106 } 107 }); 108 } else { 109 if (MapillaryLayer.INSTANCE == null) { 110 return; 111 } 112 if (this.image == null) { 113 mapillaryImageDisplay.setImage(null); 114 setTitle(tr(BASE_TITLE)); 115 disableAllButtons(); 116 return; 117 } 118 if (image instanceof MapillaryImage) { 119 mapillaryImageDisplay.hyperlink.setVisible(true); 120 MapillaryImage mapillaryImage = (MapillaryImage) this.image; 121 String title = tr(BASE_TITLE); 122 if (mapillaryImage.getUser() != null) 123 title += " -- " + mapillaryImage.getUser(); 124 if (mapillaryImage.getCapturedAt() != 0) 125 title += " -- " + mapillaryImage.getDate(); 126 setTitle(title); 127 this.nextButton.setEnabled(true); 128 this.previousButton.setEnabled(true); 129 if (mapillaryImage.next() == null 130 || !mapillaryImage.next().isVisible()) 131 this.nextButton.setEnabled(false); 132 if (mapillaryImage.previous() == null 133 || !mapillaryImage.previous().isVisible()) 134 this.previousButton.setEnabled(false); 135 136 mapillaryImageDisplay.hyperlink.setURL(mapillaryImage.getKey()); 137 // Downloads the thumbnail. 138 this.mapillaryImageDisplay.setImage(null); 139 if (thumbnailCache != null) 140 thumbnailCache.cancelOutstandingTasks(); 141 thumbnailCache = new MapillaryCache(mapillaryImage.getKey(), 142 MapillaryCache.Type.THUMBNAIL); 143 thumbnailCache.submit(this, false); 144 145 // Downloads the full resolution image. 146 if (imageCache != null) 147 imageCache.cancelOutstandingTasks(); 148 imageCache = new MapillaryCache(mapillaryImage.getKey(), 149 MapillaryCache.Type.FULL_IMAGE); 150 imageCache.submit(this, false); 151 } else if (image instanceof MapillaryImportedImage) { 152 mapillaryImageDisplay.hyperlink.setVisible(false); 153 this.nextButton.setEnabled(false); 154 this.previousButton.setEnabled(false); 155 MapillaryImportedImage mapillaryImage = (MapillaryImportedImage) this.image; 156 try { 157 mapillaryImageDisplay.setImage(mapillaryImage.getImage()); 158 } catch (IOException e) { 159 Main.error(e); 160 } 161 mapillaryImageDisplay.hyperlink.setURL(null); 162 } 163 } 164 } 165 166 private void disableAllButtons() { 167 nextButton.setEnabled(false); 168 previousButton.setEnabled(false); 169 blueButton.setEnabled(false); 170 redButton.setEnabled(false); 171 mapillaryImageDisplay.hyperlink.setVisible(false); 172 } 173 174 /** 175 * Sets a new MapillaryImage to be shown. 176 * 177 * @param image 178 */ 179 public synchronized void setImage(MapillaryAbstractImage image) { 180 this.image = image; 181 } 182 183 /** 184 * Returns the MapillaryImage objects which is being shown. 185 * 186 * @return 187 */ 188 public synchronized MapillaryAbstractImage getImage() { 189 return this.image; 190 } 191 192 /** 193 * Action class form the next image button. 194 * 195 * @author Jorge 196 * 197 */ 198 class nextPictureAction extends AbstractAction { 199 public nextPictureAction() { 200 putValue(NAME, tr("Next picture")); 201 putValue(SHORT_DESCRIPTION, 202 tr("Shows the next picture in the sequence")); 203 } 204 205 @Override 206 public void actionPerformed(ActionEvent e) { 207 if (MapillaryToggleDialog.getInstance().getImage() != null) { 208 MapillaryData.getInstance().selectNext(); 209 } 210 } 211 } 212 213 /** 214 * Action class for the previous image button. 215 * 216 * @author Jorge 217 * 218 */ 219 class previousPictureAction extends AbstractAction { 220 public previousPictureAction() { 221 putValue(NAME, tr("Previous picture")); 222 putValue(SHORT_DESCRIPTION, 223 tr("Shows the previous picture in the sequence")); 224 } 225 226 @Override 227 public void actionPerformed(ActionEvent e) { 228 if (MapillaryToggleDialog.getInstance().getImage() != null) { 229 MapillaryData.getInstance().selectPrevious(); 230 } 231 } 232 } 233 234 /** 235 * Action class to jump to the image following the red line. 236 * 237 * @author nokutu 238 * 239 */ 240 class redAction extends AbstractAction { 241 public redAction() { 242 putValue(NAME, tr("Jump to red")); 243 putValue( 244 SHORT_DESCRIPTION, 245 tr("Jumps to the picture at the other side of the red line")); 246 } 247 248 @Override 249 public void actionPerformed(ActionEvent e) { 250 if (MapillaryToggleDialog.getInstance().getImage() != null) { 251 MapillaryData.getInstance().setSelectedImage( 252 MapillaryLayer.RED, true); 253 } 254 } 255 } 256 257 /** 258 * Action class to jump to the image following the blue line. 259 * 260 * @author nokutu 261 * 262 */ 263 class blueAction extends AbstractAction { 264 public blueAction() { 265 putValue(NAME, tr("Jump to blue")); 266 putValue( 267 SHORT_DESCRIPTION, 268 tr("Jumps to the picture at the other side of the blue line")); 269 } 270 271 @Override 272 public void actionPerformed(ActionEvent e) { 273 if (MapillaryToggleDialog.getInstance().getImage() != null) { 274 MapillaryData.getInstance().setSelectedImage( 275 MapillaryLayer.BLUE, true); 276 } 277 } 278 } 279 280 /** 281 * When the pictures are returned from the cache, they are set in the 282 * {@link MapillaryImageDisplay} object. 283 */ 284 @Override 285 public void loadingFinished(CacheEntry data, 286 CacheEntryAttributes attributes, LoadResult result) { 287 if (!SwingUtilities.isEventDispatchThread()) { 288 SwingUtilities.invokeLater(new Runnable() { 289 @Override 290 public void run() { 291 updateImage(); 292 } 293 }); 294 } else if (data != null && result == LoadResult.SUCCESS) { 295 try { 296 BufferedImage img = ImageIO.read(new ByteArrayInputStream(data 297 .getContent())); 298 if (this.mapillaryImageDisplay.getImage() == null) 299 mapillaryImageDisplay.setImage(img); 300 else if (img.getHeight() > this.mapillaryImageDisplay 301 .getImage().getHeight()) { 302 mapillaryImageDisplay.setImage(img); 303 } 304 } catch (IOException e) { 305 Main.error(e); 306 } 307 } 308 } 309 310 /** 311 * Creates the layout of the dialog. 312 * 313 * @param data 314 * The content of the dialog 315 * @param buttons 316 * The buttons where you can click 317 * @param reverse 318 * {@code true} if the buttons should go at the top; 319 * {@code false} otherwise. 320 */ 321 public void createLayout(Component data, List<SideButton> buttons, 322 boolean reverse) { 323 this.removeAll(); 324 JPanel panel = new JPanel(); 325 panel.setLayout(new BorderLayout()); 326 panel.add(data, BorderLayout.CENTER); 327 if (reverse) { 328 buttonsPanel = new JPanel(new GridLayout(1, 1)); 329 if (!buttons.isEmpty() && buttons.get(0) != null) { 330 final JPanel buttonRowPanel = new JPanel(Main.pref.getBoolean( 331 "dialog.align.left", false) ? new FlowLayout( 332 FlowLayout.LEFT) : new GridLayout(1, buttons.size())); 333 buttonsPanel.add(buttonRowPanel); 334 for (SideButton button : buttons) 335 buttonRowPanel.add(button); 336 } 337 panel.add(buttonsPanel, BorderLayout.NORTH); 338 createLayout(panel, true, null); 339 } else 340 createLayout(panel, true, buttons); 341 this.add(titleBar, BorderLayout.NORTH); 342 } 343 344 @Override 345 public void selectedImageChanged(MapillaryAbstractImage oldImage, 346 MapillaryAbstractImage newImage) { 347 setImage(MapillaryData.getInstance().getSelectedImage()); 348 updateImage(); 349 } 350 351 @Override 352 public void imagesAdded() { 353 } 487 354 }
Note:
See TracChangeset
for help on using the changeset viewer.