source: josm/trunk/src/org/openstreetmap/josm/actions/SessionSaveAsAction.java@ 18135

Last change on this file since 18135 was 18135, checked in by Don-vip, 3 years ago

see #16709 - fix #20755 - Display a notification while/after saving session files

  • Property svn:eol-style set to native
File size: 10.9 KB
RevLine 
[4685]1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions;
3
[5438]4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
[4685]5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.Component;
8import java.awt.Dimension;
9import java.awt.GridBagLayout;
10import java.awt.event.ActionEvent;
11import java.io.File;
12import java.io.IOException;
13import java.util.ArrayList;
[5438]14import java.util.Arrays;
[4685]15import java.util.Collection;
16import java.util.HashMap;
17import java.util.HashSet;
18import java.util.List;
19import java.util.Map;
20import java.util.Set;
[16438]21import java.util.stream.Collectors;
[4685]22
23import javax.swing.BorderFactory;
24import javax.swing.JCheckBox;
25import javax.swing.JFileChooser;
26import javax.swing.JLabel;
27import javax.swing.JOptionPane;
28import javax.swing.JPanel;
29import javax.swing.JScrollPane;
30import javax.swing.JTabbedPane;
31import javax.swing.SwingConstants;
32import javax.swing.border.EtchedBorder;
33import javax.swing.filechooser.FileFilter;
34
35import org.openstreetmap.josm.gui.ExtendedDialog;
36import org.openstreetmap.josm.gui.HelpAwareOptionPane;
[12630]37import org.openstreetmap.josm.gui.MainApplication;
[9629]38import org.openstreetmap.josm.gui.MapFrame;
39import org.openstreetmap.josm.gui.MapFrameListener;
[18135]40import org.openstreetmap.josm.gui.Notification;
[4685]41import org.openstreetmap.josm.gui.layer.Layer;
[12678]42import org.openstreetmap.josm.gui.util.WindowGeometry;
[7578]43import org.openstreetmap.josm.gui.widgets.AbstractFileChooser;
[4685]44import org.openstreetmap.josm.io.session.SessionLayerExporter;
45import org.openstreetmap.josm.io.session.SessionWriter;
46import org.openstreetmap.josm.tools.GBC;
[18133]47import org.openstreetmap.josm.tools.JosmRuntimeException;
[12620]48import org.openstreetmap.josm.tools.Logging;
[4685]49import org.openstreetmap.josm.tools.MultiMap;
[8919]50import org.openstreetmap.josm.tools.UserCancelException;
[8404]51import org.openstreetmap.josm.tools.Utils;
[4685]52
[6245]53/**
54 * Saves a JOSM session
55 * @since 4685
56 */
[9629]57public class SessionSaveAsAction extends DiskAccessAction implements MapFrameListener {
[4685]58
[8308]59 private transient List<Layer> layers;
60 private transient Map<Layer, SessionLayerExporter> exporters;
61 private transient MultiMap<Layer, Layer> dependencies;
[4685]62
[6245]63 /**
64 * Constructs a new {@code SessionSaveAsAction}.
65 */
[4685]66 public SessionSaveAsAction() {
[16509]67 this(true, false);
68 updateEnabledState();
[9152]69 }
70
71 /**
72 * Constructs a new {@code SessionSaveAsAction}.
73 * @param toolbar Register this action for the toolbar preferences?
74 * @param installAdapters False, if you don't want to install layer changed and selection changed adapters
75 */
76 protected SessionSaveAsAction(boolean toolbar, boolean installAdapters) {
[9173]77 super(tr("Save Session As..."), "session", tr("Save the current session to a new file."),
78 null, toolbar, "save_as-session", installAdapters);
[14397]79 setHelpId(ht("/Action/SessionSaveAs"));
[12639]80 MainApplication.addMapFrameListener(this);
[4685]81 }
82
83 @Override
84 public void actionPerformed(ActionEvent e) {
[8913]85 try {
86 saveSession();
[8919]87 } catch (UserCancelException ignore) {
[12620]88 Logging.trace(ignore);
[8913]89 }
90 }
91
[14470]92 @Override
93 public void destroy() {
94 MainApplication.removeMapFrameListener(this);
95 super.destroy();
96 }
97
[8913]98 /**
99 * Attempts to save the session.
[8919]100 * @throws UserCancelException when the user has cancelled the save process.
[8913]101 * @since 8913
102 */
[8919]103 public void saveSession() throws UserCancelException {
[4685]104 if (!isEnabled()) {
105 return;
106 }
107
108 SessionSaveAsDialog dlg = new SessionSaveAsDialog();
109 dlg.showDialog();
[8913]110 if (dlg.getValue() != 1) {
[8919]111 throw new UserCancelException();
[8913]112 }
[4685]113
[16438]114 boolean zipRequired = layers.stream().map(l -> exporters.get(l))
115 .anyMatch(ex -> ex != null && ex.requiresZip());
[6069]116
[4685]117 FileFilter joz = new ExtensionFileFilter("joz", "joz", tr("Session file (archive) (*.joz)"));
118 FileFilter jos = new ExtensionFileFilter("jos", "jos", tr("Session file (*.jos)"));
[5438]119
[7578]120 AbstractFileChooser fc;
[5505]121
[4685]122 if (zipRequired) {
[13761]123 fc = createAndOpenFileChooser(false, false, tr("Save Session"), joz, JFileChooser.FILES_ONLY, "lastDirectory");
[4685]124 } else {
[13761]125 fc = createAndOpenFileChooser(false, false, tr("Save Session"), Arrays.asList(jos, joz), jos,
[8509]126 JFileChooser.FILES_ONLY, "lastDirectory");
[4685]127 }
[5438]128
[8913]129 if (fc == null) {
[8919]130 throw new UserCancelException();
[8913]131 }
[4685]132
133 File file = fc.getSelectedFile();
134 String fn = file.getName();
135
136 boolean zip;
137 FileFilter ff = fc.getFileFilter();
[11109]138 if (zipRequired || joz.equals(ff)) {
[4685]139 zip = true;
[6981]140 } else if (jos.equals(ff)) {
[4685]141 zip = false;
142 } else {
[8404]143 if (Utils.hasExtension(fn, "joz")) {
[4685]144 zip = true;
145 } else {
146 zip = false;
147 }
148 }
149 if (fn.indexOf('.') == -1) {
150 file = new File(file.getPath() + (zip ? ".joz" : ".jos"));
[8913]151 if (!SaveActionBase.confirmOverwrite(file)) {
[8919]152 throw new UserCancelException();
[8913]153 }
[4685]154 }
155
[16438]156 // TODO: resolve dependencies for layers excluded by the user
157 List<Layer> layersOut = layers.stream()
158 .filter(layer -> exporters.get(layer) != null && exporters.get(layer).shallExport())
159 .collect(Collectors.toList());
[7509]160
[6271]161 int active = -1;
[12636]162 Layer activeLayer = getLayerManager().getActiveLayer();
[6271]163 if (activeLayer != null) {
164 active = layersOut.indexOf(activeLayer);
165 }
[4685]166
[6271]167 SessionWriter sw = new SessionWriter(layersOut, active, exporters, dependencies, zip);
[4685]168 try {
[18135]169 Notification savingNotification = showSavingNotification(file.getName());
[4685]170 sw.write(file);
[8802]171 SaveActionBase.addToFileOpenHistory(file);
[18135]172 showSavedNotification(savingNotification, file.getName());
[4685]173 } catch (IOException ex) {
[12620]174 Logging.error(ex);
[4685]175 HelpAwareOptionPane.showMessageDialogInEDT(
[14153]176 MainApplication.getMainFrame(),
[11848]177 tr("<html>Could not save session file ''{0}''.<br>Error is:<br>{1}</html>",
178 file.getName(), Utils.escapeReservedCharactersHTML(ex.getMessage())),
[4685]179 tr("IO Error"),
180 JOptionPane.ERROR_MESSAGE,
181 null
182 );
183 }
184 }
185
[6245]186 /**
187 * The "Save Session" dialog
188 */
[4685]189 public class SessionSaveAsDialog extends ExtendedDialog {
190
[6245]191 /**
192 * Constructs a new {@code SessionSaveAsDialog}.
193 */
[4685]194 public SessionSaveAsDialog() {
[14153]195 super(MainApplication.getMainFrame(), tr("Save Session"), tr("Save As"), tr("Cancel"));
[14657]196 configureContextsensitiveHelp("Action/SessionSaveAs", true /* show help button */);
[4685]197 initialize();
[12279]198 setButtonIcons("save_as", "cancel");
[5684]199 setDefaultButton(1);
[4685]200 setRememberWindowGeometry(getClass().getName() + ".geometry",
[14657]201 WindowGeometry.centerInWindow(MainApplication.getMainFrame(), new Dimension(450, 450)));
[4685]202 setContent(build(), false);
203 }
204
[6271]205 /**
206 * Initializes action.
207 */
[6890]208 public final void initialize() {
[12636]209 layers = new ArrayList<>(getLayerManager().getLayers());
[7005]210 exporters = new HashMap<>();
211 dependencies = new MultiMap<>();
[4685]212
[7005]213 Set<Layer> noExporter = new HashSet<>();
[4685]214
215 for (Layer layer : layers) {
[18133]216 SessionLayerExporter exporter = null;
217 try {
218 exporter = SessionWriter.getSessionLayerExporter(layer);
219 } catch (IllegalArgumentException | JosmRuntimeException e) {
220 Logging.error(e);
221 }
[4685]222 if (exporter != null) {
223 exporters.put(layer, exporter);
224 Collection<Layer> deps = exporter.getDependencies();
225 if (deps != null) {
226 dependencies.putAll(layer, deps);
227 } else {
228 dependencies.putVoid(layer);
229 }
230 } else {
231 noExporter.add(layer);
232 exporters.put(layer, null);
233 }
234 }
235
236 int numNoExporter = 0;
[8510]237 WHILE: while (numNoExporter != noExporter.size()) {
[4685]238 numNoExporter = noExporter.size();
239 for (Layer layer : layers) {
240 if (noExporter.contains(layer)) continue;
241 for (Layer depLayer : dependencies.get(layer)) {
242 if (noExporter.contains(depLayer)) {
243 noExporter.add(layer);
244 exporters.put(layer, null);
245 break WHILE;
246 }
247 }
248 }
249 }
250 }
251
[6890]252 protected final Component build() {
[4685]253 JPanel ip = new JPanel(new GridBagLayout());
254 for (Layer layer : layers) {
255 JPanel wrapper = new JPanel(new GridBagLayout());
256 wrapper.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
257 Component exportPanel;
258 SessionLayerExporter exporter = exporters.get(layer);
259 if (exporter == null) {
260 if (!exporters.containsKey(layer)) throw new AssertionError();
261 exportPanel = getDisabledExportPanel(layer);
262 } else {
263 exportPanel = exporter.getExportPanel();
264 }
265 wrapper.add(exportPanel, GBC.std().fill(GBC.HORIZONTAL));
[8510]266 ip.add(wrapper, GBC.eol().fill(GBC.HORIZONTAL).insets(2, 2, 4, 2));
[4685]267 }
[8510]268 ip.add(GBC.glue(0, 1), GBC.eol().fill(GBC.VERTICAL));
[4685]269 JScrollPane sp = new JScrollPane(ip);
270 sp.setBorder(BorderFactory.createEmptyBorder());
[9062]271 JPanel p = new JPanel(new GridBagLayout());
[4685]272 p.add(sp, GBC.eol().fill());
273 final JTabbedPane tabs = new JTabbedPane();
274 tabs.addTab(tr("Layers"), p);
275 return tabs;
276 }
277
[6981]278 protected final Component getDisabledExportPanel(Layer layer) {
[4685]279 JPanel p = new JPanel(new GridBagLayout());
280 JCheckBox include = new JCheckBox();
281 include.setEnabled(false);
[17733]282 JLabel lbl = new JLabel(layer.getName(), layer.getIcon(), SwingConstants.LEADING);
[4685]283 lbl.setToolTipText(tr("No exporter for this layer"));
[8426]284 lbl.setLabelFor(include);
[4685]285 lbl.setEnabled(false);
286 p.add(include, GBC.std());
287 p.add(lbl, GBC.std());
[8510]288 p.add(GBC.glue(1, 0), GBC.std().fill(GBC.HORIZONTAL));
[4685]289 return p;
290 }
291 }
292
[6149]293 @Override
294 protected void updateEnabledState() {
[12630]295 setEnabled(MainApplication.isDisplayingMapView());
[6149]296 }
[9629]297
298 @Override
299 public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
300 updateEnabledState();
[9631]301 }
[4685]302}
Note: See TracBrowser for help on using the repository browser.