diff options
author | Alexander Kurtakov | 2020-02-13 08:39:52 +0000 |
---|---|---|
committer | Alexander Kurtakov | 2020-02-13 09:13:45 +0000 |
commit | 438cbdd2e3908d8799457165198a19dcc0bcc1f5 (patch) | |
tree | ad07620f3001f73e2b1fc5e2926bc229d355e1db /profiling | |
parent | 65e7395bc5e100dc5529eee38ee700351cfd63e8 (diff) | |
download | org.eclipse.linuxtools-438cbdd2e3908d8799457165198a19dcc0bcc1f5.tar.gz org.eclipse.linuxtools-438cbdd2e3908d8799457165198a19dcc0bcc1f5.tar.xz org.eclipse.linuxtools-438cbdd2e3908d8799457165198a19dcc0bcc1f5.zip |
Bug 560077 - Deprecate and remove dataviewers.chart and
dataviewers.piechart bundles
Bring back the old org.swtchart api.
Introduce the new eclipse swtchart as internal package so we can
progress on it till removal.
Change-Id: Ibe1adf8b0a35f0f78e208eff452f65b5afb1bc5b
Signed-off-by: Alexander Kurtakov <akurtako@redhat.com>
Reviewed-on: https://git.eclipse.org/r/157622
Tested-by: Linux Tools Bot <linuxtools-bot@eclipse.org>
Diffstat (limited to 'profiling')
11 files changed, 458 insertions, 24 deletions
diff --git a/profiling/org.eclipse.linuxtools.dataviewers.charts/META-INF/MANIFEST.MF b/profiling/org.eclipse.linuxtools.dataviewers.charts/META-INF/MANIFEST.MF index 17e08eba0c..d756273843 100755 --- a/profiling/org.eclipse.linuxtools.dataviewers.charts/META-INF/MANIFEST.MF +++ b/profiling/org.eclipse.linuxtools.dataviewers.charts/META-INF/MANIFEST.MF @@ -13,6 +13,6 @@ Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.linuxtools.dataviewers.charts.actions, org.eclipse.linuxtools.dataviewers.charts.provider Import-Package: org.eclipse.linuxtools.dataviewers.piechart, - org.eclipse.swtchart + org.swtchart Bundle-Localization: plugin Automatic-Module-Name: org.eclipse.linuxtools.dataviewers.charts diff --git a/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/dataviewers/charts/actions/ChartAction.java b/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/dataviewers/charts/actions/ChartAction.java index 4d1f672c1c..0bc979ef80 100755 --- a/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/dataviewers/charts/actions/ChartAction.java +++ b/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/dataviewers/charts/actions/ChartAction.java @@ -19,7 +19,7 @@ import org.eclipse.linuxtools.internal.dataviewers.charts.Messages; import org.eclipse.linuxtools.internal.dataviewers.charts.dialogs.ChartDialog; import org.eclipse.linuxtools.internal.dataviewers.charts.view.ChartView; import org.eclipse.swt.widgets.Shell; -import org.eclipse.swtchart.Chart; +import org.swtchart.Chart; /** * An action that open a chart dialog from an <code>AbstractSTViewer</code>. diff --git a/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/dataviewers/charts/actions/SaveChartAction.java b/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/dataviewers/charts/actions/SaveChartAction.java index 89d69a66e3..3e9d85001f 100755 --- a/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/dataviewers/charts/actions/SaveChartAction.java +++ b/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/dataviewers/charts/actions/SaveChartAction.java @@ -36,7 +36,7 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; -import org.eclipse.swtchart.Chart; +import org.swtchart.Chart; /** * An action to save any {@link Composite} (typically a {@link Chart}) as an image (jpeg/jpg, bmp, png). diff --git a/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/dataviewers/charts/provider/ChartFactory.java b/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/dataviewers/charts/provider/ChartFactory.java index 377d8b9ad3..e304cbf38d 100755 --- a/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/dataviewers/charts/provider/ChartFactory.java +++ b/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/dataviewers/charts/provider/ChartFactory.java @@ -24,12 +24,12 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; -import org.eclipse.swtchart.Chart; -import org.eclipse.swtchart.IAxis; -import org.eclipse.swtchart.IBarSeries; -import org.eclipse.swtchart.ISeries.SeriesType; -import org.eclipse.swtchart.ITitle; -import org.eclipse.swtchart.LineStyle; +import org.swtchart.Chart; +import org.swtchart.IAxis; +import org.swtchart.IBarSeries; +import org.swtchart.ISeries.SeriesType; +import org.swtchart.ITitle; +import org.swtchart.LineStyle; /** * A utility class that handles the charts creation (pie chart and bar chart) diff --git a/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/internal/dataviewers/charts/dialogs/ChartDialog.java b/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/internal/dataviewers/charts/dialogs/ChartDialog.java index b3dd31d93e..b344d3a97a 100755 --- a/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/internal/dataviewers/charts/dialogs/ChartDialog.java +++ b/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/internal/dataviewers/charts/dialogs/ChartDialog.java @@ -41,7 +41,7 @@ import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; -import org.eclipse.swtchart.Chart; +import org.swtchart.Chart; /** * The dialog used to customize the chart before creating it. diff --git a/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/internal/dataviewers/charts/view/ChartView.java b/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/internal/dataviewers/charts/view/ChartView.java index 9bee28b104..6389c3fd81 100755 --- a/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/internal/dataviewers/charts/view/ChartView.java +++ b/profiling/org.eclipse.linuxtools.dataviewers.charts/src/org/eclipse/linuxtools/internal/dataviewers/charts/view/ChartView.java @@ -24,7 +24,7 @@ import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.ViewPart; -import org.eclipse.swtchart.Chart; +import org.swtchart.Chart; /** * The chart view. diff --git a/profiling/org.eclipse.linuxtools.dataviewers.piechart/META-INF/MANIFEST.MF b/profiling/org.eclipse.linuxtools.dataviewers.piechart/META-INF/MANIFEST.MF index 890b92c74e..aa30e25073 100644 --- a/profiling/org.eclipse.linuxtools.dataviewers.piechart/META-INF/MANIFEST.MF +++ b/profiling/org.eclipse.linuxtools.dataviewers.piechart/META-INF/MANIFEST.MF @@ -6,8 +6,9 @@ Bundle-Version: 2.0.1.qualifier Bundle-Vendor: %bundleProvider Bundle-Localization: plugin Require-Bundle: org.eclipse.ui, + org.swtchart, org.eclipse.swtchart Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy -Export-Package: org.eclipse.linuxtools.dataviewers.piechart +Export-Package: org.eclipse.linuxtools.dataviewers.piechart, org.eclipse.linuxtools.internal.dataviewers.piechart;x-internal:=true Automatic-Module-Name: org.eclipse.linuxtools.dataviewers.piechart diff --git a/profiling/org.eclipse.linuxtools.dataviewers.piechart/src/org/eclipse/linuxtools/dataviewers/piechart/PieChart.java b/profiling/org.eclipse.linuxtools.dataviewers.piechart/src/org/eclipse/linuxtools/dataviewers/piechart/PieChart.java index df96a1ff6b..4ae832febb 100644 --- a/profiling/org.eclipse.linuxtools.dataviewers.piechart/src/org/eclipse/linuxtools/dataviewers/piechart/PieChart.java +++ b/profiling/org.eclipse.linuxtools.dataviewers.piechart/src/org/eclipse/linuxtools/dataviewers/piechart/PieChart.java @@ -20,11 +20,11 @@ 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.Chart; -import org.eclipse.swtchart.IAxis; -import org.eclipse.swtchart.IBarSeries; -import org.eclipse.swtchart.ISeries; -import org.eclipse.swtchart.ITitle; +import org.swtchart.Chart; +import org.swtchart.IAxis; +import org.swtchart.IBarSeries; +import org.swtchart.ISeries; +import org.swtchart.ITitle; public class PieChart extends Chart { @@ -38,7 +38,7 @@ public class PieChart extends Chart { for (IAxis axis : getAxisSet().getAxes()) { axis.getTitle().setVisible(false); } - getPlotArea().getControl().setVisible(false); + getPlotArea().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(); @@ -61,7 +61,7 @@ public class PieChart extends Chart { @Override public void addPaintListener(PaintListener listener) { - if (!listener.getClass().getName().startsWith("org.eclipse.swtchart.internal.axis")) { //$NON-NLS-1$ + if (!listener.getClass().getName().startsWith("org.swtchart.internal.axis")) { //$NON-NLS-1$ super.addPaintListener(listener); } } diff --git a/profiling/org.eclipse.linuxtools.dataviewers.piechart/src/org/eclipse/linuxtools/dataviewers/piechart/PieChartPaintListener.java b/profiling/org.eclipse.linuxtools.dataviewers.piechart/src/org/eclipse/linuxtools/dataviewers/piechart/PieChartPaintListener.java index 46e61a7019..b47f787eb3 100644 --- a/profiling/org.eclipse.linuxtools.dataviewers.piechart/src/org/eclipse/linuxtools/dataviewers/piechart/PieChartPaintListener.java +++ b/profiling/org.eclipse.linuxtools.dataviewers.piechart/src/org/eclipse/linuxtools/dataviewers/piechart/PieChartPaintListener.java @@ -22,10 +22,10 @@ import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; -import org.eclipse.swtchart.IBarSeries; -import org.eclipse.swtchart.ISeries; -import org.eclipse.swtchart.ITitle; -import org.eclipse.swtchart.Range; +import org.swtchart.IBarSeries; +import org.swtchart.ISeries; +import org.swtchart.ITitle; +import org.swtchart.Range; public class PieChartPaintListener implements PaintListener { @@ -53,7 +53,7 @@ public class PieChartPaintListener implements PaintListener { */ public PieChartPaintListener(PieChart chart) { this.chart = chart; - this.plotArea = chart.getPlotArea().getControl(); + this.plotArea = chart.getPlotArea(); } @Override diff --git a/profiling/org.eclipse.linuxtools.dataviewers.piechart/src/org/eclipse/linuxtools/internal/dataviewers/piechart/PieChart.java b/profiling/org.eclipse.linuxtools.dataviewers.piechart/src/org/eclipse/linuxtools/internal/dataviewers/piechart/PieChart.java new file mode 100644 index 0000000000..abc0e46fe5 --- /dev/null +++ b/profiling/org.eclipse.linuxtools.dataviewers.piechart/src/org/eclipse/linuxtools/internal/dataviewers/piechart/PieChart.java @@ -0,0 +1,167 @@ +/******************************************************************************* + * Copyright (c) 2012, 2018 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.Chart; +import org.eclipse.swtchart.IAxis; +import org.eclipse.swtchart.IBarSeries; +import org.eclipse.swtchart.ISeries; +import org.eclipse.swtchart.ITitle; + +public class PieChart extends Chart { + + 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; + } +} diff --git a/profiling/org.eclipse.linuxtools.dataviewers.piechart/src/org/eclipse/linuxtools/internal/dataviewers/piechart/PieChartPaintListener.java b/profiling/org.eclipse.linuxtools.dataviewers.piechart/src/org/eclipse/linuxtools/internal/dataviewers/piechart/PieChartPaintListener.java new file mode 100644 index 0000000000..09e4ae6376 --- /dev/null +++ b/profiling/org.eclipse.linuxtools.dataviewers.piechart/src/org/eclipse/linuxtools/internal/dataviewers/piechart/PieChartPaintListener.java @@ -0,0 +1,266 @@ +/******************************************************************************* + * Copyright (c) 2012, 2018 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 org.eclipse.swt.SWT; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swtchart.IBarSeries; +import org.eclipse.swtchart.ISeries; +import org.eclipse.swtchart.ITitle; +import org.eclipse.swtchart.Range; + +public class PieChartPaintListener implements PaintListener { + + private PieChart chart; + private Control plotArea; + private double[][] seriesValues; + private String[] seriesNames; + private static final int X_GAP = 10; + + private static final Color WHITE = Display.getDefault().getSystemColor(SWT.COLOR_WHITE); + private static final Color BLACK = Display.getDefault().getSystemColor(SWT.COLOR_BLACK); + private static final String FONT = "Arial"; //$NON-NLS-1$ + + private Point[] pieCenters; + private int[][] pieSliceAngles; + private int pieWidth; + + private String origTitleText; + + /** + * Handles drawing and updating of a PieChart, with titles given to its legend and + * to each of its pies. Pies will be drawn in the given chart's plot area. + * @param chart The PieChart to draw and update. + * @since 2.0 + */ + public PieChartPaintListener(PieChart chart) { + this.chart = chart; + this.plotArea = chart.getPlotArea().getControl(); + } + + @Override + public void paintControl(PaintEvent e) { + GC gc = e.gc; + Rectangle bounds; + this.getPieSeriesArray(); + pieCenters = new Point[seriesValues.length]; + pieSliceAngles = new int[seriesValues.length][]; + if (seriesValues.length == 0) { + bounds = gc.getClipping(); + Font oldFont = gc.getFont(); + Font font = new Font(Display.getDefault(), FONT, 15, SWT.BOLD); + gc.setForeground(BLACK); + gc.setFont(font); + String text = "No data"; //$NON-NLS-1$ + Point textSize = e.gc.textExtent(text); + gc.drawText(text, (bounds.width - textSize.x) / 2, (bounds.height - textSize.y) / 2); + gc.setFont(oldFont); + font.dispose(); + return; + } + bounds = plotArea.getBounds(); + // Adjust the title so it centers in the plot area + if (origTitleText == null) { + origTitleText = chart.getTitle().getText(); + } + + // We want to center the title in the plot area rather than the entire view which includes + // the legend. To force this, we have two algorithms depending on what level of the + // underlying SWT Chart software we are using. If the title is an SWT Control, we simply + // set the title's location manually. If the title is just a PaintListener, we center it + // by adding a number of trailing spaces which we calculate. + if (chart.getTitle() instanceof Control) { + setTitleBounds(bounds); + } else { + adjustTitle(e); + } + int width = bounds.width / seriesValues.length; + int x = bounds.x; + + if (chart.getLegend().isVisible()) { + Rectangle legendBounds = ((Control) chart.getLegend()).getBounds(); + Font oldFont = gc.getFont(); + Font font = new Font(Display.getDefault(), FONT, 10, SWT.BOLD); + gc.setForeground(BLACK); + gc.setFont(font); + String text = chart.getAxisSet().getXAxis(0).getTitle().getText(); + Point textSize = e.gc.textExtent(text); + gc.drawText(text, legendBounds.x + (legendBounds.width - textSize.x) / 2, legendBounds.y - textSize.y); + gc.setFont(oldFont); + font.dispose(); + } + + pieWidth = Math.min(width - X_GAP, bounds.height); + for (int i = 0; i < seriesValues.length; i++) { + drawPieChart(e, i, new Rectangle(x, bounds.y, width, bounds.height)); + x += width; + } + } + + // For a title which is a Control, position it appropriately to center in the plot area. + private void setTitleBounds(Rectangle bounds) { + Control title = (Control) chart.getTitle(); + Rectangle titleBounds = title.getBounds(); + title.setLocation(new Point(bounds.x + (bounds.width - titleBounds.width) / 2, title.getLocation().y)); + } + + // Adjust the title with trailing blanks so it centers in the plot area + // rather than for the entire chart view which looks odd when not + // centered above the pie-charts themselves. + private void adjustTitle(PaintEvent pe) { + ITitle title = chart.getTitle(); + Font font = title.getFont(); + Font oldFont = pe.gc.getFont(); + pe.gc.setFont(font); + Control legend = (Control)chart.getLegend(); + Rectangle legendBounds = legend.getBounds(); + int adjustment = legendBounds.width - 15; + Point blankSize = pe.gc.textExtent(" "); //$NON-NLS-1$ + int numBlanks = ((adjustment / blankSize.x) >> 1) << 1; + String text = origTitleText; + for (int i = 0; i < numBlanks; ++i) + text += " "; //$NON-NLS-1$ + pe.gc.setFont(oldFont); + title.setText(text); + } + + private void drawPieChart(PaintEvent e, int chartnum, Rectangle bounds) { + double series[] = seriesValues[chartnum]; + int nelemSeries = series.length; + double sumTotal = 0; + + pieSliceAngles[chartnum] = new int[nelemSeries - 1]; // Don't need first angle; it's always 0 + for (int i = 0; i < nelemSeries; i++) { + sumTotal += series[i]; + } + + GC gc = e.gc; + Font oldFont = gc.getFont(); + gc.setLineWidth(1); + + int pieX = bounds.x + (bounds.width - pieWidth) / 2; + int pieY = bounds.y + (bounds.height - pieWidth) / 2; + pieCenters[chartnum] = new Point(pieX + pieWidth / 2, pieY + pieWidth / 2); + if (sumTotal == 0) { + gc.drawOval(pieX, pieY, pieWidth, pieWidth); + } else { + double factor = 100 / sumTotal; + int sweepAngle = 0; + int incrementAngle = 0; + int initialAngle = 90; + for (int i = 0; i < nelemSeries; i++) { + // Stored angles increase in clockwise direction from 0 degrees at 12:00 + if (i > 0) { + pieSliceAngles[chartnum][i - 1] = 90 - initialAngle; + } + + gc.setBackground(((IBarSeries) chart.getSeriesSet().getSeries()[i]).getBarColor()); + + if (i == (nelemSeries - 1)) { + sweepAngle = 360 - incrementAngle; + } else { + double angle = series[i] * factor * 3.6; + sweepAngle = (int) Math.round(angle); + } + gc.fillArc(pieX, pieY, pieWidth, pieWidth, initialAngle, (-sweepAngle)); + gc.drawArc(pieX, pieY, pieWidth, pieWidth, initialAngle, (-sweepAngle)); + incrementAngle += sweepAngle; + initialAngle += (-sweepAngle); + } + gc.drawLine(pieCenters[chartnum].x, pieCenters[chartnum].y, pieCenters[chartnum].x, pieCenters[chartnum].y - pieWidth / 2); + } + + Font font = new Font(Display.getDefault(), FONT, 12, SWT.BOLD); + gc.setForeground(BLACK); + gc.setBackground(WHITE); + gc.setFont(font); + String text = seriesNames[chartnum]; + Point textSize = e.gc.textExtent(text); + gc.drawText(text, pieX + (pieWidth - textSize.x) / 2, pieY + pieWidth + textSize.y); + gc.setFont(oldFont); + font.dispose(); + } + + private void getPieSeriesArray() { + ISeries series[] = this.chart.getSeriesSet().getSeries(); + if (series == null || series.length == 0) { + seriesValues = new double[0][0]; + seriesNames = new String[0]; + return; + } + String names[] = this.chart.getAxisSet().getXAxis(0).getCategorySeries(); + Range range = chart.getAxisSet().getXAxis(0).getRange(); + int itemRange = (int) range.upper - (int) range.lower + 1; + int itemOffset = (int) range.lower; + seriesValues = new double[itemRange][series.length]; + seriesNames = new String[itemRange]; + + for (int i = 0; i < seriesValues.length; i++) { + seriesNames[i] = names[i + itemOffset]; + for (int j = 0; j < seriesValues[i].length; j++) { + double d[] = series[j].getXSeries(); + if (d != null && d.length > 0) { + seriesValues[i][j] = d[i + itemOffset]; + } else { + seriesValues[i][j] = 0; + } + } + } + + return; + } + + /** + * 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 chartnum The id of the chart. + * @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 chartnum, int x, int y) { + Range range = chart.getAxisSet().getXAxis(0).getRange(); + chartnum -= (int) range.lower; + if (chartnum >= pieCenters.length || chartnum < 0) { + return -1; + } + // Only continue if the point is inside the pie circle + double rad = Math.sqrt(Math.pow(pieCenters[chartnum].x - x, 2) + Math.pow(pieCenters[chartnum].y - y, 2)); + if (2 * rad > pieWidth) { + return -1; + } + // Angle is relative to 12:00 position, increases clockwise + double angle = Math.acos((pieCenters[chartnum].y - y) / rad) / Math.PI * 180.0; + if (x - pieCenters[chartnum].x < 0) { + angle = 360 - angle; + } + if (pieSliceAngles[chartnum].length == 0 || angle < pieSliceAngles[chartnum][0]) { + return 0; + } + for (int s = 0; s < pieSliceAngles[chartnum].length - 1; s++) { + if (pieSliceAngles[chartnum][s] <= angle && angle < pieSliceAngles[chartnum][s+1]) { + return s + 1; + } + } + return pieSliceAngles[chartnum].length; + } +} |