package com.robert.maps.applib.kml;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.RectF;
import android.location.Location;
import android.util.AttributeSet;
import android.view.View;
import com.robert.maps.applib.R;
import com.robert.maps.applib.kml.Track.TrackPoint;
public class ChartView extends View {
private int zoomLevel = 1;
private double maxX;
private int leftBorder = -1;
private int topBorder = 0;
private int bottomBorder = 0;
private int w = 0;
private int h = 0;
private int effectiveWidth = 0;
private int effectiveHeight = 0;
private Path[] path = {new Path(), new Path()};
private final Paint borderPaint = new Paint();
private final Paint labelPaint = new Paint();
private final Paint gridPaint = new Paint();
private final Paint gridBarPaint = new Paint();
private final Paint clearPaint = new Paint();
private final Paint[] graphPaint = {new Paint(), new Paint()};
private static final int TOP_BORDER = 15;
private static final float BOTTOM_BORDER = 40;
private static final int RIGHT_BORDER = 17;
private static final int UNIT_BORDER = 15;
private static final int FONT_HEIGHT = 10;
private static final int MAX_INTERVALS = 5;
public ChartView(Context context, AttributeSet attrs) {
super(context, attrs);
final Resources res = getResources();
labelPaint.setStyle(Style.STROKE);
labelPaint.setColor(Color.BLACK);
labelPaint.setAntiAlias(true);
borderPaint.setStyle(Style.STROKE);
borderPaint.setColor(res.getColor(R.color.chart_border));
borderPaint.setAntiAlias(true);
gridPaint.setStyle(Style.STROKE);
gridPaint.setColor(Color.GRAY);
gridPaint.setAntiAlias(false);
gridBarPaint.set(gridPaint);
gridBarPaint.setPathEffect(new DashPathEffect(new float[] { 3, 2 }, 0));
clearPaint.setStyle(Style.FILL);
clearPaint.setColor(Color.WHITE);
clearPaint.setAntiAlias(false);
graphPaint[0].setColor(res.getColor(R.color.chart_graph_0));
graphPaint[0].setStyle(Style.STROKE);
graphPaint[0].setStrokeWidth(3);
graphPaint[0].setAntiAlias(true);
graphPaint[0].setAlpha(180);
graphPaint[0].setStrokeCap(Paint.Cap.ROUND);
graphPaint[0].setShadowLayer(10.0f, 0, 0, res.getColor(R.color.chart_graph_0));
graphPaint[1] = new Paint(graphPaint[0]);
graphPaint[1].setColor(res.getColor(R.color.chart_graph_1));
graphPaint[1].setShadowLayer(10.0f, 0, 0, res.getColor(R.color.chart_graph_1));
// path = new Path();
// path.moveTo(0, 0);
// path.lineTo(100, 100);
// path.lineTo(100, 200);
// path.lineTo(200, 300);
// path.close();
updateDimensions();
}
public ChartView(Context context) {
super(context);
}
public void setTrack(final Track tr){
float[] results = {0};
float distance = 0.0f;
double minSpeed = Double.MAX_VALUE, minAlt = Double.MAX_VALUE;
TrackPoint lastpt = null;
for(TrackPoint pt : tr.getPoints()){
if(lastpt == null){
//path.moveTo(pt.date.getTime()/1000, (float) pt.speed);
path[0].moveTo(0, (float) pt.speed);
path[1].moveTo(0, (float) pt.alt);
} else {
Location.distanceBetween(lastpt.lat, lastpt.lon, pt.lat, pt.lon, results);
//path.lineTo(pt.date.getTime()/1000, (float) pt.speed);
distance += results[0];
path[0].lineTo(distance, (float) pt.speed);
path[1].lineTo(distance, (float) pt.alt);
}
if(minSpeed > pt.speed) minSpeed = pt.speed;
if(minAlt > pt.alt) minAlt = pt.alt;
lastpt = pt;
}
final Matrix m = new Matrix();
m.setTranslate(0, (float) - minSpeed);
path[0].transform(m);
m.setScale(1, -1);
path[0].transform(m);
m.setTranslate(0, (float) - minAlt);
path[1].transform(m);
m.setScale(1, -1);
path[1].transform(m);
}
@Override
protected void onDraw(Canvas c) {
updateEffectiveDimensionsIfChanged(c);
c.save();
//c.drawColor(Color.BLACK);
if(path != null){
RectF r = new RectF();
final Matrix m = new Matrix();
path[0].computeBounds(r, true);
m.setScale(effectiveWidth / r.width(), /*-*/ effectiveHeight / r.height());
path[0].transform(m);
m.setTranslate(RIGHT_BORDER, effectiveHeight + BOTTOM_BORDER);
path[0].transform(m);
c.drawPath(path[0], graphPaint[0]);
path[1].computeBounds(r, true);
m.setScale(effectiveWidth / r.width(), /*-*/ effectiveHeight / r.height());
path[1].transform(m);
m.setTranslate(RIGHT_BORDER, effectiveHeight + BOTTOM_BORDER);
path[1].transform(m);
c.drawPath(path[1], graphPaint[1]);
}
drawXAxis(c);
drawYAxis(c);
c.restore();
}
private int getX(double distance) {
return leftBorder
+ (int) ((distance * effectiveWidth / maxX) * zoomLevel);
}
private void updateDimensions() {
// maxX = xMonitor.getMax();
// if (data.size() <= 1) {
// maxX = 1;
// }
// for (ChartValueSeries cvs : series) {
// cvs.updateDimension();
// }
// // TODO: This is totally broken. Make sure that we calculate based on
// measureText for each
// // grid line, as the labels may vary across intervals.
// int maxLength = 0;
// for (ChartValueSeries cvs : series) {
// if (cvs.isEnabled() && cvs.hasData()) {
// maxLength += cvs.getMaxLabelLength();
// }
// }
final float density = getContext().getResources().getDisplayMetrics().density;
// maxLength = Math.max(maxLength, 1);
final int maxLength = 1;
leftBorder = (int) (density * (4 + 8 * maxLength));
bottomBorder = (int) (density * BOTTOM_BORDER);
topBorder = (int) (density * TOP_BORDER);
updateEffectiveDimensions();
}
private void updateEffectiveDimensions() {
effectiveWidth = Math.max(0, w - 2 * RIGHT_BORDER);
effectiveHeight = (int) Math.max(0, h - 2 * BOTTOM_BORDER);
// effectiveWidth = Math.max(0, w - leftBorder - RIGHT_BORDER);
// effectiveHeight = Math.max(0, h - topBorder - bottomBorder);
}
private void updateEffectiveDimensionsIfChanged(Canvas c) {
if (w != c.getWidth() || h != c.getHeight()) {
// Dimensions have changed (for example due to orientation change).
w = getWidth();
h = getHeight();
updateEffectiveDimensions();
//setUpPath();
}
}
/** Draws the actual X axis line and its label. */
private void drawXAxis(Canvas canvas) {
canvas.drawLine(RIGHT_BORDER, effectiveHeight + BOTTOM_BORDER, effectiveWidth + RIGHT_BORDER, effectiveHeight + BOTTOM_BORDER, borderPaint);
// float rightEdge = getX(maxX);
// final int y = effectiveHeight + topBorder;
//canvas.drawLine(leftBorder, y, rightEdge, y, borderPaint);
// Context c = getContext();
// String s = mode == Mode.BY_DISTANCE
// ? (metricUnits ? c.getString(R.string.kilometer) :
// c.getString(R.string.mile))
// : c.getString(R.string.min);
// canvas.drawText(s, rightEdge, effectiveHeight + .2f * UNIT_BORDER +
// topBorder, labelPaint);
}
/** Draws the actual Y axis line and its label. */
private void drawYAxis(Canvas canvas) {
canvas.drawLine(RIGHT_BORDER, BOTTOM_BORDER, RIGHT_BORDER,
effectiveHeight + BOTTOM_BORDER, borderPaint);
// canvas.drawRect(0, 0, leftBorder - 1, effectiveHeight + topBorder
// + UNIT_BORDER + 1, clearPaint);
// canvas.drawLine(leftBorder, UNIT_BORDER + topBorder, leftBorder,
// effectiveHeight + topBorder, borderPaint);
// for (int i = 1; i < MAX_INTERVALS; ++i) {
// int y = i * effectiveHeight / MAX_INTERVALS + topBorder;
// canvas.drawLine(leftBorder - 5, y, leftBorder, y, gridPaint);
// }
}
}