/*
* File name: OCWindow.java (package eas.plugins.standard)
* Author(s): Lukas König
* Java version: 8.0 (at generation time)
* Generation date: 21.05.2014 (13:10:53)
*
* (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.liveInteraction;
import java.awt.GridLayout;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import eas.miscellaneous.StaticMethods;
import eas.miscellaneous.system.windowFrames.GeneralDialog;
import eas.plugins.standard.visualization.chartPlugin.ChartEvent;
import eas.simulation.agent.AbstractAgent;
import eas.startSetup.GlobalVariables;
/**
* @author Lukas König
*/
public class OCWindow extends JFrame implements MouseListener, ComponentListener {
private static final long serialVersionUID = 4864558852690041239L;
private transient HashMap<JComponent, Method> allMethods;
private transient HashMap<JButton, Method> allButtonsInvoke;
private transient HashMap<JButton, Method> allButtonsChart;
private AbstractAgent<?> invokerAgent;
private Class<?> invokerClass;
private JButton moveClassUp = new JButton("Go up to superclass");
private JButton moveClassBottom = new JButton("Go down to most specific agent class");
protected transient Method invokeNext;
protected AbstractAgent<?> invokeOnNext;
protected Object[] invokeWithNext;
private transient HashMap<ChartEvent, Object[]> events = new HashMap<>();
private transient HashMap<ChartEvent, Method> chartMethods = new HashMap<>();
private HashMap<ChartEvent, AbstractAgent<?>> chartAgents = new HashMap<>();
public static final String ID = "OC-Window-Central-Frame";
public OCWindow(String string) {
super(string);
this.setSize(900, 300);
moveClassBottom.addMouseListener(this);
moveClassUp.addMouseListener(this);
this.addComponentListener(this);
StaticMethods.loadWindowFramePosition(this, ID);
}
private String invokeText = "Invoke method";
private String chartText = "Plot return value";
private JComponent getMethodGUI(Method m) {
String methodText = m.getReturnType().getSimpleName() + " " + m.getName() + "(";
int i = 0;
for (Parameter p : m.getParameters()) {
methodText += p;
if (i < m.getParameterCount() - 1) {
methodText += ", ";
}
i++;
}
methodText += ")";
JPanel component = new JPanel();
JPanel subPanel = new JPanel();
component.setLayout(new GridLayout(1, 2));
subPanel.setLayout(new GridLayout(1, 2));
JButton butt1 = new JButton(invokeText);
JButton butt2 = new JButton(chartText);
component.add(new JLabel(methodText));
subPanel.add(butt1);
subPanel.add(butt2);
component.add(subPanel);
allButtonsInvoke.put(butt1, m);
allButtonsChart.put(butt2, m);
if (!ConstructorFactory.isTypeAcceptable(m.getReturnType())) {
butt2.setEnabled(false);
}
if (this.invokerClass.equals(this.invokerAgent.getClass())) {
this.moveClassBottom.setEnabled(false);
} else {
this.moveClassBottom.setEnabled(true);
}
if (this.invokerClass.getSuperclass() == null) {
this.moveClassUp.setEnabled(false);
} else {
this.moveClassUp.setEnabled(true);
}
component.setSize(500, 40);
butt1.addMouseListener(this);
butt2.addMouseListener(this);
return component;
}
public void setMethods(AbstractAgent<?> agent) {
this.setMethods(agent, agent.getClass());
}
private void setMethods(AbstractAgent<?> agent, Class<?> classToDisplay) {
allMethods = new HashMap<>();
allButtonsInvoke = new HashMap<>();
allButtonsChart = new HashMap<>();
invokerAgent = agent;
invokerClass = classToDisplay;
Method[] methods = classToDisplay.getDeclaredMethods();
this.setTitle("Observe and control agent " + agent.id() + " ("
+ agent.getClass().getSimpleName() + " -> methods of "
+ classToDisplay.getSimpleName() + ")");
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
boolean allParsAcceptable = true;
for (Parameter parameter : m.getParameters()) {
if (ConstructorFactory.isTypeAcceptable(parameter.getType())) {
allParsAcceptable = true;
} else {
allParsAcceptable = false;
break;
}
}
if (allParsAcceptable) {
this.allMethods.put(this.getMethodGUI(m), m);
}
}
this.resetGUI();
}
private void resetGUI() {
this.getContentPane().removeAll();
LinkedList<JComponent> liste = new LinkedList<JComponent>();
for (JComponent c : this.allMethods.keySet()) {
MethodRunnableProperties prop = this.allMethods.get(c).getAnnotation(MethodRunnableProperties.class);
if (prop == null || !prop.ignoreMethod()) {
liste.add(c);
}
}
Collections.sort(liste, (c1, c2) -> {
Method m1 = this.allMethods.get(c1);
Method m2 = this.allMethods.get(c2);
int c = new Integer(m1.getParameterCount()).compareTo(
new Integer(m2.getParameterCount()));
if (c == 0) {
Integer i1 = 0;
Integer i2 = 0;
if (ConstructorFactory.isTypeAcceptable(m1.getReturnType())) {
i1 = 1;
}
if (ConstructorFactory.isTypeAcceptable(m2.getReturnType())) {
i2 = 1;
}
c = i1.compareTo(i2);
}
if (c == 0) {
c = m1.getName().compareTo(m2.getName());
}
return c;
});
// this.getContentPane().setLayout(new GridLayout(liste.size() + 1, 1));
// Classes up or down.
JPanel panel = new JPanel();
panel.add(moveClassUp);
panel.add(moveClassBottom);
// this.getContentPane().add(panel);
JPanel greatPanel = new JPanel();
greatPanel.setLayout(new GridLayout(liste.size() + 1, 1));
greatPanel.add(panel);
for (JComponent j : liste) {
greatPanel.add(j);
}
JScrollPane scrollBar = new JScrollPane(
greatPanel,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
this.getContentPane().add(scrollBar);
}
private Object[] getParametersFor(Method m) {
Object[] list = new Object[m.getParameterCount()];
int i = 0;
for (Parameter par : m.getParameters()) {
GeneralDialog dia = new GeneralDialog(
this,
null,
"Value for parameter '" + par + "' (method " + m.getName() + ")",
GeneralDialog.OK_BUTT,
"" + par.getType(),
1,
10,
true);
dia.setVisible(true);
String t = dia.getText();
if (par.getType().equals(Boolean.class) || par.getType().equals(Boolean.TYPE)) {
list[i] = Boolean.parseBoolean(t);
} else
if (par.getType().equals(Double.class) || par.getType().equals(Double.TYPE)) {
list[i] = Double.parseDouble(t);
} else
if (par.getType().equals(Float.class) || par.getType().equals(Float.TYPE)) {
list[i] = Float.parseFloat(t);
} else
if (par.getType().equals(Integer.class) || par.getType().equals(Integer.TYPE)) {
list[i] = Integer.parseInt(t);
} else
if (par.getType().equals(Long.class) || par.getType().equals(Long.TYPE)) {
list[i] = Long.parseLong(t);
} else
if (par.getType().equals(String.class)) {
list[i] = t;
}
i++;
}
return list;
}
@Override
public void mouseClicked(MouseEvent e) {
JButton butt = (JButton) e.getSource();
if (!butt.isEnabled()) {
return;
}
if (butt.equals(moveClassUp)) {
this.setMethods(this.invokerAgent, this.invokerClass.getSuperclass());
this.setVisible(true);
}
if (butt.equals(moveClassBottom)) {
this.setMethods(this.invokerAgent, this.invokerAgent.getClass());
this.setVisible(true);
}
if (butt.getText().equals(invokeText)) {
Method m = this.allButtonsInvoke.get(butt);
m.setAccessible(true);
Object[] pars = this.getParametersFor(m);
try { // Try to invoke concurrently.
m.invoke(this.invokerAgent, pars);
} catch (Exception event) {
GlobalVariables.getPrematureParameters().logWarning(
"Concurrent invokation failed: " + event.toString() + " - " + m.getName());
GlobalVariables.getPrematureParameters().logInfo("I will try to invoke at the next regular time instant.");
this.invokeNext = m;
this.invokeOnNext = this.invokerAgent;
this.invokeWithNext = pars;
}
} else if (butt.getText().equals(chartText)) {
Method m = this.allButtonsChart.get(butt);
m.setAccessible(true);
Object[] pars = this.getParametersFor(m);
GeneralDialog dia1 = new GeneralDialog(
this,
null,
"The name of the chart to add the series",
GeneralDialog.OK_BUTT,
"Chart name",
1,
20,
true);
dia1.setVisible(true);
String chartName = dia1.getText();
GeneralDialog dia2 = new GeneralDialog(
this,
null,
"The name of the series",
GeneralDialog.OK_BUTT,
m.getName() + "-agent-" + invokerAgent.id(),
1,
20,
true);
dia2.setVisible(true);
String seriesName = dia2.getText();
ChartEvent event = new ChartEvent(chartName, seriesName, 0);
events.put(event, pars);
chartMethods.put(event, m);
chartAgents.put(event, invokerAgent);
}
}
public HashMap<ChartEvent, AbstractAgent<?>> getChartAgents() {
return this.chartAgents;
}
public HashMap<ChartEvent, Method> getChartMethods() {
return this.chartMethods;
}
public HashMap<ChartEvent, Object[]> getEvents() {
if (this.events == null) {
this.events = new HashMap<ChartEvent, Object[]>();
}
return this.events;
}
@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) {}
}