Changeset 18034 in josm for trunk


Ignore:
Timestamp:
2021-07-15T22:02:36+02:00 (3 years ago)
Author:
Don-vip
Message:

fix #20795 - fix #20797 - fix wrong correlate to gpx behaviour (patch by Bjoeni)

Location:
trunk/src/org/openstreetmap/josm
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java

    r17878 r18034  
    169169            }
    170170        }
    171         if (trkTag) {
     171        if (trkTag && prevWp != null) {
    172172            ret += matchPoints(images, prevWp, prevWpTime, prevWp, prevWpTime, offset, false, trkTagTime, true);
    173173        }
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java

    r17910 r18034  
    2222import java.awt.event.WindowAdapter;
    2323import java.awt.event.WindowEvent;
     24import java.beans.PropertyChangeEvent;
     25import java.beans.PropertyChangeListener;
    2426import java.io.File;
    2527import java.io.IOException;
     
    4042import java.util.TimeZone;
    4143import java.util.concurrent.TimeUnit;
     44import java.util.function.Consumer;
    4245import java.util.stream.Collectors;
    4346
     
    99102import org.openstreetmap.josm.spi.preferences.Config;
    100103import org.openstreetmap.josm.spi.preferences.IPreferences;
     104import org.openstreetmap.josm.tools.Destroyable;
    101105import org.openstreetmap.josm.tools.GBC;
    102106import org.openstreetmap.josm.tools.ImageProvider;
     
    112116 * @since 2566
    113117 */
    114 public class CorrelateGpxWithImages extends AbstractAction {
    115 
    116     private static final List<GpxData> loadedGpxData = new ArrayList<>();
     118public class CorrelateGpxWithImages extends AbstractAction implements Destroyable {
     119
     120    private static MutableComboBoxModel<GpxDataWrapper> gpxModel;
     121    private static boolean forceTags;
    117122
    118123    private final transient GeoImageLayer yLayer;
    119124    private transient GpxTimezone timezone;
    120125    private transient GpxTimeOffset delta;
    121     private static boolean forceTags;
    122126
    123127    /**
     
    129133        new ImageProvider("dialogs/geoimage/gpx2img").getResource().attachImageIcon(this, true);
    130134        this.yLayer = layer;
    131         MainApplication.getLayerManager().addLayerChangeListener(new GpxLayerAddedListener());
    132135    }
    133136
     
    232235
    233236    private static class GpxDataWrapper {
    234         private final String name;
     237        private String name;
    235238        private final GpxData data;
    236239        private final File file;
     
    242245        }
    243246
     247        void setName(String name) {
     248            this.name = name;
     249            forEachLayer(CorrelateGpxWithImages::repaintCombobox);
     250        }
     251
    244252        @Override
    245253        public String toString() {
     
    248256    }
    249257
     258    private static class NoGpxDataWrapper extends GpxDataWrapper {
     259        NoGpxDataWrapper() {
     260            super(null, null, null);
     261        }
     262
     263        @Override
     264        public String toString() {
     265            return tr("<No GPX track loaded yet>");
     266        }
     267    }
     268
    250269    private ExtendedDialog syncDialog;
    251     private MutableComboBoxModel<GpxDataWrapper> gpxModel;
    252270    private JPanel outerPanel;
    253271    private JosmComboBox<GpxDataWrapper> cbGpx;
     
    279297            try {
    280298                outerPanel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    281                 for (int i = gpxModel.getSize() - 1; i >= 0; i--) {
    282                     GpxDataWrapper wrapper = gpxModel.getElementAt(i);
    283                     if (sel.equals(wrapper.file)) {
    284                         gpxModel.setSelectedItem(wrapper);
    285                         if (!sel.getName().equals(wrapper.name)) {
    286                             JOptionPane.showMessageDialog(
    287                                     MainApplication.getMainFrame(),
    288                                     tr("File {0} is loaded yet under the name \"{1}\"", sel.getName(), wrapper.name),
    289                                     tr("Error"),
    290                                     JOptionPane.ERROR_MESSAGE
    291                             );
    292                         }
    293                         return;
    294                     }
    295                 }
     299                removeDuplicates(sel);
    296300                GpxData data = null;
    297301                try (InputStream iStream = Compression.getUncompressedFileInputStream(sel)) {
     
    321325                }
    322326
    323                 loadedGpxData.add(data);
    324                 if (gpxModel.getElementAt(0).file == null) {
    325                     gpxModel.removeElementAt(0);
    326                 }
    327327                GpxDataWrapper elem = new GpxDataWrapper(sel.getName(), data, sel);
    328328                gpxModel.addElement(elem);
    329329                gpxModel.setSelectedItem(elem);
     330                statusBarUpdater.matchAndUpdateStatusBar();
    330331            } finally {
    331332                outerPanel.setCursor(Cursor.getDefaultCursor());
     
    526527                forceTags = cForce.isSelected(); // This setting is not supposed to be saved permanently
    527528
    528                 statusBarUpdater.updateStatusBar();
     529                statusBarUpdater.matchAndUpdateStatusBar();
    529530                yLayer.updateBufferAndRepaint();
    530531            }
     
    767768
    768769            }
    769             statusBarUpdater.updateStatusBar();
     770            statusBarUpdater.matchAndUpdateStatusBar();
    770771            yLayer.updateBufferAndRepaint();
    771772        }
     
    790791    }
    791792
    792     private class GpxLayerAddedListener implements LayerChangeListener {
     793    private static class GpxLayerAddedListener implements LayerChangeListener {
    793794        @Override
    794795        public void layerAdded(LayerAddEvent e) {
    795             if (syncDialog != null && syncDialog.isVisible()) {
    796                 Layer layer = e.getAddedLayer();
    797                 if (layer instanceof GpxLayer) {
    798                     GpxLayer gpx = (GpxLayer) layer;
    799                     GpxDataWrapper gdw = new GpxDataWrapper(gpx.getName(), gpx.data, gpx.data.storageFile);
    800                     if (gpxModel.getElementAt(0).file == null) {
    801                         gpxModel.removeElementAt(0);
    802                     }
    803                     gpxModel.addElement(gdw);
    804                 }
     796            Layer layer = e.getAddedLayer();
     797            if (layer instanceof GpxLayer) {
     798                GpxLayer gpx = (GpxLayer) layer;
     799                File file = gpx.data.storageFile;
     800                removeDuplicates(file);
     801                GpxDataWrapper gdw = new GpxDataWrapper(gpx.getName(), gpx.data, file);
     802                gpx.addPropertyChangeListener(new GpxLayerRenamedListener(gdw));
     803                gpxModel.addElement(gdw);
     804                forEachLayer(CorrelateGpxWithImages::repaintCombobox);
    805805            }
    806806        }
     
    817817    }
    818818
     819    private static class GpxLayerRenamedListener implements PropertyChangeListener {
     820        private GpxDataWrapper gdw;
     821        GpxLayerRenamedListener(GpxDataWrapper gdw) {
     822            this.gdw = gdw;
     823        }
     824
     825        @Override
     826        public void propertyChange(PropertyChangeEvent e) {
     827            if (Layer.NAME_PROP.equals(e.getPropertyName())) {
     828                gdw.setName(e.getNewValue().toString());
     829            }
     830        }
     831    }
     832
    819833    @Override
    820834    public void actionPerformed(ActionEvent ae) {
    821         // Construct the list of loaded GPX tracks
    822         gpxModel = new DefaultComboBoxModel<>();
    823         GpxDataWrapper defaultItem = null;
    824         for (GpxLayer cur : MainApplication.getLayerManager().getLayersOfType(GpxLayer.class).stream()
    825                 .filter(GpxLayer::isLocalFile).collect(Collectors.toList())) {
    826             GpxDataWrapper gdw = new GpxDataWrapper(cur.getName(), cur.data, cur.data.storageFile);
    827             gpxModel.addElement(gdw);
    828             if (cur == yLayer.gpxLayer || (defaultItem == null && gdw.file != null)) {
    829                 defaultItem = gdw;
    830             }
    831         }
    832         for (GpxData data : loadedGpxData) {
    833             GpxDataWrapper gdw = new GpxDataWrapper(data.storageFile.getName(), data, data.storageFile);
    834             gpxModel.addElement(gdw);
    835             if (defaultItem == null && gdw.file != null) { // select first GPX track associated to a file
    836                 defaultItem = gdw;
    837             }
    838         }
    839 
    840         GpxDataWrapper nogdw = new GpxDataWrapper(tr("<No GPX track loaded yet>"), null, null);
    841         if (gpxModel.getSize() == 0) {
    842             gpxModel.addElement(nogdw);
    843         } else if (defaultItem != null) {
    844             gpxModel.setSelectedItem(defaultItem);
     835        NoGpxDataWrapper nogdw = new NoGpxDataWrapper();
     836        if (gpxModel == null) {
     837            // Construct the list of loaded GPX tracks
     838            gpxModel = new DefaultComboBoxModel<>();
     839            GpxDataWrapper defaultItem = null;
     840            for (GpxLayer cur : MainApplication.getLayerManager().getLayersOfType(GpxLayer.class)) {
     841                GpxDataWrapper gdw = new GpxDataWrapper(cur.getName(), cur.data, cur.data.storageFile);
     842                cur.addPropertyChangeListener(new GpxLayerRenamedListener(gdw));
     843                gpxModel.addElement(gdw);
     844                if (cur == yLayer.gpxLayer || defaultItem == null) {
     845                    defaultItem = gdw;
     846                }
     847            }
     848
     849            if (gpxModel.getSize() == 0) {
     850                gpxModel.addElement(nogdw);
     851            } else if (defaultItem != null) {
     852                gpxModel.setSelectedItem(defaultItem);
     853            }
     854            MainApplication.getLayerManager().addLayerChangeListener(new GpxLayerAddedListener());
    845855        }
    846856
     
    10101020        cbTaggedImg.addItemListener(statusBarUpdaterWithRepaint);
    10111021
    1012         statusBarUpdater.updateStatusBar();
     1022        statusBarUpdater.matchAndUpdateStatusBar();
    10131023        yLayer.updateBufferAndRepaint();
    10141024
     
    10171027
    10181028        if (!GraphicsEnvironment.isHeadless()) {
     1029            forEachLayer(CorrelateGpxWithImages::closeDialog);
    10191030            syncDialog = new ExtendedDialog(
    10201031                    MainApplication.getMainFrame(),
     
    10341045    }
    10351046
     1047    private static void removeDuplicates(File file) {
     1048        for (int i = gpxModel.getSize() - 1; i >= 0; i--) {
     1049            GpxDataWrapper wrapper = gpxModel.getElementAt(i);
     1050            if (wrapper instanceof NoGpxDataWrapper || (file != null && file.equals(wrapper.file))) {
     1051                gpxModel.removeElement(wrapper);
     1052            }
     1053        }
     1054    }
     1055
     1056    private static void forEachLayer(Consumer<CorrelateGpxWithImages> action) {
     1057        MainApplication.getLayerManager().getLayersOfType(GeoImageLayer.class)
     1058                .forEach(geo -> action.accept(geo.getGpxCorrelateAction()));
     1059    }
     1060
    10361061    private final transient StatusBarUpdater statusBarUpdater = new StatusBarUpdater(false);
    10371062    private final transient StatusBarUpdater statusBarUpdaterWithRepaint = new StatusBarUpdater(true);
     
    10461071        @Override
    10471072        public void insertUpdate(DocumentEvent ev) {
    1048             updateStatusBar();
     1073            matchAndUpdateStatusBar();
    10491074        }
    10501075
    10511076        @Override
    10521077        public void removeUpdate(DocumentEvent ev) {
    1053             updateStatusBar();
     1078            matchAndUpdateStatusBar();
    10541079        }
    10551080
     
    10611086        @Override
    10621087        public void itemStateChanged(ItemEvent e) {
    1063             updateStatusBar();
     1088            matchAndUpdateStatusBar();
    10641089        }
    10651090
    10661091        @Override
    10671092        public void actionPerformed(ActionEvent e) {
    1068             updateStatusBar();
    1069         }
    1070 
    1071         public void updateStatusBar() {
    1072             statusBarText.setText(statusText());
    1073             if (doRepaint) {
    1074                 yLayer.updateBufferAndRepaint();
    1075             }
    1076         }
    1077 
    1078         private String statusText() {
     1093            matchAndUpdateStatusBar();
     1094        }
     1095
     1096        public void matchAndUpdateStatusBar() {
     1097            if (syncDialog != null && syncDialog.isVisible()) {
     1098                statusBarText.setText(matchAndGetStatusText());
     1099                if (doRepaint) {
     1100                    yLayer.updateBufferAndRepaint();
     1101                }
     1102            }
     1103        }
     1104
     1105        private String matchAndGetStatusText() {
    10791106            try {
    10801107                timezone = GpxTimezone.parseTimezone(tfTimezone.getText().trim());
     
    11991226                            "Time difference of {0} days", Math.abs(dayOffset), Math.abs(dayOffset)));
    12001227
    1201                     statusBarUpdater.updateStatusBar();
     1228                    statusBarUpdater.matchAndUpdateStatusBar();
    12021229                    yLayer.updateBufferAndRepaint();
    12031230                }
     
    12511278
    12521279    static class NoGpxTimestamps extends Exception {
     1280    }
     1281
     1282    void closeDialog() {
     1283        if (syncDialog != null) {
     1284            syncDialog.setVisible(false);
     1285            new SyncDialogWindowListener().windowDeactivated(null);
     1286            syncDialog.dispose();
     1287            syncDialog = null;
     1288        }
     1289    }
     1290
     1291    void repaintCombobox() {
     1292        if (cbGpx != null) {
     1293            cbGpx.repaint();
     1294        }
    12531295    }
    12541296
     
    13181360            tfOffset.getDocument().addDocumentListener(statusBarUpdater);
    13191361
    1320             statusBarUpdater.updateStatusBar();
     1362            statusBarUpdater.matchAndUpdateStatusBar();
    13211363            yLayer.updateBufferAndRepaint();
    13221364        }
     
    13461388        Object item = gpxModel.getSelectedItem();
    13471389
    1348         if (item == null || ((GpxDataWrapper) item).file == null) {
     1390        if (item == null || ((GpxDataWrapper) item).data == null) {
    13491391            if (complain) {
    13501392                JOptionPane.showMessageDialog(MainApplication.getMainFrame(), tr("You should select a GPX track"),
     
    13561398    }
    13571399
     1400    @Override
     1401    public void destroy() {
     1402        if (cbGpx != null) {
     1403            // Force the JCombobox to remove its eventListener from the static GpxDataWrapper
     1404            cbGpx.setModel(new DefaultComboBoxModel<GpxDataWrapper>());
     1405            cbGpx = null;
     1406        }
     1407        closeDialog();
     1408    }
     1409
    13581410}
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java

    r17548 r18034  
    8282    GpxLayer gpxFauxLayer;
    8383
     84    private CorrelateGpxWithImages gpxCorrelateAction;
     85
    8486    private final Icon icon = ImageProvider.get("dialogs/geoimage/photo-marker");
    8587    private final Icon selectedIcon = ImageProvider.get("dialogs/geoimage/photo-marker-selected");
     
    406408        entries.add(new RenameLayerAction(null, this));
    407409        entries.add(SeparatorLayerAction.INSTANCE);
    408         entries.add(new CorrelateGpxWithImages(this));
     410        entries.add(getGpxCorrelateAction());
    409411        entries.add(new ShowThumbnailAction(this));
    410412        if (!menuAdditions.isEmpty()) {
     
    852854        super.destroy();
    853855        stopLoadThumbs();
     856        if (gpxCorrelateAction != null) {
     857            gpxCorrelateAction.destroy();
     858            gpxCorrelateAction = null;
     859        }
    854860        MapView mapView = MainApplication.getMap().mapView;
    855861        mapView.removeMouseListener(mouseAdapter);
     
    942948    public GpxLayer getGpxLayer() {
    943949        return gpxLayer;
     950    }
     951
     952    /**
     953     * Returns the gpxCorrelateAction
     954     * @return the gpxCorrelateAction
     955     */
     956    public CorrelateGpxWithImages getGpxCorrelateAction() {
     957        if (gpxCorrelateAction == null) {
     958            gpxCorrelateAction = new CorrelateGpxWithImages(this);
     959        }
     960        return gpxCorrelateAction;
    944961    }
    945962
Note: See TracChangeset for help on using the changeset viewer.