diff --git a/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java b/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java index 4a65f342d..2b2706215 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java +++ b/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java @@ -67,14 +67,18 @@ import java.util.List; import java.util.Observable; import java.util.Observer; +import javax.swing.AbstractAction; +import javax.swing.Action; import javax.swing.JButton; import javax.swing.JCheckBoxMenuItem; import javax.swing.JLabel; +import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JSeparator; +import javax.swing.MenuElement; import javax.swing.SwingUtilities; import javax.swing.Timer; import javax.swing.plaf.basic.BasicInternalFrameUI; @@ -84,13 +88,13 @@ import org.jdom.Element; import se.sics.cooja.ClassDescription; import se.sics.cooja.GUI; +import se.sics.cooja.GUI.MoteRelation; import se.sics.cooja.Mote; import se.sics.cooja.MoteInterface; import se.sics.cooja.PluginType; +import se.sics.cooja.SimEventCentral.MoteCountListener; import se.sics.cooja.Simulation; import se.sics.cooja.VisPlugin; -import se.sics.cooja.GUI.MoteRelation; -import se.sics.cooja.SimEventCentral.MoteCountListener; import se.sics.cooja.interfaces.LED; import se.sics.cooja.interfaces.Position; import se.sics.cooja.interfaces.SerialPort; @@ -131,6 +135,7 @@ public class Visualizer extends VisPlugin { private GUI gui = null; private Simulation simulation = null; private final JPanel canvas; + private boolean loadedConfig = false; /* Viewport */ private AffineTransform viewportTransform; @@ -209,7 +214,7 @@ public class Visualizer extends VisPlugin { } } } - + /* Main canvas */ canvas = new JPanel() { private static final long serialVersionUID = 1L; @@ -238,64 +243,9 @@ public class Visualizer extends VisPlugin { skinButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Point mouse = MouseInfo.getPointerInfo().getLocation(); - JCheckBoxMenuItem item; JPopupMenu skinPopupMenu = new JPopupMenu(); - for (Class skinClass: visualizerSkins) { - String description = GUI.getDescriptionOf(skinClass); - item = new JCheckBoxMenuItem(description, false); - item.putClientProperty("skinclass", skinClass); - - /* Select skin if active */ - for (VisualizerSkin skin: currentSkins) { - if (skin.getClass() == skinClass) { - item.setSelected(true); - break; - } - } - - item.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent e) { - JCheckBoxMenuItem menuItem = ((JCheckBoxMenuItem)e.getItem()); - if (menuItem == null) { - logger.fatal("No menu item"); - return; - } - - Class skinClass = - (Class) menuItem.getClientProperty("skinclass"); - if (skinClass == null) { - logger.fatal("Unknown visualizer skin class: " + skinClass); - return; - } - - if (menuItem.isSelected()) { - /* Create and activate new skin */ - generateAndActivateSkin(skinClass); - } else { - /* Deactivate skin */ - VisualizerSkin skinToDeactivate = null; - for (VisualizerSkin skin: currentSkins) { - if (skin.getClass() == skinClass) { - skinToDeactivate = skin; - break; - } - } - if (skinToDeactivate == null) { - logger.fatal("Unknown visualizer skin to deactivate: " + skinClass); - return; - } - skinToDeactivate.setInactive(); - repaint(); - currentSkins.remove(skinToDeactivate); - skinButton.setText("Select visualizer skins " + - "(" + currentSkins.size() + "/" + visualizerSkins.size() + ")"); - } - } - }); - - skinPopupMenu.add(item); - } + populateSkinMenu(skinPopupMenu); skinPopupMenu.setLocation(mouse); skinPopupMenu.setInvoker(skinButton); @@ -393,7 +343,7 @@ public class Visualizer extends VisPlugin { if (e.isPopupTrigger()) { handlePopupRequest(e.getPoint().x, e.getPoint().y); return; - } + } if (SwingUtilities.isLeftMouseButton(e)){ handleMousePress(e); @@ -558,6 +508,24 @@ public class Visualizer extends VisPlugin { repaint(); } + public void startPlugin() { + super.startPlugin(); + if (loadedConfig) { + return; + } + + /* Activate default skins */ + String[] defaultSkins = GUI.getExternalToolsSetting("VISUALIZER_DEFAULT_SKINS", "").split(";"); + for (String skin: defaultSkins) { + if (skin.isEmpty()) { + continue; + } + Class skinClass = + simulation.getGUI().tryLoadClass(this, VisualizerSkin.class, skin); + generateAndActivateSkin(skinClass); + } + } + public VisualizerSkin[] getCurrentSkins() { VisualizerSkin[] skins = new VisualizerSkin[currentSkins.size()]; return currentSkins.toArray(skins); @@ -665,6 +633,15 @@ public class Visualizer extends VisPlugin { } } + /* Visualizer skin actions */ + menu.add(new JSeparator()); + JMenu skinMenu = new JMenu("Visualizer skins"); + populateSkinMenu(skinMenu); + menu.add(skinMenu); + makeSkinsDefaultAction.putValue(Action.NAME, "Make current skins default"); + JMenuItem skinDefaultItem = new JMenuItem(makeSkinsDefaultAction); + menu.add(skinDefaultItem); + /* Show menu */ menu.setLocation(new Point( canvas.getLocationOnScreen().x + x, @@ -673,6 +650,70 @@ public class Visualizer extends VisPlugin { menu.setVisible(true); } + private void populateSkinMenu(MenuElement skinMenu) { + JCheckBoxMenuItem item; + for (Class skinClass: visualizerSkins) { + String description = GUI.getDescriptionOf(skinClass); + item = new JCheckBoxMenuItem(description, false); + item.putClientProperty("skinclass", skinClass); + + /* Select skin if active */ + for (VisualizerSkin skin: currentSkins) { + if (skin.getClass() == skinClass) { + item.setSelected(true); + break; + } + } + + item.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + JCheckBoxMenuItem menuItem = ((JCheckBoxMenuItem)e.getItem()); + if (menuItem == null) { + logger.fatal("No menu item"); + return; + } + + Class skinClass = + (Class) menuItem.getClientProperty("skinclass"); + if (skinClass == null) { + logger.fatal("Unknown visualizer skin class: " + skinClass); + return; + } + + if (menuItem.isSelected()) { + /* Create and activate new skin */ + generateAndActivateSkin(skinClass); + } else { + /* Deactivate skin */ + VisualizerSkin skinToDeactivate = null; + for (VisualizerSkin skin: currentSkins) { + if (skin.getClass() == skinClass) { + skinToDeactivate = skin; + break; + } + } + if (skinToDeactivate == null) { + logger.fatal("Unknown visualizer skin to deactivate: " + skinClass); + return; + } + skinToDeactivate.setInactive(); + repaint(); + currentSkins.remove(skinToDeactivate); + skinButton.setText("Select visualizer skins " + + "(" + currentSkins.size() + "/" + visualizerSkins.size() + ")"); + } + } + }); + + if (skinMenu instanceof JMenu) { + ((JMenu)skinMenu).add(item); + } + if (skinMenu instanceof JPopupMenu) { + ((JPopupMenu)skinMenu).add(item); + } + } + } + private void handleMousePress(MouseEvent mouseEvent) { int x = mouseEvent.getX(); int y = mouseEvent.getY(); @@ -729,7 +770,7 @@ public class Visualizer extends VisPlugin { /* The current mouse position should correspond to where panning started */ Position moved = transformPixelToPosition(x,y); viewportTransform.translate( - moved.getXCoordinate() - panningPosition.getXCoordinate(), + moved.getXCoordinate() - panningPosition.getXCoordinate(), moved.getYCoordinate() - panningPosition.getYCoordinate() ); repaint(); @@ -745,7 +786,7 @@ public class Visualizer extends VisPlugin { /* 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 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; @@ -756,7 +797,7 @@ public class Visualizer extends VisPlugin { ); Position moved = transformPixelToPosition(zoomingPixel); viewportTransform.translate( - moved.getXCoordinate() - zoomingPosition.getXCoordinate(), + moved.getXCoordinate() - zoomingPosition.getXCoordinate(), moved.getYCoordinate() - zoomingPosition.getYCoordinate() ); repaint(); @@ -780,8 +821,8 @@ public class Visualizer extends VisPlugin { String options[] = {"Yes", "Cancel"}; int returnValue = JOptionPane.showOptionDialog(Visualizer.this, "Move mote to" + - "\nX=" + newPos.getXCoordinate() + - "\nY=" + newPos.getYCoordinate() + + "\nX=" + newPos.getXCoordinate() + + "\nY=" + newPos.getYCoordinate() + "\nZ=" + movedMote.getInterfaces().getPosition().getZCoordinate(), "Move mote?", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, @@ -975,12 +1016,12 @@ public class Visualizer extends VisPlugin { if (smallX == bigX) { scaleX = 1; } else { - scaleX = (bigX - smallX) / (double) (canvas.getWidth()); + scaleX = (bigX - smallX) / (canvas.getWidth()); } if (smallY == bigY) { scaleY = 1; } else { - scaleY = (bigY - smallY) / (double) (canvas.getHeight()); + scaleY = (bigY - smallY) / (canvas.getHeight()); } viewportTransform.setToIdentity(); @@ -1000,7 +1041,7 @@ public class Visualizer extends VisPlugin { double motesMidY = (smallYfinal + bigYfinal) / 2.0; viewportTransform.translate( - viewMid.getXCoordinate() - motesMidX, + viewMid.getXCoordinate() - motesMidX, viewMid.getYCoordinate() - motesMidY); canvas.repaint(); } @@ -1017,8 +1058,8 @@ public class Visualizer extends VisPlugin { */ public Point transformPositionToPixel(Position pos) { return transformPositionToPixel( - pos.getXCoordinate(), - pos.getYCoordinate(), + pos.getXCoordinate(), + pos.getYCoordinate(), pos.getZCoordinate() ); } @@ -1057,7 +1098,7 @@ public class Visualizer extends VisPlugin { Position position = new Position(null); position.setCoordinates( transformToPositionX(x), - transformToPositionY(y), + transformToPositionY(y), 0.0 ); return position; @@ -1111,7 +1152,7 @@ public class Visualizer extends VisPlugin { public Mote getSelectedMote() { return clickedMote; } - + public Collection getConfigXML() { ArrayList config = new ArrayList(); Element element; @@ -1128,11 +1169,11 @@ public class Visualizer extends VisPlugin { double[] matrix = new double[6]; viewportTransform.getMatrix(matrix); element.setText( - matrix[0] + " " + - matrix[1] + " " + - matrix[2] + " " + - matrix[3] + " " + - matrix[4] + " " + + matrix[0] + " " + + matrix[1] + " " + + matrix[2] + " " + + matrix[3] + " " + + matrix[4] + " " + matrix[5] ); config.add(element); @@ -1144,17 +1185,19 @@ public class Visualizer extends VisPlugin { element = new Element("hidden"); config.add(element); } - + return config; } public boolean setConfigXML(Collection configXML, boolean visAvailable) { + loadedConfig = true; + for (Element element : configXML) { if (element.getName().equals("skin")) { String wanted = element.getText(); for (Class skinClass: visualizerSkins) { if (wanted.equals(skinClass.getName()) - /* Backwards compatibility */ + /* Backwards compatibility */ || wanted.equals(GUI.getDescriptionOf(skinClass))) { final Class skin = skinClass; SwingUtilities.invokeLater(new Runnable() { @@ -1194,6 +1237,20 @@ public class Visualizer extends VisPlugin { return true; } + private AbstractAction makeSkinsDefaultAction = new AbstractAction() { + public void actionPerformed(ActionEvent e) { + StringBuilder sb = new StringBuilder(); + for (VisualizerSkin skin: currentSkins) { + if (sb.length() > 0) { + sb.append(';'); + } + sb.append(skin.getClass().getName()); + } + logger.debug("sb.toString() " + sb.toString()); + GUI.setExternalToolsSetting("VISUALIZER_DEFAULT_SKINS", sb.toString()); + } + }; + protected static class ButtonClickMoteMenuAction implements MoteMenuAction { public boolean isEnabled(Visualizer visualizer, Mote mote) { return mote.getInterfaces().getButton() != null @@ -1331,7 +1388,7 @@ public class Visualizer extends VisPlugin { ui.getNorthPane().setPreferredSize(null); visualizer.skinButton.setVisible(true); } else { - /* Hide window decorations */ + /* Hide window decorations */ ui.getNorthPane().setPreferredSize(new Dimension(0,0)); visualizer.skinButton.setVisible(false); }