Merge pull request #760 from ejoerns/pull-req/cooja-multi-mote-vis

[Cooja] (Multi-)Mote visualization updates
This commit is contained in:
Fredrik Österlind 2014-08-01 10:16:27 +02:00
commit 648d3576a0
2 changed files with 115 additions and 18 deletions

View file

@ -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);
} }
}; };

View file

@ -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;
} }