[cooja] plugins/Visualizer: Multi-mote selection functionality
This adds multi-mote selection capabilities to the visualizer plugin: - [Ctrl + Mouse Drag]: Rectangular selection of multiple motes - [Ctrl + Mouse Click]: Add/Remove motes from current selection - Mouse Drag on any selected Mote: Move all currently selected motes Note: This changes previous behaviour of using Ctrl key.
This commit is contained in:
parent
a7dbf46b8e
commit
22ac769781
4 changed files with 298 additions and 173 deletions
|
@ -33,6 +33,7 @@ import java.awt.Color;
|
|||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Point;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
@ -72,20 +73,23 @@ public class MRMVisualizerSkin implements VisualizerSkin {
|
|||
}
|
||||
|
||||
public Color[] getColorOf(Mote mote) {
|
||||
Mote selectedMote = visualizer.getSelectedMote();
|
||||
if (mote == selectedMote) {
|
||||
if (visualizer.getSelectedMotes().contains(mote)) {
|
||||
return new Color[] { Color.CYAN };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void paintBeforeMotes(Graphics g) {
|
||||
final Mote selectedMote = visualizer.getSelectedMote();
|
||||
if (simulation == null
|
||||
|| selectedMote == null
|
||||
|| selectedMote.getInterfaces().getRadio() == null) {
|
||||
Set<Mote> selectedMotes = visualizer.getSelectedMotes();
|
||||
if (simulation == null || selectedMotes == null || selectedMotes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Mote selectedMote = visualizer.getSelectedMotes().iterator().next();
|
||||
if (selectedMote.getInterfaces().getRadio() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Position sPos = selectedMote.getInterfaces().getPosition();
|
||||
|
||||
/* Paint transmission and interference range for selected mote */
|
||||
|
|
|
@ -30,10 +30,12 @@
|
|||
|
||||
package org.contikios.cooja.plugins;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Event;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
|
@ -55,7 +57,7 @@ import java.awt.event.ItemListener;
|
|||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseMotionListener;
|
||||
import java.awt.event.MouseMotionAdapter;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
import java.awt.geom.AffineTransform;
|
||||
|
@ -64,9 +66,14 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
|
@ -74,7 +81,6 @@ import javax.swing.JCheckBoxMenuItem;
|
|||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JSeparator;
|
||||
|
@ -128,6 +134,7 @@ import org.contikios.cooja.plugins.skins.UDGMVisualizerSkin;
|
|||
* @see #registerVisualizerSkin(Class)
|
||||
* @see UDGMVisualizerSkin
|
||||
* @author Fredrik Osterlind
|
||||
* @author Enrico Jorns
|
||||
*/
|
||||
@ClassDescription("Network")
|
||||
@PluginType(PluginType.SIM_STANDARD_PLUGIN)
|
||||
|
@ -149,20 +156,34 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
|||
private AffineTransform viewportTransform;
|
||||
public int resetViewport = 0;
|
||||
|
||||
/* Actions: move motes, pan view, and zoom view */
|
||||
private boolean panning = false;
|
||||
private Position panningPosition = null; /* Panning start position */
|
||||
private boolean zooming = false;
|
||||
private double zoomStart = 0;
|
||||
private Position zoomingPosition = null; /* Zooming center position */
|
||||
private Point zoomingPixel = null; /* Zooming center pixel */
|
||||
private boolean moving = false;
|
||||
private Point mouseDownPixel = null; /* Records position of mouse down to differentiate a click from a move */
|
||||
private Mote movedMote = null;
|
||||
public Mote clickedMote = null;
|
||||
private static final int SELECT_MASK = Event.CTRL_MASK;
|
||||
private static final int MOVE_MASK = Event.SHIFT_MASK;
|
||||
|
||||
enum MotesActionState {
|
||||
|
||||
UNKNWON,
|
||||
SELECT_PRESS,
|
||||
DEFAULT_PRESS,
|
||||
PAN_PRESS,
|
||||
PANNING,
|
||||
MOVING,
|
||||
// rectangular select
|
||||
SELECTING
|
||||
}
|
||||
|
||||
/* All selected motes */
|
||||
public Set<Mote> selectedMotes = new HashSet<>();
|
||||
/* Mote that was under curser while mouse press */
|
||||
Mote cursorMote;
|
||||
|
||||
MotesActionState mouseActionState = MotesActionState.UNKNWON;
|
||||
/* Position where mouse button was pressed */
|
||||
Position pressedPos;
|
||||
|
||||
private Set<Mote> movedMotes = null;
|
||||
private long moveStartTime = -1;
|
||||
private boolean moveConfirm;
|
||||
private Cursor moveCursor = new Cursor(Cursor.MOVE_CURSOR);
|
||||
private static final Cursor MOVE_CURSOR = new Cursor(Cursor.MOVE_CURSOR);
|
||||
private Selection selection;
|
||||
|
||||
/* Visualizers */
|
||||
private static ArrayList<Class<? extends VisualizerSkin>> visualizerSkins =
|
||||
|
@ -277,6 +298,7 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
|||
});
|
||||
zoomMenu.add(resetViewportItem);
|
||||
|
||||
selection = new Selection();
|
||||
/* Main canvas */
|
||||
canvas = new JPanel() {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -296,6 +318,7 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
|||
for (VisualizerSkin skin: currentSkins) {
|
||||
skin.paintAfterMotes(g);
|
||||
}
|
||||
selection.drawSelection(g);
|
||||
}
|
||||
};
|
||||
canvas.setBackground(Color.WHITE);
|
||||
|
@ -378,18 +401,16 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
|||
});
|
||||
|
||||
/* Popup menu */
|
||||
canvas.addMouseMotionListener(new MouseMotionListener() {
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
handleMouseMove(e, false);
|
||||
}
|
||||
canvas.addMouseMotionListener(new MouseMotionAdapter() {
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
handleMouseMove(e, false);
|
||||
handleMouseDrag(e, false);
|
||||
}
|
||||
});
|
||||
canvas.addMouseListener(new MouseAdapter() {
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (e.isPopupTrigger()) {
|
||||
handlePopupRequest(e.getPoint().x, e.getPoint().y);
|
||||
handlePopupRequest(e.getPoint());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -399,19 +420,13 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
|||
}
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
if (e.isPopupTrigger()) {
|
||||
handlePopupRequest(e.getPoint().x, e.getPoint().y);
|
||||
handlePopupRequest(e.getPoint());
|
||||
return;
|
||||
}
|
||||
|
||||
handleMouseMove(e, true);
|
||||
}
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.isPopupTrigger()) {
|
||||
handlePopupRequest(e.getPoint().x, e.getPoint().y);
|
||||
if (SwingUtilities.isLeftMouseButton(e)) {
|
||||
handleMouseRelease(e);
|
||||
}
|
||||
|
||||
handleMouseMove(e, true);
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
canvas.addMouseWheelListener(new MouseWheelListener() {
|
||||
|
@ -645,11 +660,11 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
|||
visualizerSkins.remove(skin);
|
||||
}
|
||||
|
||||
private void handlePopupRequest(final int x, final int y) {
|
||||
private void handlePopupRequest(Point point) {
|
||||
JPopupMenu menu = new JPopupMenu();
|
||||
|
||||
/* Mote specific actions */
|
||||
final Mote[] motes = findMotesAtPosition(x, y);
|
||||
final Mote[] motes = findMotesAtPosition(point.x, point.y);
|
||||
if (motes != null && motes.length > 0) {
|
||||
menu.add(new JSeparator());
|
||||
|
||||
|
@ -679,7 +694,7 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
|||
|
||||
/* Simulation specific actions */
|
||||
menu.add(new JSeparator());
|
||||
for (Class<? extends SimulationMenuAction> menuActionClass: simulationMenuActions) {
|
||||
for (Class<? extends SimulationMenuAction> menuActionClass : simulationMenuActions) {
|
||||
try {
|
||||
final SimulationMenuAction menuAction = menuActionClass.newInstance();
|
||||
if (menuAction.isEnabled(this, simulation)) {
|
||||
|
@ -709,8 +724,8 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
|||
|
||||
/* Show menu */
|
||||
menu.setLocation(new Point(
|
||||
canvas.getLocationOnScreen().x + x,
|
||||
canvas.getLocationOnScreen().y + y));
|
||||
canvas.getLocationOnScreen().x + point.x,
|
||||
canvas.getLocationOnScreen().y + point.y));
|
||||
menu.setInvoker(canvas);
|
||||
menu.setVisible(true);
|
||||
}
|
||||
|
@ -826,43 +841,169 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
|||
private void handleMousePress(MouseEvent mouseEvent) {
|
||||
int x = mouseEvent.getX();
|
||||
int y = mouseEvent.getY();
|
||||
clickedMote = null;
|
||||
|
||||
if (mouseEvent.isControlDown()) {
|
||||
/* Zoom */
|
||||
zooming = true;
|
||||
zoomingPixel = new Point(x, y);
|
||||
zoomingPosition = transformPixelToPosition(zoomingPixel);
|
||||
zoomStart = viewportTransform.getScaleX();
|
||||
return;
|
||||
pressedPos = transformPixelToPosition(mouseEvent.getPoint());
|
||||
|
||||
// this is the state we have from pressing button
|
||||
final Mote[] foundMotes = findMotesAtPosition(x, y);
|
||||
if (foundMotes == null) {
|
||||
cursorMote = null;
|
||||
}
|
||||
else {
|
||||
// select top mote
|
||||
cursorMote = foundMotes[foundMotes.length - 1];
|
||||
}
|
||||
|
||||
final Mote[] motes = findMotesAtPosition(x, y);
|
||||
if (mouseEvent.isShiftDown() ||
|
||||
(!mouseEvent.isAltDown() && (motes == null || motes.length == 0))) {
|
||||
/* No motes clicked or shift pressed: We should pan */
|
||||
panning = true;
|
||||
panningPosition = transformPixelToPosition(x, y);
|
||||
return;
|
||||
}
|
||||
int modifiers = mouseEvent.getModifiers();
|
||||
|
||||
if (motes != null && motes.length > 0) {
|
||||
/* One of the clicked motes should be moved */
|
||||
mouseDownPixel = new Point(x, y);
|
||||
clickedMote = motes[0];
|
||||
beginMoveRequest(motes[0], false, false);
|
||||
/* translate input */
|
||||
if ((modifiers & SELECT_MASK) != 0) {
|
||||
mouseActionState = MotesActionState.SELECT_PRESS;
|
||||
}
|
||||
else if ((modifiers & MOVE_MASK) != 0) {
|
||||
// only move viewport
|
||||
mouseActionState = MotesActionState.PAN_PRESS;
|
||||
}
|
||||
else {
|
||||
if (foundMotes == null) {
|
||||
// move viewport
|
||||
selectedMotes.clear();
|
||||
}
|
||||
else {
|
||||
// if this mote was not selected before, assume a new selection
|
||||
if (!selectedMotes.contains(cursorMote)) {
|
||||
selectedMotes.clear();
|
||||
selectedMotes.add(cursorMote);
|
||||
}
|
||||
}
|
||||
mouseActionState = MotesActionState.DEFAULT_PRESS;
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
|
||||
Map<Mote, double[]> moveStartPositions = new HashMap<>();
|
||||
|
||||
private void handleMouseDrag(MouseEvent e, boolean stop) {
|
||||
Position currPos = transformPixelToPosition(e.getPoint());
|
||||
|
||||
switch (mouseActionState) {
|
||||
case DEFAULT_PRESS:
|
||||
if (cursorMote == null) {
|
||||
mouseActionState = MotesActionState.PANNING;
|
||||
}
|
||||
else {
|
||||
mouseActionState = MotesActionState.MOVING;
|
||||
// save start position
|
||||
for (Mote m : selectedMotes) {
|
||||
Position pos = m.getInterfaces().getPosition();
|
||||
moveStartPositions.put(m, new double[]{
|
||||
pos.getXCoordinate(),
|
||||
pos.getYCoordinate(),
|
||||
pos.getZCoordinate()});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MOVING:
|
||||
canvas.setCursor(MOVE_CURSOR);
|
||||
for (Mote moveMote : selectedMotes) {
|
||||
moveMote.getInterfaces().getPosition().setCoordinates(
|
||||
moveStartPositions.get(moveMote)[0]
|
||||
+ (currPos.getXCoordinate() - pressedPos.getXCoordinate()),
|
||||
moveStartPositions.get(moveMote)[1]
|
||||
+ (currPos.getYCoordinate() - pressedPos.getYCoordinate()),
|
||||
moveStartPositions.get(moveMote)[2]
|
||||
);
|
||||
repaint();
|
||||
}
|
||||
break;
|
||||
case PAN_PRESS:
|
||||
mouseActionState = MotesActionState.PANNING;
|
||||
break;
|
||||
case PANNING:
|
||||
/* The current mouse position should correspond to where panning started */
|
||||
viewportTransform.translate(
|
||||
currPos.getXCoordinate() - pressedPos.getXCoordinate(),
|
||||
currPos.getYCoordinate() - pressedPos.getYCoordinate()
|
||||
);
|
||||
repaint();
|
||||
break;
|
||||
case SELECT_PRESS:
|
||||
mouseActionState = MotesActionState.SELECTING;
|
||||
selection.setEnabled(true);
|
||||
break;
|
||||
case SELECTING:
|
||||
int pressedX = transformToPixelX(pressedPos.getXCoordinate());
|
||||
int pressedY = transformToPixelY(pressedPos.getYCoordinate());
|
||||
int currX = transformToPixelX(currPos.getXCoordinate());
|
||||
int currY = transformToPixelY(currPos.getYCoordinate());
|
||||
int startX = pressedX < currX ? pressedX : currX;
|
||||
int startY = pressedY < currY ? pressedY : currY;
|
||||
int width = Math.abs(pressedX - currX);
|
||||
int height = Math.abs(pressedY - currY);
|
||||
|
||||
selection.setSelection(startX, startY, width, height);
|
||||
selectedMotes.clear();
|
||||
selectedMotes.addAll(Arrays.asList(findMotesInRange(startX, startY, width, height)));
|
||||
|
||||
repaint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void beginMoveRequest(Mote moteToMove, boolean withTiming, boolean confirm) {
|
||||
private void handleMouseRelease(MouseEvent mouseEvent) {
|
||||
|
||||
switch (mouseActionState) {
|
||||
case PAN_PRESS:
|
||||
// ignore
|
||||
break;
|
||||
case SELECT_PRESS:
|
||||
if (cursorMote == null) {
|
||||
/* Click on free canvas deselects all mote */
|
||||
selectedMotes.clear();
|
||||
}
|
||||
else {
|
||||
/* toggle selection for mote */
|
||||
if (selectedMotes.contains(cursorMote)) {
|
||||
selectedMotes.remove(cursorMote);
|
||||
}
|
||||
else {
|
||||
selectedMotes.add(cursorMote);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DEFAULT_PRESS:
|
||||
if (cursorMote == null) {
|
||||
/* Click on free canvas deselects all mote */
|
||||
selectedMotes.clear();
|
||||
}
|
||||
else {
|
||||
/* Click on mote selects single mote */
|
||||
selectedMotes.clear();
|
||||
selectedMotes.add(cursorMote);
|
||||
}
|
||||
break;
|
||||
case MOVING:
|
||||
/* Release stops moving */
|
||||
canvas.setCursor(Cursor.getDefaultCursor());
|
||||
break;
|
||||
case SELECTING:
|
||||
/* Release stops moving */
|
||||
selection.setEnabled(false);
|
||||
repaint();
|
||||
break;
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
|
||||
private void beginMoveRequest(Mote motesToMove, boolean withTiming, boolean confirm) {
|
||||
if (withTiming) {
|
||||
moveStartTime = System.currentTimeMillis();
|
||||
} else {
|
||||
moveStartTime = -1;
|
||||
}
|
||||
moving = true;
|
||||
moveConfirm = confirm;
|
||||
movedMote = moteToMove;
|
||||
mouseActionState = MotesActionState.DEFAULT_PRESS;
|
||||
selectedMotes.clear();
|
||||
selectedMotes.add(motesToMove);
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
@ -888,107 +1029,37 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
|||
repaint();
|
||||
}
|
||||
|
||||
private void handleMouseMove(MouseEvent e, boolean stop) {
|
||||
int x = e.getX();
|
||||
int y = e.getY();
|
||||
|
||||
/* Panning */
|
||||
if (panning) {
|
||||
if (panningPosition == null || stop) {
|
||||
panning = false;
|
||||
return;
|
||||
/**
|
||||
* Returns all motes in rectangular range
|
||||
*
|
||||
* @param startX
|
||||
* @param startY
|
||||
* @param width
|
||||
* @param height
|
||||
* @return All motes in range
|
||||
*/
|
||||
public Mote[] findMotesInRange(int startX, int startY, int width, int height) {
|
||||
List<Mote> motes = new LinkedList<>();
|
||||
for (Mote m : simulation.getMotes()) {
|
||||
Position pos = m.getInterfaces().getPosition();
|
||||
int moteX = transformToPixelX(pos.getXCoordinate());
|
||||
int moteY = transformToPixelY(pos.getYCoordinate());
|
||||
if (moteX > startX && moteX < startX + width
|
||||
&& moteY > startY && moteY < startY + height) {
|
||||
motes.add(m);
|
||||
}
|
||||
|
||||
/* The current mouse position should correspond to where panning started */
|
||||
Position moved = transformPixelToPosition(x,y);
|
||||
viewportTransform.translate(
|
||||
moved.getXCoordinate() - panningPosition.getXCoordinate(),
|
||||
moved.getYCoordinate() - panningPosition.getYCoordinate()
|
||||
);
|
||||
repaint();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Zooming */
|
||||
if (zooming) {
|
||||
if (zoomingPosition == null || zoomingPixel == null || stop) {
|
||||
zooming = false;
|
||||
return;
|
||||
}
|
||||
|
||||
/* The zooming start pixel should correspond to the zooming center position */
|
||||
/* The current mouse position should correspond to where panning started */
|
||||
double zoomFactor = 1.0 + Math.abs((double) zoomingPixel.y - y)/100.0;
|
||||
double newZoom = (zoomingPixel.y - y)>0?zoomStart*zoomFactor: zoomStart/zoomFactor;
|
||||
if (newZoom < 0.00001) {
|
||||
newZoom = 0.00001;
|
||||
}
|
||||
viewportTransform.setToScale(
|
||||
newZoom,
|
||||
newZoom
|
||||
);
|
||||
Position moved = transformPixelToPosition(zoomingPixel);
|
||||
viewportTransform.translate(
|
||||
moved.getXCoordinate() - zoomingPosition.getXCoordinate(),
|
||||
moved.getYCoordinate() - zoomingPosition.getYCoordinate()
|
||||
);
|
||||
repaint();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Moving */
|
||||
if (moving) {
|
||||
if(x != mouseDownPixel.x || y != mouseDownPixel.y) {
|
||||
Position newPos = transformPixelToPosition(x, y);
|
||||
|
||||
if (!stop) {
|
||||
canvas.setCursor(moveCursor);
|
||||
movedMote.getInterfaces().getPosition().setCoordinates(
|
||||
newPos.getXCoordinate(),
|
||||
newPos.getYCoordinate(),
|
||||
movedMote.getInterfaces().getPosition().getZCoordinate()
|
||||
);
|
||||
repaint();
|
||||
return;
|
||||
}
|
||||
/* Restore cursor */
|
||||
canvas.setCursor(Cursor.getDefaultCursor());
|
||||
|
||||
|
||||
/* Move mote */
|
||||
if (moveStartTime < 0 || System.currentTimeMillis() - moveStartTime > 300) {
|
||||
if (moveConfirm) {
|
||||
String options[] = {"Yes", "Cancel"};
|
||||
int returnValue = JOptionPane.showOptionDialog(Visualizer.this,
|
||||
"Move mote to" +
|
||||
"\nX=" + newPos.getXCoordinate() +
|
||||
"\nY=" + newPos.getYCoordinate() +
|
||||
"\nZ=" + movedMote.getInterfaces().getPosition().getZCoordinate(),
|
||||
"Move mote?",
|
||||
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,
|
||||
null, options, options[0]);
|
||||
moving = returnValue == JOptionPane.YES_OPTION;
|
||||
}
|
||||
if (moving) {
|
||||
movedMote.getInterfaces().getPosition().setCoordinates(
|
||||
newPos.getXCoordinate(),
|
||||
newPos.getYCoordinate(),
|
||||
movedMote.getInterfaces().getPosition().getZCoordinate()
|
||||
);
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
moving = false;
|
||||
movedMote = null;
|
||||
repaint();
|
||||
}
|
||||
Mote[] motesArr = new Mote[motes.size()];
|
||||
return motes.toArray(motesArr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all motes at given position.
|
||||
*
|
||||
* If multiple motes were found on at a position the motes are returned
|
||||
* in the order they are painted on screen.
|
||||
* First mote in array is the bottom mote, last mote is the top mote.
|
||||
*
|
||||
* @param clickedX
|
||||
* X coordinate
|
||||
* @param clickedY
|
||||
|
@ -1066,7 +1137,7 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
|||
int x = pixelCoord.x;
|
||||
int y = pixelCoord.y;
|
||||
|
||||
if (mote == movedMote) {
|
||||
if (mote == movedMotes) {
|
||||
g.setColor(MOVE_COLOR);
|
||||
g.fillOval(x - MOTE_RADIUS, y - MOTE_RADIUS, 2 * MOTE_RADIUS,
|
||||
2 * MOTE_RADIUS);
|
||||
|
@ -1292,8 +1363,8 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
|||
/**
|
||||
* @return Selected mote
|
||||
*/
|
||||
public Mote getSelectedMote() {
|
||||
return clickedMote;
|
||||
public Set<Mote> getSelectedMotes() {
|
||||
return selectedMotes;
|
||||
}
|
||||
|
||||
public Collection<Element> getConfigXML() {
|
||||
|
@ -1585,4 +1656,44 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
|||
"Multiple views can be active at the same time. " +
|
||||
"Use the View menu to select views. ";
|
||||
};
|
||||
|
||||
private class Selection {
|
||||
|
||||
private int x;
|
||||
private int y;
|
||||
private int width;
|
||||
private int height;
|
||||
private boolean enable;
|
||||
|
||||
public void setSelection(int x, int y, int width, int height) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enable) {
|
||||
this.enable = enable;
|
||||
}
|
||||
|
||||
public void drawSelection(Graphics g) {
|
||||
/* only draw if enabled */
|
||||
if (!enable) {
|
||||
return;
|
||||
}
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
g2d.setColor(new Color(64, 64, 64, 10));
|
||||
g2d.fillRect(x, y, width, height);
|
||||
|
||||
BasicStroke dashed
|
||||
= new BasicStroke(1.0f,
|
||||
BasicStroke.CAP_BUTT,
|
||||
BasicStroke.JOIN_MITER,
|
||||
10.0f, new float[]{5.0f}, 0.0f);
|
||||
g2d.setColor(Color.BLACK);
|
||||
g2d.setStroke(dashed);
|
||||
g2d.drawRect(x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import java.awt.Color;
|
|||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Point;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
@ -74,21 +75,25 @@ public class DGRMVisualizerSkin implements VisualizerSkin {
|
|||
}
|
||||
|
||||
public Color[] getColorOf(Mote mote) {
|
||||
Mote selectedMote = visualizer.getSelectedMote();
|
||||
if (mote == selectedMote) {
|
||||
if (visualizer.getSelectedMotes().contains(mote)) {
|
||||
return new Color[] { Color.CYAN };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void paintBeforeMotes(Graphics g) {
|
||||
Mote selectedMote = visualizer.getSelectedMote();
|
||||
Set<Mote> selectedMotes = visualizer.getSelectedMotes();
|
||||
if (simulation == null
|
||||
|| selectedMote == null
|
||||
|| selectedMote.getInterfaces().getRadio() == null) {
|
||||
|| selectedMotes == null
|
||||
|| selectedMotes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Mote selectedMote = visualizer.getSelectedMotes().iterator().next();
|
||||
if (selectedMote.getInterfaces().getRadio() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Paint transmission and interference range for selected mote */
|
||||
Position motePos = selectedMote.getInterfaces().getPosition();
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ import java.awt.FontMetrics;
|
|||
import java.awt.Graphics;
|
||||
import java.awt.Point;
|
||||
import java.beans.PropertyVetoException;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
|
@ -259,8 +260,7 @@ public class UDGMVisualizerSkin implements VisualizerSkin {
|
|||
|
||||
@Override
|
||||
public Color[] getColorOf(Mote mote) {
|
||||
Mote selectedMote = visualizer.getSelectedMote();
|
||||
if (mote == selectedMote) {
|
||||
if (visualizer.getSelectedMotes().contains(mote)) {
|
||||
return new Color[] { Color.CYAN };
|
||||
}
|
||||
return null;
|
||||
|
@ -268,10 +268,15 @@ public class UDGMVisualizerSkin implements VisualizerSkin {
|
|||
|
||||
@Override
|
||||
public void paintBeforeMotes(Graphics g) {
|
||||
Mote selectedMote = visualizer.getSelectedMote();
|
||||
Set<Mote> selectedMotes = visualizer.getSelectedMotes();
|
||||
if (simulation == null
|
||||
|| selectedMote == null
|
||||
|| selectedMote.getInterfaces().getRadio() == null) {
|
||||
|| selectedMotes == null
|
||||
|| selectedMotes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Mote selectedMote = visualizer.getSelectedMotes().iterator().next();
|
||||
if (selectedMote.getInterfaces().getRadio() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue