source: josm/trunk/src/org/openstreetmap/josm/actions/SaveActionBase.java@ 9707

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

CheckStyle

  • Property svn:eol-style set to native
File size: 8.8 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.event.ActionEvent;
7import java.io.File;
8import java.io.IOException;
9import java.util.Collection;
10import java.util.LinkedList;
11import java.util.List;
12
13import javax.swing.JFileChooser;
14import javax.swing.JOptionPane;
15import javax.swing.filechooser.FileFilter;
16
17import org.openstreetmap.josm.Main;
18import org.openstreetmap.josm.gui.ExtendedDialog;
19import org.openstreetmap.josm.gui.layer.Layer;
20import org.openstreetmap.josm.gui.layer.OsmDataLayer;
21import org.openstreetmap.josm.gui.widgets.AbstractFileChooser;
22import org.openstreetmap.josm.io.FileExporter;
23import org.openstreetmap.josm.tools.Shortcut;
24
25/**
26 * Abstract superclass of save actions.
27 * @since 290
28 */
29public abstract class SaveActionBase extends DiskAccessAction {
30 private File file;
31
32 /**
33 * Constructs a new {@code SaveActionBase}.
34 * @param name The action's text as displayed on the menu (if it is added to a menu)
35 * @param iconName The filename of the icon to use
36 * @param tooltip A longer description of the action that will be displayed in the tooltip
37 * @param shortcut A ready-created shortcut object or {@code null} if you don't want a shortcut
38 */
39 public SaveActionBase(String name, String iconName, String tooltip, Shortcut shortcut) {
40 super(name, iconName, tooltip, shortcut);
41 }
42
43 @Override
44 public void actionPerformed(ActionEvent e) {
45 if (!isEnabled())
46 return;
47 doSave();
48 }
49
50 /**
51 * Saves the active layer.
52 * @return {@code true} if the save operation succeeds
53 */
54 public boolean doSave() {
55 if (Main.isDisplayingMapView()) {
56 Layer layer = Main.map.mapView.getActiveLayer();
57 if (layer != null && layer.isSavable()) {
58 return doSave(layer);
59 }
60 }
61 return false;
62 }
63
64 /**
65 * Saves the given layer.
66 * @param layer layer to save
67 * @return {@code true} if the save operation succeeds
68 */
69 public boolean doSave(Layer layer) {
70 if (!layer.checkSaveConditions())
71 return false;
72 file = getFile(layer);
73 return doInternalSave(layer, file);
74 }
75
76 /**
77 * Saves a layer to a given file.
78 * @param layer The layer to save
79 * @param file The destination file
80 * @param checkSaveConditions if {@code true}, checks preconditions before saving. Set it to {@code false} to skip it
81 * if preconditions have already been checked (as this check can prompt UI dialog in EDT it may be best in some cases
82 * to do it earlier).
83 * @return {@code true} if the layer has been successfully saved, {@code false} otherwise
84 * @since 7204
85 */
86 public static boolean doSave(Layer layer, File file, boolean checkSaveConditions) {
87 if (checkSaveConditions && !layer.checkSaveConditions())
88 return false;
89 return doInternalSave(layer, file);
90 }
91
92 private static boolean doInternalSave(Layer layer, File file) {
93 if (file == null)
94 return false;
95
96 try {
97 boolean exported = false;
98 boolean canceled = false;
99 for (FileExporter exporter : ExtensionFileFilter.exporters) {
100 if (exporter.acceptFile(file, layer)) {
101 exporter.exportData(file, layer);
102 exported = true;
103 canceled = exporter.isCanceled();
104 break;
105 }
106 }
107 if (!exported) {
108 JOptionPane.showMessageDialog(Main.parent, tr("No Exporter found! Nothing saved."), tr("Warning"),
109 JOptionPane.WARNING_MESSAGE);
110 return false;
111 } else if (canceled) {
112 return false;
113 }
114 if (!layer.isRenamed()) {
115 layer.setName(file.getName());
116 }
117 layer.setAssociatedFile(file);
118 if (layer instanceof OsmDataLayer) {
119 ((OsmDataLayer) layer).onPostSaveToFile();
120 }
121 Main.parent.repaint();
122 } catch (IOException e) {
123 Main.error(e);
124 return false;
125 }
126 addToFileOpenHistory(file);
127 return true;
128 }
129
130 protected abstract File getFile(Layer layer);
131
132 /**
133 * Refreshes the enabled state
134 *
135 */
136 @Override
137 protected void updateEnabledState() {
138 boolean check = Main.isDisplayingMapView()
139 && Main.map.mapView.getActiveLayer() != null;
140 if (!check) {
141 setEnabled(false);
142 return;
143 }
144 Layer layer = Main.map.mapView.getActiveLayer();
145 setEnabled(layer != null && layer.isSavable());
146 }
147
148 /**
149 * Creates a new "Save" dialog for a single {@link ExtensionFileFilter} and makes it visible.<br>
150 * When the user has chosen a file, checks the file extension, and confirms overwrite if needed.
151 *
152 * @param title The dialog title
153 * @param filter The dialog file filter
154 * @return The output {@code File}
155 * @see DiskAccessAction#createAndOpenFileChooser(boolean, boolean, String, FileFilter, int, String)
156 * @since 5456
157 */
158 public static File createAndOpenSaveFileChooser(String title, ExtensionFileFilter filter) {
159 AbstractFileChooser fc = createAndOpenFileChooser(false, false, title, filter, JFileChooser.FILES_ONLY, null);
160 return checkFileAndConfirmOverWrite(fc, filter.getDefaultExtension());
161 }
162
163 /**
164 * Creates a new "Save" dialog for a given file extension and makes it visible.<br>
165 * When the user has chosen a file, checks the file extension, and confirms overwrite if needed.
166 *
167 * @param title The dialog title
168 * @param extension The file extension
169 * @return The output {@code File}
170 * @see DiskAccessAction#createAndOpenFileChooser(boolean, boolean, String, String)
171 */
172 public static File createAndOpenSaveFileChooser(String title, String extension) {
173 AbstractFileChooser fc = createAndOpenFileChooser(false, false, title, extension);
174 return checkFileAndConfirmOverWrite(fc, extension);
175 }
176
177 /**
178 * Checks if selected filename has the given extension. If not, adds the extension and asks for overwrite if filename exists.
179 *
180 * @param fc FileChooser where file was already selected
181 * @param extension file extension
182 * @return the {@code File} or {@code null} if the user cancelled the dialog.
183 */
184 public static File checkFileAndConfirmOverWrite(AbstractFileChooser fc, String extension) {
185 if (fc == null)
186 return null;
187 File file = fc.getSelectedFile();
188
189 FileFilter ff = fc.getFileFilter();
190 if (!ff.accept(file)) {
191 // Extension of another filefilter given ?
192 for (FileFilter cff : fc.getChoosableFileFilters()) {
193 if (cff.accept(file)) {
194 fc.setFileFilter(cff);
195 return file;
196 }
197 }
198 // No filefilter accepts current filename, add default extension
199 String fn = file.getPath();
200 if (extension != null) {
201 fn += '.' + extension;
202 } else if (ff instanceof ExtensionFileFilter) {
203 fn += '.' + ((ExtensionFileFilter) ff).getDefaultExtension();
204 }
205 file = new File(fn);
206 if (!fc.getSelectedFile().exists() && !confirmOverwrite(file))
207 return null;
208 }
209 return file;
210 }
211
212 /**
213 * Asks user to confirm overwiting a file.
214 * @param file file to overwrite
215 * @return {@code true} if the file can be written
216 */
217 public static boolean confirmOverwrite(File file) {
218 if (file == null || file.exists()) {
219 ExtendedDialog dialog = new ExtendedDialog(
220 Main.parent,
221 tr("Overwrite"),
222 new String[] {tr("Overwrite"), tr("Cancel")}
223 );
224 dialog.setContent(tr("File exists. Overwrite?"));
225 dialog.setButtonIcons(new String[] {"save_as", "cancel"});
226 dialog.showDialog();
227 return dialog.getValue() == 1;
228 }
229 return true;
230 }
231
232 static void addToFileOpenHistory(File file) {
233 final String filepath;
234 try {
235 filepath = file.getCanonicalPath();
236 } catch (IOException ign) {
237 Main.warn(ign);
238 return;
239 }
240
241 int maxsize = Math.max(0, Main.pref.getInteger("file-open.history.max-size", 15));
242 Collection<String> oldHistory = Main.pref.getCollection("file-open.history");
243 List<String> history = new LinkedList<>(oldHistory);
244 history.remove(filepath);
245 history.add(0, filepath);
246 Main.pref.putCollectionBounded("file-open.history", maxsize, history);
247 }
248}
Note: See TracBrowser for help on using the repository browser.