Ignore:
Timestamp:
2018-06-20T22:09:16+02:00 (7 years ago)
Author:
renerr18
Message:

Vector bubbles restored and GUI updated.

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  
    290290                throw new IllegalStateException();
    291291        }
    292     StreetsideAbstractImage tempImage = selectedImage;
     292    StreetsideAbstractImage tempImage = this.selectedImage;
    293293    while (tempImage.previous() != null) {
    294294      tempImage = tempImage.previous();
  • applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideImage.java

    r34325 r34333  
    22package org.openstreetmap.josm.plugins.streetside;
    33
     4import java.util.ArrayList;
     5import java.util.Collection;
     6import java.util.Collections;
    47import java.util.List;
    58
     
    710import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils;
    811import org.openstreetmap.josm.plugins.streetside.model.UserProfile;
     12import org.openstreetmap.josm.tools.Logging;
     13
     14import org.openstreetmap.josm.plugins.streetside.model.ImageDetection;
    915
    1016/**
     
    5965  /**
    6066   * Set of traffic signs in the image.
    61    *//*
     67   */
    6268  private final List<ImageDetection> detections = Collections.synchronizedList(new ArrayList<>());
    63 */
     69
    6470  /**
    6571   * Main constructor of the class StreetsideImage
     
    100106  }
    101107
    102   /*public List<ImageDetection> getDetections() {
     108  public List<ImageDetection> getDetections() {
    103109    return detections;
    104   }*/
    105 
    106   /*public void setAllDetections(Collection<ImageDetection> newDetections) {
     110  }
     111
     112  public void setAllDetections(Collection<ImageDetection> newDetections) {
    107113    Logging.debug("Add {0} detections to image {1}", newDetections.size(), getId());
    108114    synchronized (detections) {
     
    110116      detections.addAll(newDetections);
    111117    }
    112   }*/
     118  }
    113119
    114120  public UserProfile getUser() {
     
    119125  public String toString() {
    120126    return String.format(
    121       // TODO: format date cd (Gradle build error command line)
    122127      "Image[id=%s,lat=%f,lon=%f,he=%f,user=%s]",
    123128      id, latLon.lat(), latLon.lon(), he, "null"//, cd
  • applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideLayer.java

    r34329 r34333  
    8181  ) / 3;
    8282
    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  });
    9190
    9291        /** Unique instance of the class. */
     
    207206         */
    208207        public StreetsideData getData() {
    209                 return this.data;
     208                return data;
    210209        }
    211210
     
    259258
    260259
    261         @Override
     260  @Override
    262261  public boolean isModified() {
    263     return this.data.getImages().parallelStream().anyMatch(StreetsideAbstractImage::isModified);
     262    return data.getImages().parallelStream().anyMatch(StreetsideAbstractImage::isModified);
    264263  }
    265264
     
    286285    big.drawLine(0, 15, 15, 0);
    287286    Rectangle r = new Rectangle(0, 0, 15, 15);
    288     this.hatched = new TexturePaint(bi, r);
     287    hatched = new TexturePaint(bi, r);
    289288  }
    290289
     
    295294      // paint remainder
    296295      g.setPaint(hatched);
    297       g.fill(MapViewGeometryUtil.getNonDownloadedArea(mv, this.data.getBounds()));
     296      g.fill(MapViewGeometryUtil.getNonDownloadedArea(mv, data.getBounds()));
    298297    }
    299298
     
    314313
    315314    // Draw sequence line
    316     g.setStroke(new BasicStroke(2));
     315    // TODO: reimplement sequence lines for Streetside
     316    /*g.setStroke(new BasicStroke(2));
    317317    final StreetsideAbstractImage selectedImage = getData().getSelectedImage();
    318318    for (StreetsideSequence seq : getData().getSequences()) {
     
    327327      }
    328328      g.draw(MapViewGeometryUtil.getSequencePath(mv, seq));
    329     }
    330     for (StreetsideAbstractImage imageAbs : this.data.getImages()) {
     329    }*/
     330    for (StreetsideAbstractImage imageAbs : data.getImages()) {
    331331      if (imageAbs.isVisible() && mv != null && mv.contains(mv.getPoint(imageAbs.getMovingLatLon()))) {
    332332        drawImageMarker(g, imageAbs);
    333333      }
    334334    }
    335     if (this.mode instanceof JoinMode) {
    336       this.mode.paint(g, mv, box);
     335    if (mode instanceof JoinMode) {
     336      mode.paint(g, mv, box);
    337337    }
    338338  }
     
    392392
    393393
    394                 /*if (img instanceof StreetsideImage && !((StreetsideImage) img).getDetections().isEmpty()) {
    395                         final Path2D trafficSign = new Path2D.Double();
     394                if (img instanceof StreetsideImage && !((StreetsideImage) img).getDetections().isEmpty()) {
     395                        Path2D trafficSign = new Path2D.Double();
    396396                        trafficSign.moveTo(p.getX() - StreetsideLayer.TRAFFIC_SIGN_SIZE / 2d, p.getY() - StreetsideLayer.TRAFFIC_SIGN_HEIGHT_3RD);
    397397                        trafficSign.lineTo(p.getX() + StreetsideLayer.TRAFFIC_SIGN_SIZE / 2d, p.getY() - StreetsideLayer.TRAFFIC_SIGN_HEIGHT_3RD);
     
    403403                        g.setColor(Color.RED);
    404404                        g.draw(trafficSign);
    405                 }*/
     405                }
    406406        }
    407407
  • applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsidePlugin.java

    r34329 r34333  
    2626import org.openstreetmap.josm.tools.ImageProvider;
    2727
     28import org.openstreetmap.josm.plugins.streetside.gui.StreetsideChangesetDialog;
     29
    2830/**
    2931 * This is the main class of the Streetside plugin.
     
    4850      MainMenu.add(MainApplication.getMenu().dataMenu, new StreetsideJoinAction(), false);
    4951      MainMenu.add(MainApplication.getMenu().moreToolsMenu, WALK_ACTION, false);
    50       //MainMenu.add(MainApplication.getMenu().imagerySubMenu, new MapObjectLayerAction(), false);
    5152      //MainMenu.add(MainApplication.getMenu().imagerySubMenu, new MapObjectLayerAction(), false);
    5253    }
     
    7576   * @return the {@link StreetsideWalkAction} for the plugin
    7677   */
    77   public static StreetsideWalkAction getStreetsideWalkAction() {
     78  public static StreetsideWalkAction getWalkAction() {
    7879    return WALK_ACTION;
    7980  }
     
    9192      MainApplication.getMap().addToggleDialog(StreetsideViewerDialog.getInstance(), false);
    9293      //MainApplication.getMap().addToggleDialog(StreetsideHistoryDialog.getInstance(), false);
    93       //MainApplication.getMap().addToggleDialog(StreetsideChangesetDialog.getInstance(), false);
     94      MainApplication.getMap().addToggleDialog(StreetsideChangesetDialog.getInstance(), false);
    9495      //MainApplication.getMap().addToggleDialog(StreetsideFilterDialog.getInstance(), false);
    9596    }
     
    9798      StreetsideMainDialog.destroyInstance();
    9899      //StreetsideHistoryDialog.destroyInstance();
    99       //StreetsideChangesetDialog.destroyInstance();
     100      StreetsideChangesetDialog.destroyInstance();
    100101      //StreetsideFilterDialog.destroyInstance();
    101102      ImageInfoPanel.destroyInstance();
     
    131132   * @return the {@link StreetsideZoomAction} for the plugin
    132133   */
    133   /*public static StreetsideZoomAction getZoomAction() {
     134  public static StreetsideZoomAction getZoomAction() {
    134135    return ZOOM_ACTION;
    135   }*/
    136136  }
     137
     138}
  • applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/WalkThread.java

    r34317 r34333  
    22package org.openstreetmap.josm.plugins.streetside.actions;
    33
    4 import java.awt.image.BufferedImage;
    5 
    64import javax.swing.SwingUtilities;
    75
     6import org.openstreetmap.josm.gui.Notification;
    87import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
    98import org.openstreetmap.josm.plugins.streetside.StreetsideData;
    109import org.openstreetmap.josm.plugins.streetside.StreetsideDataListener;
     10import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
     11import org.openstreetmap.josm.plugins.streetside.StreetsidePlugin;
     12import org.openstreetmap.josm.plugins.streetside.cache.CacheUtils;
     13import org.openstreetmap.josm.plugins.streetside.cache.StreetsideCache;
     14import org.openstreetmap.josm.plugins.streetside.gui.StreetsideMainDialog;
     15import org.openstreetmap.josm.tools.I18n;
     16import org.openstreetmap.josm.tools.Logging;
     17
    1118import 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 
    1619
    1720/**
     
    2730  private final boolean followSelected;
    2831  private final boolean goForward;
    29   private BufferedImage lastImage;
    3032  private volatile boolean paused;
    3133
     
    5254  public void run() {
    5355    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);
    7068        }
    7169        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;
    8181            }
    8282          }
     
    8484            Thread.sleep(100);
    8585          }
    86           wait(interval);
     86          Thread.sleep(interval);
    8787          while (paused) {
    8888            Thread.sleep(100);
    8989          }
    90           lastImage = StreetsideMainDialog.getInstance().getStreetsideImageDisplay().getImage();
    9190          if (goForward) {
    9291            data.selectNext(followSelected);
     
    9594          }
    9695        } catch (InterruptedException e) {
     96          end();
    9797          return;
    9898        }
     99
    99100      }
    100 
    101         // TODO: WalkThread for cubemaps? @rrh
    102         /*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 @rrh
    109                 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? @rrh
    117                   while (displayCubemap == lastCubemap || displayCubemap == null || displayCubemap.getWidth() < 2048) {
    118                   Thread.sleep(100);
    119                 }
    120               } else { // Waits for thumbnail.
    121                   // TODO: handle cubemap width? @rrh
    122                   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? @rrh
    135               if (goForward) {
    136                 data.selectNext(followSelected);
    137               } else {
    138                 data.selectPrevious(followSelected);
    139               }
    140             } catch (InterruptedException e) {
    141               return;
    142             }
    143           }*/
    144101    } catch (NullPointerException e) {
     102      Logging.warn(e);
     103      end();
    145104      // TODO: Avoid NPEs instead of waiting until they are thrown and then catching them
    146105      return;
     
    149108  }
    150109
    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  /**
    169111   * Downloads n images into the cache beginning from the supplied start-image (including the start-image itself).
    170112   *
     
    172114   * @param n the number of images to download
    173115   * @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
    174117   */
    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) {
    176119    if (n >= 1 && startImage != null) {
    177120      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);
    180124      }
    181125    }
     
    224168   * Called when the walk stops by itself of forcefully.
    225169   */
    226   public void end() {
     170  private void end() {
    227171    if (SwingUtilities.isEventDispatchThread()) {
    228172      end = true;
     
    232176      SwingUtilities.invokeLater(this::end);
    233177    }
    234     // TODO: WalkThread for Cubemaps? @rrh
    235     /*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       }*/
    242178  }
    243179}
  • applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideExportDialog.java

    r34317 r34333  
    134134
    135135    private static final long serialVersionUID = 1035332841101190301L;
    136 
    137         private String lastPath;
     136    private String lastPath;
    138137    private final StreetsideExportDialog dlg;
    139138
  • applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideImageDisplay.java

    r34317 r34333  
    3939 *
    4040 * @author nokutu
     41 * @author renerr18
     42 *
    4143 * @see StreetsideImageDisplay
    4244 * @see StreetsideMainDialog
     
    8082        visibleRect = StreetsideImageDisplay.this.visibleRect;
    8183      }
    82       mouseIsDragging = false;
     84      this.mouseIsDragging = false;
    8385      selectedRect = null;
    8486      if (image != null && Math.min(getSize().getWidth(), getSize().getHeight()) > 0) {
     
    8991        // borders, this point is not calculated
    9092        // 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());
    9496        }
    9597        // Set the zoom to the visible rectangle in image coordinates
     
    121123        // cursor doesn't move on the image.
    122124        Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
    123         visibleRect.x = mousePointInImg.x
     125        visibleRect.x = this.mousePointInImg.x
    124126            + ((drawRect.x - e.getX()) * visibleRect.width) / drawRect.width;
    125         visibleRect.y = mousePointInImg.y
     127        visibleRect.y = this.mousePointInImg.y
    126128            + ((drawRect.y - e.getY()) * visibleRect.height) / drawRect.height;
    127129        // The position is also limited by the image size
     
    185187    public void mousePressed(MouseEvent e) {
    186188      if (getImage() == null) {
    187         mouseIsDragging = false;
    188         selectedRect = null;
     189        this.mouseIsDragging = false;
     190       StreetsideImageDisplay.this.selectedRect = null;
    189191        return;
    190192      }
     
    198200        return;
    199201      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;
    203205      } else if (e.getButton() == StreetsideProperties.PICTURE_ZOOM_BUTTON.get()) {
    204206        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);
    208210        StreetsideImageDisplay.this.repaint();
    209211      } else {
    210         mouseIsDragging = false;
    211         selectedRect = null;
     212        this.mouseIsDragging = false;
     213        StreetsideImageDisplay.this.selectedRect = null;
    212214      }
    213215    }
     
    215217    @Override
    216218    public void mouseDragged(MouseEvent e) {
    217       if (!mouseIsDragging && selectedRect == null)
     219      if (!this.mouseIsDragging && StreetsideImageDisplay.this.selectedRect == null)
    218220        return;
    219221      Image image;
     
    224226      }
    225227      if (image == null) {
    226         mouseIsDragging = false;
    227         selectedRect = null;
     228        this.mouseIsDragging = false;
     229        StreetsideImageDisplay.this.selectedRect = null;
    228230        return;
    229231      }
    230       if (mouseIsDragging) {
     232      if (this.mouseIsDragging) {
    231233        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;
    234236        checkVisibleRectPos(image, visibleRect);
    235237        synchronized (StreetsideImageDisplay.this) {
     
    237239        }
    238240        StreetsideImageDisplay.this.repaint();
    239       } else if (selectedRect != null) {
     241      } else if (StreetsideImageDisplay.this.selectedRect != null) {
    240242        Point p = comp2imgCoord(visibleRect, e.getX(), e.getY());
    241243        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);
    248250        checkVisibleRectSize(image, rect);
    249251        checkVisibleRectPos(image, rect);
    250         selectedRect = rect;
     252        StreetsideImageDisplay.this.selectedRect = rect;
    251253        StreetsideImageDisplay.this.repaint();
    252254      }
     
    255257    @Override
    256258    public void mouseReleased(MouseEvent e) {
    257       if (!mouseIsDragging && selectedRect == null)
     259      if (!this.mouseIsDragging && StreetsideImageDisplay.this.selectedRect == null)
    258260        return;
    259261      Image image;
     
    262264      }
    263265      if (image == null) {
    264         mouseIsDragging = false;
    265         selectedRect = null;
     266        this.mouseIsDragging = false;
     267        StreetsideImageDisplay.this.selectedRect = null;
    266268        return;
    267269      }
    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;
    273275        // 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;
    279281        }
    280282        // Set the same ratio for the visible rectangle and the display
    281283        // 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;
    284286        if (hFact > wFact) {
    285           selectedRect.width = hFact / getSize().height;
     287                StreetsideImageDisplay.this.selectedRect.width = hFact / getSize().height;
    286288        } else {
    287           selectedRect.height = wFact / getSize().width;
     289                StreetsideImageDisplay.this.selectedRect.height = wFact / getSize().width;
    288290        }
    289291        // 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);
    298300        synchronized (StreetsideImageDisplay.this) {
    299           visibleRect = selectedRect;
    300         }
    301         selectedRect = null;
     301          StreetsideImageDisplay.this.visibleRect = StreetsideImageDisplay.this.selectedRect;
     302        }
     303        StreetsideImageDisplay.this.selectedRect = null;
    302304        StreetsideImageDisplay.this.repaint();
    303305      }
     
    360362        this.detections.addAll(detections);
    361363      }
    362       selectedRect = null;
     364      this.selectedRect = null;
    363365      if (image != null)
    364         visibleRect = new Rectangle(0, 0, image.getWidth(null),
     366        this.visibleRect = new Rectangle(0, 0, image.getWidth(null),
    365367            image.getHeight(null));
    366368    }
     
    374376   */
    375377  public BufferedImage getImage() {
    376     return image;
     378    return this.image;
    377379  }
    378380
     
    402404          + target.height, visibleRect.x, visibleRect.y, visibleRect.x
    403405          + 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);
    409411        g.setColor(new Color(128, 128, 128, 180));
    410412        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  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.plugins.streetside.gui;
     3
     4import static org.openstreetmap.josm.tools.I18n.marktr;
     5import static org.openstreetmap.josm.tools.I18n.tr;
     6import static org.openstreetmap.josm.tools.I18n.trc;
    37
    48import java.awt.BorderLayout;
     
    1418import javax.imageio.ImageIO;
    1519import javax.swing.AbstractAction;
    16 import javax.swing.Action;
    1720import javax.swing.JComponent;
    1821import javax.swing.KeyStroke;
     
    3437import org.openstreetmap.josm.plugins.streetside.cache.StreetsideCache;
    3538import org.openstreetmap.josm.plugins.streetside.gui.imageinfo.ImageInfoHelpPopup;
    36 import org.openstreetmap.josm.plugins.streetside.gui.imageinfo.StreetsideViewerHelpPopup;
     39import org.openstreetmap.josm.plugins.streetside.model.UserProfile;
    3740import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
    38 import org.openstreetmap.josm.tools.I18n;
    3941import org.openstreetmap.josm.tools.ImageProvider;
    4042import org.openstreetmap.josm.tools.Logging;
     
    4446 *
    4547 * @author nokutu
    46  * @author renerr18
    4748 */
    4849public 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
    651614}
  • applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/StreetsideViewerPanel.java

    r34325 r34333  
    8484            checkPanel.add(privacyLink, BorderLayout.PAGE_END);
    8585
    86             add(checkPanel, BorderLayout.PAGE_START);
     86            add(checkPanel, BorderLayout.SOUTH);
    8787            add(threeSixtyDegreeViewerPanel, BorderLayout.CENTER);
    8888
  • applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/SequenceDownloadRunnable.java

    r34317 r34333  
    4848    }
    4949
    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());
    5153
    5254    // 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.