package com.plectix.simulator.gui.panel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.KeyEvent;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.util.Collection;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.text.PlainDocument;
import org.apache.log4j.Logger;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CombinedDomainXYPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.FixedMillisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import com.plectix.simulator.gui.lib.ColorMap;
import com.plectix.simulator.gui.lib.GridBagPanel;
import com.plectix.simulator.streaming.LiveData;
import com.plectix.simulator.streaming.LiveDataPoint;
/**
* <p>TODO document GraphPanel
* </p>
* @version $Id$
* @author ecemis
*/
public class GraphPanel extends GridBagPanel implements ControlPanelListener {
private static final long serialVersionUID = 1L;
private static final double MEGA = 1024.0 * 1024.0;
private static final Logger LOGGER = Logger.getLogger(GraphPanel.class);
private static final boolean SHOW_LEGEND = true;
private static final Shape SMALL_RECTANGLE = new Rectangle(-1, -1, 2, 2);
@SuppressWarnings("unused")
private static final Shape RECTANGLE = new Rectangle(-3, -3, 6, 6);
@SuppressWarnings("unused")
private static final Shape UP_TRIANGLE = new Polygon(new int[]{-5, 0, 5}, new int[]{12, 0, 12}, 3);
@SuppressWarnings("unused")
private static final Shape DOWN_TRIANGLE = new Polygon(new int[]{-5, 0, 5}, new int[]{-12, 0, -12}, 3);
private org.jfree.chart.ChartPanel observablesChartPanel = null;
private org.jfree.chart.ChartPanel rulesChartPanel = null;
private org.jfree.chart.ChartPanel memoryChartPanel = null;
private JTextArea textArea= new JTextArea();
private ChartZoomInfo chartZoomInfo = new ChartZoomInfo();
private TimeSeries memoryUsageTimeSeriesHeap = null;
private TimeSeries memoryUsageTimeSeriesNonHeap = null;
private TimeSeries memoryUsageTimeSeriesTotal = null;
private XYSeriesCollection seriesCollectionObservables = null;
private XYSeriesCollection seriesCollectionRules = null;
private GraphPanel() {
super();
}
public void initialize() {
GridBagConstraintsEx gc = createNewConstraints().insets(5, 5, 5, 5);
// Chart Panels
observablesChartPanel = createNewChartPanel();
rulesChartPanel = createNewChartPanel();
memoryChartPanel = createNewChartPanel();
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addTab("Observables", observablesChartPanel);
tabbedPane.setMnemonicAt(0, KeyEvent.VK_1);
tabbedPane.addTab("Rules", rulesChartPanel);
tabbedPane.setMnemonicAt(0, KeyEvent.VK_2);
tabbedPane.addTab("Memory", memoryChartPanel);
tabbedPane.setMnemonicAt(1, KeyEvent.VK_3);
textArea.setLineWrap(false);
textArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
tabbedPane.addTab("Console", scrollPane);
tabbedPane.setMnemonicAt(2, KeyEvent.VK_4);
tabbedPane.setSelectedIndex(0);
add(tabbedPane, gc.fillBoth());
}
private final org.jfree.chart.ChartPanel createNewChartPanel() {
org.jfree.chart.ChartPanel chartPanel = new org.jfree.chart.ChartPanel(null, false);
chartPanel.setMinimumSize(new Dimension(800, 600));
chartPanel.setPreferredSize(new Dimension(800, 600));
chartPanel.setMaximumDrawWidth(2000);
chartPanel.setMaximumDrawHeight(1500);
chartPanel.setMinimumDrawWidth(400);
chartPanel.setMinimumDrawHeight(300);
return chartPanel;
}
public void updateLiveDataChart(LiveData liveData) {
// LOGGER.info("Entered updateLiveDataChart with liveData having " + liveData.getNumberOfPlots() + " plots.");
seriesCollectionObservables = new XYSeriesCollection();
seriesCollectionRules = new XYSeriesCollection();
int numberOfPlots = liveData.getNumberOfPlots();
for (int i= 0; i< numberOfPlots; i++) {
if (liveData.getPlotTypes()[i].getName().equalsIgnoreCase("OBSERVABLE")){
seriesCollectionObservables.addSeries(new XYSeries(liveData.getPlotNames()[i]));
} else if (liveData.getPlotTypes()[i].getName().equalsIgnoreCase("RULE")){
seriesCollectionRules.addSeries(new XYSeries(liveData.getPlotNames()[i]));
} else {
throw new RuntimeException("Unknown plot type: " + liveData.getPlotTypes()[i].getName());
}
}
Collection<LiveDataPoint> liveDataPoints = liveData.getData();
if (liveDataPoints == null) {
return;
}
// LOGGER.info("Each curve has " + liveData.getData().size() + " points.");
for (LiveDataPoint liveDataPoint : liveDataPoints) {
double time = liveDataPoint.getEventTime();
double[] values = liveDataPoint.getPlotValues();
int observablePlotCount = 0;
int rulePlotCount = 0;
for (int i= 0; i< numberOfPlots; i++) {
if (liveData.getPlotTypes()[i].getName().equalsIgnoreCase("OBSERVABLE")){
seriesCollectionObservables.getSeries(observablePlotCount++).add(time, values[i]);
} else if (liveData.getPlotTypes()[i].getName().equalsIgnoreCase("RULE")){
seriesCollectionRules.getSeries(rulePlotCount++).add(time, values[i]);
} else {
throw new RuntimeException("Unknown plot type: " + liveData.getPlotTypes()[i].getName());
}
}
}
// LOGGER.info("Drawing " + liveDataPoints.size() + " points for " + seriesCollection.getSeriesCount() + " series!");
updateLiveDataChartPanel(observablesChartPanel, seriesCollectionObservables);
updateLiveDataChartPanel(rulesChartPanel, seriesCollectionRules);
}
public final void updateMemoryUsageChart() {
final MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();
final long currentHeap = mbean.getHeapMemoryUsage().getUsed();
final long currentNonHeap = mbean.getNonHeapMemoryUsage().getUsed();
final long currentTimeMillis = System.currentTimeMillis();
// LOGGER.info(currentTimeMillis + ": " + (memoryUsage/1024.0/1024.0));
memoryUsageTimeSeriesHeap.addOrUpdate(new FixedMillisecond(currentTimeMillis), currentHeap/MEGA);
memoryUsageTimeSeriesNonHeap.addOrUpdate(new FixedMillisecond(currentTimeMillis), currentNonHeap/MEGA);
memoryUsageTimeSeriesTotal.addOrUpdate(new FixedMillisecond(currentTimeMillis), (currentHeap + currentNonHeap)/MEGA);
updateMemoryChartPanel();
}
public final void resetCharts() {
memoryUsageTimeSeriesHeap = new TimeSeries("Heap Memory Usage (MB)");
memoryUsageTimeSeriesNonHeap = new TimeSeries("Non-Heap Memory Usage (MB)");
memoryUsageTimeSeriesTotal = new TimeSeries("Total Memory Usage (MB)");
seriesCollectionObservables = new XYSeriesCollection();
seriesCollectionRules = new XYSeriesCollection();
}
private final void updateLiveDataChartPanel(org.jfree.chart.ChartPanel chartPanel, XYSeriesCollection seriesCollection) {
// LOGGER.info("Entered updateLiveDataChartPanel with " + numberOfPlots + " plots.");
// Create X axis:
NumberAxis xAxis = new NumberAxis();
xAxis.setLowerMargin(0.02);
xAxis.setUpperMargin(0.02);
xAxis.setAutoRangeIncludesZero(true);
// Create Y axis:
NumberAxis yAxis = new NumberAxis();
yAxis.setLowerMargin(0.02);
yAxis.setUpperMargin(0.02);
yAxis.setAutoRangeIncludesZero(true);
// Plot:
XYPlot plot = new XYPlot();
plot.setBackgroundPaint(new Color(255,255,240));
plot.setDomainAxis(xAxis);
plot.setRangeAxis(yAxis);
plot.setDataset(seriesCollection);
int numberOfPlots = seriesCollection.getSeriesCount();
for (int i = 0; i < numberOfPlots; i++) {
plot.setRenderer(i, new ItemRenderer(ColorMap.getColor(i))); // XYLineAndShapeRenderer(true, false);
}
// Combine the plots
CombinedDomainXYPlot combinedPlot = new CombinedDomainXYPlot(xAxis);
combinedPlot.setOrientation(PlotOrientation.VERTICAL);
combinedPlot.setGap(8);
combinedPlot.add(plot, 1);
chartPanel.setChart(new JFreeChart(null, JFreeChart.DEFAULT_TITLE_FONT, combinedPlot, SHOW_LEGEND));
chartPanel.getChart().setBackgroundPaint(new Color(0, 0, 0, 0));
// LOGGER.info("--> Done with updateLiveDataChartPanel...");
}
/**
*
*/
private void updateMemoryChartPanel() {
// Create X axis:
DateAxis xAxis = new DateAxis();
xAxis.setLowerMargin(0.0);
xAxis.setUpperMargin(0.0);
xAxis.setLabel("Date");
// Combine the plots
CombinedDomainXYPlot combinedPlot = new CombinedDomainXYPlot(xAxis);
combinedPlot.setOrientation(PlotOrientation.VERTICAL);
combinedPlot.setGap(8);
combinedPlot.add(createTimeSeriesPlot(xAxis), 1);
// Create Chart:
memoryChartPanel.setChart(new JFreeChart(null, JFreeChart.DEFAULT_TITLE_FONT, combinedPlot, SHOW_LEGEND));
memoryChartPanel.getChart().setBackgroundPaint(new Color(0, 0, 0, 0));
}
private XYPlot createTimeSeriesPlot(DateAxis xAxis) {
// Create Y axis:
NumberAxis yAxis = new NumberAxis();
yAxis.setLowerMargin(0.02);
yAxis.setUpperMargin(0.02);
yAxis.setAutoRangeIncludesZero(true);
// Plot:
XYPlot plot = new XYPlot();
plot.setBackgroundPaint(new Color(255,255,240));
plot.setDomainAxis(xAxis);
plot.setRangeAxis(yAxis);
/*
XYItemRenderer renderer = new ItemRenderer();
renderer.setSeriesPaint(0, ColorMap.getColor(0));
renderer.setSeriesPaint(1, ColorMap.getColor(1));
renderer.setSeriesPaint(2, ColorMap.getColor(2));
// renderer.setSeriesStroke(0, new BasicStroke(5));
*/
plot.setDataset(0, new TimeSeriesCollection(memoryUsageTimeSeriesHeap));
plot.setDataset(1, new TimeSeriesCollection(memoryUsageTimeSeriesNonHeap));
plot.setDataset(2, new TimeSeriesCollection(memoryUsageTimeSeriesTotal));
plot.setRenderer(0, new ItemRenderer(ColorMap.getColor(0))); // XYLineAndShapeRenderer(true, false);
plot.setRenderer(1, new ItemRenderer(ColorMap.getColor(1)));
plot.setRenderer(2, new ItemRenderer(ColorMap.getColor(2)));
return plot;
}
public final void clearConsole() {
textArea.setDocument(new PlainDocument());
}
public final JTextArea getTextArea() {
return textArea;
}
//***************************************************************************************
/**
*
* @author ecemis
*/
private static final class ItemRenderer extends XYLineAndShapeRenderer {
private static final long serialVersionUID = 1L;
public ItemRenderer(final Color color) {
super(true, false);
Shape shape = SMALL_RECTANGLE;
setBaseShape(shape);
setBaseShape(shape);
setBaseItemLabelPaint(color);
setBasePaint(color);
}
}
}