Ticket #20913: 20913-v3.1.2.patch
File 20913-v3.1.2.patch, 51.9 KB (added by , 3 years ago) |
---|
-
src/org/openstreetmap/josm/actions/SaveAction.java
14 14 import javax.swing.JPanel; 15 15 import javax.swing.SwingConstants; 16 16 17 import org.openstreetmap.josm.data.gpx.Gpx Data.GpxDataChangeListener;17 import org.openstreetmap.josm.data.gpx.GpxConstants; 18 18 import org.openstreetmap.josm.gui.ExtendedDialog; 19 19 import org.openstreetmap.josm.gui.MainApplication; 20 import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer; 20 21 import org.openstreetmap.josm.gui.layer.GpxLayer; 21 22 import org.openstreetmap.josm.gui.layer.Layer; 22 23 import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent; 23 24 import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent; 24 import org.openstreetmap.josm.gui.layer.OsmDataLayer;25 25 import org.openstreetmap.josm.gui.layer.SaveToFile; 26 26 import org.openstreetmap.josm.gui.util.GuiHelper; 27 27 import org.openstreetmap.josm.spi.preferences.Config; … … 37 37 private static final SaveAction instance = new SaveAction(); 38 38 39 39 private final PropertyChangeListener updateOnRequireSaveChange = evt -> { 40 if ( OsmDataLayer.REQUIRES_SAVE_TO_DISK_PROP.equals(evt.getPropertyName())) {40 if (AbstractModifiableLayer.REQUIRES_SAVE_TO_DISK_PROP.equals(evt.getPropertyName())) { 41 41 updateEnabledState(); 42 42 } 43 43 }; 44 44 45 private final GpxDataChangeListener updateOnRequireSaveChangeGpx = evt -> updateEnabledState();46 47 45 /** 48 46 * Construct the action with "Save" as label. 49 47 */ … … 68 66 @Override 69 67 public void layerAdded(LayerAddEvent e) { 70 68 Layer l = e.getAddedLayer(); 71 if (l instanceof OsmDataLayer) {69 if (l instanceof AbstractModifiableLayer) { 72 70 l.addPropertyChangeListener(updateOnRequireSaveChange); 73 71 } 74 if (l instanceof GpxLayer) {75 ((GpxLayer) l).data.addWeakChangeListener(updateOnRequireSaveChangeGpx);76 }77 72 super.layerAdded(e); 78 73 } 79 74 … … 80 75 @Override 81 76 public void layerRemoving(LayerRemoveEvent e) { 82 77 Layer l = e.getRemovedLayer(); 83 if (l instanceof OsmDataLayer) {78 if (l instanceof AbstractModifiableLayer) { 84 79 l.removePropertyChangeListener(updateOnRequireSaveChange); 85 80 } 86 if (l instanceof GpxLayer) {87 ((GpxLayer) l).data.removeChangeListener(updateOnRequireSaveChangeGpx);88 }89 81 super.layerRemoving(e); 90 82 } 91 83 }; … … 113 105 } 114 106 115 107 // Ask for overwrite in case of GpxLayer 116 if (f != null && layer instanceof GpxLayer && !Config.getPref().getBoolean("gpx.export.overwrite", false)) { 108 if (f != null 109 && layer instanceof GpxLayer 110 && (((GpxLayer) layer).data == null 111 || !GpxConstants.JOSM_CREATOR_NAME.equals(((GpxLayer) layer).data.creator)) 112 && !Config.getPref().getBoolean("gpx.export.overwrite", false)) { 113 117 114 JPanel p = new JPanel(new GridBagLayout()); 118 JLabel label = new JLabel(tr("File {0} exists. Overwrite?", f.getName())); 115 JLabel label = new JLabel("<html>" 116 + tr("The file \"{0}\" will be modified.<br>Would you like to overwrite the existing file?", f.getName()) 117 + "</html>"); 119 118 label.setHorizontalAlignment(SwingConstants.CENTER); 120 JCheckBox remember = new JCheckBox(tr(" Remember choice"));119 JCheckBox remember = new JCheckBox(tr("Always overwrite GPX files without asking")); 121 120 remember.setHorizontalAlignment(SwingConstants.CENTER); 122 121 p.add(label, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 5, 5, 10)); 123 122 p.add(remember, GBC.eop().fill(GBC.HORIZONTAL)); … … 124 123 ExtendedDialog dialog = new ExtendedDialog( 125 124 MainApplication.getMainFrame(), 126 125 tr("Overwrite"), 127 tr("Overwrite"), tr(" Cancel"))128 .setButtonIcons("save _as", "cancel")126 tr("Overwrite"), tr("Save As..."), tr("Cancel")) 127 .setButtonIcons("save", "save_as", "cancel") 129 128 .setContent(p); 130 if (dialog.showDialog().getValue() != 1) { 129 int val = dialog.showDialog().getValue(); 130 if (val == 1) { 131 Config.getPref().putBoolean("gpx.export.overwrite", remember.isSelected()); 132 } else if (val == 2) { 131 133 f = null; 132 } else if (remember.isSelected()){133 Config.getPref().putBoolean("gpx.export.overwrite", true);134 } else { 135 return null; 134 136 } 135 137 } 136 138 return f == null ? layer.createAndOpenSaveFileChooser() : f; -
src/org/openstreetmap/josm/actions/SessionSaveAsAction.java
19 19 import java.util.Map; 20 20 import java.util.Set; 21 21 import java.util.stream.Collectors; 22 import java.util.stream.Stream; 22 23 23 24 import javax.swing.BorderFactory; 24 25 import javax.swing.JCheckBox; … … 32 33 import javax.swing.border.EtchedBorder; 33 34 import javax.swing.filechooser.FileFilter; 34 35 36 import org.openstreetmap.josm.data.preferences.BooleanProperty; 35 37 import org.openstreetmap.josm.gui.ExtendedDialog; 36 38 import org.openstreetmap.josm.gui.HelpAwareOptionPane; 37 39 import org.openstreetmap.josm.gui.MainApplication; … … 38 40 import org.openstreetmap.josm.gui.MapFrame; 39 41 import org.openstreetmap.josm.gui.MapFrameListener; 40 42 import org.openstreetmap.josm.gui.Notification; 43 import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer; 41 44 import org.openstreetmap.josm.gui.layer.Layer; 42 45 import org.openstreetmap.josm.gui.util.WindowGeometry; 43 46 import org.openstreetmap.josm.gui.widgets.AbstractFileChooser; … … 60 63 private transient Map<Layer, SessionLayerExporter> exporters; 61 64 private transient MultiMap<Layer, Layer> dependencies; 62 65 66 private static final BooleanProperty SAVE_LOCAL_FILES_PROPERTY = new BooleanProperty("session.savelocal", true); 67 63 68 /** 64 69 * Constructs a new {@code SessionSaveAsAction}. 65 70 */ … … 158 163 .filter(layer -> exporters.get(layer) != null && exporters.get(layer).shallExport()) 159 164 .collect(Collectors.toList()); 160 165 166 Stream<Layer> layersToSaveStream = layersOut.stream() 167 .filter(layer -> layer.isSavable() 168 && layer instanceof AbstractModifiableLayer 169 && ((AbstractModifiableLayer) layer).requiresSaveToFile() 170 && exporters.get(layer) != null 171 && !exporters.get(layer).requiresZip()); 172 173 if (SAVE_LOCAL_FILES_PROPERTY.get()) { 174 // individual files must be saved before the session file as the location may change 175 176 if (layersToSaveStream 177 .map(layer -> SaveAction.getInstance().doSave(layer, true)) 178 .collect(Collectors.toList()) //force evaluation of all elements 179 .contains(false)) { 180 181 new Notification(tr("Not all local files referenced by the session file could be saved." 182 + "<br>Make sure you save them before closing JOSM.")) 183 .setIcon(JOptionPane.WARNING_MESSAGE) 184 .setDuration(Notification.TIME_LONG) 185 .show(); 186 } 187 188 } else if (layersToSaveStream.anyMatch(l -> true)) { 189 new Notification(tr("Not all local files referenced by the session file are saved yet." 190 + "<br>Make sure you save them before closing JOSM.")) 191 .setIcon(JOptionPane.INFORMATION_MESSAGE) 192 .setDuration(Notification.TIME_LONG) 193 .show(); 194 } 195 161 196 int active = -1; 162 197 Layer activeLayer = getLayerManager().getActiveLayer(); 163 198 if (activeLayer != null) { … … 250 285 } 251 286 252 287 protected final Component build() { 288 JPanel op = new JPanel(new GridBagLayout()); 253 289 JPanel ip = new JPanel(new GridBagLayout()); 254 290 for (Layer layer : layers) { 255 291 JPanel wrapper = new JPanel(new GridBagLayout()); … … 272 308 p.add(sp, GBC.eol().fill()); 273 309 final JTabbedPane tabs = new JTabbedPane(); 274 310 tabs.addTab(tr("Layers"), p); 275 return tabs; 311 op.add(tabs, GBC.eol().fill()); 312 JCheckBox chkSaveLocal = new JCheckBox(tr("Save all local files to disk"), SAVE_LOCAL_FILES_PROPERTY.get()); 313 chkSaveLocal.addChangeListener(l -> { 314 SAVE_LOCAL_FILES_PROPERTY.put(chkSaveLocal.isSelected()); 315 }); 316 op.add(chkSaveLocal); 317 return op; 276 318 } 277 319 278 320 protected final Component getDisabledExportPanel(Layer layer) { -
src/org/openstreetmap/josm/data/gpx/GpxConstants.java
100 100 String META_BOUNDS = META_PREFIX + "bounds"; 101 101 102 102 /** 103 * The creator element that will be written when exporting a GPX file 104 */ 105 String JOSM_CREATOR_NAME = "JOSM GPX export"; 106 107 /** 103 108 * Namespace for the XSD 104 109 */ 105 110 String XML_URI_XSD = "http://www.w3.org/2001/XMLSchema-instance"; -
src/org/openstreetmap/josm/data/gpx/GpxData.java
43 43 * 44 44 * @author Raphael Mack <ramack@raphael-mack.de> 45 45 */ 46 public class GpxData extends WithAttributes implements Data {46 public class GpxData extends WithAttributes implements Data, IGpxLayerPrefs { 47 47 48 48 /** 49 49 * Constructs a new GpxData. … … 67 67 * A boolean flag indicating if the data was read from the OSM server. 68 68 */ 69 69 public boolean fromServer; 70 /** 71 * A boolean flag indicating if the data was read from a session file. 72 */ 73 public boolean fromSession; 70 74 71 75 /** 72 76 * Creator metadata for this file (usually software) … … 1022 1026 * @return Modifiable map 1023 1027 * @since 15496 1024 1028 */ 1029 @Override 1025 1030 public Map<String, String> getLayerPrefs() { 1026 1031 return layerPrefs; 1027 1032 } … … 1136 1141 suppressedInvalidate = true; 1137 1142 } else { 1138 1143 if (setModified) { 1139 modified = true;1144 setModified(true); 1140 1145 } 1141 1146 if (listeners.hasListeners()) { 1142 1147 GpxDataChangeEvent e = new GpxDataChangeEvent(this); … … 1178 1183 * @param e The event 1179 1184 */ 1180 1185 void gpxDataChanged(GpxDataChangeEvent e); 1186 1187 /** 1188 * Called when the modified state of the data changed 1189 * @param modified the new modified state 1190 */ 1191 default void modifiedStateChanged(boolean modified) { 1192 // Override if needed 1193 } 1181 1194 } 1182 1195 1183 1196 /** … … 1216 1229 * @param value modified flag 1217 1230 * @since 15496 1218 1231 */ 1232 @Override 1219 1233 public void setModified(boolean value) { 1220 modified = value; 1234 if (!initializing && modified != value) { 1235 modified = value; 1236 if (listeners.hasListeners()) { 1237 listeners.fireEvent(l -> l.modifiedStateChanged(modified)); 1238 } 1239 } 1221 1240 } 1222 1241 1223 1242 /** -
src/org/openstreetmap/josm/data/gpx/IGpxLayerPrefs.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.data.gpx; 3 4 import java.util.Map; 5 6 /** 7 * Interface containing the layer preferences. 8 * Implemented by GpxLayer and MarkerLayer 9 * @since xxx 10 */ 11 public interface IGpxLayerPrefs { 12 13 /** 14 * The layer specific prefs formerly saved in the preferences, e.g. drawing options. 15 * NOT the track specific settings (e.g. color, width) 16 * @return Modifiable map 17 */ 18 Map<String, String> getLayerPrefs(); 19 20 /** 21 * Sets the modified flag to the value. 22 * @param value modified flag 23 */ 24 void setModified(boolean value); 25 26 } -
src/org/openstreetmap/josm/gui/MainFrame.java
25 25 import javax.swing.JPanel; 26 26 27 27 import org.openstreetmap.josm.data.UserIdentityManager; 28 import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer; 28 29 import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent; 29 30 import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener; 30 31 import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent; … … 45 46 private final transient LayerStateChangeListener updateTitleOnLayerStateChange = (layer, newValue) -> onLayerChange(layer); 46 47 47 48 private final transient PropertyChangeListener updateTitleOnSaveChange = evt -> { 48 if (evt.getPropertyName().equals( OsmDataLayer.REQUIRES_SAVE_TO_DISK_PROP)49 if (evt.getPropertyName().equals(AbstractModifiableLayer.REQUIRES_SAVE_TO_DISK_PROP) 49 50 || evt.getPropertyName().equals(OsmDataLayer.REQUIRES_UPLOAD_TO_SERVER_PROP)) { 50 OsmDataLayer layer = (OsmDataLayer) evt.getSource();51 AbstractModifiableLayer layer = (AbstractModifiableLayer) evt.getSource(); 51 52 onLayerChange(layer); 52 53 } 53 54 }; … … 186 187 getRootPane().putClientProperty("Window.documentModified", dirty); 187 188 } 188 189 189 private void onLayerChange( OsmDataLayer layer) {190 private void onLayerChange(AbstractModifiableLayer layer) { 190 191 if (layer == MainApplication.getLayerManager().getEditLayer()) { 191 192 refreshTitle(); 192 193 } -
src/org/openstreetmap/josm/gui/io/importexport/GpxImporter.java
147 147 } 148 148 if (data.gpxLayer != null) { 149 149 MainApplication.getLayerManager().addLayer(data.gpxLayer); 150 MainApplication.getLayerManager().setActiveLayer(data.gpxLayer); 150 151 } 151 152 data.postLayerTask.run(); 152 153 }); -
src/org/openstreetmap/josm/gui/layer/AbstractModifiableLayer.java
16 16 */ 17 17 public abstract class AbstractModifiableLayer extends Layer implements DownloadFromServer, UploadToServer, SaveToFile, Lockable { 18 18 19 /** Property used to know if this layer has to be saved on disk */ 20 public static final String REQUIRES_SAVE_TO_DISK_PROP = AbstractModifiableLayer.class.getName() + ".requiresSaveToDisk"; 21 static final String IS_DIRTY_SYMBOL = "*"; 22 19 23 /** 20 24 * Constructs a new {@code ModifiableLayer}. 21 25 * @param name Layer name … … 55 59 } 56 60 57 61 /** 62 * Determines if this layer is "dirty", i.e. requires save or upload 63 * @return if this layer is "dirty" 64 * @since 17626 in {@link OsmDataLayer} 65 * @since xxx in {@link AbstractModifiableLayer} 66 */ 67 public boolean isDirty() { 68 // Override if needed 69 return requiresSaveToFile() || (requiresUploadToServer() && !isUploadDiscouraged()); 70 } 71 72 /** 58 73 * Determines if data managed by this layer has been modified. 59 74 * @return true if data has been modified; false, otherwise 60 75 */ … … 130 145 // Override if needed; 131 146 return null; 132 147 } 148 133 149 } -
src/org/openstreetmap/josm/gui/layer/GpxLayer.java
33 33 import org.openstreetmap.josm.data.SystemOfMeasurement; 34 34 import org.openstreetmap.josm.data.gpx.GpxConstants; 35 35 import org.openstreetmap.josm.data.gpx.GpxData; 36 import org.openstreetmap.josm.data.gpx.GpxData.GpxDataChangeEvent; 37 import org.openstreetmap.josm.data.gpx.GpxData.GpxDataChangeListener; 36 38 import org.openstreetmap.josm.data.gpx.GpxDataContainer; 37 import org.openstreetmap.josm.data.gpx.GpxData.GpxDataChangeListener;38 39 import org.openstreetmap.josm.data.gpx.IGpxTrack; 39 40 import org.openstreetmap.josm.data.gpx.IGpxTrackSegment; 40 41 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor; … … 58 59 import org.openstreetmap.josm.gui.layer.gpx.MarkersFromNamedPointsAction; 59 60 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer; 60 61 import org.openstreetmap.josm.gui.preferences.display.GPXSettingsPanel; 62 import org.openstreetmap.josm.gui.util.GuiHelper; 61 63 import org.openstreetmap.josm.gui.widgets.HtmlPanel; 62 64 import org.openstreetmap.josm.tools.ImageProvider; 63 65 import org.openstreetmap.josm.tools.Logging; … … 85 87 /** 86 88 * Added as field to be kept as reference. 87 89 */ 88 private final GpxDataChangeListener dataChangeListener = e -> this.invalidate(); 90 private final GpxDataChangeListener dataChangeListener = new GpxDataChangeListener() { 91 @Override 92 public void gpxDataChanged(GpxDataChangeEvent e) { 93 invalidate(); 94 } 95 96 @Override 97 public void modifiedStateChanged(boolean modified) { 98 GuiHelper.runInEDT(() -> propertyChangeSupport.firePropertyChange(REQUIRES_SAVE_TO_DISK_PROP, !modified, modified)); 99 } 100 }; 89 101 /** 90 102 * The MarkerLayer imported from the same file. 91 103 */ … … 375 387 } 376 388 377 389 @Override 390 public String getLabel() { 391 return isDirty() ? super.getLabel() + ' ' + IS_DIRTY_SYMBOL : super.getLabel(); 392 } 393 394 @Override 378 395 public void visitBoundingBox(BoundingXYVisitor v) { 379 396 if (data != null) { 380 397 v.visit(data.recalculateBounds()); … … 554 571 555 572 @Override 556 573 public boolean requiresSaveToFile() { 557 return isModified() && isLocalFile();574 return data != null && isModified() && (isLocalFile() || data.fromSession); 558 575 } 559 576 560 577 @Override … … 621 638 622 639 @Override 623 640 public synchronized void destroy() { 641 if (linkedMarkerLayer != null && MainApplication.getLayerManager().containsLayer(linkedMarkerLayer)) { 642 linkedMarkerLayer.data.transferLayerPrefs(data.getLayerPrefs()); 643 } 624 644 data.clear(); 625 645 data = null; 626 646 super.destroy(); -
src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
148 148 private static final int HATCHED_SIZE = 15; 149 149 // U+2205 EMPTY SET 150 150 private static final String IS_EMPTY_SYMBOL = "\u2205"; 151 private static final String IS_DIRTY_SYMBOL = "*";152 /** Property used to know if this layer has to be saved on disk */153 public static final String REQUIRES_SAVE_TO_DISK_PROP = OsmDataLayer.class.getName() + ".requiresSaveToDisk";154 151 /** Property used to know if this layer has to be uploaded */ 155 152 public static final String REQUIRES_UPLOAD_TO_SERVER_PROP = OsmDataLayer.class.getName() + ".requiresUploadToServer"; 156 153 … … 1072 1069 return getAssociatedFile() != null && requiresSaveToFile; 1073 1070 } 1074 1071 1075 /**1076 * Determines if this layer is "dirty", i.e., requires save or upload1077 * @return if this layer is "dirty"1078 * @since 176261079 */1080 public boolean isDirty() {1081 return requiresSaveToFile() || (requiresUploadToServer() && !isUploadDiscouraged());1082 }1083 1084 1072 @Override 1085 1073 public String getLabel() { 1086 1074 String label = super.getLabel(); -
src/org/openstreetmap/josm/gui/layer/markerlayer/Marker.java
189 189 */ 190 190 public WayPoint convertToWayPoint() { 191 191 WayPoint wpt = new WayPoint(getCoor()); 192 wpt.setTimeInMillis((long) (time * 1000)); 192 if (time != 0) { 193 wpt.setTimeInMillis((long) (time * 1000)); 194 } 193 195 if (text != null) { 194 196 wpt.getExtensions().add("josm", "text", text); 195 197 } else if (dataProvider != null) { -
src/org/openstreetmap/josm/gui/layer/markerlayer/MarkerLayer.java
20 20 import java.util.ArrayList; 21 21 import java.util.Collection; 22 22 import java.util.Comparator; 23 import java.util.HashMap; 23 24 import java.util.List; 25 import java.util.Map; 24 26 import java.util.Optional; 25 27 26 28 import javax.swing.AbstractAction; … … 37 39 import org.openstreetmap.josm.data.gpx.GpxData; 38 40 import org.openstreetmap.josm.data.gpx.GpxExtension; 39 41 import org.openstreetmap.josm.data.gpx.GpxLink; 42 import org.openstreetmap.josm.data.gpx.IGpxLayerPrefs; 40 43 import org.openstreetmap.josm.data.gpx.WayPoint; 41 44 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor; 42 45 import org.openstreetmap.josm.data.preferences.IntegerProperty; … … 56 59 import org.openstreetmap.josm.gui.preferences.display.GPXSettingsPanel; 57 60 import org.openstreetmap.josm.io.audio.AudioPlayer; 58 61 import org.openstreetmap.josm.spi.preferences.Config; 62 import org.openstreetmap.josm.tools.ColorHelper; 59 63 import org.openstreetmap.josm.tools.ImageProvider; 60 64 import org.openstreetmap.josm.tools.Logging; 61 65 import org.openstreetmap.josm.tools.Utils; … … 76 80 /** 77 81 * A list of markers. 78 82 */ 79 public final List<Marker>data;83 public final MarkerData data; 80 84 private boolean mousePressed; 81 85 public GpxLayer fromLayer; 82 86 private Marker currentMarker; … … 100 104 public MarkerLayer(GpxData indata, String name, File associatedFile, GpxLayer fromLayer) { 101 105 super(name); 102 106 this.setAssociatedFile(associatedFile); 103 this.data = new ArrayList<>();107 this.data = new MarkerData(); 104 108 this.fromLayer = fromLayer; 105 109 double firstTime = -1.0; 106 110 String lastLinkedFile = ""; 107 111 112 if (fromLayer == null || fromLayer.data == null) { 113 data.ownLayerPrefs = indata.getLayerPrefs(); 114 } 115 116 String cs = GPXSettingsPanel.tryGetDataPrefLocal(data, "markers.color"); 108 117 Color c = null; 109 String cs = GPXSettingsPanel.tryGetLayerPrefLocal(indata, "markers.color");110 118 if (cs != null) { 111 try { 112 c = Color.decode(cs); 113 } catch (NumberFormatException ex) { 119 c = ColorHelper.html2color(cs); 120 if (c == null) { 114 121 Logging.warn("Could not read marker color: " + cs); 115 122 } 116 123 } … … 459 466 * @return <code>true</code> if text should be shown, <code>false</code> otherwise. 460 467 */ 461 468 private boolean isTextOrIconShown() { 462 return Boolean.parseBoolean(GPXSettingsPanel.get LayerPref(fromLayer, "markers.show-text"));469 return Boolean.parseBoolean(GPXSettingsPanel.getDataPref(data, "markers.show-text")); 463 470 } 464 471 465 472 @Override … … 475 482 @Override 476 483 public void setColor(Color color) { 477 484 setPrivateColors(color); 478 if (fromLayer != null) { 479 String cs = null; 480 if (color != null) { 481 cs = String.format("#%02X%02X%02X", color.getRed(), color.getGreen(), color.getBlue()); 482 } 483 GPXSettingsPanel.putLayerPrefLocal(fromLayer, "markers.color", cs); 485 String cs = null; 486 if (color != null) { 487 cs = ColorHelper.color2html(color); 484 488 } 489 GPXSettingsPanel.putDataPrefLocal(data, "markers.color", cs); 485 490 invalidate(); 486 491 } 487 492 … … 533 538 534 539 @Override 535 540 public void actionPerformed(ActionEvent e) { 536 GPXSettingsPanel.put LayerPrefLocal(layer.fromLayer, "markers.show-text", Boolean.toString(!layer.isTextOrIconShown()));541 GPXSettingsPanel.putDataPrefLocal(layer.data, "markers.show-text", Boolean.toString(!layer.isTextOrIconShown())); 537 542 layer.invalidate(); 538 543 } 539 544 … … 617 622 invalidate(); 618 623 } 619 624 } 625 626 /** 627 * the data of a MarkerLayer 628 */ 629 public class MarkerData extends ArrayList<Marker> implements IGpxLayerPrefs { 630 631 private Map<String, String> ownLayerPrefs; 632 633 @Override 634 public Map<String, String> getLayerPrefs() { 635 if (ownLayerPrefs == null && fromLayer != null && fromLayer.data != null) { 636 return fromLayer.data.getLayerPrefs(); 637 } 638 // fallback to own layerPrefs if the corresponding gpxLayer has already been deleted 639 // by the user or never existed when loaded from a session file 640 if (ownLayerPrefs == null) { 641 ownLayerPrefs = new HashMap<>(); 642 } 643 return ownLayerPrefs; 644 } 645 646 /** 647 * Transfers the layerPrefs from the GpxData to MarkerData (when GpxData is deleted) 648 * @param gpxLayerPrefs the layerPrefs from the GpxData object 649 */ 650 public void transferLayerPrefs(Map<String, String> gpxLayerPrefs) { 651 ownLayerPrefs = new HashMap<>(gpxLayerPrefs); 652 } 653 654 @Override 655 public void setModified(boolean value) { 656 if (fromLayer != null && fromLayer.data != null) { 657 fromLayer.data.setModified(value); 658 } 659 } 660 661 } 620 662 } -
src/org/openstreetmap/josm/gui/preferences/display/GPXSettingsPanel.java
29 29 import org.apache.commons.jcs3.access.exception.InvalidArgumentException; 30 30 import org.openstreetmap.josm.actions.ExpertToggleAction; 31 31 import org.openstreetmap.josm.data.gpx.GpxData; 32 import org.openstreetmap.josm.data.gpx.IGpxLayerPrefs; 32 33 import org.openstreetmap.josm.gui.MainApplication; 33 34 import org.openstreetmap.josm.gui.layer.GpxLayer; 34 35 import org.openstreetmap.josm.gui.layer.gpx.GpxDrawHelper; … … 173 174 * @return the value 174 175 */ 175 176 public static String getLayerPref(GpxLayer layer, String key) { 177 GpxData data = layer != null ? layer.data : null; 178 return getDataPref(data, key); 179 } 180 181 /** 182 * Reads the preference for the given layer or the default preference if not available 183 * @param data the data. Can be <code>null</code>, default preference will be returned then 184 * @param key the drawing key to be read, without "draw.rawgps." 185 * @return the value 186 */ 187 public static String getDataPref(IGpxLayerPrefs data, String key) { 176 188 Object d = DEFAULT_PREFS.get(key); 177 189 String ds; 178 190 if (d != null) { … … 181 193 Logging.warn("No default value found for layer preference \"" + key + "\"."); 182 194 ds = null; 183 195 } 184 return Optional.ofNullable(tryGet LayerPrefLocal(layer, key)).orElse(Config.getPref().get("draw.rawgps." + key, ds));196 return Optional.ofNullable(tryGetDataPrefLocal(data, key)).orElse(Config.getPref().get("draw.rawgps." + key, ds)); 185 197 } 186 198 187 199 /** … … 191 203 * @return the integer value 192 204 */ 193 205 public static int getLayerPrefInt(GpxLayer layer, String key) { 194 String s = getLayerPref(layer, key); 206 GpxData data = layer != null ? layer.data : null; 207 return getDataPrefInt(data, key); 208 } 209 210 /** 211 * Reads the integer preference for the given data or the default preference if not available 212 * @param data the data. Can be <code>null</code>, default preference will be returned then 213 * @param key the drawing key to be read, without "draw.rawgps." 214 * @return the integer value 215 */ 216 public static int getDataPrefInt(IGpxLayerPrefs data, String key) { 217 String s = getDataPref(data, key); 195 218 if (s != null) { 196 219 try { 197 220 return Integer.parseInt(s); … … 214 237 * @return the value or <code>null</code> if not found 215 238 */ 216 239 public static String tryGetLayerPrefLocal(GpxLayer layer, String key) { 217 return layer != null ? tryGet LayerPrefLocal(layer.data, key) : null;240 return layer != null ? tryGetDataPrefLocal(layer.data, key) : null; 218 241 } 219 242 220 243 /** … … 223 246 * @param key the drawing key to be read, without "draw.rawgps." 224 247 * @return the value or <code>null</code> if not found 225 248 */ 226 public static String tryGet LayerPrefLocal(GpxDatadata, String key) {249 public static String tryGetDataPrefLocal(IGpxLayerPrefs data, String key) { 227 250 return data != null ? data.getLayerPrefs().get(key) : null; 228 251 } 229 252 … … 237 260 String v = value == null ? null : value.toString(); 238 261 if (layers != null) { 239 262 for (GpxLayer l : layers) { 240 put LayerPrefLocal(l.data, key, v);263 putDataPrefLocal(l.data, key, v); 241 264 } 242 265 } else { 243 266 Config.getPref().put("draw.rawgps." + key, v); … … 252 275 */ 253 276 public static void putLayerPrefLocal(GpxLayer layer, String key, String value) { 254 277 if (layer == null || layer.data == null) return; 255 put LayerPrefLocal(layer.data, key, value);278 putDataPrefLocal(layer.data, key, value); 256 279 } 257 280 258 281 /** … … 261 284 * @param key the drawing key to be written, without "draw.rawgps." 262 285 * @param value the value or <code>null</code> to remove key 263 286 */ 264 public static void putLayerPrefLocal(GpxData data, String key, String value) { 287 public static void putDataPrefLocal(IGpxLayerPrefs data, String key, String value) { 288 if (data == null) return; 289 data.setModified(true); 265 290 if (Utils.isBlank(value) || 266 291 (getLayerPref(null, key).equals(value) && DEFAULT_PREFS.get(key) != null && DEFAULT_PREFS.get(key).toString().equals(value))) { 267 292 data.getLayerPrefs().remove(key); -
src/org/openstreetmap/josm/io/GpxWriter.java
148 148 149 149 validprefixes = namespaces.stream().map(n -> n.getPrefix()).collect(Collectors.toList()); 150 150 151 data.creator = JOSM_CREATOR_NAME; 151 152 out.println("<?xml version='1.0' encoding='UTF-8'?>"); 152 out.println("<gpx version=\"1.1\" creator=\"JOSM GPX export\" xmlns=\"http://www.topografix.com/GPX/1/1\"");153 153 154 out.print("<gpx version=\"1.1\" creator=\""); 155 out.print(JOSM_CREATOR_NAME); 156 out.println("\" xmlns=\"http://www.topografix.com/GPX/1/1\""); 157 154 158 StringBuilder schemaLocations = new StringBuilder("http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"); 155 159 156 160 for (XMLNamespace n : namespaces) { -
src/org/openstreetmap/josm/io/session/GpxTracksSessionExporter.java
6 6 import java.io.PrintWriter; 7 7 import java.io.Writer; 8 8 import java.nio.charset.StandardCharsets; 9 import java.time.Instant; 9 10 10 11 import org.openstreetmap.josm.gui.layer.GpxLayer; 11 12 import org.openstreetmap.josm.io.GpxWriter; … … 16 17 */ 17 18 public class GpxTracksSessionExporter extends GenericSessionExporter<GpxLayer> { 18 19 20 private Instant metaTime; 21 19 22 /** 20 23 * Constructs a new {@code GpxTracksSessionExporter}. 21 24 * @param layer GPX layer to export … … 36 39 protected void addDataFile(OutputStream out) { 37 40 Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8); 38 41 GpxWriter w = new GpxWriter(new PrintWriter(writer)); 42 if (metaTime != null) { 43 w.setMetaTime(metaTime); 44 } 39 45 w.write(layer.data); 40 46 w.flush(); 41 47 } 48 49 protected void setMetaTime(Instant metaTime) { 50 this.metaTime = metaTime; 51 } 42 52 } -
src/org/openstreetmap/josm/io/session/GpxTracksSessionImporter.java
54 54 } else { 55 55 importData = GpxImporter.loadLayers(in, support.getFile(fileStr), support.getLayerName(), progressMonitor); 56 56 } 57 if (importData.getGpxLayer() != null && importData.getGpxLayer().data != null) { 58 importData.getGpxLayer().data.fromSession = true; 59 } 57 60 58 61 support.addPostLayersTask(importData.getPostLayerTask()); 59 62 return getLayer(importData); -
src/org/openstreetmap/josm/io/session/MarkerSessionExporter.java
9 9 import java.io.PrintWriter; 10 10 import java.io.Writer; 11 11 import java.nio.charset.StandardCharsets; 12 import java.time.Instant; 12 13 import java.util.Collection; 13 14 import java.util.Collections; 14 15 … … 32 33 */ 33 34 public class MarkerSessionExporter extends AbstractSessionExporter<MarkerLayer> { 34 35 36 private Instant metaTime; 37 35 38 /** 36 39 * Constructs a new {@code MarkerSessionExporter}. 37 40 * @param layer marker layer to export … … 86 89 protected void addDataFile(OutputStream out) { 87 90 Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8); 88 91 MarkerWriter w = new MarkerWriter(new PrintWriter(writer)); 92 if (metaTime != null) { 93 w.setMetaTime(metaTime); 94 } 89 95 w.write(layer); 90 96 w.flush(); 91 97 } 92 98 99 protected void setMetaTime(Instant metaTime) { 100 this.metaTime = metaTime; 101 } 102 93 103 /** 94 104 * Writes GPX file from marker data. 95 105 */ … … 109 119 */ 110 120 public void write(MarkerLayer layer) { 111 121 GpxData data = new GpxData(); 122 layer.data.getLayerPrefs().forEach((k, v) -> { 123 if (k != null && k.indexOf("markers.") == 0) { 124 data.getLayerPrefs().put(k, v); 125 } 126 }); 112 127 data.put(GpxData.META_DESC, "exported JOSM marker layer"); 113 128 for (Marker m : layer.data) { 114 129 data.waypoints.add(m.convertToWayPoint()); -
src/org/openstreetmap/josm/io/session/MarkerSessionImporter.java
5 5 6 6 import java.io.IOException; 7 7 import java.io.InputStream; 8 import java.util.List;9 8 10 9 import javax.xml.xpath.XPath; 11 10 import javax.xml.xpath.XPathConstants; … … 14 13 import javax.xml.xpath.XPathFactory; 15 14 16 15 import org.openstreetmap.josm.gui.io.importexport.GpxImporter; 17 import org.openstreetmap.josm.gui.layer.GpxLayer;18 16 import org.openstreetmap.josm.gui.layer.Layer; 19 17 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer; 20 18 import org.openstreetmap.josm.gui.progress.ProgressMonitor; … … 50 48 51 49 support.addPostLayersTask(importData.getPostLayerTask()); 52 50 53 GpxLayer gpxLayer = null; 54 List<SessionReader.LayerDependency> deps = support.getLayerDependencies(); 55 if (!deps.isEmpty()) { 56 Layer layer = deps.get(0).getLayer(); 57 if (layer instanceof GpxLayer) { 58 gpxLayer = (GpxLayer) layer; 59 } 60 } 61 62 MarkerLayer markerLayer = importData.getMarkerLayer(); 63 if (markerLayer != null) { 64 markerLayer.fromLayer = gpxLayer; 65 } 66 67 return markerLayer; 51 return importData.getMarkerLayer(); 68 52 } 69 53 } catch (XPathExpressionException e) { 70 54 throw new IllegalDataException(e); -
src/org/openstreetmap/josm/io/session/SessionReader.java
3 3 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 5 6 import java.awt.Color;7 6 import java.awt.GraphicsEnvironment; 8 7 import java.io.BufferedInputStream; 9 8 import java.io.File; … … 46 45 import org.openstreetmap.josm.io.Compression; 47 46 import org.openstreetmap.josm.io.IllegalDataException; 48 47 import org.openstreetmap.josm.tools.CheckParameterUtil; 49 import org.openstreetmap.josm.tools.ColorHelper;50 48 import org.openstreetmap.josm.tools.JosmRuntimeException; 51 49 import org.openstreetmap.josm.tools.Logging; 52 50 import org.openstreetmap.josm.tools.MultiMap; … … 619 617 Logging.warn(ex); 620 618 } 621 619 } 622 String colorString = el.getAttribute("color");623 if (colorString != null) {624 try {625 Color color = ColorHelper.html2color(colorString);626 layer.setColor(color);627 } catch (RuntimeException ex) {628 Logging.warn("Cannot parse color " + colorString);629 }630 }631 620 layer.setName(names.get(entry.getKey())); 632 621 layers.add(layer); 633 622 } -
src/org/openstreetmap/josm/io/session/SessionWriter.java
43 43 import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer; 44 44 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer; 45 45 import org.openstreetmap.josm.gui.preferences.projection.ProjectionPreference; 46 import org.openstreetmap.josm.tools.ColorHelper;47 46 import org.openstreetmap.josm.tools.JosmRuntimeException; 48 47 import org.openstreetmap.josm.tools.Logging; 49 48 import org.openstreetmap.josm.tools.MultiMap; … … 241 240 if (!Utils.equalsEpsilon(layer.getOpacity(), 1.0)) { 242 241 el.setAttribute("opacity", Double.toString(layer.getOpacity())); 243 242 } 244 if (layer.getColor() != null) {245 el.setAttribute("color", ColorHelper.color2html(layer.getColor()));246 }247 243 Set<Layer> deps = dependencies.get(layer); 248 244 final String depends = deps == null ? "" : deps.stream().map(depLayer -> { 249 245 int depIndex = layers.indexOf(depLayer); -
test/data/sessions/data_export.gpx
1 <?xml version='1.0' encoding='UTF-8'?> 2 <gpx version="1.1" creator="JOSM GPX export" xmlns="http://www.topografix.com/GPX/1/1" 3 xmlns:josm="http://josm.openstreetmap.de/gpx-extensions-1.1" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://josm.openstreetmap.de/gpx-extensions-1.1 http://josm.openstreetmap.de/gpx-extensions-1.1.xsd"> 6 <metadata> 7 <time>2021-10-16T18:27:12.351Z</time> 8 <bounds minlat="42.72659" minlon="-0.00749" maxlat="42.72665" maxlon="-0.00747"/> 9 <extensions> 10 <josm:layerPreferences> 11 <josm:entry key="markers.color" value="#34567812"/> 12 </josm:layerPreferences> 13 </extensions> 14 </metadata> 15 <wpt lat="42.72665" lon="-0.00747"> 16 <time>2021-01-01T10:15:30Z</time> 17 </wpt> 18 <wpt lat="42.72659" lon="-0.00749"/> 19 </gpx> 20 No newline at end of file -
test/data/sessions/gpx_markers.jos
15 15 <layer index="1" name="GPX layer name" type="tracks" version="0.1" visible="true"> 16 16 <file>layers/01/data.gpx</file> 17 17 </layer> 18 <layer color="#34567812"index="2" name="Marker layer name" opacity="0.5" type="markers" version="0.1" visible="true">18 <layer index="2" name="Marker layer name" opacity="0.5" type="markers" version="0.1" visible="true"> 19 19 <file>layers/02/data.gpx</file> 20 20 </layer> 21 21 </layers> -
test/data/sessions/markers.gpx
Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
1 <?xml version='1.0' encoding='UTF-8'?> 2 <gpx version="1.1" creator="JOSM GPX export" xmlns="http://www.topografix.com/GPX/1/1" 3 xmlns:josm="http://josm.openstreetmap.de/gpx-extensions-1.1" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://josm.openstreetmap.de/gpx-extensions-1.1 http://josm.openstreetmap.de/gpx-extensions-1.1.xsd"> 6 <metadata> 7 <desc>exported JOSM marker layer</desc> 8 <time>2021-10-16T18:27:12.351Z</time> 9 <bounds minlat="42.72659" minlon="-0.00749" maxlat="42.72665" maxlon="-0.00747"/> 10 <extensions> 11 <josm:layerPreferences> 12 <josm:entry key="markers.color" value="#34567812"/> 13 </josm:layerPreferences> 14 </extensions> 15 </metadata> 16 <wpt lat="42.72665" lon="-0.00747"> 17 <time>2021-01-01T10:15:30Z</time> 18 </wpt> 19 <wpt lat="42.72659" lon="-0.00749"/> 20 </gpx> 21 No newline at end of file -
test/unit/org/openstreetmap/josm/data/gpx/GpxDataTest.java
503 503 col.add("josm", "from-server", "true"); 504 504 EqualsVerifier.forClass(GpxData.class).usingGetClass() 505 505 .suppress(Warning.NONFINAL_FIELDS) 506 .withIgnoredFields("creator", "fromServer", " storageFile", "initializing", "updating",506 .withIgnoredFields("creator", "fromServer", "fromSession", "storageFile", "initializing", "updating", 507 507 "suppressedInvalidate", "listeners", "tracks", "routes", "waypoints", "proxy", "segSpans", "modified") 508 508 .withPrefabValues(WayPoint.class, new WayPoint(LatLon.NORTH_POLE), new WayPoint(LatLon.SOUTH_POLE)) 509 509 .withPrefabValues(ListenerList.class, ListenerList.create(), ListenerList.create()) -
test/unit/org/openstreetmap/josm/data/gpx/GpxTrackTest.java
8 8 import java.util.ArrayList; 9 9 import java.util.HashMap; 10 10 11 import org.junit.jupiter.api.Test; 11 12 import org.junit.jupiter.api.extension.RegisterExtension; 12 import org.junit.jupiter.api.Test;13 13 import org.openstreetmap.josm.TestUtils; 14 14 import org.openstreetmap.josm.testutils.JOSMTestRules; 15 15 import org.openstreetmap.josm.tools.ListenerList; … … 31 31 public JOSMTestRules test = new JOSMTestRules(); 32 32 33 33 /** 34 * Tests w eather the track can read and write colors.34 * Tests whether the track can read and write colors. 35 35 */ 36 36 @Test 37 37 void testColors() { -
test/unit/org/openstreetmap/josm/io/session/SessionWriterTest.java
1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.io.session; 3 3 4 import static org.junit.jupiter.api.Assertions.assertEquals; 5 import static org.junit.jupiter.api.Assertions.fail; 6 4 7 import java.awt.Color; 5 8 import java.io.File; 6 9 import java.io.IOException; 7 import java.io.InputStream;8 10 import java.nio.charset.StandardCharsets; 9 11 import java.nio.file.Files; 10 12 import java.nio.file.Path; 11 13 import java.nio.file.Paths; 14 import java.time.Instant; 12 15 import java.util.Arrays; 13 16 import java.util.Collections; 14 17 import java.util.HashMap; 15 18 import java.util.List; 16 19 import java.util.Map; 20 import java.util.stream.Collectors; 21 import java.util.zip.ZipEntry; 17 22 import java.util.zip.ZipFile; 18 23 19 24 import org.junit.jupiter.api.BeforeEach; … … 42 47 43 48 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 44 49 45 import static org.junit.jupiter.api.Assertions.assertEquals;46 47 50 /** 48 51 * Unit tests for Session writing. 49 52 */ … … 108 111 MainApplication.getLayerManager().addLayer(createOsmLayer()); 109 112 } 110 113 111 private byte[]testWrite(List<Layer> layers, final boolean zip) throws IOException {114 private Map<String, byte[]> testWrite(List<Layer> layers, final boolean zip) throws IOException { 112 115 Map<Layer, SessionLayerExporter> exporters = new HashMap<>(); 113 116 if (zip) { 114 117 SessionWriter.registerSessionLayerExporter(OsmDataLayer.class, OsmHeadlessJozExporter.class); … … 118 121 SessionWriter.registerSessionLayerExporter(GpxLayer.class, GpxHeadlessJosExporter.class); 119 122 } 120 123 for (final Layer l : layers) { 121 exporters.put(l, SessionWriter.getSessionLayerExporter(l)); 124 SessionLayerExporter s = SessionWriter.getSessionLayerExporter(l); 125 exporters.put(l, s); 126 if (s instanceof GpxTracksSessionExporter) { 127 ((GpxTracksSessionExporter) s).setMetaTime(Instant.parse("2021-10-16T18:27:12.351Z")); 128 } else if (s instanceof MarkerSessionExporter) { 129 ((MarkerSessionExporter) s).setMetaTime(Instant.parse("2021-10-16T18:27:12.351Z")); 130 } 122 131 } 123 132 SessionWriter sw = new SessionWriter(layers, -1, exporters, new MultiMap<Layer, Layer>(), zip); 124 133 File file = new File(System.getProperty("java.io.tmpdir"), getClass().getName()+(zip ? ".joz" : ".jos")); … … 127 136 if (!zip) { 128 137 return null; 129 138 } 130 try (ZipFile zipFile = new ZipFile(file); 131 InputStream input = zipFile.getInputStream(zipFile.getEntry("session.jos"))) { 132 return Utils.readBytesFromStream(input); 139 try (ZipFile zipFile = new ZipFile(file)) { 140 return Collections.list(zipFile.entries()).stream().collect(Collectors.toMap(ZipEntry::getName, e -> { 141 try { 142 return Utils.readBytesFromStream(zipFile.getInputStream(e)); 143 } catch (IOException ex) { 144 fail(ex); 145 } 146 return null; 147 })); 133 148 } 134 149 } finally { 135 150 if (file.exists()) { … … 146 161 147 162 private GpxLayer createGpxLayer() { 148 163 GpxData data = new GpxData(); 149 data.waypoints.add(new WayPoint(new LatLon(42.72665, -0.00747))); 164 WayPoint wp = new WayPoint(new LatLon(42.72665, -0.00747)); 165 wp.setInstant(Instant.parse("2021-01-01T10:15:30.00Z")); 166 data.waypoints.add(wp); 150 167 data.waypoints.add(new WayPoint(new LatLon(42.72659, -0.00749))); 151 168 GpxLayer layer = new GpxLayer(data, "GPX layer name"); 152 169 layer.setAssociatedFile(new File("data.gpx")); … … 232 249 @Test 233 250 void testWriteGpxAndMarkerJoz() throws IOException { 234 251 GpxLayer gpx = createGpxLayer(); 235 byte[] bytes = testWrite(Arrays.asList(gpx, createMarkerLayer(gpx)), true); 252 Map<String, byte[]> bytes = testWrite(Arrays.asList(gpx, createMarkerLayer(gpx)), true); 253 236 254 Path path = Paths.get(TestUtils.getTestDataRoot() + "/sessions/gpx_markers.jos"); 237 255 String expected = new String(Files.readAllBytes(path), StandardCharsets.UTF_8).replace("\r", ""); 238 String actual = new String(bytes , StandardCharsets.UTF_8).replace("\r", "");256 String actual = new String(bytes.get("session.jos"), StandardCharsets.UTF_8).replace("\r", ""); 239 257 assertEquals(expected, actual); 258 259 path = Paths.get(TestUtils.getTestDataRoot() + "/sessions/data_export.gpx"); 260 expected = new String(Files.readAllBytes(path), StandardCharsets.UTF_8).replace("\r", ""); 261 actual = new String(bytes.get("layers/01/data.gpx"), StandardCharsets.UTF_8).replace("\r", ""); 262 assertEquals(expected, actual); 263 264 path = Paths.get(TestUtils.getTestDataRoot() + "/sessions/markers.gpx"); 265 expected = new String(Files.readAllBytes(path), StandardCharsets.UTF_8).replace("\r", ""); 266 actual = new String(bytes.get("layers/02/data.gpx"), StandardCharsets.UTF_8).replace("\r", ""); 267 assertEquals(expected, actual); 240 268 } 241 269 242 270 /**