| /******************************************************************************* |
| * Copyright (c) 2012, 2021 IBM Corporation and others. |
| * |
| * This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 |
| * which is available at https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - Renato Stoffalette Joao <rsjoao@br.ibm.com> |
| *******************************************************************************/ |
| package org.eclipse.linuxtools.internal.dataviewers.piechart; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.linuxtools.dataviewers.piechart.IColorsConstants; |
| import org.eclipse.swt.events.PaintListener; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.RGB; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swtchart.IAxis; |
| import org.eclipse.swtchart.IBarSeries; |
| import org.eclipse.swtchart.ISeries; |
| import org.eclipse.swtchart.ITitle; |
| import org.eclipse.swtchart.extensions.charts.InteractiveChart; |
| |
| public class PieChart extends InteractiveChart { |
| |
| protected List<RGB> colorList = new ArrayList<>(); |
| private Color[] customColors = null; |
| private PieChartPaintListener pieChartPaintListener; |
| |
| public PieChart(Composite parent, int style) { |
| super(parent, style); |
| // Hide all original axes and plot area |
| for (IAxis axis : getAxisSet().getAxes()) { |
| axis.getTitle().setVisible(false); |
| } |
| getPlotArea().getControl().setVisible(false); |
| // Make the title draw after the pie-chart itself so we can modify the title |
| // to center over the pie-chart area |
| ITitle title = getTitle(); |
| // Underlying SWT Chart implementation changes from the title being a Control to just |
| // a PaintListener. In the Control class case, we can move it's location to |
| // center over a PieChart, but in the latter case, we need to alter the title |
| // with blanks in the PieChartPaintListener and have the title paint after it |
| // once the title has been altered. |
| if (title instanceof Control) { |
| addPaintListener(pieChartPaintListener = new PieChartPaintListener(this)); |
| } else { |
| removePaintListener((PaintListener)title); |
| addPaintListener(pieChartPaintListener = new PieChartPaintListener(this)); |
| addPaintListener((PaintListener)title); |
| } |
| IAxis xAxis = getAxisSet().getXAxis(0); |
| xAxis.enableCategory(true); |
| xAxis.setCategorySeries(new String[]{""}); //$NON-NLS-1$ |
| } |
| |
| @Override |
| public void addPaintListener(PaintListener listener) { |
| if (!listener.getClass().getName().startsWith("org.eclipse.swtchart.internal.axis")) { //$NON-NLS-1$ |
| super.addPaintListener(listener); |
| } |
| } |
| |
| /** |
| * Sets the custom colors to use. |
| * @param customColors The custom colors to use. |
| * @since 2.0 |
| */ |
| public void setCustomColors(Color[] customColors) { |
| this.customColors = customColors.clone(); |
| } |
| |
| /** |
| * Add data to this Pie Chart. We'll build one pie chart for each value in the array provided. The val matrix must |
| * have an array of an array of values. Ex. labels = {'a', 'b'} val = {{1,2,3}, {4,5,6}} This will create 3 pie |
| * charts. For the first one, 'a' will be 1 and 'b' will be 4. For the second chart 'a' will be 2 and 'b' will be 5. |
| * For the third 'a' will be 3 and 'b' will be 6. |
| * @param labels The titles of each series. (These are not the same as titles given to pies.) |
| * @param val New values. |
| */ |
| public void addPieChartSeries(String[] labels, double[][] val) { |
| setSeriesNames(val[0].length); |
| for (ISeries s : this.getSeriesSet().getSeries()) { |
| this.getSeriesSet().deleteSeries(s.getId()); |
| } |
| |
| int size = Math.min(labels.length, val.length); |
| for (int i = 0; i < size; i++) { |
| IBarSeries s = (IBarSeries) this.getSeriesSet().createSeries(ISeries.SeriesType.BAR, labels[i]); |
| double[] d = new double[val[i].length]; |
| for (int j = 0; j < val[i].length; j++) { |
| d[j] = val[i][j]; |
| } |
| s.setXSeries(d); |
| if (customColors != null) { |
| s.setBarColor(customColors[i % customColors.length]); |
| } else { |
| s.setBarColor(new Color(this.getDisplay(), sliceColor(i))); |
| } |
| } |
| } |
| |
| /** |
| * Sets this chart's category names such that the number of names |
| * is equal to the number of pies. This method will only make changes |
| * to category series if they are not already properly set. |
| * @param numExpected The number of pies / the expected number of category names. |
| */ |
| private void setSeriesNames(int numExpected) { |
| IAxis xAxis = getAxisSet().getXAxis(0); |
| if (xAxis.getCategorySeries().length != numExpected) { |
| String[] seriesNames = new String[numExpected]; |
| for (int i = 0, n = Math.min(xAxis.getCategorySeries().length, numExpected); i < n; i++) { |
| seriesNames[i] = xAxis.getCategorySeries()[i]; |
| } |
| for (int i = xAxis.getCategorySeries().length; i < numExpected; i++) { |
| seriesNames[i] = ""; //$NON-NLS-1$ |
| } |
| xAxis.setCategorySeries(seriesNames); |
| } |
| } |
| |
| protected RGB sliceColor(int i) { |
| if (colorList.size() > i) { |
| return colorList.get(i); |
| } |
| |
| RGB next = IColorsConstants.COLORS[i % IColorsConstants.COLORS.length]; |
| colorList.add(next); |
| return next; |
| } |
| |
| /** |
| * Given a set of 2D pixel coordinates (typically those of a mouse cursor), return the |
| * index of the given pie's slice that those coordinates reside in. |
| * @param pieIndex The index of the pie to get the slice of. |
| * @param x The x-coordinate to test. |
| * @param y The y-coordinate to test. |
| * @return The slice that contains the point with coordinates (x,y). |
| * @since 2.0 |
| */ |
| public int getSliceIndexFromPosition(int pieIndex, int x, int y) { |
| return pieChartPaintListener.getSliceIndexFromPosition(pieIndex, x, y); |
| } |
| |
| /** |
| * Given a pie and one of its slices, returns the size of the slice as a percentage of the pie. |
| * @param pieIndex The index of the pie to check. |
| * @param sliceIndex The slice of the pie to get the percentage of. |
| * @return The percentage of the entire pie taken up by the slice. |
| * @since 2.0 |
| */ |
| public double getSlicePercent(int pieIndex, int sliceIndex) { |
| double max = 0; |
| ISeries[] series = getSeriesSet().getSeries(); |
| for (int i = 0; i < series.length; i++) { |
| max += series[i].getXSeries()[pieIndex]; |
| } |
| return series[sliceIndex].getXSeries()[pieIndex] / max * 100; |
| } |
| } |