Ignore:
Timestamp:
2013-11-18T03:05:56+01:00 (10 years ago)
Author:
Don-vip
Message:

fix #9274 - GeoImageLayer functionality enhancements (patch by holgerosm)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java

    r6316 r6392  
    2323import java.util.ArrayList;
    2424import java.util.Arrays;
     25import java.util.Calendar;
    2526import java.util.Collection;
    2627import java.util.Collections;
     28import java.util.Date;
     29import java.util.GregorianCalendar;
    2730import java.util.HashSet;
    2831import java.util.LinkedHashSet;
     
    3033import java.util.List;
    3134import java.util.Set;
     35import java.util.TimeZone;
    3236
    3337import javax.swing.Action;
     
    270274     */
    271275    public GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer) {
    272         super(tr("Geotagged Images"));
    273 
     276        this(data, gpxLayer, null, false);
     277    }
     278
     279    /**
     280     * Constructs a new {@code GeoImageLayer}.
     281     * @param data The list of images to display
     282     * @param gpxLayer The associated GPX layer
     283     * @param name Layer name
     284     * @since 6392
     285     */
     286    public GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer, final String name) {
     287        this(data, gpxLayer, name, false);
     288    }
     289
     290    /**
     291     * Constructs a new {@code GeoImageLayer}.
     292     * @param data The list of images to display
     293     * @param gpxLayer The associated GPX layer
     294     * @param useThumbs Thumbnail display flag
     295     * @since 6392
     296     */
     297    public GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer, boolean useThumbs) {
     298        this(data, gpxLayer, null, useThumbs);
     299    }
     300
     301    /**
     302     * Constructs a new {@code GeoImageLayer}.
     303     * @param data The list of images to display
     304     * @param gpxLayer The associated GPX layer
     305     * @param name Layer name
     306     * @param useThumbs Thumbnail display flag
     307     * @since 6392
     308     */
     309    public GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer, final String name, boolean useThumbs) {
     310        super(name != null ? name : tr("Geotagged Images"));
    274311        Collections.sort(data);
    275312        this.data = data;
    276313        this.gpxLayer = gpxLayer;
     314        this.useThumbs = useThumbs;
    277315    }
    278316
     
    403441        Rectangle clip = g.getClipBounds();
    404442        if (useThumbs) {
     443            if (!thumbsLoaded) {
     444                loadThumbs();
     445            }
     446
    405447            if (null == offscreenBuffer || offscreenBuffer.getWidth() != width  // reuse the old buffer if possible
    406448                    || offscreenBuffer.getHeight() != height) {
     
    458500                Point p = mv.getPoint(e.getPos());
    459501
    460                 if (e.thumbnail != null) {
     502                if (useThumbs && e.thumbnail != null) {
    461503                    Dimension d = scaledDimension(e.thumbnail);
    462504                    g.setColor(new Color(128, 0, 0, 122));
     
    572614            // Do nothing
    573615        }
     616
     617        // Time and date. We can have these cases:
     618        // 1) GPS_TIME_STAMP not set -> date/time will be null
     619        // 2) GPS_DATE_STAMP not set -> use EXIF date or set to default
     620        // 3) GPS_TIME_STAMP and GPS_DATE_STAMP are set
     621        int[] timeStampComps = dirGps.getIntArray(GpsDirectory.TAG_GPS_TIME_STAMP);
     622        if (timeStampComps != null) {
     623            int gpsHour = timeStampComps[0];
     624            int gpsMin = timeStampComps[1];
     625            int gpsSec = timeStampComps[2];
     626            Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
     627
     628            // We have the time. Next step is to check if the GPS date stamp is set.
     629            // dirGps.getString() always succeeds, but the return value might be null.
     630            String dateStampStr = dirGps.getString(GpsDirectory.TAG_GPS_DATE_STAMP);
     631            if (dateStampStr != null && dateStampStr.matches("^\\d+:\\d+:\\d+$")) {
     632                String[] dateStampComps = dateStampStr.split(":");
     633                cal.set(Calendar.YEAR, Integer.parseInt(dateStampComps[0]));
     634                cal.set(Calendar.MONTH, Integer.parseInt(dateStampComps[1]) - 1);
     635                cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dateStampComps[2]));
     636            }
     637            else {
     638                // No GPS date stamp in EXIF data.  Copy it from EXIF time.
     639                // Date is not set if EXIF time is not available.
     640                Date exifTime = e.getExifTime();
     641                if (exifTime != null) {
     642                    // Time not set yet, so we can copy everything, not just date.
     643                    cal.setTime(exifTime);
     644                }
     645            }
     646
     647            cal.set(Calendar.HOUR_OF_DAY, gpsHour);
     648            cal.set(Calendar.MINUTE, gpsMin);
     649            cal.set(Calendar.SECOND, gpsSec);
     650
     651            e.setExifGpsTime(cal.getTime());
     652        }
    574653    }
    575654
     
    668747    }
    669748
     749    /**
     750     * Removes a photo from the list of images by index.
     751     * @param idx Image index
     752     * @since 6392
     753     */
     754    public void removePhotoByIdx(int idx) {
     755        if (idx >= 0 && data != null && idx < data.size()) {
     756            data.remove(idx);
     757        }
     758    }
     759
     760    /**
     761     * Returns the image that matches the position of the mouse event.
     762     * @param evt Mouse event
     763     * @return Image at mouse position, or {@code null} if there is no image at the mouse position
     764     * @since 6392
     765     */
     766    public ImageEntry getPhotoUnderMouse(MouseEvent evt) {
     767        if (data != null) {
     768            for (int idx = data.size() - 1; idx >= 0; --idx) {
     769                ImageEntry img = data.get(idx);
     770                if (img.getPos() == null) {
     771                    continue;
     772                }
     773                Point p = Main.map.mapView.getPoint(img.getPos());
     774                Rectangle r;
     775                if (useThumbs && img.thumbnail != null) {
     776                    Dimension d = scaledDimension(img.thumbnail);
     777                    r = new Rectangle(p.x - d.width / 2, p.y - d.height / 2, d.width, d.height);
     778                } else {
     779                    r = new Rectangle(p.x - icon.getIconWidth() / 2,
     780                                      p.y - icon.getIconHeight() / 2,
     781                                      icon.getIconWidth(),
     782                                      icon.getIconHeight());
     783                }
     784                if (r.contains(evt.getPoint())) {
     785                    return img;
     786                }
     787            }
     788        }
     789        return null;
     790    }
     791
     792    /**
     793     * Clears the currentPhoto, i.e. remove select marker, and optionally repaint.
     794     * @param repaint Repaint flag
     795     * @since 6392
     796     */
     797    public void clearCurrentPhoto(boolean repaint) {
     798        currentPhoto = -1;
     799        if (repaint) {
     800            updateBufferAndRepaint();
     801        }
     802    }
     803
     804    /**
     805     * Clears the currentPhoto of the other GeoImageLayer's. Otherwise there could be multiple selected photos.
     806     */
     807    private void clearOtherCurrentPhotos() {
     808        for (GeoImageLayer layer:
     809                 Main.map.mapView.getLayersOfType(GeoImageLayer.class)) {
     810            if (layer != this) {
     811                layer.clearCurrentPhoto(false);
     812            }
     813        }
     814    }
     815
     816    private static List<MapMode> supportedMapModes = null;
     817
     818    /**
     819     * Registers a map mode for which the functionality of this layer should be available.
     820     * @param mapMode Map mode to be registered
     821     * @since 6392
     822     */
     823    public static void registerSupportedMapMode(MapMode mapMode) {
     824        if (supportedMapModes == null) {
     825            supportedMapModes = new ArrayList<MapMode>();
     826        }
     827        supportedMapModes.add(mapMode);
     828    }
     829
     830    /**
     831     * Determines if the functionality of this layer is available in
     832     * the specified map mode.  SelectAction is supported by default,
     833     * other map modes can be registered.
     834     * @param mapMode Map mode to be checked
     835     * @return {@code true} if the map mode is supported,
     836     *         {@code false} otherwise
     837     */
     838    private static final boolean isSupportedMapMode(MapMode mapMode) {
     839        if (mapMode instanceof SelectAction) return true;
     840        if (supportedMapModes != null) {
     841            for (MapMode supmmode: supportedMapModes) {
     842                if (mapMode == supmmode) {
     843                    return true;
     844                }
     845            }
     846        }
     847        return false;
     848    }
     849
    670850    private MouseAdapter mouseAdapter = null;
    671851    private MapModeChangeListener mapModeListener = null;
     
    675855        mouseAdapter = new MouseAdapter() {
    676856            private final boolean isMapModeOk() {
    677                 return Main.map.mapMode == null || Main.map.mapMode instanceof SelectAction;
     857                return Main.map.mapMode == null || isSupportedMapMode(Main.map.mapMode);
    678858            }
    679859            @Override public void mousePressed(MouseEvent e) {
     
    699879                    Point p = Main.map.mapView.getPoint(e.getPos());
    700880                    Rectangle r;
    701                     if (e.thumbnail != null) {
     881                    if (useThumbs && e.thumbnail != null) {
    702882                        Dimension d = scaledDimension(e.thumbnail);
    703883                        r = new Rectangle(p.x - d.width / 2, p.y - d.height / 2, d.width, d.height);
     
    709889                    }
    710890                    if (r.contains(ev.getPoint())) {
     891                        clearOtherCurrentPhotos();
    711892                        currentPhoto = i;
    712893                        ImageViewerDialog.showImage(GeoImageLayer.this, e);
     
    721902            @Override
    722903            public void mapModeChange(MapMode oldMapMode, MapMode newMapMode) {
    723                 if (newMapMode == null || (newMapMode instanceof org.openstreetmap.josm.actions.mapmode.SelectAction)) {
     904                if (newMapMode == null || isSupportedMapMode(newMapMode)) {
    724905                    Main.map.mapView.addMouseListener(mouseAdapter);
    725906                } else {
     
    816997        showPreviousPhoto();
    817998    }
     999
     1000    /**
     1001     * Returns the current thumbnail display status.
     1002     * {@code true}: thumbnails are displayed, {@code false}: an icon is displayed instead of thumbnails.
     1003     * @return Current thumbnail display status
     1004     * @since 6392
     1005     */
     1006    public boolean isUseThumbs() {
     1007        return useThumbs;
     1008    }
     1009
     1010    /**
     1011     * Enables or disables the display of thumbnails.  Does not update the display.
     1012     * @param useThumbs New thumbnail display status
     1013     * @since 6392
     1014     */
     1015    public void setUseThumbs(boolean useThumbs) {
     1016        this.useThumbs = useThumbs;
     1017        if (useThumbs && !thumbsLoaded) {
     1018            loadThumbs();
     1019        }
     1020    }
    8181021}
Note: See TracChangeset for help on using the changeset viewer.