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