/********************************************************************************************* * Copyright (c) 2014-2015 Software Behaviour Analysis Lab, Concordia University, Montreal, Canada * * All rights reserved. This program and the accompanying materials * are made available under the terms of Eclipse Public License v1.0 License which * accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Syed Shariyar Murtaza -- Initial design and implementation **********************************************************************************************/ package org.eclipse.tracecompass.totalads.ui.live; import org.eclipse.tracecompass.totalads.exceptions.TotalADSGeneralException; import org.eclipse.tracecompass.totalads.ui.live.Messages; import org.eclipse.tracecompass.totalads.ui.utilities.SWTResourceManager; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.swtchart.Chart; import org.swtchart.IAxis; import org.swtchart.ILineSeries; import org.swtchart.ILineSeries.PlotSymbolType; import org.swtchart.ISeries; import org.swtchart.ISeries.SeriesType; import org.swtchart.ISeriesSet; import org.swtchart.Range; /** * This class creates a chart * * @author <p> * Syed Shariyar Murtaza justsshary@hotmail.com * </p> * */ public class LiveXYChart { private Chart fXyChart; private PlotSymbolType[] fPlotSymbols; private Color[] fPlotColors; private final int fMAX_SERIES = 5; /** * Constructor * * @param compParent * Composite */ public LiveXYChart(Composite compParent) { fXyChart = new Chart(compParent, SWT.NONE); fXyChart.getTitle().setVisible(false); // Keep title invisible to get // more space for the chart fXyChart.getAxisSet().getXAxis(0).getTitle().setText(Messages.LiveXYChart_Time); fXyChart.getAxisSet().getYAxis(0).getTitle().setText(Messages.LiveXYChart_Anomalies); setXRange(0, 9, 100); setYRange(-1, 2); fPlotSymbols = new PlotSymbolType[fMAX_SERIES]; fPlotSymbols[0] = PlotSymbolType.CIRCLE; fPlotSymbols[1] = PlotSymbolType.DIAMOND; fPlotSymbols[2] = PlotSymbolType.CROSS; fPlotSymbols[3] = PlotSymbolType.INVERTED_TRIANGLE; fPlotSymbols[4] = PlotSymbolType.SQUARE; fPlotColors = new Color[fMAX_SERIES]; fPlotColors[0] = SWTResourceManager.getColor(SWT.COLOR_GREEN); fPlotColors[1] = SWTResourceManager.getColor(SWT.COLOR_BLUE); fPlotColors[2] = SWTResourceManager.getColor(SWT.COLOR_RED); fPlotColors[3] = SWTResourceManager.getColor(SWT.COLOR_MAGENTA); fPlotColors[4] = SWTResourceManager.getColor(SWT.COLOR_GRAY); } /** * This function initializes different series in a chart. It must be called * immediately after the creation of an object * * @param seriesNames * An array of series names * */ public void inititaliseSeries(final String[] seriesNames) { Display.getDefault().asyncExec(new Runnable() {// Always execute on the // main GUI thread @Override public void run() { for (int j = 0; j < seriesNames.length; j++) { ILineSeries lineSeries = (ILineSeries) fXyChart.getSeriesSet(). createSeries(SeriesType.LINE, seriesNames[j]); lineSeries.setSymbolType(getSymbol(j)); lineSeries.setLineColor(getColor(j)); lineSeries.enableStep(true); } } }); } /** * Sets minimum and maximum on Y axis * * @param min * Minimum value * @param max * Maximum value */ public void setYRange(final int min, final int max) { Display.getDefault().syncExec(new Runnable() {// Always execute on the // main GUI thread @Override public void run() { IAxis yAxis = fXyChart.getAxisSet().getYAxis(0); yAxis.setRange(new Range(min, max)); yAxis.getTick().setTickMarkStepHint(100); // fXyChart.getAxisSet().adjustRange(); } }); } /** * Sets minimum and maximum on X axis * * @param min * Minimum value * @param max * Maximum value * @param step * Step */ public void setXRange(final int min, final int max, final int step) { Display.getDefault().syncExec(new Runnable() {// Always execute on the // main GUI thread @Override public void run() { IAxis xAxis = fXyChart.getAxisSet().getXAxis(0); xAxis.setRange(new Range(min, max)); xAxis.getTick().setTickMarkStepHint(step);// fXyChart.getAxisSet().adjustRange(); } }); } /** * Returns the symbol for a series out of five symbols * * @param index * Index of five symbols * @return PlotSymbolType */ private PlotSymbolType getSymbol(int index) { if (index < fMAX_SERIES) { return fPlotSymbols[index]; } return fPlotSymbols[0]; } /** * Returns the color for a series out of five colors * * @param index * Index of five colors * @return Color */ private Color getColor(int index) { if (index < fMAX_SERIES) { return fPlotColors[index]; } return fPlotColors[0]; } /** * This function allows to add the values to a series that has been * intialised earlier using inititalizeSeries function. It throws an * exception if series name is not found * * @param ySeries * Array of double values * @param seriesName * Series name * @throws TotalADSGeneralException * An exception for invalid series */ public void addYSeriesValues(double[] ySeries, String seriesName) throws TotalADSGeneralException { // create line series ILineSeries lineSeries = (ILineSeries) fXyChart.getSeriesSet().getSeries(seriesName); if (lineSeries == null) { throw new TotalADSGeneralException(Messages.LiveXYChart_NoSeries); } lineSeries.setYSeries(ySeries); } /** * This function allows to add the values to a series that has been * intialized earlier using inititalizeSeries function. It throws an * exception if series name is not found * * @param ySeries * Array of double values * @param seriesName * Series name * @throws TotalADSGeneralException * An exception for invalid series */ public void addYSeriesValues(Double[] ySeries, String seriesName) throws TotalADSGeneralException { // First convert Double to double double[] yVals = new double[ySeries.length]; for (int j = 0; j < ySeries.length; j++) { yVals[j] = ySeries[j]; } // create line series ILineSeries lineSeries = (ILineSeries) fXyChart.getSeriesSet().getSeries(seriesName); if (lineSeries == null) { throw new TotalADSGeneralException(Messages.LiveXYChart_NoSeries); } lineSeries.setYSeries(yVals); } /** * This function sets the values on X axis that would be displayed for * corresponding points on Y axis * * @param xSeries * An array of double values * @param seriesName * Name of the series * @throws TotalADSGeneralException * An exception for invalid series */ public void addXSeriesValues(double[] xSeries, String seriesName) throws TotalADSGeneralException { // create line series // fXyChart.getSeriesSet().getSeries()[0].setXSeries(xSeries); ILineSeries lineSeries = (ILineSeries) fXyChart.getSeriesSet().getSeries(seriesName); if (lineSeries == null) { throw new TotalADSGeneralException(Messages.LiveXYChart_NoSeries); } lineSeries.setXSeries(xSeries); } /** * This function sets the values on X axis that would be displayed for * corresponding points on Y axis * * @param xSeries * An array of double values * @param seriesName * Series' name * @throws TotalADSGeneralException * An exception for invalid series */ public void addXSeriesValues(Double[] xSeries, String seriesName) throws TotalADSGeneralException { // First convert Double to double double[] xVals = new double[xSeries.length]; for (int j = 0; j < xSeries.length; j++) { xVals[j] = xSeries[j]; } // create line series // fXyChart.getSeriesSet().getSeries()[0].setXSeries(xVals); ILineSeries lineSeries = (ILineSeries) fXyChart.getSeriesSet().getSeries(seriesName); if (lineSeries == null) { throw new TotalADSGeneralException(Messages.LiveXYChart_NoSeries); } lineSeries.setXSeries(xVals); } /** * Draws the chart. It must be called every time the series is updated */ public void drawChart() { Display.getDefault().syncExec(new Runnable() {// Always execute on the // main GUI thread @Override public void run() { // adjust the axis range fXyChart.redraw(); } }); } /** * Clears the chart */ public void clearChart() { Display.getDefault().syncExec(new Runnable() {// Always execute on the // main GUI thread @Override public void run() { ISeriesSet seriesSet = fXyChart.getSeriesSet(); ISeries[] series = fXyChart.getSeriesSet().getSeries(); for (int j = 0; j < series.length; j++) { seriesSet.deleteSeries(series[j].getId()); } fXyChart.redraw(); } }); } }