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.io.BufferedReader;
10 import java.io.InputStreamReader;
11 import java.io.OutputStreamWriter;
13 import javax.swing.BorderFactory;
14 import javax.swing.BoxLayout;
15 import javax.swing.JButton;
16 import javax.swing.JCheckBox;
17 import javax.swing.JDialog;
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;
28 import tim.prune.ExternalTools;
29 import tim.prune.GenericFunction;
30 import tim.prune.I18nManager;
31 import tim.prune.config.Config;
34 * Class to manage the loading of GPS data using GpsBabel
36 public class GpsSaver extends GenericFunction implements Runnable
38 private boolean _gpsBabelChecked = false;
39 private JDialog _dialog = null;
40 private JTextField _deviceField = null, _formatField = null;
41 private JTextField _trackNameField = null;
42 private JCheckBox _waypointCheckbox = null, _trackCheckbox = null;
43 private JButton _okButton = null;
44 private JProgressBar _progressBar = null;
45 private boolean _cancelled = false;
50 * @param inApp app object
52 public GpsSaver(App inApp)
58 public String getNameKey() {
59 return "function.sendtogps";
63 * Open the GUI to select options and start the load
67 // Check if gpsbabel looks like it's installed
68 if (_gpsBabelChecked || ExternalTools.isToolInstalled(ExternalTools.TOOL_GPSBABEL)
69 || JOptionPane.showConfirmDialog(_dialog,
70 I18nManager.getText("dialog.gpsload.nogpsbabel"),
71 I18nManager.getText(getNameKey()),
72 JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION)
74 _gpsBabelChecked = true;
78 _dialog = new JDialog(_parentFrame, I18nManager.getText("function.sendtogps"), true);
79 _dialog.setLocationRelativeTo(_parentFrame);
80 _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
81 _dialog.getContentPane().add(makeDialogComponents());
84 // Initialise progress bars, buttons
86 setupProgressBar(true);
87 _dialog.setVisible(true);
93 * @return a panel containing the main dialog components
95 private JPanel makeDialogComponents()
97 JPanel outerPanel = new JPanel();
98 outerPanel.setLayout(new BorderLayout());
99 // Main panel with options etc
100 JPanel mainPanel = new JPanel();
101 mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
103 // text fields for options
104 JPanel gridPanel = new JPanel();
105 gridPanel.setLayout(new GridLayout(0, 2, 10, 3));
106 JLabel deviceLabel = new JLabel(I18nManager.getText("dialog.gpsload.device"));
107 deviceLabel.setHorizontalAlignment(SwingConstants.RIGHT);
108 gridPanel.add(deviceLabel);
109 _deviceField = new JTextField(Config.getConfigString(Config.KEY_GPS_DEVICE), 12);
110 gridPanel.add(_deviceField);
111 JLabel formatLabel = new JLabel(I18nManager.getText("dialog.gpsload.format"));
112 formatLabel.setHorizontalAlignment(SwingConstants.RIGHT);
113 gridPanel.add(formatLabel);
114 _formatField = new JTextField(Config.getConfigString(Config.KEY_GPS_FORMAT), 12);
115 gridPanel.add(_formatField);
116 JLabel nameLabel = new JLabel(I18nManager.getText("dialog.gpssend.trackname"));
117 nameLabel.setHorizontalAlignment(SwingConstants.RIGHT);
118 gridPanel.add(nameLabel);
119 _trackNameField = new JTextField("", 12);
120 gridPanel.add(_trackNameField);
121 gridPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
122 gridPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 5, 20));
123 mainPanel.add(gridPanel);
126 ChangeListener checkboxListener = new ChangeListener() {
127 public void stateChanged(ChangeEvent e)
132 _waypointCheckbox = new JCheckBox(I18nManager.getText("dialog.gpssend.sendwaypoints"), true);
133 _waypointCheckbox.addChangeListener(checkboxListener);
134 _waypointCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT);
135 mainPanel.add(_waypointCheckbox);
136 _trackCheckbox = new JCheckBox(I18nManager.getText("dialog.gpssend.sendtracks"), true);
137 _trackCheckbox.addChangeListener(checkboxListener);
138 _trackCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT);
139 mainPanel.add(_trackCheckbox);
141 // progress bar (initially invisible)
142 _progressBar = new JProgressBar(0, 10);
143 mainPanel.add(_progressBar);
144 outerPanel.add(mainPanel, BorderLayout.NORTH);
146 // Lower panel with ok and cancel buttons
147 JPanel buttonPanel = new JPanel();
148 buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
149 _okButton = new JButton(I18nManager.getText("button.ok"));
150 _okButton.addActionListener(new ActionListener() {
151 public void actionPerformed(ActionEvent e)
153 // start thread to call gpsbabel
155 new Thread(GpsSaver.this).start();
158 buttonPanel.add(_okButton);
159 JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
160 cancelButton.addActionListener(new ActionListener() {
161 public void actionPerformed(ActionEvent e)
167 buttonPanel.add(cancelButton);
168 outerPanel.add(buttonPanel, BorderLayout.SOUTH);
174 * @param inStart true if the dialog is restarting
176 private void setupProgressBar(boolean inStart)
179 _progressBar.setVisible(!inStart);
180 // set indeterminate flags, initial value
181 _progressBar.setIndeterminate(false);
182 _progressBar.setValue(0);
187 * Enable or disable the ok button
189 private void enableOkButton()
191 _okButton.setEnabled(_waypointCheckbox.isSelected() || _trackCheckbox.isSelected());
196 * Run method for performing tasks in separate thread
200 _okButton.setEnabled(false);
201 setupProgressBar(false);
203 _progressBar.setIndeterminate(true);
210 JOptionPane.showMessageDialog(_dialog, e.getMessage(),
211 I18nManager.getText("function.sendtogps"), JOptionPane.ERROR_MESSAGE);
215 setupProgressBar(true);
226 * Execute the call to gpsbabel
228 private void callGpsBabel() throws Exception
230 // Set up command to call gpsbabel
231 final String command = Config.getConfigString(Config.KEY_GPSBABEL_PATH);
232 String[] commands = null;
233 final String device = _deviceField.getText().trim();
234 final String format = _formatField.getText().trim();
235 if (_waypointCheckbox.isSelected() && _trackCheckbox.isSelected()) {
236 // Both waypoints and track points selected
237 commands = new String[] {command, "-w", "-t", "-i", "gpx", "-f", "-", "-o", format,
242 // Only waypoints OR trackpoints selected
243 commands = new String[] {command, "-w", "-i", "gpx", "-f", "-", "-o", format,
245 if (_trackCheckbox.isSelected()) {
249 // Save GPS settings in config
250 Config.setConfigString(Config.KEY_GPS_DEVICE, device);
251 Config.setConfigString(Config.KEY_GPS_FORMAT, format);
253 String errorMessage = "";
254 Process process = Runtime.getRuntime().exec(commands);
256 String trackName = _trackNameField.getText();
257 if (trackName == null || trackName.equals("")) {trackName = "prune";}
258 // Generate the GPX file and send to the GPS
259 OutputStreamWriter writer = new OutputStreamWriter(process.getOutputStream());
260 boolean[] saveFlags = {true, true, true, false, true}; // export everything
261 GpxExporter.exportData(writer, _app.getTrackInfo(), trackName, null, saveFlags, false);
264 // Read the error stream to see if there's a better error message there
265 BufferedReader r = new BufferedReader(new InputStreamReader(process.getErrorStream()));
267 String errorMessage2 = "";
268 while ((line = r.readLine()) != null) {
269 errorMessage2 += line + "\n";
271 // Close error stream
274 } catch (Exception e) {}
275 if (errorMessage2.length() > 0) {errorMessage = errorMessage2;}
276 if (errorMessage.length() > 0) {throw new Exception(errorMessage);}