Changeset 18466 in josm
- Timestamp:
- 2022-06-06T19:07:05+02:00 (2 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/SessionLoadAction.java
r18211 r18466 206 206 viewport = reader.getViewport(); 207 207 projectionChoice = reader.getProjectionChoice(); 208 SessionSaveAction.setCurrentSession(file, zip, reader.getLayers()); 208 209 } finally { 209 210 if (tempFile) { -
trunk/src/org/openstreetmap/josm/actions/SessionSaveAsAction.java
r18406 r18466 5 5 import static org.openstreetmap.josm.tools.I18n.tr; 6 6 7 import java.awt.Component;8 import java.awt.Dimension;9 import java.awt.GridBagLayout;10 7 import java.awt.event.ActionEvent; 11 import java.io.File; 12 import java.io.IOException; 13 import java.util.ArrayList; 14 import java.util.Arrays; 15 import java.util.Collection; 16 import java.util.HashMap; 17 import java.util.HashSet; 18 import java.util.List; 19 import java.util.Map; 20 import java.util.Set; 21 import java.util.stream.Collectors; 22 import java.util.stream.Stream; 8 import java.awt.event.KeyEvent; 23 9 24 import javax.swing.BorderFactory;25 import javax.swing.JCheckBox;26 import javax.swing.JFileChooser;27 import javax.swing.JLabel;28 import javax.swing.JOptionPane;29 import javax.swing.JPanel;30 import javax.swing.JScrollPane;31 import javax.swing.JTabbedPane;32 import javax.swing.SwingConstants;33 import javax.swing.border.EtchedBorder;34 import javax.swing.filechooser.FileFilter;35 36 import org.openstreetmap.josm.data.preferences.BooleanProperty;37 import org.openstreetmap.josm.gui.ExtendedDialog;38 import org.openstreetmap.josm.gui.HelpAwareOptionPane;39 10 import org.openstreetmap.josm.gui.MainApplication; 40 import org.openstreetmap.josm.gui.MapFrame;41 import org.openstreetmap.josm.gui.MapFrameListener;42 import org.openstreetmap.josm.gui.Notification;43 import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer;44 import org.openstreetmap.josm.gui.layer.Layer;45 import org.openstreetmap.josm.gui.util.WindowGeometry;46 import org.openstreetmap.josm.gui.widgets.AbstractFileChooser;47 import org.openstreetmap.josm.io.session.SessionLayerExporter;48 import org.openstreetmap.josm.io.session.SessionWriter;49 import org.openstreetmap.josm.tools.GBC;50 import org.openstreetmap.josm.tools.JosmRuntimeException;51 11 import org.openstreetmap.josm.tools.Logging; 52 import org.openstreetmap.josm.tools. MultiMap;12 import org.openstreetmap.josm.tools.Shortcut; 53 13 import org.openstreetmap.josm.tools.UserCancelException; 54 import org.openstreetmap.josm.tools.Utils;55 14 56 15 /** 57 * Saves a JOSM session 16 * Saves a JOSM session to a new file 58 17 * @since 4685 59 18 */ 60 public class SessionSaveAsAction extends DiskAccessAction implements MapFrameListener { 61 62 private transient List<Layer> layers; 63 private transient Map<Layer, SessionLayerExporter> exporters; 64 private transient MultiMap<Layer, Layer> dependencies; 65 66 private static final BooleanProperty SAVE_LOCAL_FILES_PROPERTY = new BooleanProperty("session.savelocal", true); 19 public class SessionSaveAsAction extends SessionSaveAction { 67 20 68 21 /** … … 80 33 */ 81 34 protected SessionSaveAsAction(boolean toolbar, boolean installAdapters) { 35 82 36 super(tr("Save Session As..."), "session", tr("Save the current session to a new file."), 83 null, toolbar, "save_as-session", installAdapters); 37 Shortcut.registerShortcut("system:savesessionas", tr("File: {0}", tr("Save Session As...")), 38 KeyEvent.VK_S, Shortcut.ALT_CTRL_SHIFT), 39 toolbar, "save_as-session", installAdapters); 40 84 41 setHelpId(ht("/Action/SessionSaveAs")); 85 MainApplication.addMapFrameListener(this);86 42 } 87 43 … … 89 45 public void actionPerformed(ActionEvent e) { 90 46 try { 91 saveSession( );47 saveSession(true, false); 92 48 } catch (UserCancelException ignore) { 93 49 Logging.trace(ignore); … … 96 52 97 53 @Override 98 public void destroy() { 99 MainApplication.removeMapFrameListener(this); 100 super.destroy(); 101 } 102 103 /** 104 * Attempts to save the session. 105 * @throws UserCancelException when the user has cancelled the save process. 106 * @since 8913 107 */ 108 public void saveSession() throws UserCancelException { 109 if (!isEnabled()) { 110 return; 111 } 112 113 SessionSaveAsDialog dlg = new SessionSaveAsDialog(); 114 dlg.showDialog(); 115 if (dlg.getValue() != 1) { 116 throw new UserCancelException(); 117 } 118 119 // TODO: resolve dependencies for layers excluded by the user 120 List<Layer> layersOut = layers.stream() 121 .filter(layer -> exporters.get(layer) != null && exporters.get(layer).shallExport()) 122 .collect(Collectors.toList()); 123 124 boolean zipRequired = layersOut.stream().map(exporters::get) 125 .anyMatch(ex -> ex != null && ex.requiresZip()); 126 127 FileFilter joz = new ExtensionFileFilter("joz", "joz", tr("Session file (archive) (*.joz)")); 128 FileFilter jos = new ExtensionFileFilter("jos", "jos", tr("Session file (*.jos)")); 129 130 AbstractFileChooser fc; 131 132 if (zipRequired) { 133 fc = createAndOpenFileChooser(false, false, tr("Save Session"), joz, JFileChooser.FILES_ONLY, "lastDirectory"); 134 } else { 135 fc = createAndOpenFileChooser(false, false, tr("Save Session"), Arrays.asList(jos, joz), jos, 136 JFileChooser.FILES_ONLY, "lastDirectory"); 137 } 138 139 if (fc == null) { 140 throw new UserCancelException(); 141 } 142 143 File file = fc.getSelectedFile(); 144 String fn = file.getName(); 145 146 boolean zip; 147 FileFilter ff = fc.getFileFilter(); 148 if (zipRequired || joz.equals(ff)) { 149 zip = true; 150 } else if (jos.equals(ff)) { 151 zip = false; 152 } else { 153 if (Utils.hasExtension(fn, "joz")) { 154 zip = true; 155 } else { 156 zip = false; 157 } 158 } 159 if (fn.indexOf('.') == -1) { 160 file = new File(file.getPath() + (zip ? ".joz" : ".jos")); 161 if (!SaveActionBase.confirmOverwrite(file)) { 162 throw new UserCancelException(); 163 } 164 } 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 if (layersToSaveStream 176 .map(layer -> SaveAction.getInstance().doSave(layer, true)) 177 .collect(Collectors.toList()) // force evaluation of all elements 178 .contains(false)) { 179 180 new Notification(tr("Not all local files referenced by the session file could be saved." 181 + "<br>Make sure you save them before closing JOSM.")) 182 .setIcon(JOptionPane.WARNING_MESSAGE) 183 .setDuration(Notification.TIME_LONG) 184 .show(); 185 } 186 } else if (layersToSaveStream.anyMatch(l -> true)) { 187 new Notification(tr("Not all local files referenced by the session file are saved yet." 188 + "<br>Make sure you save them before closing JOSM.")) 189 .setIcon(JOptionPane.INFORMATION_MESSAGE) 190 .setDuration(Notification.TIME_LONG) 191 .show(); 192 } 193 194 int active = -1; 195 Layer activeLayer = getLayerManager().getActiveLayer(); 196 if (activeLayer != null) { 197 active = layersOut.indexOf(activeLayer); 198 } 199 200 SessionWriter sw = new SessionWriter(layersOut, active, exporters, dependencies, zip); 201 try { 202 Notification savingNotification = showSavingNotification(file.getName()); 203 sw.write(file); 204 SaveActionBase.addToFileOpenHistory(file); 205 showSavedNotification(savingNotification, file.getName()); 206 } catch (IOException ex) { 207 Logging.error(ex); 208 HelpAwareOptionPane.showMessageDialogInEDT( 209 MainApplication.getMainFrame(), 210 tr("<html>Could not save session file ''{0}''.<br>Error is:<br>{1}</html>", 211 file.getName(), Utils.escapeReservedCharactersHTML(ex.getMessage())), 212 tr("IO Error"), 213 JOptionPane.ERROR_MESSAGE, 214 null 215 ); 216 } 217 } 218 219 /** 220 * The "Save Session" dialog 221 */ 222 public class SessionSaveAsDialog extends ExtendedDialog { 223 224 /** 225 * Constructs a new {@code SessionSaveAsDialog}. 226 */ 227 public SessionSaveAsDialog() { 228 super(MainApplication.getMainFrame(), tr("Save Session"), tr("Save As"), tr("Cancel")); 229 configureContextsensitiveHelp("Action/SessionSaveAs", true /* show help button */); 230 initialize(); 231 setButtonIcons("save_as", "cancel"); 232 setDefaultButton(1); 233 setRememberWindowGeometry(getClass().getName() + ".geometry", 234 WindowGeometry.centerInWindow(MainApplication.getMainFrame(), new Dimension(450, 450))); 235 setContent(build(), false); 236 } 237 238 /** 239 * Initializes action. 240 */ 241 public final void initialize() { 242 layers = new ArrayList<>(getLayerManager().getLayers()); 243 exporters = new HashMap<>(); 244 dependencies = new MultiMap<>(); 245 246 Set<Layer> noExporter = new HashSet<>(); 247 248 for (Layer layer : layers) { 249 SessionLayerExporter exporter = null; 250 try { 251 exporter = SessionWriter.getSessionLayerExporter(layer); 252 } catch (IllegalArgumentException | JosmRuntimeException e) { 253 Logging.error(e); 254 } 255 if (exporter != null) { 256 exporters.put(layer, exporter); 257 Collection<Layer> deps = exporter.getDependencies(); 258 if (deps != null) { 259 dependencies.putAll(layer, deps); 260 } else { 261 dependencies.putVoid(layer); 262 } 263 } else { 264 noExporter.add(layer); 265 exporters.put(layer, null); 266 } 267 } 268 269 int numNoExporter = 0; 270 WHILE: while (numNoExporter != noExporter.size()) { 271 numNoExporter = noExporter.size(); 272 for (Layer layer : layers) { 273 if (noExporter.contains(layer)) continue; 274 for (Layer depLayer : dependencies.get(layer)) { 275 if (noExporter.contains(depLayer)) { 276 noExporter.add(layer); 277 exporters.put(layer, null); 278 break WHILE; 279 } 280 } 281 } 282 } 283 } 284 285 protected final Component build() { 286 JPanel op = new JPanel(new GridBagLayout()); 287 JPanel ip = new JPanel(new GridBagLayout()); 288 for (Layer layer : layers) { 289 JPanel wrapper = new JPanel(new GridBagLayout()); 290 wrapper.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED)); 291 Component exportPanel; 292 SessionLayerExporter exporter = exporters.get(layer); 293 if (exporter == null) { 294 if (!exporters.containsKey(layer)) throw new AssertionError(); 295 exportPanel = getDisabledExportPanel(layer); 296 } else { 297 exportPanel = exporter.getExportPanel(); 298 } 299 wrapper.add(exportPanel, GBC.std().fill(GBC.HORIZONTAL)); 300 ip.add(wrapper, GBC.eol().fill(GBC.HORIZONTAL).insets(2, 2, 4, 2)); 301 } 302 ip.add(GBC.glue(0, 1), GBC.eol().fill(GBC.VERTICAL)); 303 JScrollPane sp = new JScrollPane(ip); 304 sp.setBorder(BorderFactory.createEmptyBorder()); 305 JPanel p = new JPanel(new GridBagLayout()); 306 p.add(sp, GBC.eol().fill()); 307 final JTabbedPane tabs = new JTabbedPane(); 308 tabs.addTab(tr("Layers"), p); 309 op.add(tabs, GBC.eol().fill()); 310 JCheckBox chkSaveLocal = new JCheckBox(tr("Save all local files to disk"), SAVE_LOCAL_FILES_PROPERTY.get()); 311 chkSaveLocal.addChangeListener(l -> { 312 SAVE_LOCAL_FILES_PROPERTY.put(chkSaveLocal.isSelected()); 313 }); 314 op.add(chkSaveLocal); 315 return op; 316 } 317 318 protected final Component getDisabledExportPanel(Layer layer) { 319 JPanel p = new JPanel(new GridBagLayout()); 320 JCheckBox include = new JCheckBox(); 321 include.setEnabled(false); 322 JLabel lbl = new JLabel(layer.getName(), layer.getIcon(), SwingConstants.LEADING); 323 lbl.setToolTipText(tr("No exporter for this layer")); 324 lbl.setLabelFor(include); 325 lbl.setEnabled(false); 326 p.add(include, GBC.std()); 327 p.add(lbl, GBC.std()); 328 p.add(GBC.glue(1, 0), GBC.std().fill(GBC.HORIZONTAL)); 329 return p; 330 } 54 protected void addListeners() { 55 MainApplication.addMapFrameListener(this); 331 56 } 332 57 333 58 @Override 334 protected void updateEnabledState() { 335 setEnabled(MainApplication.isDisplayingMapView()); 336 } 337 338 @Override 339 public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { 340 updateEnabledState(); 59 protected void removeListeners() { 60 MainApplication.removeMapFrameListener(this); 341 61 } 342 62 } -
trunk/src/org/openstreetmap/josm/gui/MainMenu.java
r18021 r18466 97 97 import org.openstreetmap.josm.actions.SelectAllAction; 98 98 import org.openstreetmap.josm.actions.SelectNonBranchingWaySequencesAction; 99 import org.openstreetmap.josm.actions.SessionSaveAction; 99 100 import org.openstreetmap.josm.actions.SessionSaveAsAction; 100 101 import org.openstreetmap.josm.actions.ShowStatusReportAction; … … 177 178 /** File / Save As... **/ 178 179 public final SaveAsAction saveAs = SaveAsAction.getInstance(); 180 /** File / Session > Save Session **/ 181 public SessionSaveAction sessionSave = SessionSaveAction.getInstance(); 179 182 /** File / Session > Save Session As... **/ 180 public SessionSaveAsAction sessionSaveAs ;183 public SessionSaveAsAction sessionSaveAs = new SessionSaveAsAction(); 181 184 /** File / Export to GPX... **/ 182 185 public final GpxExportAction gpxExport = new GpxExportAction(); … … 739 742 add(fileMenu, save); 740 743 add(fileMenu, saveAs); 741 sessionSaveAs = new SessionSaveAsAction();742 ExpertToggleAction.addVisibilitySwitcher(fileMenu.add(sessionSaveAs));744 add(fileMenu, sessionSave, true); 745 add(fileMenu, sessionSaveAs, true); 743 746 add(fileMenu, gpxExport, true); 744 747 fileMenu.addSeparator(); -
trunk/src/org/openstreetmap/josm/gui/io/SaveLayersDialog.java
r18121 r18466 41 41 import javax.swing.event.TableModelListener; 42 42 43 import org.openstreetmap.josm.actions.SessionSaveAsAction; 43 import org.openstreetmap.josm.actions.JosmAction; 44 import org.openstreetmap.josm.actions.SessionSaveAction; 44 45 import org.openstreetmap.josm.actions.UploadAction; 45 46 import org.openstreetmap.josm.gui.ExceptionDialogUtil; … … 93 94 94 95 private final SaveAndProceedAction saveAndProceedAction = new SaveAndProceedAction(); 95 private final SaveSession Action saveSessionAction = new SaveSessionAction();96 private final SaveSessionButtonAction saveSessionAction = new SaveSessionButtonAction(); 96 97 private final DiscardAndProceedAction discardAndProceedAction = new DiscardAndProceedAction(); 97 98 private final CancelAction cancelAction = new CancelAction(); … … 433 434 } 434 435 435 class SaveSession Action extends SessionSaveAsAction {436 437 SaveSession Action() {438 super( false, false);436 class SaveSessionButtonAction extends JosmAction { 437 438 SaveSessionButtonAction() { 439 super(tr("Save Session"), "session", SessionSaveAction.getTooltip(), null, false, null, false); 439 440 } 440 441 … … 442 443 public void actionPerformed(ActionEvent e) { 443 444 try { 444 saveSession(); 445 setUserAction(UserAction.PROCEED); 446 closeDialog(); 445 if (SessionSaveAction.getInstance().saveSession(false, true)) { 446 setUserAction(UserAction.PROCEED); 447 closeDialog(); 448 } 447 449 } catch (UserCancelException ignore) { 448 450 Logging.trace(ignore); -
trunk/src/org/openstreetmap/josm/gui/layer/LayerManager.java
r17850 r18466 132 132 super(source); 133 133 this.removedLayer = removedLayer; 134 this.lastLayer = source.getLayers(). size() == 1;134 this.lastLayer = source.getLayers().isEmpty(); 135 135 } 136 136 -
trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
r18457 r18466 759 759 */ 760 760 public static GpxData toGpxData(DataSet data, File file) { 761 GpxData gpxData = new GpxData( );761 GpxData gpxData = new GpxData(true); 762 762 fillGpxData(gpxData, data, file, GpxConstants.GPX_PREFIX); 763 gpxData.endUpdate(); 763 764 return gpxData; 764 765 } … … 1011 1012 @Override 1012 1013 public void actionPerformed(ActionEvent e) { 1014 String name = getName().replaceAll("^" + tr("Converted from: {0}", ""), ""); 1013 1015 final GpxData gpxData = toGpxData(); 1014 final GpxLayer gpxLayer = new GpxLayer(gpxData, tr("Converted from: {0}", getName()));1016 final GpxLayer gpxLayer = new GpxLayer(gpxData, tr("Converted from: {0}", name), true); 1015 1017 if (getAssociatedFile() != null) { 1016 1018 String filename = getAssociatedFile().getName().replaceAll(Pattern.quote(".gpx.osm") + '$', "") + ".gpx"; 1017 1019 gpxLayer.setAssociatedFile(new File(getAssociatedFile().getParentFile(), filename)); 1020 gpxLayer.getGpxData().setModified(true); 1018 1021 } 1019 1022 MainApplication.getLayerManager().addLayer(gpxLayer, false); -
trunk/src/org/openstreetmap/josm/gui/layer/gpx/ConvertToDataLayerAction.java
r18076 r18466 72 72 SimplifyWayAction.simplifyWays(ways, err); 73 73 } 74 final OsmDataLayer osmLayer = new OsmDataLayer(ds, tr("Converted from: {0}", layer.getName()), null); 74 String name = layer.getName().replaceAll("^" + tr("Converted from: {0}", ""), ""); 75 final OsmDataLayer osmLayer = new OsmDataLayer(ds, tr("Converted from: {0}", name), null); 75 76 if (layer.getAssociatedFile() != null) { 76 77 osmLayer.setAssociatedFile(new File(layer.getAssociatedFile().getParentFile(), -
trunk/src/org/openstreetmap/josm/io/session/GenericSessionExporter.java
r17733 r18466 192 192 file.appendChild(support.createTextNode(zipPath)); 193 193 addDataFile(support.getOutputStreamZip(zipPath)); 194 layer.setAssociatedFile(null); 195 if (layer instanceof AbstractModifiableLayer) { 196 ((AbstractModifiableLayer) layer).onPostSaveToFile(); 197 } 194 198 } else { 195 199 try { -
trunk/src/org/openstreetmap/josm/io/session/GpxTracksSessionExporter.java
r18287 r18466 2 2 package org.openstreetmap.josm.io.session; 3 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 6 import java.io.IOException; 4 7 import java.io.OutputStream; 5 8 import java.io.OutputStreamWriter; … … 9 12 import java.time.Instant; 10 13 14 import javax.swing.JCheckBox; 15 import javax.swing.JPanel; 16 11 17 import org.openstreetmap.josm.gui.layer.GpxLayer; 12 18 import org.openstreetmap.josm.io.GpxWriter; 19 import org.openstreetmap.josm.io.session.SessionWriter.ExportSupport; 20 import org.openstreetmap.josm.tools.GBC; 21 import org.w3c.dom.Element; 13 22 14 23 /** … … 19 28 20 29 private Instant metaTime; 30 private JCheckBox chkMarkers; 31 private boolean hasMarkerLayer; 21 32 22 33 /** … … 33 44 throw new IllegalArgumentException("GPX layer without data: " + layer); 34 45 } 46 47 hasMarkerLayer = layer.getLinkedMarkerLayer() != null 48 && layer.getLinkedMarkerLayer().data != null 49 && !layer.getLinkedMarkerLayer().data.isEmpty(); 50 } 51 52 @Override 53 public JPanel getExportPanel() { 54 JPanel p = super.getExportPanel(); 55 if (hasMarkerLayer) { 56 chkMarkers = new JCheckBox(); 57 chkMarkers.setText(tr("include marker layer \"{0}\"", layer.getLinkedMarkerLayer().getName())); 58 chkMarkers.setSelected(true); 59 p.add(chkMarkers, GBC.eol().insets(12, 0, 0, 5)); 60 } 61 return p; 62 } 63 64 @Override 65 public Element export(ExportSupport support) throws IOException { 66 Element el = super.export(support); 67 if (hasMarkerLayer && (chkMarkers == null || chkMarkers.isSelected())) { 68 Element markerEl = support.createElement("markerLayer"); 69 markerEl.setAttribute("index", Integer.toString(support.getLayerIndexOf(layer.getLinkedMarkerLayer()))); 70 markerEl.setAttribute("name", layer.getLinkedMarkerLayer().getName()); 71 markerEl.setAttribute("visible", Boolean.toString(layer.getLinkedMarkerLayer().isVisible())); 72 if (layer.getLinkedMarkerLayer().getOpacity() != 1) { 73 markerEl.setAttribute("opacity", Double.toString(layer.getLinkedMarkerLayer().getOpacity())); 74 } 75 el.appendChild(markerEl); 76 } 77 return el; 35 78 } 36 79 -
trunk/src/org/openstreetmap/josm/io/session/GpxTracksSessionImporter.java
r18287 r18466 20 20 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 21 21 import org.openstreetmap.josm.io.IllegalDataException; 22 import org.openstreetmap.josm.tools.Logging; 22 23 import org.openstreetmap.josm.tools.Utils; 23 24 import org.w3c.dom.Element; 25 import org.w3c.dom.Node; 26 import org.w3c.dom.NodeList; 24 27 25 28 /** … … 58 61 importData.getGpxLayer().data.fromSession = true; 59 62 } 63 NodeList markerNodes = elem.getElementsByTagName("markerLayer"); 64 if (markerNodes.getLength() > 0 && markerNodes.item(0).getNodeType() == Node.ELEMENT_NODE) { 65 Element markerEl = (Element) markerNodes.item(0); 66 try { 67 int index = Integer.parseInt(markerEl.getAttribute("index")); 68 support.addSubLayer(index, importData.getMarkerLayer(), markerEl); 69 } catch (NumberFormatException ex) { 70 Logging.warn(ex); 71 } 72 } 60 73 61 74 support.addPostLayersTask(importData.getPostLayerTask()); -
trunk/src/org/openstreetmap/josm/io/session/MarkerSessionExporter.java
r18287 r18466 35 35 36 36 private Instant metaTime; 37 private boolean canExport = true; 37 38 38 39 /** … … 54 55 @Override 55 56 public Component getExportPanel() { 57 export.setSelected(true); //true even when not shown to the user as the index should be reserved for the corresponding GPX layer 58 if (layer.fromLayer != null && layer.fromLayer.getData() != null) { 59 canExport = false; 60 return null; 61 } 56 62 final JPanel p = new JPanel(new GridBagLayout()); 57 export.setSelected(true);58 63 final JLabel lbl = new JLabel(layer.getName(), layer.getIcon(), SwingConstants.LEADING); 59 64 lbl.setToolTipText(layer.getToolTipText()); … … 67 72 @Override 68 73 public boolean requiresZip() { 69 return true;74 return canExport; 70 75 } 71 76 72 77 @Override 73 78 public Element export(ExportSupport support) throws IOException { 79 if (!canExport) return null; 80 74 81 Element layerEl = support.createElement("layer"); 75 82 layerEl.setAttribute("type", "markers"); -
trunk/src/org/openstreetmap/josm/io/session/MarkerSessionImporter.java
r18287 r18466 49 49 support.addPostLayersTask(importData.getPostLayerTask()); 50 50 51 importData.getGpxLayer().destroy(); 51 52 return importData.getMarkerLayer(); 52 53 } -
trunk/src/org/openstreetmap/josm/io/session/SessionReader.java
r18287 r18466 15 15 import java.nio.charset.StandardCharsets; 16 16 import java.nio.file.Files; 17 import java.util.AbstractMap.SimpleEntry; 17 18 import java.util.ArrayList; 18 19 import java.util.Collection; … … 251 252 private final int layerIndex; 252 253 private final List<LayerDependency> layerDependencies; 254 private Map<Integer, Entry<Layer, Element>> subLayers; 253 255 254 256 /** … … 277 279 public void addPostLayersTask(Runnable task) { 278 280 postLoadTasks.add(task); 281 } 282 283 /** 284 * Add sub layers 285 * @param idx index 286 * @param layer sub layer 287 * @param el The XML element of the sub layer. 288 * Should contain "index" and "name" attributes. 289 * Can contain "opacity" and "visible" attributes 290 * @since 18466 291 */ 292 public void addSubLayer(int idx, Layer layer, Element el) { 293 if (subLayers == null) { 294 subLayers = new HashMap<>(); 295 } 296 subLayers.put(idx, new SimpleEntry<>(layer, el)); 297 } 298 299 /** 300 * Returns the sub layers 301 * @return the sub layers. Can be null. 302 * @since 18466 303 */ 304 public Map<Integer, Entry<Layer, Element>> getSubLayers() { 305 return subLayers; 279 306 } 280 307 … … 507 534 final Map<Integer, Layer> layersMap = new TreeMap<>(Collections.reverseOrder()); 508 535 final Map<Integer, SessionLayerImporter> importers = new HashMap<>(); 509 final Map<Integer, String> names = new HashMap<>();510 536 511 537 progressMonitor.setTicksCount(sorted.size()); … … 520 546 } 521 547 String name = e.getAttribute("name"); 522 names.put(idx, name);523 548 if (!e.hasAttribute("type")) { 524 549 error(tr("missing mandatory attribute ''type'' for element ''layer''")); … … 596 621 597 622 layersMap.put(idx, layer); 623 setLayerAttributes(layer, e); 624 625 if (support.getSubLayers() != null) { 626 support.getSubLayers().forEach((Integer markerIndex, Entry<Layer, Element> entry) -> { 627 Layer subLayer = entry.getKey(); 628 Element subElement = entry.getValue(); 629 630 layersMap.put(markerIndex, subLayer); 631 setLayerAttributes(subLayer, subElement); 632 }); 633 } 634 598 635 } 599 636 progressMonitor.worked(1); 600 637 } 638 601 639 602 640 layers = new ArrayList<>(); 603 641 for (Entry<Integer, Layer> entry : layersMap.entrySet()) { 604 642 Layer layer = entry.getValue(); 605 if (layer == null) { 606 continue; 607 } 608 Element el = elems.get(entry.getKey()); 609 if (el.hasAttribute("visible")) { 610 layer.setVisible(Boolean.parseBoolean(el.getAttribute("visible"))); 611 } 612 if (el.hasAttribute("opacity")) { 613 try { 614 double opacity = Double.parseDouble(el.getAttribute("opacity")); 615 layer.setOpacity(opacity); 616 } catch (NumberFormatException ex) { 617 Logging.warn(ex); 618 } 619 } 620 layer.setName(names.get(entry.getKey())); 621 layers.add(layer); 643 if (layer != null) { 644 layers.add(layer); 645 } 646 } 647 } 648 649 private static void setLayerAttributes(Layer layer, Element e) { 650 if (layer == null) 651 return; 652 653 if (e.hasAttribute("name")) { 654 layer.setName(e.getAttribute("name")); 655 } 656 if (e.hasAttribute("visible")) { 657 layer.setVisible(Boolean.parseBoolean(e.getAttribute("visible"))); 658 } 659 if (e.hasAttribute("opacity")) { 660 try { 661 double opacity = Double.parseDouble(e.getAttribute("opacity")); 662 layer.setOpacity(opacity); 663 } catch (NumberFormatException ex) { 664 Logging.warn(ex); 665 } 622 666 } 623 667 } -
trunk/src/org/openstreetmap/josm/io/session/SessionWriter.java
r18287 r18466 175 175 176 176 /** 177 * Get the index of the specified layer 178 * @param layer the layer 179 * @return the index of the specified layer 180 * @since 18466 181 */ 182 public int getLayerIndexOf(Layer layer) { 183 return layers.indexOf(layer) + 1; 184 } 185 186 /** 177 187 * Create a file inside the zip archive. 178 188 * … … 235 245 ExportSupport support = new ExportSupport(doc, index+1); 236 246 Element el = exporter.export(support); 247 if (el == null) continue; 237 248 el.setAttribute("index", Integer.toString(index+1)); 238 249 el.setAttribute("name", layer.getName()); -
trunk/src/org/openstreetmap/josm/tools/ListenerList.java
r17374 r18466 144 144 */ 145 145 public boolean hasListeners() { 146 return !listeners.isEmpty() ;146 return !listeners.isEmpty() || weakListeners.stream().map(l -> l.listener.get()).anyMatch(Objects::nonNull); 147 147 } 148 148 -
trunk/test/unit/org/openstreetmap/josm/actions/SessionSaveAsActionTest.java
r17275 r18466 4 4 import static org.junit.jupiter.api.Assertions.assertFalse; 5 5 6 import org.junit.jupiter.api.Test; 6 7 import org.junit.jupiter.api.extension.RegisterExtension; 7 import org.junit.jupiter.api.Test;8 8 import org.openstreetmap.josm.testutils.JOSMTestRules; 9 9 … … 20 20 @RegisterExtension 21 21 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 22 public JOSMTestRules test = new JOSMTestRules() ;22 public JOSMTestRules test = new JOSMTestRules().main(); 23 23 24 24 /** -
trunk/test/unit/org/openstreetmap/josm/io/session/SessionWriterTest.java
r18287 r18466 51 51 * Unit tests for Session writing. 52 52 */ 53 class SessionWriterTest {53 public class SessionWriterTest { 54 54 55 55 protected static final class OsmHeadlessJosExporter extends OsmDataSessionExporter { … … 123 123 for (final Layer l : layers) { 124 124 SessionLayerExporter s = SessionWriter.getSessionLayerExporter(l); 125 s.getExportPanel(); 125 126 exporters.put(l, s); 126 127 if (s instanceof GpxTracksSessionExporter) { … … 154 155 } 155 156 156 private OsmDataLayer createOsmLayer() { 157 /** 158 * Creates an OSM layer 159 * @return OSM layer 160 * @since 18466 161 */ 162 public static OsmDataLayer createOsmLayer() { 157 163 OsmDataLayer layer = new OsmDataLayer(new DataSet(), "OSM layer name", null); 158 164 layer.setAssociatedFile(new File("data.osm")); … … 160 166 } 161 167 162 private GpxLayer createGpxLayer() { 168 /** 169 * Creates a GPX layer 170 * @return GPX layer 171 * @since 18466 172 */ 173 public static GpxLayer createGpxLayer() { 163 174 GpxData data = new GpxData(); 164 175 WayPoint wp = new WayPoint(new LatLon(42.72665, -0.00747)); … … 171 182 } 172 183 173 private MarkerLayer createMarkerLayer(GpxLayer gpx) { 184 /** 185 * Creates a MarkerLayer 186 * @param gpx linked GPX layer 187 * @return MarkerLayer 188 * @since 18466 189 */ 190 public static MarkerLayer createMarkerLayer(GpxLayer gpx) { 174 191 MarkerLayer layer = new MarkerLayer(gpx.data, "Marker layer name", gpx.getAssociatedFile(), gpx); 175 192 layer.setOpacity(0.5); 176 193 layer.setColor(new Color(0x12345678, true)); 194 gpx.setLinkedMarkerLayer(layer); 177 195 return layer; 178 196 } 179 197 180 private ImageryLayer createImageryLayer() { 198 /** 199 * Creates an ImageryLayer 200 * @return ImageryLayer 201 * @since 18466 202 */ 203 public static ImageryLayer createImageryLayer() { 181 204 TMSLayer layer = new TMSLayer(new ImageryInfo("the name", "http://www.url.com/")); 182 205 layer.getDisplaySettings().setOffsetBookmark( … … 185 208 } 186 209 187 private NoteLayer createNoteLayer() { 210 /** 211 * Creates a NoteLayer 212 * @return NoteLayer 213 * @since 18466 214 */ 215 public static NoteLayer createNoteLayer() { 188 216 return new NoteLayer(Arrays.asList(new Note(LatLon.ZERO)), "layer name"); 189 217 } … … 250 278 void testWriteGpxAndMarkerJoz() throws IOException { 251 279 GpxLayer gpx = createGpxLayer(); 252 Map<String, byte[]> bytes = testWrite(Arrays.asList(gpx, createMarkerLayer(gpx)), true); 253 254 Path path = Paths.get(TestUtils.getTestDataRoot() + "/sessions/gpx_markers.jos"); 280 MarkerLayer markers = createMarkerLayer(gpx); 281 Map<String, byte[]> bytes = testWrite(Arrays.asList(gpx, markers), true); 282 283 Path path = Paths.get(TestUtils.getTestDataRoot() + "/sessions/gpx_markers_combined.jos"); 255 284 String expected = new String(Files.readAllBytes(path), StandardCharsets.UTF_8).replace("\r", ""); 256 285 String actual = new String(bytes.get("session.jos"), StandardCharsets.UTF_8).replace("\r", ""); … … 262 291 assertEquals(expected, actual); 263 292 293 //Test writing when the marker layer has no corresponding GPX layer: 294 gpx.setLinkedMarkerLayer(null); 295 markers.fromLayer = null; 296 markers.data.transferLayerPrefs(gpx.data.getLayerPrefs()); 297 bytes = testWrite(Arrays.asList(gpx, markers), true); 298 299 path = Paths.get(TestUtils.getTestDataRoot() + "/sessions/gpx_markers.jos"); 300 expected = new String(Files.readAllBytes(path), StandardCharsets.UTF_8).replace("\r", ""); 301 actual = new String(bytes.get("session.jos"), StandardCharsets.UTF_8).replace("\r", ""); 302 assertEquals(expected, actual); 303 304 path = Paths.get(TestUtils.getTestDataRoot() + "/sessions/data_export.gpx"); 305 expected = new String(Files.readAllBytes(path), StandardCharsets.UTF_8).replace("\r", ""); 306 actual = new String(bytes.get("layers/01/data.gpx"), StandardCharsets.UTF_8).replace("\r", ""); 307 assertEquals(expected, actual); 308 264 309 path = Paths.get(TestUtils.getTestDataRoot() + "/sessions/markers.gpx"); 265 310 expected = new String(Files.readAllBytes(path), StandardCharsets.UTF_8).replace("\r", ""); 266 311 actual = new String(bytes.get("layers/02/data.gpx"), StandardCharsets.UTF_8).replace("\r", ""); 267 312 assertEquals(expected, actual); 313 268 314 } 269 315
Note:
See TracChangeset
for help on using the changeset viewer.