/*
* RoombaRecorder --
*
* Copyright (c) 2006 Tod E. Kurt, tod@todbot.com, ThingM
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA
*
*/
package roombacomm;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.filechooser.*;
import java.util.*;
import java.io.*;
/**
* A simple wrapper for multiple MacroRecorderPanels
*
*/
public class RoombaRecorder extends JFrame implements WindowListener,ActionListener {
static final String helpMsg = ""+
//"
"+
" Roomba Movement Keyboard Shortcuts
"+
""+
"- arrow keys -- move Roomba"+
"
- space bar -- stop Roomba"+
"
- L -- blink Roomba LEDs"+
"
- V -- toggle Roomba vacuum"+
"
- T -- test Roomba"+
"
- R -- reset Roomba"+
"
- 1,2,3,4 -- adjust speed"+
"
"+
" Application Control Keyboard Shortcuts
"+
""+
"- cmd-T -- open new tab"+
"
- cmd-W -- close current tab"+
"
- cmd-arrow-left/right -- cycle through tabs"+
"
- cmd-X/C/V -- cut/copy/paste events between tabs"+
"
"+
"";
JPanel contentPane;
JPanel recordPanel;
JTabbedPane tabbedPane;
JButton stopButton,recordButton,playButton;
JCheckBox loopButton;
JCheckBox playAllButton;
JFileChooser fc;
File file;
boolean hwhandshake = false;
int maxRoombas = 16;
int lastTab = 0;
HashMap clipboard;
RoombaRecorderPanel rrpanel; // just to make some of code lines shorter
boolean movingForward = false; // is roomba moving forward or not
boolean vacuuming = false; // is roomba vacuuming or not
int turnval = 0;
public static void main(String[] args) {
new RoombaRecorder(args);
}
public RoombaRecorder(String[] args) {
super("RoombaRecorder");
addWindowListener(this);
for(int i=0; i < args.length; i++) {
if(args[i].endsWith("hwhandshake"))
hwhandshake = true;
}
clipboard = new HashMap();
fc = new JFileChooser();
setResizable(false);
makeMenu();
makeRecordPanel();
// Create and set up the content pane.
tabbedPane = new JTabbedPane();
tabbedPane.setOpaque(true); //content panes must be opaque
openNewTab();
contentPane = new JPanel(new BorderLayout());
contentPane.add(recordPanel, BorderLayout.NORTH);
contentPane.add(tabbedPane, BorderLayout.CENTER);
//Container content = getContentPane();
setContentPane(contentPane);
addBindings();
bindKeys();
// Display the window.
pack(); //setSize(400, 400);
setVisible(true);
//setFocusableWindowState(false); // prevent focus
}
void makeMenu() {
JMenuBar menubar = new JMenuBar();
JMenuItem item;
JMenu file = new JMenu("File");
JMenu edit = new JMenu("Edit");
JMenu help = new JMenu("Help");
file.setMnemonic(KeyEvent.VK_F);
edit.setMnemonic(KeyEvent.VK_E);
help.setMnemonic(KeyEvent.VK_H);
item = new JMenuItem("New Tab");
item.addActionListener(this);
file.add(item);
item = new JMenuItem("Close Tab");
item.addActionListener(this);
file.add(item);
item = new JMenuItem("Open Set");
item.addActionListener(this);
file.add(item);
item = new JMenuItem("Save Set");
item.addActionListener(this);
file.add(item);
item = new JMenuItem("Quit");
item.addActionListener(this);
file.add(item);
item = new JMenuItem("Cut");
item.addActionListener(this);
edit.add(item);
item = new JMenuItem("Copy");
item.addActionListener(this);
edit.add(item);
item = new JMenuItem("Paste");
item.addActionListener(this);
edit.add(item);
item = new JMenuItem("Help");
item.addActionListener(this);
help.add(item);
menubar.add(file);
menubar.add(edit);
menubar.add(help);
setJMenuBar(menubar);
}
void makeRecordPanel() {
recordPanel = new JPanel();
recordPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Action Record"), BorderFactory.createEmptyBorder())); //1,1,1,1)));
stopButton = new JButton(createImageIcon("images/but_transport_stop.png","stop"));
stopButton.setActionCommand("stop");
stopButton.addActionListener(this);
recordPanel.add(stopButton);
playButton = new JButton(createImageIcon("images/but_transport_play.png","play"));
playButton.setSelectedIcon(createImageIcon("images/but_transport_play_push.png","play"));
playButton.setActionCommand("play");
playButton.addActionListener(this);
recordPanel.add(playButton);
recordButton = new JButton(createImageIcon("images/but_transport_record.png","record"));
recordButton.setSelectedIcon(createImageIcon("images/but_transport_record_push.png","record"));
recordButton.setActionCommand("record");
recordButton.addActionListener(this);
recordPanel.add(recordButton);
loopButton = new JCheckBox("loop");
loopButton.setText("loop");
loopButton.setActionCommand("loop");
loopButton.addActionListener(this);
recordPanel.add(loopButton);
playAllButton = new JCheckBox("play all");
playAllButton.addActionListener(this);
recordPanel.add(playAllButton);
}
void addBindings() {
InputMap inputMap = contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
KeyStroke key;
//key = KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,0);
//contentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).remove(key);
key = KeyStroke.getKeyStroke('T',KeyEvent.CTRL_MASK);
inputMap.put(key, "new-tab");
key = KeyStroke.getKeyStroke('T',KeyEvent.META_MASK);
inputMap.put(key, "new-tab");
key = KeyStroke.getKeyStroke('N',KeyEvent.CTRL_MASK);
inputMap.put(key, "new-tab");
key = KeyStroke.getKeyStroke('N',KeyEvent.META_MASK);
inputMap.put(key, "new-tab");
key = KeyStroke.getKeyStroke('W',KeyEvent.CTRL_MASK);
inputMap.put(key, "close-tab");
key = KeyStroke.getKeyStroke('W',KeyEvent.META_MASK);
inputMap.put(key, "close-tab");
key = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,KeyEvent.CTRL_MASK);
inputMap.put(key, "right-tab");
key = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,KeyEvent.CTRL_MASK);
inputMap.put(key, "left-tab");
key = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,KeyEvent.META_MASK);
inputMap.put(key, "right-tab");
key = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,KeyEvent.META_MASK);
inputMap.put(key, "left-tab");
key = KeyStroke.getKeyStroke('X',KeyEvent.CTRL_MASK);
inputMap.put(key, "cut");
key = KeyStroke.getKeyStroke('X',KeyEvent.META_MASK);
inputMap.put(key, "cut");
key = KeyStroke.getKeyStroke('C',KeyEvent.CTRL_MASK);
inputMap.put(key, "copy");
key = KeyStroke.getKeyStroke('C',KeyEvent.META_MASK);
inputMap.put(key, "copy");
key = KeyStroke.getKeyStroke('V',KeyEvent.CTRL_MASK);
inputMap.put(key, "paste");
key = KeyStroke.getKeyStroke('V',KeyEvent.META_MASK);
inputMap.put(key, "paste");
ActionMap actionMap = contentPane.getActionMap();
actionMap.put("new-tab", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
openNewTab();
} });
actionMap.put("close-tab",new AbstractAction() {
public void actionPerformed(ActionEvent e) {
closeCurrentTab();
} });
actionMap.put("left-tab",new AbstractAction() {
public void actionPerformed(ActionEvent e) {
cycleTabLeft();
} });
actionMap.put("right-tab",new AbstractAction() {
public void actionPerformed(ActionEvent e) {
cycleTabRight();
} });
actionMap.put("cut",new AbstractAction() {
public void actionPerformed(ActionEvent e) {
clipboard = getCurrentTab().cut();
} });
actionMap.put("copy",new AbstractAction() {
public void actionPerformed(ActionEvent e) {
clipboard = getCurrentTab().copy();
} });
actionMap.put("paste",new AbstractAction() {
public void actionPerformed(ActionEvent e) {
getCurrentTab().paste(clipboard);
} });
}
/**
* Bind keys to actions using a custom KeyEventPostProcessor
* (fixme: why can't this go in the panel?)
*/
void bindKeys() {
// ahh, the succinctness of java
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
kfm.addKeyEventDispatcher( new KeyEventDispatcher() {
public boolean dispatchKeyEvent(KeyEvent e) {
String action=null;
if(e.getID() != KeyEvent.KEY_PRESSED)
return false;
if(e.getModifiers() != 0)
return false;
switch(e.getKeyCode()) {
case KeyEvent.VK_UP:
action = "forward";
movingForward=true;
turnval = 0;
break;
case KeyEvent.VK_DOWN:
action="backward";
movingForward=false;
turnval = 0;
break;
case KeyEvent.VK_LEFT:
if(movingForward) {
turnval = (turnval==0) ? 100 : turnval-turnval/2;
if(turnval<10) { action="spinleft"; turnval=0; }
else action = "turn"+turnval;
}
else action = "spinleft";
//action = (movingForward) ? "turn100" : "spinleft";
break;
case KeyEvent.VK_RIGHT:
if(movingForward) {
turnval = (turnval==0) ? -100 : turnval-turnval/2;
if(turnval>-10) { action="spinright"; turnval=0; }
else action = "turn"+turnval;
}
else action = "spinright";
//action = (movingForward) ? "turn-100" : "spinright";
break;
case KeyEvent.VK_SPACE:
action="stop";
movingForward=false;
turnval = 0;
break;
case KeyEvent.VK_L:
action="blink-leds";
break;
case KeyEvent.VK_R:
action="reset";
break;
case KeyEvent.VK_T:
action="test";
break;
case KeyEvent.VK_V:
vacuuming = !vacuuming;
action = (vacuuming) ? "vacuum-on":"vacuum-off";
break;
case KeyEvent.VK_1:
action="50";
break;
case KeyEvent.VK_2:
action="100";
break;
case KeyEvent.VK_3:
action="150";
break;
case KeyEvent.VK_4:
action="250";
break;
case KeyEvent.VK_5:
action="400";
break;
case KeyEvent.VK_6:
action="500";
break;
}
if(action!=null)
getCurrentTab().actionPerformed(new ActionEvent(this,0,action));
//System.out.println("process '"+e.getKeyCode()+"' "+e);
return true;
}
});
}
/** Implement Actionlistener */
public void actionPerformed(ActionEvent event) {
String action = event.getActionCommand();
//System.out.println("action:"+action+", event: "+event);
if("stop".equals(action)) {
playButton.setSelected(false);
recordButton.setSelected(false);
for(int i=0; i