/*
* Copyright © 2013 Michael von Glasow.
*
* This file is part of LSRN Tools.
*
* LSRN Tools is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSRN Tools is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSRN Tools. If not, see <http://www.gnu.org/licenses/>.
*/
package com.naman14.stools.location.widgets;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.location.GpsSatellite;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
/**
* Displays the signal-to-noise ratio of the GPS satellites in a bar chart.
*/
public class GpsSnrView extends View {
private String TAG = "GpsSnrView";
private Iterable<GpsSatellite> mSats;
private Paint activePaint;
private Paint inactivePaint;
private Paint gridPaint;
private Paint gridPaintStrong;
//FIXME: should be DPI-dependent, this is OK for MDPI
private int gridStrokeWidth = 2;
// Which satellites to draw
private boolean draw32 = true; // 01-32 (GPS satellites)
private boolean draw64 = false; // 33-54 are not used
private boolean draw88 = false; // 65-88 (GLONASS satellites)
/**
* @param context
*/
public GpsSnrView(Context context) {
super(context);
doInit();
}
/**
* @param context
* @param attrs
*/
public GpsSnrView(Context context, AttributeSet attrs) {
super(context, attrs);
doInit();
}
/**
* @param context
* @param attrs
* @param defStyle
*/
public GpsSnrView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
doInit();
}
private void doInit() {
activePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
activePaint.setColor(Color.parseColor("#FF33B5E5"));
activePaint.setStyle(Paint.Style.FILL);
inactivePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
inactivePaint.setColor(Color.parseColor("#FFFF4444"));
inactivePaint.setStyle(Paint.Style.FILL);
gridPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
gridPaint.setColor(Color.parseColor("#FF4D4D4D"));
gridPaint.setStyle(Paint.Style.STROKE);
gridPaint.setStrokeWidth(gridStrokeWidth);
gridPaintStrong = new Paint(gridPaint);
gridPaintStrong.setColor(Color.parseColor("#FFFFFFFF"));
}
/**
* Returns the number of SNR bars to draw
*
* The number of bars to draw varies depending on the systems supported by
* the device. The most common numbers are 32 for a GPS-only receiver or 56
* for a combined GPS/GLONASS receiver.
*
* @return The number of bars to draw
*/
private Integer getNumBars() {
return (draw32 ? 32 : 0) + (draw64 ? 32 : 0) + (draw88 ? 24 : 0);
}
@Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
int mHeight = (int) Math.min(MeasureSpec.getSize(widthMeasureSpec) * 0.15f, MeasureSpec.getSize(heightMeasureSpec));
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mHeight);
}
/*
* Draws a satellite's SNR bar.
*/
private void drawSat(Canvas canvas, int prn, float snr, boolean used) {
int w = getWidth();
int h = getHeight();
int i = draw32 ? prn : (prn - 32);
if ((i >= 64) && !draw64)
i -= 32;
int x0 = (i - 1) * (w - gridStrokeWidth) / getNumBars() + gridStrokeWidth;
int x1 = i * (w - gridStrokeWidth) / getNumBars();
int y0 = h - gridStrokeWidth;
int y1 = (int) (y0 * (1 - Math.min(snr, 60) / 60));
canvas.drawRect(x0, y1, x1, h, used?activePaint:inactivePaint);
}
@Override
protected void onDraw(Canvas canvas) {
//don't use Canvas.getWidth() and Canvas.getHeight() here, they may return incorrect values
int w = getWidth();
int h = getHeight();
if (mSats != null) {
// iterate through list to find out how many bars to draw
for (GpsSatellite sat : mSats) {
int prn = sat.getPrn();
if (prn <= 32) {
draw32 = true;
} else if (prn <= 64) {
Log.wtf(TAG, String.format("Got satellite with PRN %d, which should not be happening", prn));
draw64 = true;
} else if (prn <= 88) {
draw88 = true;
} else {
Log.w(TAG, String.format("Got satellite with PRN %d, possibly unsupported system", prn));
}
}
// then draw the bars
for (GpsSatellite sat : mSats) {
drawSat(canvas, sat.getPrn(), sat.getSnr(), sat.usedInFix());
}
}
// draw the grid on top, with an auxiliary line every 4 sats
canvas.drawLine((float) gridStrokeWidth / 2, 0, (float) gridStrokeWidth / 2, h, gridPaintStrong);
for (int i = 4; i < getNumBars(); i+=4) {
float x = (float) gridStrokeWidth / 2
+ i * (w - gridStrokeWidth) / getNumBars();
Paint paint = gridPaint;
switch(i) {
case 32:
if (draw32 || draw64)
paint = gridPaintStrong;
break;
case 56:
if ((draw32 != draw64) && draw88)
paint = gridPaintStrong;
break;
case 64:
if (draw32 && draw64)
paint = gridPaintStrong;
break;
case 88:
if (draw32 && draw64 && draw88)
paint = gridPaintStrong;
break;
default:
break;
}
canvas.drawLine(x, 0, x, h, paint);
}
canvas.drawLine(w - (float) gridStrokeWidth / 2, h, w - (float) gridStrokeWidth / 2, 0, gridPaintStrong);
canvas.drawLine(0, h - (float) gridStrokeWidth / 2, w, h - (float) gridStrokeWidth / 2, gridPaintStrong);
}
public void showSats(Iterable<GpsSatellite> sats) {
mSats = sats;
invalidate();
}
}