/**********************************************************************
* Copyright (c) 2013, 2015 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alexandre Montplaisir - Initial API and implementation
* Bernd Hufmann - Updated for TMF base chart viewer
**********************************************************************/
package org.eclipse.tracecompass.tmf.ui.viewers.xycharts.barcharts;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.TmfChartTimeStampFormat;
import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.TmfXYChartViewer;
import org.swtchart.Chart;
import org.swtchart.IAxisTick;
import org.swtchart.IBarSeries;
import org.swtchart.ISeries;
import org.swtchart.ISeries.SeriesType;
/**
* Abstract bar chart viewer class implementation. Used for displaying
* histograms.
*
* @author Alexandre Montplaisir
* @author Bernd Hufmann
*/
public abstract class TmfBarChartViewer extends TmfXYChartViewer {
// ------------------------------------------------------------------------
// Constants
// ------------------------------------------------------------------------
/** Width of each histogram bar, in pixels */
public static final int MINIMUM_BAR_WIDTH = 1;
// ------------------------------------------------------------------------
// Attributes
// ------------------------------------------------------------------------
/** List of series */
private final List<String> seriesNames = new ArrayList<>();
/** List of colors */
private final List<RGB> colors = new ArrayList<>();
/** the bar width */
private int fBarWidth = MINIMUM_BAR_WIDTH;
// ------------------------------------------------------------------------
// Constructors
// ------------------------------------------------------------------------
/**
* Constructs a TmfXYChartViewer.
*
* @param parent
* The parent composite
* @param title
* The title of the viewer
* @param xLabel
* The label of the xAxis
* @param yLabel
* The label of the yAXIS
* @param barWidth
* The bar width
*/
public TmfBarChartViewer(Composite parent, String title, String xLabel, String yLabel, int barWidth) {
super(parent, title, xLabel, yLabel);
fBarWidth = barWidth;
setTooltipProvider(new TmfHistogramTooltipProvider(this));
}
// ------------------------------------------------------------------------
// Operations
// ------------------------------------------------------------------------
@Override
protected void updateContent() {
getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
Chart swtChart = getSwtChart();
int numRequests = swtChart.getPlotArea().getBounds().width / fBarWidth;
for (int i = 0; i < seriesNames.size(); i++) {
ISeries series = swtChart.getSeriesSet().getSeries(seriesNames.get(i));
if (series == null) {
series = initSeries(seriesNames.get(i), colors.get(i));
}
readData(series, getWindowStartTime(), getWindowEndTime(), numRequests);
}
}
});
}
/**
* Method to add a series to the chart.
*
* @param name
* Name of series
* @param color
* color to use for series
*/
protected void addSeries(String name, RGB color) {
seriesNames.add(name);
colors.add(color);
}
/**
* Clears all series
*/
protected void clearSeries() {
seriesNames.clear();
colors.clear();
}
/**
* Draw the given series on the chart
*
* @param series
* The series to display
* @param x
* The X values. It can be computed with
* {@link TmfBarChartViewer#getXAxis}
* The values are stored in the internal time representation.
* To get the trace time one has to add the time offset
* {@link #getTimeOffset()}.
* @param y
* The Y values that were computed by the extended class
*/
protected void drawChart(final ISeries series, final double[] x, final double[] y) {
// Run in GUI thread to make sure that chart is ready after restart
final Display display = getDisplay();
if (display.isDisposed()) {
return;
}
display.syncExec(new Runnable() {
@Override
public void run() {
if (display.isDisposed()) {
return;
}
Chart swtChart = getSwtChart();
IAxisTick xTick = swtChart.getAxisSet().getXAxis(0).getTick();
xTick.setFormat(new TmfChartTimeStampFormat(getTimeOffset()));
series.setXSeries(x);
series.setYSeries(y);
xTick.setTickMarkStepHint(256);
swtChart.getAxisSet().adjustRange();
swtChart.redraw();
}
});
}
/**
* Convenience method to compute the X axis values for a given time range.
*
* @param start
* Start of the time range
* @param end
* End of the range
* @param nb
* Number of steps. This will be the size of the returned array.
* @return The time values (converted to double) that match every step
*/
protected final static double[] getXAxis(long start, long end, int nb) {
double timestamps[] = new double[nb];
long steps = (end - start);
double step = steps / (double) nb;
double curTime = 1;
for (int i = 0; i < nb; i++) {
timestamps[i] = curTime;
curTime += step;
}
return timestamps;
}
/**
* Load the data for the given series. This method should call
* {@link TmfBarChartViewer#drawChart} to return the results when done.
*
* Careful, this method is called by a signal handler which also happens to
* be in the main UI thread. This means any processing will block the UI! In
* most cases it's probably better to start a separate Thread/Job to do the
* processing, and that one can call drawChart() when done to update the
* view.
*
* @param series
* Which series of the chart should the viewer update
* @param start
* The start time (in nanoseconds) of the range to display
* @param end
* The end time of the range to display.
* @param nb
* The number of 'steps' in the bar chart (fewer steps means each
* bar is wider).
*/
protected abstract void readData(ISeries series, long start, long end, int nb);
// initializes a series
private IBarSeries initSeries(String name, RGB color) {
IBarSeries bs = (IBarSeries) getSwtChart().getSeriesSet().createSeries(SeriesType.BAR, name);
bs.enableStack(true);
bs.setBarColor(new Color(Display.getDefault(), color));
bs.setBarPadding(0);
return bs;
}
}