/*
* 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 listener;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.SwingUtilities;
import ilog.views.chart.IlvAffineAxisTransformer;
import ilog.views.chart.IlvAxis;
import ilog.views.chart.IlvChart;
import ilog.views.chart.IlvColor;
import ilog.views.chart.IlvLegend;
import ilog.views.chart.IlvScale;
import ilog.views.chart.IlvStyle;
import ilog.views.chart.IlvValueFormat;
import ilog.views.chart.data.IlvDataSet;
import ilog.views.chart.data.IlvDataSource;
import ilog.views.chart.data.IlvDefaultDataSet;
import ilog.views.chart.event.DataSetContentsEvent;
import ilog.views.chart.event.DataSetListener;
import ilog.views.chart.event.DataSetPropertyEvent;
import ilog.views.chart.graphic.IlvGradientRenderingHint;
import ilog.views.chart.renderer.IlvBarChartRenderer;
import ilog.views.chart.renderer.IlvHiLoChartRenderer;
import shared.AbstractChartExample;
import shared.AnimationPanel;
/**
* The <code>ListenerDemo</code> class.
*/
public class ListenerDemo extends AbstractChartExample {
/** Font for y-scales. */
protected static final Font Y_SCALE_FONT = new Font("Dialog", Font.PLAIN, 10);
/** The default stroke used by renderers. */
protected static final Stroke DEFAULT_STROKE = new BasicStroke(2.f);
/** The default background color used for plotting areas. */
protected static final Color BG_COLOR = IlvColor.getColor("slategrey");// dimGray;
// IlvColor.darker(Color.gray);
/** The hilo chart renderer. */
protected IlvHiLoChartRenderer hiloR;
/** The hilo data source. */
protected IlvDataSource hiloDS;
/** The temperature data set. */
protected IlvDataSet tempDs;
/**
* The <code>DataSetListener</code> used to update the hilo data source when a
* point is added to the temperature data set.
*/
DataSetListener tempListener = new DataSetListener() {
// Call when a change occurs on the temperature data set.
Override
public void dataSetContentsChanged(DataSetContentsEvent evt) {
if (evt.getType() == DataSetContentsEvent.DATA_ADDED) {
IlvDataSet ds = evt.getDataSet();
double x = ds.getXData(evt.getFirstIdx());
double y = ds.getYData(evt.getFirstIdx());
int count = ds.getDataCount() - 1;
if (count < 0)
count = 0;
if ((count % 24) == 0) {
// If the point begins a new day, add it to all the hilo data
// sets (Low, High, Start, End).
for (int i = 0; i < hiloDS.getDataSetCount(); ++i) {
hiloDS.getDataSet(i).addData(0, y);
}
} else {
// Otherwise, update the hilo data sets depending on the new
// value:
// - The new point is added to the "end" data set (since it
// is the last point at this time).
// - If its y value is the highest value, add it to the
// high data set.
// - If its y value is the lowest value, add it to the low
// data set.
int idx = count / 24;
// Add the new point to the "end" data set.
hiloDS.getDataSet(3).setData(idx, x, y);
// Update the high data set.
double oldTemp = hiloDS.getDataSet(1).getYData(idx);
if (y > oldTemp)
hiloDS.getDataSet(1).setData(idx, x, y);
// Update the low data set.
oldTemp = hiloDS.getDataSet(0).getYData(idx);
if (y < oldTemp)
hiloDS.getDataSet(0).setData(idx, x, y);
}
}
}
Override
public void dataSetPropertyChanged(DataSetPropertyEvent evt) {
}
};
// The timer ActionListener used to generate the new values.
ActionListener tl = new ActionListener() {
Override
public void actionPerformed(ActionEvent evt) {
int count = tempDs.getDataCount();
double oldy = (count != 0) ? tempDs.getYData(count - 1) : 0;
tempDs.addData(0, ValueGenerator.nextValue(oldy));
}
};
/**
* Initializes the sample.
*/
Override
public void init(Container container) {
super.init(container);
AnimationPanel animPanel = new AnimationPanel(10);
animPanel.getTimer().setInitialDelay(0);
// Plug the action listener used to generate the values on the timer.
animPanel.getTimer().addActionListener(tl);
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createTitledBorder("HiLo mode"));
ButtonGroup group = new ButtonGroup();
// A hilo renderer can have 3 representation modes: CLUSTERED, CANDLE,
// and OPENCLOSE. The first one only handles pairs of data sets, so it
// cannot be used here (we want to handle low/high/start/end data).
// This radio button switches the mode to CANDLE.
JRadioButton radio = new JRadioButton("Candle");
radio.addActionListener(new ActionListener() {
Override
public void actionPerformed(ActionEvent evt) {
hiloR.setMode(IlvHiLoChartRenderer.CANDLE);
}
});
group.add(radio);
panel.add(radio);
// This radio button switches the mode to OPENCLOSE.
radio = new JRadioButton("OpenClose", true);
radio.addActionListener(new ActionListener() {
Override
public void actionPerformed(ActionEvent evt) {
hiloR.setMode(IlvHiLoChartRenderer.OPENCLOSE);
}
});
group.add(radio);
panel.add(radio);
animPanel.add(panel);
animPanel.setBorder(BorderFactory.createEtchedBorder());
container.setLayout(new BorderLayout());
container.add(animPanel, BorderLayout.NORTH);
// == Create the charts.
IlvChart tempChart = createChart();
IlvChart hiloChart = createChart();
// == tempChart initialization.
// Disable the auto data range calculation on both axes and set the
// x visible range to 48 hours
tempChart.getXAxis().setAutoDataRange(false);
tempChart.getXAxis().setVisibleRange(0, 48);
IlvScale xScale = tempChart.getXScale();
// We want to format the scale labels as Day:Hour. To do so, a
// specialized IlvValueFormat is set on the x scale. This format is used
// by the scale when computing the labels.
xScale.setLabelFormat(new IlvValueFormat() {
StringBuffer buffer = new StringBuffer();
Override
public synchronized String formatValue(double value) {
buffer.setLength(0);
buffer.append(Integer.toString((int) value / 24 + 1));
buffer.append(":");
buffer.append(Integer.toString((int) value % 24));
return buffer.toString();
}
});
xScale.setStepUnit(Double.valueOf(12.), Double.valueOf(1.));
// Set the x-scale title.
xScale.setTitle("Day : Hour");
// The data set containing the temperatures.
tempDs = new IlvDefaultDataSet("Temperature", 32, false);
// Add the listener used to update the hilo data sets.
tempDs.addDataSetListener(tempListener);
// The temperatures are rendered as bars, covering 100% of the cluster
// area.
IlvBarChartRenderer barR = new IlvBarChartRenderer(100, IlvBarChartRenderer.CLUSTERED);
// Add the bar renderer to the chart and associate it with the
// temperature data set.
tempChart.addRenderer(barR, tempDs);
// To show graphically where a measurement lies in the
// temperature range, each bar will be rendered using its own color,
// the color being determined according to the temperature value:
// the coldest temperature will be rendered as a blue bar, the hottest
// as a red one. This color determination is done automatically by the
// bar renderer at drawing time, thanks to an IlvGradientRenderingHint.
// You just have to define the gradient (a value-color binding) and
// set this rendering hint on the temperature data set.
double[] values = { ValueGenerator.TMIN, 0, ValueGenerator.TMAX };
Color[] colors = { Color.blue, Color.white, Color.red };
IlvGradientRenderingHint hint = new IlvGradientRenderingHint(values, colors);
barR.setRenderingHint(tempDs, hint);
// Set visible range.
hiloChart.getXAxis().setAutoDataRange(false);
hiloChart.getXAxis().setVisibleRange(0, 28);
// A ValueFormat that formats the scale labels as Week:Day.
hiloChart.getXScale().setLabelFormat(new IlvValueFormat() {
StringBuffer buffer = new StringBuffer();
Override
public synchronized String formatValue(double value) {
buffer.setLength(0);
buffer.append(Integer.toString((int) value / 7 + 1));
buffer.append(":");
buffer.append(Integer.toString((int) value % 7 + 1));
return buffer.toString();
}
});
hiloChart.getXScale().setStepUnit(Double.valueOf(7.), Double.valueOf(1.));
hiloChart.getXScale().setTitle("Week : Day", 0.);
// hiloChart.getXScale().setTitlePlacement(99);
// Create an IlvHiLoChartRenderer in OPENCLOSE mode. In this mode, an
// IlvHiLoChartRenderer handles 2 pairs of data sets per child renderer:
// the Low/High data sets and the Start/End (that is, OPENCLOSE) data sets.
// Each pair is associated with one IlvSingleHiLoRenderer child.
hiloR = new IlvHiLoChartRenderer(IlvHiLoChartRenderer.OPENCLOSE, 0, 50);
// Create the Low, High, Start, and End data sets that will be
// associated with this renderer.
IlvDataSet[] hiloDatasets = { new IlvDefaultDataSet("Low", 32, false), new IlvDefaultDataSet("High", 32, false),
new IlvDefaultDataSet("Start", 32, false), new IlvDefaultDataSet("End", 32, false) };
hiloDS = hiloR.getDataSource();
hiloDS.setDataSets(hiloDatasets);
hiloChart.addRenderer(hiloR);
// Initialize custom rendering styles. An IlvSingleHiLoRenderer uses two
// rendering styles: one as the rise rendering style, one as the fall
// rendering style. Since 2 children are handled, we need to define 4
// rendering styles, each pair associated with a child renderer.
Color rise = new Color(183, 183, 255);
Color fall = new Color(255, 123, 123);
IlvStyle[] styles = { new IlvStyle(DEFAULT_STROKE, Color.white, Color.lightGray), // rise
new IlvStyle(DEFAULT_STROKE, new Color(100, 149, 237), new Color(60, 119, 197)), // fall
new IlvStyle(DEFAULT_STROKE, rise, IlvColor.brighter(rise)), // rise
new IlvStyle(DEFAULT_STROKE, fall, IlvColor.brighter(fall)) // fall
};
hiloR.setStyles(styles);
panel = new JPanel();
panel.setLayout(new GridLayout(0, 1));
panel.setBorder(BorderFactory.createEtchedBorder());
panel.add(tempChart);
panel.add(hiloChart);
container.add(panel, BorderLayout.CENTER);
// Initialize a legend.
IlvLegend legend = new IlvLegend();
legend.setBackground(BG_COLOR);
legend.setForeground(Color.white);
legend.setBorder(BorderFactory.createLineBorder(Color.black, 2));
// Set a flow layout. By default, the legend uses a GridLayout when
// it is not added to a chart.
legend.setLayout(new FlowLayout());
// Associate the legend with the hilo chart. This legend is not added to
// the chart itself, but to the main container.
hiloChart.setLegend(legend);
panel = new JPanel();
panel.setBorder(BorderFactory.createEtchedBorder());
panel.add(legend);
container.add(panel, BorderLayout.SOUTH);
}
/**
* Creates a chart instance with custom settings.
*/
protected IlvChart createChart() {
IlvChart chart = new IlvChart();
chart.setForeground(Color.black);
chart.setScalingFont(true);
// == Customize y-scales.
IlvScale yScale = chart.getYScale(0);
yScale.setTitle("Celsius");
// The y-scale title position will be at 100% of
// the visible range, that is, at the maximum value.
// The default value is 50, that is, at the middle of the scale.
yScale.setTitlePlacement(100);
yScale.setLabelFont(Y_SCALE_FONT);
// Explicitly set the data range of the y-scales to [TMIN, TMAX].
chart.getYAxis(0).setDataRange(ValueGenerator.TMIN, ValueGenerator.TMAX);
addFahrenheitScale(chart);
// == Customize Chart Area.
IlvChart.Area chartArea = chart.getChartArea();
chartArea.setPlotBackground(BG_COLOR);
// Enable automatic scrolling as new data comes in outside the visible
// range. The amount of visible range scrolled back is set to .5, meaning
// that half the visible range will be scrolled.
chart.setShiftScroll(true);
chart.setScrollRatio(.5);
return chart;
}
/**
* Adds another y-scale to the chart. This scale will display graduations
* using fahrenheit degrees.
*/
private void addFahrenheitScale(IlvChart chart) {
// Add another y-scale
IlvAxis yAxis = chart.addYAxis(true, false);
// Set a transformer that represents Celcius->Fahrenheit conversion
yAxis.setTransformer(new IlvAffineAxisTransformer(1.8, 32));
// Synchronize the 'Fahrenheit' axis with the 'Celcius' axis.
yAxis.synchronizeWith(chart.getYAxis(0), true);
IlvScale yScale = chart.getYScale(1);
yScale.setTitle("Fahrenheit");
yScale.setTitlePlacement(100);
yScale.setLabelFont(Y_SCALE_FONT);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
Override
public void run() {
JFrame frame = new JFrame("DataSet listener sample");
ListenerDemo demo = new ListenerDemo();
demo.init(frame.getContentPane());
demo.setFrameGeometry(600, 600, true);
frame.setVisible(true);
}
});
}
}