/* * 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); } }); } }