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 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 * Authors : Joakim Eriksson, Niclas Finne
* Created : 3 jul 2008 * Created : 3 jul 2008
* Updated : $Date: 2010/10/12 11:38:34 $ * Updated : $Date: 2010/10/12 16:28:19 $
* $Revision: 1.26 $ * $Revision: 1.27 $
*/ */
package se.sics.contiki.collect; package se.sics.contiki.collect;
@ -63,6 +63,9 @@ import java.util.HashMap;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory; import javax.swing.BorderFactory;
import javax.swing.DefaultListModel; import javax.swing.DefaultListModel;
import javax.swing.JCheckBoxMenuItem; import javax.swing.JCheckBoxMenuItem;
@ -128,9 +131,10 @@ public class CollectServer implements SerialConnectionListener {
private JMenuItem serialItem; private JMenuItem serialItem;
private JMenuItem runInitScriptItem; private JMenuItem runInitScriptItem;
private Visualizer[] visualizers; private final Visualizer[] visualizers;
private MapPanel mapPanel; private final MapPanel mapPanel;
private SerialConsole serialConsole; private final SerialConsole serialConsole;
private final MoteProgramAction moteProgramAction;
private JFileChooser fileChooser; private JFileChooser fileChooser;
private JList nodeList; private JList nodeList;
@ -139,7 +143,8 @@ public class CollectServer implements SerialConnectionListener {
private SerialConnection serialConnection; private SerialConnection serialConnection;
private boolean hasSerialOpened; private boolean hasSerialOpened;
private boolean hasSentInit; /* Do not auto send init script at startup */
private boolean doSendInitAtStartup = false;
private String initScript; private String initScript;
private long nodeTimeDelta; private long nodeTimeDelta;
@ -175,6 +180,8 @@ public class CollectServer implements SerialConnectionListener {
} }
}); });
moteProgramAction = new MoteProgramAction("Program Nodes...");
nodeModel = new DefaultListModel(); nodeModel = new DefaultListModel();
nodeModel.addElement("<All>"); nodeModel.addElement("<All>");
nodeList = new JList(nodeModel); nodeList = new JList(nodeModel);
@ -235,6 +242,8 @@ public class CollectServer implements SerialConnectionListener {
mapPanel.setMapBackground(image); mapPanel.setMapBackground(image);
} }
final int defaultMaxItemCount = 250; final int defaultMaxItemCount = 250;
NodeControl nodeControl = new NodeControl(this, MAIN);
visualizers = new Visualizer[] { visualizers = new Visualizer[] {
mapPanel, mapPanel,
new MapPanel(this, "Network Graph", MAIN, false), new MapPanel(this, "Network Graph", MAIN, false),
@ -572,7 +581,7 @@ public class CollectServer implements SerialConnectionListener {
} }
}, },
new NodeInfoPanel(this, MAIN), new NodeInfoPanel(this, MAIN),
new NodeControl(this, MAIN), nodeControl,
serialConsole serialConsole
}; };
for (int i = 0, n = visualizers.length; i < n; i++) { 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()); 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); window.getContentPane().add(mainPanel, BorderLayout.CENTER);
// Setup menu // Setup menu
@ -598,9 +611,7 @@ public class CollectServer implements SerialConnectionListener {
serialItem = new JMenuItem("Connect to serial"); serialItem = new JMenuItem("Connect to serial");
serialItem.addActionListener(new SerialItemHandler()); serialItem.addActionListener(new SerialItemHandler());
fileMenu.add(serialItem); fileMenu.add(serialItem);
JMenuItem item = new JMenuItem("Program Sky nodes..."); fileMenu.add(new JMenuItem(moteProgramAction));
item.addActionListener(new ProgramItemHandler());
fileMenu.add(item);
fileMenu.addSeparator(); fileMenu.addSeparator();
final JMenuItem clearMapItem = new JMenuItem("Remove Map Background"); final JMenuItem clearMapItem = new JMenuItem("Remove Map Background");
@ -615,23 +626,24 @@ public class CollectServer implements SerialConnectionListener {
}); });
clearMapItem.setEnabled(mapPanel.getMapBackground() != null); clearMapItem.setEnabled(mapPanel.getMapBackground() != null);
item = new JMenuItem("Select Map Background..."); JMenuItem item = new JMenuItem("Select Map Background...");
item.addActionListener(new ActionListener() { item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (fileChooser == null) { if (fileChooser == null) {
fileChooser = new JFileChooser(); fileChooser = new JFileChooser();
int reply = fileChooser.showOpenDialog(window); }
if (reply == JFileChooser.APPROVE_OPTION) { int reply = fileChooser.showOpenDialog(window);
File file = fileChooser.getSelectedFile(); if (reply == JFileChooser.APPROVE_OPTION) {
String name = file.getAbsolutePath(); File file = fileChooser.getSelectedFile();
String name = file.getAbsolutePath();
if (!mapPanel.setMapBackground(file.getAbsolutePath())) {
JOptionPane.showMessageDialog(window, "Failed to set background image", "Error", JOptionPane.ERROR_MESSAGE);
} else {
configTable.put("collect.mapimage", name); configTable.put("collect.mapimage", name);
if (!mapPanel.setMapBackground(file.getAbsolutePath())) { save();
JOptionPane.showMessageDialog(window, "Failed to set background image", "Error", JOptionPane.ERROR_MESSAGE);
}
clearMapItem.setEnabled(mapPanel.getMapBackground() != null);
saveConfig(configTable, configFile);
} }
clearMapItem.setEnabled(mapPanel.getMapBackground() != null);
} }
} }
@ -639,6 +651,17 @@ public class CollectServer implements SerialConnectionListener {
fileMenu.add(item); fileMenu.add(item);
fileMenu.add(clearMapItem); 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(); fileMenu.addSeparator();
item = new JMenuItem("Clear Sensor Data..."); item = new JMenuItem("Clear Sensor Data...");
item.addActionListener(new ActionListener() { item.addActionListener(new ActionListener() {
@ -745,7 +768,7 @@ public class CollectServer implements SerialConnectionListener {
}); });
connectToSerial(); connectToSerial();
} }
protected void connectToSerial() { protected void connectToSerial() {
if (!serialConnection.isOpen()) { if (!serialConnection.isOpen()) {
String comPort = serialConnection.getComPort(); String comPort = serialConnection.getComPort();
@ -759,18 +782,7 @@ public class CollectServer implements SerialConnectionListener {
} }
private void exit() { private void exit() {
/* TODO Clean up resources */ 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);
}
if (serialConnection != null) { if (serialConnection != null) {
serialConnection.close(); serialConnection.close();
} }
@ -839,6 +851,10 @@ public class CollectServer implements SerialConnectionListener {
return configTable.getProperty(property, config.getProperty(property, defaultValue)); return configTable.getProperty(property, config.getProperty(property, defaultValue));
} }
public Action getMoteProgramAction() {
return moteProgramAction;
}
protected void setSystemMessage(final String message) { protected void setSystemMessage(final String message) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@ -970,6 +986,20 @@ public class CollectServer implements SerialConnectionListener {
return false; 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) { private void saveConfig(Properties properties, String configFile) {
try { try {
File fp = new File(configFile); 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; private boolean isRunning = false;
public MoteProgramAction(String name) {
super(name);
}
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (!isRunning) { if (!isRunning) {
isRunning = true; isRunning = true;
@ -1207,10 +1244,10 @@ public class CollectServer implements SerialConnectionListener {
mp.searchForMotes(); mp.searchForMotes();
String[] motes = mp.getMotes(); String[] motes = mp.getMotes();
if (motes == null || motes.length == 0) { 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; 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 + '?'); + "Do you want to upload the firmware " + FIRMWARE_FILE + '?');
if (reply == JFileChooser.APPROVE_OPTION) { if (reply == JFileChooser.APPROVE_OPTION) {
boolean wasOpen = serialConnection != null && serialConnection.isOpen(); boolean wasOpen = serialConnection != null && serialConnection.isOpen();
@ -1260,9 +1297,9 @@ public class CollectServer implements SerialConnectionListener {
if (!connection.isSerialOutputSupported()) { if (!connection.isSerialOutputSupported()) {
serialConsole.addSerialData("*** Serial output not supported ***"); serialConsole.addSerialData("*** Serial output not supported ***");
} else if (!hasSentInit) { } else if (doSendInitAtStartup) {
// Send any initial commands // Send any initial commands
hasSentInit = true; doSendInitAtStartup = false;
if (hasInitScript()) { if (hasInitScript()) {
// Wait a short time before running the init script // 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 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 * Authors : Niclas Finne
* Created : 27 sep 2010 * Created : 27 sep 2010
* Updated : $Date: 2010/10/12 11:39:59 $ * Updated : $Date: 2010/10/12 16:28:19 $
* $Revision: 1.5 $ * $Revision: 1.6 $
*/ */
package se.sics.contiki.collect.gui; package se.sics.contiki.collect.gui;
@ -43,15 +43,20 @@ import java.awt.BorderLayout;
import java.awt.Color; import java.awt.Color;
import java.awt.Component; import java.awt.Component;
import java.awt.Cursor; import java.awt.Cursor;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints; import java.awt.GridBagConstraints;
import java.awt.GridBagLayout; import java.awt.GridBagLayout;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JFormattedTextField; import javax.swing.JFormattedTextField;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextPane;
import javax.swing.border.LineBorder; import javax.swing.border.LineBorder;
import se.sics.contiki.collect.CollectServer; import se.sics.contiki.collect.CollectServer;
@ -70,6 +75,7 @@ public class NodeControl implements Visualizer {
private final String category; private final String category;
private final JPanel panel; private final JPanel panel;
private final JLabel statusLabel; private final JLabel statusLabel;
private final JSeparator statusSeparator;
public NodeControl(CollectServer server, String category) { public NodeControl(CollectServer server, String category) {
this.server = server; this.server = server;
@ -85,6 +91,8 @@ public class NodeControl implements Visualizer {
statusLabel.setBackground(Color.white); statusLabel.setBackground(Color.white);
statusLabel.setBorder(LineBorder.createBlackLineBorder()); statusLabel.setBorder(LineBorder.createBlackLineBorder());
statusLabel.setVisible(false); statusLabel.setVisible(false);
statusSeparator = new JSeparator();
statusSeparator.setVisible(false);
JButton stopButton = createCommandButton("Send stop to nodes", "netcmd killall"); JButton stopButton = createCommandButton("Send stop to nodes", "netcmd killall");
@ -115,10 +123,43 @@ public class NodeControl implements Visualizer {
c.fill = GridBagConstraints.HORIZONTAL; c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0.5; c.weightx = 0.5;
c.insets.left = c.insets.right = c.insets.bottom = 3; c.insets.left = c.insets.right = c.insets.bottom = 3;
c.insets.top = 10; c.anchor = GridBagConstraints.WEST;
c.gridy = 0; c.gridy = 0;
c.gridwidth = 3; 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); JLabel label = new JLabel("Collect Settings", JLabel.CENTER);
controlPanel.add(label, c); controlPanel.add(label, c);
c.gridwidth = 1; c.gridwidth = 1;
@ -150,27 +191,34 @@ public class NodeControl implements Visualizer {
c.gridy++; c.gridy++;
c.gridwidth = 3; c.gridwidth = 3;
c.weightx = 0; c.insets.bottom = 10;
c.fill = GridBagConstraints.NONE; JPanel nodePanel = new JPanel();
c.insets.bottom = 20; nodePanel.add(sendButton);
JPanel p = new JPanel(); nodePanel.add(stopButton);
p.add(sendButton); controlPanel.add(nodePanel, c);
p.add(stopButton);
controlPanel.add(p, c);
c.gridy++; c.gridy++;
c.insets.bottom = 3; controlPanel.add(new JSeparator(), c);
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);
panel.add(controlPanel, BorderLayout.NORTH); 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) { 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.setForeground(isWarning ? Color.red : Color.black);
statusLabel.setText(text); statusLabel.setText(text);
statusLabel.setVisible(true); statusLabel.setVisible(true);
statusSeparator.setVisible(true);
} }
public String getCategory() { public String getCategory() {