/****************************************************************
* Copyright (c) 2006-2015 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
* Red Hat Inc. - ongoing maintenance
****************************************************************
*/
package org.eclipse.linuxtools.internal.systemtap.graphing.ui.charts;
import org.eclipse.linuxtools.internal.systemtap.graphing.ui.charts.listeners.BarChartMouseMoveListener;
import org.eclipse.linuxtools.systemtap.graphing.core.adapters.IAdapter;
import org.eclipse.swt.widgets.Composite;
import org.swtchart.IBarSeries;
import org.swtchart.ISeries;
import org.swtchart.ISeries.SeriesType;
import org.swtchart.Range;
/**
* A {@link Composite} for building a bar chart.
* @author Qi Liang
*/
public class BarChartBuilder extends AbstractChartWithAxisBuilder {
public static final String ID = "org.eclipse.linuxtools.systemtap.graphing.ui.charts.barchartbuilder"; //$NON-NLS-1$
public BarChartBuilder(Composite parent, int style, String title, IAdapter adapter) {
super(adapter, parent, style, title);
}
@Override
protected double getChartMarginYL() {
return 0;
}
@Override
protected void createChart() {
this.chart = new BarChart(this, getStyle());
applyTitleBoundsListener();
chartMouseMoveListener = new BarChartMouseMoveListener((BarChart) chart, chart.getPlotArea());
}
@Override
protected ISeries createChartISeries(int i) {
IBarSeries series = (IBarSeries)chart.getSeriesSet().
createSeries(SeriesType.BAR, adapter.getLabels()[i+1]);
series.setBarColor(COLORS[i % COLORS.length]);
return series;
}
@Override
protected void buildXSeries() {
Object data[][] = adapter.getData();
if (data == null || data.length == 0) {
return;
}
int start = 0, len = Math.min(this.maxItems, data.length), leny = data[0].length-1;
if (this.maxItems < data.length) {
start = data.length - this.maxItems;
}
String[] allValx = new String[len];
Double[][] allValy = new Double[leny][len];
// Want to show x-axis if possible, so default max/min is 0.
double maxY = 0;
double minY = 0;
// Read in from the data array all x/y points to plot.
// If a y-axis value is empty (null), set it to 0.
// If an x-axis category is empty, ignore the entire category.
for (int i = 0; i < len; i++) {
Object label = data[start + i][0];
if (label != null) {
allValx[i] = label.toString();
for (int j = 1; j < leny + 1; j++) {
Double val = getDoubleOrNullValue(data[start + i][j]);
if (val == null) {
val = 0.0;
}
allValy[j-1][i] = val;
maxY = Math.max(val, maxY);
minY = Math.min(val, minY);
}
}
}
// Now create dense arrays of x/y values that exclude null values,
// and plot those values to the chart.
String valx[] = new String[len];
int lenTrim = 0;
for (int i = 0; i < len; i++) {
if (allValx[i] != null) {
valx[lenTrim] = allValx[i];
lenTrim++;
}
}
String[] valxTrim = new String[lenTrim];
System.arraycopy(valx, 0, valxTrim, 0, lenTrim);
ISeries allSeries[] = chart.getSeriesSet().getSeries();
for (int i = 0; i < leny; i++) {
ISeries series;
if (i >= allSeries.length) {
series = createChartISeries(i);
} else {
series = chart.getSeriesSet().getSeries()[i];
}
double[] valy = new double[len];
int lenyTrim = 0;
for (int j = 0; j < len; j++) {
if (allValy[i][j] != null) {
valy[lenyTrim] = allValy[i][j].doubleValue();
lenyTrim++;
}
}
double[] valyTrim = new double[lenyTrim];
System.arraycopy(valy, 0, valyTrim, 0, lenyTrim);
series.setYSeries(valyTrim);
}
((BarChart) chart).suspendUpdate(true);
((BarChart) chart).setCategorySeries(getUniqueNames(valxTrim));
applyCategoryRange(valxTrim.length);
applyRangeY(minY, maxY);
((BarChart) chart).suspendUpdate(false);
chart.redraw();
}
/**
* This updates the visible range of the chart's x-axis.
*/
private void applyCategoryRange(int numItems) {
int itemRange = Math.max(1, (int) Math.ceil(numItems * scale)); // The number of items to display
int lower = (int) Math.round((numItems - itemRange) * scroll);
chart.getAxisSet().getXAxis(0).setRange(new Range(lower, lower + itemRange - 1));
}
@Override
public void updateDataSet() {
buildXSeries();
chartMouseMoveListener.update();
}
}