--- /dev/null
+/**\r
+ * Copyright (C) 2009 - 2012 SC 4ViewSoft SRL\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.achartengine.chart;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.achartengine.model.MultipleCategorySeries;\r
+import org.achartengine.renderer.DefaultRenderer;\r
+import org.achartengine.renderer.SimpleSeriesRenderer;\r
+\r
+import android.graphics.Canvas;\r
+import android.graphics.Color;\r
+import android.graphics.Paint;\r
+import android.graphics.Paint.Style;\r
+import android.graphics.RectF;\r
+\r
+/**\r
+ * The doughnut chart rendering class.\r
+ */\r
+public class DoughnutChart extends RoundChart {\r
+ /** The series dataset. */\r
+ private MultipleCategorySeries mDataset;\r
+ /** A step variable to control the size of the legend shape. */\r
+ private int mStep;\r
+\r
+ /**\r
+ * Builds a new doughnut chart instance.\r
+ * \r
+ * @param dataset the series dataset\r
+ * @param renderer the series renderer\r
+ */\r
+ public DoughnutChart(MultipleCategorySeries dataset, DefaultRenderer renderer) {\r
+ super(null, renderer);\r
+ mDataset = dataset;\r
+ }\r
+\r
+ /**\r
+ * The graphical representation of the doughnut chart.\r
+ * \r
+ * @param canvas the canvas to paint to\r
+ * @param x the top left x value of the view to draw to\r
+ * @param y the top left y value of the view to draw to\r
+ * @param width the width of the view to draw to\r
+ * @param height the height of the view to draw to\r
+ * @param paint the paint\r
+ */\r
+ @Override\r
+ public void draw(Canvas canvas, int x, int y, int width, int height, Paint paint) {\r
+ paint.setAntiAlias(mRenderer.isAntialiasing());\r
+ paint.setStyle(Style.FILL);\r
+ paint.setTextSize(mRenderer.getLabelsTextSize());\r
+ int legendSize = getLegendSize(mRenderer, height / 5, 0);\r
+ int left = x;\r
+ int top = y;\r
+ int right = x + width;\r
+ int cLength = mDataset.getCategoriesCount();\r
+ String[] categories = new String[cLength];\r
+ for (int category = 0; category < cLength; category++) {\r
+ categories[category] = mDataset.getCategory(category);\r
+ }\r
+ if (mRenderer.isFitLegend()) {\r
+ legendSize = drawLegend(canvas, mRenderer, categories, left, right, y, width, height,\r
+ legendSize, paint, true);\r
+ }\r
+\r
+ int bottom = y + height - legendSize;\r
+ drawBackground(mRenderer, canvas, x, y, width, height, paint, false, DefaultRenderer.NO_COLOR);\r
+ mStep = SHAPE_WIDTH * 3 / 4;\r
+\r
+ int mRadius = Math.min(Math.abs(right - left), Math.abs(bottom - top));\r
+ double rCoef = 0.35 * mRenderer.getScale();\r
+ double decCoef = 0.2 / cLength;\r
+ int radius = (int) (mRadius * rCoef);\r
+ if (mCenterX == NO_VALUE) {\r
+ mCenterX = (left + right) / 2;\r
+ }\r
+ if (mCenterY == NO_VALUE) {\r
+ mCenterY = (bottom + top) / 2;\r
+ }\r
+ float shortRadius = radius * 0.9f;\r
+ float longRadius = radius * 1.1f;\r
+ List<RectF> prevLabelsBounds = new ArrayList<RectF>();\r
+ for (int category = 0; category < cLength; category++) {\r
+ int sLength = mDataset.getItemCount(category);\r
+ double total = 0;\r
+ String[] titles = new String[sLength];\r
+ for (int i = 0; i < sLength; i++) {\r
+ total += mDataset.getValues(category)[i];\r
+ titles[i] = mDataset.getTitles(category)[i];\r
+ }\r
+ float currentAngle = mRenderer.getStartAngle();\r
+ RectF oval = new RectF(mCenterX - radius, mCenterY - radius, mCenterX + radius, mCenterY\r
+ + radius);\r
+ for (int i = 0; i < sLength; i++) {\r
+ paint.setColor(mRenderer.getSeriesRendererAt(i).getColor());\r
+ float value = (float) mDataset.getValues(category)[i];\r
+ float angle = (float) (value / total * 360);\r
+ canvas.drawArc(oval, currentAngle, angle, true, paint);\r
+ drawLabel(canvas, mDataset.getTitles(category)[i], mRenderer, prevLabelsBounds, mCenterX,\r
+ mCenterY, shortRadius, longRadius, currentAngle, angle, left, right,\r
+ mRenderer.getLabelsColor(), paint, true);\r
+ currentAngle += angle;\r
+ }\r
+ radius -= (int) mRadius * decCoef;\r
+ shortRadius -= mRadius * decCoef - 2;\r
+ if (mRenderer.getBackgroundColor() != 0) {\r
+ paint.setColor(mRenderer.getBackgroundColor());\r
+ } else {\r
+ paint.setColor(Color.WHITE);\r
+ }\r
+ paint.setStyle(Style.FILL);\r
+ oval = new RectF(mCenterX - radius, mCenterY - radius, mCenterX + radius, mCenterY + radius);\r
+ canvas.drawArc(oval, 0, 360, true, paint);\r
+ radius -= 1;\r
+ }\r
+ prevLabelsBounds.clear();\r
+ drawLegend(canvas, mRenderer, categories, left, right, y, width, height, legendSize, paint,\r
+ false);\r
+ drawTitle(canvas, x, y, width, paint);\r
+ }\r
+\r
+ /**\r
+ * Returns the legend shape width.\r
+ * \r
+ * @param seriesIndex the series index\r
+ * @return the legend shape width\r
+ */\r
+ public int getLegendShapeWidth(int seriesIndex) {\r
+ return SHAPE_WIDTH;\r
+ }\r
+\r
+ /**\r
+ * The graphical representation of the legend shape.\r
+ * \r
+ * @param canvas the canvas to paint to\r
+ * @param renderer the series renderer\r
+ * @param x the x value of the point the shape should be drawn at\r
+ * @param y the y value of the point the shape should be drawn at\r
+ * @param seriesIndex the series index\r
+ * @param paint the paint to be used for drawing\r
+ */\r
+ public void drawLegendShape(Canvas canvas, SimpleSeriesRenderer renderer, float x, float y,\r
+ int seriesIndex, Paint paint) {\r
+ mStep--;\r
+ canvas.drawCircle(x + SHAPE_WIDTH - mStep, y, mStep, paint);\r
+ }\r
+\r
+}\r