001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.plugins.streetside.mode; 003 004import java.awt.Cursor; 005import java.awt.Graphics2D; 006import java.awt.Point; 007import java.awt.event.MouseAdapter; 008import java.util.Calendar; 009 010import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage; 011import org.openstreetmap.josm.plugins.streetside.StreetsideLayer; 012import org.openstreetmap.josm.plugins.streetside.io.download.StreetsideDownloader; 013 014import org.openstreetmap.josm.data.Bounds; 015import org.openstreetmap.josm.gui.MainApplication; 016import org.openstreetmap.josm.gui.MapView; 017import org.openstreetmap.josm.gui.NavigatableComponent.ZoomChangeListener; 018 019/** 020 * Superclass for all the mode of the {@link StreetsideLayer}. 021 * 022 * @author nokutu 023 * @see StreetsideLayer 024 */ 025public abstract class AbstractMode extends MouseAdapter implements 026 ZoomChangeListener { 027 028 private static final int DOWNLOAD_COOLDOWN = 2000; 029 private static SemiautomaticThread semiautomaticThread = new SemiautomaticThread(); 030 031 /** 032 * Cursor that should become active when this mode is activated. 033 */ 034 public int cursor = Cursor.DEFAULT_CURSOR; 035 036 protected StreetsideAbstractImage getClosest(Point clickPoint) { 037 double snapDistance = 10; 038 double minDistance = Double.MAX_VALUE; 039 StreetsideAbstractImage closest = null; 040 for (StreetsideAbstractImage image : StreetsideLayer.getInstance().getData().getImages()) { 041 Point imagePoint = MainApplication.getMap().mapView.getPoint(image.getMovingLatLon()); 042 imagePoint.setLocation(imagePoint.getX(), imagePoint.getY()); 043 double dist = clickPoint.distanceSq(imagePoint); 044 if (minDistance > dist && clickPoint.distance(imagePoint) < snapDistance 045 && image.isVisible()) { 046 minDistance = dist; 047 closest = image; 048 } 049 } 050 return closest; 051 } 052 053 /** 054 * Paint the dataset using the engine set. 055 * 056 * @param g {@link Graphics2D} used for painting 057 * @param mv The object that can translate GeoPoints to screen coordinates. 058 * @param box Area where painting is going to be performed 059 */ 060 public abstract void paint(Graphics2D g, MapView mv, Bounds box); 061 062 @Override 063 public void zoomChanged() { 064 if (StreetsideDownloader.getMode() == StreetsideDownloader.DOWNLOAD_MODE.VISIBLE_AREA) { 065 if (!semiautomaticThread.isAlive()) 066 semiautomaticThread.start(); 067 semiautomaticThread.moved(); 068 } 069 } 070 071 /** 072 * Resets the semiautomatic mode thread. 073 */ 074 public static void resetThread() { 075 semiautomaticThread.interrupt(); 076 semiautomaticThread = new SemiautomaticThread(); 077 } 078 079 private static class SemiautomaticThread extends Thread { 080 081 /** If in semiautomatic mode, the last Epoch time when there was a download */ 082 private long lastDownload; 083 084 private boolean moved; 085 086 @Override 087 public void run() { 088 while (true) { 089 if (this.moved && Calendar.getInstance().getTimeInMillis() - this.lastDownload >= DOWNLOAD_COOLDOWN) { 090 this.lastDownload = Calendar.getInstance().getTimeInMillis(); 091 StreetsideDownloader.downloadVisibleArea(); 092 this.moved = false; 093 StreetsideLayer.invalidateInstance(); 094 } 095 try { 096 Thread.sleep(100); 097 } catch (InterruptedException e) { 098 return; 099 } 100 } 101 } 102 103 public void moved() { 104 this.moved = true; 105 } 106 } 107}