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 }