removing old visualizer plugins.
(replaced by a generic visualizer with skin support)
This commit is contained in:
parent
96fbf3b853
commit
5c38c82608
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user