added possibility to save default visualizer skins

This commit is contained in:
Fredrik Osterlind 2012-04-24 11:19:54 +02:00
parent b85bc3379c
commit baa5e67ef1
1 changed files with 137 additions and 80 deletions

View File

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