Ignore:
Timestamp:
2015-06-23T12:17:27+02:00 (9 years ago)
Author:
nokutu
Message:

Fixed bug when putting action from menu into upper bar (they were diasbled) and bug regarding the creation of new ways in the OSM data layer

Location:
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary
Files:
1 deleted
6 edited

Legend:

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

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

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

    r31297 r31298  
    3333public class MapillaryPlugin extends Plugin implements EditLayerChangeListener {
    3434
    35     public static final ImageIcon ICON24 = new ImageProvider("icon24.png")
    36             .get();
    37     public static final ImageIcon ICON16 = new ImageProvider("icon16.png")
    38             .get();
    39     public static final ImageIcon MAP_ICON = new ImageProvider("mapicon.png")
    40             .get();
    41     public static final ImageIcon MAP_ICON_SELECTED = new ImageProvider(
    42             "mapiconselected.png").get();
    43     public static final ImageIcon MAP_ICON_IMPORTED = new ImageProvider(
    44             "mapiconimported.png").get();
    45     public static final ImageIcon MAP_SIGN = new ImageProvider("sign.png")
    46             .get();
    47     public static final int ICON_SIZE = 24;
     35        public static final ImageIcon ICON24 = new ImageProvider("icon24.png")
     36                        .get();
     37        public static final ImageIcon ICON16 = new ImageProvider("icon16.png")
     38                        .get();
     39        public static final ImageIcon MAP_ICON = new ImageProvider("mapicon.png")
     40                        .get();
     41        public static final ImageIcon MAP_ICON_SELECTED = new ImageProvider(
     42                        "mapiconselected.png").get();
     43        public static final ImageIcon MAP_ICON_IMPORTED = new ImageProvider(
     44                        "mapiconimported.png").get();
     45        public static final ImageIcon MAP_SIGN = new ImageProvider("sign.png")
     46                        .get();
     47        public static final int ICON_SIZE = 24;
    4848
    49     public static CacheAccess<String, BufferedImageCacheEntry> CACHE;
     49        public static CacheAccess<String, BufferedImageCacheEntry> CACHE;
    5050
    51     private final MapillaryDownloadAction downloadAction;
    52     private final MapillaryExportAction exportAction;
    53     private final MapillaryImportAction importAction;
    54     private final MapillarySignAction signAction;
    55     private final MapillaryZoomAction zoomAction;
    56     private final MapillaryDownloadViewAction downloadViewAction;
     51        private final MapillaryDownloadAction downloadAction;
     52        private final MapillaryExportAction exportAction;
     53        private final MapillaryImportAction importAction;
     54        private final MapillaryZoomAction zoomAction;
     55        private final MapillaryDownloadViewAction downloadViewAction;
    5756
    58     public static JMenuItem DOWNLOAD_MENU;
    59     public static JMenuItem EXPORT_MENU;
    60     public static JMenuItem IMPORT_MENU;
    61     public static JMenuItem SIGN_MENU;
    62     public static JMenuItem ZOOM_MENU;
    63     public static JMenuItem DOWNLOAD_VIEW_MENU;
     57        public static JMenuItem DOWNLOAD_MENU;
     58        public static JMenuItem EXPORT_MENU;
     59        public static JMenuItem IMPORT_MENU;
     60        public static JMenuItem ZOOM_MENU;
     61        public static JMenuItem DOWNLOAD_VIEW_MENU;
    6462
    65     public MapillaryPlugin(PluginInformation info) {
    66         super(info);
    67         downloadAction = new MapillaryDownloadAction();
    68         exportAction = new MapillaryExportAction();
    69         importAction = new MapillaryImportAction();
    70         signAction = new MapillarySignAction();
    71         zoomAction = new MapillaryZoomAction();
    72         downloadViewAction = new MapillaryDownloadViewAction();
     63        public MapillaryPlugin(PluginInformation info) {
     64                super(info);
     65                downloadAction = new MapillaryDownloadAction();
     66                exportAction = new MapillaryExportAction();
     67                importAction = new MapillaryImportAction();
     68                zoomAction = new MapillaryZoomAction();
     69                downloadViewAction = new MapillaryDownloadViewAction();
    7370
    74         DOWNLOAD_MENU = MainMenu.add(Main.main.menu.imageryMenu,
    75                 downloadAction, false);
    76         EXPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, exportAction,
    77                 false, 14);
    78         IMPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, importAction,
    79                 false, 14);
    80         SIGN_MENU = MainMenu.add(Main.main.menu.dataMenu, signAction, false);
    81         ZOOM_MENU = MainMenu
    82                 .add(Main.main.menu.viewMenu, zoomAction, false, 15);
    83         DOWNLOAD_VIEW_MENU = MainMenu.add(Main.main.menu.fileMenu,
    84                 downloadViewAction, false, 14);
     71                DOWNLOAD_MENU = MainMenu.add(Main.main.menu.imageryMenu,
     72                                downloadAction, false);
     73                EXPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, exportAction,
     74                                false, 14);
     75                IMPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, importAction,
     76                                false, 14);
     77                ZOOM_MENU = MainMenu
     78                                .add(Main.main.menu.viewMenu, zoomAction, false, 15);
     79                DOWNLOAD_VIEW_MENU = MainMenu.add(Main.main.menu.fileMenu,
     80                                downloadViewAction, false, 14);
    8581
    86         EXPORT_MENU.setEnabled(false);
    87         DOWNLOAD_MENU.setEnabled(false);
    88         IMPORT_MENU.setEnabled(false);
    89         SIGN_MENU.setEnabled(false);
    90         ZOOM_MENU.setEnabled(false);
    91         DOWNLOAD_VIEW_MENU.setEnabled(false);
     82                EXPORT_MENU.setEnabled(false);
     83                DOWNLOAD_MENU.setEnabled(false);
     84                IMPORT_MENU.setEnabled(false);
     85                ZOOM_MENU.setEnabled(false);
     86                DOWNLOAD_VIEW_MENU.setEnabled(false);
    9287
    93         MapView.addEditLayerChangeListener(this);
    94         try {
    95             CACHE = JCSCacheManager.getCache("mapillary", 10, 10000,
    96                     this.getPluginDir() + "/cache/");
    97         } catch (IOException e) {
    98             Main.error(e);
    99         }
    100     }
     88                MapView.addEditLayerChangeListener(this);
     89                try {
     90                        CACHE = JCSCacheManager.getCache("mapillary", 10, 10000,
     91                                        this.getPluginDir() + "/cache/");
     92                } catch (IOException e) {
     93                        Main.error(e);
     94                }
     95        }
    10196
    102     /**
    103      * Called when the JOSM map frame is created or destroyed.
    104      */
    105     @Override
    106     public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
    107         if (oldFrame == null && newFrame != null) { // map frame added
    108             Main.map.addToggleDialog(MapillaryToggleDialog.getInstance(), false);
    109             Main.map.addToggleDialog(MapillaryHistoryDialog.getInstance(), false);
    110             Main.map.addToggleDialog(MapillaryFilterDialog.getInstance(), false);
    111         }
    112         if (oldFrame != null && newFrame == null) { // map frame destroyed
    113             MapillaryToggleDialog.destroyInstance();
    114             MapillaryHistoryDialog.destroyInstance();
    115             MapillaryFilterDialog.destroyInstance();
    116         }
    117     }
     97        /**
     98         * Called when the JOSM map frame is created or destroyed.
     99         */
     100        @Override
     101        public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
     102                if (oldFrame == null && newFrame != null) { // map frame added
     103                        Main.map.addToggleDialog(MapillaryToggleDialog.getInstance(), false);
     104                        Main.map.addToggleDialog(MapillaryHistoryDialog.getInstance(),
     105                                        false);
     106                        Main.map.addToggleDialog(MapillaryFilterDialog.getInstance(), false);
     107                }
     108                if (oldFrame != null && newFrame == null) { // map frame destroyed
     109                        MapillaryToggleDialog.destroyInstance();
     110                        MapillaryHistoryDialog.destroyInstance();
     111                        MapillaryFilterDialog.destroyInstance();
     112                }
     113        }
    118114
    119     public static void setMenuEnabled(JMenuItem menu, boolean value) {
    120         menu.setEnabled(value);
    121     }
     115        public static void setMenuEnabled(JMenuItem menu, boolean value) {
     116                menu.setEnabled(value);
     117                menu.getAction().setEnabled(value);
     118        }
    122119
    123     @Override
    124     public PreferenceSetting getPreferenceSetting() {
    125         return new MapillaryPreferenceSetting();
    126     }
     120        @Override
     121        public PreferenceSetting getPreferenceSetting() {
     122                return new MapillaryPreferenceSetting();
     123        }
    127124
    128     @Override
    129     public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
    130         if (oldLayer == null && newLayer != null) {
    131             setMenuEnabled(DOWNLOAD_MENU, true);
    132             setMenuEnabled(IMPORT_MENU, true);
    133             setMenuEnabled(DOWNLOAD_VIEW_MENU, true);
    134         } else if (oldLayer != null && newLayer == null) {
    135             setMenuEnabled(DOWNLOAD_MENU, false);
    136             setMenuEnabled(IMPORT_MENU, false);
    137             setMenuEnabled(DOWNLOAD_VIEW_MENU, false);
    138         }
    139     }
     125        @Override
     126        public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
     127                if (oldLayer == null && newLayer != null) {
     128                        setMenuEnabled(DOWNLOAD_MENU, true);
     129                        if (Main.pref.getBoolean("mapillary.download-manually"))
     130                                setMenuEnabled(IMPORT_MENU, true);
     131                        setMenuEnabled(DOWNLOAD_VIEW_MENU, true);
     132                } else if (oldLayer != null && newLayer == null) {
     133                        setMenuEnabled(DOWNLOAD_MENU, false);
     134                        setMenuEnabled(IMPORT_MENU, false);
     135                        setMenuEnabled(DOWNLOAD_VIEW_MENU, false);
     136                }
     137        }
    140138}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySequenceDownloadThread.java

    r31278 r31298  
    7979                                "captured_at").longValue());
    8080
    81                 int first = -1;
    82                 int last = -1;
    83                 int pos = 0;
     81               
    8482
     83                List<MapillaryImage> finalImages = new ArrayList<>(images);
    8584                // Here it gets only those images which are in the downloaded
    8685                // area.
    8786                for (MapillaryAbstractImage img : images) {
    88                     if (first == -1 && isInside(img))
    89                         first = pos;
    90                     else if (first != -1 && last == -1 && !isInside(img))
    91                         last = pos;
    92                     else if (last != -1 && isInside(img))
    93                         last = -1;
    94                     pos++;
     87                    if (!isInside(img))
     88                        finalImages.remove(img);
    9589                }
    96                 if (last == -1) {
    97                     last = pos;
    98                 }
    99                 if (first == -1)
    100                     continue;
    101                 List<MapillaryImage> finalImages = images.subList(first, last);
     90               
    10291                for (MapillaryImage img : finalImages) {
    10392                    MapillaryData.getInstance().getImages().remove(img);
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryPreferenceSetting.java

    r31296 r31298  
    1212import org.openstreetmap.josm.gui.preferences.SubPreferenceSetting;
    1313import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting;
     14import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin;
    1415
    1516public class MapillaryPreferenceSetting implements SubPreferenceSetting {
     
    5152        Main.pref.put("mapillary.reverse-buttons", reverseButtons.isSelected());
    5253        Main.pref.put("mapillary.download-manually", downloadMode.isSelected());
     54        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.DOWNLOAD_VIEW_MENU, downloadMode.isSelected());
     55       
    5356        Main.pref.put("mapillary.display-hour", displayHour.isSelected());
    5457        Main.pref.put("mapillary.format-24", format24.isSelected());
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryToggleDialog.java

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