001 //License: GPL. Copyright 2007 by Immanuel Scholz and others
002 package org.openstreetmap.josm.actions;
003
004 import static org.openstreetmap.josm.tools.I18n.tr;
005
006 import java.awt.event.ActionEvent;
007 import java.io.File;
008 import java.io.IOException;
009 import java.util.Collection;
010 import java.util.LinkedList;
011 import java.util.List;
012
013 import javax.swing.JFileChooser;
014 import javax.swing.JOptionPane;
015 import javax.swing.filechooser.FileFilter;
016
017 import org.openstreetmap.josm.Main;
018 import org.openstreetmap.josm.gui.ExtendedDialog;
019 import org.openstreetmap.josm.gui.layer.Layer;
020 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
021 import org.openstreetmap.josm.io.FileExporter;
022 import org.openstreetmap.josm.tools.Shortcut;
023
024 public abstract class SaveActionBase extends DiskAccessAction {
025 private File file;
026
027 public SaveActionBase(String name, String iconName, String tooltip, Shortcut shortcut) {
028 super(name, iconName, tooltip, shortcut);
029 }
030
031 @Override
032 public void actionPerformed(ActionEvent e) {
033 if (!isEnabled())
034 return;
035 boolean saved = doSave();
036 if (saved) {
037 addToFileOpenHistory();
038 }
039 }
040
041 public boolean doSave() {
042 if (Main.isDisplayingMapView()) {
043 Layer layer = Main.map.mapView.getActiveLayer();
044 if (layer != null && layer.isSavable()) {
045 return doSave(layer);
046 }
047 }
048 return false;
049 }
050
051 public boolean doSave(Layer layer) {
052 if(!layer.checkSaveConditions())
053 return false;
054 file = getFile(layer);
055 return doInternalSave(layer, file);
056 }
057
058 public static boolean doSave(Layer layer, File file) {
059 if(!layer.checkSaveConditions())
060 return false;
061 return doInternalSave(layer, file);
062 }
063
064 private static boolean doInternalSave(Layer layer, File file) {
065 if (file == null)
066 return false;
067
068 try {
069 boolean exported = false;
070 for (FileExporter exporter : ExtensionFileFilter.exporters) {
071 if (exporter.acceptFile(file, layer)) {
072 exporter.exportData(file, layer);
073 exported = true;
074 break;
075 }
076 }
077 if (!exported) {
078 JOptionPane.showMessageDialog(Main.parent, tr("No Exporter found! Nothing saved."), tr("Warning"),
079 JOptionPane.WARNING_MESSAGE);
080 return false;
081 }
082 layer.setName(file.getName());
083 layer.setAssociatedFile(file);
084 if (layer instanceof OsmDataLayer) {
085 ((OsmDataLayer) layer).onPostSaveToFile();
086 }
087 Main.parent.repaint();
088 } catch (IOException e) {
089 e.printStackTrace();
090 return false;
091 }
092 return true;
093 }
094
095 protected abstract File getFile(Layer layer);
096
097 /**
098 * Refreshes the enabled state
099 *
100 */
101 @Override
102 protected void updateEnabledState() {
103 if (Main.applet) {
104 setEnabled(false);
105 return;
106 }
107 boolean check = Main.isDisplayingMapView()
108 && Main.map.mapView.getActiveLayer() != null;
109 if(!check) {
110 setEnabled(false);
111 return;
112 }
113 Layer layer = Main.map.mapView.getActiveLayer();
114 setEnabled(layer != null && layer.isSavable());
115 }
116
117 /**
118 * Creates a new "Save" dialog for a single {@link ExtensionFileFilter} and makes it visible.<br/>
119 * When the user has chosen a file, checks the file extension, and confirms overwrite if needed.
120 *
121 * @param title The dialog title
122 * @param filter The dialog file filter
123 * @return The output {@code File}
124 * @since 5456
125 * @see DiskAccessAction#createAndOpenFileChooser(boolean, boolean, String, FileFilter, int, String)
126 */
127 public static File createAndOpenSaveFileChooser(String title, ExtensionFileFilter filter) {
128 JFileChooser fc = createAndOpenFileChooser(false, false, title, filter, JFileChooser.FILES_ONLY, null);
129 return checkFileAndConfirmOverWrite(fc, filter.getDefaultExtension());
130 }
131
132 /**
133 * Creates a new "Save" dialog for a given file extension and makes it visible.<br/>
134 * When the user has chosen a file, checks the file extension, and confirms overwrite if needed.
135 *
136 * @param title The dialog title
137 * @param extension The file extension
138 * @return The output {@code File}
139 * @see DiskAccessAction#createAndOpenFileChooser(boolean, boolean, String, String)
140 */
141 public static File createAndOpenSaveFileChooser(String title, String extension) {
142 JFileChooser fc = createAndOpenFileChooser(false, false, title, extension);
143 return checkFileAndConfirmOverWrite(fc, extension);
144 }
145
146 private static File checkFileAndConfirmOverWrite(JFileChooser fc, String extension) {
147 if (fc == null) return null;
148 File file = fc.getSelectedFile();
149 String fn = file.getPath();
150 if (fn.indexOf('.') == -1)
151 {
152 FileFilter ff = fc.getFileFilter();
153 if (ff instanceof ExtensionFileFilter) {
154 fn += "." + ((ExtensionFileFilter)ff).getDefaultExtension();
155 } else if (extension != null) {
156 fn += "." + extension;
157 }
158 file = new File(fn);
159 if (!confirmOverwrite(file))
160 return null;
161 }
162 return file;
163 }
164
165 public static boolean confirmOverwrite(File file) {
166 if (file == null || (file.exists())) {
167 ExtendedDialog dialog = new ExtendedDialog(
168 Main.parent,
169 tr("Overwrite"),
170 new String[] {tr("Overwrite"), tr("Cancel")}
171 );
172 dialog.setContent(tr("File exists. Overwrite?"));
173 dialog.setButtonIcons(new String[] {"save_as.png", "cancel.png"});
174 dialog.showDialog();
175 return (dialog.getValue() == 1);
176 }
177 return true;
178 }
179
180 protected void addToFileOpenHistory() {
181 String filepath;
182 try {
183 filepath = file.getCanonicalPath();
184 } catch (IOException ign) {
185 return;
186 }
187
188 int maxsize = Math.max(0, Main.pref.getInteger("file-open.history.max-size", 15));
189 Collection<String> oldHistory = Main.pref.getCollection("file-open.history");
190 List<String> history = new LinkedList<String>(oldHistory);
191 history.remove(filepath);
192 history.add(0, filepath);
193 Main.pref.putCollectionBounded("file-open.history", maxsize, history);
194 }
195 }