/*
* Licensed Materials - Property of Perforce Software, Inc.
* © Copyright Perforce Software, Inc. 2014, 2021
* © Copyright IBM Corp. 2009, 2014
* © Copyright ILOG 1996, 2009
* All Rights Reserved.
*
* Note to U.S. Government Users Restricted Rights:
* The Software and Documentation were developed at private expense and
* are "Commercial Items" as that term is defined at 48 CFR 2.101,
* consisting of "Commercial Computer Software" and
* "Commercial Computer Software Documentation", as such terms are
* used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4,
* as applicable.
*/
package realtime;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Enumeration;
import java.util.List;
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSlider;
import javax.swing.RepaintManager;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.BevelBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import ilog.views.chart.IlvChart;
import ilog.views.chart.IlvColor;
import ilog.views.chart.IlvScale;
import ilog.views.chart.IlvStyle;
import ilog.views.chart.data.IlvCyclicDataSet;
import ilog.views.chart.data.IlvDataSet;
import ilog.views.chart.data.IlvDefaultDataSet;
import ilog.views.chart.data.IlvMovingAvgDataSet;
import ilog.views.chart.graphic.IlvMarkerFactory;
import ilog.views.chart.graphic.IlvMarkerIcon;
import ilog.views.chart.renderer.IlvPieChartRenderer;
import ilog.views.chart.renderer.IlvSingleAreaRenderer;
import ilog.views.chart.renderer.IlvSingleBarRenderer;
import ilog.views.chart.renderer.IlvSingleChartRenderer;
import ilog.views.chart.renderer.IlvSinglePieRenderer;
import ilog.views.chart.renderer.IlvSinglePolylineRenderer;
import ilog.views.chart.renderer.IlvSingleScatterRenderer;
import ilog.views.chart.renderer.IlvSingleStairRenderer;
import ilog.views.util.IlvImageUtil;
/**
* An example showing the capabilities of the Charts library for real-time
* charting.
*/
public class RealTimeDemo extends shared.AbstractChartExample {
/** The number of charts. */
private static final int MONITOR_COUNT = 6;
private static final String BUTTON_GROUP_PROP = "_ButtonGroup_Property__";
private static final String ADD_POINT_TITLE = "New Points Per Update: ";
// the default sizes of various windows
// private static final int MAIN_WINDOW_DEFAULT_WIDTH = 550;
// private static final int MAIN_WINDOW_DEFAULT_HEIGHT = 500;
/** Number of visible points. */
private static final int VISI_COUNT = 70;
/** The data sets. */
private MonitorDataSet[] inputData;
private IlvChart[] monitors;
/** Number of points added during each update. */
private int updateCount = 2;
/** The data sets of the redraw operation monitor. */
private IlvDataSet drawTimeData;
private IlvDefaultDataSet pieDrawTime;
private IlvMovingAvgDataSet avgDrawTimeData;
/** The panel used to change the update period. */
protected AnimationPanel animPanel;
/** A custom repaint manager that logs drawing time. */
private LogRepaintManager logRpm;
// private Random random = new Random();
// private JFrame topFrame;
/**
* Initializes the example's user interface in the specified container.
*
* @param container
* The <code>contentPane</code> of the
* <code>JFrame</code>.
*/
Override
public void init(Container container) {
super.init(container);
((BorderLayout) container.getLayout()).setVgap(4);
GridLayout layout = new GridLayout(MONITOR_COUNT / 2, 2);
layout.setHgap(4);
layout.setVgap(4);
JPanel monitorPanel = new JPanel(layout);
// Create the data sets. The data sets containing the random values are
// instances of IlvCyclicDataSet with a buffer size equal to VISI_COUNT and
// no x values storage.
inputData = new MonitorDataSet[MONITOR_COUNT];
monitors = new IlvChart[MONITOR_COUNT];
List<Color> defaultColors = IlvColor.getDefaultColors();
Color[] colors = defaultColors.toArray(new Color[defaultColors.size()]);
colors[0] = IlvColor.lightBlue;
colors[1] = IlvColor.orchid;
for (int i = 0; i < MONITOR_COUNT; ++i) {
IlvChart chart = createMonitor(i);
monitors[i] = chart;
inputData[i] = new MonitorDataSet("Input#" + i, VISI_COUNT);
chart.addDecoration(inputData[i].getCursor());
Color color = colors[i % colors.length];
IlvStyle style = new IlvStyle(color, IlvColor.darker(color));
IlvSingleChartRenderer r = createSelectedRenderer(chart);
if (r != null) {
if (r instanceof IlvSingleScatterRenderer)
style = style.setStrokeOn(false);
r.setStyle(style);
chart.addRenderer(r, inputData[i]);
}
monitorPanel.add(chart);
}
container.add(monitorPanel, BorderLayout.CENTER);
animPanel = new AnimationPanel(10) {
Override
public void sweepModeChanged(boolean sweepMode) {
for (int i = 0; i < MONITOR_COUNT; ++i) {
monitors[i].setShiftScroll(!sweepMode);
monitors[i].getXAxis().setVisibleRange(0, VISI_COUNT - 1);
inputData[i].setSweepMode(sweepMode);
}
}
Override
public void timerChanged() {
addData();
}
};
animPanel.setForeground(Color.white);
JSlider slider = new JSlider(JSlider.HORIZONTAL, 1, 20, updateCount);
slider.setMajorTickSpacing(5);
slider.setMinorTickSpacing(1);
final TitledBorder title = new TitledBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.black),
ADD_POINT_TITLE + slider.getValue());
title.setTitleColor(Color.black);
slider.setBorder(title);
slider.addChangeListener(new ChangeListener() {
Override
public void stateChanged(ChangeEvent evt) {
JSlider slider = ((JSlider) evt.getSource());
updateCount = slider.getValue();
title.setTitle(ADD_POINT_TITLE + updateCount);
slider.repaint();
}
});
JPanel top = new JPanel(new GridLayout(1, 2));
top.add(animPanel);
top.add(slider);
container.add(top, BorderLayout.NORTH);
// Create the performance panel.
container.add(createPerfPanel(), BorderLayout.SOUTH);
// Create a LogRepaintManager to monitor the time spend
// in drawing operations.
logRpm = new LogRepaintManager() {
// Adds the new measure to drawTimeData.
Override
public void newLog(long elapsed, long drawTime) {
if (animPanel.getTimer().isRunning()) {
double v = Math.min(100., (100. * drawTime) / elapsed);
drawTimeData.addData(0, v);
int count = avgDrawTimeData.getDataCount();
if (count > 0) {
v = avgDrawTimeData.getYData(count - 1);
pieDrawTime.setData(0, -1, 100 - v);
pieDrawTime.setData(1, -1, v);
}
}
}
};
RepaintManager.setCurrentManager(logRpm);
logRpm.startLog();
}
/**
* Creates a chart monitor.
*/
protected IlvChart createMonitor(int i) {
// Create a new Cartesian chart with no default scales & grids.
final IlvChart chart = new IlvChart(IlvChart.CARTESIAN, false);
// Set a simple grid on the y-axis.
chart.setYGrid(0, new SimpleGrid(Color.black, 2));
// Configure the x and y axes.
chart.getXAxis().setAutoDataRange(false);
chart.getXAxis().setVisibleRange(0, VISI_COUNT - 1);
chart.getYAxis(0).setDataRange(-8, 8);
// Enable automatic scrolling as new data comes in outside the visible
// range.
chart.setShiftScroll(true);
// Add a header. A header is a JComponent added to the chart on top
// of the chart area.
ActionListener lst = new ActionListener() {
Override
public void actionPerformed(ActionEvent evt) {
IlvSingleChartRenderer r = createSelectedRenderer(chart);
if (r != null) {
IlvStyle style = chart.getRenderer(0).getStyle(0);
if (r instanceof IlvSingleScatterRenderer)
style = style.setStrokeOn(false);
else
style = style.setStrokeOn(true);
try {
r.setStyle(style);
chart.setRenderer(0, r);
} catch (IllegalArgumentException e) {
}
}
}
};
JPanel header = new JPanel();
header.setLayout(new BoxLayout(header, BoxLayout.X_AXIS));
header.setBackground(Color.gray);
header.setOpaque(true);
JLabel label = new JLabel("Monitor#" + i, JLabel.LEFT);
label.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0));
label.setForeground(Color.white);
header.add(label);
JPanel panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
panel.setOpaque(false);
ButtonGroup group = new ButtonGroup();
JRadioButton button = createRendererButton("pline.gif", "pline2.gif", "POLYLINE", "Polyline");
button.addActionListener(lst);
group.add(button);
panel.add(button);
button = createRendererButton("stair.gif", "stair2.gif", "STAIR", "Stair");
button.addActionListener(lst);
group.add(button);
panel.add(button);
button = createRendererButton("scatter.gif", "scatter2.gif", "SCATTER", "Scatter");
button.addActionListener(lst);
group.add(button);
panel.add(button);
button = createRendererButton("area.gif", "area2.gif", "AREA", "Area");
button.addActionListener(lst);
group.add(button);
panel.add(button);
button = createRendererButton("bar.gif", "bar2.gif", "BAR", "Bar");
button.addActionListener(lst);
group.add(button);
panel.add(button);
Enumeration<AbstractButton> elems = group.getElements();
int elemIdx = 0;
while (elemIdx++ < i % group.getButtonCount())
elems.nextElement();
elems.nextElement().setSelected(true);
header.add(panel);
header.putClientProperty(BUTTON_GROUP_PROP, group);
chart.setHeader(header);
// Customize the chart appeareance.
configureChart(chart, true);
return chart;
}
private JRadioButton createRendererButton(String iconName, String selIconName, String actionCmd, String tooltip) {
ImageIcon icon = null, selIcon = null;
try {
icon = new ImageIcon(IlvImageUtil.loadImageFromFile(getClass(), iconName));
selIcon = new ImageIcon(IlvImageUtil.loadImageFromFile(getClass(), selIconName));
} catch (Exception e) {
}
JRadioButton button = new JRadioButton(icon);
button.setHorizontalAlignment(JRadioButton.LEFT);
button.setBorder(null);
button.setSelectedIcon(selIcon);
button.setPreferredSize(new Dimension(button.getIcon().getIconWidth(), button.getIcon().getIconHeight()));
button.setActionCommand(actionCmd);
button.setToolTipText(tooltip);
return button;
}
/**
* Creates an instance of the current selected renderer type.
*/
private IlvSingleChartRenderer createSelectedRenderer(IlvChart chart) {
ButtonGroup group = (ButtonGroup) chart.getHeader().getClientProperty(BUTTON_GROUP_PROP);
String action = group.getSelection().getActionCommand();
IlvSingleChartRenderer r = null;
if (action.equals("POLYLINE"))
r = new IlvSinglePolylineRenderer();
else if (action.equals("SCATTER"))
r = new IlvSingleScatterRenderer(IlvMarkerFactory.getSquareMarker(), 2, null) {
Override
public boolean isClipped() {
return true;
}
};
else if (action.equals("AREA"))
r = new IlvSingleAreaRenderer();
else if (action.equals("STAIR"))
r = new IlvSingleStairRenderer();
else if (action.equals("BAR"))
r = new IlvSingleBarRenderer();
return r;
}
/**
* Invoked by the background timer to add new data points.
*/
protected void addData() {
for (int i = 0; i < MONITOR_COUNT; ++i) {
MonitorDataSet ds = inputData[i];
// If we use the sweep mode, then data will be modified instead of being
// appended. In that case, using batch updates would generate a
// FULL_UPDATE
// event.
if (!ds.isSweepMode())
ds.startBatch();
for (int j = 0; j < updateCount; ++j) {
ds.processData(RandomGenerator.rand(ds.getCounter()));
}
if (!ds.isSweepMode())
ds.endBatch();
}
}
/**
* Creates a panel holding the chart that displays drawing time.
*/
protected JPanel createPerfPanel() {
JPanel perfPanel = new JPanel(new BorderLayout());
perfPanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
IlvChart chart = new IlvChart();
configureChart(chart, false);
// Configure axes.
chart.getXAxis().setAutoDataRange(false);
chart.getXAxis().setVisibleRange(0, 50);
chart.getYAxis(0).setDataMin(0);
// We can specify a max of 100, but the auto-adjusting feature
// shows small percentages in a better way.
// chart.getYAxis(0).setDataMax(100);
chart.setShiftScroll(true);
chart.setScrollRatio(0.2);
// Configure scales & grids.
chart.setXScale(null);
chart.setXGrid(new SimpleGrid(Color.black, 2));
chart.getYGrid(0).setMajorPaint(Color.black);
chart.getYScale(0).setTickLayout(IlvScale.TICK_INSIDE);
// Add the chart renderer that displays drawing time.
IlvStyle style = IlvStyle.createStroked(IlvColor.mediumSpringGreen);
IlvSinglePolylineRenderer poly = new IlvSinglePolylineRenderer(style);
poly.setMarker(IlvMarkerFactory.getSquareMarker());
poly.setMarkerSize(2);
// The renderer displays the moving average of the drawing time.
drawTimeData = new IlvCyclicDataSet("PerfLog", 101, IlvCyclicDataSet.LINEAR_MODE, false);
avgDrawTimeData = new IlvMovingAvgDataSet(drawTimeData, 5);
chart.addRenderer(poly, avgDrawTimeData);
// Add a header.
IlvMarkerIcon icon = new IlvMarkerIcon(IlvMarkerIcon.SQUARE_MARKER, 6, new IlvStyle(IlvColor.mediumSpringGreen));
JLabel header = new JLabel("Drawing time (% of overall spent time)", icon, SwingConstants.CENTER);
header.setForeground(Color.white);
header.setOpaque(true);
header.setBackground(Color.gray);
perfPanel.add(header, BorderLayout.NORTH);
perfPanel.add(chart, BorderLayout.CENTER);
chart = new IlvChart(IlvChart.PIE);
chart.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 0));
chart.getChartArea().setOpaque(true);
configureChart(chart, false);
chart.setAntiAliasing(true);
pieDrawTime = new IlvDefaultDataSet("Drawing Time", new double[] { 100., 0. });
pieDrawTime.setDataLabels(new String[] { "Other", "Drawing time" });
IlvPieChartRenderer pieR = new IlvPieChartRenderer();
pieR.getDataSource().addDataSet(pieDrawTime);
chart.addRenderer(pieR);
int dim = (int) Math.min(chart.getPreferredSize().getHeight(), chart.getPreferredSize().getWidth());
chart.setPreferredSize(new Dimension(dim, dim));
((IlvSinglePieRenderer) pieR.getChild(0))
.setSliceColors(new Color[] { IlvColor.darkSlateGray, IlvColor.mediumSpringGreen });
perfPanel.add(chart, BorderLayout.EAST);
return perfPanel;
}
/**
* Customizes the appearance of the specified chart.
*/
protected void configureChart(IlvChart chart, boolean withBorder) {
chart.setForeground(Color.black);
chart.setFont(new Font("Dialog", Font.PLAIN, 10));
chart.getChartArea().setPlotStyle(new IlvStyle(Color.black, IlvColor.darkSlateGray));
if (withBorder)
chart.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
}
/**
* Application mainline.
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
Override
public void run() {
JFrame frame = new JFrame("Real-time Supervision sample");
shared.AbstractChartExample demo = new RealTimeDemo();
demo.init(frame.getContentPane());
demo.setFrameGeometry(650, 600, true);
frame.setVisible(true);
}
});
}
}