removing old visualizer plugins.

(replaced by a generic visualizer with skin support)
This commit is contained in:
fros4943 2009-03-24 15:44:25 +00:00
parent 96fbf3b853
commit 5c38c82608
5 changed files with 0 additions and 1750 deletions

View File

@ -1,136 +0,0 @@
/*
* Copyright (c) 2006, 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: VisBattery.java,v 1.5 2008/10/28 15:36:25 fros4943 Exp $
*/
package se.sics.cooja.plugins;
import java.awt.*;
import java.util.*;
import org.apache.log4j.Logger;
import se.sics.cooja.*;
import se.sics.cooja.interfaces.Battery;
/**
* A Battery Visualizer indicates mote energy levels by painting them in
* different colors. The mote is painted in a grayscale where white is max
* energy and black is no energy left. If a mote has no battery interface or
* infinite energy, it is painted blue. If a mote is dead it is painted red.
*
* A VisBattery observers both the simulation and all mote batteries.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Battery Visualizer")
@PluginType(PluginType.SIM_PLUGIN)
public class VisBattery extends Visualizer2D {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(VisBattery.class);
private Simulation simulation;
private Observer simObserver = null; // Watches simulation changes
private Observer batteryObserver = null; // Watches mote battery changes
/**
* Creates a new battery visualizer.
*
* @param simulationToVisualize
* Simulation to visualize
*/
public VisBattery(Simulation simulationToVisualize, GUI gui) {
super(simulationToVisualize, gui);
setTitle("Battery Visualizer");
simulation = simulationToVisualize;
// Always observe all motes in simulation
batteryObserver = new Observer() {
public void update(Observable obs, Object obj) {
getCurrentCanvas().repaint();
}
};
simulation.addObserver(simObserver = new Observer() {
public void update(Observable obs, Object obj) {
// Register (or reregister) as observer on all motes
for (int i = 0; i < simulation.getMotesCount(); i++) {
Battery battery = simulation.getMote(i).getInterfaces().getBattery();
if (battery != null) {
battery.addObserver(batteryObserver);
}
}
}
});
simObserver.update(null, null);
}
public Color[] getColorOf(Mote mote) {
if (mote.getState() == Mote.State.DEAD) {
return new Color[]{Color.RED};
}
Battery battery = mote.getInterfaces().getBattery();
if (battery == null) {
return new Color[]{Color.BLUE};
}
if (battery.hasInfiniteEnergy()) {
return new Color[]{Color.BLUE};
}
double currentEnergy = battery.getEnergyLeftRatio();
if (currentEnergy < 0.0) {
return new Color[]{Color.RED};
}
int grayValue = (int) (255 * currentEnergy);
return new Color[]{new Color(grayValue, grayValue, grayValue)};
}
public void closePlugin() {
if (simObserver != null) {
simulation.deleteObserver(simObserver);
// Delete all state observers
for (int i = 0; i < simulation.getMotesCount(); i++) {
Battery battery = simulation.getMote(i).getInterfaces().getBattery();
if (battery != null) {
battery.deleteObserver(batteryObserver);
}
}
}
super.closePlugin();
}
}

View File

@ -1,151 +0,0 @@
/*
* Copyright (c) 2006, 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: VisState.java,v 1.6 2009/03/10 21:20:39 fros4943 Exp $
*/
package se.sics.cooja.plugins;
import java.awt.*;
import java.util.*;
import org.apache.log4j.Logger;
import se.sics.cooja.*;
import se.sics.cooja.Mote.State;
/**
* A State Visualizer indicates mote states by painting them in different colors.
* Active motes are green, sleeping motes are gray and dead motes are read.
*
* The inner color indicates the mote type.
*
* A VisState observes both the simulation and all mote states.
*
* @author Fredrik Osterlind
*/
@ClassDescription("State Visualizer")
@PluginType(PluginType.SIM_STANDARD_PLUGIN)
public class VisState extends Visualizer2D {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(VisState.class);
private Simulation simulation;
private static final Color moteTypeColors[] = new Color[] {
Color.MAGENTA,
Color.CYAN,
Color.ORANGE,
Color.GREEN,
Color.BLUE,
Color.RED,
Color.YELLOW,
};
private Observer simObserver = null; // Watches simulation changes
private Observer stateObserver = null; // Watches mote state changes
/**
* Creates a new state visualizer.
*
* @param simulationToVisualize Simulation to visualize
*/
public VisState(Simulation simulationToVisualize, GUI gui) {
super(simulationToVisualize, gui);
setTitle("State Visualizer");
simulation = simulationToVisualize;
// Always observe all motes in simulation
stateObserver = new Observer() {
public void update(Observable obs, Object obj) {
getCurrentCanvas().repaint();
}
};
simulation.addObserver(simObserver = new Observer() {
public void update(Observable obs, Object obj) {
// Register (or reregister) as observer on all motes
for (int i=0; i < simulation.getMotesCount(); i++) {
Mote mote = simulation.getMote(i);
if (mote != null) {
mote.addStateObserver(stateObserver);
}
}
}
});
simObserver.update(null, null);
setLocation(
gui.getDesktopPane().getWidth() - getWidth(),
0);
}
public Color[] getColorOf(Mote mote) {
Color[] returnColors = new Color[2];
// If mote is sleeping, make outer circle blue
if (mote.getState() == Mote.State.LPM) {
returnColors[1] = Color.GRAY;
} else if (mote.getState() == State.DEAD) {
returnColors[1] = Color.RED;
} else {
returnColors[1] = Color.GREEN; // make outer circle green
}
// Associate different colors with different mote types
MoteType[] allTypes = simulation.getMoteTypes();
int numberOfTypes = allTypes.length;
for (int colCounter=0; colCounter < numberOfTypes && colCounter < moteTypeColors.length; colCounter++) {
if (mote.getType() == allTypes[colCounter]) {
returnColors[0] = moteTypeColors[colCounter];
return returnColors;
}
}
returnColors[0] = Color.WHITE;
return returnColors;
}
public void closePlugin() {
if (simObserver != null) {
simulation.deleteObserver(simObserver);
// Delete all state observers
for (int i=0; i < simulation.getMotesCount(); i++) {
Mote mote = simulation.getMote(i);
if (mote != null) {
mote.deleteStateObserver(stateObserver);
}
}
}
super.closePlugin();
}
}

