--- /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 org.achartengine.model.CategorySeries;\r
+import org.achartengine.renderer.DefaultRenderer;\r
+import org.achartengine.renderer.DialRenderer;\r
+import org.achartengine.renderer.DialRenderer.Type;\r
+import org.achartengine.util.MathHelper;\r
+\r
+import android.graphics.Canvas;\r
+import android.graphics.Paint;\r
+import android.graphics.Paint.Align;\r
+import android.graphics.Paint.Style;\r
+\r
+/**\r
+ * The dial chart rendering class.\r
+ */\r
+public class DialChart extends RoundChart {\r
+ /** The radius of the needle. */\r
+ private static final int NEEDLE_RADIUS = 10;\r
+ /** The series renderer. */\r
+ private DialRenderer mRenderer;\r
+\r
+ /**\r
+ * Builds a new dial chart instance.\r
+ * \r
+ * @param dataset the series dataset\r
+ * @param renderer the dial renderer\r
+ */\r
+ public DialChart(CategorySeries dataset, DialRenderer renderer) {\r
+ super(dataset, renderer);\r
+ mRenderer = renderer;\r
+ }\r
+\r
+ /**\r
+ * The graphical representation of the dial 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
+\r
+ int sLength = mDataset.getItemCount();\r
+ String[] titles = new String[sLength];\r
+ for (int i = 0; i < sLength; i++) {\r
+ titles[i] = mDataset.getCategory(i);\r
+ }\r
+\r
+ if (mRenderer.isFitLegend()) {\r
+ legendSize = drawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize,\r
+ paint, true);\r
+ }\r
+ int bottom = y + height - legendSize;\r
+ drawBackground(mRenderer, canvas, x, y, width, height, paint, false, DefaultRenderer.NO_COLOR);\r
+\r
+ int mRadius = Math.min(Math.abs(right - left), Math.abs(bottom - top));\r
+ int radius = (int) (mRadius * 0.35 * mRenderer.getScale());\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
+ double min = mRenderer.getMinValue();\r
+ double max = mRenderer.getMaxValue();\r
+ double angleMin = mRenderer.getAngleMin();\r
+ double angleMax = mRenderer.getAngleMax();\r
+ if (!mRenderer.isMinValueSet() || !mRenderer.isMaxValueSet()) {\r
+ int count = mRenderer.getSeriesRendererCount();\r
+ for (int i = 0; i < count; i++) {\r
+ double value = mDataset.getValue(i);\r
+ if (!mRenderer.isMinValueSet()) {\r
+ min = Math.min(min, value);\r
+ }\r
+ if (!mRenderer.isMaxValueSet()) {\r
+ max = Math.max(max, value);\r
+ }\r
+ }\r
+ }\r
+ if (min == max) {\r
+ min = min * 0.5;\r
+ max = max * 1.5;\r
+ }\r
+\r
+ paint.setColor(mRenderer.getLabelsColor());\r
+ double minorTicks = mRenderer.getMinorTicksSpacing();\r
+ double majorTicks = mRenderer.getMajorTicksSpacing();\r
+ if (minorTicks == MathHelper.NULL_VALUE) {\r
+ minorTicks = (max - min) / 30;\r
+ }\r
+ if (majorTicks == MathHelper.NULL_VALUE) {\r
+ majorTicks = (max - min) / 10;\r
+ }\r
+ drawTicks(canvas, min, max, angleMin, angleMax, mCenterX, mCenterY, longRadius, radius,\r
+ minorTicks, paint, false);\r
+ drawTicks(canvas, min, max, angleMin, angleMax, mCenterX, mCenterY, longRadius, shortRadius,\r
+ majorTicks, paint, true);\r
+\r
+ int count = mRenderer.getSeriesRendererCount();\r
+ for (int i = 0; i < count; i++) {\r
+ double angle = getAngleForValue(mDataset.getValue(i), angleMin, angleMax, min, max);\r
+ paint.setColor(mRenderer.getSeriesRendererAt(i).getColor());\r
+ boolean type = mRenderer.getVisualTypeForIndex(i) == Type.ARROW;\r
+ drawNeedle(canvas, angle, mCenterX, mCenterY, shortRadius, type, paint);\r
+ }\r
+ drawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize, paint, false);\r
+ drawTitle(canvas, x, y, width, paint);\r
+ }\r
+\r
+ /**\r
+ * Returns the angle for a specific chart value.\r
+ * \r
+ * @param value the chart value\r
+ * @param minAngle the minimum chart angle value\r
+ * @param maxAngle the maximum chart angle value\r
+ * @param min the minimum chart value\r
+ * @param max the maximum chart value\r
+ * @return the angle\r
+ */\r
+ private double getAngleForValue(double value, double minAngle, double maxAngle, double min,\r
+ double max) {\r
+ double angleDiff = maxAngle - minAngle;\r
+ double diff = max - min;\r
+ return Math.toRadians(minAngle + (value - min) * angleDiff / diff);\r
+ }\r
+\r
+ /**\r
+ * Draws the chart tick lines.\r
+ * \r
+ * @param canvas the canvas\r
+ * @param min the minimum chart value\r
+ * @param max the maximum chart value\r
+ * @param minAngle the minimum chart angle value\r
+ * @param maxAngle the maximum chart angle value\r
+ * @param centerX the center x value\r
+ * @param centerY the center y value\r
+ * @param longRadius the long radius\r
+ * @param shortRadius the short radius\r
+ * @param ticks the tick spacing\r
+ * @param paint the paint settings\r
+ * @param labels paint the labels\r
+ * @return the angle\r
+ */\r
+ private void drawTicks(Canvas canvas, double min, double max, double minAngle, double maxAngle,\r
+ int centerX, int centerY, double longRadius, double shortRadius, double ticks, Paint paint,\r
+ boolean labels) {\r
+ for (double i = min; i <= max; i += ticks) {\r
+ double angle = getAngleForValue(i, minAngle, maxAngle, min, max);\r
+ double sinValue = Math.sin(angle);\r
+ double cosValue = Math.cos(angle);\r
+ int x1 = Math.round(centerX + (float) (shortRadius * sinValue));\r
+ int y1 = Math.round(centerY + (float) (shortRadius * cosValue));\r
+ int x2 = Math.round(centerX + (float) (longRadius * sinValue));\r
+ int y2 = Math.round(centerY + (float) (longRadius * cosValue));\r
+ canvas.drawLine(x1, y1, x2, y2, paint);\r
+ if (labels) {\r
+ paint.setTextAlign(Align.LEFT);\r
+ if (x1 <= x2) {\r
+ paint.setTextAlign(Align.RIGHT);\r
+ }\r
+ String text = i + "";\r
+ if (Math.round(i) == (long) i) {\r
+ text = (long) i + "";\r
+ }\r
+ canvas.drawText(text, x1, y1, paint);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Returns the angle for a specific chart value.\r
+ * \r
+ * @param canvas the canvas\r
+ * @param angle the needle angle value\r
+ * @param centerX the center x value\r
+ * @param centerY the center y value\r
+ * @param radius the radius\r
+ * @param arrow if a needle or an arrow to be painted\r
+ * @param paint the paint settings\r
+ * @return the angle\r
+ */\r
+ private void drawNeedle(Canvas canvas, double angle, int centerX, int centerY, double radius,\r
+ boolean arrow, Paint paint) {\r
+ double diff = Math.toRadians(90);\r
+ int needleSinValue = (int) (NEEDLE_RADIUS * Math.sin(angle - diff));\r
+ int needleCosValue = (int) (NEEDLE_RADIUS * Math.cos(angle - diff));\r
+ int needleX = (int) (radius * Math.sin(angle));\r
+ int needleY = (int) (radius * Math.cos(angle));\r
+ int needleCenterX = centerX + needleX;\r
+ int needleCenterY = centerY + needleY;\r
+ float[] points;\r
+ if (arrow) {\r
+ int arrowBaseX = centerX + (int) (radius * 0.85 * Math.sin(angle));\r
+ int arrowBaseY = centerY + (int) (radius * 0.85 * Math.cos(angle));\r
+ points = new float[] { arrowBaseX - needleSinValue, arrowBaseY - needleCosValue,\r
+ needleCenterX, needleCenterY, arrowBaseX + needleSinValue, arrowBaseY + needleCosValue };\r
+ float width = paint.getStrokeWidth();\r
+ paint.setStrokeWidth(5);\r
+ canvas.drawLine(centerX, centerY, needleCenterX, needleCenterY, paint);\r
+ paint.setStrokeWidth(width);\r
+ } else {\r
+ points = new float[] { centerX - needleSinValue, centerY - needleCosValue, needleCenterX,\r
+ needleCenterY, centerX + needleSinValue, centerY + needleCosValue };\r
+ }\r
+ drawPath(canvas, points, paint, true);\r
+ }\r
+\r
+}\r