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

Last change on this file since 13111 was 12894, checked in by bastiK, 7 years ago

see #15229 - update method name and signature for consistency

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