package tim.prune.save; import java.awt.BorderLayout; import java.awt.Component; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JTextField; import javax.swing.SwingConstants; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import tim.prune.App; import tim.prune.ExternalTools; import tim.prune.GenericFunction; import tim.prune.I18nManager; import tim.prune.config.Config; /** * Class to manage the loading of GPS data using GpsBabel */ public class GpsSaver extends GenericFunction implements Runnable { private boolean _gpsBabelChecked = false; private JDialog _dialog = null; private JTextField _deviceField = null, _formatField = null; private JTextField _trackNameField = null; private JCheckBox _waypointCheckbox = null, _trackCheckbox = null; private boolean _switchedWaypointsOff = false, _switchedTrackpointsOff = false; private JButton _okButton = null; private JProgressBar _progressBar = null; private boolean _cancelled = false; /** * Constructor * @param inApp app object */ public GpsSaver(App inApp) { super(inApp); } /** get name key */ public String getNameKey() { return "function.sendtogps"; } /** * Open the GUI to select options and start the load */ public void begin() { // Check if gpsbabel looks like it's installed if (_gpsBabelChecked || ExternalTools.isToolInstalled(ExternalTools.TOOL_GPSBABEL) || JOptionPane.showConfirmDialog(_dialog, I18nManager.getText("dialog.gpsload.nogpsbabel"), I18nManager.getText(getNameKey()), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) { _gpsBabelChecked = true; // Make dialog window if (_dialog == null) { _dialog = new JDialog(_parentFrame, I18nManager.getText("function.sendtogps"), true); _dialog.setLocationRelativeTo(_parentFrame); _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); _dialog.getContentPane().add(makeDialogComponents()); _dialog.pack(); } // Initialise progress bars, buttons enableCheckboxes(); enableOkButton(); setupProgressBar(true); _trackNameField.requestFocus(); _dialog.setVisible(true); } } /** * @return a panel containing the main dialog components */ private JPanel makeDialogComponents() { JPanel outerPanel = new JPanel(); outerPanel.setLayout(new BorderLayout()); // Main panel with options etc JPanel mainPanel = new JPanel(); mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); // text fields for options JPanel gridPanel = new JPanel(); gridPanel.setLayout(new GridLayout(0, 2, 10, 3)); JLabel deviceLabel = new JLabel(I18nManager.getText("dialog.gpsload.device")); deviceLabel.setHorizontalAlignment(SwingConstants.RIGHT); gridPanel.add(deviceLabel); _deviceField = new JTextField(Config.getConfigString(Config.KEY_GPS_DEVICE), 12); gridPanel.add(_deviceField); JLabel formatLabel = new JLabel(I18nManager.getText("dialog.gpsload.format")); formatLabel.setHorizontalAlignment(SwingConstants.RIGHT); gridPanel.add(formatLabel); _formatField = new JTextField(Config.getConfigString(Config.KEY_GPS_FORMAT), 12); gridPanel.add(_formatField); JLabel nameLabel = new JLabel(I18nManager.getText("dialog.gpssend.trackname")); nameLabel.setHorizontalAlignment(SwingConstants.RIGHT); gridPanel.add(nameLabel); _trackNameField = new JTextField("", 12); gridPanel.add(_trackNameField); gridPanel.setAlignmentX(Component.CENTER_ALIGNMENT); gridPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 5, 20)); mainPanel.add(gridPanel); // close dialog when escape pressed KeyAdapter closer = new KeyAdapter() { public void keyReleased(KeyEvent e) { // close dialog if escape pressed if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { _dialog.dispose(); } } }; _deviceField.addKeyListener(closer); _formatField.addKeyListener(closer); _trackNameField.addKeyListener(closer); // checkboxes ChangeListener checkboxListener = new ChangeListener() { public void stateChanged(ChangeEvent e) { enableOkButton(); } }; _waypointCheckbox = new JCheckBox(I18nManager.getText("dialog.gpssend.sendwaypoints"), true); _waypointCheckbox.addChangeListener(checkboxListener); _waypointCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT); mainPanel.add(_waypointCheckbox); _trackCheckbox = new JCheckBox(I18nManager.getText("dialog.gpssend.sendtracks"), true); _trackCheckbox.addChangeListener(checkboxListener); _trackCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT); mainPanel.add(_trackCheckbox); // progress bar (initially invisible) _progressBar = new JProgressBar(0, 10); mainPanel.add(_progressBar); outerPanel.add(mainPanel, BorderLayout.NORTH); // Lower panel with ok and cancel buttons JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT)); _okButton = new JButton(I18nManager.getText("button.ok")); _okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // start thread to call gpsbabel _cancelled = false; new Thread(GpsSaver.this).start(); } }); buttonPanel.add(_okButton); JButton cancelButton = new JButton(I18nManager.getText("button.cancel")); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { _cancelled = true; _dialog.dispose(); } }); buttonPanel.add(cancelButton); outerPanel.add(buttonPanel, BorderLayout.SOUTH); return outerPanel; } /** * @param inStart true if the dialog is restarting */ private void setupProgressBar(boolean inStart) { // set visibility _progressBar.setVisible(!inStart); // set indeterminate flags, initial value _progressBar.setIndeterminate(false); _progressBar.setValue(0); } /** * Enable or disable the waypoints and trackpoints checkboxes */ private void enableCheckboxes() { // Enable or disable waypoints checkbox depending on whether data is available if (_waypointCheckbox.isSelected()) { if (!_app.getTrackInfo().getTrack().hasWaypoints()) { _waypointCheckbox.setSelected(false); _switchedWaypointsOff = true; } else _switchedWaypointsOff = false; } else if (_app.getTrackInfo().getTrack().hasWaypoints() && _switchedWaypointsOff) { _waypointCheckbox.setSelected(true); _switchedWaypointsOff = false; } // ... and the same for track points if (_trackCheckbox.isSelected()) { if (!_app.getTrackInfo().getTrack().hasTrackPoints()) { _trackCheckbox.setSelected(false); _switchedTrackpointsOff = true; } else _switchedTrackpointsOff = false; } else if (_app.getTrackInfo().getTrack().hasTrackPoints() && _switchedTrackpointsOff) { _trackCheckbox.setSelected(true); _switchedTrackpointsOff = false; } } /** * Enable or disable the ok button */ private void enableOkButton() { _okButton.setEnabled(_waypointCheckbox.isSelected() || _trackCheckbox.isSelected()); } /** * Run method for performing tasks in separate thread */ public void run() { _okButton.setEnabled(false); setupProgressBar(false); _progressBar.setIndeterminate(true); try { callGpsBabel(); } catch (Exception e) { JOptionPane.showMessageDialog(_dialog, e.getMessage(), I18nManager.getText("function.sendtogps"), JOptionPane.ERROR_MESSAGE); _cancelled = true; } setupProgressBar(true); enableOkButton(); // Close dialog if (!_cancelled) { _dialog.dispose(); } } /** * Execute the call to gpsbabel */ private void callGpsBabel() throws Exception { // Set up command to call gpsbabel final String command = Config.getConfigString(Config.KEY_GPSBABEL_PATH); String[] commands = null; final String device = _deviceField.getText().trim(); final String format = _formatField.getText().trim(); if (_waypointCheckbox.isSelected() && _trackCheckbox.isSelected()) { // Both waypoints and track points selected commands = new String[] {command, "-w", "-t", "-i", "gpx", "-f", "-", "-o", format, "-F", device}; } else { // Only waypoints OR trackpoints selected commands = new String[] {command, "-w", "-i", "gpx", "-f", "-", "-o", format, "-F", device}; if (_trackCheckbox.isSelected()) { commands[1] = "-t"; } } // Save GPS settings in config Config.setConfigString(Config.KEY_GPS_DEVICE, device); Config.setConfigString(Config.KEY_GPS_FORMAT, format); String errorMessage = ""; Process process = Runtime.getRuntime().exec(commands); String trackName = _trackNameField.getText(); if (trackName == null || trackName.equals("")) {trackName = "gpsprune";} // Generate the GPX file and send to the GPS OutputStreamWriter writer = new OutputStreamWriter(process.getOutputStream()); boolean[] saveFlags = {true, true, true, true, false, true}; // export everything GpxExporter.exportData(writer, _app.getTrackInfo(), trackName, null, saveFlags, null); writer.close(); // Read the error stream to see if there's a better error message there BufferedReader r = new BufferedReader(new InputStreamReader(process.getErrorStream())); String line = null; String errorMessage2 = ""; while ((line = r.readLine()) != null) { errorMessage2 += line + "\n"; } // Close error stream try { r.close(); } catch (Exception e) {} if (errorMessage2.length() > 0) {errorMessage = errorMessage2;} if (errorMessage.length() > 0) {throw new Exception(errorMessage);} } }