View File

@ -1,239 +0,0 @@
/*
* Copyright (c) 2006, 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: VisTraffic.java,v 1.6 2007/02/28 09:50:00 fros4943 Exp $
*/
package se.sics.cooja.plugins;
import java.awt.*;
import java.util.*;
import javax.swing.SwingUtilities;
import org.apache.log4j.Logger;
import se.sics.cooja.*;
import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio;
/**
* A Traffic Visualizer visualizes radio traffic by painting lines between
* communicating motes.
*
* A VisTraffic observers the current simulation radio medium.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Traffic Visualizer")
@PluginType(PluginType.SIM_PLUGIN)
public class VisTraffic extends Visualizer2D {
protected boolean USE_ALPHA = false;
protected boolean USE_HISTORY = true;
protected int MAX_PAINTED_CONNS = 50;
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(VisTraffic.class);
private RadioMedium radioMedium;
public Vector<PaintedConnection> allPaintedConnections = new Vector<PaintedConnection>();
private Simulation simulation;
private Observer radioObserver = null;
/**
* Creates a new VisTraffic visualizer.
*
* @param simulationToVisualize
* Simulation to visualize
*/
public VisTraffic(Simulation simulationToVisualize, GUI gui) {
super(simulationToVisualize, gui);
setTitle("Traffic Visualizer");
simulation = simulationToVisualize;
radioMedium = simulationToVisualize.getRadioMedium();
// Listen to radio medium and paint any new data transfers
simulationToVisualize.getRadioMedium().addRadioMediumObserver(
radioObserver = new Observer() {
public void update(Observable obs, Object obj) {
if (radioMedium == null)
return;
final RadioConnection[] connsToAdd = radioMedium
.getLastTickConnections();
if (connsToAdd != null && connsToAdd.length > 0) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (!USE_HISTORY)
allPaintedConnections.clear();
for (RadioConnection conn : connsToAdd) {
if (conn != null) {
Color connColor = getColorOf(conn);
int duration = getDurationOf(conn);
if (connColor != null && duration > 0)
allPaintedConnections.add(0, new PaintedConnection(
conn, duration, connColor));
}
}
getCurrentCanvas().repaint();
}
});
}
}
});
}
/**
* Paints given connection on given graphics.
*
* @param connection
* Connection
* @param g2d
* Graphics to paint on
*/
protected void paintConnection(PaintedConnection connection, Graphics g2d) {
Point sourcePixelPosition = transformPositionToPixel(connection.radioConnection.getSource().getPosition());
g2d.setColor(connection.getColor(simulation.isRunning()));
for (Radio destRadio : connection.radioConnection.getDestinations()) {
Position destPosition = destRadio.getPosition();
Point destPixelPosition = transformPositionToPixel(destPosition);
g2d.drawLine(sourcePixelPosition.x, sourcePixelPosition.y,
destPixelPosition.x, destPixelPosition.y);
}
}
/**
* Returns color the given connection should be painted in. If returned color
* is null, the connection will not be painted.
*
* @param connection
* Connection
* @return Color
*/
protected Color getColorOf(RadioConnection connection) {
return Color.BLACK;
}
/**
* Returns duration the given connection should be visible. If negative, the
* connection will not be painted. Observe that the duration is the number of
* repaints, not related to time.
*
* @param connection
* Connection
* @return Duration in repaints
*/
protected int getDurationOf(RadioConnection connection) {
return 10;
}
public void closePlugin() {
super.closePlugin();
// Remove radio observer
radioMedium.deleteRadioMediumObserver(radioObserver);
}
public Color[] getColorOf(Mote m) {
return null;
}
protected void visualizeSimulation(Graphics g) {
// Clean up old connections
Vector<PaintedConnection> newPaintedConnections = new Vector<PaintedConnection>();
for (PaintedConnection conn : allPaintedConnections)
if (!conn.shouldBeRemoved())
newPaintedConnections.add(conn);
allPaintedConnections = newPaintedConnections;
if (allPaintedConnections.size() > MAX_PAINTED_CONNS)
allPaintedConnections.setSize(MAX_PAINTED_CONNS);
for (PaintedConnection conn : allPaintedConnections)
paintConnection(conn, (Graphics2D) g);
}
public class PaintedConnection {
public RadioConnection radioConnection;
private int duration;
private int colorVal;
private int repaintsLeft;
private Color staticColor;
/**
* @param conn
* Radio connection to visualize
* @param duration
* Number of repaints
* @param color
* Base color of painted connection
*/
public PaintedConnection(RadioConnection conn, int duration, Color color) {
radioConnection = conn;
colorVal = color.getRGB() & 0xffffff;
repaintsLeft = duration;
this.duration = duration;
staticColor = color;
}
/**
* Get color this connection should be painted in.
*
* @param isRunning
* True if current simulation is running
* @return Color
*/
public Color getColor(boolean isRunning) {
if (isRunning)
repaintsLeft--;
if (!USE_ALPHA)
return staticColor;
int alpha = 127 + 128 * repaintsLeft / duration;
return new Color(colorVal | (alpha << 24), true);
}
public boolean shouldBeRemoved() {
return repaintsLeft <= 0;
}
}
}

