a few simple visualizer skins

This commit is contained in:
fros4943 2009-03-24 15:46:29 +00:00
parent b7840178a1
commit b949a036f2
5 changed files with 805 additions and 0 deletions

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2009, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: BasicVisualizerSkin.java,v 1.1 2009/03/24 15:46:29 fros4943 Exp $
*/
package se.sics.cooja.plugins.skins;
import java.awt.Color;
import java.awt.Graphics;
import org.apache.log4j.Logger;
import se.sics.cooja.ClassDescription;
import se.sics.cooja.Mote;
import se.sics.cooja.Simulation;
import se.sics.cooja.plugins.Visualizer;
import se.sics.cooja.plugins.VisualizerSkin;
/**
* Basic visualizer skin. Paints all motes black.
*
* @author Fredrik Osterlind
*/
@ClassDescription("[select visualizer skin]")
public class BasicVisualizerSkin implements VisualizerSkin {
private static Logger logger = Logger.getLogger(BasicVisualizerSkin.class);
private Visualizer visualizer = null;
public void setActive(Simulation simulation, Visualizer vis) {
this.visualizer = vis;
}
public void setInactive() {
}
public Color[] getColorOf(Mote mote) {
return new Color[] { Color.BLACK };
}
public void paintSkin(Graphics g) {
/* Just paint motes */
visualizer.paintSkinGeneric(g);
}
}

View File

@ -0,0 +1,139 @@
/*
* Copyright (c) 2009, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: LEDVisualizerSkin.java,v 1.1 2009/03/24 15:46:29 fros4943 Exp $
*/
package se.sics.cooja.plugins.skins;
import java.awt.Color;
import java.awt.Graphics;
import java.util.Observable;
import java.util.Observer;
import org.apache.log4j.Logger;
import se.sics.cooja.ClassDescription;
import se.sics.cooja.Mote;
import se.sics.cooja.Simulation;
import se.sics.cooja.interfaces.LED;
import se.sics.cooja.plugins.Visualizer;
import se.sics.cooja.plugins.VisualizerSkin;
/**
* Visualizer skin for LEDs.
*
* Colors motes according to current LED state.
*
* @author Fredrik Osterlind
*/
@ClassDescription("LEDs")
public class LEDVisualizerSkin implements VisualizerSkin {
private static Logger logger = Logger.getLogger(LEDVisualizerSkin.class);
private Simulation simulation = null;
private Visualizer visualizer = null;
private Observer ledObserver = new Observer() {
public void update(Observable obs, Object obj) {
visualizer.repaint();
}
};
private Observer simObserver = new Observer() {
public void update(Observable obs, Object obj) {
/* Observe LEDs */
for (Mote mote: simulation.getMotes()) {
LED led = mote.getInterfaces().getLED();
if (led != null) {
led.addObserver(ledObserver);
}
}
visualizer.repaint();
}
};
public void setActive(Simulation simulation, Visualizer vis) {
this.simulation = simulation;
this.visualizer = vis;
simulation.addObserver(simObserver);
simObserver.update(null, null);
}
public void setInactive() {
simulation.deleteObserver(simObserver);
for (Mote mote: simulation.getMotes()) {
LED led = mote.getInterfaces().getLED();
if (led != null) {
led.deleteObserver(ledObserver);
}
}
}
public Color[] getColorOf(Mote mote) {
LED led = mote.getInterfaces().getLED();
if (led == null) {
return new Color[] { Color.GRAY };
}
if (!led.isAnyOn()) {
return new Color[] { Color.BLACK };
}
if (led.isGreenOn() && led.isRedOn() && led.isYellowOn()) {
return new Color[] { Color.WHITE };
}
if (led.isRedOn()) {
if (led.isGreenOn()) {
return new Color[] { Color.RED, Color.GREEN };
}
if (led.isYellowOn()) {
return new Color[] { Color.RED, Color.YELLOW };
}
return new Color[] { Color.RED };
}
if (led.isGreenOn()) {
if (led.isYellowOn()) {
return new Color[] { Color.YELLOW, Color.GREEN };
}
return new Color[] { Color.GREEN };
}
if (led.isYellowOn()) {
return new Color[] { Color.YELLOW };
}
return new Color[] { Color.BLACK };
}
public void paintSkin(Graphics g) {
visualizer.paintSkinGeneric(g);
}
}

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2009, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: LogLEDVisualizerSkin.java,v 1.1 2009/03/24 15:46:29 fros4943 Exp $
*/
package se.sics.cooja.plugins.skins;
import java.awt.Color;
import java.awt.Graphics;
import org.apache.log4j.Logger;
import se.sics.cooja.ClassDescription;
import se.sics.cooja.Mote;
import se.sics.cooja.Simulation;
import se.sics.cooja.plugins.Visualizer;
import se.sics.cooja.plugins.VisualizerSkin;
/**
* Visualizer skin for both Log output and LEDs.
*
* @see LEDVisualizerSkin
* @see LogVisualizerSkin
* @author Fredrik Osterlind
*/
@ClassDescription("printf()'s + LEDs")
public class LogLEDVisualizerSkin implements VisualizerSkin {
private static Logger logger = Logger.getLogger(LogLEDVisualizerSkin.class);
private LEDVisualizerSkin ledSkin = new LEDVisualizerSkin();
private LogVisualizerSkin logSkin = new LogVisualizerSkin();
public void setActive(Simulation simulation, Visualizer vis) {
ledSkin.setActive(simulation, vis);
logSkin.setActive(simulation, vis);
}
public void setInactive() {
ledSkin.setInactive();
logSkin.setInactive();
}
public Color[] getColorOf(Mote mote) {
return ledSkin.getColorOf(mote);
}
public void paintSkin(Graphics g) {
logSkin.paintSkin(g);
}
}

