package carnero.cgeo.original.libs;
import android.util.AttributeSet;
import android.view.View;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Canvas;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import carnero.cgeo.original.R;
public class Compass extends View {
private changeThread watchdog = null;
private boolean wantStop = false;
private boolean lock = false;
private boolean drawing = false;
private Context context = null;
private Bitmap compassUnderlay = null;
private Bitmap compassRose = null;
private Bitmap compassArrow = null;
private Bitmap compassOverlay = null;
private Double azimuth = new Double(0);
private Double heading = new Double(0);
private Double cacheHeading = new Double(0);
private Double northHeading = new Double(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 Handler changeHandler = new Handler() {
@Override
public void handleMessage(Message message) {
try {
invalidate();
} catch (Exception e) {
Log.e(Settings.tag, "cgCompass.changeHandler: " + e.toString());
}
}
};
public Compass(Context contextIn) {
super(contextIn);
context = contextIn;
}
public Compass(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);
wantStop = false;
watchdog = new changeThread(changeHandler);
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();
}
}
public void updateNorth(Double northHeadingIn, Double cacheHeadingIn) {
northHeading = northHeadingIn;
cacheHeading = cacheHeadingIn;
}
private class changeThread extends Thread {
Handler handler = null;
public changeThread(Handler handlerIn) {
handler = handlerIn;
}
@Override
public void run() {
while (wantStop == false) {
try {
sleep(50);
} catch (Exception e) {
// nothing
}
if (Math.abs(azimuth - northHeading) < 2 && Math.abs(heading - cacheHeading) < 2) {
continue;
}
lock = true;
Double diff = new Double(0);
Double diffAbs = new Double(0);
Double tempAzimuth = new Double(0);
Double tempHeading = new Double(0);
Double actualAzimuth = azimuth;
Double actualHeading = heading;
diff = northHeading - actualAzimuth;
diffAbs = Math.abs(northHeading - actualAzimuth);
if (diff < 0) {
diff = diff + 360;
} else if (diff >= 360) {
diff = diff - 360;
}
if (diff > 0 && diff <= 180) {
if (diffAbs > 5) {
tempAzimuth = actualAzimuth + 2;
} else if (diffAbs > 1) {
tempAzimuth = actualAzimuth + 1;
} else {
tempAzimuth = actualAzimuth;
}
} else if (diff > 180 && diff < 360) {
if (diffAbs > 5) {
tempAzimuth = actualAzimuth - 2;
} else if (diffAbs > 1) {
tempAzimuth = actualAzimuth - 1;
} else {
tempAzimuth = actualAzimuth;
}
} else {
tempAzimuth = actualAzimuth;
}
diff = cacheHeading - actualHeading;
diffAbs = Math.abs(cacheHeading - actualHeading);
if (diff < 0) {
diff = diff + 360;
} else if (diff >= 360) {
diff = diff - 360;
}
if (diff > 0 && diff <= 180) {
if (diffAbs > 5) {
tempHeading = actualHeading + 2;
} else if (diffAbs > 1) {
tempHeading = actualHeading + 1;
} else {
tempHeading = actualHeading;
}
} else if (diff > 180 && diff < 360) {
if (diffAbs > 5) {
tempHeading = actualHeading - 2;
} else if (diffAbs > 1) {
tempHeading = actualHeading - 1;
} else {
tempHeading = actualHeading;
}
} else {
tempHeading = actualHeading;
}
if (tempAzimuth >= 360) {
tempAzimuth = tempAzimuth - 360;
} else if (tempAzimuth < 0) {
tempAzimuth = tempAzimuth + 360;
}
if (tempHeading >= 360) {
tempHeading = tempHeading - 360;
} else if (tempHeading < 0) {
tempHeading = tempHeading + 360;
}
azimuth = tempAzimuth;
heading = tempHeading;
lock = false;
changeHandler.sendMessage(new Message());
}
}
}
@Override
protected void onDraw(Canvas canvas) {
if (lock == true) {
return;
}
if (drawing == true) {
return;
}
Double azimuthTemp = azimuth;
Double azimuthRelative = azimuthTemp - heading;
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;
drawing = true;
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(new Float(-(azimuthTemp)), canvasCenterX, canvasCenterY);
canvas.drawBitmap(compassRose, marginLeftTemp, marginTopTemp, null);
canvas.rotate(new Float(azimuthTemp), canvasCenterX, canvasCenterY);
marginLeftTemp = (getWidth() - compassArrowWidth) / 2;
marginTopTemp = (getHeight() - compassArrowHeight) / 2;
canvas.rotate(new Float(-(azimuthRelative)), canvasCenterX, canvasCenterY);
canvas.drawBitmap(compassArrow, marginLeftTemp, marginTopTemp, null);
canvas.rotate(new Float(azimuthRelative), canvasCenterX, canvasCenterY);
marginLeftTemp = (getWidth() - compassOverlayWidth) / 2;
marginTopTemp = (getHeight() - compassOverlayHeight) / 2;
canvas.drawBitmap(compassOverlay, marginLeftTemp, marginTopTemp, null);
canvas.setDrawFilter(remfil);
canvas.restore();
drawing = false;
}
@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;
}
}