]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/save/GpsSaver.java
Version 14, October 2012
[GpsPrune.git] / tim / prune / save / GpsSaver.java
1 package tim.prune.save;
2
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;
14
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;
28
29 import tim.prune.App;
30 import tim.prune.ExternalTools;
31 import tim.prune.GenericFunction;
32 import tim.prune.I18nManager;
33 import tim.prune.config.Config;
34
35 /**
36  * Class to manage the loading of GPS data using GpsBabel
37  */
38 public class GpsSaver extends GenericFunction implements Runnable
39 {
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 JButton _okButton = null;
46         private JProgressBar _progressBar = null;
47         private boolean _cancelled = false;
48
49
50         /**
51          * Constructor
52          * @param inApp app object
53          */
54         public GpsSaver(App inApp)
55         {
56                 super(inApp);
57         }
58
59         /** get name key */
60         public String getNameKey() {
61                 return "function.sendtogps";
62         }
63
64         /**
65          * Open the GUI to select options and start the load
66          */
67         public void begin()
68         {
69                 // Check if gpsbabel looks like it's installed
70                 if (_gpsBabelChecked || ExternalTools.isToolInstalled(ExternalTools.TOOL_GPSBABEL)
71                         || JOptionPane.showConfirmDialog(_dialog,
72                                 I18nManager.getText("dialog.gpsload.nogpsbabel"),
73                                 I18nManager.getText(getNameKey()),
74                                 JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION)
75                 {
76                         _gpsBabelChecked = true;
77                         // Make dialog window
78                         if (_dialog == null)
79                         {
80                                 _dialog = new JDialog(_parentFrame, I18nManager.getText("function.sendtogps"), true);
81                                 _dialog.setLocationRelativeTo(_parentFrame);
82                                 _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
83                                 _dialog.getContentPane().add(makeDialogComponents());
84                                 _dialog.pack();
85                         }
86                         // Initialise progress bars, buttons
87                         enableOkButton();
88                         setupProgressBar(true);
89                         _dialog.setVisible(true);
90                 }
91         }
92
93
94         /**
95          * @return a panel containing the main dialog components
96          */
97         private JPanel makeDialogComponents()
98         {
99                 JPanel outerPanel = new JPanel();
100                 outerPanel.setLayout(new BorderLayout());
101                 // Main panel with options etc
102                 JPanel mainPanel = new JPanel();
103                 mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
104
105                 // text fields for options
106                 JPanel gridPanel = new JPanel();
107                 gridPanel.setLayout(new GridLayout(0, 2, 10, 3));
108                 JLabel deviceLabel = new JLabel(I18nManager.getText("dialog.gpsload.device"));
109                 deviceLabel.setHorizontalAlignment(SwingConstants.RIGHT);
110                 gridPanel.add(deviceLabel);
111                 _deviceField = new JTextField(Config.getConfigString(Config.KEY_GPS_DEVICE), 12);
112                 gridPanel.add(_deviceField);
113                 JLabel formatLabel = new JLabel(I18nManager.getText("dialog.gpsload.format"));
114                 formatLabel.setHorizontalAlignment(SwingConstants.RIGHT);
115                 gridPanel.add(formatLabel);
116                 _formatField = new JTextField(Config.getConfigString(Config.KEY_GPS_FORMAT), 12);
117                 gridPanel.add(_formatField);
118                 JLabel nameLabel = new JLabel(I18nManager.getText("dialog.gpssend.trackname"));
119                 nameLabel.setHorizontalAlignment(SwingConstants.RIGHT);
120                 gridPanel.add(nameLabel);
121                 _trackNameField = new JTextField("", 12);
122                 gridPanel.add(_trackNameField);
123                 gridPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
124                 gridPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 5, 20));
125                 mainPanel.add(gridPanel);
126                 // close dialog when escape pressed
127                 KeyAdapter closer = new KeyAdapter() {
128                         public void keyReleased(KeyEvent e)
129                         {
130                                 // close dialog if escape pressed
131                                 if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
132                                         _dialog.dispose();
133                                 }
134                         }
135                 };
136                 _deviceField.addKeyListener(closer);
137                 _formatField.addKeyListener(closer);
138                 _trackNameField.addKeyListener(closer);
139
140                 // checkboxes
141                 ChangeListener checkboxListener = new ChangeListener() {
142                         public void stateChanged(ChangeEvent e)
143                         {
144                                 enableOkButton();
145                         }
146                 };
147                 _waypointCheckbox = new JCheckBox(I18nManager.getText("dialog.gpssend.sendwaypoints"), true);
148                 _waypointCheckbox.addChangeListener(checkboxListener);
149                 _waypointCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT);
150                 mainPanel.add(_waypointCheckbox);
151                 _trackCheckbox = new JCheckBox(I18nManager.getText("dialog.gpssend.sendtracks"), true);
152                 _trackCheckbox.addChangeListener(checkboxListener);
153                 _trackCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT);
154                 mainPanel.add(_trackCheckbox);
155
156                 // progress bar (initially invisible)
157                 _progressBar = new JProgressBar(0, 10);
158                 mainPanel.add(_progressBar);
159                 outerPanel.add(mainPanel, BorderLayout.NORTH);
160
161                 // Lower panel with ok and cancel buttons
162                 JPanel buttonPanel = new JPanel();
163                 buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
164                 _okButton = new JButton(I18nManager.getText("button.ok"));
165                 _okButton.addActionListener(new ActionListener() {
166                         public void actionPerformed(ActionEvent e)
167                         {
168                                 // start thread to call gpsbabel
169                                 _cancelled = false;
170                                 new Thread(GpsSaver.this).start();
171                         }
172                 });
173                 buttonPanel.add(_okButton);
174                 JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
175                 cancelButton.addActionListener(new ActionListener() {
176                         public void actionPerformed(ActionEvent e)
177                         {
178                                 _cancelled = true;
179                                 _dialog.dispose();
180                         }
181                 });
182                 buttonPanel.add(cancelButton);
183                 outerPanel.add(buttonPanel, BorderLayout.SOUTH);
184                 return outerPanel;
185         }
186
187
188         /**
189          * @param inStart true if the dialog is restarting
190          */
191         private void setupProgressBar(boolean inStart)
192         {
193                 // set visibility
194                 _progressBar.setVisible(!inStart);
195                 // set indeterminate flags, initial value
196                 _progressBar.setIndeterminate(false);
197                 _progressBar.setValue(0);
198         }
199
200
201         /**
202          * Enable or disable the ok button
203          */
204         private void enableOkButton()
205         {
206                 _okButton.setEnabled(_waypointCheckbox.isSelected() || _trackCheckbox.isSelected());
207         }
208
209
210         /**
211          * Run method for performing tasks in separate thread
212          */
213         public void run()
214         {
215                 _okButton.setEnabled(false);
216                 setupProgressBar(false);
217
218                 _progressBar.setIndeterminate(true);
219                 try
220                 {
221                         callGpsBabel();
222                 }
223                 catch (Exception e)
224                 {
225                         JOptionPane.showMessageDialog(_dialog, e.getMessage(),
226                                 I18nManager.getText("function.sendtogps"), JOptionPane.ERROR_MESSAGE);
227                         _cancelled = true;
228                 }
229
230                 setupProgressBar(true);
231                 enableOkButton();
232
233                 // Close dialog
234                 if (!_cancelled) {
235                         _dialog.dispose();
236                 }
237         }
238
239
240         /**
241          * Execute the call to gpsbabel
242          */
243         private void callGpsBabel() throws Exception
244         {
245                 // Set up command to call gpsbabel
246                 final String command = Config.getConfigString(Config.KEY_GPSBABEL_PATH);
247                 String[] commands = null;
248                 final String device = _deviceField.getText().trim();
249                 final String format = _formatField.getText().trim();
250                 if (_waypointCheckbox.isSelected() && _trackCheckbox.isSelected()) {
251                         // Both waypoints and track points selected
252                         commands = new String[] {command, "-w", "-t", "-i", "gpx", "-f", "-", "-o", format,
253                                 "-F", device};
254                 }
255                 else
256                 {
257                         // Only waypoints OR trackpoints selected
258                         commands = new String[] {command, "-w", "-i", "gpx", "-f", "-", "-o", format,
259                                 "-F", device};
260                         if (_trackCheckbox.isSelected()) {
261                                 commands[1] = "-t";
262                         }
263                 }
264                 // Save GPS settings in config
265                 Config.setConfigString(Config.KEY_GPS_DEVICE, device);
266                 Config.setConfigString(Config.KEY_GPS_FORMAT, format);
267
268                 String errorMessage = "";
269                 Process process = Runtime.getRuntime().exec(commands);
270
271                 String trackName = _trackNameField.getText();
272                 if (trackName == null || trackName.equals("")) {trackName = "prune";}
273                 // Generate the GPX file and send to the GPS
274                 OutputStreamWriter writer = new OutputStreamWriter(process.getOutputStream());
275                 boolean[] saveFlags = {true, true, true, true, false, true}; // export everything
276                 GpxExporter.exportData(writer, _app.getTrackInfo(), trackName, null, saveFlags, null);
277                 writer.close();
278
279                 // Read the error stream to see if there's a better error message there
280                 BufferedReader r = new BufferedReader(new InputStreamReader(process.getErrorStream()));
281                 String line = null;
282                 String errorMessage2 = "";
283                 while ((line = r.readLine()) != null) {
284                         errorMessage2 += line + "\n";
285                 }
286                 // Close error stream
287                 try {
288                         r.close();
289                 } catch (Exception e) {}
290                 if (errorMessage2.length() > 0) {errorMessage = errorMessage2;}
291                 if (errorMessage.length() > 0) {throw new Exception(errorMessage);}
292         }
293 }