diff options
Diffstat (limited to 'src/cgeo/geocaching/cgCompass.java')
| -rw-r--r-- | src/cgeo/geocaching/cgCompass.java | 503 |
1 files changed, 253 insertions, 250 deletions
diff --git a/src/cgeo/geocaching/cgCompass.java b/src/cgeo/geocaching/cgCompass.java index f45501d..e748bef 100644 --- a/src/cgeo/geocaching/cgCompass.java +++ b/src/cgeo/geocaching/cgCompass.java @@ -14,255 +14,258 @@ import android.view.View; public class cgCompass extends View { - private changeThread watchdog = null; - private volatile boolean wantStop = false; - private Context context = null; - private Bitmap compassUnderlay = null; - private Bitmap compassRose = null; - private Bitmap compassArrow = null; - private Bitmap compassOverlay = null; - private double azimuth = 0.0; - private double heading = 0.0; - private double cacheHeading = 0.0; - private double northHeading = 0.0; - private PaintFlagsDrawFilter setfil = null; - private PaintFlagsDrawFilter remfil = null; - private int compassUnderlayWidth = 0; - private int compassUnderlayHeight = 0; - private int compassRoseWidth = 0; - private int compassRoseHeight = 0; - private int compassArrowWidth = 0; - private int compassArrowHeight = 0; - private int compassOverlayWidth = 0; - private int compassOverlayHeight = 0; - private boolean initialDisplay; - private Handler changeHandler = new Handler() { - - @Override - public void handleMessage(Message message) { - try { - invalidate(); - } catch (Exception e) { - Log.e(cgSettings.tag, "cgCompass.changeHandler: " + e.toString()); - } - } - }; - - public cgCompass(Context contextIn) { - super(contextIn); - context = contextIn; - } - - public cgCompass(Context contextIn, AttributeSet attrs) { - super(contextIn, attrs); - context = contextIn; - } - - @Override - public void onAttachedToWindow() { - compassUnderlay = BitmapFactory.decodeResource(context.getResources(), R.drawable.compass_underlay); - compassRose = BitmapFactory.decodeResource(context.getResources(), R.drawable.compass_rose); - compassArrow = BitmapFactory.decodeResource(context.getResources(), R.drawable.compass_arrow); - compassOverlay = BitmapFactory.decodeResource(context.getResources(), R.drawable.compass_overlay); - - compassUnderlayWidth = compassUnderlay.getWidth(); - compassUnderlayHeight = compassUnderlay.getWidth(); - compassRoseWidth = compassRose.getWidth(); - compassRoseHeight = compassRose.getWidth(); - compassArrowWidth = compassArrow.getWidth(); - compassArrowHeight = compassArrow.getWidth(); - compassOverlayWidth = compassOverlay.getWidth(); - compassOverlayHeight = compassOverlay.getWidth(); - - setfil = new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG); - remfil = new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0); - - initialDisplay = true; - wantStop = false; - - watchdog = new changeThread(); - watchdog.start(); - } - - @Override - public void onDetachedFromWindow() { - wantStop = true; - - if (compassUnderlay != null) { - compassUnderlay.recycle(); - } - - if (compassRose != null) { - compassRose.recycle(); - } - - if (compassArrow != null) { - compassArrow.recycle(); - } - - if (compassOverlay != null) { - compassOverlay.recycle(); - } - } - - protected synchronized void updateNorth(double northHeadingIn, double cacheHeadingIn) { - if (initialDisplay) { - // We will force the compass to move brutally if this is the first - // update since it is visible. - azimuth = northHeadingIn; - heading = cacheHeadingIn; - initialDisplay = false; - } - northHeading = northHeadingIn; - cacheHeading = cacheHeadingIn; - } - - /** - * Compute the new value, moving by small increments. - * @param goal the goal to reach - * @param actual the actual value - * @return the new value - */ - static protected double smoothUpdate(double goal, double actual) { - double diff = goal - actual; - final boolean largeDiff = Math.abs(diff) > 5; - - double offset = 0.0; - - if (diff < 0.0) { - diff = diff + 360.0; - } else if (diff >= 360.0) { - diff = diff - 360.0; - } - - // If the difference is smaller than 1 degree, do nothing as it - // causes the arrow to vibrate. - if (diff > 1.0 && diff <= 180.0) { - offset = largeDiff ? 2.0 : 1.0; - } else if (diff > 180.0 && diff < 359.0) { - offset = largeDiff ? -2.0 : -1.0; - } - - return actual + offset; - } - - private class changeThread extends Thread { - - @Override - public void run() { - while (wantStop == false) { - try { - sleep(50); - } catch (Exception e) { - // nothing - } - - synchronized(cgCompass.this) { - azimuth = smoothUpdate(northHeading, azimuth); - heading = smoothUpdate(cacheHeading, heading); - } - - changeHandler.sendMessage(new Message()); - } - } - } - - @Override - protected void onDraw(Canvas canvas) { - double currentAzimuth; - double currentHeading; - - synchronized(this) { - currentAzimuth = azimuth; - currentHeading = heading; - } - - double azimuthTemp = currentAzimuth; - double azimuthRelative = azimuthTemp - currentHeading; - if (azimuthRelative < 0) { - azimuthRelative = azimuthRelative + 360; - } else if (azimuthRelative >= 360) { - azimuthRelative = azimuthRelative - 360; - } - - // compass margins - int canvasCenterX = (compassRoseWidth / 2) + ((getWidth() - compassRoseWidth) / 2); - int canvasCenterY = (compassRoseHeight / 2) + ((getHeight() - compassRoseHeight) / 2); - - int marginLeftTemp = 0; - int marginTopTemp = 0; - - super.onDraw(canvas); - - canvas.save(); - canvas.setDrawFilter(setfil); - - marginLeftTemp = (getWidth() - compassUnderlayWidth) / 2; - marginTopTemp = (getHeight() - compassUnderlayHeight) / 2; - - canvas.drawBitmap(compassUnderlay, marginLeftTemp, marginTopTemp, null); - - marginLeftTemp = (getWidth() - compassRoseWidth) / 2; - marginTopTemp = (getHeight() - compassRoseHeight) / 2; - - canvas.rotate((float) -azimuthTemp, canvasCenterX, canvasCenterY); - canvas.drawBitmap(compassRose, marginLeftTemp, marginTopTemp, null); - canvas.rotate((float) azimuthTemp, canvasCenterX, canvasCenterY); - - marginLeftTemp = (getWidth() - compassArrowWidth) / 2; - marginTopTemp = (getHeight() - compassArrowHeight) / 2; - - canvas.rotate((float) -azimuthRelative, canvasCenterX, canvasCenterY); - canvas.drawBitmap(compassArrow, marginLeftTemp, marginTopTemp, null); - canvas.rotate((float) azimuthRelative, canvasCenterX, canvasCenterY); - - marginLeftTemp = (getWidth() - compassOverlayWidth) / 2; - marginTopTemp = (getHeight() - compassOverlayHeight) / 2; - - canvas.drawBitmap(compassOverlay, marginLeftTemp, marginTopTemp, null); - - canvas.setDrawFilter(remfil); - canvas.restore(); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); - } - - private int measureWidth(int measureSpec) { - int result = 0; - int specMode = MeasureSpec.getMode(measureSpec); - int specSize = MeasureSpec.getSize(measureSpec); - - if (specMode == MeasureSpec.EXACTLY) { - result = specSize; - } else { - result = compassArrow.getWidth() + getPaddingLeft() + getPaddingRight(); - - if (specMode == MeasureSpec.AT_MOST) { - result = Math.min(result, specSize); - } - } - - return result; - } - - private int measureHeight(int measureSpec) { - int result = 0; - int specMode = MeasureSpec.getMode(measureSpec); - int specSize = MeasureSpec.getSize(measureSpec); - - if (specMode == MeasureSpec.EXACTLY) { - result = specSize; - } else { - result = compassArrow.getHeight() + getPaddingTop() + getPaddingBottom(); - - if (specMode == MeasureSpec.AT_MOST) { - result = Math.min(result, specSize); - } - } + private changeThread watchdog = null; + private volatile boolean wantStop = false; + private Context context = null; + private Bitmap compassUnderlay = null; + private Bitmap compassRose = null; + private Bitmap compassArrow = null; + private Bitmap compassOverlay = null; + private double azimuth = 0.0; + private double heading = 0.0; + private double cacheHeading = 0.0; + private double northHeading = 0.0; + private PaintFlagsDrawFilter setfil = null; + private PaintFlagsDrawFilter remfil = null; + private int compassUnderlayWidth = 0; + private int compassUnderlayHeight = 0; + private int compassRoseWidth = 0; + private int compassRoseHeight = 0; + private int compassArrowWidth = 0; + private int compassArrowHeight = 0; + private int compassOverlayWidth = 0; + private int compassOverlayHeight = 0; + private boolean initialDisplay; + private Handler changeHandler = new Handler() { + + @Override + public void handleMessage(Message message) { + try { + invalidate(); + } catch (Exception e) { + Log.e(cgSettings.tag, "cgCompass.changeHandler: " + e.toString()); + } + } + }; + + public cgCompass(Context contextIn) { + super(contextIn); + context = contextIn; + } + + public cgCompass(Context contextIn, AttributeSet attrs) { + super(contextIn, attrs); + context = contextIn; + } + + @Override + public void onAttachedToWindow() { + compassUnderlay = BitmapFactory.decodeResource(context.getResources(), R.drawable.compass_underlay); + compassRose = BitmapFactory.decodeResource(context.getResources(), R.drawable.compass_rose); + compassArrow = BitmapFactory.decodeResource(context.getResources(), R.drawable.compass_arrow); + compassOverlay = BitmapFactory.decodeResource(context.getResources(), R.drawable.compass_overlay); + + compassUnderlayWidth = compassUnderlay.getWidth(); + compassUnderlayHeight = compassUnderlay.getWidth(); + compassRoseWidth = compassRose.getWidth(); + compassRoseHeight = compassRose.getWidth(); + compassArrowWidth = compassArrow.getWidth(); + compassArrowHeight = compassArrow.getWidth(); + compassOverlayWidth = compassOverlay.getWidth(); + compassOverlayHeight = compassOverlay.getWidth(); + + setfil = new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG); + remfil = new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0); + + initialDisplay = true; + wantStop = false; + + watchdog = new changeThread(); + watchdog.start(); + } + + @Override + public void onDetachedFromWindow() { + wantStop = true; + + if (compassUnderlay != null) { + compassUnderlay.recycle(); + } + + if (compassRose != null) { + compassRose.recycle(); + } + + if (compassArrow != null) { + compassArrow.recycle(); + } + + if (compassOverlay != null) { + compassOverlay.recycle(); + } + } + + protected synchronized void updateNorth(double northHeadingIn, double cacheHeadingIn) { + if (initialDisplay) { + // We will force the compass to move brutally if this is the first + // update since it is visible. + azimuth = northHeadingIn; + heading = cacheHeadingIn; + initialDisplay = false; + } + northHeading = northHeadingIn; + cacheHeading = cacheHeadingIn; + } + + /** + * Compute the new value, moving by small increments. + * + * @param goal + * the goal to reach + * @param actual + * the actual value + * @return the new value + */ + static protected double smoothUpdate(double goal, double actual) { + double diff = goal - actual; + final boolean largeDiff = Math.abs(diff) > 5; + + double offset = 0.0; + + if (diff < 0.0) { + diff = diff + 360.0; + } else if (diff >= 360.0) { + diff = diff - 360.0; + } + + // If the difference is smaller than 1 degree, do nothing as it + // causes the arrow to vibrate. + if (diff > 1.0 && diff <= 180.0) { + offset = largeDiff ? 2.0 : 1.0; + } else if (diff > 180.0 && diff < 359.0) { + offset = largeDiff ? -2.0 : -1.0; + } + + return actual + offset; + } + + private class changeThread extends Thread { + + @Override + public void run() { + while (wantStop == false) { + try { + sleep(50); + } catch (Exception e) { + // nothing + } + + synchronized (cgCompass.this) { + azimuth = smoothUpdate(northHeading, azimuth); + heading = smoothUpdate(cacheHeading, heading); + } + + changeHandler.sendMessage(new Message()); + } + } + } + + @Override + protected void onDraw(Canvas canvas) { + double currentAzimuth; + double currentHeading; + + synchronized (this) { + currentAzimuth = azimuth; + currentHeading = heading; + } + + double azimuthTemp = currentAzimuth; + double azimuthRelative = azimuthTemp - currentHeading; + if (azimuthRelative < 0) { + azimuthRelative = azimuthRelative + 360; + } else if (azimuthRelative >= 360) { + azimuthRelative = azimuthRelative - 360; + } + + // compass margins + int canvasCenterX = (compassRoseWidth / 2) + ((getWidth() - compassRoseWidth) / 2); + int canvasCenterY = (compassRoseHeight / 2) + ((getHeight() - compassRoseHeight) / 2); + + int marginLeftTemp = 0; + int marginTopTemp = 0; + + super.onDraw(canvas); + + canvas.save(); + canvas.setDrawFilter(setfil); + + marginLeftTemp = (getWidth() - compassUnderlayWidth) / 2; + marginTopTemp = (getHeight() - compassUnderlayHeight) / 2; + + canvas.drawBitmap(compassUnderlay, marginLeftTemp, marginTopTemp, null); + + marginLeftTemp = (getWidth() - compassRoseWidth) / 2; + marginTopTemp = (getHeight() - compassRoseHeight) / 2; + + canvas.rotate((float) -azimuthTemp, canvasCenterX, canvasCenterY); + canvas.drawBitmap(compassRose, marginLeftTemp, marginTopTemp, null); + canvas.rotate((float) azimuthTemp, canvasCenterX, canvasCenterY); + + marginLeftTemp = (getWidth() - compassArrowWidth) / 2; + marginTopTemp = (getHeight() - compassArrowHeight) / 2; + + canvas.rotate((float) -azimuthRelative, canvasCenterX, canvasCenterY); + canvas.drawBitmap(compassArrow, marginLeftTemp, marginTopTemp, null); + canvas.rotate((float) azimuthRelative, canvasCenterX, canvasCenterY); + + marginLeftTemp = (getWidth() - compassOverlayWidth) / 2; + marginTopTemp = (getHeight() - compassOverlayHeight) / 2; + + canvas.drawBitmap(compassOverlay, marginLeftTemp, marginTopTemp, null); + + canvas.setDrawFilter(remfil); + canvas.restore(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); + } + + private int measureWidth(int measureSpec) { + int result = 0; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + if (specMode == MeasureSpec.EXACTLY) { + result = specSize; + } else { + result = compassArrow.getWidth() + getPaddingLeft() + getPaddingRight(); + + if (specMode == MeasureSpec.AT_MOST) { + result = Math.min(result, specSize); + } + } + + return result; + } + + private int measureHeight(int measureSpec) { + int result = 0; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + if (specMode == MeasureSpec.EXACTLY) { + result = specSize; + } else { + result = compassArrow.getHeight() + getPaddingTop() + getPaddingBottom(); + + if (specMode == MeasureSpec.AT_MOST) { + result = Math.min(result, specSize); + } + } - return result; - } + return result; + } }
\ No newline at end of file |
