1 package tim.prune.load;
3 import java.awt.BorderLayout;
4 import java.awt.Component;
5 import java.awt.FlowLayout;
6 import java.awt.GridLayout;
7 import java.awt.event.ActionEvent;
8 import java.awt.event.ActionListener;
9 import java.io.BufferedReader;
10 import java.io.InputStreamReader;
12 import javax.swing.BorderFactory;
13 import javax.swing.BoxLayout;
14 import javax.swing.JButton;
15 import javax.swing.JCheckBox;
16 import javax.swing.JDialog;
17 import javax.swing.JLabel;
18 import javax.swing.JOptionPane;
19 import javax.swing.JPanel;
20 import javax.swing.JProgressBar;
21 import javax.swing.JTextField;
22 import javax.swing.SwingConstants;
23 import javax.swing.event.ChangeEvent;
24 import javax.swing.event.ChangeListener;
25 import javax.xml.parsers.SAXParser;
26 import javax.xml.parsers.SAXParserFactory;
29 import tim.prune.Config;
30 import tim.prune.ExternalTools;
31 import tim.prune.GenericFunction;
32 import tim.prune.I18nManager;
33 import tim.prune.data.Altitude;
34 import tim.prune.load.xml.XmlFileLoader;
35 import tim.prune.load.xml.XmlHandler;
38 * Class to manage the loading of GPS data using GpsBabel
40 public class GpsLoader extends GenericFunction implements Runnable
42 private boolean _gpsBabelChecked = false;
43 private JDialog _dialog = null;
44 private JTextField _deviceField = null, _formatField = null;
45 private JCheckBox _waypointCheckbox = null, _trackCheckbox = null;
46 private JButton _okButton = null;
47 private JProgressBar _progressBar = null;
48 private boolean _cancelled = false;
53 * @param inApp Application object to inform of data load
55 public GpsLoader(App inApp)
60 /** Get the name key */
61 public String getNameKey() {
62 return "function.loadfromgps";
66 * Open the GUI to select options and start the load
70 // Check if gpsbabel looks like it's installed
71 if (_gpsBabelChecked || ExternalTools.isGpsbabelInstalled()
72 || JOptionPane.showConfirmDialog(_dialog,
73 I18nManager.getText("dialog.gpsload.nogpsbabel"),
74 I18nManager.getText(getNameKey()),
75 JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION)
77 _gpsBabelChecked = true;
81 _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
82 _dialog.setLocationRelativeTo(_parentFrame);
83 _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
84 _dialog.getContentPane().add(makeDialogComponents());
87 // Initialise progress bars, buttons
89 setupProgressBar(true);
90 _dialog.setVisible(true);
96 * @return a panel containing the main dialog components
98 private JPanel makeDialogComponents()
100 JPanel outerPanel = new JPanel();
101 outerPanel.setLayout(new BorderLayout());
102 // Main panel with options etc
103 JPanel mainPanel = new JPanel();
104 mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
106 // text fields for options
107 JPanel gridPanel = new JPanel();
108 gridPanel.setLayout(new GridLayout(0, 2, 10, 3));
109 JLabel deviceLabel = new JLabel(I18nManager.getText("dialog.gpsload.device"));
110 deviceLabel.setHorizontalAlignment(SwingConstants.RIGHT);
111 gridPanel.add(deviceLabel);
112 _deviceField = new JTextField(Config.getGpsDevice(), 12);
113 gridPanel.add(_deviceField);
114 JLabel formatLabel = new JLabel(I18nManager.getText("dialog.gpsload.format"));
115 formatLabel.setHorizontalAlignment(SwingConstants.RIGHT);
116 gridPanel.add(formatLabel);
117 _formatField = new JTextField(Config.getGpsFormat(), 12);
118 gridPanel.add(_formatField);
119 gridPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
120 gridPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 5, 20));
121 mainPanel.add(gridPanel);
124 ChangeListener checkboxListener = new ChangeListener() {
125 public void stateChanged(ChangeEvent e)
130 _waypointCheckbox = new JCheckBox(I18nManager.getText("dialog.gpsload.getwaypoints"), true);
131 _waypointCheckbox.addChangeListener(checkboxListener);
132 _waypointCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT);
133 mainPanel.add(_waypointCheckbox);
134 _trackCheckbox = new JCheckBox(I18nManager.getText("dialog.gpsload.gettracks"), true);
135 _trackCheckbox.addChangeListener(checkboxListener);
136 _trackCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT);
137 mainPanel.add(_trackCheckbox);
138 // progress bar (initially invisible)
139 _progressBar = new JProgressBar(0, 10);
140 mainPanel.add(_progressBar);
141 outerPanel.add(mainPanel, BorderLayout.NORTH);
143 // Lower panel with ok and cancel buttons
144 JPanel buttonPanel = new JPanel();
145 buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
146 _okButton = new JButton(I18nManager.getText("button.ok"));
147 _okButton.addActionListener(new ActionListener() {
148 public void actionPerformed(ActionEvent e)
150 // start thread to call gpsbabel
152 new Thread(GpsLoader.this).start();
155 buttonPanel.add(_okButton);
156 JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
157 cancelButton.addActionListener(new ActionListener() {
158 public void actionPerformed(ActionEvent e)
164 buttonPanel.add(cancelButton);
165 outerPanel.add(buttonPanel, BorderLayout.SOUTH);
171 * @param inStart true if the dialog is restarting
173 private void setupProgressBar(boolean inStart)
176 _progressBar.setVisible(!inStart);
177 // set indeterminate flags, initial value
178 _progressBar.setIndeterminate(false);
179 _progressBar.setValue(0);
184 * Enable or disable the ok button
186 private void enableOkButton()
188 _okButton.setEnabled(_waypointCheckbox.isSelected() || _trackCheckbox.isSelected());
193 * Run method for performing tasks in separate thread
197 _okButton.setEnabled(false);
198 setupProgressBar(false);
199 if (_waypointCheckbox.isSelected() || _trackCheckbox.isSelected())
201 _progressBar.setIndeterminate(true);
204 callGpsBabel(_waypointCheckbox.isSelected(), _trackCheckbox.isSelected());
208 // System.err.println("Error: " + e.getClass().getName());
209 // System.err.println("Error: " + e.getMessage());
210 _app.showErrorMessageNoLookup(getNameKey(), e.getMessage());
214 setupProgressBar(true);
225 * Execute the call to gpsbabel and pass the results back to the app
226 * @param inWaypoints true to load waypoints
227 * @param inTracks true to load track points
229 private void callGpsBabel(boolean inWaypoints, boolean inTracks) throws Exception
231 // Set up command to call gpsbabel
232 String[] commands = null;
233 if (inWaypoints && inTracks) {
234 // Both waypoints and track points selected
235 commands = new String[] {"gpsbabel", "-w", "-t", "-i", _formatField.getText(),
236 "-f", _deviceField.getText(), "-o", "gpx", "-F", "-"};
240 // Only waypoints OR track points selected
241 commands = new String[] {"gpsbabel", "-w", "-i", _formatField.getText(),
242 "-f", _deviceField.getText(), "-o", "gpx", "-F", "-"};
248 String errorMessage = "";
249 XmlHandler handler = null;
250 Process process = Runtime.getRuntime().exec(commands);
252 // Pass input stream to try to parse the xml
255 XmlFileLoader xmlLoader = new XmlFileLoader(_app);
256 SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
257 saxParser.parse(process.getInputStream(), xmlLoader);
258 handler = xmlLoader.getHandler();
259 if (handler == null) {
260 errorMessage = "Null handler";
263 catch (Exception e) {
264 errorMessage = e.getMessage();
267 // Read the error stream to see if there's a better error message there
268 BufferedReader r = new BufferedReader(new InputStreamReader(process.getErrorStream()));
270 String errorMessage2 = "";
271 while ((line = r.readLine()) != null) {
272 errorMessage2 += line + "\n";
274 // Close error stream
277 } catch (Exception e) {}
279 if (errorMessage2.length() > 0) {errorMessage = errorMessage2;}
280 if (errorMessage.length() > 0) {throw new Exception(errorMessage);}
282 // Send data back to app
283 _app.informDataLoaded(handler.getFieldArray(), handler.getDataArray(),
284 Altitude.Format.METRES, _deviceField.getText());