Ticket #20795: 20795.patch
| File 20795.patch, 14.3 KB (added by , 5 years ago) |
|---|
-
src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java
### Eclipse Workspace Patch 1.0 #P josm
168 168 } 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 } 174 174 return ret; -
src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java
21 21 import java.awt.event.ItemListener; 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; 26 28 import java.io.InputStream; … … 115 117 */ 116 118 public class CorrelateGpxWithImages extends AbstractAction { 117 119 118 private static final List<GpxData> loadedGpxData = new ArrayList<>(); 120 private static MutableComboBoxModel<GpxDataWrapper> gpxModel; 121 private static List<CorrelateGpxWithImages> instances = new ArrayList<>(); 119 122 123 private static boolean forceTags; 124 120 125 private final transient GeoImageLayer yLayer; 121 126 private transient GpxTimezone timezone; 122 127 private transient GpxTimeOffset delta; 123 private static boolean forceTags;124 128 125 129 /** 126 130 * Constructs a new {@code CorrelateGpxWithImages} action. … … 130 134 super(tr("Correlate to GPX")); 131 135 new ImageProvider("dialogs/geoimage/gpx2img").getResource().attachImageIcon(this, true); 132 136 this.yLayer = layer; 133 MainApplication.getLayerManager().addLayerChangeListener(new GpxLayerAddedListener());137 instances.add(this); 134 138 } 135 139 136 140 private final class SyncDialogWindowListener extends WindowAdapter { … … 233 237 } 234 238 235 239 private static class GpxDataWrapper { 236 private finalString name;240 private String name; 237 241 private final GpxData data; 238 242 private final File file; 239 243 … … 243 247 this.file = file; 244 248 } 245 249 250 void setName(String name) { 251 this.name = name; 252 instances.forEach(CorrelateGpxWithImages::repaintCombobox); 253 } 254 246 255 @Override 247 256 public String toString() { 248 257 return name; … … 249 258 } 250 259 } 251 260 261 private static class NoGpxDataWrapper extends GpxDataWrapper { 262 NoGpxDataWrapper() { 263 super(null, null, null); 264 } 265 266 @Override 267 public String toString() { 268 return tr("<No GPX track loaded yet>"); 269 } 270 } 271 252 272 private ExtendedDialog syncDialog; 253 private MutableComboBoxModel<GpxDataWrapper> gpxModel;254 273 private JPanel outerPanel; 255 274 private JosmComboBox<GpxDataWrapper> cbGpx; 256 275 private JosmTextField tfTimezone; … … 280 299 281 300 try { 282 301 outerPanel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 283 for (int i = gpxModel.getSize() - 1; i >= 0; i--) { 284 GpxDataWrapper wrapper = gpxModel.getElementAt(i); 285 if (sel.equals(wrapper.file)) { 286 gpxModel.setSelectedItem(wrapper); 287 if (!sel.getName().equals(wrapper.name)) { 288 JOptionPane.showMessageDialog( 289 MainApplication.getMainFrame(), 290 tr("File {0} is loaded yet under the name \"{1}\"", sel.getName(), wrapper.name), 291 tr("Error"), 292 JOptionPane.ERROR_MESSAGE 293 ); 294 } 295 return; 296 } 297 } 302 removeDuplicates(sel); 298 303 GpxData data = null; 299 304 try (InputStream iStream = Compression.getUncompressedFileInputStream(sel)) { 300 305 IGpxReader reader = gpxFilter.accept(sel) ? new GpxReader(iStream) : new NmeaReader(iStream); … … 322 327 return; 323 328 } 324 329 325 loadedGpxData.add(data);326 if (gpxModel.getElementAt(0).file == null) {327 gpxModel.removeElementAt(0);328 }329 330 GpxDataWrapper elem = new GpxDataWrapper(sel.getName(), data, sel); 330 331 gpxModel.addElement(elem); 331 332 gpxModel.setSelectedItem(elem); 333 statusBarUpdater.matchAndUpdateStatusBar(); 332 334 } finally { 333 335 outerPanel.setCursor(Cursor.getDefaultCursor()); 334 336 } … … 527 529 528 530 forceTags = cForce.isSelected(); // This setting is not supposed to be saved permanently 529 531 530 statusBarUpdater. updateStatusBar();532 statusBarUpdater.matchAndUpdateStatusBar(); 531 533 yLayer.updateBufferAndRepaint(); 532 534 } 533 535 } … … 764 766 isOk = true; 765 767 766 768 } 767 statusBarUpdater. updateStatusBar();769 statusBarUpdater.matchAndUpdateStatusBar(); 768 770 yLayer.updateBufferAndRepaint(); 769 771 } 770 772 … … 787 789 } 788 790 } 789 791 790 private class GpxLayerAddedListener implements LayerChangeListener {792 private static class GpxLayerAddedListener implements LayerChangeListener { 791 793 @Override 792 794 public void layerAdded(LayerAddEvent e) { 793 if (syncDialog != null && syncDialog.isVisible()) { 794 Layer layer = e.getAddedLayer(); 795 if (layer instanceof GpxLayer) { 796 GpxLayer gpx = (GpxLayer) layer; 797 GpxDataWrapper gdw = new GpxDataWrapper(gpx.getName(), gpx.data, gpx.data.storageFile); 798 if (gpxModel.getElementAt(0).file == null) { 799 gpxModel.removeElementAt(0); 800 } 801 gpxModel.addElement(gdw); 802 } 795 Layer layer = e.getAddedLayer(); 796 if (layer instanceof GpxLayer) { 797 GpxLayer gpx = (GpxLayer) layer; 798 File file = gpx.data.storageFile; 799 removeDuplicates(file); 800 GpxDataWrapper gdw = new GpxDataWrapper(gpx.getName(), gpx.data, file); 801 gpx.addPropertyChangeListener(new GpxLayerRenamedListener(gdw)); 802 gpxModel.addElement(gdw); 803 instances.forEach(CorrelateGpxWithImages::repaintCombobox); 803 804 } 804 805 } 805 806 … … 814 815 } 815 816 } 816 817 818 private static class GpxLayerRenamedListener implements PropertyChangeListener { 819 private GpxDataWrapper gdw; 820 GpxLayerRenamedListener(GpxDataWrapper gdw) { 821 this.gdw = gdw; 822 } 823 824 @Override 825 public void propertyChange(PropertyChangeEvent e) { 826 if (Layer.NAME_PROP.equals(e.getPropertyName())) { 827 gdw.setName(e.getNewValue().toString()); 828 } 829 } 830 } 831 817 832 @Override 818 833 public void actionPerformed(ActionEvent ae) { 819 // Construct the list of loaded GPX tracks 820 gpxModel = new DefaultComboBoxModel<>(); 821 GpxDataWrapper defaultItem = null; 822 for (GpxLayer cur : MainApplication.getLayerManager().getLayersOfType(GpxLayer.class).stream() 823 .filter(GpxLayer::isLocalFile).collect(Collectors.toList())) { 824 GpxDataWrapper gdw = new GpxDataWrapper(cur.getName(), cur.data, cur.data.storageFile); 825 gpxModel.addElement(gdw); 826 if (cur == yLayer.gpxLayer || (defaultItem == null && gdw.file != null)) { 827 defaultItem = gdw; 834 NoGpxDataWrapper nogdw = new NoGpxDataWrapper(); 835 if (gpxModel == null) { 836 // Construct the list of loaded GPX tracks 837 gpxModel = new DefaultComboBoxModel<>(); 838 GpxDataWrapper defaultItem = null; 839 for (GpxLayer cur : MainApplication.getLayerManager().getLayersOfType(GpxLayer.class)) { 840 GpxDataWrapper gdw = new GpxDataWrapper(cur.getName(), cur.data, cur.data.storageFile); 841 cur.addPropertyChangeListener(new GpxLayerRenamedListener(gdw)); 842 gpxModel.addElement(gdw); 843 if (cur == yLayer.gpxLayer || defaultItem == null) { 844 defaultItem = gdw; 845 } 828 846 } 829 } 830 for (GpxData data : loadedGpxData) { 831 GpxDataWrapper gdw = new GpxDataWrapper(data.storageFile.getName(), data, data.storageFile); 832 gpxModel.addElement(gdw); 833 if (defaultItem == null && gdw.file != null) { // select first GPX track associated to a file 834 defaultItem = gdw; 847 848 if (gpxModel.getSize() == 0) { 849 gpxModel.addElement(nogdw); 850 } else if (defaultItem != null) { 851 gpxModel.setSelectedItem(defaultItem); 835 852 } 853 MainApplication.getLayerManager().addLayerChangeListener(new GpxLayerAddedListener()); 836 854 } 837 855 838 GpxDataWrapper nogdw = new GpxDataWrapper(tr("<No GPX track loaded yet>"), null, null);839 if (gpxModel.getSize() == 0) {840 gpxModel.addElement(nogdw);841 } else if (defaultItem != null) {842 gpxModel.setSelectedItem(defaultItem);843 }844 845 856 JPanel panelCb = new JPanel(); 846 857 847 858 panelCb.add(new JLabel(tr("GPX track: "))); … … 1007 1018 cbExifImg.addItemListener(statusBarUpdaterWithRepaint); 1008 1019 cbTaggedImg.addItemListener(statusBarUpdaterWithRepaint); 1009 1020 1010 statusBarUpdater. updateStatusBar();1021 statusBarUpdater.matchAndUpdateStatusBar(); 1011 1022 yLayer.updateBufferAndRepaint(); 1012 1023 1013 1024 outerPanel = new JPanel(new BorderLayout()); … … 1014 1025 outerPanel.add(statusBar, BorderLayout.PAGE_END); 1015 1026 1016 1027 if (!GraphicsEnvironment.isHeadless()) { 1028 instances.forEach(CorrelateGpxWithImages::closeDialog); 1017 1029 syncDialog = new ExtendedDialog( 1018 1030 MainApplication.getMainFrame(), 1019 1031 tr("Correlate images with GPX track"), … … 1031 1043 } 1032 1044 } 1033 1045 1046 private static void removeDuplicates(File file) { 1047 for (int i = gpxModel.getSize() - 1; i >= 0; i--) { 1048 GpxDataWrapper wrapper = gpxModel.getElementAt(i); 1049 if (wrapper instanceof NoGpxDataWrapper || (file != null && file.equals(wrapper.file))) { 1050 gpxModel.removeElement(wrapper); 1051 } 1052 } 1053 } 1054 1034 1055 private final transient StatusBarUpdater statusBarUpdater = new StatusBarUpdater(false); 1035 1056 private final transient StatusBarUpdater statusBarUpdaterWithRepaint = new StatusBarUpdater(true); 1036 1057 … … 1043 1064 1044 1065 @Override 1045 1066 public void insertUpdate(DocumentEvent ev) { 1046 updateStatusBar();1067 matchAndUpdateStatusBar(); 1047 1068 } 1048 1069 1049 1070 @Override 1050 1071 public void removeUpdate(DocumentEvent ev) { 1051 updateStatusBar();1072 matchAndUpdateStatusBar(); 1052 1073 } 1053 1074 1054 1075 @Override … … 1058 1079 1059 1080 @Override 1060 1081 public void itemStateChanged(ItemEvent e) { 1061 updateStatusBar();1082 matchAndUpdateStatusBar(); 1062 1083 } 1063 1084 1064 1085 @Override 1065 1086 public void actionPerformed(ActionEvent e) { 1066 updateStatusBar();1087 matchAndUpdateStatusBar(); 1067 1088 } 1068 1089 1069 public void updateStatusBar() { 1070 statusBarText.setText(statusText()); 1071 if (doRepaint) { 1072 yLayer.updateBufferAndRepaint(); 1090 public void matchAndUpdateStatusBar() { 1091 if (syncDialog != null && syncDialog.isVisible()) { 1092 statusBarText.setText(matchAndGetStatusText()); 1093 if (doRepaint) { 1094 yLayer.updateBufferAndRepaint(); 1095 } 1073 1096 } 1074 1097 } 1075 1098 1076 private String statusText() {1099 private String matchAndGetStatusText() { 1077 1100 try { 1078 1101 timezone = GpxTimezone.parseTimezone(tfTimezone.getText().trim()); 1079 1102 delta = GpxTimeOffset.parseOffset(tfOffset.getText().trim()); … … 1196 1219 lblMatches.setText(statusBarText.getText() + "<br>" + trn("(Time difference of {0} day)", 1197 1220 "Time difference of {0} days", Math.abs(dayOffset), Math.abs(dayOffset))); 1198 1221 1199 statusBarUpdater. updateStatusBar();1222 statusBarUpdater.matchAndUpdateStatusBar(); 1200 1223 yLayer.updateBufferAndRepaint(); 1201 1224 } 1202 1225 } … … 1250 1273 static class NoGpxTimestamps extends Exception { 1251 1274 } 1252 1275 1276 void closeDialog() { 1277 if (syncDialog != null) { 1278 syncDialog.setVisible(false); 1279 new SyncDialogWindowListener().windowDeactivated(null); 1280 syncDialog.dispose(); 1281 syncDialog = null; 1282 } 1283 } 1284 1285 void repaintCombobox() { 1286 if (cbGpx != null) { 1287 cbGpx.repaint(); 1288 } 1289 } 1290 1253 1291 /** 1254 1292 * Tries to auto-guess the timezone and offset. 1255 1293 * … … 1315 1353 tfTimezone.getDocument().addDocumentListener(statusBarUpdater); 1316 1354 tfOffset.getDocument().addDocumentListener(statusBarUpdater); 1317 1355 1318 statusBarUpdater. updateStatusBar();1356 statusBarUpdater.matchAndUpdateStatusBar(); 1319 1357 yLayer.updateBufferAndRepaint(); 1320 1358 } 1321 1359 } … … 1343 1381 private GpxDataWrapper selectedGPX(boolean complain) { 1344 1382 Object item = gpxModel.getSelectedItem(); 1345 1383 1346 if (item == null || ((GpxDataWrapper) item). file== null) {1384 if (item == null || ((GpxDataWrapper) item).data == null) { 1347 1385 if (complain) { 1348 1386 JOptionPane.showMessageDialog(MainApplication.getMainFrame(), tr("You should select a GPX track"), 1349 1387 tr("No selected GPX track"), JOptionPane.ERROR_MESSAGE);
