]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/save/FileSaver.java
Version 4, January 2008
[GpsPrune.git] / tim / prune / save / FileSaver.java
1 package tim.prune.save;
2
3 import java.awt.BorderLayout;
4 import java.awt.CardLayout;
5 import java.awt.Component;
6 import java.awt.Dimension;
7 import java.awt.FlowLayout;
8 import java.awt.GridLayout;
9 import java.awt.event.ActionEvent;
10 import java.awt.event.ActionListener;
11 import java.io.File;
12 import java.io.FileWriter;
13 import java.io.IOException;
14
15 import javax.swing.BorderFactory;
16 import javax.swing.Box;
17 import javax.swing.BoxLayout;
18 import javax.swing.ButtonGroup;
19 import javax.swing.JButton;
20 import javax.swing.JCheckBox;
21 import javax.swing.JDialog;
22 import javax.swing.JFileChooser;
23 import javax.swing.JFrame;
24 import javax.swing.JLabel;
25 import javax.swing.JOptionPane;
26 import javax.swing.JPanel;
27 import javax.swing.JRadioButton;
28 import javax.swing.JScrollPane;
29 import javax.swing.JTable;
30 import javax.swing.JTextField;
31 import javax.swing.ListSelectionModel;
32 import javax.swing.table.TableModel;
33
34 import tim.prune.App;
35 import tim.prune.I18nManager;
36 import tim.prune.data.Altitude;
37 import tim.prune.data.Coordinate;
38 import tim.prune.data.DataPoint;
39 import tim.prune.data.Field;
40 import tim.prune.data.FieldList;
41 import tim.prune.data.Timestamp;
42 import tim.prune.data.Track;
43 import tim.prune.load.OneCharDocument;
44
45 /**
46  * Class to manage the saving of track data
47  * into a user-specified file
48  */
49 public class FileSaver
50 {
51         private App _app = null;
52         private JFrame _parentFrame = null;
53         private Track _track = null;
54         private JDialog _dialog = null;
55         private JFileChooser _fileChooser = null;
56         private JPanel _cards = null;
57         private JButton _nextButton = null, _backButton = null;
58         private JTable _table = null;
59         private FieldSelectionTableModel _model = null;
60         private JButton _moveUpButton = null, _moveDownButton = null;
61         private UpDownToggler _toggler = null;
62         private JRadioButton[] _delimiterRadios = null;
63         private JTextField _otherDelimiterText = null;
64         private JCheckBox _headerRowCheckbox = null;
65         private JRadioButton[] _coordUnitsRadios = null;
66         private JRadioButton[] _altitudeUnitsRadios = null;
67         private JRadioButton[] _timestampUnitsRadios = null;
68         private static final int[] FORMAT_COORDS = {Coordinate.FORMAT_NONE, Coordinate.FORMAT_DEG_MIN_SEC,
69                 Coordinate.FORMAT_DEG_MIN, Coordinate.FORMAT_DEG};
70         private static final int[] FORMAT_ALTS = {Altitude.FORMAT_NONE, Altitude.FORMAT_METRES, Altitude.FORMAT_FEET};
71         private static final int[] FORMAT_TIMES = {Timestamp.FORMAT_ORIGINAL, Timestamp.FORMAT_LOCALE, Timestamp.FORMAT_ISO_8601};
72
73
74         /**
75          * Constructor
76          * @param inApp application object to inform of success
77          * @param inParentFrame parent frame
78          * @param inTrack track object to save
79          */
80         public FileSaver(App inApp, JFrame inParentFrame, Track inTrack)
81         {
82                 _app = inApp;
83                 _parentFrame = inParentFrame;
84                 _track = inTrack;
85         }
86
87
88         /**
89          * Show the save file dialog
90          * @param inDefaultDelimiter default delimiter to use
91          */
92         public void showDialog(char inDefaultDelimiter)
93         {
94                 if (_dialog == null)
95                 {
96                         _dialog = new JDialog(_parentFrame, I18nManager.getText("dialog.saveoptions.title"), true);
97                         _dialog.setLocationRelativeTo(_parentFrame);
98                         _dialog.getContentPane().add(makeDialogComponents());
99                         _dialog.pack();
100                 }
101                 // Check field list
102                 FieldList fieldList = _track.getFieldList();
103                 int numFields = fieldList.getNumFields();
104                 _model = new FieldSelectionTableModel(numFields);
105                 for (int i=0; i<numFields; i++)
106                 {
107                         Field field = fieldList.getField(i);
108                         FieldInfo info = new FieldInfo(field, _track.hasData(field));
109                         _model.addFieldInfo(info, i);
110                 }
111                 // Initialise dialog and show it
112                 initDialog(_model, inDefaultDelimiter);
113                 _dialog.show();
114         }
115
116
117         /**
118          * Make the dialog components
119          * @return the GUI components for the save dialog
120          */
121         private Component makeDialogComponents()
122         {
123                 JPanel panel = new JPanel();
124                 panel.setLayout(new BorderLayout());
125                 _cards = new JPanel();
126                 _cards.setLayout(new CardLayout());
127                 panel.add(_cards, BorderLayout.CENTER);
128
129                 // Make first card for field selection and delimiter
130                 JPanel firstCard = new JPanel();
131                 firstCard.setLayout(new BoxLayout(firstCard, BoxLayout.Y_AXIS));
132                 JPanel tablePanel = new JPanel();
133                 tablePanel.setLayout(new BorderLayout());
134                 _table = new JTable();
135                 _table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
136                 // Enclose table in a scrollpane to prevent other components getting lost
137                 JScrollPane scrollPane = new JScrollPane(_table);
138                 _table.setPreferredScrollableViewportSize(new Dimension(300, 150));
139                 tablePanel.add(scrollPane, BorderLayout.CENTER);
140
141                 // Make a panel to hold the table and up/down buttons
142                 JPanel fieldsPanel = new JPanel();
143                 fieldsPanel.setLayout(new BorderLayout());
144                 fieldsPanel.add(tablePanel, BorderLayout.CENTER);
145                 JPanel updownPanel = new JPanel();
146                 updownPanel.setLayout(new BoxLayout(updownPanel, BoxLayout.Y_AXIS));
147                 _moveUpButton = new JButton(I18nManager.getText("button.moveup"));
148                 _moveUpButton.addActionListener(new ActionListener() {
149                         public void actionPerformed(ActionEvent e)
150                         {
151                                 int row = _table.getSelectedRow();
152                                 if (row > 0)
153                                 {
154                                         _model.swapItems(row, row - 1);
155                                         _table.setRowSelectionInterval(row - 1, row - 1);
156                                 }
157                         }
158                 });
159                 _moveUpButton.setEnabled(false);
160                 updownPanel.add(_moveUpButton);
161                 _moveDownButton = new JButton(I18nManager.getText("button.movedown"));
162                 _moveDownButton.addActionListener(new ActionListener() {
163                         public void actionPerformed(ActionEvent e)
164                         {
165                                 int row = _table.getSelectedRow();
166                                 if (row > -1 && row < (_model.getRowCount() - 1))
167                                 {
168                                         _model.swapItems(row, row + 1);
169                                         _table.setRowSelectionInterval(row + 1, row + 1);
170                                 }
171                         }
172                 });
173                 _moveDownButton.setEnabled(false);
174                 updownPanel.add(_moveDownButton);
175                 fieldsPanel.add(updownPanel, BorderLayout.EAST);
176                 // enable/disable buttons based on table row selection
177                 _toggler = new UpDownToggler(_moveUpButton, _moveDownButton);
178                 _table.getSelectionModel().addListSelectionListener(_toggler);
179
180                 // Add fields panel and the delimiter panel to first card in pack
181                 JLabel saveOptionsLabel = new JLabel(I18nManager.getText("dialog.save.fieldstosave"));
182                 saveOptionsLabel.setAlignmentX(JLabel.LEFT_ALIGNMENT);
183                 firstCard.add(saveOptionsLabel);
184                 fieldsPanel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
185                 firstCard.add(fieldsPanel);
186                 firstCard.add(Box.createRigidArea(new Dimension(0,10)));
187
188                 // delimiter panel
189                 JLabel delimLabel = new JLabel(I18nManager.getText("dialog.delimiter.label"));
190                 delimLabel.setAlignmentX(JLabel.LEFT_ALIGNMENT);
191                 firstCard.add(delimLabel);
192                 JPanel delimsPanel = new JPanel();
193                 delimsPanel.setLayout(new GridLayout(0, 2));
194                 delimsPanel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
195                 // radio buttons
196                 _delimiterRadios = new JRadioButton[5];
197                 _delimiterRadios[0] = new JRadioButton(I18nManager.getText("dialog.delimiter.comma"));
198                 delimsPanel.add(_delimiterRadios[0]);
199                 _delimiterRadios[1] = new JRadioButton(I18nManager.getText("dialog.delimiter.tab"));
200                 delimsPanel.add(_delimiterRadios[1]);
201                 _delimiterRadios[2] = new JRadioButton(I18nManager.getText("dialog.delimiter.semicolon"));
202                 delimsPanel.add(_delimiterRadios[2]);
203                 _delimiterRadios[3] = new JRadioButton(I18nManager.getText("dialog.delimiter.space"));
204                 delimsPanel.add(_delimiterRadios[3]);
205                 JPanel otherPanel = new JPanel();
206                 otherPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
207                 _delimiterRadios[4] = new JRadioButton(I18nManager.getText("dialog.delimiter.other"));
208                 otherPanel.add(_delimiterRadios[4]);
209                 _otherDelimiterText = new JTextField(new OneCharDocument(), null, 2);
210                 otherPanel.add(_otherDelimiterText);
211                 // Group radio buttons
212                 ButtonGroup delimGroup = new ButtonGroup();
213                 for (int i=0; i<_delimiterRadios.length; i++)
214                 {
215                         delimGroup.add(_delimiterRadios[i]);
216                 }
217                 delimsPanel.add(otherPanel);
218                 firstCard.add(delimsPanel);
219
220                 // header checkbox
221                 firstCard.add(Box.createRigidArea(new Dimension(0,10)));
222                 _headerRowCheckbox = new JCheckBox(I18nManager.getText("dialog.save.headerrow"));
223                 firstCard.add(_headerRowCheckbox);
224
225                 _cards.add(firstCard, "card1");
226
227                 JPanel secondCard = new JPanel();
228                 secondCard.setLayout(new BorderLayout());
229                 JPanel secondCardHolder = new JPanel();
230                 secondCardHolder.setLayout(new BoxLayout(secondCardHolder, BoxLayout.Y_AXIS));
231                 JLabel coordLabel = new JLabel(I18nManager.getText("dialog.save.coordinateunits"));
232                 coordLabel.setAlignmentX(JLabel.LEFT_ALIGNMENT);
233                 secondCardHolder.add(coordLabel);
234                 JPanel coordsUnitsPanel = new JPanel();
235                 coordsUnitsPanel.setBorder(BorderFactory.createEtchedBorder());
236                 coordsUnitsPanel.setLayout(new GridLayout(0, 2));
237                 _coordUnitsRadios = new JRadioButton[4];
238                 _coordUnitsRadios[0] = new JRadioButton(I18nManager.getText("units.original"));
239                 _coordUnitsRadios[1] = new JRadioButton(I18nManager.getText("units.degminsec"));
240                 _coordUnitsRadios[2] = new JRadioButton(I18nManager.getText("units.degmin"));
241                 _coordUnitsRadios[3] = new JRadioButton(I18nManager.getText("units.deg"));
242                 ButtonGroup coordGroup = new ButtonGroup();
243                 for (int i=0; i<4; i++)
244                 {
245                         coordGroup.add(_coordUnitsRadios[i]);
246                         coordsUnitsPanel.add(_coordUnitsRadios[i]);
247                         _coordUnitsRadios[i].setSelected(i==0);
248                 }
249                 coordsUnitsPanel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
250                 secondCardHolder.add(coordsUnitsPanel);
251                 secondCardHolder.add(Box.createRigidArea(new Dimension(0,10)));
252                 // altitude units
253                 JLabel altUnitsLabel = new JLabel(I18nManager.getText("dialog.save.altitudeunits"));
254                 altUnitsLabel.setAlignmentX(JLabel.LEFT_ALIGNMENT);
255                 secondCardHolder.add(altUnitsLabel);
256                 JPanel altUnitsPanel = new JPanel();
257                 altUnitsPanel.setBorder(BorderFactory.createEtchedBorder());
258                 altUnitsPanel.setLayout(new GridLayout(0, 2));
259                 _altitudeUnitsRadios = new JRadioButton[3];
260                 _altitudeUnitsRadios[0] = new JRadioButton(I18nManager.getText("units.original"));
261                 _altitudeUnitsRadios[1] = new JRadioButton(I18nManager.getText("units.metres"));
262                 _altitudeUnitsRadios[2] = new JRadioButton(I18nManager.getText("units.feet"));
263                 ButtonGroup altGroup = new ButtonGroup();
264                 for (int i=0; i<3; i++)
265                 {
266                         altGroup.add(_altitudeUnitsRadios[i]);
267                         altUnitsPanel.add(_altitudeUnitsRadios[i]);
268                         _altitudeUnitsRadios[i].setSelected(i==0);
269                 }
270                 altUnitsPanel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
271                 secondCardHolder.add(altUnitsPanel);
272                 secondCardHolder.add(Box.createRigidArea(new Dimension(0,10)));
273                 // Selection of format of timestamps
274                 JLabel timestampLabel = new JLabel(I18nManager.getText("dialog.save.timestampformat"));
275                 timestampLabel.setAlignmentX(JLabel.LEFT_ALIGNMENT);
276                 secondCardHolder.add(timestampLabel);
277                 JPanel timestampPanel = new JPanel();
278                 timestampPanel.setBorder(BorderFactory.createEtchedBorder());
279                 timestampPanel.setLayout(new GridLayout(0, 2));
280                 _timestampUnitsRadios = new JRadioButton[3];
281                 _timestampUnitsRadios[0] = new JRadioButton(I18nManager.getText("units.original"));
282                 _timestampUnitsRadios[1] = new JRadioButton(I18nManager.getText("units.default"));
283                 _timestampUnitsRadios[2] = new JRadioButton(I18nManager.getText("units.iso8601"));
284                 ButtonGroup timeGroup = new ButtonGroup();
285                 for (int i=0; i<3; i++)
286                 {
287                         timeGroup.add(_timestampUnitsRadios[i]);
288                         timestampPanel.add(_timestampUnitsRadios[i]);
289                         _timestampUnitsRadios[i].setSelected(i==0);
290                 }
291                 timestampPanel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
292                 secondCardHolder.add(timestampPanel);
293                 secondCard.add(secondCardHolder, BorderLayout.NORTH);
294                 _cards.add(secondCard, "card2");
295
296                 // Put together with ok/cancel buttons on the bottom
297                 JPanel buttonPanel = new JPanel();
298                 buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
299                 _backButton = new JButton(I18nManager.getText("button.back"));
300                 _backButton.addActionListener(new ActionListener() {
301                         public void actionPerformed(ActionEvent e)
302                         {
303                                 CardLayout cl = (CardLayout) _cards.getLayout();
304                                 cl.previous(_cards);
305                                 _backButton.setEnabled(false);
306                                 _nextButton.setEnabled(true);
307                         }
308                 });
309                 _backButton.setEnabled(false);
310                 buttonPanel.add(_backButton);
311                 _nextButton = new JButton(I18nManager.getText("button.next"));
312                 _nextButton.setEnabled(true);
313                 _nextButton.addActionListener(new ActionListener() {
314                         public void actionPerformed(ActionEvent e)
315                         {
316                                 CardLayout cl = (CardLayout) _cards.getLayout();
317                                 cl.next(_cards);
318                                 _backButton.setEnabled(true);
319                                 _nextButton.setEnabled(false);
320                         }
321                 });
322                 buttonPanel.add(_nextButton);
323                 JButton okButton = new JButton(I18nManager.getText("button.finish"));
324                 okButton.addActionListener(new ActionListener() {
325                         public void actionPerformed(ActionEvent e)
326                         {
327                                 if (saveToFile())
328                                 {
329                                         _dialog.dispose();
330                                 }
331                         }
332                 });
333                 buttonPanel.add(okButton);
334                 JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
335                 cancelButton.addActionListener(new ActionListener() {
336                         public void actionPerformed(ActionEvent e)
337                         {
338                                 _dialog.dispose();
339                         }
340                 });
341                 buttonPanel.add(cancelButton);
342                 panel.add(buttonPanel, BorderLayout.SOUTH);
343                 return panel;
344         }
345
346         /**
347          * Initialize the dialog with the given details
348          * @param inModel table model
349          * @param inDefaultDelimiter default delimiter character
350          */
351         private void initDialog(TableModel inModel, char inDefaultDelimiter)
352         {
353                 // set table model
354                 _table.setModel(inModel);
355                 // reset toggler
356                 _toggler.setListSize(inModel.getRowCount());
357                 // choose last-used delimiter as default
358                 switch (inDefaultDelimiter)
359                 {
360                         case ','  : _delimiterRadios[0].setSelected(true); break;
361                         case '\t' : _delimiterRadios[1].setSelected(true); break;
362                         case ';'  : _delimiterRadios[2].setSelected(true); break;
363                         case ' '  : _delimiterRadios[3].setSelected(true); break;
364                         default   : _delimiterRadios[4].setSelected(true);
365                                                 _otherDelimiterText.setText("" + inDefaultDelimiter);
366                 }
367                 // set card and enable buttons
368                 CardLayout cl = (CardLayout) _cards.getLayout();
369                 cl.first(_cards);
370                 _nextButton.setEnabled(true);
371                 _backButton.setEnabled(false);
372         }
373
374
375         /**
376          * Save the track to file with the chosen options
377          * @return true if successful or cancelled, false if failed
378          */
379         private boolean saveToFile()
380         {
381                 boolean saveOK = true;
382                 FileWriter writer = null;
383                 if (_fileChooser == null)
384                         _fileChooser = new JFileChooser();
385                 _fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
386                 if (_fileChooser.showSaveDialog(_parentFrame) == JFileChooser.APPROVE_OPTION)
387                 {
388                         File saveFile = _fileChooser.getSelectedFile();
389                         String lineSeparator = System.getProperty("line.separator");
390                         // Get coordinate format and altitude format
391                         int coordFormat = Coordinate.FORMAT_NONE;
392                         for (int i=0; i<_coordUnitsRadios.length; i++)
393                                 if (_coordUnitsRadios[i].isSelected())
394                                         coordFormat = FORMAT_COORDS[i];
395                         int altitudeFormat = Altitude.FORMAT_NONE;
396                         for (int i=0; i<_altitudeUnitsRadios.length; i++)
397                         {
398                                 if (_altitudeUnitsRadios[i].isSelected())
399                                 {
400                                         altitudeFormat = FORMAT_ALTS[i];
401                                 }
402                         }
403                         // Get timestamp formats
404                         int timestampFormat = Timestamp.FORMAT_ORIGINAL;
405                         for (int i=0; i<_timestampUnitsRadios.length; i++)
406                         {
407                                 if (_timestampUnitsRadios[i].isSelected())
408                                 {
409                                         timestampFormat = FORMAT_TIMES[i];
410                                 }
411                         }
412
413                         // Check if file exists, and confirm overwrite if necessary
414                         Object[] buttonTexts = {I18nManager.getText("button.overwrite"), I18nManager.getText("button.cancel")};
415                         if (!saveFile.exists() || JOptionPane.showOptionDialog(_parentFrame,
416                                         I18nManager.getText("dialog.save.overwrite.text"),
417                                         I18nManager.getText("dialog.save.overwrite.title"), JOptionPane.YES_NO_OPTION,
418                                         JOptionPane.WARNING_MESSAGE, null, buttonTexts, buttonTexts[1])
419                                 == JOptionPane.YES_OPTION)
420                         {
421                                 try
422                                 {
423                                         // Create output file
424                                         writer = new FileWriter(saveFile);
425                                         // Determine delimiter character to use
426                                         char delimiter = getDelimiter();
427                                         FieldInfo info = null;
428                                         Field field = null;
429
430                                         StringBuffer buffer = null;
431                                         int numFields = _model.getRowCount();
432                                         boolean firstField = true;
433                                         // Write header row if required
434                                         if (_headerRowCheckbox.isSelected())
435                                         {
436                                                 buffer = new StringBuffer();
437                                                 for (int f=0; f<numFields; f++)
438                                                 {
439                                                         info = _model.getFieldInfo(f);
440                                                         if (info.isSelected())
441                                                         {
442                                                                 if (!firstField)
443                                                                 {
444                                                                         // output field separator
445                                                                         buffer.append(delimiter);
446                                                                 }
447                                                                 field = info.getField();
448                                                                 buffer.append(field.getName());
449                                                                 firstField = false;
450                                                         }
451                                                 }
452                                                 writer.write(buffer.toString());
453                                                 writer.write(lineSeparator);
454                                         }
455
456                                         // Loop over points outputting each in turn to buffer
457                                         int numPoints = _track.getNumPoints();
458                                         for (int p=0; p<numPoints; p++)
459                                         {
460                                                 DataPoint point = _track.getPoint(p);
461                                                 firstField = true;
462                                                 buffer = new StringBuffer();
463                                                 for (int f=0; f<numFields; f++)
464                                                 {
465                                                         info = _model.getFieldInfo(f);
466                                                         if (info.isSelected())
467                                                         {
468                                                                 if (!firstField)
469                                                                 {
470                                                                         // output field separator
471                                                                         buffer.append(delimiter);
472                                                                 }
473                                                                 field = info.getField();
474                                                                 // Output field according to type
475                                                                 if (field == Field.LATITUDE)
476                                                                 {
477                                                                         buffer.append(point.getLatitude().output(coordFormat));
478                                                                 }
479                                                                 else if (field == Field.LONGITUDE)
480                                                                 {
481                                                                         buffer.append(point.getLongitude().output(coordFormat));
482                                                                 }
483                                                                 else if (field == Field.ALTITUDE)
484                                                                 {
485                                                                         try
486                                                                         {
487                                                                                 buffer.append(point.getAltitude().getValue(altitudeFormat));
488                                                                         }
489                                                                         catch (NullPointerException npe) {}
490                                                                 }
491                                                                 else if (field == Field.TIMESTAMP)
492                                                                 {
493                                                                         try
494                                                                         {
495                                                                                 if (timestampFormat == Timestamp.FORMAT_ORIGINAL) {
496                                                                                         // output original string
497                                                                                         buffer.append(point.getFieldValue(Field.TIMESTAMP));
498                                                                                 }
499                                                                                 else {
500                                                                                         // format value accordingly
501                                                                                         buffer.append(point.getTimestamp().getText(timestampFormat));
502                                                                                 }
503                                                                         }
504                                                                         catch (NullPointerException npe) {}
505                                                                 }
506                                                                 else
507                                                                 {
508                                                                         String value = point.getFieldValue(field);
509                                                                         if (value != null)
510                                                                         {
511                                                                                 buffer.append(value);
512                                                                         }
513                                                                 }
514                                                                 firstField = false;
515                                                         }
516                                                 }
517                                                 // Output to file
518                                                 writer.write(buffer.toString());
519                                                 writer.write(lineSeparator);
520                                         }
521                                         // Save successful
522                                         JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("dialog.save.ok1")
523                                                  + " " + numPoints + " " + I18nManager.getText("dialog.save.ok2")
524                                                  + " " + saveFile.getAbsolutePath(),
525                                                 I18nManager.getText("dialog.save.oktitle"), JOptionPane.INFORMATION_MESSAGE);
526                                         _app.informDataSaved();
527                                 }
528                                 catch (IOException ioe)
529                                 {
530                                         saveOK = false;
531                                         JOptionPane.showMessageDialog(_parentFrame,
532                                                 I18nManager.getText("error.save.failed") + ioe.getMessage(),
533                                                 I18nManager.getText("error.save.dialogtitle"),
534                                                 JOptionPane.ERROR_MESSAGE);
535                                 }
536                                 finally
537                                 {
538                                         // try to close file if it's open
539                                         try
540                                         {
541                                                 if (writer != null)
542                                                 {
543                                                         writer.close();
544                                                 }
545                                         }
546                                         catch (Exception e) {}
547                                 }
548                         }
549                         else
550                         {
551                                 // Overwrite file confirm cancelled
552                                 saveOK = false;
553                         }
554                 }
555                 return saveOK;
556         }
557
558
559         /**
560          * @return the selected delimiter character
561          */
562         private char getDelimiter()
563         {
564                 // Check the preset 4 delimiters
565                 final char[] delimiters = {',', '\t', ';', ' '};
566                 for (int i=0; i<4; i++)
567                 {
568                         if (_delimiterRadios[i].isSelected())
569                         {
570                                 return delimiters[i];
571                         }
572                 }
573                 // Wasn't any of those so must be 'other'
574                 return _otherDelimiterText.getText().charAt(0);
575         }
576 }