Changeset 31278 in osm for applications/editors


Ignore:
Timestamp:
2015-06-18T18:08:53+02:00 (9 years ago)
Author:
nokutu
Message:

Tabs to spaces

Location:
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary
Files:
35 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryAbstractImage.java

    r31264 r31278  
    1212public abstract class MapillaryAbstractImage {
    1313
    14         /** Postion of the picture */
    15         public final LatLon latLon;
    16         /** Direction of the picture */
    17         public final double ca;
    18         public boolean isModified = false;
    19         /** Temporal position of the picture until it is uplaoded */
    20         public LatLon tempLatLon;
    21         /**
    22         * When the object is being dragged in the map, the temporal position is
    23         * stored here
    24         */
    25         public LatLon movingLatLon;
    26         /** Temporal direction of the picture until it is uplaoded */
    27         public double tempCa;
    28         /**
    29         * When the object direction is being moved in the map, the temporal
    30         * direction is stored here
    31         */
    32         protected double movingCa;
     14    /** Postion of the picture */
     15    public final LatLon latLon;
     16    /** Direction of the picture */
     17    public final double ca;
     18    public boolean isModified = false;
     19    /** Temporal position of the picture until it is uplaoded */
     20    public LatLon tempLatLon;
     21    /**
     22    * When the object is being dragged in the map, the temporal position is
     23    * stored here
     24    */
     25    public LatLon movingLatLon;
     26    /** Temporal direction of the picture until it is uplaoded */
     27    public double tempCa;
     28    /**
     29    * When the object direction is being moved in the map, the temporal
     30    * direction is stored here
     31    */
     32    protected double movingCa;
    3333
    34         public MapillaryAbstractImage(double lat, double lon, double ca) {
    35                 this.latLon = new LatLon(lat, lon);
    36                 this.tempLatLon = this.latLon;
    37                 this.movingLatLon = this.latLon;
    38                 this.ca = ca;
    39                 this.tempCa = ca;
    40                 this.movingCa = ca;
    41         }
     34    public MapillaryAbstractImage(double lat, double lon, double ca) {
     35        this.latLon = new LatLon(lat, lon);
     36        this.tempLatLon = this.latLon;
     37        this.movingLatLon = this.latLon;
     38        this.ca = ca;
     39        this.tempCa = ca;
     40        this.movingCa = ca;
     41    }
    4242
    43         /**
    44         * Returns whether the object has been modified or not.
    45         *
    46         * @return true if the object has been modified; false otherwise.
    47         */
    48         public boolean isModified() {
    49                 return this.isModified;
    50         }
     43    /**
     44    * Returns whether the object has been modified or not.
     45    *
     46    * @return true if the object has been modified; false otherwise.
     47    */
     48    public boolean isModified() {
     49        return this.isModified;
     50    }
    5151
    52         /**
    53          * Returns a LatLon object containing the coordintes of the object.
    54          *
    55          * @return The LatLon object with the position of the object.
    56          */
    57         public LatLon getLatLon() {
    58                 return movingLatLon;
    59         }
     52    /**
     53     * Returns a LatLon object containing the current coordinates of the object.
     54     * When you are dragging the image this changes.
     55     *
     56     * @return The LatLon object with the position of the object.
     57     */
     58    public LatLon getLatLon() {
     59        return movingLatLon;
     60    }
    6061
    61         public LatLon getTempLatLon() {
    62                 return tempLatLon;
    63         }
     62    /**
     63     * Returns the last fixed coorditanes of the object.
     64     *
     65     * @return
     66     */
     67    public LatLon getTempLatLon() {
     68        return tempLatLon;
     69    }
    6470
    65         /**
    66         * Moves the image temporally to another position
    67         *
    68         * @param pos
    69         */
    70         public void move(double x, double y) {
    71                 this.movingLatLon = new LatLon(this.tempLatLon.getY() + y,
    72                                 this.tempLatLon.getX() + x);
    73                 this.isModified = true;
    74         }
     71    /**
     72    * Moves the image temporally to another position
     73    *
     74    * @param pos
     75    */
     76    public void move(double x, double y) {
     77        this.movingLatLon = new LatLon(this.tempLatLon.getY() + y,
     78                this.tempLatLon.getX() + x);
     79        this.isModified = true;
     80    }
    7581
    76         /**
    77         * Turns the image direction.
    78         *
    79         * @param ca
    80         */
    81         public void turn(double ca) {
    82                 this.movingCa = this.tempCa + ca;
    83                 this.isModified = true;
    84         }
     82    /**
     83    * Turns the image direction.
     84    *
     85    * @param ca
     86    */
     87    public void turn(double ca) {
     88        this.movingCa = this.tempCa + ca;
     89        this.isModified = true;
     90    }
    8591
    86         /**
    87         * Called when the mouse button is released, meaning that the picture has
    88         * stopped being dragged.
    89         */
    90         public void stopMoving() {
    91                 this.tempLatLon = this.movingLatLon;
    92                 this.tempCa = this.movingCa;
    93         }
     92    /**
     93    * Called when the mouse button is released, meaning that the picture has
     94    * stopped being dragged.
     95    */
     96    public void stopMoving() {
     97        this.tempLatLon = this.movingLatLon;
     98        this.tempCa = this.movingCa;
     99    }
    94100
    95         /**
    96         * Returns the direction towards the image has been taken.
    97         *
    98         * @return The direction of the image (0 means north and goes clockwise).
    99         */
    100         public double getCa() {
    101                 return movingCa;
    102         }
     101    /**
     102    * Returns the direction towards the image has been taken.
     103    *
     104    * @return The direction of the image (0 means north and goes clockwise).
     105    */
     106    public double getCa() {
     107        return movingCa;
     108    }
    103109
    104         /**
    105         * Returns the last fixed direction of the object.
    106         *
    107         * @return
    108         */
    109         public double getTempCa() {
    110                 return tempCa;
    111         }
     110    /**
     111    * Returns the last fixed direction of the object.
     112    *
     113    * @return
     114    */
     115    public double getTempCa() {
     116        return tempCa;
     117    }
    112118}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java

    r31271 r31278  
    2020 */
    2121public class MapillaryData implements ICachedLoaderListener {
    22         public volatile static MapillaryData INSTANCE;
    23 
    24         private final List<MapillaryAbstractImage> images;
    25         private MapillaryAbstractImage selectedImage;
    26         private MapillaryAbstractImage hoveredImage;
    27         private final List<MapillaryAbstractImage> multiSelectedImages;
    28 
    29         private List<MapillaryDataListener> listeners = new ArrayList<>();
    30 
    31         public MapillaryData() {
    32                 images = new CopyOnWriteArrayList<>();
    33                 multiSelectedImages = new ArrayList<>();
    34                 selectedImage = null;
    35         }
    36 
    37         public static MapillaryData getInstance() {
    38                 if (INSTANCE == null) {
    39                         INSTANCE = new MapillaryData();
    40                 }
    41                 return INSTANCE;
    42         }
    43 
    44         /**
    45         * Adds a set of MapillaryImages to the object, and then repaints mapView.
    46         *
    47         * @param images
    48         *            The set of images to be added.
    49         */
    50         public synchronized void add(List<MapillaryAbstractImage> images) {
    51                 for (MapillaryAbstractImage image : images) {
    52                         add(image);
    53                 }
    54         }
    55 
    56         /**
    57         * Adds an MapillaryImage to the object, and then repaints mapView.
    58         *
    59         * @param image
    60         *            The image to be added.
    61         */
    62         public synchronized void add(MapillaryAbstractImage image) {
    63                 if (!images.contains(image)) {
    64                         this.images.add(image);
    65                 }
    66                 dataUpdated();
    67         }
    68 
    69         public void addListener(MapillaryDataListener lis) {
    70                 listeners.add(lis);
    71         }
    72 
    73         public void removeListener(MapillaryDataListener lis) {
    74                 listeners.remove(lis);
    75         }
    76 
    77         /**
    78         * Adds a set of MapillaryImages to the object, but doesn't repaint mapView.
    79         * This is needed for concurrency.
    80         *
    81         * @param images
    82         *            The set of images to be added.
    83         */
    84         public synchronized void addWithoutUpdate(
    85                         List<MapillaryAbstractImage> images) {
    86                 for (MapillaryAbstractImage image : images) {
    87                         addWithoutUpdate(image);
    88                 }
    89         }
    90 
    91         /**
    92         * Sets the image under the mouse cursor.
    93         *
    94         * @param image
    95         */
    96         public void setHoveredImage(MapillaryAbstractImage image) {
    97                 hoveredImage = image;
    98         }
    99 
    100         /**
    101         * Returns the image under the mouse cursor.
    102         *
    103         * @return
    104         */
    105         public MapillaryAbstractImage getHoveredImage() {
    106                 return hoveredImage;
    107         }
    108 
    109         /**
    110         * Adds a MapillaryImage to the object, but doesn't repaint mapView. This is
    111         * needed for concurrency.
    112         *
    113         * @param image
    114         *            The image to be added.
    115         */
    116         public synchronized void addWithoutUpdate(MapillaryAbstractImage image) {
    117                 if (!images.contains(image)) {
    118                         this.images.add(image);
    119                 }
    120         }
    121 
    122         /**
    123         * Repaints mapView object.
    124         */
    125         public synchronized void dataUpdated() {
    126                 Main.map.mapView.repaint();
    127         }
    128 
    129         /**
    130         * Returns a List containing all images.
    131         *
    132         * @return A List object containing all images.
    133         */
    134         public List<MapillaryAbstractImage> getImages() {
    135                 return images;
    136         }
    137 
    138         /**
    139         * Returns the MapillaryImage object that is currently selected.
    140         *
    141         * @return The selected MapillaryImage object.
    142         */
    143         public MapillaryAbstractImage getSelectedImage() {
    144                 return selectedImage;
    145         }
    146 
    147         /**
    148         * If the selected MapillaryImage is part of a MapillarySequence then the
    149         * following MapillaryImage is selected. In case there is none, does
    150         * nothing.
    151         */
    152         public void selectNext() {
    153                 if (getSelectedImage() instanceof MapillaryImage) {
    154                         if (getSelectedImage() == null)
    155                                 return;
    156                         if (((MapillaryImage) getSelectedImage()).getSequence() == null)
    157                                 return;
    158                         setSelectedImage(((MapillaryImage) getSelectedImage()).next(), true);
    159                 }
    160         }
    161 
    162         /**
    163         * If the selected MapillaryImage is part of a MapillarySequence then the
    164         * previous MapillaryImage is selected. In case there is none, does nothing.
    165         */
    166         public void selectPrevious() {
    167                 if (getSelectedImage() instanceof MapillaryImage) {
    168                         if (getSelectedImage() == null)
    169                                 return;
    170                         if (((MapillaryImage) getSelectedImage()).getSequence() == null)
    171                                 throw new IllegalStateException();
    172                         setSelectedImage(((MapillaryImage) getSelectedImage()).previous(),
    173                                         true);
    174                 }
    175         }
    176 
    177         /**
    178         * Selects a new image and then starts a new MapillaryImageDownloadThread
    179         * thread in order to download its surrounding thumbnails. If the user does
    180         * ctrl+click, this isn't triggered.
    181         *
    182         * @param image
    183         *            The MapillaryImage which is going to be selected
    184         */
    185         public void setSelectedImage(MapillaryAbstractImage image) {
    186                 setSelectedImage(image, false);
    187         }
    188 
    189         /**
    190         * Selects a new image and then starts a new MapillaryImageDownloadThread
    191         * thread in order to download its surrounding thumbnails. If the user does
    192         * ctrl+click, this isn't triggered. You can choose wheter to center the
    193         * view on the new image or not.
    194         *
    195         * @param image
    196         * @param zoom
    197         */
    198         public void setSelectedImage(MapillaryAbstractImage image, boolean zoom) {
    199                 MapillaryAbstractImage oldImage = selectedImage;
    200                 selectedImage = image;
    201                 multiSelectedImages.clear();
    202                 multiSelectedImages.add(image);
    203                 if (image != null) {
    204                         if (image instanceof MapillaryImage) {
    205                                 MapillaryImage mapillaryImage = (MapillaryImage) image;
    206                                 if (mapillaryImage.next() != null) {
    207                                         new MapillaryCache(mapillaryImage.next().getKey(),
    208                                                         MapillaryCache.Type.THUMBNAIL).submit(this, false);
    209                                         if (mapillaryImage.next().next() != null)
    210                                                 new MapillaryCache(mapillaryImage.next().next()
    211                                                                 .getKey(), MapillaryCache.Type.THUMBNAIL)
    212                                                                 .submit(this, false);
    213                                 }
    214                                 if (mapillaryImage.previous() != null) {
    215                                         new MapillaryCache(mapillaryImage.previous().getKey(),
    216                                                         MapillaryCache.Type.THUMBNAIL).submit(this, false);
    217                                         if (mapillaryImage.previous().previous() != null)
    218                                                 new MapillaryCache(mapillaryImage.previous().previous()
    219                                                                 .getKey(), MapillaryCache.Type.THUMBNAIL)
    220                                                                 .submit(this, false);
    221                                 }
    222                         }
    223                 }
    224                 if (zoom)
    225                         Main.map.mapView.zoomTo(MapillaryData.getInstance()
    226                                         .getSelectedImage().getLatLon());
    227                 if (Main.map != null) {
    228                         Main.map.mapView.repaint();
    229                 }
    230                 fireSelectedImageChanged(oldImage, selectedImage);
    231         }
    232 
    233         private void fireSelectedImageChanged(MapillaryAbstractImage oldImage,
    234                         MapillaryAbstractImage newImage) {
    235                 if (listeners.isEmpty())
    236                         return;
    237                 for (MapillaryDataListener lis : listeners)
    238                         lis.selectedImageChanged(oldImage, newImage);
    239         }
    240 
    241         /**
    242         * Adds a MapillaryImage object to the list of selected images, (when ctrl +
    243         * click)
    244         *
    245         * @param image
    246         *            The MapillaryImage object to be added.
    247         */
    248         public void addMultiSelectedImage(MapillaryAbstractImage image) {
    249                 if (!this.multiSelectedImages.contains(image)) {
    250                         if (this.getSelectedImage() != null)
    251                                 this.multiSelectedImages.add(image);
    252                         else
    253                                 this.setSelectedImage(image);
    254                 }
    255                 Main.map.mapView.repaint();
    256         }
    257 
    258         /**
    259         * Adds a set of MapillaryImage objects to the list of selected images.
    260         *
    261         * @param images
    262         */
    263         public void addMultiSelectedImage(List<MapillaryAbstractImage> images) {
    264                 for (MapillaryAbstractImage image : images)
    265                         if (!this.multiSelectedImages.contains(image)) {
    266                                 if (this.getSelectedImage() != null)
    267                                         this.multiSelectedImages.add(image);
    268                                 else
    269                                         this.setSelectedImage(image);
    270                         }
    271                 Main.map.mapView.repaint();
    272         }
    273 
    274         /**
    275         * Returns a list containing all MapillaryImage objects selected with ctrl +
    276         * click
    277         *
    278         * @return
    279         */
    280         public List<MapillaryAbstractImage> getMultiSelectedImages() {
    281                 return multiSelectedImages;
    282         }
    283 
    284         /**
    285         * This is empty because it is used just to make sure that certain images
    286         * have already been downloaded.
    287         */
    288         @Override
    289         public void loadingFinished(CacheEntry data,
    290                         CacheEntryAttributes attributes, LoadResult result) {
    291                 // DO NOTHING
    292         }
     22    public volatile static MapillaryData INSTANCE;
     23
     24    private final List<MapillaryAbstractImage> images;
     25    private MapillaryAbstractImage selectedImage;
     26    private MapillaryAbstractImage hoveredImage;
     27    private final List<MapillaryAbstractImage> multiSelectedImages;
     28
     29    private List<MapillaryDataListener> listeners = new ArrayList<>();
     30
     31    public MapillaryData() {
     32        images = new CopyOnWriteArrayList<>();
     33        multiSelectedImages = new ArrayList<>();
     34        selectedImage = null;
     35    }
     36
     37    public static MapillaryData getInstance() {
     38        if (INSTANCE == null) {
     39            INSTANCE = new MapillaryData();
     40        }
     41        return INSTANCE;
     42    }
     43
     44    /**
     45    * Adds a set of MapillaryImages to the object, and then repaints mapView.
     46    *
     47    * @param images
     48    *            The set of images to be added.
     49    */
     50    public synchronized void add(List<MapillaryAbstractImage> images) {
     51        for (MapillaryAbstractImage image : images) {
     52            add(image);
     53        }
     54    }
     55
     56    /**
     57    * Adds an MapillaryImage to the object, and then repaints mapView.
     58    *
     59    * @param image
     60    *            The image to be added.
     61    */
     62    public synchronized void add(MapillaryAbstractImage image) {
     63        if (!images.contains(image)) {
     64            this.images.add(image);
     65        }
     66        dataUpdated();
     67    }
     68
     69    public void addListener(MapillaryDataListener lis) {
     70        listeners.add(lis);
     71    }
     72
     73    public void removeListener(MapillaryDataListener lis) {
     74        listeners.remove(lis);
     75    }
     76
     77    /**
     78    * Adds a set of MapillaryImages to the object, but doesn't repaint mapView.
     79    * This is needed for concurrency.
     80    *
     81    * @param images
     82    *            The set of images to be added.
     83    */
     84    public synchronized void addWithoutUpdate(
     85            List<MapillaryAbstractImage> images) {
     86        for (MapillaryAbstractImage image : images) {
     87            addWithoutUpdate(image);
     88        }
     89    }
     90
     91    /**
     92    * Sets the image under the mouse cursor.
     93    *
     94    * @param image
     95    */
     96    public void setHoveredImage(MapillaryAbstractImage image) {
     97        hoveredImage = image;
     98    }
     99
     100    /**
     101    * Returns the image under the mouse cursor.
     102    *
     103    * @return
     104    */
     105    public MapillaryAbstractImage getHoveredImage() {
     106        return hoveredImage;
     107    }
     108
     109    /**
     110    * Adds a MapillaryImage to the object, but doesn't repaint mapView. This is
     111    * needed for concurrency.
     112    *
     113    * @param image
     114    *            The image to be added.
     115    */
     116    public synchronized void addWithoutUpdate(MapillaryAbstractImage image) {
     117        if (!images.contains(image)) {
     118            this.images.add(image);
     119        }
     120    }
     121
     122    /**
     123    * Repaints mapView object.
     124    */
     125    public synchronized void dataUpdated() {
     126        Main.map.mapView.repaint();
     127    }
     128
     129    /**
     130    * Returns a List containing all images.
     131    *
     132    * @return A List object containing all images.
     133    */
     134    public List<MapillaryAbstractImage> getImages() {
     135        return images;
     136    }
     137
     138    /**
     139    * Returns the MapillaryImage object that is currently selected.
     140    *
     141    * @return The selected MapillaryImage object.
     142    */
     143    public MapillaryAbstractImage getSelectedImage() {
     144        return selectedImage;
     145    }
     146
     147    /**
     148    * If the selected MapillaryImage is part of a MapillarySequence then the
     149    * following MapillaryImage is selected. In case there is none, does
     150    * nothing.
     151    */
     152    public void selectNext() {
     153        if (getSelectedImage() instanceof MapillaryImage) {
     154            if (getSelectedImage() == null)
     155                return;
     156            if (((MapillaryImage) getSelectedImage()).getSequence() == null)
     157                return;
     158            setSelectedImage(((MapillaryImage) getSelectedImage()).next(), true);
     159        }
     160    }
     161
     162    /**
     163    * If the selected MapillaryImage is part of a MapillarySequence then the
     164    * previous MapillaryImage is selected. In case there is none, does nothing.
     165    */
     166    public void selectPrevious() {
     167        if (getSelectedImage() instanceof MapillaryImage) {
     168            if (getSelectedImage() == null)
     169                return;
     170            if (((MapillaryImage) getSelectedImage()).getSequence() == null)
     171                throw new IllegalStateException();
     172            setSelectedImage(((MapillaryImage) getSelectedImage()).previous(),
     173                    true);
     174        }
     175    }
     176
     177    /**
     178    * Selects a new image and then starts a new MapillaryImageDownloadThread
     179    * thread in order to download its surrounding thumbnails. If the user does
     180    * ctrl+click, this isn't triggered.
     181    *
     182    * @param image
     183    *            The MapillaryImage which is going to be selected
     184    */
     185    public void setSelectedImage(MapillaryAbstractImage image) {
     186        setSelectedImage(image, false);
     187    }
     188
     189    /**
     190    * Selects a new image and then starts a new MapillaryImageDownloadThread
     191    * thread in order to download its surrounding thumbnails. If the user does
     192    * ctrl+click, this isn't triggered. You can choose wheter to center the
     193    * view on the new image or not.
     194    *
     195    * @param image
     196    * @param zoom
     197    */
     198    public void setSelectedImage(MapillaryAbstractImage image, boolean zoom) {
     199        MapillaryAbstractImage oldImage = selectedImage;
     200        selectedImage = image;
     201        multiSelectedImages.clear();
     202        multiSelectedImages.add(image);
     203        if (image != null) {
     204            if (image instanceof MapillaryImage) {
     205                MapillaryImage mapillaryImage = (MapillaryImage) image;
     206                if (mapillaryImage.next() != null) {
     207                    new MapillaryCache(mapillaryImage.next().getKey(),
     208                            MapillaryCache.Type.THUMBNAIL).submit(this, false);
     209                    if (mapillaryImage.next().next() != null)
     210                        new MapillaryCache(mapillaryImage.next().next()
     211                                .getKey(), MapillaryCache.Type.THUMBNAIL)
     212                                .submit(this, false);
     213                }
     214                if (mapillaryImage.previous() != null) {
     215                    new MapillaryCache(mapillaryImage.previous().getKey(),
     216                            MapillaryCache.Type.THUMBNAIL).submit(this, false);
     217                    if (mapillaryImage.previous().previous() != null)
     218                        new MapillaryCache(mapillaryImage.previous().previous()
     219                                .getKey(), MapillaryCache.Type.THUMBNAIL)
     220                                .submit(this, false);
     221                }
     222            }
     223        }
     224        if (zoom)
     225            Main.map.mapView.zoomTo(MapillaryData.getInstance()
     226                    .getSelectedImage().getLatLon());
     227        if (Main.map != null) {
     228            Main.map.mapView.repaint();
     229        }
     230        fireSelectedImageChanged(oldImage, selectedImage);
     231    }
     232
     233    private void fireSelectedImageChanged(MapillaryAbstractImage oldImage,
     234            MapillaryAbstractImage newImage) {
     235        if (listeners.isEmpty())
     236            return;
     237        for (MapillaryDataListener lis : listeners)
     238            lis.selectedImageChanged(oldImage, newImage);
     239    }
     240
     241    /**
     242    * Adds a MapillaryImage object to the list of selected images, (when ctrl +
     243    * click)
     244    *
     245    * @param image
     246    *            The MapillaryImage object to be added.
     247    */
     248    public void addMultiSelectedImage(MapillaryAbstractImage image) {
     249        if (!this.multiSelectedImages.contains(image)) {
     250            if (this.getSelectedImage() != null)
     251                this.multiSelectedImages.add(image);
     252            else
     253                this.setSelectedImage(image);
     254        }
     255        Main.map.mapView.repaint();
     256    }
     257
     258    /**
     259    * Adds a set of MapillaryImage objects to the list of selected images.
     260    *
     261    * @param images
     262    */
     263    public void addMultiSelectedImage(List<MapillaryAbstractImage> images) {
     264        for (MapillaryAbstractImage image : images)
     265            if (!this.multiSelectedImages.contains(image)) {
     266                if (this.getSelectedImage() != null)
     267                    this.multiSelectedImages.add(image);
     268                else
     269                    this.setSelectedImage(image);
     270            }
     271        Main.map.mapView.repaint();
     272    }
     273
     274    /**
     275    * Returns a list containing all MapillaryImage objects selected with ctrl +
     276    * click
     277    *
     278    * @return
     279    */
     280    public List<MapillaryAbstractImage> getMultiSelectedImages() {
     281        return multiSelectedImages;
     282    }
     283
     284    /**
     285    * This is empty because it is used just to make sure that certain images
     286    * have already been downloaded.
     287    */
     288    @Override
     289    public void loadingFinished(CacheEntry data,
     290            CacheEntryAttributes attributes, LoadResult result) {
     291        // DO NOTHING
     292    }
    293293}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryDataListener.java

    r31266 r31278  
    22
    33public interface MapillaryDataListener {
    4         /**
    5          * Fired when the selected image is changed by something different from
    6          * manually clicking on the icon.
    7          */
    8         public void selectedImageChanged(MapillaryAbstractImage oldImage, MapillaryAbstractImage newImage);
     4    /**
     5     * Fired when the selected image is changed by something different from
     6     * manually clicking on the icon.
     7     */
     8    public void selectedImageChanged(MapillaryAbstractImage oldImage,
     9            MapillaryAbstractImage newImage);
    910
    1011}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImage.java

    r31277 r31278  
    1414 */
    1515public class MapillaryImage extends MapillaryAbstractImage {
    16         /** Unique identifier of the object */
    17         private final String key;
    18         /** Sequence of pictures containing this object*/
    19         private MapillarySequence sequence;
     16    /** Unique identifier of the object */
     17    private final String key;
     18    /** Sequence of pictures containing this object */
     19    private MapillarySequence sequence;
    2020
    21         private long capturedAt;
    22         private String user;
    23         private List<String> signs;
    24         private String location;
     21    /** Epoch time when the image was taken. */
     22    private long capturedAt;
     23    /** The user that made the image */
     24    private String user;
     25    /** Set of traffic signs in the image */
     26    private List<String> signs;
     27    private String location;
    2528
    26         public String getLocation() {
    27                 return location;
    28         }
     29    public String getLocation() {
     30        return location;
     31    }
    2932
    30         public void setLocation(String location) {
    31                 this.location = location;
    32         }
     33    public void setLocation(String location) {
     34        this.location = location;
     35    }
    3336
    34         /**
    35         * Main contructor of the class MapillaryImage
    36         *
    37         * @param key
    38         *            The unique identifier of the image.
    39         * @param lat
    40         *            The latitude where it is positioned.
    41         * @param lon
    42         *            The longitude where it is positioned.
    43         * @param ca
    44         *            The direction of the images in degrees, meaning 0 north.
    45         */
    46         public MapillaryImage(String key, double lat, double lon, double ca) {
    47                 super(lat, lon, ca);
    48                 this.key = key;
    49                 this.signs = new ArrayList<>();
    50         }
     37    /**
     38    * Main contructor of the class MapillaryImage
     39    *
     40    * @param key
     41    *            The unique identifier of the image.
     42    * @param lat
     43    *            The latitude where it is positioned.
     44    * @param lon
     45    *            The longitude where it is positioned.
     46    * @param ca
     47    *            The direction of the images in degrees, meaning 0 north.
     48    */
     49    public MapillaryImage(String key, double lat, double lon, double ca) {
     50        super(lat, lon, ca);
     51        this.key = key;
     52        this.signs = new ArrayList<>();
     53    }
    5154
    52         /**
    53          * Returns the unique identifier of the object.
    54          *
    55          * @return A String containing the unique identifier of the object.
    56          */
    57         public String getKey() {
    58                 return this.key;
    59         }
    60        
    61         public void addSign(String sign) {
    62                 signs.add(sign);
    63         }
    64        
    65         public List<String> getSigns() {
    66                 return signs;
    67         }
     55    /**
     56     * Returns the unique identifier of the object.
     57     *
     58     * @return A String containing the unique identifier of the object.
     59     */
     60    public String getKey() {
     61        return this.key;
     62    }
    6863
    69         public void setCapturedAt(long capturedAt) {
    70                 this.capturedAt = capturedAt;
    71         }
     64    /**
     65     * Adds a new sign to the set of signs.
     66     *
     67     * @param sign
     68     */
     69    public void addSign(String sign) {
     70        signs.add(sign);
     71    }
    7272
    73         public long getCapturedAt() {
    74                 return capturedAt;
    75         }
     73    public List<String> getSigns() {
     74        return signs;
     75    }
    7676
    77         public void setUser(String user) {
    78                 this.user = user;
    79         }
     77    public void setCapturedAt(long capturedAt) {
     78        this.capturedAt = capturedAt;
     79    }
    8080
    81         public String getUser() {
    82                 return user;
    83         }
     81    public long getCapturedAt() {
     82        return capturedAt;
     83    }
    8484
    85         /**
    86          * Sets the MapillarySequence object which contains the MapillaryImage.
    87          *
    88          * @param sequence
    89          *            The MapillarySequence that contains the MapillaryImage.
    90          */
    91         public void setSequence(MapillarySequence sequence) {
    92                 this.sequence = sequence;
    93         }
     85    public void setUser(String user) {
     86        this.user = user;
     87    }
    9488
    95         /**
    96          * Returns the sequence which contains this image.
    97          *
    98          * @return The MapillarySequence object that contains this MapillaryImage.
    99          */
    100         public MapillarySequence getSequence() {
    101                 return this.sequence;
    102         }
     89    public String getUser() {
     90        return user;
     91    }
    10392
    104         public String toString() {
    105                 return "Image[key=" + this.key + ";lat=" + this.latLon.lat() + ";lon="
    106                                 + this.latLon.lon() + ";ca=" + this.ca + "]";
    107         }
     93    /**
     94     * Sets the MapillarySequence object which contains the MapillaryImage.
     95     *
     96     * @param sequence
     97     *            The MapillarySequence that contains the MapillaryImage.
     98     */
     99    public void setSequence(MapillarySequence sequence) {
     100        this.sequence = sequence;
     101    }
    108102
    109         /**
    110          * If the MapillaryImage belongs to a MapillarySequence, returns the next
    111          * MapillarySequence in it.
    112          *
    113          * @return The following MapillaryImage, or null if there is none.
    114          */
    115         public MapillaryImage next() {
    116                 if (this.getSequence() == null)
    117                         return null;
    118                 return this.getSequence().next(this);
    119         }
     103    /**
     104     * Returns the sequence which contains this image.
     105     *
     106     * @return The MapillarySequence object that contains this MapillaryImage.
     107     */
     108    public MapillarySequence getSequence() {
     109        return this.sequence;
     110    }
    120111
    121         /**
    122          * If the MapillaryImage belongs to a MapillarySequence, returns the
    123          * previous MapillarySequence in it.
    124          *
    125          * @return The previous MapillaryImage, or null if there is none.
    126          */
    127         public MapillaryImage previous() {
    128                 if (this.getSequence() == null)
    129                         return null;
    130                 return this.getSequence().previous(this);
    131         }
    132        
    133         public String getDate() {
    134                 return getDate("dd/MM/yyyy - hh:mm:ss");
    135         }
    136        
    137         public String getDate(String format) {
    138                 Date date = new Date(getCapturedAt());
     112    public String toString() {
     113        return "Image[key=" + this.key + ";lat=" + this.latLon.lat() + ";lon="
     114                + this.latLon.lon() + ";ca=" + this.ca + "]";
     115    }
    139116
    140                 SimpleDateFormat formatter = new SimpleDateFormat(format);
    141                 return formatter.format(date);
    142         }
     117    /**
     118     * If the MapillaryImage belongs to a MapillarySequence, returns the next
     119     * MapillarySequence in it.
     120     *
     121     * @return The following MapillaryImage, or null if there is none.
     122     */
     123    public MapillaryImage next() {
     124        if (this.getSequence() == null)
     125            return null;
     126        return this.getSequence().next(this);
     127    }
    143128
    144         @Override
    145         public boolean equals(Object object) {
    146                 if (object instanceof MapillaryImage)
    147                         return this.key.equals(((MapillaryImage) object).getKey());
    148                 return false;
    149         }
     129    /**
     130     * If the MapillaryImage belongs to a MapillarySequence, returns the
     131     * previous MapillarySequence in it.
     132     *
     133     * @return The previous MapillaryImage, or null if there is none.
     134     */
     135    public MapillaryImage previous() {
     136        if (this.getSequence() == null)
     137            return null;
     138        return this.getSequence().previous(this);
     139    }
    150140
    151         @Override
    152         public int hashCode() {
    153                 return this.key.hashCode();
    154         }
     141    /**
     142     * Returns the date the picture was taken in DMY format.
     143     * @return
     144     */
     145    public String getDate() {
     146        return getDate("dd/MM/yyyy - hh:mm:ss");
     147    }
     148
     149    /**
     150     * Returns the date the picture was taken in the given format.
     151     * @param format
     152     * @return
     153     */
     154    public String getDate(String format) {
     155        Date date = new Date(getCapturedAt());
     156
     157        SimpleDateFormat formatter = new SimpleDateFormat(format);
     158        return formatter.format(date);
     159    }
     160
     161    @Override
     162    public boolean equals(Object object) {
     163        if (object instanceof MapillaryImage)
     164            return this.key.equals(((MapillaryImage) object).getKey());
     165        return false;
     166    }
     167
     168    @Override
     169    public int hashCode() {
     170        return this.key.hashCode();
     171    }
    155172}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImportedImage.java

    r31277 r31278  
    99public class MapillaryImportedImage extends MapillaryAbstractImage {
    1010
    11         /**
    12         * The picture file.
    13         */
    14         protected File file;
    15         public final String datetimeOriginal;
     11    /**
     12    * The picture file.
     13    */
     14    protected File file;
     15    public final String datetimeOriginal;
    1616
    17         public MapillaryImportedImage(double lat, double lon, double ca, File file, String datetimeOriginal) {
    18                 super(lat, lon, ca);
    19                 this.file = file;
    20                 System.out.println(datetimeOriginal);
    21                 this.datetimeOriginal = datetimeOriginal;
    22         }
     17    public MapillaryImportedImage(double lat, double lon, double ca, File file,
     18            String datetimeOriginal) {
     19        super(lat, lon, ca);
     20        this.file = file;
     21        System.out.println(datetimeOriginal);
     22        this.datetimeOriginal = datetimeOriginal;
     23    }
    2324
    24         /**
    25          * Returns the pictures of the file.
    26          *
    27          * @return
    28          * @throws IOException
    29          */
    30         public BufferedImage getImage() throws IOException {
    31                 return ImageIO.read(file);
    32         }
    33        
    34         public File getFile() {
    35                 return file;
    36         }
     25    /**
     26     * Returns the pictures of the file.
     27     *
     28     * @return
     29     * @throws IOException
     30     */
     31    public BufferedImage getImage() throws IOException {
     32        return ImageIO.read(file);
     33    }
    3734
    38         @Override
    39         public boolean equals(Object object) {
    40                 if (object instanceof MapillaryImportedImage)
    41                         return this.file.equals(((MapillaryImportedImage) object).file);
    42                 return false;
    43         }
     35    public File getFile() {
     36        return file;
     37    }
    4438
    45         @Override
    46         public int hashCode() {
    47                 return this.file.hashCode();
    48         }
     39    @Override
     40    public boolean equals(Object object) {
     41        if (object instanceof MapillaryImportedImage)
     42            return this.file.equals(((MapillaryImportedImage) object).file);
     43        return false;
     44    }
     45
     46    @Override
     47    public int hashCode() {
     48        return this.file.hashCode();
     49    }
    4950}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java

    r31277 r31278  
    5353
    5454public class MapillaryLayer extends AbstractModifiableLayer implements
    55                 DataSetListener, EditLayerChangeListener, LayerChangeListener {
    56 
    57         public final static int SEQUENCE_MAX_JUMP_DISTANCE = Main.pref.getInteger(
    58                         "mapillary.sequence-max-jump-distance", 100);
    59 
    60         public static MapillaryLayer INSTANCE;
    61         public static CacheAccess<String, BufferedImageCacheEntry> CACHE;
    62         public static MapillaryImage BLUE;
    63         public static MapillaryImage RED;
    64 
    65         private final MapillaryData mapillaryData = MapillaryData.getInstance();
    66 
    67         public List<Bounds> bounds;
    68 
    69         private MapillaryToggleDialog mtd;
    70         private MapillaryHistoryDialog mhd;
    71 
    72         private MouseAdapter mouseAdapter;
    73 
    74         int highlightPointRadius = Main.pref.getInteger(
    75                         "mappaint.highlight.radius", 7);
    76         private int highlightStep = Main.pref.getInteger("mappaint.highlight.step",
    77                         4);
    78 
    79         public MapillaryLayer() {
    80                 super(tr("Mapillary Images"));
    81                 bounds = new ArrayList<>();
    82                 init();
    83         }
    84 
    85         /**
    86          * Initializes the Layer.
    87          */
    88         private void init() {
    89                 MapillaryLayer.INSTANCE = this;
    90                 startMouseAdapter();
    91                 try {
    92                         CACHE = JCSCacheManager.getCache("Mapillary");
    93                 } catch (IOException e) {
    94                         Main.error(e);
    95                 }
    96                 if (Main.map != null && Main.map.mapView != null) {
    97                         Main.map.mapView.addMouseListener(mouseAdapter);
    98                         Main.map.mapView.addMouseMotionListener(mouseAdapter);
    99                         Main.map.mapView.addLayer(this);
    100                         MapView.addEditLayerChangeListener(this, false);
    101                         MapView.addLayerChangeListener(this);
    102                         Main.map.mapView.getEditLayer().data.addDataSetListener(this);
    103                         if (mtd == null) {
    104                                 if (MapillaryToggleDialog.INSTANCE == null) {
    105                                         mtd = MapillaryToggleDialog.getInstance();
    106                                         Main.map.addToggleDialog(mtd, false);
    107                                 } else
    108                                         mtd = MapillaryToggleDialog.getInstance();
    109                         }
    110                         if (mhd == null) {
    111                                 if (MapillaryHistoryDialog.INSTANCE == null) {
    112                                         mhd = MapillaryHistoryDialog.getInstance();
    113                                         Main.map.addToggleDialog(mhd, false);
    114                                 } else
    115                                         mhd = MapillaryHistoryDialog.getInstance();
    116                         }
    117                 }
    118                 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, true);
    119                 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.SIGN_MENU, true);
    120                 Main.map.mapView.setActiveLayer(this);
    121                 Main.map.repaint();
    122         }
    123 
    124         public void startMouseAdapter() {
    125                 mouseAdapter = new MapillaryMouseAdapter();
    126         }
    127 
    128         public synchronized static MapillaryLayer getInstance() {
    129                 if (MapillaryLayer.INSTANCE == null)
    130                         MapillaryLayer.INSTANCE = new MapillaryLayer();
    131                 return MapillaryLayer.INSTANCE;
    132         }
    133 
    134         /**
    135          * Downloads all images of the area covered by the OSM data. This is only
    136          * just for automatic download.
    137          */
    138         public void download() {
    139                 checkBigAreas();
    140                 if (Main.pref.getBoolean("mapillary.download-manually"))
    141                         return;
    142                 for (Bounds bounds : Main.map.mapView.getEditLayer().data
    143                                 .getDataSourceBounds()) {
    144                         if (!this.bounds.contains(bounds)) {
    145                                 this.bounds.add(bounds);
    146                                 new MapillaryDownloader().getImages(bounds.getMin(),
    147                                                 bounds.getMax());
    148                         }
    149                 }
    150         }
    151 
    152         private void checkBigAreas() {
    153                 double area = 0;
    154                 for (Bounds bounds : Main.map.mapView.getEditLayer().data
    155                                 .getDataSourceBounds()) {
    156                         area += bounds.getArea();
    157                 }
    158                 if (area > MapillaryDownloadViewAction.MAX_AREA) {
    159                         Main.pref.put("mapillary.download-manually", true);
    160                         JOptionPane
    161                                         .showMessageDialog(
    162                                                         Main.parent,
    163                                                         tr("The downloaded OSM area is too big. Download mode has been change to manual. You can change this back to automatic in preferences settings."));
    164                 }
    165         }
    166 
    167         /**
    168          * Returns the MapillaryData object, which acts as the database of the
    169          * Layer.
    170          *
    171          * @return
    172          */
    173         public MapillaryData getMapillaryData() {
    174                 return mapillaryData;
    175         }
    176 
    177         /**
    178          * Method invoked when the layer is destroyed.
    179          */
    180         @Override
    181         public void destroy() {
    182                 MapillaryToggleDialog.getInstance().mapillaryImageDisplay
    183                                 .setImage(null);
    184                 MapillaryData.getInstance().getImages().clear();
    185                 MapillaryLayer.INSTANCE = null;
    186                 MapillaryData.INSTANCE = null;
    187                 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, false);
    188                 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.SIGN_MENU, false);
    189                 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.ZOOM_MENU, false);
    190                 Main.map.mapView.removeMouseListener(mouseAdapter);
    191                 Main.map.mapView.removeMouseMotionListener(mouseAdapter);
    192                 MapView.removeEditLayerChangeListener(this);
    193                 if (Main.map.mapView.getEditLayer() != null)
    194                         Main.map.mapView.getEditLayer().data.removeDataSetListener(this);
    195                 super.destroy();
    196         }
    197 
    198         /**
    199          * Returns true any of the images from the database has been modified.
    200          */
    201         @Override
    202         public boolean isModified() {
    203                 for (MapillaryAbstractImage image : mapillaryData.getImages())
    204                         if (image.isModified())
    205                                 return true;
    206                 return false;
    207         }
    208 
    209         /**
    210          * Paints the database in the map.
    211          */
    212         @Override
    213         public void paint(Graphics2D g, MapView mv, Bounds box) {
    214                 synchronized (this) {
    215                         // Draw colored lines
    216                         MapillaryLayer.BLUE = null;
    217                         MapillaryLayer.RED = null;
    218                         MapillaryToggleDialog.getInstance().blueButton.setEnabled(false);
    219                         MapillaryToggleDialog.getInstance().redButton.setEnabled(false);
    220                         if (mapillaryData.getSelectedImage() != null) {
    221                                 MapillaryImage[] closestImages = getClosestImagesFromDifferentSequences();
    222                                 Point selected = mv.getPoint(mapillaryData.getSelectedImage()
    223                                                 .getLatLon());
    224                                 if (closestImages[0] != null) {
    225                                         MapillaryLayer.BLUE = closestImages[0];
    226                                         g.setColor(Color.BLUE);
    227                                         g.drawLine(mv.getPoint(closestImages[0].getLatLon()).x,
    228                                                         mv.getPoint(closestImages[0].getLatLon()).y,
    229                                                         selected.x, selected.y);
    230                                         MapillaryToggleDialog.getInstance().blueButton
    231                                                         .setEnabled(true);
    232                                 }
    233                                 if (closestImages[1] != null) {
    234                                         MapillaryLayer.RED = closestImages[1];
    235                                         g.setColor(Color.RED);
    236                                         g.drawLine(mv.getPoint(closestImages[1].getLatLon()).x,
    237                                                         mv.getPoint(closestImages[1].getLatLon()).y,
    238                                                         selected.x, selected.y);
    239                                         MapillaryToggleDialog.getInstance().redButton
    240                                                         .setEnabled(true);
    241                                 }
    242                         }
    243                         g.setColor(Color.WHITE);
    244                         for (MapillaryAbstractImage imageAbs : mapillaryData.getImages()) {
    245                                 Point p = mv.getPoint(imageAbs.getLatLon());
    246                                 if (imageAbs instanceof MapillaryImage) {
    247                                         MapillaryImage image = (MapillaryImage) imageAbs;
    248                                         Point nextp;
    249                                         if (image.getSequence() != null
    250                                                         && image.getSequence().next(image) != null) {
    251                                                 nextp = mv.getPoint(image.getSequence().next(image)
    252                                                                 .getLatLon());
    253                                                 g.drawLine(p.x, p.y, nextp.x, nextp.y);
    254                                         }
    255                                         ImageIcon icon;
    256                                         if (!mapillaryData.getMultiSelectedImages().contains(image))
    257                                                 icon = MapillaryPlugin.MAP_ICON;
    258                                         else
    259                                                 icon = MapillaryPlugin.MAP_ICON_SELECTED;
    260                                         draw(g, image, icon, p);
    261                                         if (!image.getSigns().isEmpty()) {
    262                                                 g.drawImage(MapillaryPlugin.MAP_SIGN.getImage(), p.x
    263                                                                 + icon.getIconWidth() / 2,
    264                                                                 p.y - icon.getIconHeight() / 2,
    265                                                                 Main.map.mapView);
    266                                         }
    267                                 } else if (imageAbs instanceof MapillaryImportedImage) {
    268                                         MapillaryImportedImage image = (MapillaryImportedImage) imageAbs;
    269                                         ImageIcon icon;
    270                                         if (!mapillaryData.getMultiSelectedImages().contains(image))
    271                                                 icon = MapillaryPlugin.MAP_ICON_IMPORTED;
    272                                         else
    273                                                 icon = MapillaryPlugin.MAP_ICON_SELECTED;
    274                                         draw(g, image, icon, p);
    275                                 }
    276                         }
    277                 }
    278         }
    279 
    280         /**
    281          * Draws the highlight of the icon.
    282          *
    283          * @param g
    284          * @param p
    285          * @param size
    286          */
    287         private void drawPointHighlight(Graphics2D g, Point p, int size) {
    288                 Color oldColor = g.getColor();
    289                 Color highlightColor = PaintColors.HIGHLIGHT.get();
    290                 Color highlightColorTransparent = new Color(highlightColor.getRed(),
    291                                 highlightColor.getGreen(), highlightColor.getBlue(), 100);
    292                 g.setColor(highlightColorTransparent);
    293                 int s = size + highlightPointRadius;
    294                 while (s >= size) {
    295                         int r = (int) Math.floor(s / 2d);
    296                         g.fillRoundRect(p.x - r, p.y - r, s, s, r, r);
    297                         s -= highlightStep;
    298                 }
    299                 g.setColor(oldColor);
    300         }
    301 
    302         /**
    303          * Draws the given icon of an image. Also checks if the mouse is over the
    304          * image.
    305          *
    306          * @param g
    307          * @param image
    308          * @param icon
    309          * @param p
    310          */
    311         private void draw(Graphics2D g, MapillaryAbstractImage image,
    312                         ImageIcon icon, Point p) {
    313                 Image imagetemp = icon.getImage();
    314                 BufferedImage bi = (BufferedImage) imagetemp;
    315                 int width = icon.getIconWidth();
    316                 int height = icon.getIconHeight();
    317 
    318                 // Rotate the image
    319                 double rotationRequired = Math.toRadians(image.getCa());
    320                 double locationX = width / 2;
    321                 double locationY = height / 2;
    322                 AffineTransform tx = AffineTransform.getRotateInstance(
    323                                 rotationRequired, locationX, locationY);
    324                 AffineTransformOp op = new AffineTransformOp(tx,
    325                                 AffineTransformOp.TYPE_BILINEAR);
    326 
    327                 g.drawImage(op.filter(bi, null), p.x - (width / 2), p.y - (height / 2),
    328                                 Main.map.mapView);
    329                 if (MapillaryData.getInstance().getHoveredImage() == image) {
    330                         drawPointHighlight(g, p, 16);
    331                 }
    332         }
    333 
    334         @Override
    335         public Icon getIcon() {
    336                 return MapillaryPlugin.ICON16;
    337         }
    338 
    339         @Override
    340         public boolean isMergable(Layer other) {
    341                 return false;
    342         }
    343 
    344         @Override
    345         public void mergeFrom(Layer from) {
    346                 throw new UnsupportedOperationException(
    347                                 "This layer does not support merging yet");
    348         }
    349 
    350         @Override
    351         public Action[] getMenuEntries() {
    352                 List<Action> actions = new ArrayList<>();
    353                 actions.add(LayerListDialog.getInstance().createShowHideLayerAction());
    354                 actions.add(LayerListDialog.getInstance().createDeleteLayerAction());
    355                 actions.add(new LayerListPopup.InfoAction(this));
    356                 return actions.toArray(new Action[actions.size()]);
    357         }
    358 
    359         private MapillaryImage[] getClosestImagesFromDifferentSequences() {
    360                 if (!(mapillaryData.getSelectedImage() instanceof MapillaryImage))
    361                         return new MapillaryImage[2];
    362                 MapillaryImage selected = (MapillaryImage) mapillaryData
    363                                 .getSelectedImage();
    364                 MapillaryImage[] ret = new MapillaryImage[2];
    365                 double[] distances = { SEQUENCE_MAX_JUMP_DISTANCE,
    366                                 SEQUENCE_MAX_JUMP_DISTANCE };
    367                 LatLon selectedCoords = mapillaryData.getSelectedImage().getLatLon();
    368                 for (MapillaryAbstractImage imagePrev : mapillaryData.getImages()) {
    369                         if (!(imagePrev instanceof MapillaryImage))
    370                                 continue;
    371                         MapillaryImage image = (MapillaryImage) imagePrev;
    372                         if (image.getLatLon().greatCircleDistance(selectedCoords) < SEQUENCE_MAX_JUMP_DISTANCE
    373                                         && selected.getSequence() != image.getSequence()) {
    374                                 if ((ret[0] == null && ret[1] == null)
    375                                                 || (image.getLatLon().greatCircleDistance(
    376                                                                 selectedCoords) < distances[0] && (ret[1] == null || image
    377                                                                 .getSequence() != ret[1].getSequence()))) {
    378                                         ret[0] = image;
    379                                         distances[0] = image.getLatLon().greatCircleDistance(
    380                                                         selectedCoords);
    381                                 } else if ((ret[1] == null || image.getLatLon()
    382                                                 .greatCircleDistance(selectedCoords) < distances[1])
    383                                                 && image.getSequence() != ret[0].getSequence()) {
    384                                         ret[1] = image;
    385                                         distances[1] = image.getLatLon().greatCircleDistance(
    386                                                         selectedCoords);
    387                                 }
    388                         }
    389                 }
    390                 // Predownloads the thumbnails
    391                 if (ret[0] != null)
    392                         new MapillaryCache(ret[0].getKey(), MapillaryCache.Type.THUMBNAIL)
    393                                         .submit(MapillaryData.getInstance(), false);
    394                 if (ret[1] != null)
    395                         new MapillaryCache(ret[1].getKey(), MapillaryCache.Type.THUMBNAIL)
    396                                         .submit(MapillaryData.getInstance(), false);
    397                 return ret;
    398         }
    399 
    400         @Override
    401         public Object getInfoComponent() {
    402                 StringBuilder sb = new StringBuilder();
    403                 sb.append(tr("Mapillary layer"));
    404                 sb.append("\n");
    405                 sb.append(tr("Total images:"));
    406                 sb.append(" ");
    407                 sb.append(this.size());
    408                 sb.append("\n");
    409                 return sb.toString();
    410         }
    411 
    412         @Override
    413         public String getToolTipText() {
    414                 return this.size() + " " + tr("images");
    415         }
    416 
    417         private int size() {
    418                 return mapillaryData.getImages().size();
    419         }
    420 
    421         // EditDataLayerChanged
    422         @Override
    423         public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
    424         }
    425 
    426         /**
    427          * When more data is downloaded, a delayed update is thrown, in order to
    428          * wait for the data bounds to be set.
    429          *
    430          * @param event
    431          */
    432         @Override
    433         public void dataChanged(DataChangedEvent event) {
    434                 Main.worker.submit(new delayedDownload());
    435         }
    436 
    437         private class delayedDownload extends Thread {
    438 
    439                 @Override
    440                 public void run() {
    441                         try {
    442                                 sleep(1000);
    443                         } catch (InterruptedException e) {
    444                                 Main.error(e);
    445                         }
    446                         MapillaryLayer.getInstance().download();
    447                 }
    448         }
    449 
    450         @Override
    451         public void primitivesAdded(PrimitivesAddedEvent event) {
    452         }
    453 
    454         @Override
    455         public void primitivesRemoved(PrimitivesRemovedEvent event) {
    456         }
    457 
    458         @Override
    459         public void tagsChanged(TagsChangedEvent event) {
    460         }
    461 
    462         @Override
    463         public void nodeMoved(NodeMovedEvent event) {
    464         }
    465 
    466         @Override
    467         public void wayNodesChanged(WayNodesChangedEvent event) {
    468         }
    469 
    470         @Override
    471         public void relationMembersChanged(RelationMembersChangedEvent event) {
    472         }
    473 
    474         @Override
    475         public void otherDatasetChange(AbstractDatasetChangedEvent event) {
    476         }
    477 
    478         @Override
    479         public void visitBoundingBox(BoundingXYVisitor v) {
    480         }
    481 
    482         @Override
    483         public void activeLayerChange(Layer oldLayer, Layer newLayer) {
    484                 if (newLayer == this) {
    485                         if (MapillaryData.getInstance().getImages().size() > 0)
    486                                 Main.map.statusLine.setHelpText(tr("Total images: {0}",
    487                                                 MapillaryData.getInstance().getImages().size()));
    488                         else
    489                                 Main.map.statusLine.setHelpText(tr("No images found"));
    490                 }
    491         }
    492 
    493         @Override
    494         public void layerAdded(Layer newLayer) {
    495         }
    496 
    497         @Override
    498         public void layerRemoved(Layer oldLayer) {
    499         }
     55        DataSetListener, EditLayerChangeListener, LayerChangeListener {
     56
     57    public final static int SEQUENCE_MAX_JUMP_DISTANCE = Main.pref.getInteger(
     58            "mapillary.sequence-max-jump-distance", 100);
     59
     60    public static MapillaryLayer INSTANCE;
     61    public static CacheAccess<String, BufferedImageCacheEntry> CACHE;
     62    public static MapillaryImage BLUE;
     63    public static MapillaryImage RED;
     64
     65    private final MapillaryData mapillaryData = MapillaryData.getInstance();
     66
     67    public List<Bounds> bounds;
     68
     69    private MapillaryToggleDialog mtd;
     70    private MapillaryHistoryDialog mhd;
     71
     72    private MouseAdapter mouseAdapter;
     73
     74    int highlightPointRadius = Main.pref.getInteger(
     75            "mappaint.highlight.radius", 7);
     76    private int highlightStep = Main.pref.getInteger("mappaint.highlight.step",
     77            4);
     78
     79    public MapillaryLayer() {
     80        super(tr("Mapillary Images"));
     81        bounds = new ArrayList<>();
     82        init();
     83    }
     84
     85    /**
     86     * Initializes the Layer.
     87     */
     88    private void init() {
     89        MapillaryLayer.INSTANCE = this;
     90        startMouseAdapter();
     91        try {
     92            CACHE = JCSCacheManager.getCache("Mapillary");
     93        } catch (IOException e) {
     94            Main.error(e);
     95        }
     96        if (Main.map != null && Main.map.mapView != null) {
     97            Main.map.mapView.addMouseListener(mouseAdapter);
     98            Main.map.mapView.addMouseMotionListener(mouseAdapter);
     99            Main.map.mapView.addLayer(this);
     100            MapView.addEditLayerChangeListener(this, false);
     101            MapView.addLayerChangeListener(this);
     102            Main.map.mapView.getEditLayer().data.addDataSetListener(this);
     103            if (mtd == null) {
     104                if (MapillaryToggleDialog.INSTANCE == null) {
     105                    mtd = MapillaryToggleDialog.getInstance();
     106                    Main.map.addToggleDialog(mtd, false);
     107                } else
     108                    mtd = MapillaryToggleDialog.getInstance();
     109            }
     110            if (mhd == null) {
     111                if (MapillaryHistoryDialog.INSTANCE == null) {
     112                    mhd = MapillaryHistoryDialog.getInstance();
     113                    Main.map.addToggleDialog(mhd, false);
     114                } else
     115                    mhd = MapillaryHistoryDialog.getInstance();
     116            }
     117        }
     118        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, true);
     119        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.SIGN_MENU, true);
     120        Main.map.mapView.setActiveLayer(this);
     121        Main.map.repaint();
     122    }
     123
     124    public void startMouseAdapter() {
     125        mouseAdapter = new MapillaryMouseAdapter();
     126    }
     127
     128    public synchronized static MapillaryLayer getInstance() {
     129        if (MapillaryLayer.INSTANCE == null)
     130            MapillaryLayer.INSTANCE = new MapillaryLayer();
     131        return MapillaryLayer.INSTANCE;
     132    }
     133
     134    /**
     135     * Downloads all images of the area covered by the OSM data. This is only
     136     * just for automatic download.
     137     */
     138    public void download() {
     139        checkBigAreas();
     140        if (Main.pref.getBoolean("mapillary.download-manually"))
     141            return;
     142        for (Bounds bounds : Main.map.mapView.getEditLayer().data
     143                .getDataSourceBounds()) {
     144            if (!this.bounds.contains(bounds)) {
     145                this.bounds.add(bounds);
     146                new MapillaryDownloader().getImages(bounds.getMin(),
     147                        bounds.getMax());
     148            }
     149        }
     150    }
     151
     152    /**
     153     * Checks if the area of the OSM data is too big. This means that probably
     154     * lots of Mapillary images are going to be downloaded, slowing down the
     155     * program too much. To solve this the automatic is stopped, an alert is
     156     * shown and you will have to download areas manually.
     157     */
     158    private void checkBigAreas() {
     159        double area = 0;
     160        for (Bounds bounds : Main.map.mapView.getEditLayer().data
     161                .getDataSourceBounds()) {
     162            area += bounds.getArea();
     163        }
     164        if (area > MapillaryDownloadViewAction.MAX_AREA) {
     165            Main.pref.put("mapillary.download-manually", true);
     166            JOptionPane
     167                    .showMessageDialog(
     168                            Main.parent,
     169                            tr("The downloaded OSM area is too big. Download mode has been change to manual. You can change this back to automatic in preferences settings."));
     170        }
     171    }
     172
     173    /**
     174     * Returns the MapillaryData object, which acts as the database of the
     175     * Layer.
     176     *
     177     * @return
     178     */
     179    public MapillaryData getMapillaryData() {
     180        return mapillaryData;
     181    }
     182
     183    /**
     184     * Method invoked when the layer is destroyed.
     185     */
     186    @Override
     187    public void destroy() {
     188        MapillaryToggleDialog.getInstance().mapillaryImageDisplay
     189                .setImage(null);
     190        MapillaryData.getInstance().getImages().clear();
     191        MapillaryLayer.INSTANCE = null;
     192        MapillaryData.INSTANCE = null;
     193        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, false);
     194        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.SIGN_MENU, false);
     195        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.ZOOM_MENU, false);
     196        Main.map.mapView.removeMouseListener(mouseAdapter);
     197        Main.map.mapView.removeMouseMotionListener(mouseAdapter);
     198        MapView.removeEditLayerChangeListener(this);
     199        if (Main.map.mapView.getEditLayer() != null)
     200            Main.map.mapView.getEditLayer().data.removeDataSetListener(this);
     201        super.destroy();
     202    }
     203
     204    /**
     205     * Returns true any of the images from the database has been modified.
     206     */
     207    @Override
     208    public boolean isModified() {
     209        for (MapillaryAbstractImage image : mapillaryData.getImages())
     210            if (image.isModified())
     211                return true;
     212        return false;
     213    }
     214
     215    /**
     216     * Paints the database in the map.
     217     */
     218    @Override
     219    public void paint(Graphics2D g, MapView mv, Bounds box) {
     220        synchronized (this) {
     221            // Draw colored lines
     222            MapillaryLayer.BLUE = null;
     223            MapillaryLayer.RED = null;
     224            MapillaryToggleDialog.getInstance().blueButton.setEnabled(false);
     225            MapillaryToggleDialog.getInstance().redButton.setEnabled(false);
     226            if (mapillaryData.getSelectedImage() != null) {
     227                MapillaryImage[] closestImages = getClosestImagesFromDifferentSequences();
     228                Point selected = mv.getPoint(mapillaryData.getSelectedImage()
     229                        .getLatLon());
     230                if (closestImages[0] != null) {
     231                    MapillaryLayer.BLUE = closestImages[0];
     232                    g.setColor(Color.BLUE);
     233                    g.drawLine(mv.getPoint(closestImages[0].getLatLon()).x,
     234                            mv.getPoint(closestImages[0].getLatLon()).y,
     235                            selected.x, selected.y);
     236                    MapillaryToggleDialog.getInstance().blueButton
     237                            .setEnabled(true);
     238                }
     239                if (closestImages[1] != null) {
     240                    MapillaryLayer.RED = closestImages[1];
     241                    g.setColor(Color.RED);
     242                    g.drawLine(mv.getPoint(closestImages[1].getLatLon()).x,
     243                            mv.getPoint(closestImages[1].getLatLon()).y,
     244                            selected.x, selected.y);
     245                    MapillaryToggleDialog.getInstance().redButton
     246                            .setEnabled(true);
     247                }
     248            }
     249            g.setColor(Color.WHITE);
     250            for (MapillaryAbstractImage imageAbs : mapillaryData.getImages()) {
     251                Point p = mv.getPoint(imageAbs.getLatLon());
     252                if (imageAbs instanceof MapillaryImage) {
     253                    MapillaryImage image = (MapillaryImage) imageAbs;
     254                    Point nextp;
     255                    if (image.getSequence() != null
     256                            && image.getSequence().next(image) != null) {
     257                        nextp = mv.getPoint(image.getSequence().next(image)
     258                                .getLatLon());
     259                        g.drawLine(p.x, p.y, nextp.x, nextp.y);
     260                    }
     261                    ImageIcon icon;
     262                    if (!mapillaryData.getMultiSelectedImages().contains(image))
     263                        icon = MapillaryPlugin.MAP_ICON;
     264                    else
     265                        icon = MapillaryPlugin.MAP_ICON_SELECTED;
     266                    draw(g, image, icon, p);
     267                    if (!image.getSigns().isEmpty()) {
     268                        g.drawImage(MapillaryPlugin.MAP_SIGN.getImage(), p.x
     269                                + icon.getIconWidth() / 2,
     270                                p.y - icon.getIconHeight() / 2,
     271                                Main.map.mapView);
     272                    }
     273                } else if (imageAbs instanceof MapillaryImportedImage) {
     274                    MapillaryImportedImage image = (MapillaryImportedImage) imageAbs;
     275                    ImageIcon icon;
     276                    if (!mapillaryData.getMultiSelectedImages().contains(image))
     277                        icon = MapillaryPlugin.MAP_ICON_IMPORTED;
     278                    else
     279                        icon = MapillaryPlugin.MAP_ICON_SELECTED;
     280                    draw(g, image, icon, p);
     281                }
     282            }
     283        }
     284    }
     285
     286    /**
     287     * Draws the highlight of the icon.
     288     *
     289     * @param g
     290     * @param p
     291     * @param size
     292     */
     293    private void drawPointHighlight(Graphics2D g, Point p, int size) {
     294        Color oldColor = g.getColor();
     295        Color highlightColor = PaintColors.HIGHLIGHT.get();
     296        Color highlightColorTransparent = new Color(highlightColor.getRed(),
     297                highlightColor.getGreen(), highlightColor.getBlue(), 100);
     298        g.setColor(highlightColorTransparent);
     299        int s = size + highlightPointRadius;
     300        while (s >= size) {
     301            int r = (int) Math.floor(s / 2d);
     302            g.fillRoundRect(p.x - r, p.y - r, s, s, r, r);
     303            s -= highlightStep;
     304        }
     305        g.setColor(oldColor);
     306    }
     307
     308    /**
     309     * Draws the given icon of an image. Also checks if the mouse is over the
     310     * image.
     311     *
     312     * @param g
     313     * @param image
     314     * @param icon
     315     * @param p
     316     */
     317    private void draw(Graphics2D g, MapillaryAbstractImage image,
     318            ImageIcon icon, Point p) {
     319        Image imagetemp = icon.getImage();
     320        BufferedImage bi = (BufferedImage) imagetemp;
     321        int width = icon.getIconWidth();
     322        int height = icon.getIconHeight();
     323
     324        // Rotate the image
     325        double rotationRequired = Math.toRadians(image.getCa());
     326        double locationX = width / 2;
     327        double locationY = height / 2;
     328        AffineTransform tx = AffineTransform.getRotateInstance(
     329                rotationRequired, locationX, locationY);
     330        AffineTransformOp op = new AffineTransformOp(tx,
     331                AffineTransformOp.TYPE_BILINEAR);
     332
     333        g.drawImage(op.filter(bi, null), p.x - (width / 2), p.y - (height / 2),
     334                Main.map.mapView);
     335        if (MapillaryData.getInstance().getHoveredImage() == image) {
     336            drawPointHighlight(g, p, 16);
     337        }
     338    }
     339
     340    @Override
     341    public Icon getIcon() {
     342        return MapillaryPlugin.ICON16;
     343    }
     344
     345    @Override
     346    public boolean isMergable(Layer other) {
     347        return false;
     348    }
     349
     350    @Override
     351    public void mergeFrom(Layer from) {
     352        throw new UnsupportedOperationException(
     353                "This layer does not support merging yet");
     354    }
     355
     356    @Override
     357    public Action[] getMenuEntries() {
     358        List<Action> actions = new ArrayList<>();
     359        actions.add(LayerListDialog.getInstance().createShowHideLayerAction());
     360        actions.add(LayerListDialog.getInstance().createDeleteLayerAction());
     361        actions.add(new LayerListPopup.InfoAction(this));
     362        return actions.toArray(new Action[actions.size()]);
     363    }
     364
     365    private MapillaryImage[] getClosestImagesFromDifferentSequences() {
     366        if (!(mapillaryData.getSelectedImage() instanceof MapillaryImage))
     367            return new MapillaryImage[2];
     368        MapillaryImage selected = (MapillaryImage) mapillaryData
     369                .getSelectedImage();
     370        MapillaryImage[] ret = new MapillaryImage[2];
     371        double[] distances = { SEQUENCE_MAX_JUMP_DISTANCE,
     372                SEQUENCE_MAX_JUMP_DISTANCE };
     373        LatLon selectedCoords = mapillaryData.getSelectedImage().getLatLon();
     374        for (MapillaryAbstractImage imagePrev : mapillaryData.getImages()) {
     375            if (!(imagePrev instanceof MapillaryImage))
     376                continue;
     377            MapillaryImage image = (MapillaryImage) imagePrev;
     378            if (image.getLatLon().greatCircleDistance(selectedCoords) < SEQUENCE_MAX_JUMP_DISTANCE
     379                    && selected.getSequence() != image.getSequence()) {
     380                if ((ret[0] == null && ret[1] == null)
     381                        || (image.getLatLon().greatCircleDistance(
     382                                selectedCoords) < distances[0] && (ret[1] == null || image
     383                                .getSequence() != ret[1].getSequence()))) {
     384                    ret[0] = image;
     385                    distances[0] = image.getLatLon().greatCircleDistance(
     386                            selectedCoords);
     387                } else if ((ret[1] == null || image.getLatLon()
     388                        .greatCircleDistance(selectedCoords) < distances[1])
     389                        && image.getSequence() != ret[0].getSequence()) {
     390                    ret[1] = image;
     391                    distances[1] = image.getLatLon().greatCircleDistance(
     392                            selectedCoords);
     393                }
     394            }
     395        }
     396        // Predownloads the thumbnails
     397        if (ret[0] != null)
     398            new MapillaryCache(ret[0].getKey(), MapillaryCache.Type.THUMBNAIL)
     399                    .submit(MapillaryData.getInstance(), false);
     400        if (ret[1] != null)
     401            new MapillaryCache(ret[1].getKey(), MapillaryCache.Type.THUMBNAIL)
     402                    .submit(MapillaryData.getInstance(), false);
     403        return ret;
     404    }
     405
     406    @Override
     407    public Object getInfoComponent() {
     408        StringBuilder sb = new StringBuilder();
     409        sb.append(tr("Mapillary layer"));
     410        sb.append("\n");
     411        sb.append(tr("Total images:"));
     412        sb.append(" ");
     413        sb.append(this.size());
     414        sb.append("\n");
     415        return sb.toString();
     416    }
     417
     418    @Override
     419    public String getToolTipText() {
     420        return this.size() + " " + tr("images");
     421    }
     422
     423    private int size() {
     424        return mapillaryData.getImages().size();
     425    }
     426
     427    // EditDataLayerChanged
     428    @Override
     429    public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
     430    }
     431
     432    /**
     433     * When more data is downloaded, a delayed update is thrown, in order to
     434     * wait for the data bounds to be set.
     435     *
     436     * @param event
     437     */
     438    @Override
     439    public void dataChanged(DataChangedEvent event) {
     440        Main.worker.submit(new delayedDownload());
     441    }
     442
     443    private class delayedDownload extends Thread {
     444
     445        @Override
     446        public void run() {
     447            try {
     448                sleep(1000);
     449            } catch (InterruptedException e) {
     450                Main.error(e);
     451            }
     452            MapillaryLayer.getInstance().download();
     453        }
     454    }
     455
     456    @Override
     457    public void primitivesAdded(PrimitivesAddedEvent event) {
     458    }
     459
     460    @Override
     461    public void primitivesRemoved(PrimitivesRemovedEvent event) {
     462    }
     463
     464    @Override
     465    public void tagsChanged(TagsChangedEvent event) {
     466    }
     467
     468    @Override
     469    public void nodeMoved(NodeMovedEvent event) {
     470    }
     471
     472    @Override
     473    public void wayNodesChanged(WayNodesChangedEvent event) {
     474    }
     475
     476    @Override
     477    public void relationMembersChanged(RelationMembersChangedEvent event) {
     478    }
     479
     480    @Override
     481    public void otherDatasetChange(AbstractDatasetChangedEvent event) {
     482    }
     483
     484    @Override
     485    public void visitBoundingBox(BoundingXYVisitor v) {
     486    }
     487
     488    @Override
     489    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
     490        if (newLayer == this) {
     491            if (MapillaryData.getInstance().getImages().size() > 0)
     492                Main.map.statusLine.setHelpText(tr("Total images: {0}",
     493                        MapillaryData.getInstance().getImages().size()));
     494            else
     495                Main.map.statusLine.setHelpText(tr("No images found"));
     496        }
     497    }
     498
     499    @Override
     500    public void layerAdded(Layer newLayer) {
     501    }
     502
     503    @Override
     504    public void layerRemoved(Layer oldLayer) {
     505    }
    500506}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryMouseAdapter.java

    r31277 r31278  
    2222 */
    2323public class MapillaryMouseAdapter extends MouseAdapter {
    24         private Point start;
    25         private int lastButton;
    26         private MapillaryAbstractImage closest;
    27         private MapillaryAbstractImage lastClicked;
    28         private MapillaryData mapillaryData;
    29         private MapillaryRecord record;
    30 
    31         private boolean nothingHighlighted;
    32 
    33         public MapillaryMouseAdapter() {
    34                 mapillaryData = MapillaryData.getInstance();
    35                 record = MapillaryRecord.getInstance();
    36         }
    37 
    38         @Override
    39         public void mousePressed(MouseEvent e) {
    40                 lastButton = e.getButton();
    41                 if (e.getButton() != MouseEvent.BUTTON1)
    42                         return;
    43                 MapillaryAbstractImage closestTemp = getClosest(e.getPoint());
    44                 if (Main.map.mapView.getActiveLayer() instanceof OsmDataLayer
    45                                 && closestTemp != null) {
    46                         this.lastClicked = this.closest;
    47                         MapillaryData.getInstance().setSelectedImage(closestTemp);
    48                         return;
    49                 } else if (Main.map.mapView.getActiveLayer() != MapillaryLayer
    50                                 .getInstance())
    51                         return;
    52                 if (closestTemp instanceof MapillaryImage || closestTemp == null) {
    53                         MapillaryImage closest = (MapillaryImage) closestTemp;
    54                         // Doube click
    55                         if (e.getClickCount() == 2
    56                                         && mapillaryData.getSelectedImage() != null
    57                                         && closest != null) {
    58                                 for (MapillaryAbstractImage img : closest.getSequence()
    59                                                 .getImages()) {
    60                                         mapillaryData.addMultiSelectedImage(img);
    61                                 }
    62                         }
    63                         this.start = e.getPoint();
    64                         this.lastClicked = this.closest;
    65                         this.closest = closest;
    66                         if (mapillaryData.getMultiSelectedImages().contains(closest))
    67                                 return;
    68                         // ctrl+click
    69                         if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.CTRL_MASK)
    70                                         && closest != null)
    71                                 mapillaryData.addMultiSelectedImage(closest);
    72                         // shift + click
    73                         else if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.SHIFT_MASK)
    74                                         && this.closest instanceof MapillaryImage
    75                                         && this.lastClicked instanceof MapillaryImage) {
    76                                 if (this.closest != null
    77                                                 && this.lastClicked != null
    78                                                 && ((MapillaryImage) this.closest).getSequence() == ((MapillaryImage) this.lastClicked)
    79                                                                 .getSequence()) {
    80                                         int i = ((MapillaryImage) this.closest).getSequence()
    81                                                         .getImages().indexOf(this.closest);
    82                                         int j = ((MapillaryImage) this.lastClicked).getSequence()
    83                                                         .getImages().indexOf(this.lastClicked);
    84                                         if (i < j)
    85                                                 mapillaryData
    86                                                                 .addMultiSelectedImage(new ArrayList<MapillaryAbstractImage>(
    87                                                                                 ((MapillaryImage) this.closest)
    88                                                                                                 .getSequence().getImages()
    89                                                                                                 .subList(i, j + 1)));
    90                                         else
    91                                                 mapillaryData
    92                                                                 .addMultiSelectedImage(new ArrayList<MapillaryAbstractImage>(
    93                                                                                 ((MapillaryImage) this.closest)
    94                                                                                                 .getSequence().getImages()
    95                                                                                                 .subList(j, i + 1)));
    96                                 }
    97                                 // click
    98                         } else
    99                                 mapillaryData.setSelectedImage(closest);
    100                         // If you select an imported image
    101                 } else if (closestTemp instanceof MapillaryImportedImage) {
    102                         MapillaryImportedImage closest = (MapillaryImportedImage) closestTemp;
    103                         this.start = e.getPoint();
    104                         this.lastClicked = this.closest;
    105                         this.closest = closest;
    106                         if (mapillaryData.getMultiSelectedImages().contains(closest))
    107                                 return;
    108                         if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.CTRL_MASK)
    109                                         && closest != null)
    110                                 mapillaryData.addMultiSelectedImage(closest);
    111                         else
    112                                 mapillaryData.setSelectedImage(closest);
    113                 }
    114         }
    115 
    116         private MapillaryAbstractImage getClosest(Point clickPoint) {
    117                 double snapDistance = 10;
    118                 double minDistance = Double.MAX_VALUE;
    119                 MapillaryAbstractImage closest = null;
    120                 for (MapillaryAbstractImage image : mapillaryData.getImages()) {
    121                         Point imagePoint = Main.map.mapView.getPoint(image.getLatLon());
    122                         imagePoint.setLocation(imagePoint.getX(), imagePoint.getY());
    123                         double dist = clickPoint.distanceSq(imagePoint);
    124                         if (minDistance > dist
    125                                         && clickPoint.distance(imagePoint) < snapDistance) {
    126                                 minDistance = dist;
    127                                 closest = image;
    128                         }
    129                 }
    130                 return closest;
    131         }
    132 
    133         @Override
    134         public void mouseDragged(MouseEvent e) {
    135                 if (Main.map.mapView.getActiveLayer() != MapillaryLayer.getInstance())
    136                         return;
    137 
    138                 if (!Main.pref.getBoolean("mapillary.developer"))
    139                         for (MapillaryAbstractImage img : MapillaryData.getInstance()
    140                                         .getMultiSelectedImages()) {
    141                                 if (img instanceof MapillaryImage)
    142                                         return;
    143                         }
    144                 if (MapillaryData.getInstance().getSelectedImage() != null) {
    145                         if (lastButton == MouseEvent.BUTTON1 && !e.isShiftDown()) {
    146                                 LatLon to = Main.map.mapView.getLatLon(e.getX(), e.getY());
    147                                 LatLon from = Main.map.mapView.getLatLon(start.getX(),
    148                                                 start.getY());
    149                                 for (MapillaryAbstractImage img : MapillaryData.getInstance()
    150                                                 .getMultiSelectedImages()) {
    151 
    152                                         img.move(to.getX() - from.getX(), to.getY() - from.getY());
    153                                 }
    154                                 Main.map.repaint();
    155                         } else if (lastButton == MouseEvent.BUTTON1 && e.isShiftDown()) {
    156                                 this.closest.turn(Math.toDegrees(Math.atan2(
    157                                                 (e.getX() - start.x), -(e.getY() - start.y)))
    158                                                 - closest.getTempCa());
    159                                 for (MapillaryAbstractImage img : MapillaryData.getInstance()
    160                                                 .getMultiSelectedImages()) {
    161                                         img.turn(Math.toDegrees(Math.atan2((e.getX() - start.x),
    162                                                         -(e.getY() - start.y))) - closest.getTempCa());
    163                                 }
    164                                 Main.map.repaint();
    165                         }
    166                 }
    167         }
    168 
    169         @Override
    170         public void mouseReleased(MouseEvent e) {
    171                 if (mapillaryData.getSelectedImage() == null)
    172                         return;
    173                 if (mapillaryData.getSelectedImage().getTempCa() != mapillaryData
    174                                 .getSelectedImage().getCa()) {
    175                         double from = mapillaryData.getSelectedImage().getTempCa();
    176                         double to = mapillaryData.getSelectedImage().getCa();
    177                         record.addCommand(new CommandTurnImage(mapillaryData
    178                                         .getMultiSelectedImages(), to - from));
    179                 } else if (mapillaryData.getSelectedImage().getTempLatLon() != mapillaryData
    180                                 .getSelectedImage().getLatLon()) {
    181                         LatLon from = mapillaryData.getSelectedImage().getTempLatLon();
    182                         LatLon to = mapillaryData.getSelectedImage().getLatLon();
    183                         record.addCommand(new CommandMoveImage(mapillaryData
    184                                         .getMultiSelectedImages(), to.getX() - from.getX(), to
    185                                         .getY() - from.getY()));
    186                 }
    187                 for (MapillaryAbstractImage img : mapillaryData
    188                                 .getMultiSelectedImages()) {
    189                         if (img != null)
    190                                 img.stopMoving();
    191                 }
    192         }
    193 
    194         /**
    195         * Checks if the mouse is over pictures.
    196         */
    197         @Override
    198         public void mouseMoved(MouseEvent e) {
    199                 MapillaryAbstractImage closestTemp = getClosest(e.getPoint());
    200 
    201                 if (closestTemp != null
    202                                 && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer
    203                                 && Main.map.mapModeSelect.getValue("active") == Boolean.TRUE) {
    204                         Main.map.mapModeSelect.exitMode();
    205                 } else if (closestTemp == null
    206                                 && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer
    207                                 && Main.map.mapModeSelect.getValue("active") == Boolean.FALSE) {
    208                         Main.map.mapModeSelect.enterMode();
    209                         nothingHighlighted = false;
    210                 } else if (Main.map.mapModeSelect.getValue("active") == Boolean.FALSE
    211                                 && !nothingHighlighted) {
    212                         for (OsmPrimitive primivitive : Main.map.mapView.getEditLayer().data
    213                                         .allPrimitives()) {
    214                                 primivitive.setHighlighted(false);
    215                         }
    216                         nothingHighlighted = true;
    217                 }
    218 
    219                 // TODO check if it is possible to do this while the OSM data layer is
    220                 // selected.
    221                 if (MapillaryData.getInstance().getHoveredImage() != closestTemp
    222                                 && closestTemp != null) {
    223                         MapillaryData.getInstance().setHoveredImage(closestTemp);
    224                         MapillaryToggleDialog.getInstance().setImage(closestTemp);
    225                         MapillaryToggleDialog.getInstance().updateImage();
    226                 } else if (MapillaryData.getInstance().getHoveredImage() != closestTemp
    227                                 && closestTemp == null) {
    228                         MapillaryData.getInstance().setHoveredImage(null);
    229                         MapillaryToggleDialog.getInstance().setImage(
    230                                         MapillaryData.getInstance().getSelectedImage());
    231                         MapillaryToggleDialog.getInstance().updateImage();
    232                 }
    233                 MapillaryData.getInstance().dataUpdated();
    234         }
     24    private Point start;
     25    private int lastButton;
     26    private MapillaryAbstractImage closest;
     27    private MapillaryAbstractImage lastClicked;
     28    private MapillaryData mapillaryData;
     29    private MapillaryRecord record;
     30
     31    private boolean nothingHighlighted;
     32
     33    public MapillaryMouseAdapter() {
     34        mapillaryData = MapillaryData.getInstance();
     35        record = MapillaryRecord.getInstance();
     36    }
     37
     38    @Override
     39    public void mousePressed(MouseEvent e) {
     40        lastButton = e.getButton();
     41        if (e.getButton() != MouseEvent.BUTTON1)
     42            return;
     43        MapillaryAbstractImage closestTemp = getClosest(e.getPoint());
     44        if (Main.map.mapView.getActiveLayer() instanceof OsmDataLayer
     45                && closestTemp != null) {
     46            this.lastClicked = this.closest;
     47            MapillaryData.getInstance().setSelectedImage(closestTemp);
     48            return;
     49        } else if (Main.map.mapView.getActiveLayer() != MapillaryLayer
     50                .getInstance())
     51            return;
     52        if (closestTemp instanceof MapillaryImage || closestTemp == null) {
     53            MapillaryImage closest = (MapillaryImage) closestTemp;
     54            // Doube click
     55            if (e.getClickCount() == 2
     56                    && mapillaryData.getSelectedImage() != null
     57                    && closest != null) {
     58                for (MapillaryAbstractImage img : closest.getSequence()
     59                        .getImages()) {
     60                    mapillaryData.addMultiSelectedImage(img);
     61                }
     62            }
     63            this.start = e.getPoint();
     64            this.lastClicked = this.closest;
     65            this.closest = closest;
     66            if (mapillaryData.getMultiSelectedImages().contains(closest))
     67                return;
     68            // ctrl+click
     69            if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.CTRL_MASK)
     70                    && closest != null)
     71                mapillaryData.addMultiSelectedImage(closest);
     72            // shift + click
     73            else if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.SHIFT_MASK)
     74                    && this.closest instanceof MapillaryImage
     75                    && this.lastClicked instanceof MapillaryImage) {
     76                if (this.closest != null
     77                        && this.lastClicked != null
     78                        && ((MapillaryImage) this.closest).getSequence() == ((MapillaryImage) this.lastClicked)
     79                                .getSequence()) {
     80                    int i = ((MapillaryImage) this.closest).getSequence()
     81                            .getImages().indexOf(this.closest);
     82                    int j = ((MapillaryImage) this.lastClicked).getSequence()
     83                            .getImages().indexOf(this.lastClicked);
     84                    if (i < j)
     85                        mapillaryData
     86                                .addMultiSelectedImage(new ArrayList<MapillaryAbstractImage>(
     87                                        ((MapillaryImage) this.closest)
     88                                                .getSequence().getImages()
     89                                                .subList(i, j + 1)));
     90                    else
     91                        mapillaryData
     92                                .addMultiSelectedImage(new ArrayList<MapillaryAbstractImage>(
     93                                        ((MapillaryImage) this.closest)
     94                                                .getSequence().getImages()
     95                                                .subList(j, i + 1)));
     96                }
     97                // click
     98            } else
     99                mapillaryData.setSelectedImage(closest);
     100            // If you select an imported image
     101        } else if (closestTemp instanceof MapillaryImportedImage) {
     102            MapillaryImportedImage closest = (MapillaryImportedImage) closestTemp;
     103            this.start = e.getPoint();
     104            this.lastClicked = this.closest;
     105            this.closest = closest;
     106            if (mapillaryData.getMultiSelectedImages().contains(closest))
     107                return;
     108            if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.CTRL_MASK)
     109                    && closest != null)
     110                mapillaryData.addMultiSelectedImage(closest);
     111            else
     112                mapillaryData.setSelectedImage(closest);
     113        }
     114    }
     115
     116    private MapillaryAbstractImage getClosest(Point clickPoint) {
     117        double snapDistance = 10;
     118        double minDistance = Double.MAX_VALUE;
     119        MapillaryAbstractImage closest = null;
     120        for (MapillaryAbstractImage image : mapillaryData.getImages()) {
     121            Point imagePoint = Main.map.mapView.getPoint(image.getLatLon());
     122            imagePoint.setLocation(imagePoint.getX(), imagePoint.getY());
     123            double dist = clickPoint.distanceSq(imagePoint);
     124            if (minDistance > dist
     125                    && clickPoint.distance(imagePoint) < snapDistance) {
     126                minDistance = dist;
     127                closest = image;
     128            }
     129        }
     130        return closest;
     131    }
     132
     133    @Override
     134    public void mouseDragged(MouseEvent e) {
     135        if (Main.map.mapView.getActiveLayer() != MapillaryLayer.getInstance())
     136            return;
     137
     138        if (!Main.pref.getBoolean("mapillary.developer"))
     139            for (MapillaryAbstractImage img : MapillaryData.getInstance()
     140                    .getMultiSelectedImages()) {
     141                if (img instanceof MapillaryImage)
     142                    return;
     143            }
     144        if (MapillaryData.getInstance().getSelectedImage() != null) {
     145            if (lastButton == MouseEvent.BUTTON1 && !e.isShiftDown()) {
     146                LatLon to = Main.map.mapView.getLatLon(e.getX(), e.getY());
     147                LatLon from = Main.map.mapView.getLatLon(start.getX(),
     148                        start.getY());
     149                for (MapillaryAbstractImage img : MapillaryData.getInstance()
     150                        .getMultiSelectedImages()) {
     151
     152                    img.move(to.getX() - from.getX(), to.getY() - from.getY());
     153                }
     154                Main.map.repaint();
     155            } else if (lastButton == MouseEvent.BUTTON1 && e.isShiftDown()) {
     156                this.closest.turn(Math.toDegrees(Math.atan2(
     157                        (e.getX() - start.x), -(e.getY() - start.y)))
     158                        - closest.getTempCa());
     159                for (MapillaryAbstractImage img : MapillaryData.getInstance()
     160                        .getMultiSelectedImages()) {
     161                    img.turn(Math.toDegrees(Math.atan2((e.getX() - start.x),
     162                            -(e.getY() - start.y))) - closest.getTempCa());
     163                }
     164                Main.map.repaint();
     165            }
     166        }
     167    }
     168
     169    @Override
     170    public void mouseReleased(MouseEvent e) {
     171        if (mapillaryData.getSelectedImage() == null)
     172            return;
     173        if (mapillaryData.getSelectedImage().getTempCa() != mapillaryData
     174                .getSelectedImage().getCa()) {
     175            double from = mapillaryData.getSelectedImage().getTempCa();
     176            double to = mapillaryData.getSelectedImage().getCa();
     177            record.addCommand(new CommandTurnImage(mapillaryData
     178                    .getMultiSelectedImages(), to - from));
     179        } else if (mapillaryData.getSelectedImage().getTempLatLon() != mapillaryData
     180                .getSelectedImage().getLatLon()) {
     181            LatLon from = mapillaryData.getSelectedImage().getTempLatLon();
     182            LatLon to = mapillaryData.getSelectedImage().getLatLon();
     183            record.addCommand(new CommandMoveImage(mapillaryData
     184                    .getMultiSelectedImages(), to.getX() - from.getX(), to
     185                    .getY() - from.getY()));
     186        }
     187        for (MapillaryAbstractImage img : mapillaryData
     188                .getMultiSelectedImages()) {
     189            if (img != null)
     190                img.stopMoving();
     191        }
     192    }
     193
     194    /**
     195    * Checks if the mouse is over pictures.
     196    */
     197    @Override
     198    public void mouseMoved(MouseEvent e) {
     199        MapillaryAbstractImage closestTemp = getClosest(e.getPoint());
     200
     201        if (closestTemp != null
     202                && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer
     203                && Main.map.mapModeSelect.getValue("active") == Boolean.TRUE) {
     204            Main.map.mapModeSelect.exitMode();
     205        } else if (closestTemp == null
     206                && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer
     207                && Main.map.mapModeSelect.getValue("active") == Boolean.FALSE) {
     208            Main.map.mapModeSelect.enterMode();
     209            nothingHighlighted = false;
     210        } else if (Main.map.mapModeSelect.getValue("active") == Boolean.FALSE
     211                && !nothingHighlighted) {
     212            for (OsmPrimitive primivitive : Main.map.mapView.getEditLayer().data
     213                    .allPrimitives()) {
     214                primivitive.setHighlighted(false);
     215            }
     216            nothingHighlighted = true;
     217        }
     218
     219        // TODO check if it is possible to do this while the OSM data layer is
     220        // selected.
     221        if (MapillaryData.getInstance().getHoveredImage() != closestTemp
     222                && closestTemp != null) {
     223            MapillaryData.getInstance().setHoveredImage(closestTemp);
     224            MapillaryToggleDialog.getInstance().setImage(closestTemp);
     225            MapillaryToggleDialog.getInstance().updateImage();
     226        } else if (MapillaryData.getInstance().getHoveredImage() != closestTemp
     227                && closestTemp == null) {
     228            MapillaryData.getInstance().setHoveredImage(null);
     229            MapillaryToggleDialog.getInstance().setImage(
     230                    MapillaryData.getInstance().getSelectedImage());
     231            MapillaryToggleDialog.getInstance().updateImage();
     232        }
     233        MapillaryData.getInstance().dataUpdated();
     234    }
    235235}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java

    r31277 r31278  
    3131public class MapillaryPlugin extends Plugin implements EditLayerChangeListener {
    3232
    33         public static final ImageIcon ICON24 = new ImageProvider("icon24.png")
    34                         .get();
    35         public static final ImageIcon ICON16 = new ImageProvider("icon16.png")
    36                         .get();
    37         public static final ImageIcon MAP_ICON = new ImageProvider("mapicon.png")
    38                         .get();
    39         public static final ImageIcon MAP_ICON_SELECTED = new ImageProvider(
    40                         "mapiconselected.png").get();
    41         public static final ImageIcon MAP_ICON_IMPORTED = new ImageProvider(
    42                         "mapiconimported.png").get();
    43         public static final ImageIcon MAP_SIGN = new ImageProvider("sign.png")
    44                         .get();
    45         public static final int ICON_SIZE = 24;
     33    public static final ImageIcon ICON24 = new ImageProvider("icon24.png")
     34            .get();
     35    public static final ImageIcon ICON16 = new ImageProvider("icon16.png")
     36            .get();
     37    public static final ImageIcon MAP_ICON = new ImageProvider("mapicon.png")
     38            .get();
     39    public static final ImageIcon MAP_ICON_SELECTED = new ImageProvider(
     40            "mapiconselected.png").get();
     41    public static final ImageIcon MAP_ICON_IMPORTED = new ImageProvider(
     42            "mapiconimported.png").get();
     43    public static final ImageIcon MAP_SIGN = new ImageProvider("sign.png")
     44            .get();
     45    public static final int ICON_SIZE = 24;
    4646
    47         public static CacheAccess<String, BufferedImageCacheEntry> CACHE;
     47    public static CacheAccess<String, BufferedImageCacheEntry> CACHE;
    4848
    49         private final MapillaryDownloadAction downloadAction;
    50         private final MapillaryExportAction exportAction;
    51         private final MapillaryImportAction importAction;
    52         private final MapillarySignAction signAction;
    53         private final MapillaryZoomAction zoomAction;
    54         private final MapillaryDownloadViewAction downloadViewAction;
     49    private final MapillaryDownloadAction downloadAction;
     50    private final MapillaryExportAction exportAction;
     51    private final MapillaryImportAction importAction;
     52    private final MapillarySignAction signAction;
     53    private final MapillaryZoomAction zoomAction;
     54    private final MapillaryDownloadViewAction downloadViewAction;
    5555
    56         public static JMenuItem DOWNLOAD_MENU;
    57         public static JMenuItem EXPORT_MENU;
    58         public static JMenuItem IMPORT_MENU;
    59         public static JMenuItem SIGN_MENU;
    60         public static JMenuItem ZOOM_MENU;
    61         public static JMenuItem DOWNLOAD_VIEW_MENU;
     56    public static JMenuItem DOWNLOAD_MENU;
     57    public static JMenuItem EXPORT_MENU;
     58    public static JMenuItem IMPORT_MENU;
     59    public static JMenuItem SIGN_MENU;
     60    public static JMenuItem ZOOM_MENU;
     61    public static JMenuItem DOWNLOAD_VIEW_MENU;
    6262
    63         public MapillaryPlugin(PluginInformation info) {
    64                 super(info);
    65                 downloadAction = new MapillaryDownloadAction();
    66                 exportAction = new MapillaryExportAction();
    67                 importAction = new MapillaryImportAction();
    68                 signAction = new MapillarySignAction();
    69                 zoomAction = new MapillaryZoomAction();
    70                 downloadViewAction = new MapillaryDownloadViewAction();
     63    public MapillaryPlugin(PluginInformation info) {
     64        super(info);
     65        downloadAction = new MapillaryDownloadAction();
     66        exportAction = new MapillaryExportAction();
     67        importAction = new MapillaryImportAction();
     68        signAction = new MapillarySignAction();
     69        zoomAction = new MapillaryZoomAction();
     70        downloadViewAction = new MapillaryDownloadViewAction();
    7171
    72                 DOWNLOAD_MENU = MainMenu.add(Main.main.menu.imageryMenu,
    73                                 downloadAction, false);
    74                 EXPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, exportAction,
    75                                 false, 14);
    76                 IMPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, importAction,
    77                                 false, 14);
    78                 SIGN_MENU = MainMenu.add(Main.main.menu.dataMenu, signAction, false);
    79                 ZOOM_MENU = MainMenu
    80                                 .add(Main.main.menu.viewMenu, zoomAction, false, 15);
    81                 DOWNLOAD_VIEW_MENU = MainMenu.add(Main.main.menu.fileMenu,
    82                                 downloadViewAction, false, 14);
    83                
    84                 EXPORT_MENU.setEnabled(false);
    85                 DOWNLOAD_MENU.setEnabled(false);
    86                 IMPORT_MENU.setEnabled(false);
    87                 SIGN_MENU.setEnabled(false);
    88                 ZOOM_MENU.setEnabled(false);
    89                 DOWNLOAD_VIEW_MENU.setEnabled(false);
     72        DOWNLOAD_MENU = MainMenu.add(Main.main.menu.imageryMenu,
     73                downloadAction, false);
     74        EXPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, exportAction,
     75                false, 14);
     76        IMPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, importAction,
     77                false, 14);
     78        SIGN_MENU = MainMenu.add(Main.main.menu.dataMenu, signAction, false);
     79        ZOOM_MENU = MainMenu
     80                .add(Main.main.menu.viewMenu, zoomAction, false, 15);
     81        DOWNLOAD_VIEW_MENU = MainMenu.add(Main.main.menu.fileMenu,
     82                downloadViewAction, false, 14);
    9083
    91                 MapView.addEditLayerChangeListener(this);
    92                 try {
    93                         CACHE = JCSCacheManager.getCache("mapillary", 10, 10000,
    94                                         this.getPluginDir() + "/cache/");
    95                 } catch (IOException e) {
    96                         Main.error(e);
    97                 }
    98         }
     84        EXPORT_MENU.setEnabled(false);
     85        DOWNLOAD_MENU.setEnabled(false);
     86        IMPORT_MENU.setEnabled(false);
     87        SIGN_MENU.setEnabled(false);
     88        ZOOM_MENU.setEnabled(false);
     89        DOWNLOAD_VIEW_MENU.setEnabled(false);
    9990
    100         /**
    101          * Called when the JOSM map frame is created or destroyed.
    102          */
    103         @Override
    104         public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
    105                 if (oldFrame == null && newFrame != null) { // map frame added
    106                 }
    107                 if (oldFrame != null && newFrame == null) { // map frame destroyed
    108                         MapillaryToggleDialog.destroyInstance();
    109                 }
    110         }
     91        MapView.addEditLayerChangeListener(this);
     92        try {
     93            CACHE = JCSCacheManager.getCache("mapillary", 10, 10000,
     94                    this.getPluginDir() + "/cache/");
     95        } catch (IOException e) {
     96            Main.error(e);
     97        }
     98    }
    11199
    112         public static void setMenuEnabled(JMenuItem menu, boolean value) {
    113                 menu.setEnabled(value);
    114         }
     100    /**
     101     * Called when the JOSM map frame is created or destroyed.
     102     */
     103    @Override
     104    public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
     105        if (oldFrame == null && newFrame != null) { // map frame added
     106        }
     107        if (oldFrame != null && newFrame == null) { // map frame destroyed
     108            MapillaryToggleDialog.destroyInstance();
     109        }
     110    }
    115111
    116         @Override
    117         public PreferenceSetting getPreferenceSetting() {
    118                 return new MapillaryPreferenceSetting();
    119         }
     112    public static void setMenuEnabled(JMenuItem menu, boolean value) {
     113        menu.setEnabled(value);
     114    }
    120115
    121         @Override
    122         public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
    123                 if (oldLayer == null && newLayer != null) {
    124                         DOWNLOAD_MENU.setEnabled(true);
    125                         IMPORT_MENU.setEnabled(true);
    126                         DOWNLOAD_VIEW_MENU.setEnabled(true);
    127                 } else if (oldLayer != null && newLayer == null) {
    128                         DOWNLOAD_MENU.setEnabled(false);
    129                         IMPORT_MENU.setEnabled(false);
    130                         DOWNLOAD_VIEW_MENU.setEnabled(false);
    131                 }
    132         }
     116    @Override
     117    public PreferenceSetting getPreferenceSetting() {
     118        return new MapillaryPreferenceSetting();
     119    }
     120
     121    @Override
     122    public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
     123        if (oldLayer == null && newLayer != null) {
     124            DOWNLOAD_MENU.setEnabled(true);
     125            IMPORT_MENU.setEnabled(true);
     126            DOWNLOAD_VIEW_MENU.setEnabled(true);
     127        } else if (oldLayer != null && newLayer == null) {
     128            DOWNLOAD_MENU.setEnabled(false);
     129            IMPORT_MENU.setEnabled(false);
     130            DOWNLOAD_VIEW_MENU.setEnabled(false);
     131        }
     132    }
    133133}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillarySequence.java

    r31277 r31278  
    1212 */
    1313public class MapillarySequence {
    14         private final List<MapillaryImage> images;
    15         private final String key;
    16         private final long created_at;
     14    private final List<MapillaryImage> images;
     15    private final String key;
     16    private final long created_at;
    1717
    18         public MapillarySequence(String key, long created_at) {
    19                 this.images = new ArrayList<>();
    20                 this.key = key;
    21                 this.created_at = created_at;
    22         }
     18    public MapillarySequence(String key, long created_at) {
     19        this.images = new ArrayList<>();
     20        this.key = key;
     21        this.created_at = created_at;
     22    }
    2323
    24         /**
    25         * Returns all MapillaryImages objects contained by this object.
    26         *
    27         * @return
    28         */
    29         public List<MapillaryImage> getImages() {
    30                 return this.images;
    31         }
     24    /**
     25    * Returns all MapillaryImages objects contained by this object.
     26    *
     27    * @return
     28    */
     29    public List<MapillaryImage> getImages() {
     30        return this.images;
     31    }
    3232
    33         public long getCreatedAt() {
    34                 return created_at;
    35         }
     33    public long getCreatedAt() {
     34        return created_at;
     35    }
    3636
    37         /**
    38         * Adds a new MapillaryImage object to this object.
    39         *
    40         * @param image
    41         */
    42         public synchronized void add(MapillaryImage image) {
    43                 this.images.add(image);
    44         }
     37    /**
     38    * Adds a new MapillaryImage object to this object.
     39    *
     40    * @param image
     41    */
     42    public synchronized void add(MapillaryImage image) {
     43        this.images.add(image);
     44    }
    4545
    46         public String getKey() {
    47                 return this.key;
    48         }
     46    public String getKey() {
     47        return this.key;
     48    }
    4949
    50         /**
    51         * Adds a set of MapillaryImage objects to this object.
    52         *
    53         * @param images
    54         */
    55         public synchronized void add(List<MapillaryImage> images) {
    56                 for (MapillaryImage image : images)
    57                         add(image);
    58         }
     50    /**
     51    * Adds a set of MapillaryImage objects to this object.
     52    *
     53    * @param images
     54    */
     55    public synchronized void add(List<MapillaryImage> images) {
     56        for (MapillaryImage image : images)
     57            add(image);
     58    }
    5959
    60         /**
    61         * Removes a MapillaryImage object from this object.
    62         *
    63         * @param image
    64         */
    65         public void remove(MapillaryImage image) {
    66                 this.images.remove(image);
    67         }
     60    /**
     61    * Removes a MapillaryImage object from this object.
     62    *
     63    * @param image
     64    */
     65    public void remove(MapillaryImage image) {
     66        this.images.remove(image);
     67    }
    6868
    69         /**
    70         * Returns the next MapillaryImage in the sequence.
    71         *
    72         * @param image
    73         * @return
    74         */
    75         public MapillaryImage next(MapillaryImage image) {
    76                 if (!images.contains(image))
    77                         throw new IllegalArgumentException();
    78                 int i = images.indexOf(image);
    79                 if (i == images.size() - 1)
    80                         return null;
    81                 else
    82                         return images.get(i + 1);
    83         }
     69    /**
     70    * Returns the next MapillaryImage in the sequence.
     71    *
     72    * @param image
     73    * @return
     74    */
     75    public MapillaryImage next(MapillaryImage image) {
     76        if (!images.contains(image))
     77            throw new IllegalArgumentException();
     78        int i = images.indexOf(image);
     79        if (i == images.size() - 1)
     80            return null;
     81        else
     82            return images.get(i + 1);
     83    }
    8484
    85         /**
    86         * Returns the previous MapillaryImage in the sequence.
    87         *
    88         * @param image
    89         * @return
    90         */
    91         public MapillaryImage previous(MapillaryImage image) {
    92                 if (!images.contains(image))
    93                         throw new IllegalArgumentException();
    94                 int i = images.indexOf(image);
    95                 if (i == 0)
    96                         return null;
    97                 else
    98                         return images.get(i - 1);
    99         }
     85    /**
     86    * Returns the previous MapillaryImage in the sequence.
     87    *
     88    * @param image
     89    * @return
     90    */
     91    public MapillaryImage previous(MapillaryImage image) {
     92        if (!images.contains(image))
     93            throw new IllegalArgumentException();
     94        int i = images.indexOf(image);
     95        if (i == 0)
     96            return null;
     97        else
     98            return images.get(i - 1);
     99    }
    100100
    101         /**
    102         * Returns the difference of index between two MapillaryImage objects
    103         * belonging to the same MapillarySequence.
    104         *
    105         * @param image1
    106         * @param image2
    107         * @return
    108         */
    109         public int getDistance(MapillaryImage image1, MapillaryImage image2) {
    110                 if (!this.images.contains(image1) || !this.images.contains(image2))
    111                         throw new IllegalArgumentException();
    112                 return Math.abs(this.images.indexOf(image1)
    113                                 - this.images.indexOf(image2));
    114         }
     101    /**
     102    * Returns the difference of index between two MapillaryImage objects
     103    * belonging to the same MapillarySequence.
     104    *
     105    * @param image1
     106    * @param image2
     107    * @return
     108    */
     109    public int getDistance(MapillaryImage image1, MapillaryImage image2) {
     110        if (!this.images.contains(image1) || !this.images.contains(image2))
     111            throw new IllegalArgumentException();
     112        return Math.abs(this.images.indexOf(image1)
     113                - this.images.indexOf(image2));
     114    }
    115115
    116         @Override
    117         public boolean equals(Object obj) {
    118                 if (obj instanceof MapillarySequence)
    119                         return this.getKey().equals(((MapillarySequence) obj).getKey());
    120                 return false;
    121         }
     116    @Override
     117    public boolean equals(Object obj) {
     118        if (obj instanceof MapillarySequence)
     119            return this.getKey().equals(((MapillarySequence) obj).getKey());
     120        return false;
     121    }
    122122
    123         @Override
    124         public int hashCode() {
    125                 return this.key.hashCode();
    126         }
     123    @Override
     124    public int hashCode() {
     125        return this.key.hashCode();
     126    }
    127127}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadAction.java

    r31277 r31278  
    2323public class MapillaryDownloadAction extends JosmAction {
    2424
    25         public MapillaryDownloadAction() {
    26                 super(tr("Mapillary"), new ImageProvider("icon24.png"),
    27                                 tr("Create Mapillary layer"), Shortcut.registerShortcut(
    28                                                 "Mapillary", tr("Start Mapillary layer"),
    29                                                 KeyEvent.VK_M, Shortcut.ALT_CTRL_SHIFT), false,
    30                                 "mapillaryDownload", false);
    31                 this.setEnabled(false);
    32         }
     25    public MapillaryDownloadAction() {
     26        super(tr("Mapillary"), new ImageProvider("icon24.png"),
     27                tr("Create Mapillary layer"), Shortcut.registerShortcut(
     28                        "Mapillary", tr("Start Mapillary layer"),
     29                        KeyEvent.VK_M, Shortcut.ALT_CTRL_SHIFT), false,
     30                "mapillaryDownload", false);
     31        this.setEnabled(false);
     32    }
    3333
    34         @Override
    35         public void actionPerformed(ActionEvent arg0) {
    36                 if (MapillaryLayer.INSTANCE == null)
    37                         MapillaryLayer.getInstance().download();
    38                 else {
    39                         if (Main.map.mapView.getActiveLayer() != MapillaryLayer
    40                                         .getInstance())
    41                                 Main.map.mapView.setActiveLayer(MapillaryLayer.getInstance());
    42                         else
    43                                 Main.map.mapView
    44                                                 .setActiveLayer(Main.map.mapView.getEditLayer());
    45                 }
    46         }
     34    @Override
     35    public void actionPerformed(ActionEvent arg0) {
     36        if (MapillaryLayer.INSTANCE == null)
     37            MapillaryLayer.getInstance().download();
     38        else {
     39            if (Main.map.mapView.getActiveLayer() != MapillaryLayer
     40                    .getInstance())
     41                Main.map.mapView.setActiveLayer(MapillaryLayer.getInstance());
     42            else
     43                Main.map.mapView
     44                        .setActiveLayer(Main.map.mapView.getEditLayer());
     45        }
     46    }
    4747
    4848}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadViewAction.java

    r31277 r31278  
    1717public class MapillaryDownloadViewAction extends JosmAction {
    1818
    19         public static double MAX_AREA = Main.pref.getDouble(
    20                         "mapillary.max-download-area", 0.025);
     19    public static double MAX_AREA = Main.pref.getDouble(
     20            "mapillary.max-download-area", 0.025);
    2121
    22         public MapillaryDownloadViewAction() {
    23                 super(tr("Download Mapillary images in current view"),
    24                                 new ImageProvider("icon24.png"),
    25                                 tr("Download Mapillary images in current view"),
    26                                 Shortcut.registerShortcut("Mapillary area",
    27                                                 tr("Download Mapillary images in current view"),
    28                                                 KeyEvent.VK_M, Shortcut.NONE), false, "mapillaryArea",
    29                                 false);
    30                 this.setEnabled(false);
    31         }
     22    public MapillaryDownloadViewAction() {
     23        super(tr("Download Mapillary images in current view"),
     24                new ImageProvider("icon24.png"),
     25                tr("Download Mapillary images in current view"),
     26                Shortcut.registerShortcut("Mapillary area",
     27                        tr("Download Mapillary images in current view"),
     28                        KeyEvent.VK_M, Shortcut.NONE), false, "mapillaryArea",
     29                false);
     30        this.setEnabled(false);
     31    }
    3232
    33         @Override
    34         public void actionPerformed(ActionEvent arg0) {
    35                 MapillaryLayer.getInstance();
    36                 MapillaryLayer.getInstance().bounds.add(Main.map.mapView
    37                                 .getRealBounds());
    38                 if (Main.map.mapView.getRealBounds().getArea() <= MAX_AREA) {
    39                         new MapillaryDownloader().getImages(Main.map.mapView
    40                                         .getRealBounds());
    41                 } else {
    42                         JOptionPane.showMessageDialog(Main.parent,
    43                                         tr("This area too big to be downloaded"));
    44                 }
    45         }
     33    @Override
     34    public void actionPerformed(ActionEvent arg0) {
     35        MapillaryLayer.getInstance();
     36        MapillaryLayer.getInstance().bounds.add(Main.map.mapView
     37                .getRealBounds());
     38        if (Main.map.mapView.getRealBounds().getArea() <= MAX_AREA) {
     39            new MapillaryDownloader().getImages(Main.map.mapView
     40                    .getRealBounds());
     41        } else {
     42            JOptionPane.showMessageDialog(Main.parent,
     43                    tr("This area too big to be downloaded"));
     44        }
     45    }
    4646}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryExportAction.java

    r31266 r31278  
    3232public class MapillaryExportAction extends JosmAction {
    3333
    34         MapillaryExportDialog dialog;
     34    MapillaryExportDialog dialog;
    3535
    36         public MapillaryExportAction() {
    37                 super(tr("Export pictures"), new ImageProvider("icon24.png"),
    38                                 tr("Export pictures"), Shortcut.registerShortcut(
    39                                                 "Export Mapillary", tr("Export Mapillary pictures"),
    40                                                 KeyEvent.VK_M, Shortcut.NONE), false, "mapillaryExport", false);
    41                 this.setEnabled(false);
    42         }
     36    public MapillaryExportAction() {
     37        super(tr("Export pictures"), new ImageProvider("icon24.png"),
     38                tr("Export pictures"), Shortcut.registerShortcut(
     39                        "Export Mapillary", tr("Export Mapillary pictures"),
     40                        KeyEvent.VK_M, Shortcut.NONE), false,
     41                "mapillaryExport", false);
     42        this.setEnabled(false);
     43    }
    4344
    44         @Override
    45         public void actionPerformed(ActionEvent e) {
    46                 dialog = new MapillaryExportDialog();
    47                 JOptionPane pane = new JOptionPane(dialog, JOptionPane.PLAIN_MESSAGE,
    48                                 JOptionPane.OK_CANCEL_OPTION);
    49                 JDialog dlg = pane.createDialog(Main.parent, tr("Export images"));
    50                 dlg.setMinimumSize(new Dimension(400, 150));
    51                 dlg.setVisible(true);
     45    @Override
     46    public void actionPerformed(ActionEvent e) {
     47        dialog = new MapillaryExportDialog();
     48        JOptionPane pane = new JOptionPane(dialog, JOptionPane.PLAIN_MESSAGE,
     49                JOptionPane.OK_CANCEL_OPTION);
     50        JDialog dlg = pane.createDialog(Main.parent, tr("Export images"));
     51        dlg.setMinimumSize(new Dimension(400, 150));
     52        dlg.setVisible(true);
    5253
    53                 // Checks if the inputs are correct and starts the export process.
    54                 if (pane.getValue() != null
    55                                 && (int) pane.getValue() == JOptionPane.OK_OPTION
    56                                 && dialog.chooser != null) {
    57                         if (dialog.group.isSelected(dialog.all.getModel())) {
    58                                 export(MapillaryData.getInstance().getImages());
    59                         } else if (dialog.group.isSelected(dialog.sequence.getModel())) {
    60                                 ArrayList<MapillaryAbstractImage> images = new ArrayList<>();
    61                                 for (MapillaryAbstractImage image : MapillaryData.getInstance().getMultiSelectedImages())
    62                                         if (image instanceof MapillaryImage) {
    63                                                 if (!images.contains(image))
    64                                                         images.addAll(((MapillaryImage) image).getSequence().getImages());
    65                                         }
    66                                         else
    67                                                 images.add(image);
    68                                 export(images);
    69                         } else if (dialog.group.isSelected(dialog.selected.getModel())) {
    70                                 export(MapillaryData.getInstance().getMultiSelectedImages());
    71                         }
    72                 // This option ignores the selected directory.
    73                  } else if (dialog.group.isSelected(dialog.rewrite.getModel())) {
    74                         ArrayList<MapillaryImportedImage> images = new ArrayList<>();
    75                         for (MapillaryAbstractImage image : MapillaryData.getInstance().getImages())
    76                                 if (image instanceof MapillaryImportedImage) {
    77                                         images.add(((MapillaryImportedImage) image));
    78                                 }
    79                         try {
    80                                 Main.worker.submit(new Thread(new MapillaryExportManager(images)));
    81                         } catch (IOException e1) {
    82                                 Main.error(e1);
    83                         }
    84                 }
    85                 dlg.dispose();
    86         }
     54        // Checks if the inputs are correct and starts the export process.
     55        if (pane.getValue() != null
     56                && (int) pane.getValue() == JOptionPane.OK_OPTION
     57                && dialog.chooser != null) {
     58            if (dialog.group.isSelected(dialog.all.getModel())) {
     59                export(MapillaryData.getInstance().getImages());
     60            } else if (dialog.group.isSelected(dialog.sequence.getModel())) {
     61                ArrayList<MapillaryAbstractImage> images = new ArrayList<>();
     62                for (MapillaryAbstractImage image : MapillaryData.getInstance()
     63                        .getMultiSelectedImages())
     64                    if (image instanceof MapillaryImage) {
     65                        if (!images.contains(image))
     66                            images.addAll(((MapillaryImage) image)
     67                                    .getSequence().getImages());
     68                    } else
     69                        images.add(image);
     70                export(images);
     71            } else if (dialog.group.isSelected(dialog.selected.getModel())) {
     72                export(MapillaryData.getInstance().getMultiSelectedImages());
     73            }
     74            // This option ignores the selected directory.
     75        } else if (dialog.group.isSelected(dialog.rewrite.getModel())) {
     76            ArrayList<MapillaryImportedImage> images = new ArrayList<>();
     77            for (MapillaryAbstractImage image : MapillaryData.getInstance()
     78                    .getImages())
     79                if (image instanceof MapillaryImportedImage) {
     80                    images.add(((MapillaryImportedImage) image));
     81                }
     82            try {
     83                Main.worker.submit(new Thread(
     84                        new MapillaryExportManager(images)));
     85            } catch (IOException e1) {
     86                Main.error(e1);
     87            }
     88        }
     89        dlg.dispose();
     90    }
    8791
    88         /**
    89         * Exports the given images from the database.
    90         */
    91         public void export(List<MapillaryAbstractImage> images) {
    92                 Main.worker.submit(new Thread(new MapillaryExportManager(images,
    93                                 dialog.chooser.getSelectedFile().toString())));
    94         }
     92    /**
     93    * Exports the given images from the database.
     94    */
     95    public void export(List<MapillaryAbstractImage> images) {
     96        Main.worker.submit(new Thread(new MapillaryExportManager(images,
     97                dialog.chooser.getSelectedFile().toString())));
     98    }
    9599
    96100}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryImportAction.java

    r31277 r31278  
    3838public class MapillaryImportAction extends JosmAction {
    3939
    40         public JFileChooser chooser;
     40    public JFileChooser chooser;
    4141
    42         /**
    43         * Amount of pictures without the proper EXIF tags.
    44         */
    45         private int noTagsPics = 0;
     42    /**
     43    * Amount of pictures without the proper EXIF tags.
     44    */
     45    private int noTagsPics = 0;
    4646
    47         public MapillaryImportAction() {
    48                 super(tr("Import pictures"), new ImageProvider("icon24.png"),
    49                                 tr("Import local pictures"), Shortcut.registerShortcut(
    50                                                 "Import Mapillary",
    51                                                 tr("Import pictures into Mapillary layer"),
    52                                                 KeyEvent.VK_M, Shortcut.NONE), false,
    53                                 "mapillaryImport", false);
    54                 this.setEnabled(false);
    55         }
     47    public MapillaryImportAction() {
     48        super(tr("Import pictures"), new ImageProvider("icon24.png"),
     49                tr("Import local pictures"), Shortcut.registerShortcut(
     50                        "Import Mapillary",
     51                        tr("Import pictures into Mapillary layer"),
     52                        KeyEvent.VK_M, Shortcut.NONE), false,
     53                "mapillaryImport", false);
     54        this.setEnabled(false);
     55    }
    5656
    57         @Override
    58         public void actionPerformed(ActionEvent e) {
    59                 chooser = new JFileChooser();
    60                 chooser.setCurrentDirectory(new java.io.File(System
    61                                 .getProperty("user.home")));
    62                 chooser.setDialogTitle(tr("Select pictures"));
    63                 chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
    64                 chooser.setAcceptAllFileFilterUsed(false);
    65                 chooser.addChoosableFileFilter(new FileNameExtensionFilter("images",
    66                                 "jpg", "jpeg", "png"));
    67                 chooser.setMultiSelectionEnabled(true);
    68                 if (chooser.showOpenDialog(Main.parent) == JFileChooser.APPROVE_OPTION) {
    69                         for (int i = 0; i < chooser.getSelectedFiles().length; i++) {
    70                                 File file = chooser.getSelectedFiles()[i];
    71                                 if (file.isDirectory()) {
     57    @Override
     58    public void actionPerformed(ActionEvent e) {
     59        chooser = new JFileChooser();
     60        chooser.setCurrentDirectory(new java.io.File(System
     61                .getProperty("user.home")));
     62        chooser.setDialogTitle(tr("Select pictures"));
     63        chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
     64        chooser.setAcceptAllFileFilterUsed(false);
     65        chooser.addChoosableFileFilter(new FileNameExtensionFilter("images",
     66                "jpg", "jpeg", "png"));
     67        chooser.setMultiSelectionEnabled(true);
     68        if (chooser.showOpenDialog(Main.parent) == JFileChooser.APPROVE_OPTION) {
     69            for (int i = 0; i < chooser.getSelectedFiles().length; i++) {
     70                File file = chooser.getSelectedFiles()[i];
     71                if (file.isDirectory()) {
    7272
    73                                 } else {
    74                                         if (file.getPath().substring(file.getPath().length() - 4)
    75                                                         .equals(".jpg")
    76                                                         || file.getPath()
    77                                                                         .substring(file.getPath().length() - 5)
    78                                                                         .equals(".jpeg")) {
    79                                                 try {
    80                                                         readJPG(file);
    81                                                 } catch (ImageReadException ex) {
    82                                                         Main.error(ex);
    83                                                 } catch (IOException ex) {
    84                                                         Main.error(ex);
    85                                                 }
    86                                         } else if (file.getPath()
    87                                                         .substring(file.getPath().length() - 4)
    88                                                         .equals(".png")) {
    89                                                 readPNG(file);
    90                                         }
    91                                 }
    92                         }
    93                 }
    94                 MapillaryLayer.getInstance();
    95         }
     73                } else {
     74                    if (file.getPath().substring(file.getPath().length() - 4)
     75                            .equals(".jpg")
     76                            || file.getPath()
     77                                    .substring(file.getPath().length() - 5)
     78                                    .equals(".jpeg")) {
     79                        try {
     80                            readJPG(file);
     81                        } catch (ImageReadException ex) {
     82                            Main.error(ex);
     83                        } catch (IOException ex) {
     84                            Main.error(ex);
     85                        }
     86                    } else if (file.getPath()
     87                            .substring(file.getPath().length() - 4)
     88                            .equals(".png")) {
     89                        readPNG(file);
     90                    }
     91                }
     92            }
     93        }
     94        MapillaryLayer.getInstance();
     95    }
    9696
    97         /**
    98         * Reads a jpg pictures that contains the needed GPS information (position
    99         * and direction) and creates a new icon in that position.
    100         *
    101         * @param file
    102         * @throws ImageReadException
    103         * @throws IOException
    104         */
    105         public void readJPG(File file) throws ImageReadException, IOException {
    106                 final ImageMetadata metadata = Imaging.getMetadata(file);
    107                 if (metadata instanceof JpegImageMetadata) {
    108                         final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
    109                         final TiffField lat_ref = jpegMetadata
    110                                         .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF);
    111                         final TiffField lat = jpegMetadata
    112                                         .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LATITUDE);
    113                         final TiffField lon_ref = jpegMetadata
    114                                         .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LONGITUDE_REF);
    115                         final TiffField lon = jpegMetadata
    116                                         .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LONGITUDE);
    117                         final TiffField ca = jpegMetadata
    118                                         .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION);
    119                         final TiffField datetimeOriginal = jpegMetadata
    120                                         .findEXIFValueWithExactMatch(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);
    121                         if (lat_ref == null || lat == null || lon == null
    122                                         || lon_ref == null) {
    123                                 readNoTags(file);
    124                         }
    125                         double latValue = 0;
    126                         double lonValue = 0;
    127                         double caValue = 0;
    128                         if (lat != null && lat.getValue() instanceof RationalNumber[])
    129                                 latValue = DegMinSecToDouble((RationalNumber[]) lat.getValue(),
    130                                                 lat_ref.getValue().toString());
    131                         if (lon != null && lon.getValue() instanceof RationalNumber[])
    132                                 lonValue = DegMinSecToDouble((RationalNumber[]) lon.getValue(),
    133                                                 lon_ref.getValue().toString());
    134                         if (ca != null && ca.getValue() instanceof RationalNumber)
    135                                 caValue = ((RationalNumber) ca.getValue()).doubleValue();
    136                         if (lat_ref.getValue().toString().equals("S"))
    137                                 latValue = -latValue;
    138                         if (lon_ref.getValue().toString().equals("W"))
    139                                 lonValue = -lonValue;
    140                         if (datetimeOriginal != null)
    141                                 MapillaryData.getInstance().add(
    142                                                 new MapillaryImportedImage(latValue, lonValue, caValue,
    143                                                                 file, datetimeOriginal.getStringValue()));
    144                         else
    145                                 MapillaryData.getInstance().add(
    146                                                 new MapillaryImportedImage(latValue, lonValue, caValue,
    147                                                                 file, currentDate()));
    148                 }
    149         }
     97    /**
     98    * Reads a jpg pictures that contains the needed GPS information (position
     99    * and direction) and creates a new icon in that position.
     100    *
     101    * @param file
     102    * @throws ImageReadException
     103    * @throws IOException
     104    */
     105    public void readJPG(File file) throws ImageReadException, IOException {
     106        final ImageMetadata metadata = Imaging.getMetadata(file);
     107        if (metadata instanceof JpegImageMetadata) {
     108            final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
     109            final TiffField lat_ref = jpegMetadata
     110                    .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF);
     111            final TiffField lat = jpegMetadata
     112                    .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LATITUDE);
     113            final TiffField lon_ref = jpegMetadata
     114                    .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LONGITUDE_REF);
     115            final TiffField lon = jpegMetadata
     116                    .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LONGITUDE);
     117            final TiffField ca = jpegMetadata
     118                    .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION);
     119            final TiffField datetimeOriginal = jpegMetadata
     120                    .findEXIFValueWithExactMatch(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);
     121            if (lat_ref == null || lat == null || lon == null
     122                    || lon_ref == null) {
     123                readNoTags(file);
     124            }
     125            double latValue = 0;
     126            double lonValue = 0;
     127            double caValue = 0;
     128            if (lat != null && lat.getValue() instanceof RationalNumber[])
     129                latValue = DegMinSecToDouble((RationalNumber[]) lat.getValue(),
     130                        lat_ref.getValue().toString());
     131            if (lon != null && lon.getValue() instanceof RationalNumber[])
     132                lonValue = DegMinSecToDouble((RationalNumber[]) lon.getValue(),
     133                        lon_ref.getValue().toString());
     134            if (ca != null && ca.getValue() instanceof RationalNumber)
     135                caValue = ((RationalNumber) ca.getValue()).doubleValue();
     136            if (lat_ref.getValue().toString().equals("S"))
     137                latValue = -latValue;
     138            if (lon_ref.getValue().toString().equals("W"))
     139                lonValue = -lonValue;
     140            if (datetimeOriginal != null)
     141                MapillaryData.getInstance().add(
     142                        new MapillaryImportedImage(latValue, lonValue, caValue,
     143                                file, datetimeOriginal.getStringValue()));
     144            else
     145                MapillaryData.getInstance().add(
     146                        new MapillaryImportedImage(latValue, lonValue, caValue,
     147                                file, currentDate()));
     148        }
     149    }
    150150
    151         /**
    152         * Reads a image file that doesn't contain the needed GPS information. And
    153         * creates a new icon in the middle of the map.
    154         *
    155         * @param file
    156         */
    157         private void readNoTags(File file) {
    158                 double HORIZONTAL_DISTANCE = 0.0001;
    159                 double horDev;
    160                 if (noTagsPics % 2 == 0)
    161                         horDev = HORIZONTAL_DISTANCE * noTagsPics / 2;
    162                 else
    163                         horDev = -HORIZONTAL_DISTANCE * (noTagsPics + 1) / 2;
    164                 LatLon pos = Main.map.mapView.getProjection().eastNorth2latlon(
    165                                 Main.map.mapView.getCenter());
    166                 MapillaryData.getInstance().add(
    167                                 new MapillaryImportedImage(pos.lat(), pos.lon() + horDev, 0,
    168                                                 file, currentDate()));
    169                 noTagsPics++;
    170         }
     151    /**
     152    * Reads a image file that doesn't contain the needed GPS information. And
     153    * creates a new icon in the middle of the map.
     154    *
     155    * @param file
     156    */
     157    private void readNoTags(File file) {
     158        double HORIZONTAL_DISTANCE = 0.0001;
     159        double horDev;
     160        if (noTagsPics % 2 == 0)
     161            horDev = HORIZONTAL_DISTANCE * noTagsPics / 2;
     162        else
     163            horDev = -HORIZONTAL_DISTANCE * (noTagsPics + 1) / 2;
     164        LatLon pos = Main.map.mapView.getProjection().eastNorth2latlon(
     165                Main.map.mapView.getCenter());
     166        MapillaryData.getInstance().add(
     167                new MapillaryImportedImage(pos.lat(), pos.lon() + horDev, 0,
     168                        file, currentDate()));
     169        noTagsPics++;
     170    }
    171171
    172         private void readPNG(File file) {
    173                 readNoTags(file);
    174         }
     172    private void readPNG(File file) {
     173        readNoTags(file);
     174    }
    175175
    176         private double DegMinSecToDouble(RationalNumber[] degMinSec, String ref) {
    177                 RationalNumber deg = degMinSec[0];
    178                 RationalNumber min = degMinSec[1];
    179                 RationalNumber sec = degMinSec[2];
    180                 return deg.doubleValue() + min.doubleValue() / 60 + sec.doubleValue()
    181                                 / 3600;
    182         }
    183        
    184         private String currentDate() {
    185                    Calendar cal = Calendar.getInstance();
     176    private double DegMinSecToDouble(RationalNumber[] degMinSec, String ref) {
     177        RationalNumber deg = degMinSec[0];
     178        RationalNumber min = degMinSec[1];
     179        RationalNumber sec = degMinSec[2];
     180        return deg.doubleValue() + min.doubleValue() / 60 + sec.doubleValue()
     181                / 3600;
     182    }
    186183
    187                         SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
    188                         return formatter.format(cal);
    189        
    190         }
     184    private String currentDate() {
     185        Calendar cal = Calendar.getInstance();
     186
     187        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
     188        return formatter.format(cal);
     189
     190    }
    191191}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillarySignAction.java

    r31275 r31278  
    2020public class MapillarySignAction extends JosmAction {
    2121
    22         public MapillarySignAction() {
    23                 super(tr("Switch sign/normal mode"), new ImageProvider("icon24sign.png"),
    24                                 tr("Switch sign/normal mode"), Shortcut.registerShortcut(
    25                                                 "Mapillary sign", tr("Switch Mapillary plugin's sign mode on/off"),
    26                                                 KeyEvent.VK_M, Shortcut.NONE), false,
    27                                 "mapillarySign", false);
    28                 this.setEnabled(false);
    29         }
     22    public MapillarySignAction() {
     23        super(tr("Switch sign/normal mode"),
     24                new ImageProvider("icon24sign.png"),
     25                tr("Switch sign/normal mode"), Shortcut.registerShortcut(
     26                        "Mapillary sign",
     27                        tr("Switch Mapillary plugin's sign mode on/off"),
     28                        KeyEvent.VK_M, Shortcut.NONE), false, "mapillarySign",
     29                false);
     30        this.setEnabled(false);
     31    }
    3032
    31         @Override
    32         public void actionPerformed(ActionEvent e) {
    33                 MapillaryToggleDialog.getInstance().switchMode();
    34         }
     33    @Override
     34    public void actionPerformed(ActionEvent e) {
     35        MapillaryToggleDialog.getInstance().switchMode();
     36    }
    3537}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryZoomAction.java

    r31266 r31278  
    2222 */
    2323public class MapillaryZoomAction extends JosmAction implements
    24                 MapillaryDataListener {
     24        MapillaryDataListener {
    2525
    26         public MapillaryZoomAction() {
    27                 super(tr("Zoom to selected image"), new ImageProvider("icon24.png"),
    28                                 tr("Zoom to selected image"), Shortcut.registerShortcut(
    29                                                 "Zoom Mapillary",
    30                                                 tr("Zoom to the currently selected Mapillary image"),
    31                                                 KeyEvent.VK_M, Shortcut.NONE), false, "mapillaryZoom",
    32                                 false);
    33                 MapillaryData.getInstance().addListener(this);
    34                 this.setEnabled(false);
    35         }
     26    public MapillaryZoomAction() {
     27        super(tr("Zoom to selected image"), new ImageProvider("icon24.png"),
     28                tr("Zoom to selected image"), Shortcut.registerShortcut(
     29                        "Zoom Mapillary",
     30                        tr("Zoom to the currently selected Mapillary image"),
     31                        KeyEvent.VK_M, Shortcut.NONE), false, "mapillaryZoom",
     32                false);
     33        MapillaryData.getInstance().addListener(this);
     34        this.setEnabled(false);
     35    }
    3636
    37         @Override
    38         public void actionPerformed(ActionEvent arg0) {
    39                 if (MapillaryData.getInstance().getSelectedImage() == null)
    40                         throw new IllegalStateException();
    41                 Main.map.mapView.zoomTo(MapillaryData.getInstance().getSelectedImage()
    42                                 .getLatLon());
    43         }
     37    @Override
     38    public void actionPerformed(ActionEvent arg0) {
     39        if (MapillaryData.getInstance().getSelectedImage() == null)
     40            throw new IllegalStateException();
     41        Main.map.mapView.zoomTo(MapillaryData.getInstance().getSelectedImage()
     42                .getLatLon());
     43    }
    4444
    45         @Override
    46         public void selectedImageChanged(MapillaryAbstractImage oldImage,
    47                         MapillaryAbstractImage newImage) {
    48                 if (oldImage == null && newImage != null)
    49                         MapillaryPlugin.ZOOM_MENU.setEnabled(true);
    50                 else if (oldImage != null && newImage == null)
    51                         MapillaryPlugin.ZOOM_MENU.setEnabled(false);
    52         }
     45    @Override
     46    public void selectedImageChanged(MapillaryAbstractImage oldImage,
     47            MapillaryAbstractImage newImage) {
     48        if (oldImage == null && newImage != null)
     49            MapillaryPlugin.ZOOM_MENU.setEnabled(true);
     50        else if (oldImage != null && newImage == null)
     51            MapillaryPlugin.ZOOM_MENU.setEnabled(false);
     52    }
    5353}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/cache/MapillaryCache.java

    r31273 r31278  
    1111
    1212public class MapillaryCache extends
    13                 JCSCachedTileLoaderJob<String, BufferedImageCacheEntry> {
     13        JCSCachedTileLoaderJob<String, BufferedImageCacheEntry> {
    1414
    15         private volatile URL url;
    16         private volatile String key;
     15    private volatile URL url;
     16    private volatile String key;
    1717
    18         public static enum Type {
    19                 FULL_IMAGE, THUMBNAIL
    20         }
     18    public static enum Type {
     19        FULL_IMAGE, THUMBNAIL
     20    }
    2121
    22         public MapillaryCache(String key, Type type) {
    23                 super(MapillaryPlugin.CACHE, 50000, 50000, new HashMap<String, String>());
    24                 this.key = key;
    25                 try {
    26                         if (type == Type.FULL_IMAGE) {
    27                                 url = new URL("https://d1cuyjsrcm0gby.cloudfront.net/" + key
    28                                                 + "/thumb-2048.jpg");
    29                                 this.key += ".FULL_IMAGE";
     22    public MapillaryCache(String key, Type type) {
     23        super(MapillaryPlugin.CACHE, 50000, 50000,
     24                new HashMap<String, String>());
     25        this.key = key;
     26        try {
     27            if (type == Type.FULL_IMAGE) {
     28                url = new URL("https://d1cuyjsrcm0gby.cloudfront.net/" + key
     29                        + "/thumb-2048.jpg");
     30                this.key += ".FULL_IMAGE";
    3031
    31                         } else if (type == Type.THUMBNAIL) {
    32                                 url = new URL("https://d1cuyjsrcm0gby.cloudfront.net/" + key
    33                                                 + "/thumb-320.jpg");
    34                                 this.key += ".THUMBNAIL";
    35                         }
    36                 } catch (MalformedURLException e) {
    37                         Main.error(e);
    38                 }
    39         }
     32            } else if (type == Type.THUMBNAIL) {
     33                url = new URL("https://d1cuyjsrcm0gby.cloudfront.net/" + key
     34                        + "/thumb-320.jpg");
     35                this.key += ".THUMBNAIL";
     36            }
     37        } catch (MalformedURLException e) {
     38            Main.error(e);
     39        }
     40    }
    4041
    41         @Override
    42         public String getCacheKey() {
    43                 return key;
    44         }
     42    @Override
     43    public String getCacheKey() {
     44        return key;
     45    }
    4546
    46         @Override
    47         public URL getUrl() {
    48                 return url;
    49         }
     47    @Override
     48    public URL getUrl() {
     49        return url;
     50    }
    5051
    51         @Override
    52         protected BufferedImageCacheEntry createCacheEntry(byte[] content) {
    53                 return new BufferedImageCacheEntry(content);
    54         }
     52    @Override
     53    protected BufferedImageCacheEntry createCacheEntry(byte[] content) {
     54        return new BufferedImageCacheEntry(content);
     55    }
    5556
    56         @Override
    57         protected boolean isObjectLoadable() {
    58                 if (cacheData == null)
    59                         return false;
    60                 byte[] content = cacheData.getContent();
    61                 return content != null && content.length > 0;
    62         }
     57    @Override
     58    protected boolean isObjectLoadable() {
     59        if (cacheData == null)
     60            return false;
     61        byte[] content = cacheData.getContent();
     62        return content != null && content.length > 0;
     63    }
    6364
    64         // @Override
    65         protected boolean handleNotFound() {
    66                 return false;
    67         }
     65    // @Override
     66    protected boolean handleNotFound() {
     67        return false;
     68    }
    6869}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/CommandMoveImage.java

    r31257 r31278  
    1616 */
    1717public class CommandMoveImage extends MapillaryCommand {
    18         private double x;
    19         private double y;
     18    private double x;
     19    private double y;
    2020
    21         public CommandMoveImage(List<MapillaryAbstractImage> images, double x, double y) {
    22                 this.images = new ArrayList<>(images);
    23                 this.x = x;
    24                 this.y = y;
    25         }
     21    public CommandMoveImage(List<MapillaryAbstractImage> images, double x,
     22            double y) {
     23        this.images = new ArrayList<>(images);
     24        this.x = x;
     25        this.y = y;
     26    }
    2627
    27         @Override
    28         public void undo() {
    29                 for (MapillaryAbstractImage image : images) {
    30                         image.move(-x, -y);
    31                         image.stopMoving();
    32                 }
    33                 checkModified();
    34                 Main.map.repaint();
    35         }
     28    @Override
     29    public void undo() {
     30        for (MapillaryAbstractImage image : images) {
     31            image.move(-x, -y);
     32            image.stopMoving();
     33        }
     34        checkModified();
     35        Main.map.repaint();
     36    }
    3637
    37         @Override
    38         public void redo() {
    39                 for (MapillaryAbstractImage image : images) {
    40                         image.move(x, y);
    41                         image.stopMoving();
    42                 }
    43                 checkModified();
    44                 Main.map.repaint();
    45         }
    46        
    47         public String toString() {
    48                 return trn("Moved {0} node", "Moved {0} nodes", images.size(), images.size());
    49         }
    50        
    51         @Override
    52         public void sum(MapillaryCommand command) {
    53                 if (command instanceof CommandMoveImage) {
    54                         this.x += ((CommandMoveImage) command).x;
    55                         this.y += ((CommandMoveImage) command).y;
    56                 }
    57         }
     38    @Override
     39    public void redo() {
     40        for (MapillaryAbstractImage image : images) {
     41            image.move(x, y);
     42            image.stopMoving();
     43        }
     44        checkModified();
     45        Main.map.repaint();
     46    }
     47
     48    public String toString() {
     49        return trn("Moved {0} node", "Moved {0} nodes", images.size(),
     50                images.size());
     51    }
     52
     53    @Override
     54    public void sum(MapillaryCommand command) {
     55        if (command instanceof CommandMoveImage) {
     56            this.x += ((CommandMoveImage) command).x;
     57            this.y += ((CommandMoveImage) command).y;
     58        }
     59    }
    5860}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/CommandTurnImage.java

    r31257 r31278  
    1616 */
    1717public class CommandTurnImage extends MapillaryCommand {
    18         private double ca;
     18    private double ca;
    1919
    20         public CommandTurnImage(List<MapillaryAbstractImage> images, double ca) {
    21                 this.images = new ArrayList<>(images);
    22                 this.ca = ca;
    23         }
     20    public CommandTurnImage(List<MapillaryAbstractImage> images, double ca) {
     21        this.images = new ArrayList<>(images);
     22        this.ca = ca;
     23    }
    2424
    25         @Override
    26         public void undo() {
    27                 for (MapillaryAbstractImage image : images) {
    28                         image.turn(-ca);
    29                         image.stopMoving();
    30                 }
    31                 checkModified();
    32                 Main.map.repaint();
    33         }
     25    @Override
     26    public void undo() {
     27        for (MapillaryAbstractImage image : images) {
     28            image.turn(-ca);
     29            image.stopMoving();
     30        }
     31        checkModified();
     32        Main.map.repaint();
     33    }
    3434
    35         @Override
    36         public void redo() {
    37                 for (MapillaryAbstractImage image : images) {
    38                         image.turn(ca);
    39                         image.stopMoving();
    40                 }
    41                 checkModified();
    42                 Main.map.repaint();
    43         }
     35    @Override
     36    public void redo() {
     37        for (MapillaryAbstractImage image : images) {
     38            image.turn(ca);
     39            image.stopMoving();
     40        }
     41        checkModified();
     42        Main.map.repaint();
     43    }
    4444
    45         public String toString() {
    46                 return trn("Turned {0} node", "Turned {0} nodes", this.images.size(),
    47                                 this.images.size());
    48         }
     45    public String toString() {
     46        return trn("Turned {0} node", "Turned {0} nodes", this.images.size(),
     47                this.images.size());
     48    }
    4949
    50         @Override
    51         public void sum(MapillaryCommand command) {
    52                 if (command instanceof CommandTurnImage) {
    53                         this.ca += ((CommandTurnImage) command).ca;
    54                 }
    55         }
     50    @Override
     51    public void sum(MapillaryCommand command) {
     52        if (command instanceof CommandTurnImage) {
     53            this.ca += ((CommandTurnImage) command).ca;
     54        }
     55    }
    5656}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/MapillaryCommand.java

    r31264 r31278  
    1212 */
    1313public abstract class MapillaryCommand {
    14         protected List<MapillaryAbstractImage> images;
     14    protected List<MapillaryAbstractImage> images;
    1515
    16         public abstract void undo();
     16    public abstract void undo();
    1717
    18         public abstract void redo();
     18    public abstract void redo();
    1919
    20         /**
    21         * If two equal commands are applied consecutively to the same set of
    22         * images, they are summed in order to reduce them to just one command.
    23         *
    24         * @param command
    25         */
    26         public abstract void sum(MapillaryCommand command);
     20    /**
     21    * If two equal commands are applied consecutively to the same set of
     22    * images, they are summed in order to reduce them to just one command.
     23    *
     24    * @param command
     25    */
     26    public abstract void sum(MapillaryCommand command);
    2727
    28         /**
    29         * Checks if the image has been modified, compairing with its original
    30         * values.
    31         */
    32         public void checkModified() {
    33                 for (MapillaryAbstractImage image : images)
    34                         image.isModified = (image.tempLatLon == image.latLon || image.tempCa == image.ca);
    35         }
     28    /**
     29    * Checks if the image has been modified, compairing with its original
     30    * values.
     31    */
     32    public void checkModified() {
     33        for (MapillaryAbstractImage image : images)
     34            image.isModified = (image.tempLatLon == image.latLon || image.tempCa == image.ca);
     35    }
    3636}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/MapillaryRecord.java

    r31257 r31278  
    1010 */
    1111public class MapillaryRecord {
    12         public static MapillaryRecord INSTANCE;
     12    public static MapillaryRecord INSTANCE;
    1313
    14         private ArrayList<MapillaryRecordListener> listeners;
     14    private ArrayList<MapillaryRecordListener> listeners;
    1515
    16         public ArrayList<MapillaryCommand> commandList;
    17         /** Last written command */
    18         public int position;
     16    public ArrayList<MapillaryCommand> commandList;
     17    /** Last written command */
     18    public int position;
    1919
    20         public MapillaryRecord() {
    21                 commandList = new ArrayList<>();
    22                 position = -1;
    23                 listeners = new ArrayList<>();
    24         }
     20    public MapillaryRecord() {
     21        commandList = new ArrayList<>();
     22        position = -1;
     23        listeners = new ArrayList<>();
     24    }
    2525
    26         public static synchronized MapillaryRecord getInstance() {
    27                 if (MapillaryRecord.INSTANCE == null)
    28                         MapillaryRecord.INSTANCE = new MapillaryRecord();
    29                 return MapillaryRecord.INSTANCE;
    30         }
     26    public static synchronized MapillaryRecord getInstance() {
     27        if (MapillaryRecord.INSTANCE == null)
     28            MapillaryRecord.INSTANCE = new MapillaryRecord();
     29        return MapillaryRecord.INSTANCE;
     30    }
    3131
    32         public void addListener(MapillaryRecordListener lis) {
    33                 this.listeners.add(lis);
    34         }
     32    public void addListener(MapillaryRecordListener lis) {
     33        this.listeners.add(lis);
     34    }
    3535
    36         public void removeListener(MapillaryRecordListener lis) {
    37                 this.listeners.remove(lis);
    38         }
     36    public void removeListener(MapillaryRecordListener lis) {
     37        this.listeners.remove(lis);
     38    }
    3939
    40         /**
    41         * Adds a new command to the list.
    42         *
    43         * @param command
    44         */
    45         public void addCommand(MapillaryCommand command) {
    46                 // Checks if it is a continuation of last command
    47                 if (position != -1
    48                                 && commandList.get(position).images.equals(command.images)
    49                                 && commandList.get(position).getClass() == command.getClass()) {
    50                         commandList.get(position).sum(command);
    51                         fireRecordChanged();
    52                         return;
    53                 }
    54                 commandList.add(position + 1, command);
    55                 position++;
    56                 while (commandList.size() > position + 1) {
    57                         commandList.remove(position + 1);
    58                 }
    59                 fireRecordChanged();
    60         }
     40    /**
     41    * Adds a new command to the list.
     42    *
     43    * @param command
     44    */
     45    public void addCommand(MapillaryCommand command) {
     46        // Checks if it is a continuation of last command
     47        if (position != -1
     48                && commandList.get(position).images.equals(command.images)
     49                && commandList.get(position).getClass() == command.getClass()) {
     50            commandList.get(position).sum(command);
     51            fireRecordChanged();
     52            return;
     53        }
     54        commandList.add(position + 1, command);
     55        position++;
     56        while (commandList.size() > position + 1) {
     57            commandList.remove(position + 1);
     58        }
     59        fireRecordChanged();
     60    }
    6161
    62         /**
    63         * Undo latest command.
    64         */
    65         public void undo() {
    66                 if (position == -1)
    67                         return;
    68                 commandList.get(position).undo();
    69                 position--;
    70                 fireRecordChanged();
    71         }
     62    /**
     63    * Undo latest command.
     64    */
     65    public void undo() {
     66        if (position == -1)
     67            return;
     68        commandList.get(position).undo();
     69        position--;
     70        fireRecordChanged();
     71    }
    7272
    73         /**
    74         * Redo latest undoed action.
    75         */
    76         public void redo() {
    77                 if (position + 1 >= commandList.size())
    78                         return;
    79                 position++;
    80                 commandList.get(position).redo();
    81                 fireRecordChanged();
    82         }
     73    /**
     74    * Redo latest undoed action.
     75    */
     76    public void redo() {
     77        if (position + 1 >= commandList.size())
     78            return;
     79        position++;
     80        commandList.get(position).redo();
     81        fireRecordChanged();
     82    }
    8383
    84         private void fireRecordChanged() {
    85                 for (MapillaryRecordListener lis : listeners)
    86                         if (lis != null)
    87                                 lis.recordChanged();
    88         }
     84    private void fireRecordChanged() {
     85        for (MapillaryRecordListener lis : listeners)
     86            if (lis != null)
     87                lis.recordChanged();
     88    }
    8989}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/MapillaryRecordListener.java

    r31257 r31278  
    22
    33public interface MapillaryRecordListener {
    4         public void recordChanged();
     4    public void recordChanged();
    55}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryDownloader.java

    r31277 r31278  
    1515public class MapillaryDownloader {
    1616
    17         public final static String BASE_URL = "https://a.mapillary.com/v2/";
    18         public final static String CLIENT_ID = "NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1YTA2NmNlODhlNWMwOTBm";
     17    public final static String BASE_URL = "https://a.mapillary.com/v2/";
     18    public final static String CLIENT_ID = "NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1YTA2NmNlODhlNWMwOTBm";
    1919
    20         private String[] parameters = { "lat", "lon", "distance", "limit",
    21                         "min_lat", "min_lon", "max_lat", "max_lon" };
     20    private String[] parameters = { "lat", "lon", "distance", "limit",
     21            "min_lat", "min_lon", "max_lat", "max_lon" };
    2222
    23         public MapillaryDownloader() {
    24         }
     23    public MapillaryDownloader() {
     24    }
    2525
    26         /**
    27          * Gets all the images in a square. It downloads all the images of all the
    28          * sequences that pass through the given rectangle.
    29          *
    30          * @param minLatLon
    31          *            The minimum latitude and longitude of the rectangle.
    32          * @param maxLatLon
    33          *            The maximum latitude and longitude of the rectangle
    34          */
    35         public void getImages(LatLon minLatLon, LatLon maxLatLon) {
    36                 String url1 = BASE_URL;
    37                 String url2 = BASE_URL;
    38                 String url3 = BASE_URL;
    39                 url1 += "search/im/";
    40                 url2 += "search/s/";
    41                 url3 += "search/im/or";
    42                 ConcurrentHashMap<String, Double> hash = new ConcurrentHashMap<>();
    43                 hash.put("min_lat", minLatLon.lat());
    44                 hash.put("min_lon", minLatLon.lon());
    45                 hash.put("max_lat", maxLatLon.lat());
    46                 hash.put("max_lon", maxLatLon.lon());
    47                 url1 += buildParameters(hash);
    48                 url2 += buildParameters(hash);
    49                 url3 += buildParameters(hash);
    50                 System.out.println(url2);
    51                
    52                 try {
    53                         Main.info("MapillaryPlugin GET " + url2);
    54                         Main.worker.submit(new MapillarySquareDownloadManagerThread(url1, url2, url3));
    55                 } catch (Exception e) {
    56                         Main.error(e);
    57                 }
    58         }
    59        
    60         public void getImages(Bounds bounds) {
    61                 getImages(bounds.getMin(), bounds.getMax());
    62         }
     26    /**
     27     * Gets all the images in a square. It downloads all the images of all the
     28     * sequences that pass through the given rectangle.
     29     *
     30     * @param minLatLon
     31     *            The minimum latitude and longitude of the rectangle.
     32     * @param maxLatLon
     33     *            The maximum latitude and longitude of the rectangle
     34     */
     35    public void getImages(LatLon minLatLon, LatLon maxLatLon) {
     36        String url1 = BASE_URL;
     37        String url2 = BASE_URL;
     38        String url3 = BASE_URL;
     39        url1 += "search/im/";
     40        url2 += "search/s/";
     41        url3 += "search/im/or";
     42        ConcurrentHashMap<String, Double> hash = new ConcurrentHashMap<>();
     43        hash.put("min_lat", minLatLon.lat());
     44        hash.put("min_lon", minLatLon.lon());
     45        hash.put("max_lat", maxLatLon.lat());
     46        hash.put("max_lon", maxLatLon.lon());
     47        url1 += buildParameters(hash);
     48        url2 += buildParameters(hash);
     49        url3 += buildParameters(hash);
     50        System.out.println(url2);
    6351
    64         private String buildParameters(ConcurrentHashMap<String, Double> hash) {
    65                 String ret = "?client_id=" + CLIENT_ID;
    66                 for (int i = 0; i < parameters.length; i++)
    67                         if (hash.get(parameters[i]) != null)
    68                                 ret += "&" + parameters[i] + "=" + hash.get(parameters[i]);
    69                 return ret;
    70         }
     52        try {
     53            Main.info("MapillaryPlugin GET " + url2);
     54            Main.worker.submit(new MapillarySquareDownloadManagerThread(url1,
     55                    url2, url3));
     56        } catch (Exception e) {
     57            Main.error(e);
     58        }
     59    }
     60
     61    public void getImages(Bounds bounds) {
     62        getImages(bounds.getMin(), bounds.getMax());
     63    }
     64
     65    private String buildParameters(ConcurrentHashMap<String, Double> hash) {
     66        String ret = "?client_id=" + CLIENT_ID;
     67        for (int i = 0; i < parameters.length; i++)
     68            if (hash.get(parameters[i]) != null)
     69                ret += "&" + parameters[i] + "=" + hash.get(parameters[i]);
     70        return ret;
     71    }
    7172}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportDownloadThread.java

    r31252 r31278  
    2525 */
    2626public class MapillaryExportDownloadThread implements Runnable,
    27                 ICachedLoaderListener {
     27        ICachedLoaderListener {
    2828
    29         String url;
    30         ArrayBlockingQueue<BufferedImage> queue;
    31         ArrayBlockingQueue<MapillaryAbstractImage> queueImages;
     29    String url;
     30    ArrayBlockingQueue<BufferedImage> queue;
     31    ArrayBlockingQueue<MapillaryAbstractImage> queueImages;
    3232
    33         ProgressMonitor monitor;
    34         MapillaryImage image;
     33    ProgressMonitor monitor;
     34    MapillaryImage image;
    3535
    36         public MapillaryExportDownloadThread(MapillaryImage image,
    37                         ArrayBlockingQueue<BufferedImage> queue,
    38                         ArrayBlockingQueue<MapillaryAbstractImage> queueImages) {
    39                 url = "https://d1cuyjsrcm0gby.cloudfront.net/" + image.getKey()
    40                                 + "/thumb-2048.jpg";
    41                 this.queue = queue;
    42                 this.image = image;
    43                 this.queueImages = queueImages;
    44         }
     36    public MapillaryExportDownloadThread(MapillaryImage image,
     37            ArrayBlockingQueue<BufferedImage> queue,
     38            ArrayBlockingQueue<MapillaryAbstractImage> queueImages) {
     39        url = "https://d1cuyjsrcm0gby.cloudfront.net/" + image.getKey()
     40                + "/thumb-2048.jpg";
     41        this.queue = queue;
     42        this.image = image;
     43        this.queueImages = queueImages;
     44    }
    4545
    46         @Override
    47         public void run() {
    48                 new MapillaryCache(image.getKey(), MapillaryCache.Type.FULL_IMAGE).submit(this,
    49                                 false);
     46    @Override
     47    public void run() {
     48        new MapillaryCache(image.getKey(), MapillaryCache.Type.FULL_IMAGE)
     49                .submit(this, false);
    5050
    51         }
     51    }
    5252
    53         @Override
    54         public void loadingFinished(CacheEntry data,
    55                         CacheEntryAttributes attributes, LoadResult result) {
    56                 try {
    57                         queue.put(ImageIO.read(new ByteArrayInputStream(data.getContent())));
    58                         queueImages.put(image);
     53    @Override
     54    public void loadingFinished(CacheEntry data,
     55            CacheEntryAttributes attributes, LoadResult result) {
     56        try {
     57            queue.put(ImageIO.read(new ByteArrayInputStream(data.getContent())));
     58            queueImages.put(image);
    5959
    60                 } catch (InterruptedException e) {
    61                         Main.error(e);
    62                 } catch (IOException e) {
    63                         Main.error(e);
    64                 }
    65         }
     60        } catch (InterruptedException e) {
     61            Main.error(e);
     62        } catch (IOException e) {
     63            Main.error(e);
     64        }
     65    }
    6666}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportManager.java

    r31277 r31278  
    3232public class MapillaryExportManager extends PleaseWaitRunnable {
    3333
    34         ArrayBlockingQueue<BufferedImage> queue;
    35         ArrayBlockingQueue<MapillaryAbstractImage> queueImages;
     34    ArrayBlockingQueue<BufferedImage> queue;
     35    ArrayBlockingQueue<MapillaryAbstractImage> queueImages;
    3636
    37         final int amount;
    38         List<MapillaryAbstractImage> images;
    39         String path;
     37    final int amount;
     38    List<MapillaryAbstractImage> images;
     39    String path;
    4040
    41         public MapillaryExportManager(List<MapillaryAbstractImage> images,
    42                         String path) {
    43                 super(tr("Downloading") + "...", new PleaseWaitProgressMonitor(
    44                                 "Exporting Mapillary Images"), true);
    45                 queue = new ArrayBlockingQueue<>(10);
    46                 queueImages = new ArrayBlockingQueue<>(10);
     41    public MapillaryExportManager(List<MapillaryAbstractImage> images,
     42            String path) {
     43        super(tr("Downloading") + "...", new PleaseWaitProgressMonitor(
     44                "Exporting Mapillary Images"), true);
     45        queue = new ArrayBlockingQueue<>(10);
     46        queueImages = new ArrayBlockingQueue<>(10);
    4747
    48                 this.images = images;
    49                 amount = images.size();
    50                 this.path = path;
    51         }
    52        
    53         /**
    54          * Constructor used to rewrite imported images.
    55          * @param images
    56          * @throws IOException
    57          */
    58         public MapillaryExportManager(List<MapillaryImportedImage> images) throws IOException {
    59                 super(tr("Downloading") + "...", new PleaseWaitProgressMonitor(
    60                                 "Exporting Mapillary Images"), true);
    61                 queue = new ArrayBlockingQueue<>(10);
    62                 queueImages = new ArrayBlockingQueue<>(10);
    63                 for (MapillaryImportedImage image : images) {
    64                         queue.add(image.getImage());
    65                         queueImages.add(image);
    66                 }
    67                 amount = images.size();         
    68         }
     48        this.images = images;
     49        amount = images.size();
     50        this.path = path;
     51    }
    6952
    70         @Override
    71         protected void cancel() {
    72                 // TODO Auto-generated method stub
    73         }
     53    /**
     54     * Constructor used to rewrite imported images.
     55     *
     56     * @param images
     57     * @throws IOException
     58     */
     59    public MapillaryExportManager(List<MapillaryImportedImage> images)
     60            throws IOException {
     61        super(tr("Downloading") + "...", new PleaseWaitProgressMonitor(
     62                "Exporting Mapillary Images"), true);
     63        queue = new ArrayBlockingQueue<>(10);
     64        queueImages = new ArrayBlockingQueue<>(10);
     65        for (MapillaryImportedImage image : images) {
     66            queue.add(image.getImage());
     67            queueImages.add(image);
     68        }
     69        amount = images.size();
     70    }
    7471
    75         @Override
    76         protected void realRun() throws SAXException, IOException,
    77                         OsmTransferException {
    78                 // Starts a writer thread in order to write the pictures on the disk.
    79                 Thread writer = new Thread(new MapillaryExportWriterThread(path, queue,
    80                                 queueImages, amount, this.getProgressMonitor()));
    81                 writer.start();
    82                 if (path == null) {
    83                         try {
    84                                 writer.join();
    85                         } catch (InterruptedException e) {
    86                                 Main.error(e);
    87                         }
    88                         return;
    89                 }
    90                 ThreadPoolExecutor ex = new ThreadPoolExecutor(20, 35, 25,
    91                                 TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10));
    92                 for (MapillaryAbstractImage image : images) {
    93                         if (image instanceof MapillaryImage) {
    94                                 try {
    95                                         ex.execute(new MapillaryExportDownloadThread(
    96                                                         (MapillaryImage) image, queue, queueImages));
    97                                 } catch (Exception e) {
    98                                         Main.error(e);
    99                                 }
    100                         } else if (image instanceof MapillaryImportedImage) {
    101                                 try {
    102                                         queue.put(((MapillaryImportedImage) image).getImage());
    103                                         queueImages.put((MapillaryImportedImage) image);
    104                                 } catch (InterruptedException e) {
    105                                         Main.error(e);
    106                                 }
    107                         }
    108                         try {
    109                                 // If the queue is full, waits for it to have more space
    110                                 // available before executing anything else.
    111                                 while (ex.getQueue().remainingCapacity() == 0)
    112                                         Thread.sleep(100);
    113                         } catch (Exception e) {
    114                                 Main.error(e);
    115                         }
    116                 }
    117                 try {
    118                         writer.join();
    119                 } catch (InterruptedException e) {
    120                         Main.error(e);
    121                 }
     72    @Override
     73    protected void cancel() {
     74        // TODO Auto-generated method stub
     75    }
    12276
    123         }
     77    @Override
     78    protected void realRun() throws SAXException, IOException,
     79            OsmTransferException {
     80        // Starts a writer thread in order to write the pictures on the disk.
     81        Thread writer = new Thread(new MapillaryExportWriterThread(path, queue,
     82                queueImages, amount, this.getProgressMonitor()));
     83        writer.start();
     84        if (path == null) {
     85            try {
     86                writer.join();
     87            } catch (InterruptedException e) {
     88                Main.error(e);
     89            }
     90            return;
     91        }
     92        ThreadPoolExecutor ex = new ThreadPoolExecutor(20, 35, 25,
     93                TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10));
     94        for (MapillaryAbstractImage image : images) {
     95            if (image instanceof MapillaryImage) {
     96                try {
     97                    ex.execute(new MapillaryExportDownloadThread(
     98                            (MapillaryImage) image, queue, queueImages));
     99                } catch (Exception e) {
     100                    Main.error(e);
     101                }
     102            } else if (image instanceof MapillaryImportedImage) {
     103                try {
     104                    queue.put(((MapillaryImportedImage) image).getImage());
     105                    queueImages.put((MapillaryImportedImage) image);
     106                } catch (InterruptedException e) {
     107                    Main.error(e);
     108                }
     109            }
     110            try {
     111                // If the queue is full, waits for it to have more space
     112                // available before executing anything else.
     113                while (ex.getQueue().remainingCapacity() == 0)
     114                    Thread.sleep(100);
     115            } catch (Exception e) {
     116                Main.error(e);
     117            }
     118        }
     119        try {
     120            writer.join();
     121        } catch (InterruptedException e) {
     122            Main.error(e);
     123        }
    124124
    125         @Override
    126         protected void finish() {
    127                 // TODO Auto-generated method stub
    128         }
     125    }
     126
     127    @Override
     128    protected void finish() {
     129        // TODO Auto-generated method stub
     130    }
    129131}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportWriterThread.java

    r31277 r31278  
    3434public class MapillaryExportWriterThread implements Runnable {
    3535
    36         private final String path;
    37         private final ArrayBlockingQueue<BufferedImage> queue;
    38         private final ArrayBlockingQueue<MapillaryAbstractImage> queueImages;
    39         private final int amount;
    40         private final ProgressMonitor monitor;
     36    private final String path;
     37    private final ArrayBlockingQueue<BufferedImage> queue;
     38    private final ArrayBlockingQueue<MapillaryAbstractImage> queueImages;
     39    private final int amount;
     40    private final ProgressMonitor monitor;
    4141
    42         public MapillaryExportWriterThread(String path,
    43                         ArrayBlockingQueue<BufferedImage> queue,
    44                         ArrayBlockingQueue<MapillaryAbstractImage> queueImages, int amount,
    45                         ProgressMonitor monitor) {
    46                 this.path = path;
    47                 this.queue = queue;
    48                 this.queueImages = queueImages;
    49                 this.amount = amount;
    50                 this.monitor = monitor;
    51         }
     42    public MapillaryExportWriterThread(String path,
     43            ArrayBlockingQueue<BufferedImage> queue,
     44            ArrayBlockingQueue<MapillaryAbstractImage> queueImages, int amount,
     45            ProgressMonitor monitor) {
     46        this.path = path;
     47        this.queue = queue;
     48        this.queueImages = queueImages;
     49        this.amount = amount;
     50        this.monitor = monitor;
     51    }
    5252
    53         @Override
    54         public void run() {
    55                 monitor.setCustomText("Downloaded 0/" + amount);
    56                 File tempFile = null;
    57                 BufferedImage img;
    58                 MapillaryAbstractImage mimg = null;
    59                 String finalPath = "";
    60                 for (int i = 0; i < amount; i++) {
    61                         try {
    62                                 img = queue.take();
    63                                 mimg = queueImages.take();
    64                                 if (path == null && mimg instanceof MapillaryImportedImage) {
    65                                         String path = ((MapillaryImportedImage) mimg).getFile()
    66                                                         .getPath();
    67                                         finalPath = path.substring(0, path.lastIndexOf('.'));
    68                                 } else if (mimg instanceof MapillaryImage)
    69                                         finalPath = path + "/" + ((MapillaryImage) mimg).getKey();
    70                                 else
    71                                         finalPath = path + "/" + i;
    72                                 // Creates a temporal file that is going to be deleted after
    73                                 // writing the EXIF tags.
    74                                 tempFile = new File(finalPath + ".tmp");
    75                                 ImageIO.write(img, "jpg", tempFile);
     53    @Override
     54    public void run() {
     55        monitor.setCustomText("Downloaded 0/" + amount);
     56        File tempFile = null;
     57        BufferedImage img;
     58        MapillaryAbstractImage mimg = null;
     59        String finalPath = "";
     60        for (int i = 0; i < amount; i++) {
     61            try {
     62                img = queue.take();
     63                mimg = queueImages.take();
     64                if (path == null && mimg instanceof MapillaryImportedImage) {
     65                    String path = ((MapillaryImportedImage) mimg).getFile()
     66                            .getPath();
     67                    finalPath = path.substring(0, path.lastIndexOf('.'));
     68                } else if (mimg instanceof MapillaryImage)
     69                    finalPath = path + "/" + ((MapillaryImage) mimg).getKey();
     70                else
     71                    finalPath = path + "/" + i;
     72                // Creates a temporal file that is going to be deleted after
     73                // writing the EXIF tags.
     74                tempFile = new File(finalPath + ".tmp");
     75                ImageIO.write(img, "jpg", tempFile);
    7676
    77                                 // Write EXIF tags
    78                                 TiffOutputSet outputSet = new TiffOutputSet();
    79                                 TiffOutputDirectory exifDirectory = outputSet.getOrCreateExifDirectory();
    80                                 exifDirectory
    81                                                 .add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF,
    82                                                                 GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF_VALUE_TRUE_NORTH);
    83                                 exifDirectory.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION,
    84                                                 RationalNumber.valueOf(mimg.getCa()));
    85                                 if (mimg instanceof MapillaryImportedImage) {
    86                                         exifDirectory.add(
    87                                                         ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL,
    88                                                         ((MapillaryImportedImage) mimg).datetimeOriginal);
    89                                 }
    90                                 else if (mimg instanceof MapillaryImage)
    91                                         exifDirectory.add(
    92                                                         ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL,
    93                                                         ((MapillaryImage) mimg).getDate("yyyy/MM/dd hh/mm/ss"));
    94                                 outputSet.setGPSInDegrees(mimg.getLatLon().lon(), mimg
    95                                                 .getLatLon().lat());
    96                                 OutputStream os = new BufferedOutputStream(
    97                                                 new FileOutputStream(finalPath + ".jpg"));
    98                                 new ExifRewriter().updateExifMetadataLossless(tempFile, os,
    99                                                 outputSet);
    100                                 tempFile.delete();
    101                                 os.close();
    102                         } catch (InterruptedException e) {
    103                                 Main.error(e);
    104                         } catch (IOException e) {
    105                                 Main.error(e);
    106                         } catch (ImageWriteException e) {
    107                                 Main.error(e);
    108                         } catch (ImageReadException e) {
    109                                 Main.error(e);
    110                         }
     77                // Write EXIF tags
     78                TiffOutputSet outputSet = new TiffOutputSet();
     79                TiffOutputDirectory exifDirectory = outputSet
     80                        .getOrCreateExifDirectory();
     81                exifDirectory
     82                        .add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF,
     83                                GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF_VALUE_TRUE_NORTH);
     84                exifDirectory.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION,
     85                        RationalNumber.valueOf(mimg.getCa()));
     86                if (mimg instanceof MapillaryImportedImage) {
     87                    exifDirectory.add(
     88                            ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL,
     89                            ((MapillaryImportedImage) mimg).datetimeOriginal);
     90                } else if (mimg instanceof MapillaryImage)
     91                    exifDirectory.add(
     92                            ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL,
     93                            ((MapillaryImage) mimg)
     94                                    .getDate("yyyy/MM/dd hh/mm/ss"));
     95                outputSet.setGPSInDegrees(mimg.getLatLon().lon(), mimg
     96                        .getLatLon().lat());
     97                OutputStream os = new BufferedOutputStream(
     98                        new FileOutputStream(finalPath + ".jpg"));
     99                new ExifRewriter().updateExifMetadataLossless(tempFile, os,
     100                        outputSet);
     101                tempFile.delete();
     102                os.close();
     103            } catch (InterruptedException e) {
     104                Main.error(e);
     105            } catch (IOException e) {
     106                Main.error(e);
     107            } catch (ImageWriteException e) {
     108                Main.error(e);
     109            } catch (ImageReadException e) {
     110                Main.error(e);
     111            }
    111112
    112                         // Increases the progress bar.
    113                         monitor.worked(PleaseWaitProgressMonitor.PROGRESS_BAR_MAX / amount);
    114                         monitor.setCustomText("Downloaded " + (i + 1) + "/" + amount);
    115                 }
    116         }
     113            // Increases the progress bar.
     114            monitor.worked(PleaseWaitProgressMonitor.PROGRESS_BAR_MAX / amount);
     115            monitor.setCustomText("Downloaded " + (i + 1) + "/" + amount);
     116        }
     117    }
    117118}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryImageInfoDownloaderThread.java

    r31267 r31278  
    2525 */
    2626public class MapillaryImageInfoDownloaderThread implements Runnable {
    27         private final String url;
    28         private final ExecutorService ex;
     27    private final String url;
     28    private final ExecutorService ex;
    2929
    30         public MapillaryImageInfoDownloaderThread(ExecutorService ex, String url) {
    31                 this.ex = ex;
    32                 this.url = url;
    33         }
     30    public MapillaryImageInfoDownloaderThread(ExecutorService ex, String url) {
     31        this.ex = ex;
     32        this.url = url;
     33    }
    3434
    35         public void run() {
    36                 try {
    37                         BufferedReader br = new BufferedReader(new InputStreamReader(
    38                                         new URL(url).openStream()));
    39                         JsonObject jsonobj = Json.createReader(br).readObject();
    40                         if (!jsonobj.getBoolean("more"))
    41                                 ex.shutdown();
    42                         JsonArray jsonarr = jsonobj.getJsonArray("ims");
    43                         JsonObject data;
    44                         for (int i = 0; i < jsonarr.size(); i++) {
    45                                 data = jsonarr.getJsonObject(i);
    46                                 String key = data.getString("key");
    47                                 for (MapillaryAbstractImage image : MapillaryData.getInstance()
    48                                                 .getImages()) {
    49                                         if (image instanceof MapillaryImage) {
    50                                                 if (((MapillaryImage) image).getKey().equals(key)) {
    51                                                         ((MapillaryImage) image).setUser(data
    52                                                                         .getString("user"));
    53                                                         ((MapillaryImage) image).setCapturedAt(data
    54                                                                         .getJsonNumber("captured_at").longValue());
    55                                                         ((MapillaryImage) image).setLocation(data
    56                                                                         .getString("location"));
    57                                                 }
    58                                         }
    59                                 }
    60                         }
    61                 } catch (MalformedURLException e) {
    62                         Main.error(e);
    63                 } catch (IOException e) {
    64                         Main.error(e);
    65                 }
    66         }
     35    public void run() {
     36        try {
     37            BufferedReader br = new BufferedReader(new InputStreamReader(
     38                    new URL(url).openStream()));
     39            JsonObject jsonobj = Json.createReader(br).readObject();
     40            if (!jsonobj.getBoolean("more"))
     41                ex.shutdown();
     42            JsonArray jsonarr = jsonobj.getJsonArray("ims");
     43            JsonObject data;
     44            for (int i = 0; i < jsonarr.size(); i++) {
     45                data = jsonarr.getJsonObject(i);
     46                String key = data.getString("key");
     47                for (MapillaryAbstractImage image : MapillaryData.getInstance()
     48                        .getImages()) {
     49                    if (image instanceof MapillaryImage) {
     50                        if (((MapillaryImage) image).getKey().equals(key)) {
     51                            ((MapillaryImage) image).setUser(data
     52                                    .getString("user"));
     53                            ((MapillaryImage) image).setCapturedAt(data
     54                                    .getJsonNumber("captured_at").longValue());
     55                            ((MapillaryImage) image).setLocation(data
     56                                    .getString("location"));
     57                        }
     58                    }
     59                }
     60            }
     61        } catch (MalformedURLException e) {
     62            Main.error(e);
     63        } catch (IOException e) {
     64            Main.error(e);
     65        }
     66    }
    6767}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySequenceDownloadThread.java

    r31277 r31278  
    3232public class MapillarySequenceDownloadThread implements Runnable {
    3333
    34         private String url;
    35         private ExecutorService ex;
    36         private List<Bounds> bounds;
     34    private String url;
     35    private ExecutorService ex;
     36    private List<Bounds> bounds;
    3737
    38         public MapillarySequenceDownloadThread(ExecutorService ex, String url) {
    39                 this.url = url;
    40                 this.ex = ex;
    41                 this.bounds = MapillaryLayer.getInstance().bounds;
    42         }
     38    public MapillarySequenceDownloadThread(ExecutorService ex, String url) {
     39        this.url = url;
     40        this.ex = ex;
     41        this.bounds = MapillaryLayer.getInstance().bounds;
     42    }
    4343
    44         public void run() {
    45                 try {
    46                         BufferedReader br;
    47                         br = new BufferedReader(new InputStreamReader(
    48                                         new URL(url).openStream()));
    49                         JsonObject jsonall = Json.createReader(br).readObject();
     44    public void run() {
     45        try {
     46            BufferedReader br;
     47            br = new BufferedReader(new InputStreamReader(
     48                    new URL(url).openStream()));
     49            JsonObject jsonall = Json.createReader(br).readObject();
    5050
    51                         if (!jsonall.getBoolean("more") && !ex.isShutdown())
    52                                 ex.shutdown();
    53                         JsonArray jsonseq = jsonall.getJsonArray("ss");
    54                         // At the moment there is a bug with some sequences at Mapillay API,
    55                         // so if they are wrong he use this variable to skip them.
    56                         boolean isSequenceWrong = false;
    57                         for (int i = 0; i < jsonseq.size(); i++) {
    58                                 JsonObject jsonobj = jsonseq.getJsonObject(i);
    59                                 JsonArray cas = jsonobj.getJsonArray("cas");
    60                                 JsonArray coords = jsonobj.getJsonArray("coords");
    61                                 JsonArray keys = jsonobj.getJsonArray("keys");
    62                                 ArrayList<MapillaryImage> images = new ArrayList<>();
    63                                 for (int j = 0; j < cas.size(); j++) {
    64                                         try {
    65                                                 images.add(new MapillaryImage(keys.getString(j),
    66                                                                 coords.getJsonArray(j).getJsonNumber(1)
    67                                                                                 .doubleValue(), coords.getJsonArray(j)
    68                                                                                 .getJsonNumber(0).doubleValue(), cas
    69                                                                                 .getJsonNumber(j).doubleValue()));
    70                                         } catch (IndexOutOfBoundsException e) {
    71                                                 Main.warn("Mapillary bug at " + url);
    72                                                 isSequenceWrong = true;
    73                                         }
    74                                 }
    75                                 if (isSequenceWrong)
    76                                         break;
    77                                 MapillarySequence sequence = new MapillarySequence(
    78                                                 jsonobj.getString("key"), jsonobj.getJsonNumber(
    79                                                                 "captured_at").longValue());
    80                                                                
    81                                 int first = -1;
    82                                 int last = -1;
    83                                 int pos = 0;
     51            if (!jsonall.getBoolean("more") && !ex.isShutdown())
     52                ex.shutdown();
     53            JsonArray jsonseq = jsonall.getJsonArray("ss");
     54            // At the moment there is a bug with some sequences at Mapillay API,
     55            // so if they are wrong he use this variable to skip them.
     56            boolean isSequenceWrong = false;
     57            for (int i = 0; i < jsonseq.size(); i++) {
     58                JsonObject jsonobj = jsonseq.getJsonObject(i);
     59                JsonArray cas = jsonobj.getJsonArray("cas");
     60                JsonArray coords = jsonobj.getJsonArray("coords");
     61                JsonArray keys = jsonobj.getJsonArray("keys");
     62                ArrayList<MapillaryImage> images = new ArrayList<>();
     63                for (int j = 0; j < cas.size(); j++) {
     64                    try {
     65                        images.add(new MapillaryImage(keys.getString(j),
     66                                coords.getJsonArray(j).getJsonNumber(1)
     67                                        .doubleValue(), coords.getJsonArray(j)
     68                                        .getJsonNumber(0).doubleValue(), cas
     69                                        .getJsonNumber(j).doubleValue()));
     70                    } catch (IndexOutOfBoundsException e) {
     71                        Main.warn("Mapillary bug at " + url);
     72                        isSequenceWrong = true;
     73                    }
     74                }
     75                if (isSequenceWrong)
     76                    break;
     77                MapillarySequence sequence = new MapillarySequence(
     78                        jsonobj.getString("key"), jsonobj.getJsonNumber(
     79                                "captured_at").longValue());
    8480
    85                                 // Here it gets only those images which are in the downloaded
    86                                 // area.
    87                                 for (MapillaryAbstractImage img : images) {
    88                                         if (first == -1 && isInside(img))
    89                                                 first = pos;
    90                                         else if (first != -1 && last == -1
    91                                                         && !isInside(img))
    92                                                 last = pos;
    93                                         else if (last != -1 && isInside(img))
    94                                                 last = -1;
    95                                         pos++;
    96                                 }
    97                                 if (last == -1) {
    98                                         last = pos;
    99                                 }
    100                                 if (first == -1)
    101                                         continue;
    102                                 List<MapillaryImage> finalImages = images.subList(first, last);
    103                                 for (MapillaryImage img : finalImages) {
    104                                         MapillaryData.getInstance().getImages().remove(img);
    105                                         img.setSequence(sequence);
    106                                 }
    107                                 MapillaryData.getInstance().addWithoutUpdate(
    108                                                 new ArrayList<MapillaryAbstractImage>(finalImages));
    109                                 sequence.add(finalImages);
    110                         }
    111                 } catch (IOException e) {
    112                         Main.error("Error reading the url " + url
    113                                         + " might be a Mapillary problem.");
    114                 }
    115         }
    116        
    117         private boolean isInside(MapillaryAbstractImage image) {
    118                 for (int i = 0; i < bounds.size(); i++) {
    119                         if (bounds.get(i).contains(image.getLatLon()))
    120                                 return true;
    121                 }
    122                 return false;
    123         }
     81                int first = -1;
     82                int last = -1;
     83                int pos = 0;
     84
     85                // Here it gets only those images which are in the downloaded
     86                // area.
     87                for (MapillaryAbstractImage img : images) {
     88                    if (first == -1 && isInside(img))
     89                        first = pos;
     90                    else if (first != -1 && last == -1 && !isInside(img))
     91                        last = pos;
     92                    else if (last != -1 && isInside(img))
     93                        last = -1;
     94                    pos++;
     95                }
     96                if (last == -1) {
     97                    last = pos;
     98                }
     99                if (first == -1)
     100                    continue;
     101                List<MapillaryImage> finalImages = images.subList(first, last);
     102                for (MapillaryImage img : finalImages) {
     103                    MapillaryData.getInstance().getImages().remove(img);
     104                    img.setSequence(sequence);
     105                }
     106                MapillaryData.getInstance().addWithoutUpdate(
     107                        new ArrayList<MapillaryAbstractImage>(finalImages));
     108                sequence.add(finalImages);
     109            }
     110        } catch (IOException e) {
     111            Main.error("Error reading the url " + url
     112                    + " might be a Mapillary problem.");
     113        }
     114    }
     115
     116    private boolean isInside(MapillaryAbstractImage image) {
     117        for (int i = 0; i < bounds.size(); i++) {
     118            if (bounds.get(i).contains(image.getLatLon()))
     119                return true;
     120        }
     121        return false;
     122    }
    124123}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySignDownloaderThread.java

    r31277 r31278  
    1919public class MapillarySignDownloaderThread implements Runnable {
    2020
    21         private final String url;
    22         private final ExecutorService ex;
     21    private final String url;
     22    private final ExecutorService ex;
    2323
    24         public MapillarySignDownloaderThread(ExecutorService ex, String url) {
    25                 this.ex = ex;
    26                 this.url = url;
    27         }
     24    public MapillarySignDownloaderThread(ExecutorService ex, String url) {
     25        this.ex = ex;
     26        this.url = url;
     27    }
    2828
    29         @Override
    30         public void run() {
    31                 BufferedReader br;
    32                 try {
    33                         br = new BufferedReader(new InputStreamReader(
    34                                         new URL(url).openStream()));
    35                         JsonObject jsonobj = Json.createReader(br).readObject();
    36                         if (!jsonobj.getBoolean("more")) {
    37                                 ex.shutdown();
    38                         }
    39                         JsonArray jsonarr = jsonobj.getJsonArray("ims");
    40                         for (int i = 0; i < jsonarr.size(); i++) {
    41                                 JsonArray rects = jsonarr.getJsonObject(i)
    42                                                 .getJsonArray("rects");
    43                                 JsonArray rectversions = jsonarr.getJsonObject(i).getJsonArray(
    44                                                 "rectversions");
    45                                 String key = jsonarr.getJsonObject(i).getString("key");
    46                                 if (rectversions != null) {
    47                                         for (int j = 0; j < rectversions.size(); j++) {
    48                                                 rects = rectversions.getJsonObject(j).getJsonArray("rects");
    49                                                 for (int k = 0; k < rects.size(); k++) {
    50                                                         JsonObject data = rects.getJsonObject(k);
    51                                                         for (MapillaryAbstractImage image : MapillaryData
    52                                                                         .getInstance().getImages())
    53                                                                 if (image instanceof MapillaryImage
    54                                                                                 && ((MapillaryImage) image).getKey()
    55                                                                                                 .equals(key))
    56                                                                         ((MapillaryImage) image).addSign(data
    57                                                                                         .getString("type"));
    58                                                 }
    59                                         }
    60                                 }
     29    @Override
     30    public void run() {
     31        BufferedReader br;
     32        try {
     33            br = new BufferedReader(new InputStreamReader(
     34                    new URL(url).openStream()));
     35            JsonObject jsonobj = Json.createReader(br).readObject();
     36            if (!jsonobj.getBoolean("more")) {
     37                ex.shutdown();
     38            }
     39            JsonArray jsonarr = jsonobj.getJsonArray("ims");
     40            for (int i = 0; i < jsonarr.size(); i++) {
     41                JsonArray rects = jsonarr.getJsonObject(i)
     42                        .getJsonArray("rects");
     43                JsonArray rectversions = jsonarr.getJsonObject(i).getJsonArray(
     44                        "rectversions");
     45                String key = jsonarr.getJsonObject(i).getString("key");
     46                if (rectversions != null) {
     47                    for (int j = 0; j < rectversions.size(); j++) {
     48                        rects = rectversions.getJsonObject(j).getJsonArray(
     49                                "rects");
     50                        for (int k = 0; k < rects.size(); k++) {
     51                            JsonObject data = rects.getJsonObject(k);
     52                            for (MapillaryAbstractImage image : MapillaryData
     53                                    .getInstance().getImages())
     54                                if (image instanceof MapillaryImage
     55                                        && ((MapillaryImage) image).getKey()
     56                                                .equals(key))
     57                                    ((MapillaryImage) image).addSign(data
     58                                            .getString("type"));
     59                        }
     60                    }
     61                }
    6162
    62                                 // Just one sign on the picture
    63                                 else if (rects != null) {
    64                                         for (int j = 0; j < rects.size(); j++) {
    65                                                 JsonObject data = rects.getJsonObject(j);
    66                                                 for (MapillaryAbstractImage image : MapillaryData
    67                                                                 .getInstance().getImages())
    68                                                         if (image instanceof MapillaryImage
    69                                                                         && ((MapillaryImage) image).getKey()
    70                                                                                         .equals(key))
    71                                                                 ((MapillaryImage) image).addSign(data
    72                                                                                 .getString("type"));
    73                                         }
    74                                 }
    75                         }
    76                 } catch (MalformedURLException e) {
    77                         Main.error(e);
    78                 } catch (IOException e) {
    79                         Main.error(e);
    80                 }
    81         }
     63                // Just one sign on the picture
     64                else if (rects != null) {
     65                    for (int j = 0; j < rects.size(); j++) {
     66                        JsonObject data = rects.getJsonObject(j);
     67                        for (MapillaryAbstractImage image : MapillaryData
     68                                .getInstance().getImages())
     69                            if (image instanceof MapillaryImage
     70                                    && ((MapillaryImage) image).getKey()
     71                                            .equals(key))
     72                                ((MapillaryImage) image).addSign(data
     73                                        .getString("type"));
     74                    }
     75                }
     76            }
     77        } catch (MalformedURLException e) {
     78            Main.error(e);
     79        } catch (IOException e) {
     80            Main.error(e);
     81        }
     82    }
    8283}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySquareDownloadManagerThread.java

    r31277 r31278  
    2121public class MapillarySquareDownloadManagerThread implements Runnable {
    2222
    23         private final String urlImages;
    24         private final String urlSequences;
    25         private final String urlSigns;
     23    private final String urlImages;
     24    private final String urlSequences;
     25    private final String urlSigns;
    2626
    27         public MapillarySquareDownloadManagerThread(String urlImages,
    28                         String urlSequences, String urlSigns) {
    29                 this.urlImages = urlImages;
    30                 this.urlSequences = urlSequences;
    31                 this.urlSigns = urlSigns;
    32         }
     27    public MapillarySquareDownloadManagerThread(String urlImages,
     28            String urlSequences, String urlSigns) {
     29        this.urlImages = urlImages;
     30        this.urlSequences = urlSequences;
     31        this.urlSigns = urlSigns;
     32    }
    3333
    34         public void run() {
    35                 Main.map.statusLine.setHelpText("Downloading images from Mapillary");
    36                 try {
    37                         downloadSequences();
    38                         Main.map.statusLine.setHelpText("Downloading image's information");
    39                         completeImages();
    40                         Main.map.statusLine.setHelpText("Downloading signs");
    41                         downloadSigns();
    42                 } catch (InterruptedException e) {
    43                         Main.error(e);
    44                 }
    45                 if (MapillaryData.getInstance().getImages().size() > 0)
    46                         Main.map.statusLine.setHelpText(tr("Total images: ")
    47                                         + MapillaryData.getInstance().getImages().size());
    48                 else
    49                         Main.map.statusLine.setHelpText(tr("No images found"));
    50                 MapillaryData.getInstance().dataUpdated();
    51         }
     34    public void run() {
     35        Main.map.statusLine.setHelpText("Downloading images from Mapillary");
     36        try {
     37            downloadSequences();
     38            Main.map.statusLine.setHelpText("Downloading image's information");
     39            completeImages();
     40            Main.map.statusLine.setHelpText("Downloading signs");
     41            downloadSigns();
     42        } catch (InterruptedException e) {
     43            Main.error(e);
     44        }
     45        if (MapillaryData.getInstance().getImages().size() > 0)
     46            Main.map.statusLine.setHelpText(tr("Total images: ")
     47                    + MapillaryData.getInstance().getImages().size());
     48        else
     49            Main.map.statusLine.setHelpText(tr("No images found"));
     50        MapillaryData.getInstance().dataUpdated();
     51    }
    5252
    53         private void downloadSequences() throws InterruptedException {
    54                 ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
    55                                 TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
    56                 int page = 0;
    57                 while (!ex.isShutdown()) {
    58                         ex.execute(new MapillarySequenceDownloadThread(ex, urlSequences
    59                                         + "&page=" + page + "&limit=1"));
    60                         while (ex.getQueue().remainingCapacity() == 0)
    61                                 Thread.sleep(100);
    62                         page++;
    63                 }
    64                 ex.awaitTermination(15, TimeUnit.SECONDS);
    65                 MapillaryData.getInstance().dataUpdated();
    66         }
     53    private void downloadSequences() throws InterruptedException {
     54        ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
     55                TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
     56        int page = 0;
     57        while (!ex.isShutdown()) {
     58            ex.execute(new MapillarySequenceDownloadThread(ex, urlSequences
     59                    + "&page=" + page + "&limit=1"));
     60            while (ex.getQueue().remainingCapacity() == 0)
     61                Thread.sleep(100);
     62            page++;
     63        }
     64        ex.awaitTermination(15, TimeUnit.SECONDS);
     65        MapillaryData.getInstance().dataUpdated();
     66    }
    6767
    68         private void completeImages() throws InterruptedException {
    69                 ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
    70                                 TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
    71                 int page = 0;
    72                 while (!ex.isShutdown()) {
    73                         ex.execute(new MapillaryImageInfoDownloaderThread(ex, urlImages
    74                                         + "&page=" + page + "&limit=20"));
    75                         while (ex.getQueue().remainingCapacity() == 0)
    76                                 Thread.sleep(100);
    77                         page++;
    78                 }
    79                 ex.awaitTermination(15, TimeUnit.SECONDS);
    80         }
     68    private void completeImages() throws InterruptedException {
     69        ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
     70                TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
     71        int page = 0;
     72        while (!ex.isShutdown()) {
     73            ex.execute(new MapillaryImageInfoDownloaderThread(ex, urlImages
     74                    + "&page=" + page + "&limit=20"));
     75            while (ex.getQueue().remainingCapacity() == 0)
     76                Thread.sleep(100);
     77            page++;
     78        }
     79        ex.awaitTermination(15, TimeUnit.SECONDS);
     80    }
    8181
    82         private void downloadSigns() throws InterruptedException {
    83                 ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
    84                                 TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
    85                 int page = 0;
    86                 while (!ex.isShutdown()) {
    87                         ex.execute(new MapillarySignDownloaderThread(ex, urlSigns
    88                                         + "&page=" + page + "&limit=20"));
    89                         while (ex.getQueue().remainingCapacity() == 0)
    90                                 Thread.sleep(100);
    91                         page++;
    92                 }
    93                 ex.awaitTermination(15, TimeUnit.SECONDS);
    94         }
     82    private void downloadSigns() throws InterruptedException {
     83        ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
     84                TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
     85        int page = 0;
     86        while (!ex.isShutdown()) {
     87            ex.execute(new MapillarySignDownloaderThread(ex, urlSigns
     88                    + "&page=" + page + "&limit=20"));
     89            while (ex.getQueue().remainingCapacity() == 0)
     90                Thread.sleep(100);
     91            page++;
     92        }
     93        ex.awaitTermination(15, TimeUnit.SECONDS);
     94    }
    9595}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/HyperlinkLabel.java

    r31256 r31278  
    2121public class HyperlinkLabel extends JLabel implements ActionListener {
    2222
    23         private String text;
    24         private URL url;
     23    private String text;
     24    private URL url;
    2525
    26         /**
    27         * Creates a new HyperlinlLabel.
    28         */
    29         public HyperlinkLabel() {
    30                 super(tr("View in website"), SwingUtilities.RIGHT);
    31                 this.addActionListener(this);
    32                 setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
     26    /**
     27    * Creates a new HyperlinlLabel.
     28    */
     29    public HyperlinkLabel() {
     30        super(tr("View in website"), SwingUtilities.RIGHT);
     31        this.addActionListener(this);
     32        setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
    3333
    34                 enableEvents(MouseEvent.MOUSE_EVENT_MASK);
    35         }
     34        enableEvents(MouseEvent.MOUSE_EVENT_MASK);
     35    }
    3636
    37         /**
    38         * Sets the text of the label.
    39         */
    40         public void setText(String text) {
    41                 super.setText("<html><font color=\"#0000CF\" size=\"2\">" + text + "</font></html>"); //$NON-NLS-1$ //$NON-NLS-2$
    42                 this.text = text;
    43         }
     37    /**
     38    * Sets the text of the label.
     39    */
     40    public void setText(String text) {
     41        super.setText("<html><font color=\"#0000CF\" size=\"2\">" + text + "</font></html>"); //$NON-NLS-1$ //$NON-NLS-2$
     42        this.text = text;
     43    }
    4444
    45         /**
    46         * Sets a new URL, just pass the key of the image or null if there is none.
    47         *
    48         * @param key
    49         */
    50         public void setURL(String key) {
    51                 if (key == null) {
    52                         this.url = null;
    53                         return;
    54                 }
    55                 try {
    56                         this.url = new URL("http://www.mapillary.com/map/im/" + key);
    57                 } catch (MalformedURLException e) {
    58                         Main.error(e);
    59                 }
    60         }
     45    /**
     46    * Sets a new URL, just pass the key of the image or null if there is none.
     47    *
     48    * @param key
     49    */
     50    public void setURL(String key) {
     51        if (key == null) {
     52            this.url = null;
     53            return;
     54        }
     55        try {
     56            this.url = new URL("http://www.mapillary.com/map/im/" + key);
     57        } catch (MalformedURLException e) {
     58            Main.error(e);
     59        }
     60    }
    6161
    62         /**
    63         * Returns the text set by the user.
    64         */
    65         public String getNormalText() {
    66                 return text;
    67         }
     62    /**
     63    * Returns the text set by the user.
     64    */
     65    public String getNormalText() {
     66        return text;
     67    }
    6868
    69         /**
    70         * Processes mouse events and responds to clicks.
    71         */
    72         protected void processMouseEvent(MouseEvent evt) {
    73                 super.processMouseEvent(evt);
    74                 if (evt.getID() == MouseEvent.MOUSE_CLICKED)
    75                         fireActionPerformed(new ActionEvent(this,
    76                                         ActionEvent.ACTION_PERFORMED, getNormalText()));
    77         }
     69    /**
     70    * Processes mouse events and responds to clicks.
     71    */
     72    protected void processMouseEvent(MouseEvent evt) {
     73        super.processMouseEvent(evt);
     74        if (evt.getID() == MouseEvent.MOUSE_CLICKED)
     75            fireActionPerformed(new ActionEvent(this,
     76                    ActionEvent.ACTION_PERFORMED, getNormalText()));
     77    }
    7878
    79         /**
    80         * Adds an ActionListener to the list of listeners receiving notifications
    81         * when the label is clicked.
    82         */
    83         public void addActionListener(ActionListener listener) {
    84                 listenerList.add(ActionListener.class, listener);
    85         }
     79    /**
     80    * Adds an ActionListener to the list of listeners receiving notifications
     81    * when the label is clicked.
     82    */
     83    public void addActionListener(ActionListener listener) {
     84        listenerList.add(ActionListener.class, listener);
     85    }
    8686
    87         /**
    88         * Removes the given ActionListener from the list of listeners receiving
    89         * notifications when the label is clicked.
    90         */
    91         public void removeActionListener(ActionListener listener) {
    92                 listenerList.remove(ActionListener.class, listener);
    93         }
     87    /**
     88    * Removes the given ActionListener from the list of listeners receiving
     89    * notifications when the label is clicked.
     90    */
     91    public void removeActionListener(ActionListener listener) {
     92        listenerList.remove(ActionListener.class, listener);
     93    }
    9494
    95         /**
    96         * Fires an ActionEvent to all interested listeners.
    97         */
    98         protected void fireActionPerformed(ActionEvent evt) {
    99                 Object[] listeners = listenerList.getListenerList();
    100                 for (int i = 0; i < listeners.length; i += 2) {
    101                         if (listeners[i] == ActionListener.class) {
    102                                 ActionListener listener = (ActionListener) listeners[i + 1];
    103                                 listener.actionPerformed(evt);
    104                         }
    105                 }
    106         }
     95    /**
     96    * Fires an ActionEvent to all interested listeners.
     97    */
     98    protected void fireActionPerformed(ActionEvent evt) {
     99        Object[] listeners = listenerList.getListenerList();
     100        for (int i = 0; i < listeners.length; i += 2) {
     101            if (listeners[i] == ActionListener.class) {
     102                ActionListener listener = (ActionListener) listeners[i + 1];
     103                listener.actionPerformed(evt);
     104            }
     105        }
     106    }
    107107
    108         @Override
    109         public void actionPerformed(ActionEvent e) {
    110                 if (this.url == null)
    111                         return;
    112                 Desktop desktop = Desktop.getDesktop();
    113                 try {
    114                         desktop.browse(url.toURI());
    115                 } catch (IOException | URISyntaxException ex) {
    116                         ex.printStackTrace();
    117                 } catch (UnsupportedOperationException ex) {
    118                         Runtime runtime = Runtime.getRuntime();
    119                         try {
    120                                 runtime.exec("xdg-open " + url);
    121                         } catch (IOException exc) {
    122                                 exc.printStackTrace();
    123                         }
    124                 }
    125         }
     108    @Override
     109    public void actionPerformed(ActionEvent e) {
     110        if (this.url == null)
     111            return;
     112        Desktop desktop = Desktop.getDesktop();
     113        try {
     114            desktop.browse(url.toURI());
     115        } catch (IOException | URISyntaxException ex) {
     116            ex.printStackTrace();
     117        } catch (UnsupportedOperationException ex) {
     118            Runtime runtime = Runtime.getRuntime();
     119            try {
     120                runtime.exec("xdg-open " + url);
     121            } catch (IOException exc) {
     122                exc.printStackTrace();
     123            }
     124        }
     125    }
    126126}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryExportDialog.java

    r31260 r31278  
    2727public class MapillaryExportDialog extends JPanel implements ActionListener {
    2828
    29         protected JOptionPane optionPane;
    30         /** Button to export all downloaded images. */
    31         public JRadioButton all;
    32         /**
    33         * Button to export all images in the sequence of the selected
    34         * MapillaryImage.
    35         */
    36         public JRadioButton sequence;
    37         /**
    38         * Button to export all images belonging to the selected MapillaryImage
    39         * objects.
    40         */
    41         public JRadioButton selected;
    42         public JRadioButton rewrite;
    43         public ButtonGroup group;
    44         protected JButton choose;
    45         protected JLabel path;
    46         public JFileChooser chooser;
    47         protected String exportDirectory;
     29    protected JOptionPane optionPane;
     30    /** Button to export all downloaded images. */
     31    public JRadioButton all;
     32    /**
     33    * Button to export all images in the sequence of the selected
     34    * MapillaryImage.
     35    */
     36    public JRadioButton sequence;
     37    /**
     38    * Button to export all images belonging to the selected MapillaryImage
     39    * objects.
     40    */
     41    public JRadioButton selected;
     42    public JRadioButton rewrite;
     43    public ButtonGroup group;
     44    protected JButton choose;
     45    protected JLabel path;
     46    public JFileChooser chooser;
     47    protected String exportDirectory;
    4848
    49         public MapillaryExportDialog() {
    50                 setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
     49    public MapillaryExportDialog() {
     50        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
    5151
    52                 group = new ButtonGroup();
    53                 all = new JRadioButton(tr("Export all images"));
    54                 sequence = new JRadioButton(tr("Export selected sequence"));
    55                 selected = new JRadioButton(tr("Export selected images"));
    56                 rewrite = new JRadioButton(tr("Rewrite imported images"));
    57                 group.add(all);
    58                 group.add(sequence);
    59                 group.add(selected);
    60                 group.add(rewrite);
    61                 // Some options are disabled depending on the circumstances
    62                 if (MapillaryData.getInstance().getSelectedImage() == null
    63                                 || !(MapillaryData.getInstance().getSelectedImage() instanceof MapillaryImage && ((MapillaryImage) MapillaryData
    64                                                 .getInstance().getSelectedImage()).getSequence() != null)) {
    65                         sequence.setEnabled(false);
    66                 }
    67                 if (MapillaryData.getInstance().getMultiSelectedImages().isEmpty()) {
    68                         selected.setEnabled(false);
    69                 }
    70                 path = new JLabel(tr("Select a folder"));
    71                 choose = new JButton(tr("Explore"));
    72                 choose.addActionListener(this);
     52        group = new ButtonGroup();
     53        all = new JRadioButton(tr("Export all images"));
     54        sequence = new JRadioButton(tr("Export selected sequence"));
     55        selected = new JRadioButton(tr("Export selected images"));
     56        rewrite = new JRadioButton(tr("Rewrite imported images"));
     57        group.add(all);
     58        group.add(sequence);
     59        group.add(selected);
     60        group.add(rewrite);
     61        // Some options are disabled depending on the circumstances
     62        if (MapillaryData.getInstance().getSelectedImage() == null
     63                || !(MapillaryData.getInstance().getSelectedImage() instanceof MapillaryImage && ((MapillaryImage) MapillaryData
     64                        .getInstance().getSelectedImage()).getSequence() != null)) {
     65            sequence.setEnabled(false);
     66        }
     67        if (MapillaryData.getInstance().getMultiSelectedImages().isEmpty()) {
     68            selected.setEnabled(false);
     69        }
     70        path = new JLabel(tr("Select a folder"));
     71        choose = new JButton(tr("Explore"));
     72        choose.addActionListener(this);
    7373
    74                 // All options belong to the same jpanel so the are in line.
    75                 JPanel jpanel = new JPanel();
    76                 jpanel.setLayout(new BoxLayout(jpanel, BoxLayout.PAGE_AXIS));
    77                 jpanel.add(all);
    78                 jpanel.add(sequence);
    79                 jpanel.add(selected);
    80                 jpanel.add(rewrite);
    81                 jpanel.setAlignmentX(Component.CENTER_ALIGNMENT);
    82                 path.setAlignmentX(Component.CENTER_ALIGNMENT);
    83                 choose.setAlignmentX(Component.CENTER_ALIGNMENT);
     74        // All options belong to the same jpanel so the are in line.
     75        JPanel jpanel = new JPanel();
     76        jpanel.setLayout(new BoxLayout(jpanel, BoxLayout.PAGE_AXIS));
     77        jpanel.add(all);
     78        jpanel.add(sequence);
     79        jpanel.add(selected);
     80        jpanel.add(rewrite);
     81        jpanel.setAlignmentX(Component.CENTER_ALIGNMENT);
     82        path.setAlignmentX(Component.CENTER_ALIGNMENT);
     83        choose.setAlignmentX(Component.CENTER_ALIGNMENT);
    8484
    85                 add(jpanel);
    86                 add(path);
    87                 add(choose);
    88         }
     85        add(jpanel);
     86        add(path);
     87        add(choose);
     88    }
    8989
    90         /**
    91         * Creates the folder choser GUI.
    92         */
    93         @Override
    94         public void actionPerformed(ActionEvent e) {
    95                 chooser = new JFileChooser();
    96                 chooser.setCurrentDirectory(new java.io.File(System
    97                                 .getProperty("user.home")));
    98                 chooser.setDialogTitle(tr("Select a directory"));
    99                 chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
    100                 chooser.setAcceptAllFileFilterUsed(false);
     90    /**
     91    * Creates the folder choser GUI.
     92    */
     93    @Override
     94    public void actionPerformed(ActionEvent e) {
     95        chooser = new JFileChooser();
     96        chooser.setCurrentDirectory(new java.io.File(System
     97                .getProperty("user.home")));
     98        chooser.setDialogTitle(tr("Select a directory"));
     99        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
     100        chooser.setAcceptAllFileFilterUsed(false);
    101101
    102                 if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
    103                         path.setText(chooser.getSelectedFile().toString());
    104                         this.updateUI();
    105                 }
    106         }
     102        if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
     103            path.setText(chooser.getSelectedFile().toString());
     104            this.updateUI();
     105        }
     106    }
    107107}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryHistoryDialog.java

    r31262 r31278  
    3131
    3232public class MapillaryHistoryDialog extends ToggleDialog implements
    33                 MapillaryRecordListener {
     33        MapillaryRecordListener {
    3434
    35         public static MapillaryHistoryDialog INSTANCE;
     35    public static MapillaryHistoryDialog INSTANCE;
    3636
    37         private final DefaultTreeModel undoTreeModel = new DefaultTreeModel(
    38                         new DefaultMutableTreeNode());
    39         private final DefaultTreeModel redoTreeModel = new DefaultTreeModel(
    40                         new DefaultMutableTreeNode());
    41         private final JTree undoTree = new JTree(undoTreeModel);
    42         private final JTree redoTree = new JTree(redoTreeModel);
     37    private final DefaultTreeModel undoTreeModel = new DefaultTreeModel(
     38            new DefaultMutableTreeNode());
     39    private final DefaultTreeModel redoTreeModel = new DefaultTreeModel(
     40            new DefaultMutableTreeNode());
     41    private final JTree undoTree = new JTree(undoTreeModel);
     42    private final JTree redoTree = new JTree(redoTreeModel);
    4343
    44         private JSeparator separator = new JSeparator();
    45         private Component spacer = Box.createRigidArea(new Dimension(0, 3));
     44    private JSeparator separator = new JSeparator();
     45    private Component spacer = Box.createRigidArea(new Dimension(0, 3));
    4646
    47         private SideButton undoButton;
    48         private SideButton redoButton;
     47    private SideButton undoButton;
     48    private SideButton redoButton;
    4949
    50         public MapillaryHistoryDialog() {
    51                 super(tr("Mapillary history"), "mapillaryhistory.png",
    52                                 tr("Open Mapillary history dialog"), Shortcut.registerShortcut(
    53                                                 tr("Mapillary history"),
    54                                                 tr("Open Mapillary history dialog"), KeyEvent.VK_M,
    55                                                 Shortcut.NONE), 200);
     50    public MapillaryHistoryDialog() {
     51        super(tr("Mapillary history"), "mapillaryhistory.png",
     52                tr("Open Mapillary history dialog"), Shortcut.registerShortcut(
     53                        tr("Mapillary history"),
     54                        tr("Open Mapillary history dialog"), KeyEvent.VK_M,
     55                        Shortcut.NONE), 200);
    5656
    57                 MapillaryRecord.getInstance().addListener(this);
     57        MapillaryRecord.getInstance().addListener(this);
    5858
    59                 undoTree.expandRow(0);
    60                 undoTree.setShowsRootHandles(true);
    61                 undoTree.setRootVisible(false);
    62                 undoTree.setCellRenderer(new MapillaryCellRenderer());
    63                 redoTree.expandRow(0);
    64                 redoTree.setCellRenderer(new MapillaryCellRenderer());
    65                 redoTree.setShowsRootHandles(true);
    66                 redoTree.setRootVisible(false);
     59        undoTree.expandRow(0);
     60        undoTree.setShowsRootHandles(true);
     61        undoTree.setRootVisible(false);
     62        undoTree.setCellRenderer(new MapillaryCellRenderer());
     63        redoTree.expandRow(0);
     64        redoTree.setCellRenderer(new MapillaryCellRenderer());
     65        redoTree.setShowsRootHandles(true);
     66        redoTree.setRootVisible(false);
    6767
    68                 JPanel treesPanel = new JPanel(new GridBagLayout());
    69                 treesPanel.add(spacer, GBC.eol());
    70                 spacer.setVisible(false);
    71                 treesPanel.add(undoTree, GBC.eol().fill(GBC.HORIZONTAL));
    72                 separator.setVisible(false);
    73                 treesPanel.add(separator, GBC.eol().fill(GBC.HORIZONTAL));
    74                 treesPanel.add(redoTree, GBC.eol().fill(GBC.HORIZONTAL));
    75                 treesPanel.add(Box.createRigidArea(new Dimension(0, 0)), GBC.std()
    76                                 .weight(0, 1));
    77                 treesPanel.setBackground(redoTree.getBackground());
     68        JPanel treesPanel = new JPanel(new GridBagLayout());
     69        treesPanel.add(spacer, GBC.eol());
     70        spacer.setVisible(false);
     71        treesPanel.add(undoTree, GBC.eol().fill(GBC.HORIZONTAL));
     72        separator.setVisible(false);
     73        treesPanel.add(separator, GBC.eol().fill(GBC.HORIZONTAL));
     74        treesPanel.add(redoTree, GBC.eol().fill(GBC.HORIZONTAL));
     75        treesPanel.add(Box.createRigidArea(new Dimension(0, 0)), GBC.std()
     76                .weight(0, 1));
     77        treesPanel.setBackground(redoTree.getBackground());
    7878
    79                 undoButton = new SideButton(new UndoAction());
    80                 redoButton = new SideButton(new RedoAction());
     79        undoButton = new SideButton(new UndoAction());
     80        redoButton = new SideButton(new RedoAction());
    8181
    82                 createLayout(treesPanel, true,
    83                                 Arrays.asList(new SideButton[] { undoButton, redoButton }));
    84         }
     82        createLayout(treesPanel, true,
     83                Arrays.asList(new SideButton[] { undoButton, redoButton }));
     84    }
    8585
    86         public static MapillaryHistoryDialog getInstance() {
    87                 if (INSTANCE == null)
    88                         INSTANCE = new MapillaryHistoryDialog();
    89                 return INSTANCE;
    90         }
     86    public static MapillaryHistoryDialog getInstance() {
     87        if (INSTANCE == null)
     88            INSTANCE = new MapillaryHistoryDialog();
     89        return INSTANCE;
     90    }
    9191
    92         private void buildTree() {
    93                 redoButton.setEnabled(true);
    94                 undoButton.setEnabled(true);
    95                 ArrayList<MapillaryCommand> commands = MapillaryRecord.getInstance().commandList;
    96                 int position = MapillaryRecord.getInstance().position;
    97                 ArrayList<MapillaryCommand> undoCommands = new ArrayList<>();
    98                 if (position >= 0)
    99                         undoCommands = new ArrayList<>(commands.subList(0, position + 1));
    100                 else
    101                         undoButton.setEnabled(false);
    102                 ArrayList<MapillaryCommand> redoCommands = new ArrayList<>();
    103                 if (commands.size() > 0 && position + 1 < commands.size())
    104                         redoCommands = new ArrayList<>(commands.subList(position + 1,
    105                                         commands.size()));
    106                 else
    107                         redoButton.setEnabled(false);
     92    private void buildTree() {
     93        redoButton.setEnabled(true);
     94        undoButton.setEnabled(true);
     95        ArrayList<MapillaryCommand> commands = MapillaryRecord.getInstance().commandList;
     96        int position = MapillaryRecord.getInstance().position;
     97        ArrayList<MapillaryCommand> undoCommands = new ArrayList<>();
     98        if (position >= 0)
     99            undoCommands = new ArrayList<>(commands.subList(0, position + 1));
     100        else
     101            undoButton.setEnabled(false);
     102        ArrayList<MapillaryCommand> redoCommands = new ArrayList<>();
     103        if (commands.size() > 0 && position + 1 < commands.size())
     104            redoCommands = new ArrayList<>(commands.subList(position + 1,
     105                    commands.size()));
     106        else
     107            redoButton.setEnabled(false);
    108108
    109                 DefaultMutableTreeNode redoRoot = new DefaultMutableTreeNode();
    110                 DefaultMutableTreeNode undoRoot = new DefaultMutableTreeNode();
     109        DefaultMutableTreeNode redoRoot = new DefaultMutableTreeNode();
     110        DefaultMutableTreeNode undoRoot = new DefaultMutableTreeNode();
    111111
    112                 for (MapillaryCommand command : undoCommands) {
    113                         if (command != null)
    114                                 undoRoot.add(new DefaultMutableTreeNode(command.toString()));
    115                 }
    116                 for (MapillaryCommand command : redoCommands) {
    117                         if (command != null)
    118                                 redoRoot.add(new DefaultMutableTreeNode(command.toString()));
    119                 }
     112        for (MapillaryCommand command : undoCommands) {
     113            if (command != null)
     114                undoRoot.add(new DefaultMutableTreeNode(command.toString()));
     115        }
     116        for (MapillaryCommand command : redoCommands) {
     117            if (command != null)
     118                redoRoot.add(new DefaultMutableTreeNode(command.toString()));
     119        }
    120120
    121                 separator
    122                                 .setVisible(!undoCommands.isEmpty() || !redoCommands.isEmpty());
    123                 spacer.setVisible(undoCommands.isEmpty() && !redoCommands.isEmpty());
     121        separator
     122                .setVisible(!undoCommands.isEmpty() || !redoCommands.isEmpty());
     123        spacer.setVisible(undoCommands.isEmpty() && !redoCommands.isEmpty());
    124124
    125                 undoTreeModel.setRoot(undoRoot);
    126                 redoTreeModel.setRoot(redoRoot);
    127         }
     125        undoTreeModel.setRoot(undoRoot);
     126        redoTreeModel.setRoot(redoRoot);
     127    }
    128128
    129         @Override
    130         public void recordChanged() {
    131                 buildTree();
    132         }
     129    @Override
     130    public void recordChanged() {
     131        buildTree();
     132    }
    133133
    134         private class UndoAction extends AbstractAction {
     134    private class UndoAction extends AbstractAction {
    135135
    136                 public UndoAction() {
    137                         putValue(NAME, tr("Undo"));
    138                         putValue(SMALL_ICON, ImageProvider.get("undo"));
    139                 }
     136        public UndoAction() {
     137            putValue(NAME, tr("Undo"));
     138            putValue(SMALL_ICON, ImageProvider.get("undo"));
     139        }
    140140
    141                 @Override
    142                 public void actionPerformed(ActionEvent arg0) {
    143                         MapillaryRecord.getInstance().undo();
    144                 }
     141        @Override
     142        public void actionPerformed(ActionEvent arg0) {
     143            MapillaryRecord.getInstance().undo();
     144        }
    145145
    146         }
     146    }
    147147
    148         private class RedoAction extends AbstractAction {
    149                 public RedoAction() {
    150                         putValue(NAME, tr("Redo"));
    151                         putValue(SMALL_ICON, ImageProvider.get("redo"));
    152                 }
     148    private class RedoAction extends AbstractAction {
     149        public RedoAction() {
     150            putValue(NAME, tr("Redo"));
     151            putValue(SMALL_ICON, ImageProvider.get("redo"));
     152        }
    153153
    154                 @Override
    155                 public void actionPerformed(ActionEvent arg0) {
    156                         MapillaryRecord.getInstance().redo();
    157                 }
     154        @Override
     155        public void actionPerformed(ActionEvent arg0) {
     156            MapillaryRecord.getInstance().redo();
     157        }
    158158
    159         }
     159    }
    160160
    161         private static class MapillaryCellRenderer extends DefaultTreeCellRenderer {
    162                 @Override
    163                 public Component getTreeCellRendererComponent(JTree tree, Object value,
    164                                 boolean sel, boolean expanded, boolean leaf, int row,
    165                                 boolean hasFocus) {
    166                         super.getTreeCellRendererComponent(tree, value, sel, expanded,
    167                                         leaf, row, hasFocus);
    168                         setIcon(ImageProvider.get("data/node.png"));
    169                         return this;
    170                 }
    171         }
     161    private static class MapillaryCellRenderer extends DefaultTreeCellRenderer {
     162        @Override
     163        public Component getTreeCellRendererComponent(JTree tree, Object value,
     164                boolean sel, boolean expanded, boolean leaf, int row,
     165                boolean hasFocus) {
     166            super.getTreeCellRendererComponent(tree, value, sel, expanded,
     167                    leaf, row, hasFocus);
     168            setIcon(ImageProvider.get("data/node.png"));
     169            return this;
     170        }
     171    }
    172172}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryImageDisplay.java

    r31277 r31278  
    3333public class MapillaryImageDisplay extends JComponent {
    3434
    35         private static final int DRAG_BUTTON = Main.pref.getInteger("mapillary.picture-drag-button", 3);
    36         private static final int OPTION_BUTTON = Main.pref.getInteger("mapillary.picture-option-button", 2);
    37         private static final int ZOOM_BUTTON = Main.pref.getInteger("mapillary.picture-zoom-button", 1);
    38 
    39         /** The image currently displayed */
    40         private transient BufferedImage image = null;
    41 
    42         /**
    43          * The rectangle (in image coordinates) of the image that is visible. This
    44          * rectangle is calculated each time the zoom is modified
    45          */
    46         private Rectangle visibleRect = null;
    47 
    48         /**
    49          * When a selection is done, the rectangle of the selection (in image
    50          * coordinates)
    51          */
    52         private Rectangle selectedRect = null;
    53 
    54         public HyperlinkLabel hyperlink;
    55 
    56         private class ImgDisplayMouseListener implements MouseListener,
    57                         MouseWheelListener, MouseMotionListener {
    58                 private boolean mouseIsDragging = false;
    59                 private long lastTimeForMousePoint = 0L;
    60                 private Point mousePointInImg = null;
    61 
    62                 /**
    63                  * Zoom in and out, trying to preserve the point of the image that was
    64                  * under the mouse cursor at the same place
    65                  */
    66                 @Override
    67                 public void mouseWheelMoved(MouseWheelEvent e) {
    68                         Image image;
    69                         Rectangle visibleRect;
    70                         synchronized (MapillaryImageDisplay.this) {
    71                                 image = MapillaryImageDisplay.this.image;
    72                                 visibleRect = MapillaryImageDisplay.this.visibleRect;
    73                         }
    74                         mouseIsDragging = false;
    75                         selectedRect = null;
    76                         if (image == null)
    77                                 return;
    78                         // Calculate the mouse cursor position in image coordinates, so that
    79                         // we can center the zoom
    80                         // on that mouse position.
    81                         // To avoid issues when the user tries to zoom in on the image
    82                         // borders, this point is not calculated
    83                         // again if there was less than 1.5seconds since the last event.
    84                         if (e.getWhen() - lastTimeForMousePoint > 1500
    85                                         || mousePointInImg == null) {
    86                                 lastTimeForMousePoint = e.getWhen();
    87                                 mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
    88                         }
    89                         // Applicate the zoom to the visible rectangle in image coordinates
    90                         if (e.getWheelRotation() > 0) {
    91                                 visibleRect.width = visibleRect.width * 3 / 2;
    92                                 visibleRect.height = visibleRect.height * 3 / 2;
    93                         } else {
    94                                 visibleRect.width = visibleRect.width * 2 / 3;
    95                                 visibleRect.height = visibleRect.height * 2 / 3;
    96                         }
    97                         // Check that the zoom doesn't exceed 2:1
    98                         if (visibleRect.width < getSize().width / 2) {
    99                                 visibleRect.width = getSize().width / 2;
    100                         }
    101                         if (visibleRect.height < getSize().height / 2) {
    102                                 visibleRect.height = getSize().height / 2;
    103                         }
    104                         // Set the same ratio for the visible rectangle and the display area
    105                         int hFact = visibleRect.height * getSize().width;
    106                         int wFact = visibleRect.width * getSize().height;
    107                         if (hFact > wFact) {
    108                                 visibleRect.width = hFact / getSize().height;
    109                         } else {
    110                                 visibleRect.height = wFact / getSize().width;
    111                         }
    112                         // The size of the visible rectangle is limited by the image size.
    113                         checkVisibleRectSize(image, visibleRect);
    114                         // Set the position of the visible rectangle, so that the mouse
    115                         // cursor doesn't move on the image.
    116                         Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
    117                         visibleRect.x = mousePointInImg.x
    118                                         + ((drawRect.x - e.getX()) * visibleRect.width)
    119                                         / drawRect.width;
    120                         visibleRect.y = mousePointInImg.y
    121                                         + ((drawRect.y - e.getY()) * visibleRect.height)
    122                                         / drawRect.height;
    123                         // The position is also limited by the image size
    124                         checkVisibleRectPos(image, visibleRect);
    125                         synchronized (MapillaryImageDisplay.this) {
    126                                 MapillaryImageDisplay.this.visibleRect = visibleRect;
    127                         }
    128                         MapillaryImageDisplay.this.repaint();
    129                 }
    130 
    131                 /** Center the display on the point that has been clicked */
    132                 @Override
    133                 public void mouseClicked(MouseEvent e) {
    134                         // Move the center to the clicked point.
    135                         Image image;
    136                         Rectangle visibleRect;
    137                         synchronized (MapillaryImageDisplay.this) {
    138                                 image = MapillaryImageDisplay.this.image;
    139                                 visibleRect = MapillaryImageDisplay.this.visibleRect;
    140                         }
    141                         if (image == null)
    142                                 return;
    143                         if (e.getButton() == OPTION_BUTTON) {
    144                                 if (!MapillaryImageDisplay.this.visibleRect
    145                                                 .equals(new Rectangle(0, 0, image.getWidth(null), image
    146                                                                 .getHeight(null))))
    147                                         // Zooms to 1:1
    148                                         MapillaryImageDisplay.this.visibleRect = new Rectangle(0,
    149                                                         0, image.getWidth(null), image.getHeight(null));
    150                                 else
    151                                         // Zooms to best fit.
    152                                         MapillaryImageDisplay.this.visibleRect = new Rectangle(
    153                                                         0,
    154                                                         (image.getHeight(null) - (image.getWidth(null) * getHeight())
    155                                                                         / getWidth()) / 2, image.getWidth(null),
    156                                                         (image.getWidth(null) * getHeight()) / getWidth());
    157                                 MapillaryImageDisplay.this.repaint();
    158                                 return;
    159                         } else if (e.getButton() != DRAG_BUTTON)
    160                                 return;
    161                         // Calculate the translation to set the clicked point the center of
    162                         // the view.
    163                         Point click = comp2imgCoord(visibleRect, e.getX(), e.getY());
    164                         Point center = getCenterImgCoord(visibleRect);
    165                         visibleRect.x += click.x - center.x;
    166                         visibleRect.y += click.y - center.y;
    167                         checkVisibleRectPos(image, visibleRect);
    168                         synchronized (MapillaryImageDisplay.this) {
    169                                 MapillaryImageDisplay.this.visibleRect = visibleRect;
    170                         }
    171                         MapillaryImageDisplay.this.repaint();
    172                 }
    173 
    174                 /**
    175                  * Initialize the dragging, either with button 1 (simple dragging) or
    176                  * button 3 (selection of a picture part)
    177                  */
    178                 @Override
    179                 public void mousePressed(MouseEvent e) {
    180                         if (image == null) {
    181                                 mouseIsDragging = false;
    182                                 selectedRect = null;
    183                                 return;
    184                         }
    185                         Image image;
    186                         Rectangle visibleRect;
    187                         synchronized (MapillaryImageDisplay.this) {
    188                                 image = MapillaryImageDisplay.this.image;
    189                                 visibleRect = MapillaryImageDisplay.this.visibleRect;
    190                         }
    191                         if (image == null)
    192                                 return;
    193                         if (e.getButton() == DRAG_BUTTON) {
    194                                 mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
    195                                 mouseIsDragging = true;
    196                                 selectedRect = null;
    197                         } else if (e.getButton() == ZOOM_BUTTON) {
    198                                 mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
    199                                 checkPointInVisibleRect(mousePointInImg, visibleRect);
    200                                 mouseIsDragging = false;
    201                                 selectedRect = new Rectangle(mousePointInImg.x,
    202                                                 mousePointInImg.y, 0, 0);
    203                                 MapillaryImageDisplay.this.repaint();
    204                         } else {
    205                                 mouseIsDragging = false;
    206                                 selectedRect = null;
    207                         }
    208                 }
    209 
    210                 @Override
    211                 public void mouseDragged(MouseEvent e) {
    212                         if (!mouseIsDragging && selectedRect == null)
    213                                 return;
    214                         Image image;
    215                         Rectangle visibleRect;
    216                         synchronized (MapillaryImageDisplay.this) {
    217                                 image = MapillaryImageDisplay.this.image;
    218                                 visibleRect = MapillaryImageDisplay.this.visibleRect;
    219                         }
    220                         if (image == null) {
    221                                 mouseIsDragging = false;
    222                                 selectedRect = null;
    223                                 return;
    224                         }
    225                         if (mouseIsDragging) {
    226                                 Point p = comp2imgCoord(visibleRect, e.getX(), e.getY());
    227                                 visibleRect.x += mousePointInImg.x - p.x;
    228                                 visibleRect.y += mousePointInImg.y - p.y;
    229                                 checkVisibleRectPos(image, visibleRect);
    230                                 synchronized (MapillaryImageDisplay.this) {
    231                                         MapillaryImageDisplay.this.visibleRect = visibleRect;
    232                                 }
    233                                 MapillaryImageDisplay.this.repaint();
    234                         } else if (selectedRect != null) {
    235                                 Point p = comp2imgCoord(visibleRect, e.getX(), e.getY());
    236                                 checkPointInVisibleRect(p, visibleRect);
    237                                 Rectangle rect = new Rectangle(p.x < mousePointInImg.x ? p.x
    238                                                 : mousePointInImg.x, p.y < mousePointInImg.y ? p.y
    239                                                 : mousePointInImg.y,
    240                                                 p.x < mousePointInImg.x ? mousePointInImg.x - p.x : p.x
    241                                                                 - mousePointInImg.x,
    242                                                 p.y < mousePointInImg.y ? mousePointInImg.y - p.y : p.y
    243                                                                 - mousePointInImg.y);
    244                                 checkVisibleRectSize(image, rect);
    245                                 checkVisibleRectPos(image, rect);
    246                                 MapillaryImageDisplay.this.selectedRect = rect;
    247                                 MapillaryImageDisplay.this.repaint();
    248                         }
    249                 }
    250 
    251                 @Override
    252                 public void mouseReleased(MouseEvent e) {
    253                         if (!mouseIsDragging && selectedRect == null)
    254                                 return;
    255                         Image image;
    256                         synchronized (MapillaryImageDisplay.this) {
    257                                 image = MapillaryImageDisplay.this.image;
    258                         }
    259                         if (image == null) {
    260                                 mouseIsDragging = false;
    261                                 selectedRect = null;
    262                                 return;
    263                         }
    264                         if (mouseIsDragging) {
    265                                 mouseIsDragging = false;
    266                         } else if (selectedRect != null) {
    267                                 int oldWidth = selectedRect.width;
    268                                 int oldHeight = selectedRect.height;
    269                                 // Check that the zoom doesn't exceed 2:1
    270                                 if (selectedRect.width < getSize().width / 2) {
    271                                         selectedRect.width = getSize().width / 2;
    272                                 }
    273                                 if (selectedRect.height < getSize().height / 2) {
    274                                         selectedRect.height = getSize().height / 2;
    275                                 }
    276                                 // Set the same ratio for the visible rectangle and the display
    277                                 // area
    278                                 int hFact = selectedRect.height * getSize().width;
    279                                 int wFact = selectedRect.width * getSize().height;
    280                                 if (hFact > wFact) {
    281                                         selectedRect.width = hFact / getSize().height;
    282                                 } else {
    283                                         selectedRect.height = wFact / getSize().width;
    284                                 }
    285                                 // Keep the center of the selection
    286                                 if (selectedRect.width != oldWidth) {
    287                                         selectedRect.x -= (selectedRect.width - oldWidth) / 2;
    288                                 }
    289                                 if (selectedRect.height != oldHeight) {
    290                                         selectedRect.y -= (selectedRect.height - oldHeight) / 2;
    291                                 }
    292                                 checkVisibleRectSize(image, selectedRect);
    293                                 checkVisibleRectPos(image, selectedRect);
    294                                 synchronized (MapillaryImageDisplay.this) {
    295                                         MapillaryImageDisplay.this.visibleRect = selectedRect;
    296                                 }
    297                                 selectedRect = null;
    298                                 MapillaryImageDisplay.this.repaint();
    299                         }
    300                 }
    301 
    302                 @Override
    303                 public void mouseEntered(MouseEvent e) {
    304                 }
    305 
    306                 @Override
    307                 public void mouseExited(MouseEvent e) {
    308                 }
    309 
    310                 @Override
    311                 public void mouseMoved(MouseEvent e) {
    312                 }
    313 
    314                 private void checkPointInVisibleRect(Point p, Rectangle visibleRect) {
    315                         if (p.x < visibleRect.x) {
    316                                 p.x = visibleRect.x;
    317                         }
    318                         if (p.x > visibleRect.x + visibleRect.width) {
    319                                 p.x = visibleRect.x + visibleRect.width;
    320                         }
    321                         if (p.y < visibleRect.y) {
    322                                 p.y = visibleRect.y;
    323                         }
    324                         if (p.y > visibleRect.y + visibleRect.height) {
    325                                 p.y = visibleRect.y + visibleRect.height;
    326                         }
    327                 }
    328         }
    329 
    330         public MapillaryImageDisplay() {
    331                 ImgDisplayMouseListener mouseListener = new ImgDisplayMouseListener();
    332                 addMouseListener(mouseListener);
    333                 addMouseWheelListener(mouseListener);
    334                 addMouseMotionListener(mouseListener);
    335                 this.setLayout(new BorderLayout());
    336                 JPanel southPanel = new JPanel();
    337                 southPanel.setLayout(new BorderLayout());
    338                 hyperlink = new HyperlinkLabel();
    339                 southPanel.add(hyperlink, BorderLayout.EAST);
    340                 southPanel.setOpaque(false);
    341 
    342                 add(southPanel, BorderLayout.SOUTH);
    343         }
    344 
    345         /**
    346          * Sets a new picture to be displayed.
    347          *
    348          * @param image
    349          */
    350         public void setImage(BufferedImage image) {
    351                 synchronized (this) {
    352                         this.image = image;
    353                         selectedRect = null;
    354                         if (image != null)
    355                                 this.visibleRect = new Rectangle(0, 0, image.getWidth(null),
    356                                                 image.getHeight(null));
    357                 }
    358                 repaint();
    359         }
    360 
    361         /**
    362          * Returns the picture that is being displayerd
    363          *
    364          * @return
    365          */
    366         public BufferedImage getImage() {
    367                 return this.image;
    368         }
    369 
    370         /**
    371          * Paints the visible part of the picture.
    372          */
    373         public void paintComponent(Graphics g) {
    374                 Image image;
    375                 Rectangle visibleRect;
    376                 synchronized (this) {
    377                         image = this.image;
    378                         visibleRect = this.visibleRect;
    379                 }
    380                 if (image == null) {
    381                         g.setColor(Color.black);
    382                         String noImageStr = tr("No image");
    383                         Rectangle2D noImageSize = g.getFontMetrics(g.getFont())
    384                                         .getStringBounds(noImageStr, g);
    385                         Dimension size = getSize();
    386                         g.drawString(noImageStr,
    387                                         (int) ((size.width - noImageSize.getWidth()) / 2),
    388                                         (int) ((size.height - noImageSize.getHeight()) / 2));
    389                 } else {
    390                         Rectangle target = calculateDrawImageRectangle(visibleRect);
    391                         g.drawImage(image, target.x, target.y, target.x + target.width,
    392                                         target.y + target.height, visibleRect.x, visibleRect.y,
    393                                         visibleRect.x + visibleRect.width, visibleRect.y
    394                                                         + visibleRect.height, null);
    395                         if (selectedRect != null) {
    396                                 Point topLeft = img2compCoord(visibleRect, selectedRect.x,
    397                                                 selectedRect.y);
    398                                 Point bottomRight = img2compCoord(visibleRect, selectedRect.x
    399                                                 + selectedRect.width, selectedRect.y
    400                                                 + selectedRect.height);
    401                                 g.setColor(new Color(128, 128, 128, 180));
    402                                 g.fillRect(target.x, target.y, target.width, topLeft.y
    403                                                 - target.y);
    404                                 g.fillRect(target.x, target.y, topLeft.x - target.x,
    405                                                 target.height);
    406                                 g.fillRect(bottomRight.x, target.y, target.x + target.width
    407                                                 - bottomRight.x, target.height);
    408                                 g.fillRect(target.x, bottomRight.y, target.width, target.y
    409                                                 + target.height - bottomRight.y);
    410                                 g.setColor(Color.black);
    411                                 g.drawRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x,
    412                                                 bottomRight.y - topLeft.y);
    413                         }
    414                 }
    415         }
    416 
    417         private final Point img2compCoord(Rectangle visibleRect, int xImg, int yImg) {
    418                 Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
    419                 return new Point(drawRect.x + ((xImg - visibleRect.x) * drawRect.width)
    420                                 / visibleRect.width, drawRect.y
    421                                 + ((yImg - visibleRect.y) * drawRect.height)
    422                                 / visibleRect.height);
    423         }
    424 
    425         private final Point comp2imgCoord(Rectangle visibleRect, int xComp,
    426                         int yComp) {
    427                 Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
    428                 return new Point(visibleRect.x
    429                                 + ((xComp - drawRect.x) * visibleRect.width) / drawRect.width,
    430                                 visibleRect.y + ((yComp - drawRect.y) * visibleRect.height)
    431                                                 / drawRect.height);
    432         }
    433 
    434         private final Point getCenterImgCoord(Rectangle visibleRect) {
    435                 return new Point(visibleRect.x + visibleRect.width / 2, visibleRect.y
    436                                 + visibleRect.height / 2);
    437         }
    438 
    439         private Rectangle calculateDrawImageRectangle(Rectangle visibleRect) {
    440                 return calculateDrawImageRectangle(visibleRect, new Rectangle(0, 0,
    441                                 getSize().width, getSize().height));
    442         }
    443 
    444         /**
    445          * calculateDrawImageRectangle
    446          *
    447          * @param imgRect
    448          *            the part of the image that should be drawn (in image
    449          *            coordinates)
    450          * @param compRect
    451          *            the part of the component where the image should be drawn (in
    452          *            component coordinates)
    453          * @return the part of compRect with the same width/height ratio as the
    454          *         image
    455          */
    456         static Rectangle calculateDrawImageRectangle(Rectangle imgRect,
    457                         Rectangle compRect) {
    458                 int x, y, w, h;
    459                 x = 0;
    460                 y = 0;
    461                 w = compRect.width;
    462                 h = compRect.height;
    463                 int wFact = w * imgRect.height;
    464                 int hFact = h * imgRect.width;
    465                 if (wFact != hFact) {
    466                         if (wFact > hFact) {
    467                                 w = hFact / imgRect.height;
    468                                 x = (compRect.width - w) / 2;
    469                         } else {
    470                                 h = wFact / imgRect.width;
    471                                 y = (compRect.height - h) / 2;
    472                         }
    473                 }
    474                 return new Rectangle(x + compRect.x, y + compRect.y, w, h);
    475         }
    476 
    477         public void zoomBestFitOrOne() {
    478                 Image image;
    479                 Rectangle visibleRect;
    480                 synchronized (this) {
    481                         image = MapillaryImageDisplay.this.image;
    482                         visibleRect = MapillaryImageDisplay.this.visibleRect;
    483                 }
    484                 if (image == null)
    485                         return;
    486                 if (visibleRect.width != image.getWidth(null)
    487                                 || visibleRect.height != image.getHeight(null)) {
    488                         // The display is not at best fit. => Zoom to best fit
    489                         visibleRect = new Rectangle(0, 0, image.getWidth(null),
    490                                         image.getHeight(null));
    491                 } else {
    492                         // The display is at best fit => zoom to 1:1
    493                         Point center = getCenterImgCoord(visibleRect);
    494                         visibleRect = new Rectangle(center.x - getWidth() / 2, center.y
    495                                         - getHeight() / 2, getWidth(), getHeight());
    496                         checkVisibleRectPos(image, visibleRect);
    497                 }
    498                 synchronized (this) {
    499                         this.visibleRect = visibleRect;
    500                 }
    501                 repaint();
    502         }
    503 
    504         private final void checkVisibleRectPos(Image image, Rectangle visibleRect) {
    505                 if (visibleRect.x < 0) {
    506                         visibleRect.x = 0;
    507                 }
    508                 if (visibleRect.y < 0) {
    509                         visibleRect.y = 0;
    510                 }
    511                 if (visibleRect.x + visibleRect.width > image.getWidth(null)) {
    512                         visibleRect.x = image.getWidth(null) - visibleRect.width;
    513                 }
    514                 if (visibleRect.y + visibleRect.height > image.getHeight(null)) {
    515                         visibleRect.y = image.getHeight(null) - visibleRect.height;
    516                 }
    517         }
    518 
    519         private void checkVisibleRectSize(Image image, Rectangle visibleRect) {
    520                 if (visibleRect.width > image.getWidth(null)) {
    521                         visibleRect.width = image.getWidth(null);
    522                 }
    523                 if (visibleRect.height > image.getHeight(null)) {
    524                         visibleRect.height = image.getHeight(null);
    525                 }
    526         }
     35    private static final int DRAG_BUTTON = Main.pref.getInteger(
     36            "mapillary.picture-drag-button", 3);
     37    private static final int OPTION_BUTTON = Main.pref.getInteger(
     38            "mapillary.picture-option-button", 2);
     39    private static final int ZOOM_BUTTON = Main.pref.getInteger(
     40            "mapillary.picture-zoom-button", 1);
     41
     42    /** The image currently displayed */
     43    private transient BufferedImage image = null;
     44
     45    /**
     46     * The rectangle (in image coordinates) of the image that is visible. This
     47     * rectangle is calculated each time the zoom is modified
     48     */
     49    private Rectangle visibleRect = null;
     50
     51    /**
     52     * When a selection is done, the rectangle of the selection (in image
     53     * coordinates)
     54     */
     55    private Rectangle selectedRect = null;
     56
     57    public HyperlinkLabel hyperlink;
     58
     59    private class ImgDisplayMouseListener implements MouseListener,
     60            MouseWheelListener, MouseMotionListener {
     61        private boolean mouseIsDragging = false;
     62        private long lastTimeForMousePoint = 0L;
     63        private Point mousePointInImg = null;
     64
     65        /**
     66         * Zoom in and out, trying to preserve the point of the image that was
     67         * under the mouse cursor at the same place
     68         */
     69        @Override
     70        public void mouseWheelMoved(MouseWheelEvent e) {
     71            Image image;
     72            Rectangle visibleRect;
     73            synchronized (MapillaryImageDisplay.this) {
     74                image = MapillaryImageDisplay.this.image;
     75                visibleRect = MapillaryImageDisplay.this.visibleRect;
     76            }
     77            mouseIsDragging = false;
     78            selectedRect = null;
     79            if (image == null)
     80                return;
     81            // Calculate the mouse cursor position in image coordinates, so that
     82            // we can center the zoom
     83            // on that mouse position.
     84            // To avoid issues when the user tries to zoom in on the image
     85            // borders, this point is not calculated
     86            // again if there was less than 1.5seconds since the last event.
     87            if (e.getWhen() - lastTimeForMousePoint > 1500
     88                    || mousePointInImg == null) {
     89                lastTimeForMousePoint = e.getWhen();
     90                mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
     91            }
     92            // Applicate the zoom to the visible rectangle in image coordinates
     93            if (e.getWheelRotation() > 0) {
     94                visibleRect.width = visibleRect.width * 3 / 2;
     95                visibleRect.height = visibleRect.height * 3 / 2;
     96            } else {
     97                visibleRect.width = visibleRect.width * 2 / 3;
     98                visibleRect.height = visibleRect.height * 2 / 3;
     99            }
     100            // Check that the zoom doesn't exceed 2:1
     101            if (visibleRect.width < getSize().width / 2) {
     102                visibleRect.width = getSize().width / 2;
     103            }
     104            if (visibleRect.height < getSize().height / 2) {
     105                visibleRect.height = getSize().height / 2;
     106            }
     107            // Set the same ratio for the visible rectangle and the display area
     108            int hFact = visibleRect.height * getSize().width;
     109            int wFact = visibleRect.width * getSize().height;
     110            if (hFact > wFact) {
     111                visibleRect.width = hFact / getSize().height;
     112            } else {
     113                visibleRect.height = wFact / getSize().width;
     114            }
     115            // The size of the visible rectangle is limited by the image size.
     116            checkVisibleRectSize(image, visibleRect);
     117            // Set the position of the visible rectangle, so that the mouse
     118            // cursor doesn't move on the image.
     119            Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
     120            visibleRect.x = mousePointInImg.x
     121                    + ((drawRect.x - e.getX()) * visibleRect.width)
     122                    / drawRect.width;
     123            visibleRect.y = mousePointInImg.y
     124                    + ((drawRect.y - e.getY()) * visibleRect.height)
     125                    / drawRect.height;
     126            // The position is also limited by the image size
     127            checkVisibleRectPos(image, visibleRect);
     128            synchronized (MapillaryImageDisplay.this) {
     129                MapillaryImageDisplay.this.visibleRect = visibleRect;
     130            }
     131            MapillaryImageDisplay.this.repaint();
     132        }
     133
     134        /** Center the display on the point that has been clicked */
     135        @Override
     136        public void mouseClicked(MouseEvent e) {
     137            // Move the center to the clicked point.
     138            Image image;
     139            Rectangle visibleRect;
     140            synchronized (MapillaryImageDisplay.this) {
     141                image = MapillaryImageDisplay.this.image;
     142                visibleRect = MapillaryImageDisplay.this.visibleRect;
     143            }
     144            if (image == null)
     145                return;
     146            if (e.getButton() == OPTION_BUTTON) {
     147                if (!MapillaryImageDisplay.this.visibleRect
     148                        .equals(new Rectangle(0, 0, image.getWidth(null), image
     149                                .getHeight(null))))
     150                    // Zooms to 1:1
     151                    MapillaryImageDisplay.this.visibleRect = new Rectangle(0,
     152                            0, image.getWidth(null), image.getHeight(null));
     153                else
     154                    // Zooms to best fit.
     155                    MapillaryImageDisplay.this.visibleRect = new Rectangle(
     156                            0,
     157                            (image.getHeight(null) - (image.getWidth(null) * getHeight())
     158                                    / getWidth()) / 2, image.getWidth(null),
     159                            (image.getWidth(null) * getHeight()) / getWidth());
     160                MapillaryImageDisplay.this.repaint();
     161                return;
     162            } else if (e.getButton() != DRAG_BUTTON)
     163                return;
     164            // Calculate the translation to set the clicked point the center of
     165            // the view.
     166            Point click = comp2imgCoord(visibleRect, e.getX(), e.getY());
     167            Point center = getCenterImgCoord(visibleRect);
     168            visibleRect.x += click.x - center.x;
     169            visibleRect.y += click.y - center.y;
     170            checkVisibleRectPos(image, visibleRect);
     171            synchronized (MapillaryImageDisplay.this) {
     172                MapillaryImageDisplay.this.visibleRect = visibleRect;
     173            }
     174            MapillaryImageDisplay.this.repaint();
     175        }
     176
     177        /**
     178         * Initialize the dragging, either with button 1 (simple dragging) or
     179         * button 3 (selection of a picture part)
     180         */
     181        @Override
     182        public void mousePressed(MouseEvent e) {
     183            if (image == null) {
     184                mouseIsDragging = false;
     185                selectedRect = null;
     186                return;
     187            }
     188            Image image;
     189            Rectangle visibleRect;
     190            synchronized (MapillaryImageDisplay.this) {
     191                image = MapillaryImageDisplay.this.image;
     192                visibleRect = MapillaryImageDisplay.this.visibleRect;
     193            }
     194            if (image == null)
     195                return;
     196            if (e.getButton() == DRAG_BUTTON) {
     197                mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
     198                mouseIsDragging = true;
     199                selectedRect = null;
     200            } else if (e.getButton() == ZOOM_BUTTON) {
     201                mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
     202                checkPointInVisibleRect(mousePointInImg, visibleRect);
     203                mouseIsDragging = false;
     204                selectedRect = new Rectangle(mousePointInImg.x,
     205                        mousePointInImg.y, 0, 0);
     206                MapillaryImageDisplay.this.repaint();
     207            } else {
     208                mouseIsDragging = false;
     209                selectedRect = null;
     210            }
     211        }
     212
     213        @Override
     214        public void mouseDragged(MouseEvent e) {
     215            if (!mouseIsDragging && selectedRect == null)
     216                return;
     217            Image image;
     218            Rectangle visibleRect;
     219            synchronized (MapillaryImageDisplay.this) {
     220                image = MapillaryImageDisplay.this.image;
     221                visibleRect = MapillaryImageDisplay.this.visibleRect;
     222            }
     223            if (image == null) {
     224                mouseIsDragging = false;
     225                selectedRect = null;
     226                return;
     227            }
     228            if (mouseIsDragging) {
     229                Point p = comp2imgCoord(visibleRect, e.getX(), e.getY());
     230                visibleRect.x += mousePointInImg.x - p.x;
     231                visibleRect.y += mousePointInImg.y - p.y;
     232                checkVisibleRectPos(image, visibleRect);
     233                synchronized (MapillaryImageDisplay.this) {
     234                    MapillaryImageDisplay.this.visibleRect = visibleRect;
     235                }
     236                MapillaryImageDisplay.this.repaint();
     237            } else if (selectedRect != null) {
     238                Point p = comp2imgCoord(visibleRect, e.getX(), e.getY());
     239                checkPointInVisibleRect(p, visibleRect);
     240                Rectangle rect = new Rectangle(p.x < mousePointInImg.x ? p.x
     241                        : mousePointInImg.x, p.y < mousePointInImg.y ? p.y
     242                        : mousePointInImg.y,
     243                        p.x < mousePointInImg.x ? mousePointInImg.x - p.x : p.x
     244                                - mousePointInImg.x,
     245                        p.y < mousePointInImg.y ? mousePointInImg.y - p.y : p.y
     246                                - mousePointInImg.y);
     247                checkVisibleRectSize(image, rect);
     248                checkVisibleRectPos(image, rect);
     249                MapillaryImageDisplay.this.selectedRect = rect;
     250                MapillaryImageDisplay.this.repaint();
     251            }
     252        }
     253
     254        @Override
     255        public void mouseReleased(MouseEvent e) {
     256            if (!mouseIsDragging && selectedRect == null)
     257                return;
     258            Image image;
     259            synchronized (MapillaryImageDisplay.this) {
     260                image = MapillaryImageDisplay.this.image;
     261            }
     262            if (image == null) {
     263                mouseIsDragging = false;
     264                selectedRect = null;
     265                return;
     266            }
     267            if (mouseIsDragging) {
     268                mouseIsDragging = false;
     269            } else if (selectedRect != null) {
     270                int oldWidth = selectedRect.width;
     271                int oldHeight = selectedRect.height;
     272                // Check that the zoom doesn't exceed 2:1
     273                if (selectedRect.width < getSize().width / 2) {
     274                    selectedRect.width = getSize().width / 2;
     275                }
     276                if (selectedRect.height < getSize().height / 2) {
     277                    selectedRect.height = getSize().height / 2;
     278                }
     279                // Set the same ratio for the visible rectangle and the display
     280                // area
     281                int hFact = selectedRect.height * getSize().width;
     282                int wFact = selectedRect.width * getSize().height;
     283                if (hFact > wFact) {
     284                    selectedRect.width = hFact / getSize().height;
     285                } else {
     286                    selectedRect.height = wFact / getSize().width;
     287                }
     288                // Keep the center of the selection
     289                if (selectedRect.width != oldWidth) {
     290                    selectedRect.x -= (selectedRect.width - oldWidth) / 2;
     291                }
     292                if (selectedRect.height != oldHeight) {
     293                    selectedRect.y -= (selectedRect.height - oldHeight) / 2;
     294                }
     295                checkVisibleRectSize(image, selectedRect);
     296                checkVisibleRectPos(image, selectedRect);
     297                synchronized (MapillaryImageDisplay.this) {
     298                    MapillaryImageDisplay.this.visibleRect = selectedRect;
     299                }
     300                selectedRect = null;
     301                MapillaryImageDisplay.this.repaint();
     302            }
     303        }
     304
     305        @Override
     306        public void mouseEntered(MouseEvent e) {
     307        }
     308
     309        @Override
     310        public void mouseExited(MouseEvent e) {
     311        }
     312
     313        @Override
     314        public void mouseMoved(MouseEvent e) {
     315        }
     316
     317        private void checkPointInVisibleRect(Point p, Rectangle visibleRect) {
     318            if (p.x < visibleRect.x) {
     319                p.x = visibleRect.x;
     320            }
     321            if (p.x > visibleRect.x + visibleRect.width) {
     322                p.x = visibleRect.x + visibleRect.width;
     323            }
     324            if (p.y < visibleRect.y) {
     325                p.y = visibleRect.y;
     326            }
     327            if (p.y > visibleRect.y + visibleRect.height) {
     328                p.y = visibleRect.y + visibleRect.height;
     329            }
     330        }
     331    }
     332
     333    public MapillaryImageDisplay() {
     334        ImgDisplayMouseListener mouseListener = new ImgDisplayMouseListener();
     335        addMouseListener(mouseListener);
     336        addMouseWheelListener(mouseListener);
     337        addMouseMotionListener(mouseListener);
     338        this.setLayout(new BorderLayout());
     339        JPanel southPanel = new JPanel();
     340        southPanel.setLayout(new BorderLayout());
     341        hyperlink = new HyperlinkLabel();
     342        southPanel.add(hyperlink, BorderLayout.EAST);
     343        southPanel.setOpaque(false);
     344
     345        add(southPanel, BorderLayout.SOUTH);
     346    }
     347
     348    /**
     349     * Sets a new picture to be displayed.
     350     *
     351     * @param image
     352     */
     353    public void setImage(BufferedImage image) {
     354        synchronized (this) {
     355            this.image = image;
     356            selectedRect = null;
     357            if (image != null)
     358                this.visibleRect = new Rectangle(0, 0, image.getWidth(null),
     359                        image.getHeight(null));
     360        }
     361        repaint();
     362    }
     363
     364    /**
     365     * Returns the picture that is being displayerd
     366     *
     367     * @return
     368     */
     369    public BufferedImage getImage() {
     370        return this.image;
     371    }
     372
     373    /**
     374     * Paints the visible part of the picture.
     375     */
     376    public void paintComponent(Graphics g) {
     377        Image image;
     378        Rectangle visibleRect;
     379        synchronized (this) {
     380            image = this.image;
     381            visibleRect = this.visibleRect;
     382        }
     383        if (image == null) {
     384            g.setColor(Color.black);
     385            String noImageStr = tr("No image");
     386            Rectangle2D noImageSize = g.getFontMetrics(g.getFont())
     387                    .getStringBounds(noImageStr, g);
     388            Dimension size = getSize();
     389            g.drawString(noImageStr,
     390                    (int) ((size.width - noImageSize.getWidth()) / 2),
     391                    (int) ((size.height - noImageSize.getHeight()) / 2));
     392        } else {
     393            Rectangle target = calculateDrawImageRectangle(visibleRect);
     394            g.drawImage(image, target.x, target.y, target.x + target.width,
     395                    target.y + target.height, visibleRect.x, visibleRect.y,
     396                    visibleRect.x + visibleRect.width, visibleRect.y
     397                            + visibleRect.height, null);
     398            if (selectedRect != null) {
     399                Point topLeft = img2compCoord(visibleRect, selectedRect.x,
     400                        selectedRect.y);
     401                Point bottomRight = img2compCoord(visibleRect, selectedRect.x
     402                        + selectedRect.width, selectedRect.y
     403                        + selectedRect.height);
     404                g.setColor(new Color(128, 128, 128, 180));
     405                g.fillRect(target.x, target.y, target.width, topLeft.y
     406                        - target.y);
     407                g.fillRect(target.x, target.y, topLeft.x - target.x,
     408                        target.height);
     409                g.fillRect(bottomRight.x, target.y, target.x + target.width
     410                        - bottomRight.x, target.height);
     411                g.fillRect(target.x, bottomRight.y, target.width, target.y
     412                        + target.height - bottomRight.y);
     413                g.setColor(Color.black);
     414                g.drawRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x,
     415                        bottomRight.y - topLeft.y);
     416            }
     417        }
     418    }
     419
     420    private final Point img2compCoord(Rectangle visibleRect, int xImg, int yImg) {
     421        Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
     422        return new Point(drawRect.x + ((xImg - visibleRect.x) * drawRect.width)
     423                / visibleRect.width, drawRect.y
     424                + ((yImg - visibleRect.y) * drawRect.height)
     425                / visibleRect.height);
     426    }
     427
     428    private final Point comp2imgCoord(Rectangle visibleRect, int xComp,
     429            int yComp) {
     430        Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
     431        return new Point(visibleRect.x
     432                + ((xComp - drawRect.x) * visibleRect.width) / drawRect.width,
     433                visibleRect.y + ((yComp - drawRect.y) * visibleRect.height)
     434                        / drawRect.height);
     435    }
     436
     437    private final Point getCenterImgCoord(Rectangle visibleRect) {
     438        return new Point(visibleRect.x + visibleRect.width / 2, visibleRect.y
     439                + visibleRect.height / 2);
     440    }
     441
     442    private Rectangle calculateDrawImageRectangle(Rectangle visibleRect) {
     443        return calculateDrawImageRectangle(visibleRect, new Rectangle(0, 0,
     444                getSize().width, getSize().height));
     445    }
     446
     447    /**
     448     * calculateDrawImageRectangle
     449     *
     450     * @param imgRect
     451     *            the part of the image that should be drawn (in image
     452     *            coordinates)
     453     * @param compRect
     454     *            the part of the component where the image should be drawn (in
     455     *            component coordinates)
     456     * @return the part of compRect with the same width/height ratio as the
     457     *         image
     458     */
     459    static Rectangle calculateDrawImageRectangle(Rectangle imgRect,
     460            Rectangle compRect) {
     461        int x, y, w, h;
     462        x = 0;
     463        y = 0;
     464        w = compRect.width;
     465        h = compRect.height;
     466        int wFact = w * imgRect.height;
     467        int hFact = h * imgRect.width;
     468        if (wFact != hFact) {
     469            if (wFact > hFact) {
     470                w = hFact / imgRect.height;
     471                x = (compRect.width - w) / 2;
     472            } else {
     473                h = wFact / imgRect.width;
     474                y = (compRect.height - h) / 2;
     475            }
     476        }
     477        return new Rectangle(x + compRect.x, y + compRect.y, w, h);
     478    }
     479
     480    public void zoomBestFitOrOne() {
     481        Image image;
     482        Rectangle visibleRect;
     483        synchronized (this) {
     484            image = MapillaryImageDisplay.this.image;
     485            visibleRect = MapillaryImageDisplay.this.visibleRect;
     486        }
     487        if (image == null)
     488            return;
     489        if (visibleRect.width != image.getWidth(null)
     490                || visibleRect.height != image.getHeight(null)) {
     491            // The display is not at best fit. => Zoom to best fit
     492            visibleRect = new Rectangle(0, 0, image.getWidth(null),
     493                    image.getHeight(null));
     494        } else {
     495            // The display is at best fit => zoom to 1:1
     496            Point center = getCenterImgCoord(visibleRect);
     497            visibleRect = new Rectangle(center.x - getWidth() / 2, center.y
     498                    - getHeight() / 2, getWidth(), getHeight());
     499            checkVisibleRectPos(image, visibleRect);
     500        }
     501        synchronized (this) {
     502            this.visibleRect = visibleRect;
     503        }
     504        repaint();
     505    }
     506
     507    private final void checkVisibleRectPos(Image image, Rectangle visibleRect) {
     508        if (visibleRect.x < 0) {
     509            visibleRect.x = 0;
     510        }
     511        if (visibleRect.y < 0) {
     512            visibleRect.y = 0;
     513        }
     514        if (visibleRect.x + visibleRect.width > image.getWidth(null)) {
     515            visibleRect.x = image.getWidth(null) - visibleRect.width;
     516        }
     517        if (visibleRect.y + visibleRect.height > image.getHeight(null)) {
     518            visibleRect.y = image.getHeight(null) - visibleRect.height;
     519        }
     520    }
     521
     522    private void checkVisibleRectSize(Image image, Rectangle visibleRect) {
     523        if (visibleRect.width > image.getWidth(null)) {
     524            visibleRect.width = image.getWidth(null);
     525        }
     526        if (visibleRect.height > image.getHeight(null)) {
     527            visibleRect.height = image.getHeight(null);
     528        }
     529    }
    527530}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryPreferenceSetting.java

    r31277 r31278  
    1414public class MapillaryPreferenceSetting implements SubPreferenceSetting {
    1515
    16         private JCheckBox reverseButtons = new JCheckBox(tr("Reverse buttons position when displaying images."));
    17         private JCheckBox downloadMode = new JCheckBox(tr("Download images manually"));
     16    private JCheckBox reverseButtons = new JCheckBox(
     17            tr("Reverse buttons position when displaying images."));
     18    private JCheckBox downloadMode = new JCheckBox(
     19            tr("Download images manually"));
    1820
    19        
    20         @Override
    21         public TabPreferenceSetting getTabPreferenceSetting(PreferenceTabbedPane gui) {
    22                 return gui.getDisplayPreference();
    23         }
     21    @Override
     22    public TabPreferenceSetting getTabPreferenceSetting(PreferenceTabbedPane gui) {
     23        return gui.getDisplayPreference();
     24    }
    2425
    25         @Override
    26         public void addGui(PreferenceTabbedPane gui) {
    27                 JPanel panel = new JPanel();
    28                
    29                 reverseButtons.setSelected(Main.pref.getBoolean("mapillary.reverse-buttons"));
    30                 downloadMode.setSelected(Main.pref.getBoolean("mapillary.download-manually"));
    31                
    32                 panel.setLayout(new FlowLayout(FlowLayout.LEFT));
    33                 panel.add(reverseButtons);
    34                 panel.add(downloadMode);
     26    @Override
     27    public void addGui(PreferenceTabbedPane gui) {
     28        JPanel panel = new JPanel();
     29
     30        reverseButtons.setSelected(Main.pref
     31                .getBoolean("mapillary.reverse-buttons"));
     32        downloadMode.setSelected(Main.pref
     33                .getBoolean("mapillary.download-manually"));
     34
     35        panel.setLayout(new FlowLayout(FlowLayout.LEFT));
     36        panel.add(reverseButtons);
     37        panel.add(downloadMode);
    3538        gui.getDisplayPreference().addSubTab(this, "Mapillary", panel);
    36         }
     39    }
    3740
    38         @Override
    39         public boolean ok() {
     41    @Override
     42    public boolean ok() {
    4043        boolean mod = false;
    4144        Main.pref.put("mapillary.reverse-buttons", reverseButtons.isSelected());
    4245        Main.pref.put("mapillary.download-manually", downloadMode.isSelected());
    4346        return mod;
    44         }
     47    }
    4548
    46         @Override
    47         public boolean isExpert() {
    48                 return false;
    49         }
     49    @Override
     50    public boolean isExpert() {
     51        return false;
     52    }
    5053
    5154}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryToggleDialog.java

    r31275 r31278  
    4343 */
    4444public class MapillaryToggleDialog extends ToggleDialog implements
    45                 ICachedLoaderListener, MapillaryDataListener {
    46 
    47         public final static int NORMAL_MODE = 0;
    48         public final static int SIGN_MODE = 1;
    49 
    50         public final static String BASE_TITLE = "Mapillary picture";
    51 
    52         public static MapillaryToggleDialog INSTANCE;
    53 
    54         public volatile MapillaryAbstractImage image;
    55 
    56         public final SideButton nextButton = new SideButton(new nextPictureAction());
    57         public final SideButton previousButton = new SideButton(
    58                         new previousPictureAction());
    59         public final SideButton redButton = new SideButton(new redAction());
    60         public final SideButton blueButton = new SideButton(new blueAction());
    61         private List<SideButton> normalMode;
    62 
    63         public final SideButton nextSignButton = new SideButton(
    64                         new NextSignAction());
    65         public final SideButton previousSignButton = new SideButton(
    66                         new PreviousSignAction());
    67         private List<SideButton> signMode;
    68 
    69         private int mode;
    70 
    71         private JPanel buttonsPanel;
    72 
    73         public MapillaryImageDisplay mapillaryImageDisplay;
    74 
    75         private MapillaryCache imageCache;
    76         private MapillaryCache thumbnailCache;
    77 
    78         public MapillaryToggleDialog() {
    79                 super(tr(BASE_TITLE), "mapillary.png", tr("Open Mapillary window"),
    80                                 Shortcut.registerShortcut(tr("Mapillary dialog"),
    81                                                 tr("Open Mapillary main dialog"), KeyEvent.VK_M,
    82                                                 Shortcut.NONE), 200);
    83                 MapillaryData.getInstance().addListener(this);
    84 
    85                 mapillaryImageDisplay = new MapillaryImageDisplay();
    86 
    87                 blueButton.setForeground(Color.BLUE);
    88                 redButton.setForeground(Color.RED);
    89 
    90                 normalMode = Arrays.asList(new SideButton[] { blueButton,
    91                                 previousButton, nextButton, redButton });
    92                 signMode = Arrays.asList(new SideButton[] { previousSignButton,
    93                                 nextSignButton });
    94 
    95                 mode = NORMAL_MODE;
    96                
    97                 createLayout(mapillaryImageDisplay, normalMode,
    98                                 Main.pref.getBoolean("mapillary.reverse-buttons"));
    99                 disableAllButtons();
    100         }
    101 
    102         public static MapillaryToggleDialog getInstance() {
    103                 if (INSTANCE == null)
    104                         INSTANCE = new MapillaryToggleDialog();
    105                 return INSTANCE;
    106         }
    107 
    108         public static void destroyInstance() {
    109                 INSTANCE = null;
    110         }
    111 
    112         /**
    113         * Switches from one mode to the other one.
    114         */
    115         public void switchMode() {
    116                 this.removeAll();
    117                 List<SideButton> list = null;
    118                 if (mode == NORMAL_MODE) {
    119                         list = signMode;
    120                         mode = SIGN_MODE;
    121                 } else if (mode == SIGN_MODE) {
    122                         list = normalMode;
    123                         mode = NORMAL_MODE;
    124                 }
    125                
    126                 createLayout(mapillaryImageDisplay, list,
    127                                 Main.pref.getBoolean("mapillary.reverse-buttons"));
    128                 disableAllButtons();
    129                 updateImage();
    130         }
    131 
    132         /**
    133         * Downloads the image of the selected MapillaryImage and sets in the
    134         * MapillaryImageDisplay object.
    135         */
    136         public synchronized void updateImage() {
    137                 if (!SwingUtilities.isEventDispatchThread()) {
    138                         SwingUtilities.invokeLater(new Runnable() {
    139                                 @Override
    140                                 public void run() {
    141                                         updateImage();
    142                                 }
    143                         });
    144                 } else {
    145                         if (MapillaryLayer.INSTANCE == null) {
    146                                 return;
    147                         }
    148                         if (this.image == null) {
    149                                 mapillaryImageDisplay.setImage(null);
    150                                 titleBar.setTitle(tr(BASE_TITLE));
    151                                 disableAllButtons();
    152                                 return;
    153                         }
    154                         if (image instanceof MapillaryImage) {
    155                                 mapillaryImageDisplay.hyperlink.setVisible(true);
    156                                 MapillaryImage mapillaryImage = (MapillaryImage) this.image;
    157                                 String title = tr(BASE_TITLE);
    158                                 if (mapillaryImage.getUser() != null)
    159                                         title += " -- " + mapillaryImage.getUser();
    160                                 if (mapillaryImage.getCapturedAt() != 0)
    161                                         title += " -- " + mapillaryImage.getDate();
    162                                 titleBar.setTitle(title);
    163                                 if (mode == NORMAL_MODE) {
    164                                         this.nextButton.setEnabled(true);
    165                                         this.previousButton.setEnabled(true);
    166                                         if (mapillaryImage.next() == null)
    167                                                 this.nextButton.setEnabled(false);
    168                                         if (mapillaryImage.previous() == null)
    169                                                 this.previousButton.setEnabled(false);
    170                                 } else if (mode == SIGN_MODE) {
    171                                         previousSignButton.setEnabled(true);
    172                                         nextSignButton.setEnabled(true);
    173                                         int i = MapillaryData
    174                                                         .getInstance()
    175                                                         .getImages()
    176                                                         .indexOf(
    177                                                                         MapillaryData.getInstance()
    178                                                                                         .getSelectedImage());
    179                                         int first = -1;
    180                                         int last = -1;
    181                                         int c = 0;
    182                                         for (MapillaryAbstractImage img : MapillaryData
    183                                                         .getInstance().getImages()) {
    184                                                 if (img instanceof MapillaryImage)
    185                                                         if (!((MapillaryImage) img).getSigns().isEmpty()) {
    186                                                                 if (first == -1)
    187                                                                         first = c;
    188                                                                 last = c;
    189                                                         }
    190                                                 c++;
    191                                         }
    192                                         if (first >= i)
    193                                                 previousSignButton.setEnabled(false);
    194                                         if (last <= i)
    195                                                 nextSignButton.setEnabled(false);
    196                                 }
    197 
    198                                 mapillaryImageDisplay.hyperlink.setURL(mapillaryImage.getKey());
    199                                 // Downloads the thumbnail.
    200                                 this.mapillaryImageDisplay.setImage(null);
    201                                 if (thumbnailCache != null)
    202                                         thumbnailCache.cancelOutstandingTasks();
    203                                 thumbnailCache = new MapillaryCache(mapillaryImage.getKey(),
    204                                                 MapillaryCache.Type.THUMBNAIL);
    205                                 thumbnailCache.submit(this, false);
    206 
    207                                 // Downloads the full resolution image.
    208                                 if (imageCache != null)
    209                                         imageCache.cancelOutstandingTasks();
    210                                 imageCache = new MapillaryCache(mapillaryImage.getKey(),
    211                                                 MapillaryCache.Type.FULL_IMAGE);
    212                                 imageCache.submit(this, false);
    213                         } else if (image instanceof MapillaryImportedImage) {
    214                                 mapillaryImageDisplay.hyperlink.setVisible(false);
    215                                 this.nextButton.setEnabled(false);
    216                                 this.previousButton.setEnabled(false);
    217                                 MapillaryImportedImage mapillaryImage = (MapillaryImportedImage) this.image;
    218                                 try {
    219                                         mapillaryImageDisplay.setImage(mapillaryImage.getImage());
    220                                 } catch (IOException e) {
    221                                         Main.error(e);
    222                                 }
    223                                 mapillaryImageDisplay.hyperlink.setURL(null);
    224                         }
    225                 }
    226         }
    227 
    228         private void disableAllButtons() {
    229                 nextButton.setEnabled(false);
    230                 previousButton.setEnabled(false);
    231                 blueButton.setEnabled(false);
    232                 redButton.setEnabled(false);
    233                 nextSignButton.setEnabled(false);
    234                 previousSignButton.setEnabled(false);
    235                 mapillaryImageDisplay.hyperlink.setVisible(false);
    236         }
    237 
    238         /**
    239         * Sets a new MapillaryImage to be shown.
    240         *
    241         * @param image
    242         */
    243         public synchronized void setImage(MapillaryAbstractImage image) {
    244                 this.image = image;
    245         }
    246 
    247         /**
    248         * Returns the MapillaryImage objects which is being shown.
    249         *
    250         * @return
    251         */
    252         public synchronized MapillaryAbstractImage getImage() {
    253                 return this.image;
    254         }
    255 
    256         /**
    257         * Action class form the next image button.
    258         *
    259         * @author Jorge
    260         *
    261         */
    262         class nextPictureAction extends AbstractAction {
    263                 public nextPictureAction() {
    264                         putValue(NAME, tr("Next picture"));
    265                         putValue(SHORT_DESCRIPTION,
    266                                         tr("Shows the next picture in the sequence"));
    267                 }
    268 
    269                 @Override
    270                 public void actionPerformed(ActionEvent e) {
    271                         if (MapillaryToggleDialog.getInstance().getImage() != null) {
    272                                 MapillaryData.getInstance().selectNext();
    273                         }
    274                 }
    275         }
    276 
    277         /**
    278         * Action class for the previous image button.
    279         *
    280         * @author Jorge
    281         *
    282         */
    283         class previousPictureAction extends AbstractAction {
    284                 public previousPictureAction() {
    285                         putValue(NAME, tr("Previous picture"));
    286                         putValue(SHORT_DESCRIPTION,
    287                                         tr("Shows the previous picture in the sequence"));
    288                 }
    289 
    290                 @Override
    291                 public void actionPerformed(ActionEvent e) {
    292                         if (MapillaryToggleDialog.getInstance().getImage() != null) {
    293                                 MapillaryData.getInstance().selectPrevious();
    294                         }
    295                 }
    296         }
    297 
    298         /**
    299         * Action class to jump to the image following the red line.
    300         *
    301         * @author nokutu
    302         *
    303         */
    304         class redAction extends AbstractAction {
    305                 public redAction() {
    306                         putValue(NAME, tr("Jump to red"));
    307                         putValue(
    308                                         SHORT_DESCRIPTION,
    309                                         tr("Jumps to the picture at the other side of the red line"));
    310                 }
    311 
    312                 @Override
    313                 public void actionPerformed(ActionEvent e) {
    314                         if (MapillaryToggleDialog.getInstance().getImage() != null) {
    315                                 MapillaryData.getInstance().setSelectedImage(
    316                                                 MapillaryLayer.RED, true);
    317                         }
    318                 }
    319         }
    320 
    321         /**
    322         * Action class to jump to the image following the blue line.
    323         *
    324         * @author nokutu
    325         *
    326         */
    327         class blueAction extends AbstractAction {
    328                 public blueAction() {
    329                         putValue(NAME, tr("Jump to blue"));
    330                         putValue(
    331                                         SHORT_DESCRIPTION,
    332                                         tr("Jumps to the picture at the other side of the blue line"));
    333                 }
    334 
    335                 @Override
    336                 public void actionPerformed(ActionEvent e) {
    337                         if (MapillaryToggleDialog.getInstance().getImage() != null) {
    338                                 MapillaryData.getInstance().setSelectedImage(
    339                                                 MapillaryLayer.BLUE, true);
    340                         }
    341                 }
    342         }
    343 
    344         /**
    345         * When the pictures are returned from the cache, they are set in the
    346         * {@link MapillaryImageDisplay} object.
    347         */
    348         @Override
    349         public void loadingFinished(CacheEntry data,
    350                         CacheEntryAttributes attributes, LoadResult result) {
    351                 if (!SwingUtilities.isEventDispatchThread()) {
    352                         SwingUtilities.invokeLater(new Runnable() {
    353                                 @Override
    354                                 public void run() {
    355                                         updateImage();
    356                                 }
    357                         });
    358                 } else if (data != null && result == LoadResult.SUCCESS) {
    359                         try {
    360                                 BufferedImage img = ImageIO.read(new ByteArrayInputStream(data
    361                                                 .getContent()));
    362                                 if (this.mapillaryImageDisplay.getImage() == null)
    363                                         mapillaryImageDisplay.setImage(img);
    364                                 else if (img.getHeight() > this.mapillaryImageDisplay
    365                                                 .getImage().getHeight()) {
    366                                         mapillaryImageDisplay.setImage(img);
    367                                 }
    368                         } catch (IOException e) {
    369                                 Main.error(e);
    370                         }
    371                 }
    372         }
    373 
    374         /**
    375         * Creates the layout of the dialog.
    376         *
    377         * @param data
    378         *            The content of the dialog
    379         * @param buttons
    380         *            The buttons where you can click
    381         * @param reverse
    382         *            {@code true} if the buttons should go at the top;
    383         *            {@code false} otherwise.
    384         */
    385         public void createLayout(Component data, List<SideButton> buttons,
    386                         boolean reverse) {
    387                 this.removeAll();
    388                 JPanel panel = new JPanel();
    389                 panel.setLayout(new BorderLayout());
    390                 panel.add(data, BorderLayout.CENTER);
    391                 if (reverse) {
    392                         buttonsPanel = new JPanel(new GridLayout(1, 1));
    393                         if (!buttons.isEmpty() && buttons.get(0) != null) {
    394                                 final JPanel buttonRowPanel = new JPanel(Main.pref.getBoolean(
    395                                                 "dialog.align.left", false) ? new FlowLayout(
    396                                                 FlowLayout.LEFT) : new GridLayout(1, buttons.size()));
    397                                 buttonsPanel.add(buttonRowPanel);
    398                                 for (SideButton button : buttons)
    399                                         buttonRowPanel.add(button);
    400                         }
    401                         panel.add(buttonsPanel, BorderLayout.NORTH);
    402                         createLayout(panel, true, null);
    403                 } else
    404                         createLayout(panel, true, buttons);
    405                 this.add(titleBar, BorderLayout.NORTH);
    406         }
    407 
    408         @Override
    409         public void selectedImageChanged(MapillaryAbstractImage oldImage,
    410                         MapillaryAbstractImage newImage) {
    411                 setImage(MapillaryData.getInstance().getSelectedImage());
    412                 updateImage();
    413         }
    414 
    415         /**
    416         * Action class to jump to the next picture containing a sign.
    417         *
    418         * @author nokutu
    419         *
    420         */
    421         class NextSignAction extends AbstractAction {
    422                 public NextSignAction() {
    423                         putValue(NAME, tr("Next Sign"));
    424                         putValue(SHORT_DESCRIPTION,
    425                                         tr("Jumps to the next picture that contains a sign"));
    426                 }
    427 
    428                 @Override
    429                 public void actionPerformed(ActionEvent e) {
    430                         if (MapillaryToggleDialog.getInstance().getImage() != null) {
    431                                 int i = MapillaryData
    432                                                 .getInstance()
    433                                                 .getImages()
    434                                                 .indexOf(MapillaryData.getInstance().getSelectedImage());
    435                                 for (int j = i + 1; j < MapillaryData.getInstance().getImages()
    436                                                 .size(); j++) {
    437                                         MapillaryAbstractImage img = MapillaryData.getInstance()
    438                                                         .getImages().get(j);
    439                                         if (img instanceof MapillaryImage)
    440                                                 if (!((MapillaryImage) img).getSigns().isEmpty()) {
    441                                                         MapillaryData.getInstance().setSelectedImage(img,
    442                                                                         true);
    443                                                         return;
    444                                                 }
    445                                 }
    446                         }
    447                 }
    448         }
    449 
    450         /**
    451         * Action class to jump to the previous picture containing a sign.
    452         *
    453         * @author nokutu
    454         *
    455         */
    456         class PreviousSignAction extends AbstractAction {
    457                 public PreviousSignAction() {
    458                         putValue(NAME, tr("Previous Sign"));
    459                         putValue(SHORT_DESCRIPTION,
    460                                         tr("Jumps to the previous picture that contains a sign"));
    461                 }
    462 
    463                 @Override
    464                 public void actionPerformed(ActionEvent e) {
    465                         if (MapillaryToggleDialog.getInstance().getImage() != null) {
    466                                 int i = MapillaryData
    467                                                 .getInstance()
    468                                                 .getImages()
    469                                                 .indexOf(MapillaryData.getInstance().getSelectedImage());
    470                                 for (int j = i - 1; j >= 0; j--) {
    471                                         MapillaryAbstractImage img = MapillaryData.getInstance()
    472                                                         .getImages().get(j);
    473                                         if (img instanceof MapillaryImage)
    474                                                 if (!((MapillaryImage) img).getSigns().isEmpty()) {
    475                                                         MapillaryData.getInstance().setSelectedImage(img,
    476                                                                         true);
    477                                                         return;
    478                                                 }
    479                                 }
    480                         }
    481                 }
    482         }
     45        ICachedLoaderListener, MapillaryDataListener {
     46
     47    public final static int NORMAL_MODE = 0;
     48    public final static int SIGN_MODE = 1;
     49
     50    public final static String BASE_TITLE = "Mapillary picture";
     51
     52    public static MapillaryToggleDialog INSTANCE;
     53
     54    public volatile MapillaryAbstractImage image;
     55
     56    public final SideButton nextButton = new SideButton(new nextPictureAction());
     57    public final SideButton previousButton = new SideButton(
     58            new previousPictureAction());
     59    public final SideButton redButton = new SideButton(new redAction());
     60    public final SideButton blueButton = new SideButton(new blueAction());
     61    private List<SideButton> normalMode;
     62
     63    public final SideButton nextSignButton = new SideButton(
     64            new NextSignAction());
     65    public final SideButton previousSignButton = new SideButton(
     66            new PreviousSignAction());
     67    private List<SideButton> signMode;
     68
     69    private int mode;
     70
     71    private JPanel buttonsPanel;
     72
     73    public MapillaryImageDisplay mapillaryImageDisplay;
     74
     75    private MapillaryCache imageCache;
     76    private MapillaryCache thumbnailCache;
     77
     78    public MapillaryToggleDialog() {
     79        super(tr(BASE_TITLE), "mapillary.png", tr("Open Mapillary window"),
     80                Shortcut.registerShortcut(tr("Mapillary dialog"),
     81                        tr("Open Mapillary main dialog"), KeyEvent.VK_M,
     82                        Shortcut.NONE), 200);
     83        MapillaryData.getInstance().addListener(this);
     84
     85        mapillaryImageDisplay = new MapillaryImageDisplay();
     86
     87        blueButton.setForeground(Color.BLUE);
     88        redButton.setForeground(Color.RED);
     89
     90        normalMode = Arrays.asList(new SideButton[] { blueButton,
     91                previousButton, nextButton, redButton });
     92        signMode = Arrays.asList(new SideButton[] { previousSignButton,
     93                nextSignButton });
     94
     95        mode = NORMAL_MODE;
     96
     97        createLayout(mapillaryImageDisplay, normalMode,
     98                Main.pref.getBoolean("mapillary.reverse-buttons"));
     99        disableAllButtons();
     100    }
     101
     102    public static MapillaryToggleDialog getInstance() {
     103        if (INSTANCE == null)
     104            INSTANCE = new MapillaryToggleDialog();
     105        return INSTANCE;
     106    }
     107
     108    public static void destroyInstance() {
     109        INSTANCE = null;
     110    }
     111
     112    /**
     113    * Switches from one mode to the other one.
     114    */
     115    public void switchMode() {
     116        this.removeAll();
     117        List<SideButton> list = null;
     118        if (mode == NORMAL_MODE) {
     119            list = signMode;
     120            mode = SIGN_MODE;
     121        } else if (mode == SIGN_MODE) {
     122            list = normalMode;
     123            mode = NORMAL_MODE;
     124        }
     125
     126        createLayout(mapillaryImageDisplay, list,
     127                Main.pref.getBoolean("mapillary.reverse-buttons"));
     128        disableAllButtons();
     129        updateImage();
     130    }
     131
     132    /**
     133    * Downloads the image of the selected MapillaryImage and sets in the
     134    * MapillaryImageDisplay object.
     135    */
     136    public synchronized void updateImage() {
     137        if (!SwingUtilities.isEventDispatchThread()) {
     138            SwingUtilities.invokeLater(new Runnable() {
     139                @Override
     140                public void run() {
     141                    updateImage();
     142                }
     143            });
     144        } else {
     145            if (MapillaryLayer.INSTANCE == null) {
     146                return;
     147            }
     148            if (this.image == null) {
     149                mapillaryImageDisplay.setImage(null);
     150                titleBar.setTitle(tr(BASE_TITLE));
     151                disableAllButtons();
     152                return;
     153            }
     154            if (image instanceof MapillaryImage) {
     155                mapillaryImageDisplay.hyperlink.setVisible(true);
     156                MapillaryImage mapillaryImage = (MapillaryImage) this.image;
     157                String title = tr(BASE_TITLE);
     158                if (mapillaryImage.getUser() != null)
     159                    title += " -- " + mapillaryImage.getUser();
     160                if (mapillaryImage.getCapturedAt() != 0)
     161                    title += " -- " + mapillaryImage.getDate();
     162                titleBar.setTitle(title);
     163                if (mode == NORMAL_MODE) {
     164                    this.nextButton.setEnabled(true);
     165                    this.previousButton.setEnabled(true);
     166                    if (mapillaryImage.next() == null)
     167                        this.nextButton.setEnabled(false);
     168                    if (mapillaryImage.previous() == null)
     169                        this.previousButton.setEnabled(false);
     170                } else if (mode == SIGN_MODE) {
     171                    previousSignButton.setEnabled(true);
     172                    nextSignButton.setEnabled(true);
     173                    int i = MapillaryData
     174                            .getInstance()
     175                            .getImages()
     176                            .indexOf(
     177                                    MapillaryData.getInstance()
     178                                            .getSelectedImage());
     179                    int first = -1;
     180                    int last = -1;
     181                    int c = 0;
     182                    for (MapillaryAbstractImage img : MapillaryData
     183                            .getInstance().getImages()) {
     184                        if (img instanceof MapillaryImage)
     185                            if (!((MapillaryImage) img).getSigns().isEmpty()) {
     186                                if (first == -1)
     187                                    first = c;
     188                                last = c;
     189                            }
     190                        c++;
     191                    }
     192                    if (first >= i)
     193                        previousSignButton.setEnabled(false);
     194                    if (last <= i)
     195                        nextSignButton.setEnabled(false);
     196                }
     197
     198                mapillaryImageDisplay.hyperlink.setURL(mapillaryImage.getKey());
     199                // Downloads the thumbnail.
     200                this.mapillaryImageDisplay.setImage(null);
     201                if (thumbnailCache != null)
     202                    thumbnailCache.cancelOutstandingTasks();
     203                thumbnailCache = new MapillaryCache(mapillaryImage.getKey(),
     204                        MapillaryCache.Type.THUMBNAIL);
     205                thumbnailCache.submit(this, false);
     206
     207                // Downloads the full resolution image.
     208                if (imageCache != null)
     209                    imageCache.cancelOutstandingTasks();
     210                imageCache = new MapillaryCache(mapillaryImage.getKey(),
     211                        MapillaryCache.Type.FULL_IMAGE);
     212                imageCache.submit(this, false);
     213            } else if (image instanceof MapillaryImportedImage) {
     214                mapillaryImageDisplay.hyperlink.setVisible(false);
     215                this.nextButton.setEnabled(false);
     216                this.previousButton.setEnabled(false);
     217                MapillaryImportedImage mapillaryImage = (MapillaryImportedImage) this.image;
     218                try {
     219                    mapillaryImageDisplay.setImage(mapillaryImage.getImage());
     220                } catch (IOException e) {
     221                    Main.error(e);
     222                }
     223                mapillaryImageDisplay.hyperlink.setURL(null);
     224            }
     225        }
     226    }
     227
     228    private void disableAllButtons() {
     229        nextButton.setEnabled(false);
     230        previousButton.setEnabled(false);
     231        blueButton.setEnabled(false);
     232        redButton.setEnabled(false);
     233        nextSignButton.setEnabled(false);
     234        previousSignButton.setEnabled(false);
     235        mapillaryImageDisplay.hyperlink.setVisible(false);
     236    }
     237
     238    /**
     239    * Sets a new MapillaryImage to be shown.
     240    *
     241    * @param image
     242    */
     243    public synchronized void setImage(MapillaryAbstractImage image) {
     244        this.image = image;
     245    }
     246
     247    /**
     248    * Returns the MapillaryImage objects which is being shown.
     249    *
     250    * @return
     251    */
     252    public synchronized MapillaryAbstractImage getImage() {
     253        return this.image;
     254    }
     255
     256    /**
     257    * Action class form the next image button.
     258    *
     259    * @author Jorge
     260    *
     261    */
     262    class nextPictureAction extends AbstractAction {
     263        public nextPictureAction() {
     264            putValue(NAME, tr("Next picture"));
     265            putValue(SHORT_DESCRIPTION,
     266                    tr("Shows the next picture in the sequence"));
     267        }
     268
     269        @Override
     270        public void actionPerformed(ActionEvent e) {
     271            if (MapillaryToggleDialog.getInstance().getImage() != null) {
     272                MapillaryData.getInstance().selectNext();
     273            }
     274        }
     275    }
     276
     277    /**
     278    * Action class for the previous image button.
     279    *
     280    * @author Jorge
     281    *
     282    */
     283    class previousPictureAction extends AbstractAction {
     284        public previousPictureAction() {
     285            putValue(NAME, tr("Previous picture"));
     286            putValue(SHORT_DESCRIPTION,
     287                    tr("Shows the previous picture in the sequence"));
     288        }
     289
     290        @Override
     291        public void actionPerformed(ActionEvent e) {
     292            if (MapillaryToggleDialog.getInstance().getImage() != null) {
     293                MapillaryData.getInstance().selectPrevious();
     294            }
     295        }
     296    }
     297
     298    /**
     299    * Action class to jump to the image following the red line.
     300    *
     301    * @author nokutu
     302    *
     303    */
     304    class redAction extends AbstractAction {
     305        public redAction() {
     306            putValue(NAME, tr("Jump to red"));
     307            putValue(
     308                    SHORT_DESCRIPTION,
     309                    tr("Jumps to the picture at the other side of the red line"));
     310        }
     311
     312        @Override
     313        public void actionPerformed(ActionEvent e) {
     314            if (MapillaryToggleDialog.getInstance().getImage() != null) {
     315                MapillaryData.getInstance().setSelectedImage(
     316                        MapillaryLayer.RED, true);
     317            }
     318        }
     319    }
     320
     321    /**
     322    * Action class to jump to the image following the blue line.
     323    *
     324    * @author nokutu
     325    *
     326    */
     327    class blueAction extends AbstractAction {
     328        public blueAction() {
     329            putValue(NAME, tr("Jump to blue"));
     330            putValue(
     331                    SHORT_DESCRIPTION,
     332                    tr("Jumps to the picture at the other side of the blue line"));
     333        }
     334
     335        @Override
     336        public void actionPerformed(ActionEvent e) {
     337            if (MapillaryToggleDialog.getInstance().getImage() != null) {
     338                MapillaryData.getInstance().setSelectedImage(
     339                        MapillaryLayer.BLUE, true);
     340            }
     341        }
     342    }
     343
     344    /**
     345    * When the pictures are returned from the cache, they are set in the
     346    * {@link MapillaryImageDisplay} object.
     347    */
     348    @Override
     349    public void loadingFinished(CacheEntry data,
     350            CacheEntryAttributes attributes, LoadResult result) {
     351        if (!SwingUtilities.isEventDispatchThread()) {
     352            SwingUtilities.invokeLater(new Runnable() {
     353                @Override
     354                public void run() {
     355                    updateImage();
     356                }
     357            });
     358        } else if (data != null && result == LoadResult.SUCCESS) {
     359            try {
     360                BufferedImage img = ImageIO.read(new ByteArrayInputStream(data
     361                        .getContent()));
     362                if (this.mapillaryImageDisplay.getImage() == null)
     363                    mapillaryImageDisplay.setImage(img);
     364                else if (img.getHeight() > this.mapillaryImageDisplay
     365                        .getImage().getHeight()) {
     366                    mapillaryImageDisplay.setImage(img);
     367                }
     368            } catch (IOException e) {
     369                Main.error(e);
     370            }
     371        }
     372    }
     373
     374    /**
     375    * Creates the layout of the dialog.
     376    *
     377    * @param data
     378    *            The content of the dialog
     379    * @param buttons
     380    *            The buttons where you can click
     381    * @param reverse
     382    *            {@code true} if the buttons should go at the top;
     383    *            {@code false} otherwise.
     384    */
     385    public void createLayout(Component data, List<SideButton> buttons,
     386            boolean reverse) {
     387        this.removeAll();
     388        JPanel panel = new JPanel();
     389        panel.setLayout(new BorderLayout());
     390        panel.add(data, BorderLayout.CENTER);
     391        if (reverse) {
     392            buttonsPanel = new JPanel(new GridLayout(1, 1));
     393            if (!buttons.isEmpty() && buttons.get(0) != null) {
     394                final JPanel buttonRowPanel = new JPanel(Main.pref.getBoolean(
     395                        "dialog.align.left", false) ? new FlowLayout(
     396                        FlowLayout.LEFT) : new GridLayout(1, buttons.size()));
     397                buttonsPanel.add(buttonRowPanel);
     398                for (SideButton button : buttons)
     399                    buttonRowPanel.add(button);
     400            }
     401            panel.add(buttonsPanel, BorderLayout.NORTH);
     402            createLayout(panel, true, null);
     403        } else
     404            createLayout(panel, true, buttons);
     405        this.add(titleBar, BorderLayout.NORTH);
     406    }
     407
     408    @Override
     409    public void selectedImageChanged(MapillaryAbstractImage oldImage,
     410            MapillaryAbstractImage newImage) {
     411        setImage(MapillaryData.getInstance().getSelectedImage());
     412        updateImage();
     413    }
     414
     415    /**
     416    * Action class to jump to the next picture containing a sign.
     417    *
     418    * @author nokutu
     419    *
     420    */
     421    class NextSignAction extends AbstractAction {
     422        public NextSignAction() {
     423            putValue(NAME, tr("Next Sign"));
     424            putValue(SHORT_DESCRIPTION,
     425                    tr("Jumps to the next picture that contains a sign"));
     426        }
     427
     428        @Override
     429        public void actionPerformed(ActionEvent e) {
     430            if (MapillaryToggleDialog.getInstance().getImage() != null) {
     431                int i = MapillaryData
     432                        .getInstance()
     433                        .getImages()
     434                        .indexOf(MapillaryData.getInstance().getSelectedImage());
     435                for (int j = i + 1; j < MapillaryData.getInstance().getImages()
     436                        .size(); j++) {
     437                    MapillaryAbstractImage img = MapillaryData.getInstance()
     438                            .getImages().get(j);
     439                    if (img instanceof MapillaryImage)
     440                        if (!((MapillaryImage) img).getSigns().isEmpty()) {
     441                            MapillaryData.getInstance().setSelectedImage(img,
     442                                    true);
     443                            return;
     444                        }
     445                }
     446            }
     447        }
     448    }
     449
     450    /**
     451    * Action class to jump to the previous picture containing a sign.
     452    *
     453    * @author nokutu
     454    *
     455    */
     456    class PreviousSignAction extends AbstractAction {
     457        public PreviousSignAction() {
     458            putValue(NAME, tr("Previous Sign"));
     459            putValue(SHORT_DESCRIPTION,
     460                    tr("Jumps to the previous picture that contains a sign"));
     461        }
     462
     463        @Override
     464        public void actionPerformed(ActionEvent e) {
     465            if (MapillaryToggleDialog.getInstance().getImage() != null) {
     466                int i = MapillaryData
     467                        .getInstance()
     468                        .getImages()
     469                        .indexOf(MapillaryData.getInstance().getSelectedImage());
     470                for (int j = i - 1; j >= 0; j--) {
     471                    MapillaryAbstractImage img = MapillaryData.getInstance()
     472                            .getImages().get(j);
     473                    if (img instanceof MapillaryImage)
     474                        if (!((MapillaryImage) img).getSigns().isEmpty()) {
     475                            MapillaryData.getInstance().setSelectedImage(img,
     476                                    true);
     477                            return;
     478                        }
     479                }
     480            }
     481        }
     482    }
    483483}
Note: See TracChangeset for help on using the changeset viewer.