[319] | 1 | //License: GPL. Copyright 2007 by Immanuel Scholz and others
|
---|
[290] | 2 | package org.openstreetmap.josm.actions;
|
---|
| 3 |
|
---|
| 4 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
| 5 |
|
---|
| 6 | import java.awt.event.ActionEvent;
|
---|
| 7 | import java.io.File;
|
---|
| 8 | import java.io.IOException;
|
---|
| 9 |
|
---|
[1949] | 10 | import javax.swing.JFileChooser;
|
---|
[290] | 11 | import javax.swing.JOptionPane;
|
---|
[1949] | 12 | import javax.swing.filechooser.FileFilter;
|
---|
[290] | 13 |
|
---|
| 14 | import org.openstreetmap.josm.Main;
|
---|
[1750] | 15 | import org.openstreetmap.josm.data.conflict.ConflictCollection;
|
---|
[290] | 16 | import org.openstreetmap.josm.data.osm.OsmPrimitive;
|
---|
[1397] | 17 | import org.openstreetmap.josm.gui.ExtendedDialog;
|
---|
[1523] | 18 | import org.openstreetmap.josm.gui.layer.GpxLayer;
|
---|
| 19 | import org.openstreetmap.josm.gui.layer.Layer;
|
---|
[290] | 20 | import org.openstreetmap.josm.gui.layer.OsmDataLayer;
|
---|
[1949] | 21 | import org.openstreetmap.josm.io.FileExporter;
|
---|
[1084] | 22 | import org.openstreetmap.josm.tools.Shortcut;
|
---|
[290] | 23 |
|
---|
[1820] | 24 | public abstract class SaveActionBase extends DiskAccessAction {
|
---|
[290] | 25 |
|
---|
[1808] | 26 | public SaveActionBase(String name, String iconName, String tooltip, Shortcut shortcut) {
|
---|
[1169] | 27 | super(name, iconName, tooltip, shortcut);
|
---|
| 28 | }
|
---|
[1023] | 29 |
|
---|
[1169] | 30 | public void actionPerformed(ActionEvent e) {
|
---|
[1808] | 31 | if (!isEnabled())
|
---|
| 32 | return;
|
---|
[1373] | 33 | doSave();
|
---|
| 34 | }
|
---|
| 35 |
|
---|
[1808] | 36 | public boolean doSave() {
|
---|
| 37 | Layer layer = null;
|
---|
[2343] | 38 | if (Main.isDisplayingMapView() && (Main.map.mapView.getActiveLayer() instanceof OsmDataLayer
|
---|
[1750] | 39 | || Main.map.mapView.getActiveLayer() instanceof GpxLayer)) {
|
---|
[1169] | 40 | layer = Main.map.mapView.getActiveLayer();
|
---|
[1750] | 41 | }
|
---|
[1808] | 42 | if (layer == null)
|
---|
| 43 | return false;
|
---|
| 44 | return doSave(layer);
|
---|
| 45 | }
|
---|
[290] | 46 |
|
---|
[1808] | 47 | public boolean doSave(Layer layer) {
|
---|
| 48 | if (layer == null)
|
---|
| 49 | return false;
|
---|
| 50 | if ( !(layer instanceof OsmDataLayer) && !(layer instanceof GpxLayer))
|
---|
| 51 | return false;
|
---|
[1169] | 52 | if (!checkSaveConditions(layer))
|
---|
[1373] | 53 | return false;
|
---|
[290] | 54 |
|
---|
[1169] | 55 | File file = getFile(layer);
|
---|
| 56 | if (file == null)
|
---|
[1373] | 57 | return false;
|
---|
[290] | 58 |
|
---|
[1949] | 59 | try {
|
---|
| 60 | boolean exported = false;
|
---|
| 61 | for (FileExporter exporter : ExtensionFileFilter.exporters) {
|
---|
| 62 | if (exporter.acceptFile(file, layer)) {
|
---|
| 63 | exporter.exportData(file, layer);
|
---|
| 64 | exported = true;
|
---|
| 65 | }
|
---|
| 66 | }
|
---|
| 67 | if (!exported) {
|
---|
[2017] | 68 | JOptionPane.showMessageDialog(Main.parent, tr("No Exporter found! Nothing saved."), tr("Warning"),
|
---|
[1949] | 69 | JOptionPane.WARNING_MESSAGE);
|
---|
| 70 | return false;
|
---|
| 71 | }
|
---|
| 72 | layer.setName(file.getName());
|
---|
| 73 | layer.setAssociatedFile(file);
|
---|
[2025] | 74 | if (layer instanceof OsmDataLayer) {
|
---|
| 75 | ((OsmDataLayer) layer).onPostSaveToFile();
|
---|
| 76 | }
|
---|
[1949] | 77 | Main.parent.repaint();
|
---|
| 78 | } catch (IOException e) {
|
---|
| 79 | e.printStackTrace();
|
---|
| 80 | return false;
|
---|
| 81 | }
|
---|
[1373] | 82 | return true;
|
---|
[1169] | 83 | }
|
---|
[319] | 84 |
|
---|
[1169] | 85 | protected abstract File getFile(Layer layer);
|
---|
[290] | 86 |
|
---|
[1169] | 87 | /**
|
---|
| 88 | * Checks whether it is ok to launch a save (whether we have data,
|
---|
| 89 | * there is no conflict etc.)
|
---|
| 90 | * @return <code>true</code>, if it is safe to save.
|
---|
| 91 | */
|
---|
| 92 | public boolean checkSaveConditions(Layer layer) {
|
---|
[2070] | 93 | if (layer instanceof OsmDataLayer && isDataSetEmpty((OsmDataLayer)layer)) {
|
---|
| 94 | ExtendedDialog dialog = new ExtendedDialog(
|
---|
| 95 | Main.parent,
|
---|
| 96 | tr("Empty document"),
|
---|
| 97 | new String[] {tr("Save anyway"), tr("Cancel")}
|
---|
| 98 | );
|
---|
| 99 | dialog.setContent(tr("The document contains no data."));
|
---|
| 100 | dialog.setButtonIcons(new String[] {"save.png", "cancel.png"});
|
---|
| 101 | dialog.showDialog();
|
---|
| 102 | if (dialog.getValue() != 1) return false;
|
---|
| 103 | }
|
---|
| 104 |
|
---|
[1750] | 105 | if (layer instanceof GpxLayer && ((GpxLayer)layer).data == null)
|
---|
[1169] | 106 | return false;
|
---|
[1750] | 107 | if (layer instanceof OsmDataLayer) {
|
---|
| 108 | ConflictCollection conflicts = ((OsmDataLayer)layer).getConflicts();
|
---|
| 109 | if (conflicts != null && !conflicts.isEmpty()) {
|
---|
[2070] | 110 | ExtendedDialog dialog = new ExtendedDialog(
|
---|
| 111 | Main.parent,
|
---|
[1750] | 112 | tr("Conflicts"),
|
---|
[2070] | 113 | new String[] {tr("Reject Conflicts and Save"), tr("Cancel")}
|
---|
| 114 | );
|
---|
| 115 | dialog.setContent(tr("There are unresolved conflicts. Conflicts will not be saved and handled as if you rejected all. Continue?"));
|
---|
| 116 | dialog.setButtonIcons(new String[] {"save.png", "cancel.png"});
|
---|
| 117 | dialog.showDialog();
|
---|
| 118 | if (dialog.getValue() != 1) return false;
|
---|
[1750] | 119 | }
|
---|
[1169] | 120 | }
|
---|
| 121 | return true;
|
---|
| 122 | }
|
---|
[290] | 123 |
|
---|
[1169] | 124 | public static File openFileDialog(Layer layer) {
|
---|
[1646] | 125 | if (layer instanceof OsmDataLayer)
|
---|
[2029] | 126 | return createAndOpenSaveFileChooser(tr("Save OSM file"), "osm");
|
---|
[1646] | 127 | else if (layer instanceof GpxLayer)
|
---|
[2029] | 128 | return createAndOpenSaveFileChooser(tr("Save GPX file"), "gpx");
|
---|
| 129 | return createAndOpenSaveFileChooser(tr("Save Layer"), "lay");
|
---|
[1169] | 130 | }
|
---|
[319] | 131 |
|
---|
[1169] | 132 | /**
|
---|
| 133 | * Check the data set if it would be empty on save. It is empty, if it contains
|
---|
| 134 | * no objects (after all objects that are created and deleted without being
|
---|
[1676] | 135 | * transferred to the server have been removed).
|
---|
[1169] | 136 | *
|
---|
| 137 | * @return <code>true</code>, if a save result in an empty data set.
|
---|
| 138 | */
|
---|
| 139 | private boolean isDataSetEmpty(OsmDataLayer layer) {
|
---|
| 140 | for (OsmPrimitive osm : layer.data.allNonDeletedPrimitives())
|
---|
[2273] | 141 | if (!osm.isDeleted() || !osm.isNew())
|
---|
[1169] | 142 | return false;
|
---|
| 143 | return true;
|
---|
| 144 | }
|
---|
[1808] | 145 |
|
---|
| 146 | /**
|
---|
| 147 | * Refreshes the enabled state
|
---|
[1949] | 148 | *
|
---|
[1808] | 149 | */
|
---|
[1820] | 150 | @Override
|
---|
| 151 | protected void updateEnabledState() {
|
---|
[1879] | 152 | if (Main.applet) {
|
---|
| 153 | setEnabled(false);
|
---|
| 154 | return;
|
---|
| 155 | }
|
---|
[1820] | 156 | boolean check = Main.map != null
|
---|
[1808] | 157 | && Main.map.mapView !=null
|
---|
| 158 | && Main.map.mapView.getActiveLayer() != null;
|
---|
| 159 | if(!check) {
|
---|
| 160 | setEnabled(false);
|
---|
| 161 | return;
|
---|
| 162 | }
|
---|
| 163 | Layer layer = Main.map.mapView.getActiveLayer();
|
---|
| 164 | setEnabled(layer instanceof OsmDataLayer || layer instanceof GpxLayer);
|
---|
| 165 | }
|
---|
[1949] | 166 |
|
---|
| 167 | public static File createAndOpenSaveFileChooser(String title, String extension) {
|
---|
| 168 | String curDir = Main.pref.get("lastDirectory");
|
---|
| 169 | if (curDir.equals("")) {
|
---|
| 170 | curDir = ".";
|
---|
| 171 | }
|
---|
| 172 | JFileChooser fc = new JFileChooser(new File(curDir));
|
---|
| 173 | if (title != null) {
|
---|
| 174 | fc.setDialogTitle(title);
|
---|
| 175 | }
|
---|
| 176 |
|
---|
| 177 | fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
---|
| 178 | fc.setMultiSelectionEnabled(false);
|
---|
| 179 | fc.setAcceptAllFileFilterUsed(false);
|
---|
[2029] | 180 | ExtensionFileFilter.applyChoosableExportFileFilters(fc, extension);
|
---|
[1949] | 181 | int answer = fc.showSaveDialog(Main.parent);
|
---|
| 182 | if (answer != JFileChooser.APPROVE_OPTION)
|
---|
| 183 | return null;
|
---|
| 184 |
|
---|
| 185 | if (!fc.getCurrentDirectory().getAbsolutePath().equals(curDir)) {
|
---|
| 186 | Main.pref.put("lastDirectory", fc.getCurrentDirectory().getAbsolutePath());
|
---|
| 187 | }
|
---|
| 188 |
|
---|
| 189 | File file = fc.getSelectedFile();
|
---|
| 190 | if(extension != null){
|
---|
| 191 | String fn = file.getPath();
|
---|
| 192 | if(fn.indexOf('.') == -1)
|
---|
| 193 | {
|
---|
| 194 | FileFilter ff = fc.getFileFilter();
|
---|
| 195 | if (ff instanceof ExtensionFileFilter) {
|
---|
[2029] | 196 | fn += "." + ((ExtensionFileFilter)ff).getDefaultExtension();
|
---|
[1949] | 197 | } else {
|
---|
| 198 | fn += extension;
|
---|
| 199 | }
|
---|
| 200 | file = new File(fn);
|
---|
| 201 | }
|
---|
| 202 | }
|
---|
[2070] | 203 | if(file == null || (file.exists())) {
|
---|
| 204 | ExtendedDialog dialog = new ExtendedDialog(
|
---|
| 205 | Main.parent,
|
---|
| 206 | tr("Overwrite"),
|
---|
| 207 | new String[] {tr("Overwrite"), tr("Cancel")}
|
---|
| 208 | );
|
---|
| 209 | dialog.setContent(tr("File exists. Overwrite?"));
|
---|
| 210 | dialog.setButtonIcons(new String[] {"save_as.png", "cancel.png"});
|
---|
| 211 | dialog.showDialog();
|
---|
| 212 | if (dialog.getValue() != 1) return null;
|
---|
| 213 | }
|
---|
[1949] | 214 | return file;
|
---|
| 215 | }
|
---|
[290] | 216 | }
|
---|