- Timestamp:
- 2021-07-15T22:02:36+02:00 (3 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java
r17878 r18034 169 169 } 170 170 } 171 if (trkTag ) {171 if (trkTag && prevWp != null) { 172 172 ret += matchPoints(images, prevWp, prevWpTime, prevWp, prevWpTime, offset, false, trkTagTime, true); 173 173 } -
trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java
r17910 r18034 22 22 import java.awt.event.WindowAdapter; 23 23 import java.awt.event.WindowEvent; 24 import java.beans.PropertyChangeEvent; 25 import java.beans.PropertyChangeListener; 24 26 import java.io.File; 25 27 import java.io.IOException; … … 40 42 import java.util.TimeZone; 41 43 import java.util.concurrent.TimeUnit; 44 import java.util.function.Consumer; 42 45 import java.util.stream.Collectors; 43 46 … … 99 102 import org.openstreetmap.josm.spi.preferences.Config; 100 103 import org.openstreetmap.josm.spi.preferences.IPreferences; 104 import org.openstreetmap.josm.tools.Destroyable; 101 105 import org.openstreetmap.josm.tools.GBC; 102 106 import org.openstreetmap.josm.tools.ImageProvider; … … 112 116 * @since 2566 113 117 */ 114 public class CorrelateGpxWithImages extends AbstractAction { 115 116 private static final List<GpxData> loadedGpxData = new ArrayList<>(); 118 public class CorrelateGpxWithImages extends AbstractAction implements Destroyable { 119 120 private static MutableComboBoxModel<GpxDataWrapper> gpxModel; 121 private static boolean forceTags; 117 122 118 123 private final transient GeoImageLayer yLayer; 119 124 private transient GpxTimezone timezone; 120 125 private transient GpxTimeOffset delta; 121 private static boolean forceTags;122 126 123 127 /** … … 129 133 new ImageProvider("dialogs/geoimage/gpx2img").getResource().attachImageIcon(this, true); 130 134 this.yLayer = layer; 131 MainApplication.getLayerManager().addLayerChangeListener(new GpxLayerAddedListener());132 135 } 133 136 … … 232 235 233 236 private static class GpxDataWrapper { 234 private finalString name;237 private String name; 235 238 private final GpxData data; 236 239 private final File file; … … 242 245 } 243 246 247 void setName(String name) { 248 this.name = name; 249 forEachLayer(CorrelateGpxWithImages::repaintCombobox); 250 } 251 244 252 @Override 245 253 public String toString() { … … 248 256 } 249 257 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 250 269 private ExtendedDialog syncDialog; 251 private MutableComboBoxModel<GpxDataWrapper> gpxModel;252 270 private JPanel outerPanel; 253 271 private JosmComboBox<GpxDataWrapper> cbGpx; … … 279 297 try { 280 298 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); 296 300 GpxData data = null; 297 301 try (InputStream iStream = Compression.getUncompressedFileInputStream(sel)) { … … 321 325 } 322 326 323 loadedGpxData.add(data);324 if (gpxModel.getElementAt(0).file == null) {325 gpxModel.removeElementAt(0);326 }327 327 GpxDataWrapper elem = new GpxDataWrapper(sel.getName(), data, sel); 328 328 gpxModel.addElement(elem); 329 329 gpxModel.setSelectedItem(elem); 330 statusBarUpdater.matchAndUpdateStatusBar(); 330 331 } finally { 331 332 outerPanel.setCursor(Cursor.getDefaultCursor()); … … 526 527 forceTags = cForce.isSelected(); // This setting is not supposed to be saved permanently 527 528 528 statusBarUpdater. updateStatusBar();529 statusBarUpdater.matchAndUpdateStatusBar(); 529 530 yLayer.updateBufferAndRepaint(); 530 531 } … … 767 768 768 769 } 769 statusBarUpdater. updateStatusBar();770 statusBarUpdater.matchAndUpdateStatusBar(); 770 771 yLayer.updateBufferAndRepaint(); 771 772 } … … 790 791 } 791 792 792 private class GpxLayerAddedListener implements LayerChangeListener {793 private static class GpxLayerAddedListener implements LayerChangeListener { 793 794 @Override 794 795 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); 805 805 } 806 806 } … … 817 817 } 818 818 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 819 833 @Override 820 834 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()); 845 855 } 846 856 … … 1010 1020 cbTaggedImg.addItemListener(statusBarUpdaterWithRepaint); 1011 1021 1012 statusBarUpdater. updateStatusBar();1022 statusBarUpdater.matchAndUpdateStatusBar(); 1013 1023 yLayer.updateBufferAndRepaint(); 1014 1024 … … 1017 1027 1018 1028 if (!GraphicsEnvironment.isHeadless()) { 1029 forEachLayer(CorrelateGpxWithImages::closeDialog); 1019 1030 syncDialog = new ExtendedDialog( 1020 1031 MainApplication.getMainFrame(), … … 1034 1045 } 1035 1046 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 1036 1061 private final transient StatusBarUpdater statusBarUpdater = new StatusBarUpdater(false); 1037 1062 private final transient StatusBarUpdater statusBarUpdaterWithRepaint = new StatusBarUpdater(true); … … 1046 1071 @Override 1047 1072 public void insertUpdate(DocumentEvent ev) { 1048 updateStatusBar();1073 matchAndUpdateStatusBar(); 1049 1074 } 1050 1075 1051 1076 @Override 1052 1077 public void removeUpdate(DocumentEvent ev) { 1053 updateStatusBar();1078 matchAndUpdateStatusBar(); 1054 1079 } 1055 1080 … … 1061 1086 @Override 1062 1087 public void itemStateChanged(ItemEvent e) { 1063 updateStatusBar();1088 matchAndUpdateStatusBar(); 1064 1089 } 1065 1090 1066 1091 @Override 1067 1092 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() { 1079 1106 try { 1080 1107 timezone = GpxTimezone.parseTimezone(tfTimezone.getText().trim()); … … 1199 1226 "Time difference of {0} days", Math.abs(dayOffset), Math.abs(dayOffset))); 1200 1227 1201 statusBarUpdater. updateStatusBar();1228 statusBarUpdater.matchAndUpdateStatusBar(); 1202 1229 yLayer.updateBufferAndRepaint(); 1203 1230 } … … 1251 1278 1252 1279 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 } 1253 1295 } 1254 1296 … … 1318 1360 tfOffset.getDocument().addDocumentListener(statusBarUpdater); 1319 1361 1320 statusBarUpdater. updateStatusBar();1362 statusBarUpdater.matchAndUpdateStatusBar(); 1321 1363 yLayer.updateBufferAndRepaint(); 1322 1364 } … … 1346 1388 Object item = gpxModel.getSelectedItem(); 1347 1389 1348 if (item == null || ((GpxDataWrapper) item). file== null) {1390 if (item == null || ((GpxDataWrapper) item).data == null) { 1349 1391 if (complain) { 1350 1392 JOptionPane.showMessageDialog(MainApplication.getMainFrame(), tr("You should select a GPX track"), … … 1356 1398 } 1357 1399 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 1358 1410 } -
trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java
r17548 r18034 82 82 GpxLayer gpxFauxLayer; 83 83 84 private CorrelateGpxWithImages gpxCorrelateAction; 85 84 86 private final Icon icon = ImageProvider.get("dialogs/geoimage/photo-marker"); 85 87 private final Icon selectedIcon = ImageProvider.get("dialogs/geoimage/photo-marker-selected"); … … 406 408 entries.add(new RenameLayerAction(null, this)); 407 409 entries.add(SeparatorLayerAction.INSTANCE); 408 entries.add( new CorrelateGpxWithImages(this));410 entries.add(getGpxCorrelateAction()); 409 411 entries.add(new ShowThumbnailAction(this)); 410 412 if (!menuAdditions.isEmpty()) { … … 852 854 super.destroy(); 853 855 stopLoadThumbs(); 856 if (gpxCorrelateAction != null) { 857 gpxCorrelateAction.destroy(); 858 gpxCorrelateAction = null; 859 } 854 860 MapView mapView = MainApplication.getMap().mapView; 855 861 mapView.removeMouseListener(mouseAdapter); … … 942 948 public GpxLayer getGpxLayer() { 943 949 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; 944 961 } 945 962
Note:
See TracChangeset
for help on using the changeset viewer.