Added quick start help text, added explicit save settings in menu, fixed bug in the background image selection.

This commit is contained in:
nifi 2010-10-12 16:28:19 +00:00
parent 3edd8ff316
commit d2f7f62a34
2 changed files with 147 additions and 61 deletions

View file

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: CollectServer.java,v 1.26 2010/10/12 11:38:34 adamdunkels Exp $
* $Id: CollectServer.java,v 1.27 2010/10/12 16:28:19 nifi Exp $
*
* -----------------------------------------------------------------
*
@ -34,8 +34,8 @@
*
* Authors : Joakim Eriksson, Niclas Finne
* Created : 3 jul 2008
* Updated : $Date: 2010/10/12 11:38:34 $
* $Revision: 1.26 $
* Updated : $Date: 2010/10/12 16:28:19 $
* $Revision: 1.27 $
*/
package se.sics.contiki.collect;
@ -63,6 +63,9 @@ import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JCheckBoxMenuItem;
@ -128,9 +131,10 @@ public class CollectServer implements SerialConnectionListener {
private JMenuItem serialItem;
private JMenuItem runInitScriptItem;
private Visualizer[] visualizers;
private MapPanel mapPanel;
private SerialConsole serialConsole;
private final Visualizer[] visualizers;
private final MapPanel mapPanel;
private final SerialConsole serialConsole;
private final MoteProgramAction moteProgramAction;
private JFileChooser fileChooser;
private JList nodeList;
@ -139,7 +143,8 @@ public class CollectServer implements SerialConnectionListener {
private SerialConnection serialConnection;
private boolean hasSerialOpened;
private boolean hasSentInit;
/* Do not auto send init script at startup */
private boolean doSendInitAtStartup = false;
private String initScript;
private long nodeTimeDelta;
@ -175,6 +180,8 @@ public class CollectServer implements SerialConnectionListener {
}
});
moteProgramAction = new MoteProgramAction("Program Nodes...");
nodeModel = new DefaultListModel();
nodeModel.addElement("<All>");
nodeList = new JList(nodeModel);
@ -235,6 +242,8 @@ public class CollectServer implements SerialConnectionListener {
mapPanel.setMapBackground(image);
}
final int defaultMaxItemCount = 250;
NodeControl nodeControl = new NodeControl(this, MAIN);
visualizers = new Visualizer[] {
mapPanel,
new MapPanel(this, "Network Graph", MAIN, false),
@ -572,7 +581,7 @@ public class CollectServer implements SerialConnectionListener {
}
},
new NodeInfoPanel(this, MAIN),
new NodeControl(this, MAIN),
nodeControl,
serialConsole
};
for (int i = 0, n = visualizers.length; i < n; i++) {
@ -587,6 +596,10 @@ public class CollectServer implements SerialConnectionListener {
}
pane.add(visualizers[i].getTitle(), visualizers[i].getPanel());
}
JTabbedPane pane = categoryTable.get(nodeControl.getCategory());
if (pane != null) {
pane.setSelectedComponent(nodeControl.getPanel());
}
window.getContentPane().add(mainPanel, BorderLayout.CENTER);
// Setup menu
@ -598,9 +611,7 @@ public class CollectServer implements SerialConnectionListener {
serialItem = new JMenuItem("Connect to serial");
serialItem.addActionListener(new SerialItemHandler());
fileMenu.add(serialItem);
JMenuItem item = new JMenuItem("Program Sky nodes...");
item.addActionListener(new ProgramItemHandler());
fileMenu.add(item);
fileMenu.add(new JMenuItem(moteProgramAction));
fileMenu.addSeparator();
final JMenuItem clearMapItem = new JMenuItem("Remove Map Background");
@ -615,23 +626,24 @@ public class CollectServer implements SerialConnectionListener {
});
clearMapItem.setEnabled(mapPanel.getMapBackground() != null);
item = new JMenuItem("Select Map Background...");
JMenuItem item = new JMenuItem("Select Map Background...");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (fileChooser == null) {
fileChooser = new JFileChooser();
}
int reply = fileChooser.showOpenDialog(window);
if (reply == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
String name = file.getAbsolutePath();
configTable.put("collect.mapimage", name);
if (!mapPanel.setMapBackground(file.getAbsolutePath())) {
JOptionPane.showMessageDialog(window, "Failed to set background image", "Error", JOptionPane.ERROR_MESSAGE);
} else {
configTable.put("collect.mapimage", name);
save();
}
clearMapItem.setEnabled(mapPanel.getMapBackground() != null);
saveConfig(configTable, configFile);
}
}
}
@ -639,6 +651,17 @@ public class CollectServer implements SerialConnectionListener {
fileMenu.add(item);
fileMenu.add(clearMapItem);
item = new JMenuItem("Save Settings");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
save();
JOptionPane.showMessageDialog(window, "Settings have been saved.");
}
});
fileMenu.add(item);
fileMenu.addSeparator();
item = new JMenuItem("Clear Sensor Data...");
item.addActionListener(new ActionListener() {
@ -759,18 +782,7 @@ public class CollectServer implements SerialConnectionListener {
}
private void exit() {
/* TODO Clean up resources */
if (configFile != null) {
configTable.setProperty("collect.bounds", "" + window.getX() + ',' + window.getY() + ',' + window.getWidth() + ',' + window.getHeight());
if (visualizers != null) {
for(Visualizer v : visualizers) {
if (v instanceof Configurable) {
((Configurable)v).updateConfig(configTable);
}
}
}
saveConfig(configTable, configFile);
}
save();
if (serialConnection != null) {
serialConnection.close();
}
@ -839,6 +851,10 @@ public class CollectServer implements SerialConnectionListener {
return configTable.getProperty(property, config.getProperty(property, defaultValue));
}
public Action getMoteProgramAction() {
return moteProgramAction;
}
protected void setSystemMessage(final String message) {
SwingUtilities.invokeLater(new Runnable() {
@ -970,6 +986,20 @@ public class CollectServer implements SerialConnectionListener {
return false;
}
private void save() {
if (configFile != null) {
configTable.setProperty("collect.bounds", "" + window.getX() + ',' + window.getY() + ',' + window.getWidth() + ',' + window.getHeight());
if (visualizers != null) {
for(Visualizer v : visualizers) {
if (v instanceof Configurable) {
((Configurable)v).updateConfig(configTable);
}
}
}
saveConfig(configTable, configFile);
}
}
private void saveConfig(Properties properties, String configFile) {
try {
File fp = new File(configFile);
@ -1188,9 +1218,16 @@ public class CollectServer implements SerialConnectionListener {
}
protected class ProgramItemHandler implements ActionListener, Runnable {
protected class MoteProgramAction extends AbstractAction implements Runnable {
private static final long serialVersionUID = 1L;
private boolean isRunning = false;
public MoteProgramAction(String name) {
super(name);
}
public void actionPerformed(ActionEvent e) {
if (!isRunning) {
isRunning = true;
@ -1207,10 +1244,10 @@ public class CollectServer implements SerialConnectionListener {
mp.searchForMotes();
String[] motes = mp.getMotes();
if (motes == null || motes.length == 0) {
JOptionPane.showMessageDialog(window, "Could not find any connected Sky nodes", "Error", JOptionPane.ERROR_MESSAGE);
JOptionPane.showMessageDialog(window, "Could not find any connected nodes", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
int reply = JOptionPane.showConfirmDialog(window, "Found " + motes.length + " connected Sky nodes.\n"
int reply = JOptionPane.showConfirmDialog(window, "Found " + motes.length + " connected nodes.\n"
+ "Do you want to upload the firmware " + FIRMWARE_FILE + '?');
if (reply == JFileChooser.APPROVE_OPTION) {
boolean wasOpen = serialConnection != null && serialConnection.isOpen();
@ -1260,9 +1297,9 @@ public class CollectServer implements SerialConnectionListener {
if (!connection.isSerialOutputSupported()) {
serialConsole.addSerialData("*** Serial output not supported ***");
} else if (!hasSentInit) {
} else if (doSendInitAtStartup) {
// Send any initial commands
hasSentInit = true;
doSendInitAtStartup = false;
if (hasInitScript()) {
// Wait a short time before running the init script

View file

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: NodeControl.java,v 1.5 2010/10/12 11:39:59 adamdunkels Exp $
* $Id: NodeControl.java,v 1.6 2010/10/12 16:28:19 nifi Exp $
*
* -----------------------------------------------------------------
*
@ -34,8 +34,8 @@
*
* Authors : Niclas Finne
* Created : 27 sep 2010
* Updated : $Date: 2010/10/12 11:39:59 $
* $Revision: 1.5 $
* Updated : $Date: 2010/10/12 16:28:19 $
* $Revision: 1.6 $
*/
package se.sics.contiki.collect.gui;
@ -43,15 +43,20 @@ import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextPane;
import javax.swing.border.LineBorder;
import se.sics.contiki.collect.CollectServer;
@ -70,6 +75,7 @@ public class NodeControl implements Visualizer {
private final String category;
private final JPanel panel;
private final JLabel statusLabel;
private final JSeparator statusSeparator;
public NodeControl(CollectServer server, String category) {
this.server = server;
@ -85,6 +91,8 @@ public class NodeControl implements Visualizer {
statusLabel.setBackground(Color.white);
statusLabel.setBorder(LineBorder.createBlackLineBorder());
statusLabel.setVisible(false);
statusSeparator = new JSeparator();
statusSeparator.setVisible(false);
JButton stopButton = createCommandButton("Send stop to nodes", "netcmd killall");
@ -115,10 +123,43 @@ public class NodeControl implements Visualizer {
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0.5;
c.insets.left = c.insets.right = c.insets.bottom = 3;
c.insets.top = 10;
c.anchor = GridBagConstraints.WEST;
c.gridy = 0;
c.gridwidth = 3;
controlPanel.add(statusLabel, c);
c.gridy++;
controlPanel.add(statusSeparator, c);
c.insets.top = 10;
c.gridy++;
c.gridwidth = 1;
controlPanel.add(new JLabel("Program Connected Nodes", JLabel.RIGHT), c);
c.gridwidth = 2;
c.fill = GridBagConstraints.NONE;
controlPanel.add(new JButton(server.getMoteProgramAction()), c);
c.gridy++;
c.gridwidth = 3;
c.fill = GridBagConstraints.HORIZONTAL;
controlPanel.add(new JSeparator(), c);
c.gridy++;
c.gridwidth = 1;
controlPanel.add(new JLabel("Base Station Control", JLabel.RIGHT), c);
c.gridwidth = 2;
JPanel basePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 5));
basePanel.add(collectButton);
basePanel.add(stopCollectButton);
c.insets.left -= 5;
controlPanel.add(basePanel, c);
c.insets.left += 5;
c.gridy++;
c.gridwidth = 3;
controlPanel.add(new JSeparator(), c);
c.gridy++;
JLabel label = new JLabel("Collect Settings", JLabel.CENTER);
controlPanel.add(label, c);
c.gridwidth = 1;
@ -150,27 +191,34 @@ public class NodeControl implements Visualizer {
c.gridy++;
c.gridwidth = 3;
c.weightx = 0;
c.fill = GridBagConstraints.NONE;
c.insets.bottom = 20;
JPanel p = new JPanel();
p.add(sendButton);
p.add(stopButton);
controlPanel.add(p, c);
c.insets.bottom = 10;
JPanel nodePanel = new JPanel();
nodePanel.add(sendButton);
nodePanel.add(stopButton);
controlPanel.add(nodePanel, c);
c.gridy++;
c.insets.bottom = 3;
controlPanel.add(new JLabel("Base Station Control", JLabel.CENTER), c);
c.gridy++;
c.insets.bottom = 20;
p = new JPanel();
p.add(collectButton);
p.add(stopCollectButton);
controlPanel.add(p, c);
controlPanel.add(new JSeparator(), c);
panel.add(controlPanel, BorderLayout.NORTH);
panel.add(statusLabel, BorderLayout.SOUTH);
JTextPane helpPane = new JTextPane();
helpPane.setContentType("text/html");
helpPane.setEditable(false);
helpPane.setText("<html>" +
"<h3>Quick Startup Instructions</h3>" +
"<lu>" +
"<li> Connect nodes to USB. Press the <strong>Program Nodes...</strong> button." +
"<li> Disconnect all except one node. " +
"Press the <strong>Start Collect</strong> button." +
"<li> Press the <strong>Send command to nodes</strong> button." +
"</lu>" +
"</html>");
helpPane.setBackground(panel.getBackground());
JScrollPane helpScroll = new JScrollPane(helpPane,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
helpScroll.setBorder(BorderFactory.createEmptyBorder(3, 10, 10, 10));
panel.add(helpScroll, BorderLayout.CENTER);
}
private JButton createCommandButton(String name, final String... command) {
@ -219,6 +267,7 @@ public class NodeControl implements Visualizer {
statusLabel.setForeground(isWarning ? Color.red : Color.black);
statusLabel.setText(text);
statusLabel.setVisible(true);
statusSeparator.setVisible(true);
}
public String getCategory() {