package uk.org.smithfamily.mslogger.widgets.renderers; import uk.org.smithfamily.mslogger.dashboards.DashboardView; import uk.org.smithfamily.mslogger.widgets.Indicator; import uk.org.smithfamily.mslogger.widgets.Indicator.DisplayType; import android.content.Context; import android.graphics.*; public class Histogram extends Painter { private Paint backgroundPaint; private Paint linePaint; private Paint valuePaint; private RectF borderRect; private static final int NB_VALUES = 100; private final float[] values = new float[NB_VALUES]; private int indexValue = 0; private Path linePath; private int height; private int width; public Histogram(final DashboardView parent, final Indicator model, final Context c) { super(parent, model, c); } @Override protected void init(final Context c) { initDrawingTools(c); } /** * * @param context */ private void initDrawingTools(final Context context) { int anti_alias_flag = Paint.ANTI_ALIAS_FLAG; if (parent.isInEditMode()) { anti_alias_flag = 0; } linePath = new Path(); backgroundPaint = new Paint(); backgroundPaint.setColor(Color.WHITE); backgroundPaint.setTextSize(0.06f); backgroundPaint.setTextAlign(Paint.Align.LEFT); backgroundPaint.setStyle(Paint.Style.STROKE); backgroundPaint.setFlags(anti_alias_flag); backgroundPaint.setAntiAlias(true); valuePaint = new Paint(); valuePaint.setColor(Color.DKGRAY); valuePaint.setTextAlign(Paint.Align.RIGHT); valuePaint.setLinearText(true); valuePaint.setFlags(anti_alias_flag); valuePaint.setAntiAlias(true); linePaint = new Paint(); linePaint.setColor(Color.BLUE); linePaint.setFlags(anti_alias_flag); linePaint.setAntiAlias(true); linePaint.setStyle(Paint.Style.STROKE); borderRect = new RectF(); borderRect.set(0.05f, 0.05f, 0.94f, 0.83f); } /** * Add a value to display on the histogram * * @param value */ public void addValue(final double value) { values[indexValue] = (float) value; indexValue++; indexValue = indexValue % NB_VALUES; } /** * @param canvas */ @Override public void renderFrame(final Canvas canvas) { height = (int) (bottom - top); width = (int) (right - left); if ((width == 0) || (height == 0)) {// We're not ready to do this yet return; } canvas.save(Canvas.ALL_SAVE_FLAG); canvas.translate(left, top); canvas.clipRect(0, 0, width, height); backgroundPaint.setTextSize(0.06f * height); // canvas.scale(width, height); drawBackground(canvas); addValue(model.getValue()); drawTitle(canvas); drawValue(canvas); drawLines(canvas); canvas.restore(); } private void drawLines(final Canvas canvas) { linePath.reset(); final double min = model.getMin(); final double max = model.getMax(); final double range = max - min; float x; float y; float value; int idx; final int numPoints = NB_VALUES - 1; for (int i = 0; i < numPoints; i++) { idx = (indexValue + i) % numPoints; value = values[idx]; x = ((float) i / (float) numPoints) * width + 1; y = (float) (1.0f - ((value - min) / range)) * height; if (i == 0) { linePath.moveTo(x, y); } else { linePath.lineTo(x, y); } } canvas.drawPath(linePath, linePaint); } public void drawBackground(final Canvas canvas) { canvas.drawRect(0, 0, width, height, backgroundPaint); } public void drawValue(final Canvas canvas) { valuePaint.setColor(getFgColour()); final double value = model.getValue(); final int valueDigits = model.getVd(); final float displayValue = (float) (Math.floor((value / Math.pow(10, -valueDigits)) + 0.5) * Math.pow(10, -valueDigits)); String text; if (valueDigits <= 0) { text = Integer.toString((int) displayValue); } else { text = Float.toString(displayValue); } valuePaint.setTextSize(0.06f * height); canvas.drawText(text, 0.94f * width, 0.90f * height, valuePaint); } public void drawTitle(final Canvas canvas) { backgroundPaint.setColor(getFgColour()); String text = model.getTitle(); if (!model.getUnits().equals("")) { text += " (" + model.getUnits() + ")"; } canvas.drawText(text, 0.05f * width, 0.90f * height, backgroundPaint); } @Override public DisplayType getType() { return DisplayType.HISTOGRAM; } @Override public boolean isIsotropic() { return false; } @Override public boolean updateAnimation() { // Histogram is not animated like a gauge so we just say we're good to go return false; } }