package org.schmivits.airball.display.speed; import android.content.res.AssetManager; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Typeface; import org.schmivits.airball.display.DisplayConfiguration; import org.schmivits.airball.widget.Widget; public class SpeedTapeCore extends Widget { public interface Model { float getSpeed(); float getVs0(); // Bottom of white arc float getVfe(); // Top of white arc float getVs1(); // Bottom of green arc float getVno(); // Top of green / bottom of yellow arc float getVne(); // Top of yellow / bottom of red arc } // The below constants, while they may seem silly ;), are useful for // tweaking exact RGB values if necessary private static final int WHITE_ARC_COLOR = Color.WHITE; private static final int GREEN_ARC_COLOR = Color.GREEN; private static final int YELLOW_ARC_COLOR = Color.YELLOW; private static final int RED_ARC_COLOR = Color.RED; private static final float TEXT_BASELINE_TO_CENTER_FACTOR = 0.375f; private final DisplayConfiguration mConfig; private final Model mModel; private final float mVArcRightBoundaryFromRight; private final float mTapePixelsPerKnot; private final float mTickMarkFivesLength; private final float mTickMarkTensLength; private final float mTextSize; private final float mTextRightBoundaryFromRight; private final float mVArcThickness; private final Paint mTextPaint = new Paint(); private final Paint mWhiteArcPaint = new Paint(); private final Paint mGreenArcPaint = new Paint(); private final Paint mYellowArcPaint = new Paint(); private final Paint mRedArcPaint = new Paint(); public SpeedTapeCore( DisplayConfiguration config, AssetManager assets, float x, float y, float w, float h, Model model) { super(x, y, w, h); mConfig = config; mModel = model; mVArcThickness = (float) Math.floor(w / 12); mVArcRightBoundaryFromRight = 2f * mConfig.mThinLineThickness; mTapePixelsPerKnot = (float) Math.floor(w / 10); mTickMarkFivesLength = (float) Math.floor(3 * mVArcThickness); mTickMarkTensLength = (float) Math.floor(3.25 * mVArcThickness); mTextSize = (float) Math.floor(w / 2.5); mTextRightBoundaryFromRight = (float) Math.floor(3.75 * mVArcThickness); Typeface tf = Typeface.createFromAsset(assets, mConfig.mTextTypeface); mTextPaint.setColor(mConfig.mTextColor); mTextPaint.setTypeface(tf); mTextPaint.setTextSize(mTextSize); mTextPaint.setTextAlign(Align.RIGHT); mTextPaint.setAntiAlias(true); mWhiteArcPaint.setColor(WHITE_ARC_COLOR); mGreenArcPaint.setColor(GREEN_ARC_COLOR); mYellowArcPaint.setColor(YELLOW_ARC_COLOR); mRedArcPaint.setColor(RED_ARC_COLOR); } float speedToCanvasPosition(float speed) { return getHeight() / 2 + (speed - mModel.getSpeed()) * mTapePixelsPerKnot; } private void drawSpeed(Canvas canvas, int speed5) { if (speed5 < 0) { return; } int speed = speed5 * 5; float y = speedToCanvasPosition(speed); boolean isTens = ((speed % 10f) == 0); if (isTens) { canvas.drawText( "" + speed, getWidth() - mTextRightBoundaryFromRight, y + mTextSize * TEXT_BASELINE_TO_CENTER_FACTOR, mTextPaint); canvas.drawRect( getWidth() - mTickMarkTensLength, y - mConfig.mThickLineThickness / 2, getWidth(), y + mConfig.mThickLineThickness / 2, mConfig.mLinePaint); } else { canvas.drawRect( getWidth() - mTickMarkFivesLength, y - mConfig.mThinLineThickness / 2, getWidth(), y + mConfig.mThinLineThickness / 2, mConfig.mLinePaint); } } private void drawScaleLine(Canvas canvas) { float yMin = Math.max(0, speedToCanvasPosition(0f)); canvas.drawRect( getWidth() - mConfig.mThinLineThickness, yMin - mConfig.mThinLineThickness / 2, getWidth(), getHeight(), mConfig.mLinePaint); } private void drawVArcs(Canvas canvas) { canvas.drawRect( getWidth() - mVArcRightBoundaryFromRight - 2 * mVArcThickness, speedToCanvasPosition(mModel.getVs0()), getWidth() - mVArcRightBoundaryFromRight - mVArcThickness, speedToCanvasPosition(mModel.getVfe()), mWhiteArcPaint); canvas.drawRect( getWidth() - mVArcRightBoundaryFromRight - mVArcThickness, speedToCanvasPosition(mModel.getVs1()), getWidth() - mVArcRightBoundaryFromRight, speedToCanvasPosition(mModel.getVno()), mGreenArcPaint); canvas.drawRect( getWidth() - mVArcRightBoundaryFromRight - mVArcThickness, speedToCanvasPosition(mModel.getVno()), getWidth() - mVArcRightBoundaryFromRight, speedToCanvasPosition(mModel.getVne()), mYellowArcPaint); canvas.drawRect( getWidth() - mVArcRightBoundaryFromRight - mVArcThickness, speedToCanvasPosition(mModel.getVne()), getWidth() - mVArcRightBoundaryFromRight, getHeight(), mRedArcPaint); } @Override protected void drawContents(Canvas canvas) { drawScaleLine(canvas); drawVArcs(canvas); int speed5AtTop = (int) Math.floor((mModel.getSpeed() - getHeight() / 2 / mTapePixelsPerKnot) / 5) - 1; int speed5AtBottom = (int) Math.ceil((mModel.getSpeed() + getHeight() / 2 / mTapePixelsPerKnot) / 5) + 1; for (int i = speed5AtTop; i <= speed5AtBottom; i++) { drawSpeed(canvas, i); } } }