View File

@ -0,0 +1,130 @@
/*
* Copyright (c) 2009, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: LogVisualizerSkin.java,v 1.1 2009/03/24 15:46:29 fros4943 Exp $
*/
package se.sics.cooja.plugins.skins;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Observable;
import java.util.Observer;
import org.apache.log4j.Logger;
import se.sics.cooja.ClassDescription;
import se.sics.cooja.Mote;
import se.sics.cooja.Simulation;
import se.sics.cooja.interfaces.Log;
import se.sics.cooja.interfaces.Position;
import se.sics.cooja.plugins.Visualizer;
import se.sics.cooja.plugins.VisualizerSkin;
/**
* Visualizer skin for Log output.
*
* Paints the last log message above each mote.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Log output: printf()'s")
public class LogVisualizerSkin implements VisualizerSkin {
private static Logger logger = Logger.getLogger(LogVisualizerSkin.class);
private Simulation simulation = null;
private Visualizer visualizer = null;
private Observer logObserver = new Observer() {
public void update(Observable obs, Object obj) {
visualizer.repaint();
}
};
private Observer simObserver = new Observer() {
public void update(Observable obs, Object obj) {
/* Observe logs */
for (Mote mote: simulation.getMotes()) {
Log log = mote.getInterfaces().getLog();
if (log != null) {
log.addObserver(logObserver);
}
}
visualizer.repaint();
}
};
public void setActive(Simulation simulation, Visualizer vis) {
this.simulation = simulation;
this.visualizer = vis;
simulation.addObserver(simObserver);
simObserver.update(null, null);
}
public void setInactive() {
simulation.deleteObserver(simObserver);
for (Mote mote: simulation.getMotes()) {
Log log = mote.getInterfaces().getLog();
if (log != null) {
log.deleteObserver(logObserver);
}
}
}
public Color[] getColorOf(Mote mote) {
return new Color[] { Color.BLACK };
}
public void paintSkin(Graphics g) {
visualizer.paintSkinGeneric(g);
FontMetrics fm = g.getFontMetrics();
/* Paint last output below motes */
Mote[] allMotes = simulation.getMotes();
for (Mote mote: allMotes) {
Log log = mote.getInterfaces().getLog();
if (log == null) {
continue;
}
String msg = log.getLastLogMessage();
if (msg == null) {
continue;
}
Position pos = mote.getInterfaces().getPosition();
Point pixel = visualizer.transformPositionToPixel(pos);
int msgWidth = fm.stringWidth(msg);
g.drawString(msg, pixel.x - msgWidth/2, pixel.y - Visualizer.MOTE_RADIUS);
}
}
}

View File

