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

Last change on this file since 9152 was 9152, checked in by simon04, 8 years ago

fix #12183 - "Registered toolbar action save_as-session overwritten"

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