micropeak is code complete now.
authorKeith Packard <keithp@keithp.com>
Tue, 1 Jan 2013 23:30:11 +0000 (15:30 -0800)
committerKeith Packard <keithp@keithp.com>
Tue, 1 Jan 2013 23:30:11 +0000 (15:30 -0800)
Added save and download functionality. Removed 'new' from file menu.

Signed-off-by: Keith Packard <keithp@keithp.com>
15 files changed:
altoslib/AltosLib.java
altosuilib/AltosDevice.java [new file with mode: 0644]
altosuilib/AltosDeviceDialog.java [new file with mode: 0644]
altosuilib/AltosUSBDevice.java [new file with mode: 0644]
altosuilib/Makefile.am
libaltos/libaltos.c
micropeak/Makefile.am
micropeak/MicroData.java
micropeak/MicroDeviceDialog.java [new file with mode: 0644]
micropeak/MicroDownload.java [new file with mode: 0644]
micropeak/MicroGraph.java
micropeak/MicroPeak.java
micropeak/MicroSave.java [new file with mode: 0644]
micropeak/MicroSerial.java
micropeak/MicroUSB.java

index 07516aebd389fe3af4fcac245ffb42fa25ef8b1c..6713845013e9299ec24bc1db3ad65324455db00f 100644 (file)
@@ -97,6 +97,7 @@ public class AltosLib {
        public final static int product_any = 0x10000;
        public final static int product_basestation = 0x10000 + 1;
        public final static int product_altimeter = 0x10000 + 2;
+       public final static int product_micropeak_serial = 0x10000 + 3;
 
        /* Bluetooth "identifier" (bluetooth sucks) */
        public final static String bt_product_telebt = "TeleBT";
diff --git a/altosuilib/AltosDevice.java b/altosuilib/AltosDevice.java
new file mode 100644 (file)
index 0000000..69b025b
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altosuilib;
+
+import libaltosJNI.*;
+
+public interface AltosDevice {
+       public abstract String toString();
+       public abstract String toShortString();
+       public abstract int getSerial();
+       public abstract String getPath();
+       public abstract boolean matchProduct(int product);
+       public abstract String getErrorString();
+       public SWIGTYPE_p_altos_file open();
+}
diff --git a/altosuilib/AltosDeviceDialog.java b/altosuilib/AltosDeviceDialog.java
new file mode 100644 (file)
index 0000000..82620b8
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altosuilib;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+
+public abstract class AltosDeviceDialog extends AltosUIDialog implements ActionListener {
+
+       private AltosDevice     value;
+       private JList           list;
+       private JButton         cancel_button;
+       private JButton         select_button;
+       private JButton         manage_bluetooth_button;
+       private Frame           frame;
+       private int             product;
+
+       public AltosDevice getValue() {
+               return value;
+       }
+
+       public abstract AltosDevice[] devices();
+
+       private void update_devices() {
+               AltosDevice[] devices = devices();
+               list.setListData(devices);
+               select_button.setEnabled(devices.length > 0);
+       }
+
+       public AltosDeviceDialog (Frame in_frame, Component location, int in_product) {
+               super(in_frame, "Device Selection", true);
+
+               product = in_product;
+               frame = in_frame;
+               value = null;
+
+               AltosDevice[]   devices = devices();
+
+               cancel_button = new JButton("Cancel");
+               cancel_button.setActionCommand("cancel");
+               cancel_button.addActionListener(this);
+
+//             manage_bluetooth_button = new JButton("Manage Bluetooth");
+//             manage_bluetooth_button.setActionCommand("manage");
+//             manage_bluetooth_button.addActionListener(this);
+
+               select_button = new JButton("Select");
+               select_button.setActionCommand("select");
+               select_button.addActionListener(this);
+               if (devices.length == 0)
+                       select_button.setEnabled(false);
+               getRootPane().setDefaultButton(select_button);
+
+               list = new JList(devices) {
+                               //Subclass JList to workaround bug 4832765, which can cause the
+                               //scroll pane to not let the user easily scroll up to the beginning
+                               //of the list.  An alternative would be to set the unitIncrement
+                               //of the JScrollBar to a fixed value. You wouldn't get the nice
+                               //aligned scrolling, but it should work.
+                               public int getScrollableUnitIncrement(Rectangle visibleRect,
+                                                                     int orientation,
+                                                                     int direction) {
+                                       int row;
+                                       if (orientation == SwingConstants.VERTICAL &&
+                                           direction < 0 && (row = getFirstVisibleIndex()) != -1) {
+                                               Rectangle r = getCellBounds(row, row);
+                                               if ((r.y == visibleRect.y) && (row != 0))  {
+                                                       Point loc = r.getLocation();
+                                                       loc.y--;
+                                                       int prevIndex = locationToIndex(loc);
+                                                       Rectangle prevR = getCellBounds(prevIndex, prevIndex);
+
+                                                       if (prevR == null || prevR.y >= r.y) {
+                                                               return 0;
+                                                       }
+                                                       return prevR.height;
+                                               }
+                                       }
+                                       return super.getScrollableUnitIncrement(
+                                               visibleRect, orientation, direction);
+                               }
+                       };
+
+               list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+               list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
+               list.setVisibleRowCount(-1);
+               list.addMouseListener(new MouseAdapter() {
+                                public void mouseClicked(MouseEvent e) {
+                                        if (e.getClickCount() == 2) {
+                                                select_button.doClick(); //emulate button click
+                                        }
+                                }
+                       });
+               JScrollPane listScroller = new JScrollPane(list);
+               listScroller.setPreferredSize(new Dimension(400, 80));
+               listScroller.setAlignmentX(LEFT_ALIGNMENT);
+
+               //Create a container so that we can add a title around
+               //the scroll pane.  Can't add a title directly to the
+               //scroll pane because its background would be white.
+               //Lay out the label and scroll pane from top to bottom.
+               JPanel listPane = new JPanel();
+               listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS));
+
+               JLabel label = new JLabel("Select Device");
+               label.setLabelFor(list);
+               listPane.add(label);
+               listPane.add(Box.createRigidArea(new Dimension(0,5)));
+               listPane.add(listScroller);
+               listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
+
+               //Lay out the buttons from left to right.
+               JPanel buttonPane = new JPanel();
+               buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
+               buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
+               buttonPane.add(Box.createHorizontalGlue());
+               buttonPane.add(cancel_button);
+               buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
+//             buttonPane.add(manage_bluetooth_button);
+//             buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
+               buttonPane.add(select_button);
+
+               //Put everything together, using the content pane's BorderLayout.
+               Container contentPane = getContentPane();
+               contentPane.add(listPane, BorderLayout.CENTER);
+               contentPane.add(buttonPane, BorderLayout.PAGE_END);
+
+               //Initialize values.
+               if (devices != null && devices.length != 0)
+                       list.setSelectedValue(devices[0], true);
+               pack();
+               setLocationRelativeTo(location);
+       }
+
+       //Handle clicks on the Set and Cancel buttons.
+       public void actionPerformed(ActionEvent e) {
+               if ("select".equals(e.getActionCommand()))
+                       value = (AltosDevice)(list.getSelectedValue());
+//             if ("manage".equals(e.getActionCommand())) {
+//                     AltosBTManage.show(frame, AltosBTKnown.bt_known());
+//                     update_devices();
+//                     return;
+//             }
+               setVisible(false);
+       }
+
+}
diff --git a/altosuilib/AltosUSBDevice.java b/altosuilib/AltosUSBDevice.java
new file mode 100644 (file)
index 0000000..2f4e0dc
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altosuilib;
+
+import java.util.*;
+import libaltosJNI.*;
+
+public class AltosUSBDevice  extends altos_device implements AltosDevice {
+
+       public String toString() {
+               String  name = getName();
+               if (name == null)
+                       name = "Altus Metrum";
+               return String.format("%-20.20s %4d %s",
+                                    name, getSerial(), getPath());
+       }
+
+       public String toShortString() {
+               String  name = getName();
+               if (name == null)
+                       name = "Altus Metrum";
+               return String.format("%s %d %s",
+                                    name, getSerial(), getPath());
+
+       }
+
+       public String getErrorString() {
+               altos_error     error = new altos_error();
+
+               libaltos.altos_get_last_error(error);
+               return String.format("%s (%d)", error.getString(), error.getCode());
+       }
+
+       public SWIGTYPE_p_altos_file open() {
+               return libaltos.altos_open(this);
+       }
+
+       private boolean isAltusMetrum() {
+               if (getVendor() != AltosUILib.vendor_altusmetrum)
+                       return false;
+               if (getProduct() < AltosUILib.product_altusmetrum_min)
+                       return false;
+               if (getProduct() > AltosUILib.product_altusmetrum_max)
+                       return false;
+               return true;
+       }
+
+       public boolean matchProduct(int want_product) {
+
+               if (!isAltusMetrum())
+                       return false;
+
+               if (want_product == AltosUILib.product_any)
+                       return true;
+
+               if (want_product == AltosUILib.product_basestation)
+                       return matchProduct(AltosUILib.product_teledongle) ||
+                               matchProduct(AltosUILib.product_teleterra) ||
+                               matchProduct(AltosUILib.product_telebt) ||
+                               matchProduct(AltosUILib.product_megadongle);
+
+               if (want_product == AltosUILib.product_altimeter)
+                       return matchProduct(AltosUILib.product_telemetrum) ||
+                               matchProduct(AltosUILib.product_megametrum);
+
+               int have_product = getProduct();
+
+               if (have_product == AltosUILib.product_altusmetrum)     /* old devices match any request */
+                       return true;
+
+               if (want_product == have_product)
+                       return true;
+
+               return false;
+       }
+
+       static java.util.List<AltosDevice> list(int product) {
+               if (!AltosUILib.load_library())
+                       return null;
+
+               SWIGTYPE_p_altos_list list = libaltos.altos_list_start();
+
+               ArrayList<AltosDevice> device_list = new ArrayList<AltosDevice>();
+               if (list != null) {
+                       for (;;) {
+                               AltosUSBDevice device = new AltosUSBDevice();
+                               if (libaltos.altos_list_next(list, device) == 0)
+                                       break;
+                               if (device.matchProduct(product))
+                                       device_list.add(device);
+                       }
+                       libaltos.altos_list_finish(list);
+               }
+
+               return device_list;
+       }
+}
\ No newline at end of file
index 26aee7c4de68f5b3cc396e5809e3f914d84a6859..e2ff8cb5df679d4dc215eeec9ac140221554dfeb 100644 (file)
@@ -11,6 +11,9 @@ AltosUILibdir = $(datadir)/java
 
 AltosUILib_JAVA = \
        AltosConfigureUI.java \