View File

@ -1,345 +0,0 @@
package se.sics.cooja.plugins;
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 java.util.Vector;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import se.sics.cooja.ClassDescription;
import se.sics.cooja.GUI;
import se.sics.cooja.Mote;
import se.sics.cooja.PluginType;
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.Visualizer2D;
import se.sics.cooja.radiomediums.UDGM;
/**
* Visualizes radio traffic in the UDGM radio medium.
* Allows a user to change the collective TX/interference ranges,
* and the TX/RX success ratio.
*
* Sending motes are blue, receiving motes are green and motes that hear noise
* are painted red. Motes without radios are painted gray, and the rest are
* white.
*
* @author Fredrik Osterlind
*/
@ClassDescription("UDGM Visualizer")
@PluginType(PluginType.SIM_PLUGIN)
public class VisUDGM extends Visualizer2D {
private JSpinner txRangeSpinner = null;
private JSpinner interferenceRangeSpinner = null;
private JSpinner successRatioTxSpinner = null;
private JSpinner successRatioRxSpinner = null;
private UDGM radioMedium = null;
private Observer radioMediumObserver;
private Mote selectedMote = null;
private class RangeMenuAction implements MoteMenuAction {
public boolean isEnabled(Mote mote) {
return true;
}
public String getDescription(Mote mote) {
return "Change transmission ranges";
}
public void doAction(Mote mote) {
txRangeSpinner.setVisible(true);
interferenceRangeSpinner.setVisible(true);
repaint();
}
};
private class SuccessRatioMenuAction implements MoteMenuAction {
public boolean isEnabled(Mote mote) {
return true;
}
public String getDescription(Mote mote) {
return "Change transmission success ratio";
}
public void doAction(Mote mote) {
successRatioTxSpinner.setVisible(true);
successRatioRxSpinner.setVisible(true);
repaint();
}
};
public VisUDGM(Simulation sim, GUI gui) {
super(sim, gui);
setTitle("UDGM Visualizer");
radioMedium = (UDGM) sim.getRadioMedium();
// Create spinners for changing ranges
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();
repaint();
}
});
interferenceRangeSpinner.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
radioMedium.INTERFERENCE_RANGE = ((SpinnerNumberModel)
interferenceRangeSpinner.getModel()).getNumber().doubleValue();
repaint();
}
});
successRatioTxSpinner.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
radioMedium.SUCCESS_RATIO_TX = ((SpinnerNumberModel)
successRatioTxSpinner.getModel()).getNumber().doubleValue();
repaint();
}
});
successRatioRxSpinner.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
radioMedium.SUCCESS_RATIO_RX = ((SpinnerNumberModel)
successRatioRxSpinner.getModel()).getNumber().doubleValue();
repaint();
}
});
getCurrentCanvas().add(txRangeSpinner);
getCurrentCanvas().add(interferenceRangeSpinner);
getCurrentCanvas().add(successRatioTxSpinner);
getCurrentCanvas().add(successRatioRxSpinner);
txRangeSpinner.setVisible(false);
interferenceRangeSpinner.setVisible(false);
successRatioTxSpinner.setVisible(false);
successRatioRxSpinner.setVisible(false);
/* Enable user to select mote by mouse click */
getCurrentCanvas().addMouseListener(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) {
Vector<Mote> clickedMotes = findMotesAtPosition(e.getX(), e.getY());
if (clickedMotes == null || clickedMotes.size() == 0) {
selectedMote = null;
txRangeSpinner.setVisible(false);
interferenceRangeSpinner.setVisible(false);
successRatioTxSpinner.setVisible(false);
successRatioRxSpinner.setVisible(false);
repaint();
return;
}
/* Several motes may have been clicked: select another one */
if (clickedMotes.contains(selectedMote)) {
int pos = clickedMotes.indexOf(selectedMote);
if (pos < clickedMotes.size() - 1) {
selectedMote = clickedMotes.get(pos + 1);
} else {
selectedMote = clickedMotes.firstElement();
}
} else {
selectedMote = clickedMotes.firstElement();
}
repaint();
}
});
// Register change ranges and change success ratio action
addMoteMenuAction(new RangeMenuAction());
addMoteMenuAction(new SuccessRatioMenuAction());
// Observe radio medium
radioMedium.addRadioMediumObserver(radioMediumObserver = new Observer() {
public void update(Observable obs, Object obj) {
getCurrentCanvas().repaint();
}
});
}
public void closePlugin() {
super.closePlugin();
radioMedium.deleteRadioMediumObserver(radioMediumObserver);
}
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 visualizeSimulation(Graphics g) {
/* Paint transmission and interference range for select mote */
if (selectedMote != null) {
Position motePos = selectedMote.getInterfaces().getPosition();
Point pixelCoord = 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 = transformPositionToPixel(0.0, 0.0, 0.0);
Point translatedInterference = transformPositionToPixel(moteInterferenceRange, moteInterferenceRange, 0.0);
Point translatedTransmission = 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
g.setColor(Color.DARK_GRAY);
g.fillOval(
x - translatedInterference.x,
y - translatedInterference.y,
2 * translatedInterference.x,
2 * translatedInterference.y);
// Transmission
g.setColor(Color.GREEN);
g.fillOval(
x - translatedTransmission.x,
y - translatedTransmission.y,
2 * translatedTransmission.x,
2 * translatedTransmission.y);
}
}
// Let parent paint motes
super.visualizeSimulation(g);
/* Paint active connections in black */
RadioConnection[] conns = radioMedium.getActiveConnections();
if (conns != null) {
g.setColor(Color.BLACK);
for (RadioConnection conn : conns) {
Point sourcePoint = transformPositionToPixel(conn.getSource().getPosition());
for (Radio destRadio : conn.getDestinations()) {
Position destPos = destRadio.getPosition();
Point destPoint = 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 = transformPositionToPixel(conn.getSource().getPosition());
for (Radio dest : conn.getDestinations()) {
Position destPos = dest.getPosition();
Point destPoint = transformPositionToPixel(destPos);
g.drawLine(sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y);
}
}
}
}
}

