Merge pull request #760 from ejoerns/pull-req/cooja-multi-mote-vis
[Cooja] (Multi-)Mote visualization updates
This commit is contained in:
commit
648d3576a0
2 changed files with 115 additions and 18 deletions
|
@ -67,6 +67,7 @@ import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -160,12 +161,16 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
||||||
private static final int MOVE_MASK = Event.SHIFT_MASK;
|
private static final int MOVE_MASK = Event.SHIFT_MASK;
|
||||||
|
|
||||||
enum MotesActionState {
|
enum MotesActionState {
|
||||||
|
NONE,
|
||||||
UNKNWON,
|
// press to select mote
|
||||||
SELECT_PRESS,
|
SELECT_PRESS,
|
||||||
|
// press
|
||||||
DEFAULT_PRESS,
|
DEFAULT_PRESS,
|
||||||
|
// press to start panning
|
||||||
PAN_PRESS,
|
PAN_PRESS,
|
||||||
|
// panning the viewport
|
||||||
PANNING,
|
PANNING,
|
||||||
|
// moving a mote
|
||||||
MOVING,
|
MOVING,
|
||||||
// rectangular select
|
// rectangular select
|
||||||
SELECTING
|
SELECTING
|
||||||
|
@ -176,7 +181,7 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
||||||
/* Mote that was under curser while mouse press */
|
/* Mote that was under curser while mouse press */
|
||||||
Mote cursorMote;
|
Mote cursorMote;
|
||||||
|
|
||||||
MotesActionState mouseActionState = MotesActionState.UNKNWON;
|
MotesActionState mouseActionState = MotesActionState.NONE;
|
||||||
/* Position where mouse button was pressed */
|
/* Position where mouse button was pressed */
|
||||||
Position pressedPos;
|
Position pressedPos;
|
||||||
|
|
||||||
|
@ -427,12 +432,51 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
canvas.getInputMap().put(KeyStroke.getKeyStroke("ESCAPE"), "abort_action");
|
||||||
|
canvas.getInputMap().put(KeyStroke.getKeyStroke("DELETE"), "delete_motes");
|
||||||
|
|
||||||
|
canvas.getActionMap().put("abort_action", new AbstractAction() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (mouseActionState == MotesActionState.MOVING) {
|
||||||
|
/* Reset positions to those of move start */
|
||||||
|
for (Mote m : Visualizer.this.getSelectedMotes()) {
|
||||||
|
double rstPos[] = Visualizer.this.moveStartPositions.get(m);
|
||||||
|
m.getInterfaces().getPosition().setCoordinates(rstPos[0], rstPos[1], rstPos[2]);
|
||||||
|
}
|
||||||
|
mouseActionState = MotesActionState.NONE;
|
||||||
|
}
|
||||||
|
/* Always deselect all */
|
||||||
|
Visualizer.this.getSelectedMotes().clear();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
canvas.getActionMap().put("delete_motes", new AbstractAction() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
Iterator<Mote> iter = Visualizer.this.getSelectedMotes().iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
Mote m = iter.next();
|
||||||
|
m.getSimulation().removeMote(m);
|
||||||
|
iter.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/* Popup menu */
|
/* Popup menu */
|
||||||
canvas.addMouseMotionListener(new MouseMotionAdapter() {
|
canvas.addMouseMotionListener(new MouseMotionAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void mouseDragged(MouseEvent e) {
|
public void mouseDragged(MouseEvent e) {
|
||||||
handleMouseDrag(e, false);
|
handleMouseDrag(e, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseMoved(MouseEvent e) {
|
||||||
|
handleMouseDrag(e, false);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
canvas.addMouseListener(new MouseAdapter() {
|
canvas.addMouseListener(new MouseAdapter() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -477,10 +521,11 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Register mote menu actions */
|
/* Register mote menu actions */
|
||||||
registerMoteMenuAction(MoveMoteMenuAction.class);
|
|
||||||
registerMoteMenuAction(ButtonClickMoteMenuAction.class);
|
registerMoteMenuAction(ButtonClickMoteMenuAction.class);
|
||||||
registerMoteMenuAction(ShowLEDMoteMenuAction.class);
|
registerMoteMenuAction(ShowLEDMoteMenuAction.class);
|
||||||
registerMoteMenuAction(ShowSerialMoteMenuAction.class);
|
registerMoteMenuAction(ShowSerialMoteMenuAction.class);
|
||||||
|
|
||||||
|
registerMoteMenuAction(MoveMoteMenuAction.class);
|
||||||
registerMoteMenuAction(DeleteMoteMenuAction.class);
|
registerMoteMenuAction(DeleteMoteMenuAction.class);
|
||||||
|
|
||||||
/* Register simulation menu actions */
|
/* Register simulation menu actions */
|
||||||
|
@ -889,6 +934,11 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
||||||
|
|
||||||
pressedPos = transformPixelToPosition(mouseEvent.getPoint());
|
pressedPos = transformPixelToPosition(mouseEvent.getPoint());
|
||||||
|
|
||||||
|
// if we are in moving, we ignore the press (rest is handled by release)
|
||||||
|
if (mouseActionState == MotesActionState.MOVING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// this is the state we have from pressing button
|
// this is the state we have from pressing button
|
||||||
final Mote[] foundMotes = findMotesAtPosition(x, y);
|
final Mote[] foundMotes = findMotesAtPosition(x, y);
|
||||||
if (foundMotes == null) {
|
if (foundMotes == null) {
|
||||||
|
@ -937,6 +987,7 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
||||||
mouseActionState = MotesActionState.PANNING;
|
mouseActionState = MotesActionState.PANNING;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
/* If we start moving with on a cursor mote, switch to MOVING */
|
||||||
mouseActionState = MotesActionState.MOVING;
|
mouseActionState = MotesActionState.MOVING;
|
||||||
// save start position
|
// save start position
|
||||||
for (Mote m : selectedMotes) {
|
for (Mote m : selectedMotes) {
|
||||||
|
@ -1037,20 +1088,33 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
||||||
repaint();
|
repaint();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* Release always stops previous actions */
|
||||||
|
mouseActionState = MotesActionState.NONE;
|
||||||
|
canvas.setCursor(Cursor.getDefaultCursor());
|
||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void beginMoveRequest(Mote motesToMove, boolean withTiming, boolean confirm) {
|
private void beginMoveRequest(Mote selectedMote, boolean withTiming, boolean confirm) {
|
||||||
if (withTiming) {
|
if (withTiming) {
|
||||||
moveStartTime = System.currentTimeMillis();
|
moveStartTime = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
moveStartTime = -1;
|
moveStartTime = -1;
|
||||||
}
|
}
|
||||||
mouseActionState = MotesActionState.DEFAULT_PRESS;
|
/* Save start positions and set move-start position to clicked mote */
|
||||||
selectedMotes.clear();
|
for (Mote m : selectedMotes) {
|
||||||
selectedMotes.add(motesToMove);
|
Position pos = m.getInterfaces().getPosition();
|
||||||
repaint();
|
moveStartPositions.put(m, new double[]{
|
||||||
|
pos.getXCoordinate(),
|
||||||
|
pos.getYCoordinate(),
|
||||||
|
pos.getZCoordinate()});
|
||||||
|
}
|
||||||
|
pressedPos.setCoordinates(
|
||||||
|
selectedMote.getInterfaces().getPosition().getXCoordinate(),
|
||||||
|
selectedMote.getInterfaces().getPosition().getYCoordinate(),
|
||||||
|
selectedMote.getInterfaces().getPosition().getZCoordinate());
|
||||||
|
|
||||||
|
mouseActionState = MotesActionState.MOVING;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double zoomFactor() {
|
private double zoomFactor() {
|
||||||
|
@ -1209,11 +1273,24 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
||||||
2 * MOTE_RADIUS);
|
2 * MOTE_RADIUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getSelectedMotes().contains(mote)) {
|
||||||
|
/* If mote is selected, highlight with red circle
|
||||||
|
and semitransparent gray overlay */
|
||||||
|
g.setColor(new Color(51, 102, 255));
|
||||||
|
g.drawOval(x - MOTE_RADIUS, y - MOTE_RADIUS, 2 * MOTE_RADIUS,
|
||||||
|
2 * MOTE_RADIUS);
|
||||||
|
g.drawOval(x - MOTE_RADIUS - 1, y - MOTE_RADIUS - 1, 2 * MOTE_RADIUS + 2,
|
||||||
|
2 * MOTE_RADIUS + 2);
|
||||||
|
g.setColor(new Color(128, 128, 128, 128));
|
||||||
|
g.fillOval(x - MOTE_RADIUS, y - MOTE_RADIUS, 2 * MOTE_RADIUS,
|
||||||
|
2 * MOTE_RADIUS);
|
||||||
|
} else {
|
||||||
g.setColor(Color.BLACK);
|
g.setColor(Color.BLACK);
|
||||||
g.drawOval(x - MOTE_RADIUS, y - MOTE_RADIUS, 2 * MOTE_RADIUS,
|
g.drawOval(x - MOTE_RADIUS, y - MOTE_RADIUS, 2 * MOTE_RADIUS,
|
||||||
2 * MOTE_RADIUS);
|
2 * MOTE_RADIUS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Polygon arrowPoly = new Polygon();
|
private Polygon arrowPoly = new Polygon();
|
||||||
|
|
||||||
|
@ -1571,12 +1648,25 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription(Visualizer visualizer, Mote mote) {
|
public String getDescription(Visualizer visualizer, Mote mote) {
|
||||||
|
if (visualizer.getSelectedMotes().contains(mote) && visualizer.getSelectedMotes().size() > 1) {
|
||||||
|
return "Delete selected Motes";
|
||||||
|
} else {
|
||||||
return "Delete " + mote;
|
return "Delete " + mote;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doAction(Visualizer visualizer, Mote mote) {
|
public void doAction(Visualizer visualizer, Mote mote) {
|
||||||
mote.getSimulation().removeMote(mote);
|
|
||||||
|
/* If the currently clicked mote is not in the current mote selection,
|
||||||
|
* select it exclusively */
|
||||||
|
if (!visualizer.getSelectedMotes().contains(mote)) {
|
||||||
|
visualizer.getSelectedMotes().clear();
|
||||||
|
visualizer.getSelectedMotes().add(mote);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invoke 'delete_motes' action */
|
||||||
|
visualizer.canvas.getActionMap().get("delete_motes").actionPerformed(null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1675,11 +1765,21 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription(Visualizer visualizer, Mote mote) {
|
public String getDescription(Visualizer visualizer, Mote mote) {
|
||||||
|
if (visualizer.getSelectedMotes().contains(mote) && visualizer.getSelectedMotes().size() > 1) {
|
||||||
|
return "Move selected Motes";
|
||||||
|
} else {
|
||||||
return "Move " + mote;
|
return "Move " + mote;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doAction(Visualizer visualizer, Mote mote) {
|
public void doAction(Visualizer visualizer, Mote mote) {
|
||||||
|
/* If the currently clicked mote is note in the current mote selection,
|
||||||
|
* select it exclusively */
|
||||||
|
if (!visualizer.getSelectedMotes().contains(mote)) {
|
||||||
|
visualizer.getSelectedMotes().clear();
|
||||||
|
visualizer.getSelectedMotes().add(mote);
|
||||||
|
}
|
||||||
visualizer.beginMoveRequest(mote, false, false);
|
visualizer.beginMoveRequest(mote, false, false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -263,9 +263,6 @@ public class UDGMVisualizerSkin implements VisualizerSkin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Color[] getColorOf(Mote mote) {
|
public Color[] getColorOf(Mote mote) {
|
||||||
if (visualizer.getSelectedMotes().contains(mote)) {
|
|
||||||
return new Color[]{Color.CYAN};
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue