package org.lucci.madhoc.simulation.monitor;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.lucci.madhoc.gui.MonitorView;
import org.lucci.madhoc.simulation.Monitor;
import org.lucci.madhoc.simulation.measure.MeasureHistory;
import org.lucci.madhoc.simulation.measure.NumericalSensor;
import org.lucci.math.Utilities;
import org.lucci.up.GNUPlotFilePlotter;
import org.lucci.up.InteractiveSwingPlotter;
import org.lucci.up.SwingPlotter;
import org.lucci.up.data.Figure;
import org.lucci.up.data.FigureFactory;
import org.lucci.up.data.rendering.DataElementRenderer;
import org.lucci.up.data.rendering.figure.BSplineFigureRenderer;
import org.lucci.up.data.rendering.figure.BezierCurveFigureRenderer;
import org.lucci.up.data.rendering.figure.ConnectedLineFigureRenderer;
import org.lucci.up.data.rendering.point.CirclePointRenderer;
import org.lucci.up.data.rendering.point.HistogramPointRenderer;
import org.lucci.up.system.Space;
public class NumericalMeasures2DGraphicalView extends MonitorView
{
private NumericalSensor xSensor, ySensor;
private SwingPlotter plotter = new InteractiveSwingPlotter();
private JCheckBox sortXCheckBox = new JCheckBox("Sort on X values", true);
private JList rendererList = new JList();
private ChangeListener changeListener = new ChangeHandler();
private JCheckBox selectXCheckbox;
private JCheckBox selectYCheckbox;
private JButton invertXY;
private JComboBox whatToShowComboBox;
private JTextField intervalSizeTextField;
public void setMonitor(Monitor application)
{
super.setMonitor(application);
Space space = plotter.getGraphics2DPlotter().getSpace();
space.setColor(Color.black);
space.setBackgroundColor(Color.white);
space.setArrowsVisible(false);
space.getLegend().setVisible(false);
space.getXDimension().getOriginAxis().getGraduation().setVisible(false);
space.getYDimension().getOriginAxis().getGraduation().setVisible(false);
space.getXDimension().getOriginAxis().setColor(Color.gray);
space.getYDimension().getOriginAxis().setColor(Color.gray);
plotter.setImageBufferedUsed(false);
plotter.getGraphics2DPlotter().setFigure(new Figure());
setLayout(new BorderLayout());
add(BorderLayout.CENTER, plotter);
add(BorderLayout.EAST, new JScrollPane(createConfPanel()));
}
private JPanel createConfPanel()
{
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(new TitledBorder("Parameters"));
{
JPanel xyPanel = new JPanel(new GridLayout(1, 2));
selectXCheckbox = new JCheckBox("X", true);
selectXCheckbox.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
selectYCheckbox.setSelected(!selectYCheckbox.isSelected());
}
});
selectYCheckbox = new JCheckBox("Y", false);
selectYCheckbox.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
selectXCheckbox.setSelected(!selectXCheckbox.isSelected());
}
});
xyPanel.add(selectXCheckbox);
xyPanel.add(selectYCheckbox);
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.CENTER;
c.gridy = 0;
panel.add(xyPanel, c);
}
{
invertXY = new JButton("Swap X/Y");
invertXY.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
NumericalSensor tmp = xSensor;
xSensor = ySensor;
ySensor = tmp;
updateViewContent();
}
});
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.CENTER;
c.gridy = 1;
panel.add(invertXY, c);
}
{
GridBagConstraints c = new GridBagConstraints();
c.gridy = 2;
c.insets = new Insets(10, 10, 10, 10);
panel.add(sortXCheckBox, c);
sortXCheckBox.addChangeListener(changeListener);
}
{
CirclePointRenderer cp = new CirclePointRenderer();
cp.setFillColor(null);
rendererList.setListData(new Object[] {
new ConnectedLineFigureRenderer(),
new HistogramPointRenderer(),
new BezierCurveFigureRenderer(),
new BSplineFigureRenderer(),
cp,
});
rendererList.setSelectedIndices(new int[] {0});
rendererList.setCellRenderer(new ListRenderer());
rendererList.setBorder(new TitledBorder("Renderers"));
rendererList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
GridBagConstraints c = new GridBagConstraints();
c.gridy = 3;
c.insets = new Insets(10, 10, 10, 10);
panel.add(rendererList, c);
rendererList.addListSelectionListener(new ListSelectionListener()
{
public void valueChanged(ListSelectionEvent arg0)
{
updateViewContent();
}
});
}
{
whatToShowComboBox = new JComboBox();
whatToShowComboBox.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
updateViewContent();
}
});
whatToShowComboBox.addItem("All");
whatToShowComboBox.addItem("Average");
whatToShowComboBox.addItem("Standard deviation");
whatToShowComboBox.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
intervalSizeTextField.setEnabled(!whatToShowComboBox.getSelectedItem().equals("All"));
}
});
GridBagConstraints c = new GridBagConstraints();
c.gridy = 4;
c.insets = new Insets(10, 10, 0, 10);
panel.add(whatToShowComboBox, c);
}
{
intervalSizeTextField = new JTextField("10");
intervalSizeTextField.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
updateViewContent();
}
});
intervalSizeTextField.setEnabled(false);
JPanel p = new JPanel(new GridLayout(1,2));
p.add(new JLabel("Show last: "));
p.add(intervalSizeTextField);
GridBagConstraints c = new GridBagConstraints();
c.gridy = 5;
c.insets = new Insets(0, 10, 10, 10);
panel.add(p, c);
}
return panel;
}
public void saveState(File directory)
{
File file = new File(directory.getAbsolutePath() + "/" + getName() + ".dat");
GNUPlotFilePlotter gnuPlotter = new GNUPlotFilePlotter();
gnuPlotter.setGraphics2DPlotter(plotter.getGraphics2DPlotter());
String text = gnuPlotter.getGNUplotData();
try
{
FileOutputStream fos = new FileOutputStream(file);
fos.write(text.getBytes());
fos.close();
}
catch (IOException ex)
{
System.err.println("Error while writing " + file.getAbsolutePath());
}
}
public String getName()
{
return "2D plotter";
}
public void updateViewContent()
{
if (xSensor != null)
{
String legend = org.lucci.madhoc.util.Utilities.getLegend(xSensor);
if (legend != null)
{
plotter.getGraphics2DPlotter().getSpace().getXDimension().getLegend().setText(legend);
plotter.getGraphics2DPlotter().getSpace().getXDimension().getLegend().setColor(xSensor.getMonitor().getColor());
}
}
if (ySensor != null)
{
String legend = org.lucci.madhoc.util.Utilities.getLegend(ySensor);
if (legend != null)
{
plotter.getGraphics2DPlotter().getSpace().getYDimension().getLegend().setText(legend);
plotter.getGraphics2DPlotter().getSpace().getYDimension().getLegend().setColor(ySensor.getMonitor().getColor());
}
}
if (xSensor != null && ySensor != null)
{
Figure fig = createFigure();
Iterator rendererIterator = Arrays.asList(rendererList.getSelectedValues()).iterator();
while (rendererIterator.hasNext())
{
DataElementRenderer renderer = (DataElementRenderer) rendererIterator.next();
if (renderer instanceof CirclePointRenderer)
{
CirclePointRenderer r = (CirclePointRenderer) renderer;
if (fig.getPointCount() < 50)
{
r.setRadius(5);
}
else if (fig.getPointCount() < 100)
{
r.setRadius(4);
}
else if (fig.getPointCount() < 150)
{
r.setRadius(3);
}
else
{
r.setRadius(2);
}
}
renderer.setColor(ySensor.getMonitor().getColor());
fig.addRenderer(renderer);
}
plotter.getGraphics2DPlotter().setFigure(fig);
}
else
{
plotter.getGraphics2DPlotter().setFigure(new Figure());
}
plotter.repaint(0);
}
private Figure createFigure()
{
MeasureHistory x = (MeasureHistory) getProjectionComponent().getProjection().getMeasureHistoryMap().get(xSensor);
MeasureHistory y = (MeasureHistory) getProjectionComponent().getProjection().getMeasureHistoryMap().get(ySensor);
List yValues = getYValues(y);
List xValues = new Vector(x.getValues());
if (xValues.size() != yValues.size())
{
xValues = xValues.subList(xValues.size() - yValues.size(), xValues.size());
}
Figure fig = FigureFactory.createFigure(xValues, yValues);
if (sortXCheckBox.isSelected())
{
fig.sortX();
}
return fig;
}
private List getYValues(MeasureHistory yr)
{
String whatToShow = (String) whatToShowComboBox.getSelectedItem();
if (whatToShow.equalsIgnoreCase("all"))
{
return yr.getValues();
}
else
{
List values = new Vector();
try
{
Integer.valueOf(intervalSizeTextField.getText()).intValue();
}
catch (NumberFormatException ex)
{
intervalSizeTextField.setText("20");
}
int interval = Integer.valueOf(intervalSizeTextField.getText()).intValue();
int iteration = getMonitor().getNetwork().getSimulation().getIteration();
for (int i = 0; i < iteration; ++i)
{
if (i - interval >= 0)
{
List subList = yr.getValues().subList(i - interval, i);
if (whatToShow.equalsIgnoreCase("average"))
{
values.add(new Double(Utilities.getAverage(subList)));
}
else if (whatToShow.equalsIgnoreCase("standard deviation"))
{
values.add(new Double(Utilities.getStandardDeviation(subList)));
}
else
{
throw new IllegalStateException();
}
}
}
return values;
}
}
public class ChangeHandler implements ChangeListener
{
public void stateChanged(ChangeEvent arg0)
{
updateViewContent();
}
}
public class ListRenderer extends DefaultListCellRenderer
{
public Component getListCellRendererComponent(JList arg0, Object arg1, int arg2, boolean arg3, boolean arg4)
{
super.getListCellRendererComponent(arg0, arg1, arg2, arg3, arg4);
setText(cleanRendererName(arg1.getClass().getName()));
return this;
}
private String cleanRendererName(String name)
{
name = name.substring(name.lastIndexOf(".") + 1);
if (name.endsWith("Renderer"))
{
name = name.substring(0, name.length() - "Renderer".length());
}
if (name.endsWith("Figure"))
{
name = name.substring(0, name.length() - "Figure".length());
}
if (name.endsWith("Point"))
{
name = name.substring(0, name.length() - "Point".length());
}
return name;
}
}
public NumericalSensor getXMeasure()
{
return xSensor;
}
public void setXMeasure(NumericalSensor measure)
{
xSensor = measure;
}
public NumericalSensor getYMeasure()
{
return ySensor;
}
public void setYMeasure(NumericalSensor measure)
{
ySensor = measure;
}
public JCheckBox getSelectXCheckbox()
{
return selectXCheckbox;
}
public JCheckBox getSelectYCheckbox()
{
return selectYCheckbox;
}
public void configure() throws Throwable
{
}
}