@ -0,0 +1,390 @@
/*
* Copyright (c) 2009, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: UDGMVisualizerSkin.java,v 1.1 2009/03/24 15:46:29 fros4943 Exp $
*/
package se.sics.cooja.plugins.skins;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.apache.log4j.Logger;
import se.sics.cooja.ClassDescription;
import se.sics.cooja.Mote;
import se.sics.cooja.RadioConnection;
import se.sics.cooja.Simulation;
import se.sics.cooja.contikimote.interfaces.ContikiRadio;
import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio;
import se.sics.cooja.plugins.Visualizer;
import se.sics.cooja.plugins.VisualizerSkin;
import se.sics.cooja.plugins.Visualizer.SimulationMenuAction;
import se.sics.cooja.radiomediums.UDGM;
/**
* Visualizer skin for Unit Disk Graph radio medium.
*
* Allows a user to change the collective TX/interference ranges,
* and the TX/RX success ratio.
*
* Transmitting motes are painted blue.
* Receiving motes are painted green.
* Interfered motes are painted red.
* Motes without radios are painted gray.
* All other motes are painted white.
*
* @see UDGM
* @author Fredrik Osterlind
*/
@ClassDescription("Radio environment (UDGM)")
public class UDGMVisualizerSkin implements VisualizerSkin {
private static Logger logger = Logger.getLogger(UDGMVisualizerSkin.class);
private Simulation simulation = null;
private Visualizer visualizer = null;
private UDGM radioMedium = null;
private Observer radioMediumObserver;
private JSpinner txRangeSpinner = null;
private JSpinner interferenceRangeSpinner = null;
private JSpinner successRatioTxSpinner = null;
private JSpinner successRatioRxSpinner = null;
private Mote selectedMote = null;
private MouseListener selectMoteMouseListener = new MouseListener() {
public void mouseExited(MouseEvent e) { }
public void mouseEntered(MouseEvent e) { }
public void mouseReleased(MouseEvent e) { }
public void mouseClicked(MouseEvent e) { }
public void mousePressed(MouseEvent e) {
Mote[] motes = visualizer.findMotesAtPosition(e.getX(), e.getY());
if (motes == null || motes.length == 0) {
selectedMote = null;
txRangeSpinner.setVisible(false);
interferenceRangeSpinner.setVisible(false);
successRatioTxSpinner.setVisible(false);
successRatioRxSpinner.setVisible(false);
visualizer.repaint();
return;
}
selectedMote = motes[0];
visualizer.repaint();
}
};
public void setActive(Simulation simulation, Visualizer vis) {
this.simulation = simulation;
this.visualizer = vis;
this.radioMedium = (UDGM) simulation.getRadioMedium();
/* Spinner GUI components */
SpinnerNumberModel transmissionModel = new SpinnerNumberModel();
transmissionModel.setValue(new Double(radioMedium.TRANSMITTING_RANGE));
transmissionModel.setStepSize(new Double(1.0)); // 1m
transmissionModel.setMinimum(new Double(0.0));
SpinnerNumberModel interferenceModel = new SpinnerNumberModel();
interferenceModel.setValue(new Double(radioMedium.INTERFERENCE_RANGE));
interferenceModel.setStepSize(new Double(1.0)); // 1m
interferenceModel.setMinimum(new Double(0.0));
SpinnerNumberModel successRatioTxModel = new SpinnerNumberModel();
successRatioTxModel.setValue(new Double(radioMedium.SUCCESS_RATIO_TX));
successRatioTxModel.setStepSize(new Double(0.001)); // 0.1%
successRatioTxModel.setMinimum(new Double(0.0));
successRatioTxModel.setMaximum(new Double(1.0));
SpinnerNumberModel successRatioRxModel = new SpinnerNumberModel();
successRatioRxModel.setValue(new Double(radioMedium.SUCCESS_RATIO_RX));
successRatioRxModel.setStepSize(new Double(0.001)); // 0.1%
successRatioRxModel.setMinimum(new Double(0.0));
successRatioRxModel.setMaximum(new Double(1.0));
JSpinner.NumberEditor editor;
txRangeSpinner = new JSpinner(transmissionModel);
editor = new JSpinner.NumberEditor(txRangeSpinner, "0m");
txRangeSpinner.setEditor(editor);
interferenceRangeSpinner = new JSpinner(interferenceModel);
editor = new JSpinner.NumberEditor(interferenceRangeSpinner, "0m");
interferenceRangeSpinner.setEditor(editor);
successRatioTxSpinner = new JSpinner(successRatioTxModel);
editor = new JSpinner.NumberEditor(successRatioTxSpinner, "0.0%");
successRatioTxSpinner.setEditor(editor);
successRatioRxSpinner = new JSpinner(successRatioRxModel);
editor = new JSpinner.NumberEditor(successRatioRxSpinner, "0.0%");
successRatioRxSpinner.setEditor(editor);
((JSpinner.DefaultEditor) txRangeSpinner.getEditor()).getTextField().setColumns(5);
((JSpinner.DefaultEditor) interferenceRangeSpinner.getEditor()).getTextField().setColumns(5);
((JSpinner.DefaultEditor) successRatioTxSpinner.getEditor()).getTextField().setColumns(5);
((JSpinner.DefaultEditor) successRatioRxSpinner.getEditor()).getTextField().setColumns(5);
txRangeSpinner.setToolTipText("Transmitting range (m)");
interferenceRangeSpinner.setToolTipText("Interference range (m)");
successRatioTxSpinner.setToolTipText("Transmission success ratio (%)");
successRatioRxSpinner.setToolTipText("Reception success ratio (%)");
txRangeSpinner.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
radioMedium.TRANSMITTING_RANGE = ((SpinnerNumberModel)
txRangeSpinner.getModel()).getNumber().doubleValue();
visualizer.repaint();
}
});
interferenceRangeSpinner.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
radioMedium.INTERFERENCE_RANGE = ((SpinnerNumberModel)
interferenceRangeSpinner.getModel()).getNumber().doubleValue();
visualizer.repaint();
}
});
successRatioTxSpinner.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
radioMedium.SUCCESS_RATIO_TX = ((SpinnerNumberModel)
successRatioTxSpinner.getModel()).getNumber().doubleValue();
visualizer.repaint();
}
});
successRatioRxSpinner.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
radioMedium.SUCCESS_RATIO_RX = ((SpinnerNumberModel)
successRatioRxSpinner.getModel()).getNumber().doubleValue();
visualizer.repaint();
}
});
txRangeSpinner.setVisible(false);
interferenceRangeSpinner.setVisible(false);
successRatioTxSpinner.setVisible(false);
successRatioRxSpinner.setVisible(false);
/* Register mouse listener */
visualizer.getCurrentCanvas().addMouseListener(selectMoteMouseListener);
/* Register menu actions */
visualizer.registerSimulationMenuAction(RangeMenuAction.class);
visualizer.registerSimulationMenuAction(SuccessRatioMenuAction.class);
/* Add (currently invisible) spinners */
visualizer.getCurrentCanvas().add(txRangeSpinner);
visualizer.getCurrentCanvas().add(interferenceRangeSpinner);
visualizer.getCurrentCanvas().add(successRatioTxSpinner);
visualizer.getCurrentCanvas().add(successRatioRxSpinner);
/* Start observing radio medium */
radioMedium.addRadioMediumObserver(radioMediumObserver = new Observer() {
public void update(Observable obs, Object obj) {
visualizer.repaint();
}
});
}
public void setInactive() {
/* Remove mouse listener */
visualizer.getCurrentCanvas().removeMouseListener(selectMoteMouseListener);
/* Stop observing radio medium */
radioMedium.deleteRadioMediumObserver(radioMediumObserver);
radioMediumObserver = null;
radioMedium = null;
/* Remove spinners */
visualizer.getCurrentCanvas().remove(txRangeSpinner);
visualizer.getCurrentCanvas().remove(interferenceRangeSpinner);
visualizer.getCurrentCanvas().remove(successRatioTxSpinner);
visualizer.getCurrentCanvas().remove(successRatioRxSpinner);
/* Unregister menu actions */
visualizer.unregisterSimulationMenuAction(RangeMenuAction.class);
visualizer.unregisterSimulationMenuAction(SuccessRatioMenuAction.class);
}
public Color[] getColorOf(Mote mote) {
Radio moteRadio = mote.getInterfaces().getRadio();
if (moteRadio == null) {
return new Color[] { Color.BLACK };
}
if (mote.getState() == Mote.State.DEAD) {
return new Color[] { Color.BLACK };
}
if (selectedMote != null && mote == selectedMote) {
return new Color[] { Color.CYAN };
}
if (moteRadio instanceof ContikiRadio && !((ContikiRadio) moteRadio).isOn()) {
return new Color[] { Color.GRAY };
}
if (moteRadio.isTransmitting()) {
return new Color[] { Color.BLUE };
}
if (moteRadio.isInterfered()) {
return new Color[] { Color.RED };
}
if (moteRadio.isReceiving()) {
return new Color[] { Color.GREEN };
}
return new Color[] { Color.WHITE };
}
public void paintSkin(Graphics g) {
/* Paint transmission and interference range for select mote */
if (selectedMote != null) {
Position motePos = selectedMote.getInterfaces().getPosition();
Point pixelCoord = visualizer.transformPositionToPixel(motePos);
int x = pixelCoord.x;
int y = pixelCoord.y;
// Fetch current output power indicator (scale with as percent)
if (selectedMote.getInterfaces().getRadio() != null) {
Radio selectedRadio = selectedMote.getInterfaces().getRadio();
double moteInterferenceRange =
radioMedium.INTERFERENCE_RANGE
* ((double) selectedRadio.getCurrentOutputPowerIndicator()
/ (double) selectedRadio.getOutputPowerIndicatorMax());
double moteTransmissionRange =
radioMedium.TRANSMITTING_RANGE
* ((double) selectedRadio.getCurrentOutputPowerIndicator()
/ (double) selectedRadio.getOutputPowerIndicatorMax());
Point translatedZero = visualizer.transformPositionToPixel(0.0, 0.0, 0.0);
Point translatedInterference = visualizer.transformPositionToPixel(moteInterferenceRange, moteInterferenceRange, 0.0);
Point translatedTransmission = visualizer.transformPositionToPixel(moteTransmissionRange, moteTransmissionRange, 0.0);
translatedInterference.x = Math.abs(translatedInterference.x - translatedZero.x);
translatedInterference.y = Math.abs(translatedInterference.y - translatedZero.y);
translatedTransmission.x = Math.abs(translatedTransmission.x - translatedZero.x);
translatedTransmission.y = Math.abs(translatedTransmission.y - translatedZero.y);
/* Interference range */
g.setColor(Color.DARK_GRAY);
g.fillOval(
x - translatedInterference.x,
y - translatedInterference.y,
2 * translatedInterference.x,
2 * translatedInterference.y);
/* Transmission range */
g.setColor(Color.GREEN);
g.fillOval(
x - translatedTransmission.x,
y - translatedTransmission.y,
2 * translatedTransmission.x,
2 * translatedTransmission.y);
}
}
/* Skin generic visualization */
visualizer.paintSkinGeneric(g);
/* Paint active connections in black */
RadioConnection[] conns = radioMedium.getActiveConnections();
if (conns != null) {
g.setColor(Color.BLACK);
for (RadioConnection conn : conns) {
Point sourcePoint = visualizer.transformPositionToPixel(conn.getSource().getPosition());
for (Radio destRadio : conn.getDestinations()) {
Position destPos = destRadio.getPosition();
Point destPoint = visualizer.transformPositionToPixel(destPos);
g.drawLine(sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y);
}
}
}
/* Paint past connections in gray */
conns = radioMedium.getLastTickConnections();
if (conns != null) {
g.setColor(Color.GRAY);
for (RadioConnection conn : conns) {
Point sourcePoint = visualizer.transformPositionToPixel(conn.getSource().getPosition());
for (Radio dest : conn.getDestinations()) {
Position destPos = dest.getPosition();
Point destPoint = visualizer.transformPositionToPixel(destPos);
g.drawLine(sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y);
}
}
}
}
protected static class RangeMenuAction implements SimulationMenuAction {
public boolean isEnabled(Simulation simulation) {
return true;
}
public String getDescription(Simulation simulation) {
return "Change transmission ranges";
}
public void doAction(Visualizer visualizer, Simulation simulation) {
UDGMVisualizerSkin skin = (UDGMVisualizerSkin) visualizer.getCurrentSkin();
skin.txRangeSpinner.setVisible(true);
skin.interferenceRangeSpinner.setVisible(true);
visualizer.repaint();
}
};
protected static class SuccessRatioMenuAction implements SimulationMenuAction {
public boolean isEnabled(Simulation simulation) {
return true;
}
public String getDescription(Simulation simulation) {
return "Change TX/RX success ratio";
}
public void doAction(Visualizer visualizer, Simulation simulation) {
UDGMVisualizerSkin skin = (UDGMVisualizerSkin) visualizer.getCurrentSkin();
skin.successRatioTxSpinner.setVisible(true);
skin.successRatioRxSpinner.setVisible(true);
visualizer.repaint();
}
};
}