2 * Copyright (C) 2009 - 2012 SC 4ViewSoft SRL
\r
4 * Licensed under the Apache License, Version 2.0 (the "License");
\r
5 * you may not use this file except in compliance with the License.
\r
6 * You may obtain a copy of the License at
\r
8 * http://www.apache.org/licenses/LICENSE-2.0
\r
10 * Unless required by applicable law or agreed to in writing, software
\r
11 * distributed under the License is distributed on an "AS IS" BASIS,
\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 * See the License for the specific language governing permissions and
\r
14 * limitations under the License.
\r
16 package org.achartengine.chart;
\r
18 import java.util.ArrayList;
\r
19 import java.util.List;
\r
21 import org.achartengine.model.MultipleCategorySeries;
\r
22 import org.achartengine.renderer.DefaultRenderer;
\r
23 import org.achartengine.renderer.SimpleSeriesRenderer;
\r
25 import android.graphics.Canvas;
\r
26 import android.graphics.Color;
\r
27 import android.graphics.Paint;
\r
28 import android.graphics.Paint.Style;
\r
29 import android.graphics.RectF;
\r
32 * The doughnut chart rendering class.
\r
34 public class DoughnutChart extends RoundChart {
\r
35 /** The series dataset. */
\r
36 private MultipleCategorySeries mDataset;
\r
37 /** A step variable to control the size of the legend shape. */
\r
41 * Builds a new doughnut chart instance.
\r
43 * @param dataset the series dataset
\r
44 * @param renderer the series renderer
\r
46 public DoughnutChart(MultipleCategorySeries dataset, DefaultRenderer renderer) {
\r
47 super(null, renderer);
\r
52 * The graphical representation of the doughnut chart.
\r
54 * @param canvas the canvas to paint to
\r
55 * @param x the top left x value of the view to draw to
\r
56 * @param y the top left y value of the view to draw to
\r
57 * @param width the width of the view to draw to
\r
58 * @param height the height of the view to draw to
\r
59 * @param paint the paint
\r
62 public void draw(Canvas canvas, int x, int y, int width, int height, Paint paint) {
\r
63 paint.setAntiAlias(mRenderer.isAntialiasing());
\r
64 paint.setStyle(Style.FILL);
\r
65 paint.setTextSize(mRenderer.getLabelsTextSize());
\r
66 int legendSize = getLegendSize(mRenderer, height / 5, 0);
\r
69 int right = x + width;
\r
70 int cLength = mDataset.getCategoriesCount();
\r
71 String[] categories = new String[cLength];
\r
72 for (int category = 0; category < cLength; category++) {
\r
73 categories[category] = mDataset.getCategory(category);
\r
75 if (mRenderer.isFitLegend()) {
\r
76 legendSize = drawLegend(canvas, mRenderer, categories, left, right, y, width, height,
\r
77 legendSize, paint, true);
\r
80 int bottom = y + height - legendSize;
\r
81 drawBackground(mRenderer, canvas, x, y, width, height, paint, false, DefaultRenderer.NO_COLOR);
\r
82 mStep = SHAPE_WIDTH * 3 / 4;
\r
84 int mRadius = Math.min(Math.abs(right - left), Math.abs(bottom - top));
\r
85 double rCoef = 0.35 * mRenderer.getScale();
\r
86 double decCoef = 0.2 / cLength;
\r
87 int radius = (int) (mRadius * rCoef);
\r
88 if (mCenterX == NO_VALUE) {
\r
89 mCenterX = (left + right) / 2;
\r
91 if (mCenterY == NO_VALUE) {
\r
92 mCenterY = (bottom + top) / 2;
\r
94 float shortRadius = radius * 0.9f;
\r
95 float longRadius = radius * 1.1f;
\r
96 List<RectF> prevLabelsBounds = new ArrayList<RectF>();
\r
97 for (int category = 0; category < cLength; category++) {
\r
98 int sLength = mDataset.getItemCount(category);
\r
100 String[] titles = new String[sLength];
\r
101 for (int i = 0; i < sLength; i++) {
\r
102 total += mDataset.getValues(category)[i];
\r
103 titles[i] = mDataset.getTitles(category)[i];
\r
105 float currentAngle = mRenderer.getStartAngle();
\r
106 RectF oval = new RectF(mCenterX - radius, mCenterY - radius, mCenterX + radius, mCenterY
\r
108 for (int i = 0; i < sLength; i++) {
\r
109 paint.setColor(mRenderer.getSeriesRendererAt(i).getColor());
\r
110 float value = (float) mDataset.getValues(category)[i];
\r
111 float angle = (float) (value / total * 360);
\r
112 canvas.drawArc(oval, currentAngle, angle, true, paint);
\r
113 drawLabel(canvas, mDataset.getTitles(category)[i], mRenderer, prevLabelsBounds, mCenterX,
\r
114 mCenterY, shortRadius, longRadius, currentAngle, angle, left, right,
\r
115 mRenderer.getLabelsColor(), paint, true);
\r
116 currentAngle += angle;
\r
118 radius -= (int) mRadius * decCoef;
\r
119 shortRadius -= mRadius * decCoef - 2;
\r
120 if (mRenderer.getBackgroundColor() != 0) {
\r
121 paint.setColor(mRenderer.getBackgroundColor());
\r
123 paint.setColor(Color.WHITE);
\r
125 paint.setStyle(Style.FILL);
\r
126 oval = new RectF(mCenterX - radius, mCenterY - radius, mCenterX + radius, mCenterY + radius);
\r
127 canvas.drawArc(oval, 0, 360, true, paint);
\r
130 prevLabelsBounds.clear();
\r
131 drawLegend(canvas, mRenderer, categories, left, right, y, width, height, legendSize, paint,
\r
133 drawTitle(canvas, x, y, width, paint);
\r
137 * Returns the legend shape width.
\r
139 * @param seriesIndex the series index
\r
140 * @return the legend shape width
\r
142 public int getLegendShapeWidth(int seriesIndex) {
\r
143 return SHAPE_WIDTH;
\r
147 * The graphical representation of the legend shape.
\r
149 * @param canvas the canvas to paint to
\r
150 * @param renderer the series renderer
\r
151 * @param x the x value of the point the shape should be drawn at
\r
152 * @param y the y value of the point the shape should be drawn at
\r
153 * @param seriesIndex the series index
\r
154 * @param paint the paint to be used for drawing
\r
156 public void drawLegendShape(Canvas canvas, SimpleSeriesRenderer renderer, float x, float y,
\r
157 int seriesIndex, Paint paint) {
\r
159 canvas.drawCircle(x + SHAPE_WIDTH - mStep, y, mStep, paint);
\r