/**
* Copyright (C) 2009, 2010 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.androsz.achartengine.chart;
import java.io.Serializable;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.Path;
import com.androsz.achartengine.renderer.DefaultRenderer;
import com.androsz.achartengine.renderer.SimpleSeriesRenderer;
import com.androsz.achartengine.renderer.XYMultipleSeriesRenderer;
import com.androsz.achartengine.renderer.XYMultipleSeriesRenderer.Orientation;
/**
* An abstract class to be implemented by the chart rendering classes.
*/
public abstract class AbstractChart implements Serializable {
/**
*
*/
private static final long serialVersionUID = 9212809539383635286L;
/**
* The graphical representation of the 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
*/
public abstract void draw(Canvas canvas, int x, int y, int width,
int height, Paint paint);
/**
* Draws the chart background.
*
* @param renderer
* the chart renderer
* @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 used for drawing
* @param newColor
* if a new color is to be used
* @param color
* the color to be used
*/
protected void drawBackground(DefaultRenderer renderer, Canvas canvas,
int x, int y, int width, int height, Paint paint, boolean newColor,
int color) {
if (renderer.isApplyBackgroundColor() || newColor) {
if (newColor) {
paint.setColor(color);
} else {
paint.setColor(renderer.getBackgroundColor());
}
paint.setStyle(Style.FILL);
canvas.drawRect(x, y, x + width, y + height, paint);
}
}
/**
* Draws the chart legend.
*
* @param canvas
* the canvas to paint to
* @param renderer
* the series renderer
* @param titles
* the titles to go to the legend
* @param left
* the left X value of the area to draw to
* @param right
* the right X value of the area to draw to
* @param y
* the y value of the area to draw to
* @param width
* the width of the area to draw to
* @param height
* the height of the area to draw to
* @param legendSize
* the legend size
* @param paint
* the paint to be used for drawing
*/
protected void drawLegend(Canvas canvas, DefaultRenderer renderer,
String[] titles, int left, int right, int y, int width, int height,
int legendSize, Paint paint) {
if (renderer.isShowLegend()) {
float currentX = left;
float currentY = y + height - legendSize + 32;
final float lineSize = getLegendShapeWidth();
paint.setTextAlign(Align.LEFT);
paint.setTextSize(renderer.getLegendTextSize());
final int sLength = Math.min(titles.length,
renderer.getSeriesRendererCount());
for (int i = 0; i < sLength; i++) {
String text = titles[i];
if (titles.length == renderer.getSeriesRendererCount()) {
paint.setColor(renderer.getSeriesRendererAt(i).getColor());
} else {
paint.setColor(Color.LTGRAY);
}
final float[] widths = new float[text.length()];
paint.getTextWidths(text, widths);
float sum = 0;
for (final float value : widths) {
sum += value;
}
final float extraSize = lineSize + 10 + sum;
float currentWidth = currentX + extraSize;
if (i > 0 && getExceed(currentWidth, renderer, right, width)) {
currentX = left;
currentY += renderer.getLegendTextSize();
currentWidth = currentX + extraSize;
}
if (getExceed(currentWidth, renderer, right, width)) {
float maxWidth = right - currentX - lineSize - 10;
if (isVertical(renderer)) {
maxWidth = width - currentX - lineSize - 10;
}
final int nr = paint
.breakText(text, true, maxWidth, widths);
text = text.substring(0, nr) + "...";
}
drawLegendShape(canvas, renderer.getSeriesRendererAt(i),
currentX, currentY, paint);
canvas.drawText(text, currentX + lineSize + 5, currentY + 5,
paint);
currentX += extraSize;
}
}
}
/**
* The graphical representation of the legend shape.
*
* @param canvas
* the canvas to paint to
* @param renderer
* the series renderer
* @param x
* the x value of the point the shape should be drawn at
* @param y
* the y value of the point the shape should be drawn at
* @param paint
* the paint to be used for drawing
*/
public abstract void drawLegendShape(Canvas canvas,
SimpleSeriesRenderer renderer, float x, float y, Paint paint);
/**
* The graphical representation of a path.
*
* @param canvas
* the canvas to paint to
* @param points
* the points that are contained in the path to paint
* @param paint
* the paint to be used for painting
* @param circular
* if the path ends with the start point
*/
protected void drawPath(Canvas canvas, float[] points, Paint paint,
boolean circular) {
final Path path = new Path();
path.moveTo(points[0], points[1]);
for (int i = 2; i < points.length; i += 2) {
path.lineTo(points[i], points[i + 1]);
}
if (circular) {
path.lineTo(points[0], points[1]);
}
canvas.drawPath(path, paint);
}
private boolean getExceed(float currentWidth, DefaultRenderer renderer,
int right, int width) {
boolean exceed = currentWidth > right;
if (isVertical(renderer)) {
exceed = currentWidth > width;
}
return exceed;
}
/**
* Returns the legend shape width.
*
* @return the legend shape width
*/
public abstract int getLegendShapeWidth();
/**
* Checks if the current chart is rendered as vertical.
*
* @param renderer
* the renderer
* @return if the chart is rendered as a vertical one
*/
private boolean isVertical(DefaultRenderer renderer) {
return renderer instanceof XYMultipleSeriesRenderer
&& ((XYMultipleSeriesRenderer) renderer).getOrientation() == Orientation.VERTICAL;
}
}