/*
* File name: JListenFrame.java (package eas.plugins.standard.visualization)
* Author(s): Lukas König
* Java version: 8.0 (at generation time)
* Generation date: 28.05.2014 (09:37:21)
*
* (c) This file and the EAS (Easy Agent Simulation) framework containing it
* is protected by Creative Commons by-nc-sa license. Any altered or
* further developed versions of this file have to meet the agreements
* stated by the license conditions.
*
* In a nutshell
* -------------
* You are free:
* - to Share -- to copy, distribute and transmit the work
* - to Remix -- to adapt the work
*
* Under the following conditions:
* - Attribution -- You must attribute the work in the manner specified by the
* author or licensor (but not in any way that suggests that they endorse
* you or your use of the work).
* - Noncommercial -- You may not use this work for commercial purposes.
* - Share Alike -- If you alter, transform, or build upon this work, you may
* distribute the resulting work only under the same or a similar license to
* this one.
*
* + Detailed license conditions (Germany):
* http://creativecommons.org/licenses/by-nc-sa/3.0/de/
* + Detailed license conditions (unported):
* http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en
*
* This header must be placed in the beginning of any version of this file.
*/
package eas.plugins.standard.visualization;
import java.awt.Cursor;
import java.awt.FileDialog;
import java.awt.HeadlessException;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import com.lowagie.text.pdf.DefaultFontMapper;
import eas.math.geometry.Vector2D;
import eas.miscellaneous.StaticMethods;
import eas.miscellaneous.system.FileNamePostfixFilter;
import eas.miscellaneous.system.windowFrames.GeneralDialog;
import eas.miscellaneous.useful.crawlerUnserializableFields.Crawler;
import eas.plugins.Plugin;
import eas.plugins.PluginFactory;
import eas.plugins.standard.liveInteraction.AllroundPluginManager;
import eas.plugins.standard.visualization.chartPlugin.AllroundChartPlugin;
import eas.simulation.SerializableSimulationState;
import eas.simulation.SimStateUnserializableException;
import eas.simulation.agent.AbstractAgent;
import eas.simulation.spatial.sim2D.standardEnvironments.AbstractEnvironment2D;
import eas.startSetup.GlobalVariables;
class ControlPanel extends JFrame implements ActionListener, ChangeListener,
MouseListener, ComponentListener {
private final LiveWindow liveWindow;
private static final long serialVersionUID = 1L;
public static final String ID = "Control-Window";
private final String saveString = "Save SimState...";
private final String pluginManagerString = "Run plugin manager";
private AllroundVideoPlugin videoPlugin;
public ControlPanel(LiveWindow liveWindow, AllroundVideoPlugin vid, String title)
throws HeadlessException {
super(title);
this.liveWindow = liveWindow;
this.videoPlugin = vid;
}
@Override
public void actionPerformed(ActionEvent arg0) {
if (arg0.getActionCommand().equals("Zoom")) {
this.liveWindow.isHand = false;
liveWindow.setCursor(new Cursor(0));
} else {
liveWindow.setZoom(false);
this.liveWindow.isHand = true;
if (this.liveWindow.isHand) {
liveWindow.setCursor(new Cursor(12));
} else {
liveWindow.setCursor(new Cursor(0));
}
}
if (arg0.getActionCommand().equals("Zoom")) {
liveWindow.setZoom(true);
} else if (arg0.getActionCommand().equals("Deactivate zoom")) {
liveWindow.setZoom(false);
} else if (arg0.getActionCommand().equals("Fit to agents")) {
liveWindow.resetZoom();
liveWindow.vidParent.setFollowAgent(false);
liveWindow.vidParent.setFitPerfectly(false);
} else if (arg0.getActionCommand().equals("Fit tight to agents")) {
liveWindow.resetZoom();
liveWindow.vidParent.setFollowAgent(false);
liveWindow.vidParent.setFitPerfectly(true);
} else if (arg0.getActionCommand().equals("Zoom ( + )")) {
liveWindow.vidParent.setZoom2DPlus();
} else if (arg0.getActionCommand().equals("Zoom ( - )")) {
liveWindow.vidParent.setZoom2DMinus();
} else if (arg0.getActionCommand().equals("Follow marked")) {
liveWindow.vidParent.setFollowAgent(!liveWindow.vidParent
.isFollow());
} else if (arg0.getActionCommand().equals("Toggle pause")) {
if (liveWindow.vidParent.getPause()) {
liveWindow.vidParent.depause();
} else {
liveWindow.vidParent.pause();
}
this.liveWindow.metaInfVis.repaint();
} else if (arg0.getActionCommand().equals("Generate PDF...")) {
boolean pause = liveWindow.vidParent.getPause();
liveWindow.vidParent.pause();
FileDialog dia = new FileDialog(
this,
"Save environment view as pdf (works with AbstractEnvironment2D<?> only)...",
FileDialog.SAVE);
dia.setFilenameFilter(new FileNamePostfixFilter("pdf"));
dia.setVisible(true);
if (dia.getDirectory() != null && dia.getFile() != null) {
StaticMethods.saveEnvironmentViewAsPDF(
new File(dia.getDirectory() + "/" + dia.getFile()),
// dia.getFiles()[0],
(AbstractEnvironment2D<?>) this.liveWindow.vidParent
.getEnvironment(), new DefaultFontMapper());
}
if (!pause) {
liveWindow.vidParent.depause();
}
} else if (arg0.getActionCommand().equals(this.saveString)) {
AllroundVideoPlugin vid = this.videoPlugin;
if (vid != null) {
vid.pause();
// Ask for executable simState.
String butt1 = "SimState only";
String butt2 = "Executable SimState";
String text = "Saving the simState allows to continue the simulation at another time and on another computer.\n"
+ "However, problems may occur if the EAS version to run the simulation on is different from the current.\n \n"
+ "Choose \"" + butt1 + "\" to keep track of the EAS version yourself or \"" + butt2 + "\" to create a package\n"
+ "containing EAS and everything else required to load the simState including an executable batch file\n"
+ "(only available when not already running an exectuable simState).";
String[] buttons = {butt1, GeneralDialog.CANCEL};
File testFile = new File("./" + GlobalVariables.ROOT_PACKAGE_NAME);
if (testFile.exists() && testFile.isDirectory()) {
buttons = new String[] {butt1, butt2, GeneralDialog.CANCEL};
}
GeneralDialog dia2 = new GeneralDialog(
null,
text,
"Save simState on its own or create executable simState (may take a bit)?",
buttons,
null);
dia2.setVisible(true);
if (dia2.getResult().equals(GeneralDialog.CANCEL)) {
return;
}
// Ask for location.
FileDialog dia = new FileDialog(this, "Select a place to store simulation state", FileDialog.SAVE);
dia.setFilenameFilter(new FileNamePostfixFilter(".eas"));
dia.setVisible(true);
if (dia.getDirectory() != null && dia.getFile() != null) {
File easFile;
if (dia.getFile().endsWith(".eas")) {
easFile = new File(dia.getDirectory() + File.separator + dia.getFile());
} else {
easFile = new File(dia.getDirectory() + File.separator + dia.getFile() + ".eas");
}
SerializableSimulationState simState = new SerializableSimulationState(
this.liveWindow.environment.getSimTime(), easFile);
try {
if (dia2.getResult().equals(butt1)) {
simState.save();
} else if (dia2.getResult().equals(butt2)) {
GlobalVariables.getPrematureParameters().logInfo("Creating executable simState (this may take a while).");
simState.createExecutableSimState();
}
} catch (SimStateUnserializableException e) {
String info =
"The simulation state could not be saved. This probably means that one or more objects\n"
+ "stored as field variables are not implementing the Serializable interface.\n"
+ "Most EAS classes are serializable, so you should check field types from the\n"
+ "Java internal or possibly external libraries. A good starting point often appears\n"
+ "to be objects of type BufferedImage (or Graphics, Graphics2D etc). Another known problem\n"
+ "is given by the unseriablizable Stroke classes - when using " + new AllroundChartPlugin().id() + ",\n"
+ "try avoiding to specifically set the Stroke. Note that all 3D simulation currently cannot\n"
+ "be serialized. Concerning AVI and GIF recording, both should be turned off for now\n"
+ "as errors will occur on reloading the simState (this is work in progress).\n\n"
+ "A list of unserializable fields in the currently used plugins and environments follows.\n"
+ "You should first look into them as the trouble-causing field(s) is/are probably among them:\n\n";
LinkedList<Class<?>> classes = new LinkedList<>();
for (Plugin<?> p : this.videoPlugin.getCurrentEnv().getSimTime().getPlugins()) {
classes.add(p.getClass());
}
classes.add(this.videoPlugin.getCurrentEnv().getClass());
for (AbstractAgent<?> a : this.videoPlugin.getCurrentEnv().getAgents()) {
classes.add(a.getClass());
}
HashMap<Field, HashSet<String>> result = Crawler.initiateCrawling(classes);
String resString = "";
for (Field field : result.keySet()) {
resString += "<UnSer> "
+ field.getType().getSimpleName() + " "
+ field.getName() + " ("
+ field.getDeclaringClass().getName() + ") => " + result.get(field) + "\n";
}
info += resString + "\n\n";
GeneralDialog dia3 = new GeneralDialog(
null,
null,
"Simulation state not serialized",
new String[] {GeneralDialog.OK, "Throw exception"},
info
+ "Exception caught: " + e.toString() + "\n" + Arrays.toString(e.getStackTrace()).replace(", ", "\n"));
dia3.setVisible(true);
if (dia3.getResult().equals("Throw exception")) {
GlobalVariables.getPrematureParameters().logDebug("Full stack trace of exception: ");
e.printStackTrace();
GlobalVariables.getPrematureParameters().logError("Throwing exception: ");
throw new RuntimeException(e);
}
}
}
vid.depause();
}
} else if (arg0.getActionCommand().equals(this.pluginManagerString)) {
liveWindow.vidParent
.getEnvironment()
.getSimTime()
.registerPlugin(PluginFactory.getKonstPlug(
new AllroundPluginManager().id(),
GlobalVariables.getPrematureParameters()));
} else if (arg0.getActionCommand().equals("Exit!")) {
liveWindow.vidParent.pause();
GeneralDialog dia = new GeneralDialog(
null,
"Do you really want to exit?\n\nUnsaved changes will be lost!",
"Exit request", GeneralDialog.YES_NO, null);
dia.setLocationRelativeTo(null);
dia.setVisible(true);
if (dia.getResult().equals(GeneralDialog.YES)) {
System.exit(0);
}
liveWindow.vidParent.depause();
}
}
@Override
public void stateChanged(ChangeEvent e) {
if (e.getSource().equals(this.speedSlider)) {
this.liveWindow.pauseInterval = -this.speedSlider
.getValue();
}
if (e.getSource().equals(this.turnSlider)) {
Vector2D center = null;
if (this.turnSlider.getValue() != 0) {
center = this.liveWindow.centerChosenByClick;
}
this.liveWindow.vidParent.setVisualizationAngle(center,
this.turnSlider.getValue() / 180.0 * Math.PI);
}
}
JSlider turnSlider = new JSlider(-180, 180);
JSlider speedSlider = new JSlider(-1000, 0);
void addComponents() {
JButton zoom = new JButton("Zoom");
JButton positiveZoom = new JButton("Zoom ( + )");
JButton negativeZoom = new JButton("Zoom ( - )");
// Button hand = new Button("Toggle hand tool");
JButton noZoom = new JButton("Deactivate zoom");
JButton zoomOut = new JButton("Fit to agents");
JButton zoomOutPerfectly = new JButton("Fit tight to agents");
JButton follow = new JButton("Follow marked");
JButton pauseButton = new JButton("Toggle pause");
JButton pdfButton = new JButton("Generate PDF...");
JButton harshExit = new JButton("Exit!");
JButton storeSim = new JButton(saveString);
JButton plugManager = new JButton(pluginManagerString);
turnSlider.addChangeListener(this);
turnSlider.addMouseListener(this);
speedSlider.addChangeListener(this);
speedSlider.addMouseListener(this);
zoom.addActionListener(this);
noZoom.addActionListener(this);
zoomOut.addActionListener(this);
zoomOutPerfectly.addActionListener(this);
positiveZoom.addActionListener(this);
negativeZoom.addActionListener(this);
pdfButton.addActionListener(this);
harshExit.addActionListener(this);
storeSim.addActionListener(this);
plugManager.addActionListener(this);
// hand.addActionListener(frame);
follow.addActionListener(this);
pauseButton.addActionListener(this);
this.setSize(210, 370);
this.setLocation(this.getWidth(), 100);
this.setVisible(true);
Panel p = new Panel();
this.add(p);
this.addComponentListener(this);
p.add(zoom);
p.add(noZoom);
p.add(zoomOut);
p.add(zoomOutPerfectly);
p.add(positiveZoom);
p.add(negativeZoom);
// p.add(hand);
p.add(follow);
p.add(pauseButton);
p.add(pdfButton);
p.add(turnSlider);
p.add(speedSlider);
speedSlider.setValue(speedSlider.getMaximum());
p.add(plugManager);
p.add(storeSim);
p.add(harshExit);
}
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == 3) {
this.turnSlider.setValue(0);
}
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void componentResized(ComponentEvent e) {
StaticMethods.storeWindowFramePosition(this, ID);
}
@Override public void componentMoved(ComponentEvent e) {
StaticMethods.storeWindowFramePosition(this, ID);
}
@Override public void componentShown(ComponentEvent e) {}
@Override public void componentHidden(ComponentEvent e) {}
}