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.JFrame;
18 import javax.swing.JLabel;
19 import javax.swing.JOptionPane;
20 import javax.swing.JPanel;
21 import javax.swing.JProgressBar;
22 import javax.swing.JTextField;
23 import javax.swing.SwingConstants;
24 import javax.swing.event.ChangeEvent;
25 import javax.swing.event.ChangeListener;
26 import javax.xml.parsers.SAXParser;
27 import javax.xml.parsers.SAXParserFactory;
30 import tim.prune.Config;
31 import tim.prune.ExternalTools;
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 implements Runnable
42 private App _app = null;
43 private JFrame _parentFrame = null;
44 private boolean _gpsBabelChecked = false;
45 private JDialog _dialog = null;
46 private JTextField _deviceField = null, _formatField = null;
47 private JCheckBox _waypointCheckbox = null, _trackCheckbox = null;
48 private JButton _okButton = null;
49 private JProgressBar _waypointProgressBar = null, _trackProgressBar = null;
50 private boolean _cancelled = false;
55 * @param inApp Application object to inform of data load
56 * @param inParentFrame parent frame to reference for dialogs
58 public GpsLoader(App inApp, JFrame inParentFrame)
61 _parentFrame = inParentFrame;
66 * Open the GUI to select options and start the load
68 public void openDialog()
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("dialog.gpsload.title"),
75 JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION)
77 _gpsBabelChecked = true;
81 _dialog = new JDialog(_parentFrame, I18nManager.getText("dialog.gpsload.title"), true);
82 _dialog.setLocationRelativeTo(_parentFrame);
83 _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
84 _dialog.getContentPane().add(makeDialogComponents());
87 // Initialise progress bars, buttons
89 setupProgressBars(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 bars (initially invisible)
139 _waypointProgressBar = new JProgressBar(0, 10);
140 mainPanel.add(_waypointProgressBar);
141 _trackProgressBar = new JProgressBar(0, 10);
142 mainPanel.add(_trackProgressBar);
143 outerPanel.add(mainPanel, BorderLayout.NORTH);
145 // Lower panel with ok and cancel buttons
146 JPanel buttonPanel = new JPanel();
147 buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
148 _okButton = new JButton(I18nManager.getText("button.ok"));
149 _okButton.addActionListener(new ActionListener() {
150 public void actionPerformed(ActionEvent e)
152 // start thread to call gpsbabel
154 new Thread(GpsLoader.this).start();
157 buttonPanel.add(_okButton);
158 JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
159 cancelButton.addActionListener(new ActionListener() {
160 public void actionPerformed(ActionEvent e)
166 buttonPanel.add(cancelButton);
167 outerPanel.add(buttonPanel, BorderLayout.SOUTH);
173 * @param inStart true if the dialog is restarting
175 private void setupProgressBars(boolean inStart)
178 _waypointProgressBar.setVisible(!inStart && _waypointCheckbox.isSelected());
179 _trackProgressBar.setVisible(!inStart && _trackCheckbox.isSelected());
180 // set indeterminate flags, initial value
181 _waypointProgressBar.setIndeterminate(false);
182 _waypointProgressBar.setValue(0);
183 _trackProgressBar.setIndeterminate(false);
184 _trackProgressBar.setValue(0);
189 * Enable or disable the ok button
191 private void enableOkButton()
193 _okButton.setEnabled(_waypointCheckbox.isSelected() || _trackCheckbox.isSelected());
198 * Run method for performing tasks in separate thread
202 _okButton.setEnabled(false);
203 setupProgressBars(false);
204 if (_waypointCheckbox.isSelected())
206 _waypointProgressBar.setIndeterminate(true);
207 _trackProgressBar.setIndeterminate(false);
214 JOptionPane.showMessageDialog(_dialog, e.getMessage(),
215 I18nManager.getText("dialog.gpsload.title"), JOptionPane.ERROR_MESSAGE);
219 // Exit if cancelled or failed
221 setupProgressBars(true);
225 if (_trackCheckbox.isSelected())
227 _waypointProgressBar.setIndeterminate(false);
228 _waypointProgressBar.setValue(10);
229 _trackProgressBar.setIndeterminate(true);
236 JOptionPane.showMessageDialog(_dialog, e.getMessage(),
237 I18nManager.getText("dialog.gpsload.title"), JOptionPane.ERROR_MESSAGE);
241 setupProgressBars(true);
252 * Execute the call to gpsbabel and pass the results back to the app
253 * @param inWaypoints true to get waypoints, false to get track data
255 private void callGpsBabel(boolean inWaypoints) throws Exception
257 // Set up command to call gpsbabel
258 String[] commands = {"gpsbabel", null, "-i", _formatField.getText(), "-f", _deviceField.getText(), "-o", "gpx", "-F", "-"};
259 commands[1] = inWaypoints?"-w":"-t";
261 String errorMessage = "";
262 XmlHandler handler = null;
263 Process process = Runtime.getRuntime().exec(commands);
265 // Pass input stream to try to parse the xml
268 XmlFileLoader xmlLoader = new XmlFileLoader(_app, _parentFrame);
269 SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
270 saxParser.parse(process.getInputStream(), xmlLoader);
271 handler = xmlLoader.getHandler();
272 if (handler == null) {
273 errorMessage = "Null handler";
276 catch (Exception e) {
277 errorMessage = e.getMessage();
280 // Read the error stream to see if there's a better error message there
281 BufferedReader r = new BufferedReader(new InputStreamReader(process.getErrorStream()));
283 String errorMessage2 = "";
284 while ((line = r.readLine()) != null) {
285 errorMessage2 += line + "\n";
287 if (errorMessage2.length() > 0) {errorMessage = errorMessage2;}
288 if (errorMessage.length() > 0) {throw new Exception(errorMessage);}
290 // Send data back to app
291 boolean append = _waypointCheckbox.isSelected() && !inWaypoints;
292 _app.informDataLoaded(handler.getFieldArray(), handler.getDataArray(),
293 Altitude.FORMAT_METRES, _deviceField.getText(), append);