/* * Copyright (C) 2007 The Android Open Source Project * * 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 net.redgeek.android.eventrend.graph; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.DashPathEffect; import android.graphics.Paint; import android.graphics.Path; import net.redgeek.android.eventrend.primitives.Datapoint; import net.redgeek.android.eventrend.primitives.TimeSeries; import net.redgeek.android.eventrend.primitives.Tuple; import java.util.ArrayList; public interface TimeSeriesPainter { public void setColor(String colorStr); public void setPointRadius(float size); public void drawPath(Canvas canvas, TimeSeries ts); public void drawTrend(Canvas canvas, TimeSeries ts); public void drawMarker(Canvas canvas, Tuple start, Tuple end); public void drawGoal(Canvas canvas, Tuple start, Tuple end); public void drawText(Canvas canvas, String text, float x, float y); public static class Default implements TimeSeriesPainter { private Path mPath; private Path mTrend; private Path mPoints; private Paint mPathPaint; private Paint mPointsPaint; private Paint mTrendPaint; private Paint mTrendMarkerPaint; private Paint mGoalPaint; private Paint mLabelPaint; private float mPointRadius; public Default() { defaultInit(); } public Default(TimeSeriesPainter.Default other) { if (other == null) { defaultInit(); } else mPath = new Path(other.mPath); mTrend = new Path(other.mTrend); mPoints = new Path(other.mPoints); mPathPaint = new Paint(other.mPathPaint); mPointsPaint = new Paint(other.mPointsPaint); mTrendPaint = new Paint(other.mTrendPaint); mTrendMarkerPaint = new Paint(other.mTrendMarkerPaint); mGoalPaint = new Paint(other.mGoalPaint); mLabelPaint = new Paint(other.mLabelPaint); mPointRadius = other.mPointRadius; } private void defaultInit() { mPath = new Path(); mTrend = new Path(); mPoints = new Path(); mPathPaint = new Paint(); mPointsPaint = new Paint(); mTrendPaint = new Paint(); mTrendMarkerPaint = new Paint(); mGoalPaint = new Paint(); mLabelPaint = new Paint(); mPointRadius = 3.0f; } public void setPointRadius(float size) { mPointRadius = size; } public void drawText(Canvas canvas, String text, float x, float y) { canvas.drawText(text, x, y, mLabelPaint); } public void drawGoal(Canvas canvas, Tuple start, Tuple end) { canvas.drawLine(start.x, start.y, end.x, end.y, mGoalPaint); } public void drawMarker(Canvas canvas, Tuple start, Tuple end) { canvas.drawLine(start.x, start.y, end.x, end.y, mTrendMarkerPaint); } public void drawPath(Canvas canvas, TimeSeries ts) { Datapoint thisPoint = null; Datapoint prevPoint = null; Tuple first = null; Tuple second = null; int datapointsSize; if (ts.isEnabled() == false) return; mPath.rewind(); mPoints.rewind(); // we don't have to draw all the point preceding the first visible on, // just the last of them, up until one after the last visible ArrayList<Datapoint> datapoints = ts.getDatapoints(); datapointsSize = datapoints.size(); int offset = ts.getVisiblePreLastIdx(); if (offset < 0 || offset == Integer.MAX_VALUE) offset = 0; int end = ts.getVisiblePostFirstIdx(); if (end < 0 || end == Integer.MAX_VALUE) end = datapointsSize - 1; for (int i = offset; i < datapointsSize && i <= end; i++) { thisPoint = datapoints.get(i); if (thisPoint != null) second = thisPoint.mValueScreen; if (prevPoint != null) first = prevPoint.mValueScreen; ts.getInterpolator().updatePath(mPath, first, second); mPoints.moveTo(thisPoint.mValueScreen.x, thisPoint.mValueScreen.y); mPoints.addCircle(thisPoint.mValueScreen.x, thisPoint.mValueScreen.y, mPointRadius, Path.Direction.CW); prevPoint = thisPoint; } if (thisPoint != null) { mPath.setLastPoint(thisPoint.mValueScreen.x, thisPoint.mValueScreen.y); canvas.drawPath(mPath, mPathPaint); canvas.drawPath(mPoints, mPointsPaint); } } public void drawTrend(Canvas canvas, TimeSeries ts) { Datapoint thisPoint = null; Datapoint prevPoint = null; Tuple first = null; Tuple second = null; int datapointsSize; if (ts.isEnabled() == false) return; // we don't have to draw all the point preceding the first visible on, // just the last of them, up until one after the last visible ArrayList<Datapoint> datapoints = ts.getDatapoints(); datapointsSize = datapoints.size(); int offset = ts.getVisiblePreLastIdx(); if (offset < 0 || offset == Integer.MAX_VALUE) offset = 0; int end = ts.getVisiblePostFirstIdx(); if (end < 0 || end == Integer.MAX_VALUE) end = datapointsSize - 1; mTrend.rewind(); for (int i = offset; i < datapointsSize && i <= end; i++) { thisPoint = datapoints.get(i); if (thisPoint != null) second = thisPoint.mTrendScreen; if (prevPoint != null) first = prevPoint.mTrendScreen; ts.getInterpolator().updatePath(mTrend, first, second); prevPoint = thisPoint; } if (thisPoint != null) { canvas.drawPath(mTrend, mTrendPaint); } } public void setColor(String color) { int colorInt = Color.BLACK; try { colorInt = Color.parseColor(color); } catch (IllegalArgumentException e) { colorInt = Color.BLACK; } mPathPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPathPaint.setStyle(Paint.Style.STROKE); mPathPaint.setStrokeWidth(GraphView.PATH_WIDTH); mPathPaint.setColor(colorInt); mPointsPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPointsPaint.setStyle(Paint.Style.FILL_AND_STROKE); mPointsPaint.setStrokeWidth(GraphView.PATH_WIDTH); mPointsPaint.setColor(colorInt); mTrendPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTrendPaint.setStyle(Paint.Style.STROKE); mTrendPaint.setStrokeWidth(GraphView.TREND_WIDTH); mTrendPaint.setColor(colorInt); DashPathEffect trendDashes = new DashPathEffect(new float[] { GraphView.TREND_DASH_WIDTH, GraphView.TREND_DASH_WIDTH }, 0); mTrendPaint.setPathEffect(trendDashes); mTrendMarkerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTrendMarkerPaint.setStyle(Paint.Style.STROKE); mTrendMarkerPaint.setStrokeWidth(GraphView.TREND_WIDTH); mTrendMarkerPaint.setColor(colorInt); DashPathEffect trendMarkerDashes = new DashPathEffect(new float[] { GraphView.GOAL_DASH_WIDTH / 2, GraphView.GOAL_DASH_WIDTH, }, 0); mTrendMarkerPaint.setPathEffect(trendMarkerDashes); mGoalPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mGoalPaint.setStyle(Paint.Style.STROKE); mGoalPaint.setStrokeWidth(GraphView.GOAL_WIDTH); mGoalPaint.setColor(colorInt); DashPathEffect goalDashes = new DashPathEffect(new float[] { GraphView.GOAL_DASH_WIDTH, GraphView.GOAL_DASH_WIDTH }, 0); mGoalPaint.setPathEffect(goalDashes); mLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mLabelPaint.setStyle(Paint.Style.STROKE); mLabelPaint.setStrokeWidth(GraphView.LABEL_WIDTH); mLabelPaint.setColor(colorInt); } } }