package lejos.pc.tools; import lejos.pc.comm.*; import lejos.nxt.remote.*; import java.awt.*; import javax.swing.*; import javax.swing.table.*; import org.apache.commons.cli.CommandLine; import java.awt.event.*; import java.io.*; /** * * Graphical file browser for leJOS NXJ. * Supports uploading,, downloading, and deleting files. * Also supports running programs, defragging the file system * and setting the name of the NXT. * * @author Lawrie Griffiths <lawrie.griffiths@ntlworld.com> */ public class NXJBrowser { public static final int MAX_FILES = 30; private NXTCommand nxtCommand; private Cursor hourglassCursor = new Cursor(Cursor.WAIT_CURSOR); private Cursor normalCursor = new Cursor(Cursor.DEFAULT_CURSOR); private NXJBrowserCommandLineParser fParser; private static String title = "NXJ File Browser"; private JFrame frame; public NXJBrowser() { fParser = new NXJBrowserCommandLineParser(); } public static void main(String args[]) { try { NXJBrowser instance = new NXJBrowser(); instance.run(args); } catch(Throwable t) { System.err.println("Error: " + t.getMessage()); } } public void run(String[] args) throws js.tinyvm.TinyVMException, NXTCommException { frame = new JFrame(title); WindowListener listener = new WindowAdapter() { public void windowClosing(WindowEvent w) { try { nxtCommand.close(); } catch (IOException ioe) {} System.exit(0); } }; frame.addWindowListener(listener); nxtCommand = NXTCommand.getSingleton(); CommandLine commandLine = fParser.parse(args); String name = commandLine.getOptionValue("n"); boolean blueTooth = commandLine.hasOption("b"); boolean usb = commandLine.hasOption("u"); String address = commandLine.getOptionValue("d"); int protocols = 0; if (blueTooth) protocols |= NXTCommFactory.BLUETOOTH; if (usb) protocols |= NXTCommFactory.USB; if (protocols == 0) protocols = NXTCommFactory.USB | NXTCommFactory.BLUETOOTH; NXTConnector conn = new NXTConnector(); conn.addLogListener(new ToolsLogger()); final NXTInfo[] nxts = conn.search(name, address, protocols); if (nxts.length == 0) { System.err.println("No NXT found - is it switched on and plugged in (for USB)?"); System.exit(1); } // Display a list of NXTs final NXTConnectionModel nm = new NXTConnectionModel(nxts, nxts.length); final JTable nxtTable = new JTable(nm); final JScrollPane nxtTablePane = new JScrollPane(nxtTable); nxtTable.setRowSelectionInterval(0, 0); frame.getContentPane().add(nxtTablePane, BorderLayout.CENTER); JButton connectButton = new JButton("Connect"); connectButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { int row = nxtTable.getSelectedRow(); if (row >= 0) { boolean open = false; try { NXTComm nxtComm = NXTCommFactory.createNXTComm(nxts[row].protocol); open = nxtComm.open(nxts[row], NXTComm.LCP); nxtCommand.setNXTComm(nxtComm); } catch(NXTCommException n) { open = false; } if (!open) { JOptionPane.showMessageDialog(frame, "Failed to connect"); } else showFiles(frame,nxts[row]); } } }); JPanel buttonPanel = new JPanel(); buttonPanel.add(connectButton); frame.getContentPane().add(new JScrollPane(buttonPanel), BorderLayout.SOUTH); frame.pack(); frame.setVisible(true); } private void showFiles(final JFrame frame, NXTInfo nxt) { try { frame.setTitle(title + " : " + nxtCommand.getFriendlyName()); } catch (IOException ioe) { showMessage("IOException getting friendly name"); } frame.getContentPane().removeAll(); final ExtendedFileModel fm = new ExtendedFileModel(nxtCommand); final JTable table = new JTable(fm); table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); TableColumn col = table.getColumnModel().getColumn(0); col.setPreferredWidth(300); final JScrollPane tablePane = new JScrollPane(table); tablePane.setPreferredSize(new Dimension(605, 500)); frame.getContentPane().add(tablePane, BorderLayout.CENTER); JPanel buttonPanel = new JPanel(); JButton deleteButton = new JButton("Delete Files"); JButton uploadButton = new JButton("Upload file"); JButton downloadButton = new JButton("Download file"); JButton runButton = new JButton("Run program"); JButton defragButton = new JButton("Defrag"); JButton nameButton = new JButton("Set Name"); buttonPanel.add(deleteButton); buttonPanel.add(uploadButton); buttonPanel.add(downloadButton); buttonPanel.add(runButton); buttonPanel.add(defragButton); buttonPanel.add(nameButton); frame.getContentPane().add(new JScrollPane(buttonPanel), BorderLayout.SOUTH); deleteButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { frame.setCursor(hourglassCursor); try { for(int i=0;i<fm.getRowCount();i++) { Boolean b = (Boolean) fm.getValueAt(i,4); boolean deleteIt = b.booleanValue(); String fileName = (String) fm.getValueAt(i,0); if (deleteIt) { //System.out.println("Deleting " + fileName); nxtCommand.delete(fileName); fm.delete(fileName, i); i--; table.invalidate(); tablePane.revalidate(); } } } catch (IOException ioe) { showMessage("IOException deleting files"); } frame.setCursor(normalCursor); } }); uploadButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { JFileChooser fc = new JFileChooser(); int returnVal = fc.showOpenDialog(frame); if (returnVal == JFileChooser.APPROVE_OPTION) { frame.setCursor(hourglassCursor); try { File file = fc.getSelectedFile(); if (file.getName().length() > 20) { showMessage("File name is more than 20 characters"); } else { nxtCommand.uploadFile(file, file.getName()); String s = fm.fetchFiles(); if (s != null) throw new IOException(); table.invalidate(); tablePane.revalidate(); } } catch (IOException ioe) { showMessage("IOException uploading file"); } frame.setCursor(normalCursor); } } }); downloadButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { int i = table.getSelectedRow(); if (i<0) return; String fileName = fm.getFile(i).fileName; int size = fm.getFile(i).fileSize; JFileChooser fc = new JFileChooser(); fc.setFileSelectionMode(JFileChooser.FILES_ONLY); fc.setSelectedFile(new File(fileName)); int returnVal = fc.showSaveDialog(frame); if (returnVal == 0) { File file = fc.getSelectedFile(); frame.setCursor(hourglassCursor); getFile(file, fileName, size); frame.setCursor(normalCursor); } } }); defragButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { frame.setCursor(hourglassCursor); try { nxtCommand.defrag(); String s = fm.fetchFiles(); if (s != null) throw new IOException(); table.invalidate(); tablePane.revalidate(); tablePane.repaint(); } catch (IOException ioe) { showMessage("IOException during defrag"); } frame.setCursor(normalCursor); } }); runButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { int i = table.getSelectedRow(); if (i<0) return; String fileName = fm.getFile(i).fileName; try { runProgram(fileName); System.exit(0); } catch (IOException ioe) { showMessage("IOException running program"); } } }); nameButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { String name = JOptionPane.showInputDialog(frame,"New Name"); if (name != null && name.length() <= 16) { frame.setCursor(hourglassCursor); try { nxtCommand.setFriendlyName(name); frame.setTitle(title + " : " + name); } catch (IOException ioe) { showMessage("IOException setting friendly name"); } frame.setCursor(normalCursor); } } }); frame.pack(); frame.setVisible(true); } public void getFile(File file, String fileName, int size) { FileOutputStream out = null; int received = 0; try { out = new FileOutputStream(file); } catch (FileNotFoundException e) {} try { nxtCommand.openRead(fileName); do { byte [] data = nxtCommand.readFile((byte) 0,(size-received < 51 ? size-received : 51)); //System.out.println("Received " + data.length + " bytes"); received += data.length; out.write(data); } while (received < size); //System.out.println("Received " + received + " bytes"); nxtCommand.closeFile((byte) 0); out.close(); } catch (IOException ioe) { showMessage("IOException downloading file"); } } public void runProgram(String fileName) throws IOException { nxtCommand.startProgram(fileName); } public void showMessage(String msg) { JOptionPane.showMessageDialog(frame, msg); } }