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