[cooja] plugins/VariableWatcher: Implemented formatted output for value fields

This commit is contained in:
Enrico Joerns 2014-08-27 16:43:08 +02:00
parent 053b1d55af
commit a1671462c0

View File

@ -40,17 +40,21 @@ import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
@ -63,10 +67,9 @@ import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultFormatterFactory;
import javax.swing.text.DocumentFilter;
import javax.swing.text.PlainDocument;
import org.jdom.Element;
import org.contikios.cooja.ClassDescription;
import org.contikios.cooja.Cooja;
import org.contikios.cooja.Mote;
@ -76,6 +79,7 @@ import org.contikios.cooja.Simulation;
import org.contikios.cooja.VisPlugin;
import org.contikios.cooja.mote.memory.UnknownVariableException;
import org.contikios.cooja.mote.memory.VarMemory;
import org.jdom.Element;
/**
* Variable Watcher enables a user to watch mote variables during a simulation.
@ -108,6 +112,7 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
private JComboBox varTypeCombo;
private JComboBox varFormatCombo;
private JFormattedTextField[] varValues;
private byte[] bufferedBytes;
private JTextField[] charValues;
private JFormattedTextField varLength;
private JButton writeButton;
@ -118,6 +123,7 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
private FocusAdapter jFormattedTextFocusAdapter;
private NumberFormat integerFormat;
private ValueFormatter hf;
private Mote mote;
@ -258,33 +264,30 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
JPanel reprPanel = new JPanel(new BorderLayout());
varTypeCombo = new JComboBox(valueTypes);
varTypeCombo.addItemListener(new ItemListener() {
varTypeCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int selectedIndex = varTypeCombo.getSelectedIndex();
if (selectedIndex == ARRAY_INDEX || selectedIndex == CHAR_ARRAY_INDEX) {
lengthPane.setVisible(true);
setNumberOfValues(((Number) varLength.getValue()).intValue());
if(selectedIndex == CHAR_ARRAY_INDEX) {
charValuePane.setVisible(true);
setNumberOfCharValues(((Number) varLength.getValue()).intValue());
} else {
charValuePane.setVisible(false);
setNumberOfCharValues(1);
}
} else {
lengthPane.setVisible(false);
charValuePane.setVisible(false);
setNumberOfValues(1);
setNumberOfCharValues(1);
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
hf.setType((VarTypes) e.getItem());
updateNumberOfValues(); // number of elements should have changed
}
pack();
}
});
varFormatCombo = new JComboBox(valueFormats);
varFormatCombo.setSelectedItem(VarFormats.HEX);
varFormatCombo.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
hf.setFormat((VarFormats) e.getItem());
refreshValues(); // format of elements should have changed
}
}
});
reprPanel.add(BorderLayout.WEST, varTypeCombo);
reprPanel.add(BorderLayout.EAST, varFormatCombo);
@ -345,6 +348,10 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
valuePane = new JPanel();
valuePane.setLayout(new BoxLayout(valuePane, BoxLayout.X_AXIS));
hf = new ValueFormatter(
(VarTypes) varTypeCombo.getSelectedItem(),
(VarFormats) varFormatCombo.getSelectedItem());
varValues = new JFormattedTextField[1];
varValues[0] = new JFormattedTextField(integerFormat);
varValues[0].setValue(new Integer(0));
@ -578,6 +585,170 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
pack();
}
/**
* String to Value to String conversion for JFormattedTextField
* based on selected VarTypes and VarFormats.
*/
public class ValueFormatter extends JFormattedTextField.AbstractFormatter {
final String TEXT_NOT_TO_TOUCH;
private VarTypes mType;
private VarFormats mFormat;
public ValueFormatter(VarTypes type, VarFormats format) {
mType = type;
mFormat = format;
if (mFormat == VarFormats.HEX) {
TEXT_NOT_TO_TOUCH = "0x";
}
else {
TEXT_NOT_TO_TOUCH = "";
}
}
public void setType(VarTypes type) {
mType = type;
}
public void setFormat(VarFormats format) {
mFormat = format;
}
@Override
public Object stringToValue(String text) throws ParseException {
Object ret;
switch (mFormat) {
case CHAR:
ret = text.charAt(0);
break;
case DEC:
case HEX:
try {
ret = Integer.decode(text);
}
catch (NumberFormatException ex) {
ret = 0;
}
break;
default:
ret = null;
}
return ret;
}
@Override
public String valueToString(Object value) throws ParseException {
if (value == null) {
return "?";
}
switch (mFormat) {
case CHAR:
return String.format("%c", value);
case DEC:
return String.format("%d", value);
case HEX:
return String.format("0x%x", value);
default:
return "";
}
}
/* Do not override TEXT_NOT_TO_TOUCH */
@Override
public DocumentFilter getDocumentFilter() {
return new DocumentFilter() {
@Override
public void insertString(DocumentFilter.FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
if (offset < TEXT_NOT_TO_TOUCH.length()) {
return;
}
super.insertString(fb, offset, string, attr);
}
@Override
public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
if (offset < TEXT_NOT_TO_TOUCH.length()) {
length = Math.max(0, length - TEXT_NOT_TO_TOUCH.length());
offset = TEXT_NOT_TO_TOUCH.length();
}
super.replace(fb, offset, length, text, attrs);
}
@Override
public void remove(DocumentFilter.FilterBypass fb, int offset, int length) throws BadLocationException {
if (offset < TEXT_NOT_TO_TOUCH.length()) {
length = Math.max(0, length + offset - TEXT_NOT_TO_TOUCH.length());
offset = TEXT_NOT_TO_TOUCH.length();
}
if (length > 0) {
super.remove(fb, offset, length);
}
}
};
}
}
/**
* Updates all value fields based on buffered data.
*/
private void refreshValues() {
int bytes = moteMemory.getVariableSize((String) varNameCombo.getSelectedItem());
int typeSize = ((VarTypes) varTypeCombo.getSelectedItem()).getBytes();
int elements = (int) Math.ceil((double) bytes / typeSize);
/* Skip if we have no data to set */
if ((bufferedBytes == null) || (bufferedBytes.length < bytes)) {
return;
}
/* Set values based on buffered data */
for (int i = 0; i < elements; i += 1) {
int val = 0;
for (int j = 0; j < typeSize; j++) {
val += ((bufferedBytes[i * typeSize + j] & 0xFF) << (j * 8));
}
varValues[i].setValue(val);
try {
varValues[i].commitEdit();
}
catch (ParseException ex) {
Logger.getLogger(VariableWatcher.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
/**
* Updates number of value fields.
*/
private void updateNumberOfValues() {
valuePane.removeAll();
DefaultFormatterFactory defac = new DefaultFormatterFactory(hf);
long address = moteMemory.getVariableAddress((String) varNameCombo.getSelectedItem());
int bytes = moteMemory.getVariableSize((String) varNameCombo.getSelectedItem());
int typeSize = ((VarTypes) varTypeCombo.getSelectedItem()).getBytes();
int elements = (int) Math.ceil((double) bytes / typeSize);
if (elements > 0) {
varValues = new JFormattedTextField[elements];
for (int i = 0; i < elements; i++) {
varValues[i] = new JFormattedTextField(defac);
valuePane.add(varValues[i]);
}
}
refreshValues();
pack();
}
private void setNumberOfValues(int nr) {
valuePane.removeAll();