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

Last change on this file since 7859 was 7578, checked in by Don-vip, 10 years ago

fix #10024 - Add an option in Preferences/Look-and-Feel to use native file-choosing dialogs.
They look nicer but they do not support file filters, so we cannot use them (yet) as default.
Based on patch by Lesath and code review by simon04.
The native dialogs are not used if selection mode is not supported ("files and directories" on all platforms, "directories" on systems other than OS X)

  • Property svn:eol-style set to native
File size: 8.9 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.WindowGeometry;
44
45/**
46 * Saves a JOSM session
47 * @since 4685
48 */
49public class SessionSaveAsAction extends DiskAccessAction {
50
51 private List<Layer> layers;
52 private Map<Layer, SessionLayerExporter> exporters;
53 private MultiMap<Layer, Layer> dependencies;
54
55 /**
56 * Constructs a new {@code SessionSaveAsAction}.
57 */
58 public SessionSaveAsAction() {
59 super(tr("Save Session As..."), "save_as", tr("Save the current session to a new file."), null, true, "save_as-session", true);
60 putValue("help", ht("/Action/SessionSaveAs"));
61 }
62
63 @Override
64 public void actionPerformed(ActionEvent e) {
65 if (!isEnabled()) {
66 return;
67 }
68
69 SessionSaveAsDialog dlg = new SessionSaveAsDialog();
70 dlg.showDialog();
71 if (dlg.getValue() != 1) return;
72
73 boolean zipRequired = false;
74 for (Layer l : layers) {
75 SessionLayerExporter ex = exporters.get(l);
76 if (ex != null && ex.requiresZip()) {
77 zipRequired = true;
78 break;
79 }
80 }
81
82 FileFilter joz = new ExtensionFileFilter("joz", "joz", tr("Session file (archive) (*.joz)"));
83 FileFilter jos = new ExtensionFileFilter("jos", "jos", tr("Session file (*.jos)"));
84
85 AbstractFileChooser fc;
86
87 if (zipRequired) {
88 fc = createAndOpenFileChooser(false, false, tr("Save session"), joz, JFileChooser.FILES_ONLY, "lastDirectory");
89 } else {
90 fc = createAndOpenFileChooser(false, false, tr("Save session"), Arrays.asList(new FileFilter[]{jos, joz}), jos, JFileChooser.FILES_ONLY, "lastDirectory");
91 }
92
93 if (fc == null)
94 return;
95
96 File file = fc.getSelectedFile();
97 String fn = file.getName();
98
99 boolean zip;
100 FileFilter ff = fc.getFileFilter();
101 if (zipRequired) {
102 zip = true;
103 } else if (joz.equals(ff)) {
104 zip = true;
105 } else if (jos.equals(ff)) {
106 zip = false;
107 } else {
108 if (fn.toLowerCase().endsWith(".joz")) {
109 zip = true;
110 } else {
111 zip = false;
112 }
113 }
114 if (fn.indexOf('.') == -1) {
115 file = new File(file.getPath() + (zip ? ".joz" : ".jos"));
116 if (!SaveActionBase.confirmOverwrite(file))
117 return;
118 }
119
120 List<Layer> layersOut = new ArrayList<>();
121 for (Layer layer : layers) {
122 if (exporters.get(layer) == null || !exporters.get(layer).shallExport()) continue;
123 // TODO: resolve dependencies for layers excluded by the user
124 layersOut.add(layer);
125 }
126
127 int active = -1;
128 Layer activeLayer = Main.map.mapView.getActiveLayer();
129 if (activeLayer != null) {
130 active = layersOut.indexOf(activeLayer);
131 }
132
133 SessionWriter sw = new SessionWriter(layersOut, active, exporters, dependencies, zip);
134 try {
135 sw.write(file);
136 } catch (IOException ex) {
137 Main.error(ex);
138 HelpAwareOptionPane.showMessageDialogInEDT(
139 Main.parent,
140 tr("<html>Could not save session file ''{0}''.<br>Error is:<br>{1}</html>", file.getName(), ex.getMessage()),
141 tr("IO Error"),
142 JOptionPane.ERROR_MESSAGE,
143 null
144 );
145 }
146 }
147
148 /**
149 * The "Save Session" dialog
150 */
151 public class SessionSaveAsDialog extends ExtendedDialog {
152
153 /**
154 * Constructs a new {@code SessionSaveAsDialog}.
155 */
156 public SessionSaveAsDialog() {
157 super(Main.parent, tr("Save Session"), new String[] {tr("Save As"), tr("Cancel")});
158 initialize();
159 setButtonIcons(new String[] {"save_as", "cancel"});
160 setDefaultButton(1);
161 setRememberWindowGeometry(getClass().getName() + ".geometry",
162 WindowGeometry.centerInWindow(Main.parent, new Dimension(350, 450)));
163 setContent(build(), false);
164 }
165
166 /**
167 * Initializes action.
168 */
169 public final void initialize() {
170 layers = new ArrayList<>(Main.map.mapView.getAllLayersAsList());
171 exporters = new HashMap<>();
172 dependencies = new MultiMap<>();
173
174 Set<Layer> noExporter = new HashSet<>();
175
176 for (Layer layer : layers) {
177 SessionLayerExporter exporter = SessionWriter.getSessionLayerExporter(layer);
178 if (exporter != null) {
179 exporters.put(layer, exporter);
180 Collection<Layer> deps = exporter.getDependencies();
181 if (deps != null) {
182 dependencies.putAll(layer, deps);
183 } else {
184 dependencies.putVoid(layer);
185 }
186 } else {
187 noExporter.add(layer);
188 exporters.put(layer, null);
189 }
190 }
191
192 int numNoExporter = 0;
193 WHILE:while (numNoExporter != noExporter.size()) {
194 numNoExporter = noExporter.size();
195 for (Layer layer : layers) {
196 if (noExporter.contains(layer)) continue;
197 for (Layer depLayer : dependencies.get(layer)) {
198 if (noExporter.contains(depLayer)) {
199 noExporter.add(layer);
200 exporters.put(layer, null);
201 break WHILE;
202 }
203 }
204 }
205 }
206 }
207
208 protected final Component build() {
209 JPanel p = new JPanel(new GridBagLayout());
210 JPanel ip = new JPanel(new GridBagLayout());
211 for (Layer layer : layers) {
212 JPanel wrapper = new JPanel(new GridBagLayout());
213 wrapper.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
214 Component exportPanel;
215 SessionLayerExporter exporter = exporters.get(layer);
216 if (exporter == null) {
217 if (!exporters.containsKey(layer)) throw new AssertionError();
218 exportPanel = getDisabledExportPanel(layer);
219 } else {
220 exportPanel = exporter.getExportPanel();
221 }
222 wrapper.add(exportPanel, GBC.std().fill(GBC.HORIZONTAL));
223 ip.add(wrapper, GBC.eol().fill(GBC.HORIZONTAL).insets(2,2,4,2));
224 }
225 ip.add(GBC.glue(0,1), GBC.eol().fill(GBC.VERTICAL));
226 JScrollPane sp = new JScrollPane(ip);
227 sp.setBorder(BorderFactory.createEmptyBorder());
228 p.add(sp, GBC.eol().fill());
229 final JTabbedPane tabs = new JTabbedPane();
230 tabs.addTab(tr("Layers"), p);
231 return tabs;
232 }
233
234 protected final Component getDisabledExportPanel(Layer layer) {
235 JPanel p = new JPanel(new GridBagLayout());
236 JCheckBox include = new JCheckBox();
237 include.setEnabled(false);
238 JLabel lbl = new JLabel(layer.getName(), layer.getIcon(), SwingConstants.LEFT);
239 lbl.setToolTipText(tr("No exporter for this layer"));
240 lbl.setEnabled(false);
241 p.add(include, GBC.std());
242 p.add(lbl, GBC.std());
243 p.add(GBC.glue(1,0), GBC.std().fill(GBC.HORIZONTAL));
244 return p;
245 }
246 }
247
248 @Override
249 protected void updateEnabledState() {
250 setEnabled(Main.isDisplayingMapView());
251 }
252}
Note: See TracBrowser for help on using the repository browser.