+       AltosDevice.java \
+       AltosDeviceDialog.java \
+       AltosUSBDevice.java \
        AltosFontListener.java \
        AltosUIDialog.java \
        AltosUIFrame.java \
index d7b266cf08936f23abd1a18003b26c4cc0f9012e..6e884c80ea145eeb576955d7d703f6a43f2d94af 100644 (file)
@@ -116,6 +116,7 @@ altos_open(struct altos_device *device)
                return NULL;
        }
 
+       printf ("open\n");
 //     altos_set_last_error(12, "yeah yeah, failed again");
 //     free(file);
 //     return NULL;
@@ -148,6 +149,8 @@ altos_open(struct altos_device *device)
                return NULL;
        }
        cfmakeraw(&term);
+       cfsetospeed(&term, B9600);
+       cfsetispeed(&term, B9600);
 #ifdef USE_POLL
        term.c_cc[VMIN] = 1;
        term.c_cc[VTIME] = 0;
@@ -609,6 +612,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device)
 {
        struct altos_usbdev *dev;
        if (list->current >= list->ndev) {
+               printf ("end\n");
                return 0;
        }
        dev = list->dev[list->current];
index e0de690c05270beb0453c60f0fd0be62758bd49d..a54b78a5bc5a27c839f6018f3c54bfd6b08cbcce 100644 (file)
@@ -10,12 +10,15 @@ micropeakdir=$(datadir)/java
 micropeak_JAVA= \
        MicroPeak.java \
        MicroData.java \
+       MicroDownload.java \
        MicroFrame.java \
        MicroGraph.java \
+       MicroSave.java \
        MicroSerial.java \
        MicroStats.java \
        MicroStatsTable.java \
        MicroFileChooser.java \
+       MicroDeviceDialog.java \
        MicroUSB.java
 
 JFREECHART_CLASS= \
index ec9b83d8179e0902bc82c74de968bfac996b9e54..8ccd5fd8a88e21ec9ef592777d4c8e03e210e1dd 100644 (file)
@@ -110,6 +110,7 @@ public class MicroData {
        private double          time_step;
        private double          ground_altitude;
        private ArrayList<Integer>      bytes;
+       String                  name;
        
 
        class FileEndedException extends Exception {
@@ -310,12 +311,18 @@ public class MicroData {
        public void save (OutputStream f) throws IOException {
                for (int c : bytes)
                        f.write(c);
+               f.write('\n');
        }
 
-       public MicroData (InputStream f) throws IOException {
+       public void set_name(String name) {
+               this.name = name;
+       }
+
+       public MicroData (InputStream f, String name) throws IOException, InterruptedException {
+               this.name = name;
                bytes = new ArrayList<Integer>();
                if (!find_header(f))
-                       throw new IOException();
+                       throw new IOException("No MicroPeak data header found");
                try {
                        file_crc = 0xffff;
                        ground_pressure = get_32(f);
@@ -354,9 +361,9 @@ public class MicroData {
 
                        time_step = 0.192;
                } catch (FileEndedException fe) {
-                       throw new IOException();
+                       throw new IOException("File Ended Unexpectedly");
                } catch (NonHexcharException ne) {
-                       throw new IOException();
+                       throw new IOException("Non hexadecimal character found");
                }
        }
 
diff --git a/micropeak/MicroDeviceDialog.java b/micropeak/MicroDeviceDialog.java
new file mode 100644 (file)
index 0000000..7b8a630
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.micropeak;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import org.altusmetrum.altosuilib.*;
+
+public class MicroDeviceDialog extends AltosDeviceDialog {
+
+       public AltosDevice[] devices() {
+               java.util.List<MicroUSB>        list = MicroUSB.list();
+               int             num_devices = list.size();
+               AltosDevice[]   devices = new AltosDevice[num_devices];
+
+               for (int i = 0; i < num_devices; i++)
+                       devices[i] = list.get(i);
+               return devices;
+       }
+
+       public MicroDeviceDialog (Frame in_frame, Component location) {
+               super(in_frame, location, 0);
+       }
+
+       public static AltosDevice show (Component frameComp) {
+               Frame                   frame = JOptionPane.getFrameForComponent(frameComp);
+               MicroDeviceDialog       dialog;
+
+               dialog = new MicroDeviceDialog (frame, frameComp);
+               dialog.setVisible(true);
+               return dialog.getValue();
+       }
+}
diff --git a/micropeak/MicroDownload.java b/micropeak/MicroDownload.java
new file mode 100644 (file)
index 0000000..2e328b4
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.micropeak;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.io.*;
+import java.util.concurrent.*;
+import java.util.*;
+import org.altusmetrum.AltosLib.*;
+import org.altusmetrum.altosuilib.*;
+
+public class MicroDownload extends AltosUIDialog implements Runnable, ActionListener {
+       MicroPeak       owner;
+       Container       pane;
+       AltosDevice     device;
+       JButton         cancel;
+       MicroData       data;
+       MicroSerial     serial;
+
+       private void done_internal() {
+               setVisible(false);
+               if (data != null) {
+                       owner = owner.SetData(data);
+                       MicroSave save = new MicroSave(owner, data);
+                       if (save.runDialog())
+                               owner.SetName(data.name);
+               }
+               dispose();
+       }
+
+       public void done() {
+               Runnable r = new Runnable() {
+                               public void run() {
+                                       try {
+                                               done_internal();
+                                       } catch (Exception ex) {
+                                       }
+                               }
+                       };
+               SwingUtilities.invokeLater(r);
+       }
+
+       public void run() {
+               try {
+                       data = new MicroData(serial, device.toShortString());
+                       serial.close();
+               } catch (FileNotFoundException fe) {
+               } catch (IOException ioe) {
+               } catch (InterruptedException ie) {
+               }
+               done();
+       }
+
+       Thread  serial_thread;
+
+       public void start() {
+               try {
+                       serial = new MicroSerial(device);
+               } catch (FileNotFoundException fe) {
+                       return;
+               }
+               serial_thread = new Thread(this);
+               serial_thread.start();
+       }
+
+       public void actionPerformed(ActionEvent ae) {
+               System.out.printf ("command %s\n", ae.getActionCommand());
+               if (serial_thread != null) {
+                       System.out.printf ("Interrupting serial_thread\n");
+                       serial.close();
+                       serial_thread.interrupt();
+               }
+       }
+
+       public MicroDownload(MicroPeak owner, AltosDevice device) {
+               super (owner, "Download MicroPeak Data", false);
+
+               GridBagConstraints c;
+               Insets il = new Insets(4,4,4,4);
+               Insets ir = new Insets(4,4,4,4);
+
+               this.owner = owner;
+               this.device = device;
+
+               pane = getContentPane();
+               pane.setLayout(new GridBagLayout());
+
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = 0;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               JLabel device_label = new JLabel("Device:");
+               pane.add(device_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 1; c.gridy = 0;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               JLabel device_value = new JLabel(device.toString());
+               pane.add(device_value, c);
+
+               cancel = new JButton("Cancel");
+               c = new GridBagConstraints();
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.CENTER;
+               c.gridx = 0; c.gridy = 1;
+               c.gridwidth = GridBagConstraints.REMAINDER;
+               Insets ic = new Insets(4,4,4,4);
+               c.insets = ic;
+               pane.add(cancel, c);
+
+               cancel.addActionListener(this);
+
+               pack();
+               setLocationRelativeTo(owner);
+               setVisible(true);
+               this.start();
+       }
+}
index 38f54fe04fa7f9905327000de0f2a47721669ba0..b9b084f855880539fb7fc422b002920a41e7ce9c 100644 (file)
@@ -111,8 +111,13 @@ public class MicroGraph implements AltosUnitsListener {
                }
        }
 
+       public void setName (String name) {
+               chart.setTitle(name);
+       }
+
        public void setData (MicroData data) {
                this.data = data;
+               chart.setTitle(data.name);
                resetData();
        }
 
index c69f7167904df828f9a103927fa1efec28dd3cb5..5e375057a37c1d1ac6e1a116fe4f64ed4e7edd30 100644 (file)
@@ -34,13 +34,36 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene
        MicroData       data;
        Container       container;
        JTabbedPane     pane;
+       static int      number_of_windows;
 
-       private void RunFile(InputStream input) {
+       MicroPeak SetData(MicroData data) {
+               MicroPeak       mp = this;
+               if (this.data != null) {
+                       mp = new MicroPeak();
+                       return mp.SetData(data);
+               }
+               this.data = data;
+               graph.setData(data);
+               stats.setData(data);
+               setTitle(data.name);
+               return this;
+       }
+
+       void SetName(String name) {
+               graph.setName(name);
+               setTitle(name);
+       }
+
+       private void RunFile(InputStream input, String name) {
                try {
-                       data = new MicroData(input);
-                       graph.setData(data);
-                       stats.setData(data);
+                       MicroData data = new MicroData(input, name);
+                       SetData(data);
                } catch (IOException ioe) {
+                       JOptionPane.showMessageDialog(this,
+                                                     ioe.getMessage(),
+                                                     "File Read Error",
+                                                     JOptionPane.ERROR_MESSAGE);
+               } catch (InterruptedException ie) {
                }
                try {
                        input.close();
@@ -50,8 +73,12 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene
 
        private void OpenFile(File filename) {
                try {
-                       RunFile (new FileInputStream(filename));
+                       RunFile (new FileInputStream(filename), filename.getName());
                } catch (FileNotFoundException fne) {
+                       JOptionPane.showMessageDialog(this,
+                                                     fne.getMessage(),
+                                                     "Cannot open file",
+                                                     JOptionPane.ERROR_MESSAGE);
                }
        }
 
@@ -60,30 +87,44 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene
                InputStream             input = chooser.runDialog();
 
                if (input != null)
-                       RunFile(input);
+                       RunFile(input, chooser.filename);
        }
 
        private void Preferences() {
                new AltosConfigureUI(this);
        }
-               
+
        private void DownloadData() {
-               java.util.List<MicroUSB>        devices = MicroUSB.list();
-               for (MicroUSB device : devices)
-                       System.out.printf("device %s\n", device.toString());
+               AltosDevice     device = MicroDeviceDialog.show(this);
+               
+               if (device != null)
+                       new MicroDownload(this, device);
        }
 
+       private void Save() {
+               if (data == null) {
+                       JOptionPane.showMessageDialog(this,
+                                                     "No data available",
+                                                     "No data",
+                                                     JOptionPane.INFORMATION_MESSAGE);
+                       return;
+               }
+               MicroSave       save = new MicroSave (this, data);
+               if (save.runDialog())
+                       SetName(data.name);
+       }
+       
        public void actionPerformed(ActionEvent ev) {
                if ("Exit".equals(ev.getActionCommand()))
                        System.exit(0);
                else if ("Open".equals(ev.getActionCommand()))
                        SelectFile();
-               else if ("New".equals(ev.getActionCommand()))
-                       new MicroPeak();
                else if ("Download".equals(ev.getActionCommand()))
                        DownloadData();
                else if ("Preferences".equals(ev.getActionCommand()))
                        Preferences();
+               else if ("Save a Copy".equals(ev.getActionCommand()))
+                       Save();
        }
 
        public void itemStateChanged(ItemEvent e) {
@@ -91,6 +132,8 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene
 
        public MicroPeak() {
 
+               ++number_of_windows;
+
                AltosUIPreferences.set_component(this);
 
                container = getContentPane();
@@ -104,10 +147,6 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene
                JMenu fileMenu = new JMenu("File");
                menuBar.add(fileMenu);
 
-               JMenuItem newAction = new JMenuItem("New");
-               fileMenu.add(newAction);
-               newAction.addActionListener(this);
-
                JMenuItem openAction = new JMenuItem("Open");
                fileMenu.add(openAction);
                openAction.addActionListener(this);
@@ -116,6 +155,10 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene
                fileMenu.add(downloadAction);
                downloadAction.addActionListener(this);
 
+               JMenuItem saveAction = new JMenuItem("Save a Copy");
+               fileMenu.add(saveAction);
+               saveAction.addActionListener(this);
+
                JMenuItem preferencesAction = new JMenuItem("Preferences");
                fileMenu.add(preferencesAction);
                preferencesAction.addActionListener(this);
@@ -128,7 +171,11 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene
                addWindowListener(new WindowAdapter() {
                        @Override
                        public void windowClosing(WindowEvent e) {
-                               System.exit(0);
+                               setVisible(false);
+                               dispose();
+                               --number_of_windows;
+                               if (number_of_windows == 0)
+                                       System.exit(0);
                        }
                });
 
diff --git a/micropeak/MicroSave.java b/micropeak/MicroSave.java
new file mode 100644 (file)
index 0000000..cb4b422
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.micropeak;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import java.io.*;
+import java.util.concurrent.*;
+import java.util.*;
+import org.altusmetrum.AltosLib.*;
+import org.altusmetrum.altosuilib.*;
+
+public class MicroSave extends JFileChooser {
+
+       JFrame          frame;
+       MicroData       data;
+
+       public boolean runDialog() {
+               int     ret;
+
+               for (;;) {
+                       ret = showSaveDialog(frame);
+                       if (ret != APPROVE_OPTION)
+                               return false;
+                       File    file;
+                       String  filename;
+                       file = getSelectedFile();
+                       if (file == null)
+                               continue;
+                       if (!file.getName().contains(".")) {
+                               String fullname = file.getPath();
+                               file = new File(fullname.concat(".mpd"));
+                       }
+                       filename = file.getName();
+                       if (file.exists()) {
+                               if (file.isDirectory()) {
+                                       JOptionPane.showMessageDialog(frame,
+                                                                     String.format("\"%s\" is a directory",
+                                                                                   filename),
+                                                                     "Directory",
+                                                                     JOptionPane.ERROR_MESSAGE);
+                                       continue;
+                               }
+                               int r = JOptionPane.showConfirmDialog(frame,
+                                                                     String.format("\"%s\" already exists. Overwrite?",
+                                                                                   filename),
+                                                                     "Overwrite file?",
+                                                                     JOptionPane.YES_NO_OPTION);
+                               if (r != JOptionPane.YES_OPTION)
+                                       continue;
+                                                             
+                               if (!file.canWrite()) {
+                                       JOptionPane.showMessageDialog(frame,
+                                                                     String.format("\"%s\" is not writable",
+                                                                                   filename),
+                                                                     "File not writable",
+                                                                     JOptionPane.ERROR_MESSAGE);
+                                       continue;
+                               }
+                       }
+                       try {
+                               FileOutputStream fos = new FileOutputStream(file);
+                               data.save(fos);
+                               fos.close();
+                               data.set_name(filename);
+                               return true;
+                       } catch (FileNotFoundException fe) {
+                               JOptionPane.showMessageDialog(frame,
+                                                             fe.getMessage(),
+                                                             "Cannot create file",
+                                                             JOptionPane.ERROR_MESSAGE);
+                       } catch (IOException ioe) {
+                       }
+               }
+       }
+
+       public MicroSave(JFrame frame, MicroData data) {
+               this.frame = frame;
+               this.data = data;
+               setDialogTitle("Save MicroPeak Data File");
+               setFileFilter(new FileNameExtensionFilter("MicroPeak data file",
+                                                         "mpd"));
+               setCurrentDirectory(AltosUIPreferences.logdir());
+       }
+}
index a1a77a1d5b3b5516f877108f4eea886737a9733d..15ef858244bcfa5cc3efee138d56caf008115bdc 100644 (file)
@@ -27,6 +27,10 @@ public class MicroSerial extends InputStream {
 
        public int read() {
                int     c = libaltos.altos_getchar(file, 0);
+               if (Thread.interrupted())
+                       return -1;
+               if (c == -1)
+                       return -1;
                if (AltosUIPreferences.serial_debug)
                        System.out.printf("%c", c);
                return c;
@@ -39,12 +43,12 @@ public class MicroSerial extends InputStream {
                }
        }
 
-       public MicroSerial(MicroUSB usb) throws FileNotFoundException {
-               file = usb.open();
+       public MicroSerial(AltosDevice device) throws FileNotFoundException {
+               file = device.open();
                if (file == null) {
-                       final String message = usb.getErrorString();
+                       final String message = device.getErrorString();
                        throw new FileNotFoundException(String.format("%s (%s)",
-                                                                     usb.toShortString(),
+                                                                     device.toShortString(),
                                                                      message));
                }
        }
index d48610fe720a07d5e057931eb3e29389254455ad..244f7bc0d3af7ad7c3155951cc9c287600f7dbda 100644 (file)
  */
 
 package org.altusmetrum.micropeak;
+
 import java.util.*;
 import libaltosJNI.*;
+import org.altusmetrum.altosuilib.*;
 
-public class MicroUSB extends altos_device {
+public class MicroUSB extends altos_device implements AltosDevice {
 
        static boolean  initialized = false;
        static boolean  loaded_library = false;
@@ -48,16 +50,16 @@ public class MicroUSB extends altos_device {
                String  name = getName();
                if (name == null)
                        name = "Altus Metrum";
-               return String.format("%-20.20s %4d %s",
-                                    name, getSerial(), getPath());
+               return String.format("%-20.20s %s",
+                                    name, getPath());
        }
 
        public String toShortString() {
                String  name = getName();
                if (name == null)
                        name = "Altus Metrum";
-               return String.format("%s %d %s",
-                                    name, getSerial(), getPath());
+               return String.format("%s %s",
+                                    name, getPath());
 
        }
 
@@ -75,11 +77,15 @@ public class MicroUSB extends altos_device {
        private boolean isMicro() {
                if (getVendor() != 0x0403)
                        return false;
-               if (getProduct() != 0x6001)
+               if (getProduct() != 0x6015)
                        return false;
                return true;
        }
 
+       public boolean matchProduct(int product) {
+               return isMicro();
+       }
+
        static java.util.List<MicroUSB> list() {
                if (!load_library())
                        return null;
@@ -92,6 +98,7 @@ public class MicroUSB extends altos_device {
                                MicroUSB device = new MicroUSB();
                                if (libaltos.altos_list_next(list, device) == 0)
                                        break;
+                               System.out.printf("Device %s\n", device.toString());
                                if (device.isMicro())
                                        device_list.add(device);
                        }