1 package tim.prune.save;
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.awt.event.KeyAdapter;
10 import java.awt.event.KeyEvent;
11 import java.io.BufferedReader;
12 import java.io.InputStreamReader;
13 import java.io.OutputStreamWriter;
15 import javax.swing.BorderFactory;
16 import javax.swing.BoxLayout;
17 import javax.swing.JButton;
18 import javax.swing.JCheckBox;
19 import javax.swing.JDialog;
20 import javax.swing.JLabel;
21 import javax.swing.JOptionPane;
22 import javax.swing.JPanel;
23 import javax.swing.JProgressBar;
24 import javax.swing.JTextField;
25 import javax.swing.SwingConstants;
26 import javax.swing.event.ChangeEvent;
27 import javax.swing.event.ChangeListener;
30 import tim.prune.ExternalTools;
31 import tim.prune.GenericFunction;
32 import tim.prune.I18nManager;
33 import tim.prune.config.Config;
36 * Class to manage the loading of GPS data using GpsBabel
38 public class GpsSaver extends GenericFunction implements Runnable
40 private boolean _gpsBabelChecked = false;
41 private JDialog _dialog = null;
42 private JTextField _deviceField = null, _formatField = null;
43 private JTextField _trackNameField = null;
44 private JCheckBox _waypointCheckbox = null, _trackCheckbox = null;
45 private boolean _switchedWaypointsOff = false, _switchedTrackpointsOff = false;
46 private JButton _okButton = null;
47 private JProgressBar _progressBar = null;
48 private boolean _cancelled = false;
53 * @param inApp app object
55 public GpsSaver(App inApp)
61 public String getNameKey() {
62 return "function.sendtogps";
66 * Open the GUI to select options and start the load
70 // Check if gpsbabel looks like it's installed
71 if (_gpsBabelChecked || ExternalTools.isToolInstalled(ExternalTools.TOOL_GPSBABEL)
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("function.sendtogps"), true);
82 _dialog.setLocationRelativeTo(_parentFrame);
83 _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
84 _dialog.getContentPane().add(makeDialogComponents());
87 // Initialise progress bars, buttons
90 setupProgressBar(true);
91 _trackNameField.requestFocus();
92 _dialog.setVisible(true);
98 * @return a panel containing the main dialog components
100 private JPanel makeDialogComponents()
102 JPanel outerPanel = new JPanel();
103 outerPanel.setLayout(new BorderLayout());
104 // Main panel with options etc
105 JPanel mainPanel = new JPanel();
106 mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
108 // text fields for options
109 JPanel gridPanel = new JPanel();
110 gridPanel.setLayout(new GridLayout(0, 2, 10, 3));
111 JLabel deviceLabel = new JLabel(I18nManager.getText("dialog.gpsload.device"));
112 deviceLabel.setHorizontalAlignment(SwingConstants.RIGHT);
113 gridPanel.add(deviceLabel);
114 _deviceField = new JTextField(Config.getConfigString(Config.KEY_GPS_DEVICE), 12);
115 gridPanel.add(_deviceField);
116 JLabel formatLabel = new JLabel(I18nManager.getText("dialog.gpsload.format"));
117 formatLabel.setHorizontalAlignment(SwingConstants.RIGHT);
118 gridPanel.add(formatLabel);
119 _formatField = new JTextField(Config.getConfigString(Config.KEY_GPS_FORMAT), 12);
120 gridPanel.add(_formatField);
121 JLabel nameLabel = new JLabel(I18nManager.getText("dialog.gpssend.trackname"));
122 nameLabel.setHorizontalAlignment(SwingConstants.RIGHT);
123 gridPanel.add(nameLabel);
124 _trackNameField = new JTextField("", 12);
125 gridPanel.add(_trackNameField);
126 gridPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
127 gridPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 5, 20));
128 mainPanel.add(gridPanel);
129 // close dialog when escape pressed
130 KeyAdapter closer = new KeyAdapter() {
131 public void keyReleased(KeyEvent e)
133 // close dialog if escape pressed
134 if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
139 _deviceField.addKeyListener(closer);
140 _formatField.addKeyListener(closer);
141 _trackNameField.addKeyListener(closer);
144 ChangeListener checkboxListener = new ChangeListener() {
145 public void stateChanged(ChangeEvent e)
150 _waypointCheckbox = new JCheckBox(I18nManager.getText("dialog.gpssend.sendwaypoints"), true);
151 _waypointCheckbox.addChangeListener(checkboxListener);
152 _waypointCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT);
153 mainPanel.add(_waypointCheckbox);
154 _trackCheckbox = new JCheckBox(I18nManager.getText("dialog.gpssend.sendtracks"), true);
155 _trackCheckbox.addChangeListener(checkboxListener);
156 _trackCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT);
157 mainPanel.add(_trackCheckbox);
159 // progress bar (initially invisible)
160 _progressBar = new JProgressBar(0, 10);
161 mainPanel.add(_progressBar);
162 outerPanel.add(mainPanel, BorderLayout.NORTH);
164 // Lower panel with ok and cancel buttons
165 JPanel buttonPanel = new JPanel();
166 buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
167 _okButton = new JButton(I18nManager.getText("button.ok"));
168 _okButton.addActionListener(new ActionListener() {
169 public void actionPerformed(ActionEvent e)
171 // start thread to call gpsbabel
173 new Thread(GpsSaver.this).start();
176 buttonPanel.add(_okButton);
177 JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
178 cancelButton.addActionListener(new ActionListener() {
179 public void actionPerformed(ActionEvent e)
185 buttonPanel.add(cancelButton);
186 outerPanel.add(buttonPanel, BorderLayout.SOUTH);
192 * @param inStart true if the dialog is restarting
194 private void setupProgressBar(boolean inStart)
197 _progressBar.setVisible(!inStart);
198 // set indeterminate flags, initial value
199 _progressBar.setIndeterminate(false);
200 _progressBar.setValue(0);
204 * Enable or disable the waypoints and trackpoints checkboxes
206 private void enableCheckboxes()
208 // Enable or disable waypoints checkbox depending on whether data is available
209 if (_waypointCheckbox.isSelected())
211 if (!_app.getTrackInfo().getTrack().hasWaypoints())
213 _waypointCheckbox.setSelected(false);
214 _switchedWaypointsOff = true;
216 else _switchedWaypointsOff = false;
218 else if (_app.getTrackInfo().getTrack().hasWaypoints() && _switchedWaypointsOff)
220 _waypointCheckbox.setSelected(true);
221 _switchedWaypointsOff = false;
223 // ... and the same for track points
224 if (_trackCheckbox.isSelected())
226 if (!_app.getTrackInfo().getTrack().hasTrackPoints())
228 _trackCheckbox.setSelected(false);
229 _switchedTrackpointsOff = true;
231 else _switchedTrackpointsOff = false;
233 else if (_app.getTrackInfo().getTrack().hasTrackPoints() && _switchedTrackpointsOff)
235 _trackCheckbox.setSelected(true);
236 _switchedTrackpointsOff = false;
241 * Enable or disable the ok button
243 private void enableOkButton()
245 _okButton.setEnabled(_waypointCheckbox.isSelected() || _trackCheckbox.isSelected());
250 * Run method for performing tasks in separate thread
254 _okButton.setEnabled(false);
255 setupProgressBar(false);
257 _progressBar.setIndeterminate(true);
264 JOptionPane.showMessageDialog(_dialog, e.getMessage(),
265 I18nManager.getText("function.sendtogps"), JOptionPane.ERROR_MESSAGE);
269 setupProgressBar(true);
280 * Execute the call to gpsbabel
282 private void callGpsBabel() throws Exception
284 // Set up command to call gpsbabel
285 final String command = Config.getConfigString(Config.KEY_GPSBABEL_PATH);
286 String[] commands = null;
287 final String device = _deviceField.getText().trim();
288 final String format = _formatField.getText().trim();
289 if (_waypointCheckbox.isSelected() && _trackCheckbox.isSelected()) {
290 // Both waypoints and track points selected
291 commands = new String[] {command, "-w", "-t", "-i", "gpx", "-f", "-", "-o", format,
296 // Only waypoints OR trackpoints selected
297 commands = new String[] {command, "-w", "-i", "gpx", "-f", "-", "-o", format,
299 if (_trackCheckbox.isSelected()) {
303 // Save GPS settings in config
304 Config.setConfigString(Config.KEY_GPS_DEVICE, device);
305 Config.setConfigString(Config.KEY_GPS_FORMAT, format);
307 String errorMessage = "";
308 Process process = Runtime.getRuntime().exec(commands);
310 String trackName = _trackNameField.getText();
311 if (trackName == null || trackName.equals("")) {trackName = "gpsprune";}
312 // Generate the GPX file and send to the GPS
313 OutputStreamWriter writer = new OutputStreamWriter(process.getOutputStream());
314 SettingsForExport settings = new SettingsForExport();
315 settings.setExportMissingAltitudesAsZero(true);
316 GpxExporter.exportData(writer, _app.getTrackInfo(), trackName, null, settings, null);
319 // Read the error stream to see if there's a better error message there
320 BufferedReader r = new BufferedReader(new InputStreamReader(process.getErrorStream()));
322 String errorMessage2 = "";
323 while ((line = r.readLine()) != null) {
324 errorMessage2 += line + "\n";
326 // Close error stream
329 } catch (Exception e) {}
330 if (errorMessage2.length() > 0) {errorMessage = errorMessage2;}
331 if (errorMessage.length() > 0) {throw new Exception(errorMessage);}