com.codename1.charts.views.DialChart Maven / Gradle / Ivy
/**
* Copyright (C) 2009 - 2013 SC 4ViewSoft SRL
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.codename1.charts.views;
import com.codename1.charts.compat.Canvas;
import com.codename1.charts.compat.Paint;
import com.codename1.charts.compat.Paint.Style;
import com.codename1.charts.models.CategorySeries;
import com.codename1.charts.renderers.DefaultRenderer;
import com.codename1.charts.renderers.DialRenderer;
import com.codename1.charts.renderers.DialRenderer.Type;
import com.codename1.ui.Component;
import com.codename1.charts.util.MathHelper;
/**
* The dial chart rendering class.
*/
public class DialChart extends RoundChart {
/** The radius of the needle. */
private static final int NEEDLE_RADIUS = 10;
/** The series renderer. */
private DialRenderer mRenderer;
/**
* Builds a new dial chart instance.
*
* @param dataset the series dataset
* @param renderer the dial renderer
*/
public DialChart(CategorySeries dataset, DialRenderer renderer) {
super(dataset, renderer);
mRenderer = renderer;
}
/**
* The graphical representation of the dial chart.
*
* @param canvas the canvas to paint to
* @param x the top left x value of the view to draw to
* @param y the top left y value of the view to draw to
* @param width the width of the view to draw to
* @param height the height of the view to draw to
* @param paint the paint
*/
@Override
public void draw(Canvas canvas, int x, int y, int width, int height, Paint paint) {
paint.setAntiAlias(mRenderer.isAntialiasing());
paint.setStyle(Style.FILL);
paint.setTextSize(mRenderer.getLabelsTextSize());
int legendSize = getLegendSize(mRenderer, height / 5, 0);
int left = x;
int top = y;
int right = x + width;
int sLength = mDataset.getItemCount();
String[] titles = new String[sLength];
for (int i = 0; i < sLength; i++) {
titles[i] = mDataset.getCategory(i);
}
if (mRenderer.isFitLegend()) {
legendSize = drawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize,
paint, true);
}
int bottom = y + height - legendSize;
drawBackground(mRenderer, canvas, x, y, width, height, paint, false, DefaultRenderer.NO_COLOR);
int mRadius = Math.min(Math.abs(right - left), Math.abs(bottom - top));
int radius = (int) (mRadius * 0.35 * mRenderer.getScale());
if (autoCalculateCenter || mCenterX == NO_VALUE) {
mCenterX = (left + right) / 2;
}
if (autoCalculateCenter || mCenterY == NO_VALUE) {
mCenterY = (bottom + top) / 2;
}
float shortRadius = radius * 0.9f;
float longRadius = radius * 1.1f;
double min = mRenderer.getMinValue();
double max = mRenderer.getMaxValue();
double angleMin = mRenderer.getAngleMin();
double angleMax = mRenderer.getAngleMax();
if (!mRenderer.isMinValueSet() || !mRenderer.isMaxValueSet()) {
int count = mRenderer.getSeriesRendererCount();
for (int i = 0; i < count; i++) {
double value = mDataset.getValue(i);
if (!mRenderer.isMinValueSet()) {
min = min == MathHelper.NULL_VALUE ? value : Math.min(min, value);
}
if (!mRenderer.isMaxValueSet()) {
max = max == MathHelper.NULL_VALUE ? value : Math.max(max, value);
}
}
}
if (min == max) {
min = min * 0.5;
max = max * 1.5;
}
paint.setColor(mRenderer.getLabelsColor());
double minorTicks = mRenderer.getMinorTicksSpacing();
double majorTicks = mRenderer.getMajorTicksSpacing();
if (minorTicks == MathHelper.NULL_VALUE) {
minorTicks = (max - min) / 30;
}
if (majorTicks == MathHelper.NULL_VALUE) {
majorTicks = (max - min) / 10;
}
drawTicks(canvas, min, max, angleMin, angleMax, mCenterX, mCenterY, longRadius, radius,
minorTicks, paint, false);
drawTicks(canvas, min, max, angleMin, angleMax, mCenterX, mCenterY, longRadius, shortRadius,
majorTicks, paint, true);
int count = mRenderer.getSeriesRendererCount();
for (int i = 0; i < count; i++) {
double angle = getAngleForValue(mDataset.getValue(i), angleMin, angleMax, min, max);
paint.setColor(mRenderer.getSeriesRendererAt(i).getColor());
boolean type = mRenderer.getVisualTypeForIndex(i) == Type.ARROW;
drawNeedle(canvas, angle, mCenterX, mCenterY, shortRadius, type, paint);
}
drawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize, paint, false);
drawTitle(canvas, x, y, width, paint);
}
/**
* Returns the angle for a specific chart value.
*
* @param value the chart value
* @param minAngle the minimum chart angle value
* @param maxAngle the maximum chart angle value
* @param min the minimum chart value
* @param max the maximum chart value
* @return the angle
*/
private double getAngleForValue(double value, double minAngle, double maxAngle, double min,
double max) {
double angleDiff = maxAngle - minAngle;
double diff = max - min;
return Math.toRadians(minAngle + (value - min) * angleDiff / diff);
}
/**
* Draws the chart tick lines.
*
* @param canvas the canvas
* @param min the minimum chart value
* @param max the maximum chart value
* @param minAngle the minimum chart angle value
* @param maxAngle the maximum chart angle value
* @param centerX the center x value
* @param centerY the center y value
* @param longRadius the long radius
* @param shortRadius the short radius
* @param ticks the tick spacing
* @param paint the paint settings
* @param labels paint the labels
* @return the angle
*/
private void drawTicks(Canvas canvas, double min, double max, double minAngle, double maxAngle,
int centerX, int centerY, double longRadius, double shortRadius, double ticks, Paint paint,
boolean labels) {
for (double i = min; i <= max; i += ticks) {
double angle = getAngleForValue(i, minAngle, maxAngle, min, max);
double sinValue = Math.sin(angle);
double cosValue = Math.cos(angle);
int x1 = Math.round(centerX + (float) (shortRadius * sinValue));
int y1 = Math.round(centerY + (float) (shortRadius * cosValue));
int x2 = Math.round(centerX + (float) (longRadius * sinValue));
int y2 = Math.round(centerY + (float) (longRadius * cosValue));
canvas.drawLine(x1, y1, x2, y2, paint);
if (labels) {
paint.setTextAlign(Component.LEFT);
if (x1 <= x2) {
paint.setTextAlign(Component.RIGHT);
}
String text = i + "";
if (Math.round(i) == (long) i) {
text = (long) i + "";
}
canvas.drawText(text, x1, y1, paint);
}
}
}
/**
* Returns the angle for a specific chart value.
*
* @param canvas the canvas
* @param angle the needle angle value
* @param centerX the center x value
* @param centerY the center y value
* @param radius the radius
* @param arrow if a needle or an arrow to be painted
* @param paint the paint settings
* @return the angle
*/
private void drawNeedle(Canvas canvas, double angle, int centerX, int centerY, double radius,
boolean arrow, Paint paint) {
double diff = Math.toRadians(90);
int needleSinValue = (int) (NEEDLE_RADIUS * Math.sin(angle - diff));
int needleCosValue = (int) (NEEDLE_RADIUS * Math.cos(angle - diff));
int needleX = (int) (radius * Math.sin(angle));
int needleY = (int) (radius * Math.cos(angle));
int needleCenterX = centerX + needleX;
int needleCenterY = centerY + needleY;
float[] points;
if (arrow) {
int arrowBaseX = centerX + (int) (radius * 0.85 * Math.sin(angle));
int arrowBaseY = centerY + (int) (radius * 0.85 * Math.cos(angle));
points = new float[] { arrowBaseX - needleSinValue, arrowBaseY - needleCosValue,
needleCenterX, needleCenterY, arrowBaseX + needleSinValue, arrowBaseY + needleCosValue };
float width = paint.getStrokeWidth();
paint.setStrokeWidth(5);
canvas.drawLine(centerX, centerY, needleCenterX, needleCenterY, paint);
paint.setStrokeWidth(width);
} else {
points = new float[] { centerX - needleSinValue, centerY - needleCosValue, needleCenterX,
needleCenterY, centerX + needleSinValue, centerY + needleCosValue };
}
drawPath(canvas, points, paint, true);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy