package com.csound.wizard.view.unit;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.csound.wizard.Const;
import com.csound.wizard.layout.UnitUtils;
import com.csound.wizard.layout.Units.StatefulUnit;
import com.csound.wizard.layout.param.ColorParam;
import com.csound.wizard.layout.param.Types.Range;
import com.csound.wizard.view.Listener;
import com.csound.wizard.view.ViewUtils;
import com.csound.wizard.view.GraphUtils.Circle;
import com.csound.wizard.view.GraphUtils.Rect;
import com.csound.wizard.view.Listener.OnPress;
import com.csound.wizard.view.Listener.OnSlide;
import com.csound.wizard.view.Listener.OnSlideListener;
import com.csound.wizard.view.Listener.SetSlide;
import com.csound.wizard.view.ViewUtils.OnMeasure;
public class Dial extends View implements StatefulUnit, OnSlideListener, SetSlide {
private static final float
coeffX = 0.007f,
coeffY = 0.007f;
private String mid;
private float
mx = 0,
my = 0;
private OnSlide mSlideListener = Listener.defaultOnSlide();
private OnPress mPressListener = Listener.defaultOnPress();
private Paint paint = new Paint();
private static final int desiredSize = Const.desiredCircleSize;
private Circle mCircle = new Circle();
private Rect mRect = new Rect();
private float value = 0.5f;
private ColorParam colors = new ColorParam();
private boolean isOutputOnlyMode = false;
private Range mRange;
public static float defaultState() {
return 0.5f;
}
public Dial(Context context, String id, float initVal, Range range, ColorParam colorParam) {
super(context);
ViewUtils.initPaint(paint);
colors = colorParam;
mid = id;
value = range.toRelative(initVal);
mRange = range;
}
public Dial(Context context, AttributeSet attrs) {
super(context, attrs);
ViewUtils.initPaint(attrs, paint);
}
@Override
public String getUnitId() {
return mid;
}
@Override
public double[] getUnitState() {
return UnitUtils.getUnitStateFloat(mRange.fromRelative(value));
}
@Override
public void setOnSlideListener(OnSlide listener) {
mSlideListener = listener;
}
public void setOnPressListener(OnPress listener) {
mPressListener = listener;
}
@Override
public void setSlide(float x) {
value = ViewUtils.withinBounds(mRange.toRelative(x));
invalidate();
}
public void setOutputOnlyMode() {
isOutputOnlyMode = true;
}
@Override
public void onDraw(Canvas canvas) {
mRect.setView(this);
mCircle.setCircle(mRect.getCenterX(), mRect.getCenterY(), 0.45f * mRect.getWidth());
if (colors.getBkgColor() != Color.TRANSPARENT) {
paint.setColor(colors.getBkgColor());
mCircle.drawFill(canvas, paint);
}
float angle = value;
paint.setColor(colors.getSndColor());
mCircle.drawRim(canvas, paint);
paint.setStyle(Style.FILL);
paint.setColor(colors.getFstColor());
paint.setAlpha(80);
mCircle.drawPie(canvas, 0.25f, angle, paint);
paint.setAlpha(255);
mCircle.drawDial(canvas, angle + 0.25f, paint);
paint.setStyle(Style.STROKE);
mCircle.drawArc(canvas, 0.25f, angle, paint);
}
@Override
public boolean performClick() {
// TODO Auto-generated method stub
return super.performClick();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isOutputOnlyMode) {
return true;
}
switch(event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
if (mCircle.contains(event.getX(0), event.getY(0))) {
this.performClick();
initCursor(event.getX(0), event.getY(0));
pressButton();
}
break;
case MotionEvent.ACTION_UP:
releaseButton();
break;
case MotionEvent.ACTION_MOVE:
updateValue(event.getX(0), event.getY(0));
break;
}
return true;
}
private void initCursor(float x, float y) {
mx = x; my = y;
}
private void updateValue(float x, float y) {
float newValue = updateOnDiff(x - mx, y - my);
if (Math.abs(value - newValue) > ViewUtils.EPS) {
mSlideListener.slide(mRange.fromRelative(newValue));
invalidate();
}
value = newValue;
initCursor(x, y);
}
private float updateOnDiff(float dx, float dy) {
if (Math.abs(dx) > Math.abs(dy)) {
return ViewUtils.withinBounds(value + coeffX * dx);
} else {
return ViewUtils.withinBounds(value - coeffY * dy);
}
}
private void pressButton() {
mPressListener.press();
}
private void releaseButton() {
mPressListener.release();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
ViewUtils.mkOnMeasure(widthMeasureSpec, heightMeasureSpec, desiredSize, desiredSize, onMeasureRunner);
}
private OnMeasure onMeasureRunner = new OnMeasure() {
@Override
public void apply(int width, int height) {
int size = Math.min(width, height);
mCircle.setCircle(size/2, size/2, size/2 - 10);
setMeasuredDimension(size, size);
}
};
}