View File

@ -1,879 +0,0 @@
/*
* Copyright (c) 2006, 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: Visualizer2D.java,v 1.16 2009/02/26 13:29:30 fros4943 Exp $
*/
package se.sics.cooja.plugins;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.Timer;
import org.apache.log4j.Logger;
import se.sics.cooja.*;
import se.sics.cooja.GUI.MoteRelation;
import se.sics.cooja.interfaces.*;
/**
* Visualizer2D is an abstract mote visualizer for simulations. All motes are
* painted in the XY-plane, as seen from positive Z axis.
*
* An implementation of this class must colorize the different motes, each mote
* has two different colors; inner and outer.
*
* By right-clicking the mouse on a mote a popup menu will be displayed. From
* this menu mote plugins can be started. or the mote can be moved. Each
* implementation may also register its own actions to be accessed from this
* menu.
*
* A Visualizer2D observers both the simulation and all mote positions.
*
* @author Fredrik Osterlind
*/
@ClassDescription("2D Mote Visualizer")
@PluginType(PluginType.SIM_PLUGIN)
public abstract class Visualizer2D extends VisPlugin {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(Visualizer2D.class);
private double factorXCoordToPixel;
private double factorYCoordToPixel;
private double smallestXCoord;
private double smallestYCoord;
private GUI myGUI = null;
private Simulation simulation = null;
private final JPanel canvas;
private Visualizer2D myPlugin;
private static final int CANVAS_BORDER_WIDTH = 25;
private static final int MOTE_RADIUS = 8;
private boolean moteIsBeingMoved = false;
private long moteMoveBeginTime = -1;
private Mote moteToMove = null;
private Cursor moveCursor = new Cursor(Cursor.MOVE_CURSOR);
private Observer simObserver = null; // Watches simulation changes
private Observer posObserver = null; // Watches position changes
private Observer moteHighligtObserver = null;
private Observer moteRelationsObserver = null;
private Mote highlightedMote = null;
private Color highlightColor = Color.GRAY;
private Timer highlightTimer = null;
public interface MoteMenuAction {
public boolean isEnabled(Mote mote);
public String getDescription(Mote mote);
public void doAction(Mote mote);
}
private class MoveMoteMenuAction implements MoteMenuAction {
public boolean isEnabled(Mote mote) {
return true;
}
public String getDescription(Mote mote) {
return "Move " + mote;
}
public void doAction(Mote mote) {
moteMoveBeginTime = -1;
beginMoveRequest(mote);
}
};
private class ButtonClickMoteMenuAction implements MoteMenuAction {
public boolean isEnabled(Mote mote) {
return mote.getInterfaces().getButton() != null
&& !mote.getInterfaces().getButton().isPressed();
}
public String getDescription(Mote mote) {
return "Click button on " + mote;
}
public void doAction(Mote mote) {
mote.getInterfaces().getButton().clickButton();
}
};
private class DeleteMoteMenuAction implements MoteMenuAction {
public boolean isEnabled(Mote mote) {
return true;
}
public String getDescription(Mote mote) {
return "Delete " + mote;
}
public void doAction(Mote mote) {
simulation.removeMote(mote);
}
};
private class ShowLEDMoteMenuAction implements MoteMenuAction {
public boolean isEnabled(Mote mote) {
return mote.getInterfaces().getLED() != null;
}
public String getDescription(Mote mote) {
return "Show LEDs on " + mote;
}
public void doAction(Mote mote) {
LED led = mote.getInterfaces().getLED();
if (led == null) {
return;
}
/* Extract description (input to plugin) */
String desc = GUI.getDescriptionOf(mote.getInterfaces().getLED());
MoteInterfaceViewer viewer =
(MoteInterfaceViewer) simulation.getGUI().startPlugin(
MoteInterfaceViewer.class,
simulation.getGUI(),
simulation,
mote);
viewer.setSelectedInterface(desc);
viewer.pack();
}
};
private class ShowSerialMoteMenuAction implements MoteMenuAction {
public boolean isEnabled(Mote mote) {
SerialPort serialPort = null;
for (MoteInterface intf: mote.getInterfaces().getInterfaces()) {
try {
/* Try casting to serial port */
serialPort = (SerialPort) intf;
return true;
} catch (Exception e) {
}
}
return false;
}
public String getDescription(Mote mote) {
return "Show serial port on " + mote;
}
public void doAction(Mote mote) {
SerialPort serialPort = null;
for (MoteInterface intf: mote.getInterfaces().getInterfaces()) {
try {
/* Try casting to serial port */
serialPort = (SerialPort) intf;
break;
} catch (Exception e) {
}
}
if (serialPort == null) {
return;
}
/* Extract description (input to plugin) */
String desc = GUI.getDescriptionOf(serialPort);
MoteInterfaceViewer viewer =
(MoteInterfaceViewer) simulation.getGUI().startPlugin(
MoteInterfaceViewer.class,
simulation.getGUI(),
simulation,
mote);
viewer.setSelectedInterface(desc);
viewer.pack();
}
};
private Vector<MoteMenuAction> menuActions = new Vector<MoteMenuAction>();
/**
* Registers as an simulation observer and initializes the canvas.
*
* @param simulationToVisualize
* Simulation to visualize
*/
public Visualizer2D(Simulation simulationToVisualize, GUI gui) {
super("Visualizer2D", gui);
myGUI = gui;
myPlugin = this;
// Set initial bounds of frame
this.setBounds(150, 150, 300, 300);
setVisible(true);
simulation = simulationToVisualize;
// Create "canvas" to paint on
canvas = new JPanel() {
private static final long serialVersionUID = 1L;
public void paintComponent(Graphics g) {
super.paintComponent(g);
visualizeSimulation(g);
}
};
canvas.setPreferredSize(new Dimension(getSize().width - 16,
getSize().height - 38));
canvas.setBorder(BorderFactory.createLineBorder(Color.GREEN, 2));
canvas.setBackground(Color.WHITE);
calculateTransformations();
this.setContentPane(canvas);
// Detect general simulation changes
posObserver = new Observer() {
public void update(Observable obs, Object obj) {
calculateTransformations();
canvas.repaint();
}
};
simulation.addObserver(simObserver = new Observer() {
public void update(Observable obs, Object obj) {
canvas.setPreferredSize(new Dimension(getSize().width - 16,
getSize().height - 38));
// Register (or reregister) as observer on all mote positions
for (int i = 0; i < simulation.getMotesCount(); i++) {
Position posIntf = simulation.getMote(i).getInterfaces()
.getPosition();
if (posIntf != null) {
posIntf.addObserver(posObserver);
}
}
calculateTransformations();
canvas.repaint();
}
});
simObserver.update(null, null);
// Detect mote highligts
myGUI.addMoteHighlightObserver(moteHighligtObserver = new Observer() {
public void update(Observable obs, Object obj) {
if (!(obj instanceof Mote)) {
return;
}
if (highlightTimer != null && highlightTimer.isRunning()) {
highlightTimer.stop();
}
highlightTimer = new Timer(100, null);
highlightedMote = (Mote) obj;
highlightTimer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Decrease delay
if (highlightTimer.getDelay() < 90) {
highlightTimer.stop();
highlightedMote = null;
repaint();
return;
}
// Toggle color
if (highlightColor == Color.GRAY) {
highlightColor = Color.CYAN;
} else {
highlightColor = Color.GRAY;
}
highlightTimer.setDelay(highlightTimer.getDelay()-1);
repaint();
}
});
highlightTimer.start();
}
});
/* Paint mote relations */
myGUI.addMoteRelationsObserver(moteRelationsObserver = new Observer() {
public void update(Observable obs, Object obj) {
repaint();
}
});
canvas.addMouseMotionListener(new MouseMotionListener() {
public void mouseMoved(MouseEvent e) {
myPlugin.handleMoveRequest(e.getPoint().x, e.getPoint().y, false);
}
public void mouseDragged(MouseEvent e) {
myPlugin.handleMoveRequest(e.getPoint().x, e.getPoint().y, false);
}
});
// Detect mouse events
canvas.addMouseListener(new MouseListener() {
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) {
myPlugin.handlePopupRequest(e.getPoint().x, e.getPoint().y);
} else if (SwingUtilities.isLeftMouseButton(e)){
//myPlugin.handleMoveRequest(e.getPoint().x, e.getPoint().y, false);
beginMoveRequest(e.getPoint().x, e.getPoint().y);
}
}
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
myPlugin.handlePopupRequest(e.getPoint().x, e.getPoint().y);
} else {
myPlugin.handleMoveRequest(e.getPoint().x, e.getPoint().y, true);
}
}
public void mouseEntered(MouseEvent e) {
if (e.isPopupTrigger()) {
myPlugin.handlePopupRequest(e.getPoint().x, e.getPoint().y);
}
}
public void mouseExited(MouseEvent e) {
if (e.isPopupTrigger()) {
myPlugin.handlePopupRequest(e.getPoint().x, e.getPoint().y);
}
}
public void mouseClicked(MouseEvent e) {
if (e.isPopupTrigger()) {
myPlugin.handlePopupRequest(e.getPoint().x, e.getPoint().y);
}
}
});
// Detect component events
addComponentListener(new ComponentListener() {
public void componentMoved(ComponentEvent ce) {
// NOP
}
public void componentShown(ComponentEvent ce) {
// NOP
}
public void componentHidden(ComponentEvent ce) {
// NOP
}
public void componentResized(ComponentEvent ce) {
canvas.setPreferredSize(new Dimension(getSize().width - 16,
getSize().height - 38));
calculateTransformations();
canvas.repaint();
}
});
// Add menu action for moving motes
addMoteMenuAction(new MoveMoteMenuAction());
/* Add some commonly used mote interface actions */
addMoteMenuAction(new ButtonClickMoteMenuAction());
addMoteMenuAction(new ShowLEDMoteMenuAction());
addMoteMenuAction(new ShowSerialMoteMenuAction());
// Add menu action for deleting mote
addMoteMenuAction(new DeleteMoteMenuAction());
try {
setSelected(true);
} catch (java.beans.PropertyVetoException e) {
// Could not select
}
/* Drag and drop files to motes */
DropTargetListener dTargetListener = new DropTargetListener() {
public void dragEnter(DropTargetDragEvent dtde) {
if (acceptOrRejectDrag(dtde)) {
dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
} else {
dtde.rejectDrag();
}
}
public void dragExit(DropTargetEvent dte) {
}
public void dropActionChanged(DropTargetDragEvent dtde) {
if (acceptOrRejectDrag(dtde)) {
dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
} else {
dtde.rejectDrag();
}
}
public void dragOver(DropTargetDragEvent dtde) {
if (acceptOrRejectDrag(dtde)) {
dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
} else {
dtde.rejectDrag();
}
}
public void drop(DropTargetDropEvent dtde) {
Transferable transferable = dtde.getTransferable();
/* Only accept single files */
File file = null;
if (!transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
dtde.rejectDrop();
return;
}
dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
try {
List<Object> transferList = Arrays.asList(
transferable.getTransferData(DataFlavor.javaFileListFlavor)
);
if (transferList.size() != 1) {
return;
}
List<File> list = (List<File>) transferList.get(0);
if (list.size() != 1) {
return;
}
file = list.get(0);
}
catch (Exception e) {
return;
}
if (file == null || !file.exists()) {
return;
}
handleDropFile(file, dtde.getLocation());
}
private boolean acceptOrRejectDrag(DropTargetDragEvent dtde) {
Transferable transferable = dtde.getTransferable();
/* Make sure one, and only one, mote exists under mouse pointer */
Point point = dtde.getLocation();
Vector<Mote> motes = findMotesAtPosition(point.x, point.y);
if (motes == null || motes.size() != 1) {
return false;
}
/* Only accept single files */
File file;
if (!transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
return false;
}
try {
List<Object> transferList = Arrays.asList(
transferable.getTransferData(DataFlavor.javaFileListFlavor)
);
if (transferList.size() != 1) {
return false;
}
List<File> list = (List<File>) transferList.get(0);
if (list.size() != 1) {
return false;
}
file = list.get(0);
} catch (UnsupportedFlavorException e) {
return false;
} catch (IOException e) {
return false;
}
/* Extract file extension */
return isDropFileAccepted(file);
}
};
canvas.setDropTarget(
new DropTarget(canvas, DnDConstants.ACTION_COPY_OR_MOVE, dTargetListener, true, null)
);
}
/**
* Add new mote menu action.
*
* @see MoteMenuAction
* @param menuAction Menu action
*/
public void addMoteMenuAction(MoteMenuAction menuAction) {
menuActions.add(menuAction);
}
private void handlePopupRequest(final int x, final int y) {
final Vector<Mote> foundMotes = findMotesAtPosition(x, y);
if (foundMotes == null || foundMotes.size() == 0) {
return;
}
JPopupMenu pickMoteMenu = new JPopupMenu();
pickMoteMenu.add(new JLabel("Select action:"));
pickMoteMenu.add(new JSeparator());
// Add 'show mote plugins'-actions
for (final Mote mote : foundMotes) {
pickMoteMenu.add(simulation.getGUI().createMotePluginsSubmenu(mote));
}
// Add the rest of the actions
for (final MoteMenuAction menuAction : menuActions) {
for (final Mote mote : foundMotes) {
if (menuAction.isEnabled(mote)) {
JMenuItem menuItem = new JMenuItem(menuAction.getDescription(mote));
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
menuAction.doAction(mote);
}
});
pickMoteMenu.add(menuItem);
}
}
}
// Show menu
Point pos = new Point(canvas.getLocationOnScreen().x + x, canvas
.getLocationOnScreen().y
+ y);
pickMoteMenu.setLocation(pos.x, pos.y);
pickMoteMenu.setInvoker(canvas);
pickMoteMenu.setVisible(true);
}
private void beginMoveRequest(final int x, final int y) {
final Vector<Mote> foundMotes = findMotesAtPosition(x, y);
if (foundMotes == null || foundMotes.size() == 0) {
return;
}
moteMoveBeginTime = System.currentTimeMillis();
beginMoveRequest(foundMotes.get(0));
}
private void beginMoveRequest(Mote moteToMove) {
moteIsBeingMoved = true;
this.moteToMove = moteToMove;
canvas.repaint();
}
private void handleMoveRequest(final int x, final int y,
boolean wasJustReleased) {
if (!moteIsBeingMoved) {
return;
}
if (!wasJustReleased) {
// Still moving mote
canvas.setCursor(moveCursor);
return;
}
// Stopped moving mote
canvas.setCursor(Cursor.getDefaultCursor());
moteIsBeingMoved = false;
Position newXYValues = transformPixelToPositon(new Point(x, y));
if (moteMoveBeginTime <= 0 || System.currentTimeMillis() - moteMoveBeginTime > 300) {
int returnValue = JOptionPane.showConfirmDialog(myPlugin, "Move mote to"
+ "\nX=" + newXYValues.getXCoordinate() + "\nY="
+ newXYValues.getYCoordinate() + "\nZ="
+ moteToMove.getInterfaces().getPosition().getZCoordinate());
if (returnValue == JOptionPane.OK_OPTION) {
moteToMove.getInterfaces().getPosition().setCoordinates(
newXYValues.getXCoordinate(), newXYValues.getYCoordinate(),
moteToMove.getInterfaces().getPosition().getZCoordinate());
}
}
moteMoveBeginTime = -1;
moteToMove = null;
repaint();
}
/**
* Returns all motes at given position.
*
* @param clickedX
* X coordinate
* @param clickedY
* Y coordinate
* @return All motes at given position
*/
protected Vector<Mote> findMotesAtPosition(int clickedX, int clickedY) {
double xCoord = factorXPixelToCoord(clickedX);
double yCoord = factorYPixelToCoord(clickedY);
Vector<Mote> motesFound = new Vector<Mote>();
// Calculate painted mote radius in coordinates
double paintedMoteWidth = factorXPixelToCoord(MOTE_RADIUS)
- factorXPixelToCoord(0);
double paintedMoteHeight = factorYPixelToCoord(MOTE_RADIUS)
- factorYPixelToCoord(0);
for (int i = 0; i < simulation.getMotesCount(); i++) {
Position pos = simulation.getMote(i).getInterfaces().getPosition();
// Transform to unit circle before checking if mouse hit this mote
double distanceX = Math.abs(xCoord - pos.getXCoordinate())
/ paintedMoteWidth;
double distanceY = Math.abs(yCoord - pos.getYCoordinate())
/ paintedMoteHeight;
if (distanceX * distanceX + distanceY * distanceY <= 1) {
motesFound.add(simulation.getMote(i));
}
}
if (motesFound.size() == 0) {
return null;
}
return motesFound;
}
/**
* Get colors a certain mote should be painted with. May be overridden to get
* a different color scheme.
*
* Normally this method returns an array of two colors, one for the state
* (outer circle), the other for the type (inner circle).
*
* If this method only returns one color, the entire mote will be painted
* using that.
*
* @param mote
* Mote to paint
* @return Color[] { Inner color, Outer color }
*/
abstract public Color[] getColorOf(Mote mote);
protected void visualizeSimulation(Graphics g) {
Mote[] allMotes = simulation.getMotes();
for (Mote mote: allMotes) {
Color moteColors[] = getColorOf(mote);
Position motePos = mote.getInterfaces().getPosition();
Point pixelCoord = transformPositionToPixel(motePos);
int x = pixelCoord.x;
int y = pixelCoord.y;
if (mote == highlightedMote) {
g.setColor(highlightColor);
g.fillOval(x - MOTE_RADIUS, y - MOTE_RADIUS, 2 * MOTE_RADIUS,
2 * MOTE_RADIUS);
} else if (mote == moteToMove) {
// Don't fill mote
} else if (moteColors.length >= 2) {
g.setColor(moteColors[0]);
g.fillOval(x - MOTE_RADIUS, y - MOTE_RADIUS, 2 * MOTE_RADIUS,
2 * MOTE_RADIUS);
g.setColor(moteColors[1]);
g.fillOval(x - MOTE_RADIUS / 2, y - MOTE_RADIUS / 2, MOTE_RADIUS,
MOTE_RADIUS);
} else if (moteColors.length >= 1) {
g.setColor(moteColors[0]);
g.fillOval(x - MOTE_RADIUS, y - MOTE_RADIUS, 2 * MOTE_RADIUS,
2 * MOTE_RADIUS);
}
g.setColor(Color.BLACK);
g.drawOval(x - MOTE_RADIUS, y - MOTE_RADIUS, 2 * MOTE_RADIUS,
2 * MOTE_RADIUS);
}
/* Paint mote relations */
MoteRelation[] relations = simulation.getGUI().getMoteRelations();
for (MoteRelation r: relations) {
Position sourcePos = r.source.getInterfaces().getPosition();
Position destPos = r.dest.getInterfaces().getPosition();
Point sourcePoint = transformPositionToPixel(sourcePos);
Point destPoint = transformPositionToPixel(destPos);
Point middlePoint = new Point(
(destPoint.x*9 + sourcePoint.x*1)/10,
(destPoint.y*9 + sourcePoint.y*1)/10
);
/* "Arrow body" is painted gray */
g.setColor(Color.LIGHT_GRAY);
g.drawLine(sourcePoint.x, sourcePoint.y, middlePoint.x, middlePoint.y);
/* "Arrow head" is painted black */
g.setColor(Color.BLACK);
g.drawLine(middlePoint.x, middlePoint.y, destPoint.x, destPoint.y);
}
}
/**
* Recalculate size of canvas and factors for transforming between real and
* pixel coordinates. This method is called every time this frame is resized
* or created.
*/
protected void calculateTransformations() {
if (simulation.getMotesCount() == 0) {
smallestXCoord = 0;
smallestYCoord = 0;
factorXCoordToPixel = 1;
factorYCoordToPixel = 1;
return;
}
double biggestXCoord, biggestYCoord;
Position motePos = simulation.getMote(0).getInterfaces().getPosition();
smallestXCoord = biggestXCoord = motePos.getXCoordinate();
smallestYCoord = biggestYCoord = motePos.getYCoordinate();
// Get extreme coordinates
for (int i = 0; i < simulation.getMotesCount(); i++) {
motePos = simulation.getMote(i).getInterfaces().getPosition();
if (motePos.getXCoordinate() < smallestXCoord) {
smallestXCoord = motePos.getXCoordinate();
}
if (motePos.getXCoordinate() > biggestXCoord) {
biggestXCoord = motePos.getXCoordinate();
}
if (motePos.getYCoordinate() < smallestYCoord) {
smallestYCoord = motePos.getYCoordinate();
}
if (motePos.getYCoordinate() > biggestYCoord) {
biggestYCoord = motePos.getYCoordinate();
}
}
if ((biggestXCoord - smallestXCoord) == 0) {
factorXCoordToPixel = 1;
} else {
factorXCoordToPixel = ((double) canvas.getPreferredSize().width - 2 * CANVAS_BORDER_WIDTH)
/ (biggestXCoord - smallestXCoord);
}
if ((biggestYCoord - smallestYCoord) == 0) {
factorYCoordToPixel = 1;
} else {
factorYCoordToPixel = ((double) canvas.getPreferredSize().height - 2 * CANVAS_BORDER_WIDTH)
/ (biggestYCoord - smallestYCoord);
}
}
/**
* Transforms a real-world position to a pixel which can be painted onto the
* current sized canvas.
*
* @param pos
* Real-world position
* @return Pixel coordinates
*/
public Point transformPositionToPixel(Position pos) {
return new Point(factorXCoordToPixel(pos.getXCoordinate()),
factorYCoordToPixel(pos.getYCoordinate()));
}
/**
* Transforms real-world coordinates to a pixel which can be painted onto the
* current sized canvas.
*
* @param x Real world X
* @param y Real world Y
* @param z Real world Z (ignored)
* @return Pixel coordinates
*/
public Point transformPositionToPixel(double x, double y, double z) {
return new Point(factorXCoordToPixel(x), factorYCoordToPixel(y));
}
/**
* Transforms a pixel coordinate to a real-world. Z-value will always be 0.
*
* @param pixelPos
* On-screen pixel coordinate
* @return Real world coordinate (z=0).
*/
public Position transformPixelToPositon(Point pixelPos) {
Position dummyPosition = new Position(null);
dummyPosition.setCoordinates(factorXPixelToCoord(pixelPos.x),
factorYPixelToCoord(pixelPos.y), 0.0);
return dummyPosition;
}
/**
* @return The current canvas to paint on
*/
public JPanel getCurrentCanvas() {
return canvas;
}
private int factorXCoordToPixel(double xCoordinate) {
return (int) ((xCoordinate - smallestXCoord) * factorXCoordToPixel + CANVAS_BORDER_WIDTH);
}
private int factorYCoordToPixel(double yCoordinate) {
return (int) ((yCoordinate - smallestYCoord) * factorYCoordToPixel)
+ CANVAS_BORDER_WIDTH;
}
private double factorXPixelToCoord(int xPixel) {
return ((xPixel - CANVAS_BORDER_WIDTH) / factorXCoordToPixel)
+ smallestXCoord;
}
private double factorYPixelToCoord(int yPixel) {
return ((yPixel - CANVAS_BORDER_WIDTH) / factorYCoordToPixel)
+ smallestYCoord;
}
public void closePlugin() {
if (moteHighligtObserver != null) {
myGUI.deleteMoteHighlightObserver(moteHighligtObserver);
}
if (moteRelationsObserver != null) {
myGUI.deleteMoteRelationsObserver(moteRelationsObserver);
}
if (simObserver != null) {
simulation.deleteObserver(simObserver);
for (int i = 0; i < simulation.getMotesCount(); i++) {
Position posIntf = simulation.getMote(i).getInterfaces().getPosition();
if (posIntf != null) {
posIntf.deleteObserver(posObserver);
}
}
}
}
protected boolean isDropFileAccepted(File file) {
return true; /* TODO */
}
protected void handleDropFile(File file, Point point) {
logger.fatal("Drag and drop not implemented: " + file);
}
}