import javax.swing.table.TableModel;
import tim.prune.App;
-import tim.prune.Config;
import tim.prune.I18nManager;
import tim.prune.UpdateMessageBroker;
-import tim.prune.data.Altitude;
+import tim.prune.config.Config;
import tim.prune.data.Coordinate;
import tim.prune.data.DataPoint;
import tim.prune.data.Field;
import tim.prune.data.FieldList;
+import tim.prune.data.RecentFile;
import tim.prune.data.Timestamp;
import tim.prune.data.Track;
+import tim.prune.data.Unit;
+import tim.prune.data.UnitSetLibrary;
import tim.prune.load.GenericFileFilter;
import tim.prune.load.OneCharDocument;
/**
* Class to manage the saving of track data
- * into a user-specified file
+ * as text into a user-specified file
*/
public class FileSaver
{
private App _app = null;
private JFrame _parentFrame = null;
- private Track _track = null;
private JDialog _dialog = null;
private JFileChooser _fileChooser = null;
private JPanel _cards = null;
private JRadioButton[] _delimiterRadios = null;
private JTextField _otherDelimiterText = null;
private JCheckBox _headerRowCheckbox = null;
+ private PointTypeSelector _pointTypeSelector = null;
private JRadioButton[] _coordUnitsRadios = null;
private JRadioButton[] _altitudeUnitsRadios = null;
private JRadioButton[] _timestampUnitsRadios = null;
+
private static final int[] FORMAT_COORDS = {Coordinate.FORMAT_NONE, Coordinate.FORMAT_DEG_MIN_SEC,
Coordinate.FORMAT_DEG_MIN, Coordinate.FORMAT_DEG};
- private static final int[] FORMAT_ALTS = {Altitude.FORMAT_NONE, Altitude.FORMAT_METRES, Altitude.FORMAT_FEET};
+ private static final Unit[] UNIT_ALTS = {null, UnitSetLibrary.UNITS_METRES, UnitSetLibrary.UNITS_FEET};
private static final int[] FORMAT_TIMES = {Timestamp.FORMAT_ORIGINAL, Timestamp.FORMAT_LOCALE, Timestamp.FORMAT_ISO_8601};
* Constructor
* @param inApp application object to inform of success
* @param inParentFrame parent frame
- * @param inTrack track object to save
*/
- public FileSaver(App inApp, JFrame inParentFrame, Track inTrack)
+ public FileSaver(App inApp, JFrame inParentFrame)
{
_app = inApp;
_parentFrame = inParentFrame;
- _track = inTrack;
}
_dialog.pack();
}
// Check field list
- FieldList fieldList = _track.getFieldList();
+ Track track = _app.getTrackInfo().getTrack();
+ FieldList fieldList = track.getFieldList();
int numFields = fieldList.getNumFields();
_model = new FieldSelectionTableModel(numFields);
for (int i=0; i<numFields; i++)
{
Field field = fieldList.getField(i);
- FieldInfo info = new FieldInfo(field, _track.hasData(field));
+ FieldInfo info = new FieldInfo(field, track.hasData(field));
_model.addFieldInfo(info, i);
}
// Initialise dialog and show it
initDialog(_model, inDefaultDelimiter);
- _dialog.show();
+ _dialog.setVisible(true);
}
firstCard.add(Box.createRigidArea(new Dimension(0,10)));
_headerRowCheckbox = new JCheckBox(I18nManager.getText("dialog.save.headerrow"), true);
firstCard.add(_headerRowCheckbox);
-
_cards.add(firstCard, "card1");
+ // Second card
JPanel secondCard = new JPanel();
secondCard.setLayout(new BorderLayout());
JPanel secondCardHolder = new JPanel();
secondCardHolder.setLayout(new BoxLayout(secondCardHolder, BoxLayout.Y_AXIS));
+ // point type selector
+ secondCardHolder.add(Box.createRigidArea(new Dimension(0,10)));
+ _pointTypeSelector = new PointTypeSelector();
+ _pointTypeSelector.setAlignmentX(JLabel.LEFT_ALIGNMENT);
+ secondCardHolder.add(_pointTypeSelector);
JLabel coordLabel = new JLabel(I18nManager.getText("dialog.save.coordinateunits"));
coordLabel.setAlignmentX(JLabel.LEFT_ALIGNMENT);
secondCardHolder.add(coordLabel);
}
coordsUnitsPanel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
secondCardHolder.add(coordsUnitsPanel);
- secondCardHolder.add(Box.createRigidArea(new Dimension(0,10)));
+ secondCardHolder.add(Box.createRigidArea(new Dimension(0,7)));
// altitude units
JLabel altUnitsLabel = new JLabel(I18nManager.getText("dialog.save.altitudeunits"));
altUnitsLabel.setAlignmentX(JLabel.LEFT_ALIGNMENT);
}
altUnitsPanel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
secondCardHolder.add(altUnitsPanel);
- secondCardHolder.add(Box.createRigidArea(new Dimension(0,10)));
+ secondCardHolder.add(Box.createRigidArea(new Dimension(0,7)));
// Selection of format of timestamps
JLabel timestampLabel = new JLabel(I18nManager.getText("dialog.save.timestampformat"));
timestampLabel.setAlignmentX(JLabel.LEFT_ALIGNMENT);
default : _delimiterRadios[4].setSelected(true);
_otherDelimiterText.setText("" + inDefaultDelimiter);
}
+ _pointTypeSelector.init(_app.getTrackInfo());
// set card and enable buttons
CardLayout cl = (CardLayout) _cards.getLayout();
cl.first(_cards);
/**
- * Save the track to file with the chosen options
+ * Start the save process by choosing the file to save to
* @return true if successful or cancelled, false if failed
*/
private boolean saveToFile()
{
- boolean saveOK = true;
- FileWriter writer = null;
+ if (!_pointTypeSelector.getAnythingSelected()) {
+ JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("dialog.save.notypesselected"),
+ I18nManager.getText("dialog.saveoptions.title"), JOptionPane.WARNING_MESSAGE);
+ return false;
+ }
if (_fileChooser == null)
{
_fileChooser = new JFileChooser();
_fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
_fileChooser.addChoosableFileFilter(new GenericFileFilter("filetype.txt", new String[] {"txt", "text"}));
- _fileChooser.addChoosableFileFilter(new GenericFileFilter("filetype.gpx", new String[] {"gpx"}));
- _fileChooser.addChoosableFileFilter(new GenericFileFilter("filetype.kml", new String[] {"kml"}));
_fileChooser.setAcceptAllFileFilterUsed(true);
// start from directory in config which should be set
- File configDir = Config.getWorkingDirectory();
- if (configDir != null) {_fileChooser.setCurrentDirectory(configDir);}
+ String configDir = Config.getConfigString(Config.KEY_TRACK_DIR);
+ if (configDir == null) {configDir = Config.getConfigString(Config.KEY_PHOTO_DIR);}
+ if (configDir != null) {_fileChooser.setCurrentDirectory(new File(configDir));}
}
if (_fileChooser.showSaveDialog(_parentFrame) == JFileChooser.APPROVE_OPTION)
{
- File saveFile = _fileChooser.getSelectedFile();
- String lineSeparator = System.getProperty("line.separator");
- // Get coordinate format and altitude format
- int coordFormat = Coordinate.FORMAT_NONE;
- for (int i=0; i<_coordUnitsRadios.length; i++)
- if (_coordUnitsRadios[i].isSelected())
- coordFormat = FORMAT_COORDS[i];
- int altitudeFormat = Altitude.FORMAT_NONE;
- for (int i=0; i<_altitudeUnitsRadios.length; i++)
- {
- if (_altitudeUnitsRadios[i].isSelected())
- {
- altitudeFormat = FORMAT_ALTS[i];
- }
+ return saveToFile(_fileChooser.getSelectedFile());
+ }
+ return true; // cancelled
+ }
+
+
+ /**
+ * Save the track to the specified file using the chosen options
+ * @param inSaveFile file to save to
+ * @return true if save successful, false if failed
+ */
+ private boolean saveToFile(File inSaveFile)
+ {
+ // TODO: Shorten method
+ FileWriter writer = null;
+ final String lineSeparator = System.getProperty("line.separator");
+ boolean saveOK = true;
+ // Get coordinate format and altitude format
+ int coordFormat = Coordinate.FORMAT_NONE;
+ for (int i=0; i<_coordUnitsRadios.length; i++)
+ if (_coordUnitsRadios[i].isSelected())
+ coordFormat = FORMAT_COORDS[i];
+ Unit altitudeUnit = null;
+ for (int i=0; i<_altitudeUnitsRadios.length; i++)
+ {
+ if (_altitudeUnitsRadios[i].isSelected()) {
+ altitudeUnit = UNIT_ALTS[i];
}
- // Get timestamp formats
- int timestampFormat = Timestamp.FORMAT_ORIGINAL;
- for (int i=0; i<_timestampUnitsRadios.length; i++)
- {
- if (_timestampUnitsRadios[i].isSelected())
- {
- timestampFormat = FORMAT_TIMES[i];
- }
+ }
+ // Get timestamp format
+ int timestampFormat = Timestamp.FORMAT_ORIGINAL;
+ for (int i=0; i<_timestampUnitsRadios.length; i++)
+ {
+ if (_timestampUnitsRadios[i].isSelected()) {
+ timestampFormat = FORMAT_TIMES[i];
}
+ }
+
+ // Correct chosen filename if necessary
+ final File saveFile = (isFilenameOk(inSaveFile)?inSaveFile:new File(inSaveFile.getAbsolutePath() + ".txt"));
- // Check if file exists, and confirm overwrite if necessary
- Object[] buttonTexts = {I18nManager.getText("button.overwrite"), I18nManager.getText("button.cancel")};
- if (!saveFile.exists() || JOptionPane.showOptionDialog(_parentFrame,
- I18nManager.getText("dialog.save.overwrite.text"),
- I18nManager.getText("dialog.save.overwrite.title"), JOptionPane.YES_NO_OPTION,
- JOptionPane.WARNING_MESSAGE, null, buttonTexts, buttonTexts[1])
- == JOptionPane.YES_OPTION)
+ // Check if file exists, and confirm overwrite if necessary
+ Object[] buttonTexts = {I18nManager.getText("button.overwrite"), I18nManager.getText("button.cancel")};
+ if (!saveFile.exists() || JOptionPane.showOptionDialog(_parentFrame,
+ I18nManager.getText("dialog.save.overwrite.text"),
+ I18nManager.getText("dialog.save.overwrite.title"), JOptionPane.YES_NO_OPTION,
+ JOptionPane.WARNING_MESSAGE, null, buttonTexts, buttonTexts[1])
+ == JOptionPane.YES_OPTION)
+ {
+ try
{
- try
- {
- // Create output file
- writer = new FileWriter(saveFile);
- // Determine delimiter character to use
- char delimiter = getDelimiter();
- FieldInfo info = null;
- Field field = null;
-
- StringBuffer buffer = null;
- int numFields = _model.getRowCount();
- boolean firstField = true;
- // Write header row if required
- if (_headerRowCheckbox.isSelected())
- {
- buffer = new StringBuffer();
- for (int f=0; f<numFields; f++)
- {
- info = _model.getFieldInfo(f);
- if (info.isSelected())
- {
- if (!firstField)
- {
- // output field separator
- buffer.append(delimiter);
- }
- field = info.getField();
- buffer.append(field.getName());
- firstField = false;
- }
- }
- writer.write(buffer.toString());
- writer.write(lineSeparator);
- }
+ // Create output file
+ writer = new FileWriter(saveFile);
+ // Determine delimiter character to use
+ final char delimiter = getDelimiter();
+ FieldInfo info = null;
- // Loop over points outputting each in turn to buffer
- int numPoints = _track.getNumPoints();
- for (int p=0; p<numPoints; p++)
+ StringBuffer buffer = null;
+ int numFields = _model.getRowCount();
+ boolean firstField = true;
+ // Write header row if required
+ if (_headerRowCheckbox.isSelected())
+ {
+ buffer = new StringBuffer();
+ for (int f=0; f<numFields; f++)
{
- DataPoint point = _track.getPoint(p);
- firstField = true;
- buffer = new StringBuffer();
- for (int f=0; f<numFields; f++)
+ info = _model.getFieldInfo(f);
+ if (info.isSelected())
{
- info = _model.getFieldInfo(f);
- if (info.isSelected())
- {
- if (!firstField)
- {
- // output field separator
- buffer.append(delimiter);
- }
- field = info.getField();
- // Output field according to type
- if (field == Field.LATITUDE)
- {
- buffer.append(point.getLatitude().output(coordFormat));
- }
- else if (field == Field.LONGITUDE)
- {
- buffer.append(point.getLongitude().output(coordFormat));
- }
- else if (field == Field.ALTITUDE)
- {
- try
- {
- buffer.append(point.getAltitude().getStringValue(altitudeFormat));
- }
- catch (NullPointerException npe) {}
- }
- else if (field == Field.TIMESTAMP)
- {
- if (point.hasTimestamp())
- {
- if (timestampFormat == Timestamp.FORMAT_ORIGINAL) {
- // output original string
- buffer.append(point.getFieldValue(Field.TIMESTAMP));
- }
- else {
- // format value accordingly
- buffer.append(point.getTimestamp().getText(timestampFormat));
- }
- }
- }
- else
- {
- String value = point.getFieldValue(field);
- if (value != null)
- {
- buffer.append(value);
- }
- }
- firstField = false;
+ // output field separator
+ if (!firstField) {
+ buffer.append(delimiter);
}
+ buffer.append(info.getField().getName());
+ firstField = false;
}
- // Output to file
- writer.write(buffer.toString());
- writer.write(lineSeparator);
}
- // Store directory in config for later
- Config.setWorkingDirectory(saveFile.getParentFile());
- // Save successful
- UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.save.ok1")
- + " " + numPoints + " " + I18nManager.getText("confirm.save.ok2")
- + " " + saveFile.getAbsolutePath());
- _app.informDataSaved();
+ writer.write(buffer.toString());
+ writer.write(lineSeparator);
}
- catch (IOException ioe)
- {
- saveOK = false;
- JOptionPane.showMessageDialog(_parentFrame,
- I18nManager.getText("error.save.failed") + ioe.getMessage(),
- I18nManager.getText("error.save.dialogtitle"),
- JOptionPane.ERROR_MESSAGE);
+
+ // Examine selection
+ int selStart = -1, selEnd = -1;
+ if (_pointTypeSelector.getJustSelection()) {
+ selStart = _app.getTrackInfo().getSelection().getStart();
+ selEnd = _app.getTrackInfo().getSelection().getEnd();
}
- finally
+ // Loop over points outputting each in turn to buffer
+ Track track = _app.getTrackInfo().getTrack();
+ final int numPoints = track.getNumPoints();
+ int numSaved = 0;
+ for (int p=0; p<numPoints; p++)
{
- // try to close file if it's open
- try
+ DataPoint point = track.getPoint(p);
+ boolean savePoint = ((point.isWaypoint() && _pointTypeSelector.getWaypointsSelected())
+ || (!point.isWaypoint() && !point.hasMedia() && _pointTypeSelector.getTrackpointsSelected())
+ || (!point.isWaypoint() && point.getPhoto()!=null && _pointTypeSelector.getPhotopointsSelected())
+ || (!point.isWaypoint() && point.getAudio()!=null && _pointTypeSelector.getAudiopointsSelected()))
+ && (!_pointTypeSelector.getJustSelection() || (p>=selStart && p<=selEnd));
+ if (!savePoint) {continue;}
+ numSaved++;
+ firstField = true;
+ buffer = new StringBuffer();
+ for (int f=0; f<numFields; f++)
{
- if (writer != null)
+ info = _model.getFieldInfo(f);
+ if (info.isSelected())
{
- writer.close();
+ // output field separator
+ if (!firstField) {
+ buffer.append(delimiter);
+ }
+ saveField(buffer, point, info.getField(), coordFormat, altitudeUnit, timestampFormat);
+ firstField = false;
}
}
- catch (Exception e) {}
+ // Output to file
+ writer.write(buffer.toString());
+ writer.write(lineSeparator);
}
+ // Store directory in config for later
+ Config.setConfigString(Config.KEY_TRACK_DIR, saveFile.getParentFile().getAbsolutePath());
+ // Add to recent file list
+ Config.getRecentFileList().addFile(new RecentFile(inSaveFile, true));
+ // Save successful
+ UpdateMessageBroker.informSubscribers();
+ UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.save.ok1")
+ + " " + numSaved + " " + I18nManager.getText("confirm.save.ok2")
+ + " " + saveFile.getAbsolutePath());
+ _app.informDataSaved();
}
- else
+ catch (IOException ioe)
{
- // Overwrite file confirm cancelled
saveOK = false;
+ _app.showErrorMessageNoLookup("error.save.dialogtitle",
+ I18nManager.getText("error.save.failed") + " : " + ioe.getMessage());
+ }
+ finally
+ {
+ // try to close file if it's open
+ try {
+ writer.close();
+ }
+ catch (Exception e) {}
}
}
+ else
+ {
+ // Overwrite file confirm cancelled
+ saveOK = false;
+ }
return saveOK;
}
+ /**
+ * Format the given field and append to the given buffer for saving
+ * @param inBuffer buffer to append to
+ * @param inPoint point object
+ * @param inField field object
+ * @param inCoordFormat coordinate format
+ * @param inAltitudeUnit altitude unit
+ * @param inTimestampFormat timestamp format
+ */
+ private void saveField(StringBuffer inBuffer, DataPoint inPoint, Field inField,
+ int inCoordFormat, Unit inAltitudeUnit, int inTimestampFormat)
+ {
+ // Output field according to type
+ if (inField == Field.LATITUDE)
+ {
+ inBuffer.append(inPoint.getLatitude().output(inCoordFormat));
+ }
+ else if (inField == Field.LONGITUDE)
+ {
+ inBuffer.append(inPoint.getLongitude().output(inCoordFormat));
+ }
+ else if (inField == Field.ALTITUDE)
+ {
+ try
+ {
+ inBuffer.append(inPoint.getAltitude().getStringValue(inAltitudeUnit));
+ }
+ catch (NullPointerException npe) {}
+ }
+ else if (inField == Field.TIMESTAMP)
+ {
+ if (inPoint.hasTimestamp())
+ {
+ if (inTimestampFormat == Timestamp.FORMAT_ORIGINAL) {
+ // output original string
+ inBuffer.append(inPoint.getTimestamp().getText(Timestamp.FORMAT_ORIGINAL));
+ }
+ else {
+ // format value accordingly
+ inBuffer.append(inPoint.getTimestamp().getText(inTimestampFormat));
+ }
+ }
+ }
+ else
+ {
+ String value = inPoint.getFieldValue(inField);
+ if (value != null)
+ {
+ inBuffer.append(value);
+ }
+ }
+ }
+
+
/**
* @return the selected delimiter character
*/
// Wasn't any of those so must be 'other'
return _otherDelimiterText.getText().charAt(0);
}
+
+
+ /**
+ * Check the selected filename to see if it is acceptable
+ * @param inFile chosen file to save
+ * @return true if filename is ok
+ */
+ private static boolean isFilenameOk(File inFile)
+ {
+ String filename = inFile.getName().toLowerCase();
+ return (filename.length() <4 || (!filename.endsWith(".gpx")
+ && !filename.endsWith(".kml") && !filename.endsWith(".kmz") && !filename.endsWith(".zip")));
+ }
}