]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - src/tim/prune/save/GpsSaver.java
Moved source into separate src directory due to popular request
[GpsPrune.git] / src / tim / prune / save / GpsSaver.java
diff --git a/src/tim/prune/save/GpsSaver.java b/src/tim/prune/save/GpsSaver.java
new file mode 100644 (file)
index 0000000..6179a5c
--- /dev/null
@@ -0,0 +1,333 @@
+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());
+               SettingsForExport settings = new SettingsForExport();
+               settings.setExportMissingAltitudesAsZero(true);
+               GpxExporter.exportData(writer, _app.getTrackInfo(), trackName, null, settings, 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);}
+       }
+}