package com.csound.wizard.view;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.SparseArray;
import android.view.View;
import com.csound.wizard.layout.param.ColorParam;
public class GraphUtils {
public interface OnToggleDraw {
public void active(Canvas c);
public void passive(Canvas c);
}
public static class ToggleDraw {
private OnToggleDraw mDraw;
private View mContxet;
private boolean mIsActive = false;
public ToggleDraw(OnToggleDraw draw) {
mDraw = draw;
}
void draw(Canvas c) {
if (mIsActive) {
mDraw.active(c);
} else {
mDraw.passive(c);
}
}
public void toggle() {
mIsActive = !mIsActive;
mContxet.invalidate();
}
public boolean isActive() {
return mIsActive;
}
}
public static class Circle {
private float mx, my, mrad;
public Circle() {
mx = 0; my = 0; mrad = 0;
}
public Circle(float x, float y, float rad) {
mx = x; my = y; mrad = rad;
}
public void setCircle(float x, float y, float rad) {
mx = x; my = y; mrad = rad;
}
public void draw(Canvas c, Paint p) {
c.drawCircle(mx, my, mrad, p);
}
public void drawArc(Canvas c, float startAngle, float sweepAngle, Paint p) {
int n = 25;
float da = Math.abs(sweepAngle) / n;
float k = Math.signum(sweepAngle);
float angle = startAngle;
float angle1;
for (int i = 0; i < n; i++) {
angle1 = angle + k * da;
c.drawLine(px(angle), py(angle), px(angle1), py(angle1), p);
angle = angle1;
}
}
public void drawRim(Canvas c, Paint p) {
p.setStyle(Style.STROKE);
draw(c, p);
}
public void drawFill(Canvas c, Paint p) {
p.setStyle(Style.FILL);
draw(c, p);
}
public void drawDial(Canvas c, float angle, Paint p) {
c.drawLine(mx, my, px(angle), py(angle), p);
}
public void drawPie(Canvas c, float startAngle, float sweepAngle, Paint p) {
int n = 25;
float da = Math.abs(sweepAngle) / n;
float k = Math.signum(sweepAngle);
float angle = startAngle;
float angle1;
Path path = new Path();
path.moveTo(mx, my);
path.lineTo(px(angle), py(angle));
for (int i = 0; i < n; i++) {
angle1 = angle + k * da;
path.lineTo(px(angle1), py(angle1));
angle = angle1;
}
path.lineTo(mx, my);
c.drawPath(path, p);
}
public void drawPlayButton(Canvas c, Paint p) {
drawRightPolyFill(c, 0, 3, 0.7f, p);
}
public void drawStopButton(Canvas c, Paint p) {
c.drawRect(new RectF(mx - mrad/2, my - mrad/2, mx + mrad/2, my + mrad/2), p);
}
public void drawRightPoly(Canvas c, float startAngle, int n, Paint paint) {
float da = 1.0f / n;
float angle = startAngle;
for (int i = 0; i < n; i++) {
c.drawLine(
px(angle), py(angle),
px(angle + da), py(angle + da),
paint);
angle += da;
}
}
public void drawRightPolyFill(Canvas c, float startAngle, int n, Paint paint) {
drawRightPolyFill(c, startAngle, n, 1.0f, paint);
}
public void drawRightPolyFill(Canvas c, float startAngle, int n, float scale, Paint paint) {
float da = 1.0f / n;
float angle = startAngle;
Path poly = new Path();
poly.moveTo(px(angle, scale), py(angle, scale));
for (int i = 0; i < n; i++) {
poly.lineTo(px(angle + da, scale), py(angle + da, scale));
angle += da;
}
c.drawPath(poly, paint);
}
private float px(float angle) {
return mx + (float) (mrad * Math.cos(2.0 * Math.PI * angle));
}
private float py(float angle) {
return my + (float) (mrad * Math.sin(2.0 * Math.PI * angle));
}
private float px(float angle, float scale) {
return mx + (float) (scale * mrad * Math.cos(2.0 * Math.PI * angle));
}
private float py(float angle, float scale) {
return my + (float) (scale * mrad * Math.sin(2.0 * Math.PI * angle));
}
public boolean contains(float x, float y) {
return Math.sqrt((mx - x) * (mx - x) + (my - y) * (my - y)) <= mrad;
}
}
public static class Rect {
private static final float
cornerArc = 15,
crossSize = 20;
private float mw, mh, mx, my;
private RectF mRectF;
public Rect() {
this(0, 0, 0, 0);
}
public Rect(float x, float y, float w, float h) {
mx = x; my = y; mw = w; mh = h;
mRectF = new RectF(mx, my, mx + mw, my + mh);
}
public void setRect(float x, float y, float w, float h) {
mx = x; my = y; mw = w; mh = h;
mRectF = new RectF(mx, my, mx + mw, my + mh);
}
public RectF getRectF() {
return mRectF;
}
public float getLeft() {
return mx;
}
public float getTop() {
return my;
}
public float getRight() {
return mx + mw;
}
public float getBottom() {
return my + mh;
}
public void setView(View v) {
setRect(
v.getPaddingLeft(),
v.getPaddingTop(),
v.getWidth() - v.getPaddingLeft() - v.getPaddingRight(),
v.getHeight() - v.getPaddingTop() - v.getPaddingBottom());
}
public boolean contains(float x, float y) {
return mRectF.contains(x, y);
}
public float relativeX(float x) {
return (x - mx) / mw;
}
public float relativeY(float y) {
return (y - my) / mh;
}
public void drawRounded(Canvas c, Paint p) {
p.setStyle(Style.FILL);
c.drawRoundRect(mRectF, cornerArc, cornerArc, p);
}
public void draw(Canvas c, Paint p) {
c.drawRect(mRectF, p);
}
public void drawRim(Canvas c, Paint p) {
p.setStyle(Style.STROKE);
draw(c, p);
}
public void drawRimRounded(Canvas c, Paint p) {
p.setStyle(Style.STROKE);
c.drawRoundRect(mRectF, cornerArc, cornerArc, p);
}
public void drawCross(Canvas c, float x, float y, Paint p) {
float cx = mx + mw * x;
float cy = my + mh * y;
float offsetX = 0, offsetY = 0;
if (cx < cornerArc || cx > mx + mw - cornerArc) {
offsetY = cornerArc;
}
if (cy < cornerArc || cy > my + mh - cornerArc) {
offsetX = cornerArc;
}
c.drawLine(cx, my + offsetY, cx, my + mh - offsetY, p);
c.drawLine(mx + offsetX, cy, mx + mw - offsetX, cy, p);
p.setStyle(Style.FILL);
new Circle(cx, cy, crossSize).draw(c, p);
}
public void drawSlider(Canvas c, float x, Paint p) {
p.setStyle(Style.FILL);
if (mw > mh) {
c.drawRoundRect(new RectF(mx, my, mx + x * mw, my + mh), cornerArc, cornerArc, p);
} else {
c.drawRoundRect(new RectF(mx, my + x * mh, mx + mw, my + mh), cornerArc, cornerArc, p);
}
}
public void drawStripesX(Canvas c, int n, Paint paint) {
float dx = mw / n;
float x = mx;
paint.setStyle(Style.FILL);
paint.setAlpha(60);
for (int i = 0; i < n; i = i + 2) {
c.drawRoundRect(new RectF(x, my, x + dx, my + mh), cornerArc, cornerArc, paint);
x += 2 * dx;
}
}
public void drawSelectedStripesX(Canvas c, int n, int selected, Paint paint) {
paint.setStyle(Style.STROKE);
paint.setAlpha(100);
float dx = mw / n;
float x = mx + selected * dx;
c.drawRoundRect(new RectF(x, my, x + dx, my + mh), cornerArc, cornerArc, paint);
}
public void drawStripesY(Canvas c, int n, Paint paint) {
float dy = mh / n;
float y = my;
paint.setStyle(Style.FILL);
paint.setAlpha(60);
for (int i = 0; i < n; i = i + 2) {
c.drawRoundRect(new RectF(mx, y, mx + mw, y + dy), cornerArc, cornerArc, paint);
y += 2 * dy;
}
}
public void drawSelectedStripesY(Canvas c, int n, int selected, Paint paint) {
paint.setStyle(Style.STROKE);
paint.setAlpha(100);
float dy = mh / n;
float y = my + selected * dy;
c.drawRoundRect(new RectF(mx, y, mx + mw, y + dy), cornerArc, cornerArc, paint);
}
public void drawChess(Canvas c, int nx, int ny, Paint paint) {
paint.setStyle(Style.FILL);
paint.setAlpha(60);
boolean isBlack = true;
float x, y;
float dx = mw / nx;
float dy = mh / ny;
for (int i = 0; i < nx; i++) {
for (int j = 0; j < ny; j++) {
if ((i + j) % 2 == 0) {
x = mx + i * dx;
y = my + j * dy;
c.drawRoundRect(new RectF(x, y, x + dx, y + dy), cornerArc, cornerArc, paint);
}
isBlack = !isBlack;
}
}
}
public void drawCell(Canvas c, int nx, int ny, int selectedX, int selectedY, Paint paint) {
paint.setStyle(Style.STROKE);
paint.setAlpha(100);
float dx = mw / nx;
float dy = mh / ny;
float x = mx + dx * selectedX;
float y = my + dy * selectedY;
c.drawRoundRect(new RectF(x, y, x + dx, y + dy), cornerArc, cornerArc, paint);
}
public void drawRound(Canvas c, float roundness, boolean leftTop, boolean rightTop, boolean rightBottom, boolean leftBottom, Paint paint) {
c.drawRoundRect(mRectF, roundness, roundness, paint);
if (!leftTop) {
c.drawRect(new RectF(mx, my, mx + roundness, my + roundness), paint);
}
if (!leftBottom) {
c.drawRect(new RectF(mx, my + mh - roundness, mx + roundness, my + mh), paint);
}
if (!rightTop) {
c.drawRect(new RectF(mx + mw - roundness, my, mx + mw, my + roundness), paint);
}
if (!rightBottom) {
c.drawRect(new RectF(mx + mw - roundness, my + mh - roundness, mx + mw, my + mh), paint);
}
}
public void drawRound(Canvas c, boolean leftTop, boolean rightTop, boolean rightBottom, boolean leftBottom, Paint paint) {
drawRound(c, cornerArc, leftTop, rightTop, rightBottom, leftBottom, paint);
}
public void drawChessLines(Canvas c, int nx, int ny, Paint paint) {
paint.setAlpha(150);
float
dx = mw / nx,
dy = mh / ny,
x = mx,
y = my;
for (int i = 0; i < nx - 1; i++) {
x += dx;
c.drawLine(x, my, x, my + mh, paint);
}
for (int i = 0; i < ny - 1; i++) {
y += dy;
c.drawLine(mx, y, mx + mw, y, paint);
}
paint.setAlpha(255);
}
public void drawSelectedTightSquare(Canvas c, int nx, int ny, int selectedX, int selectedY, Paint paint) {
paint.setStyle(Style.FILL);
float
dx = mw / nx,
dy = mh / ny;
Rect rect = new Rect(mx + selectedX * dx, my + selectedY * dy, dx, dy);
if (isCorner(nx, ny, selectedX, selectedY)) {
rect.drawRound(c,
isLeftTopCorner(nx, ny, selectedX, selectedY),
isRightTopCorner(nx, ny, selectedX, selectedY),
isRightBottomCorner(nx, ny, selectedX, selectedY),
isLeftBottomCorner(nx, ny, selectedX, selectedY),
paint);
} else {
rect.draw(c, paint);
}
}
private static boolean isCorner(int nx, int ny, int selectedX, int selectedY) {
return (
isLeftTopCorner(nx, ny, selectedX, selectedY) ||
isRightTopCorner(nx, ny, selectedX, selectedY) ||
isLeftBottomCorner(nx, ny, selectedX, selectedY) ||
isRightBottomCorner(nx, ny, selectedX, selectedY) );
}
private static boolean isLeftTopCorner(int nx, int ny, int selectedX, int selectedY) {
return isLeftCorner(nx, selectedX) && isTopCorner(ny, selectedY);
}
private static boolean isRightTopCorner(int nx, int ny, int selectedX, int selectedY) {
return isRightCorner(nx, selectedX) && isTopCorner(ny, selectedY);
}
private static boolean isLeftBottomCorner(int nx, int ny, int selectedX, int selectedY) {
return isLeftCorner(nx, selectedX) && isBottomCorner(ny, selectedY);
}
private static boolean isRightBottomCorner(int nx, int ny, int selectedX, int selectedY) {
return isRightCorner(nx, selectedX) && isBottomCorner(ny, selectedY);
}
private static boolean isLeftCorner(int nx, int selectedX) {
return selectedX == 0;
}
private static boolean isTopCorner(int ny, int selectedY) {
return selectedY == 0;
}
private static boolean isRightCorner(int nx, int selectedX) {
return selectedX == nx - 1;
}
private static boolean isBottomCorner(int ny, int selectedY) {
return selectedY == ny - 1;
}
public void drawChessLabels(Canvas c, int nx, int ny, List<String> labels, Paint paint) {
float x, y;
float dx = mw / nx;
float dy = mh / ny;
LabelsDrawer labelsDrawer = new LabelsDrawer(c, paint, labels);
for (int i = 0; i < ny; i++) {
for (int j = 0; j < nx; j++) {
x = mx + j * dx;
y = my + i * dy;
labelsDrawer.next(x + 0.5f * dx, y + 0.5f * dy);
}
}
labelsDrawer.close();
}
public void drawStripesXText(Canvas c, int n, Paint paint,
List<String> labels) {
float dx = mw / n;
float x = mx;
float y = my + mh * 0.5f;
LabelsDrawer labelsDrawer = new LabelsDrawer(c, paint, labels);
for (int i = 0; i < n; i++) {
labelsDrawer.next(x + 0.5f * dx, y);
x += dx;
}
labelsDrawer.close();
}
public void drawStripesYText(Canvas c, int n, Paint paint,
List<String> labels) {
float dy = mh / n;
float y = my;
float x = mx + mw * 0.5f;
LabelsDrawer labelsDrawer = new LabelsDrawer(c, paint, labels);
for (int i = 0; i < n; i++) {
labelsDrawer.next(x, y + 0.5f * dy);
y += dy;
}
labelsDrawer.close();
}
public boolean contains(PointF f) {
return contains(f.x, f.y);
}
public float getCenterX() {
return mx + mw * 0.5f;
}
public float getCenterY() {
return my + mh * 0.5f;
}
public float getWidth() {
return mw;
}
public float getHeight() {
return mh;
}
public void drawText(Canvas c, String text, Paint paint) {
paint.setStrokeWidth(1);
paint.setStyle(Style.FILL_AND_STROKE);
c.drawText(text, getCenterX(), getCenterY() + 10, paint);
paint.setStrokeWidth(ViewUtils.getDefaultStrokeWidth());
}
}
public static class TapBoard {
private Rect mRect;
int mnx, mny;
public TapBoard(Rect rect, int nx, int ny) {
mRect = rect;
mnx = nx; mny = ny;
}
public Rect getRect() {
return mRect;
}
public void setRect(float x, float y, float w, float h) {
mRect.setRect(x, y, w, h);
}
public void draw(Canvas c, Paint p, int selectedX, int selectedY) {
mRect.drawRim(c, p);
mRect.drawChessLines(c, mnx, mny, p);
p.setStyle(Style.FILL);
float dw = mRect.mw / mnx;
float dh = mRect.mh / mny;
float x = mRect.mx + selectedX * dw;
float y = mRect.my + selectedY * dh;
c.drawRect(x, y, x + dw, y + dh, p);
}
public void draw(Canvas c, Paint p, SparseArray<PointF> presses, int size, ColorParam colors) {
if (colors.getBkgColor() != Color.TRANSPARENT) {
p.setColor(colors.getBkgColor());
mRect.draw(c, p);
}
p.setColor(colors.getSndColor());
mRect.drawRim(c, p);
mRect.drawChessLines(c, mnx, mny, p);
p.setStyle(Style.FILL);
float dw = mRect.mw / mnx;
float dh = mRect.mh / mny;
p.setColor(colors.getFstColor());
for (int i = 0; i < size; i++) {
PointF point = presses.get(i);
if (point != null) {
int selectedX = ViewUtils.getCell(mnx, mRect.relativeX(point.x));
int selectedY = ViewUtils.getCell(mny, mRect.relativeY(point.y));
float x = mRect.mx + selectedX * dw;
float y = mRect.my + selectedY * dh;
c.drawRect(x, y, x + dw, y + dh, p);
}
}
}
public void draw(Canvas c, Paint p, boolean[] isOns,
ColorParam colors) {
p.setColor(colors.getSndColor());
mRect.drawRim(c, p);
mRect.drawChessLines(c, mnx, mny, p);
p.setStyle(Style.FILL);
float dw = mRect.mw / mnx;
float dh = mRect.mh / mny;
p.setColor(colors.getFstColor());
int k = 0;
int offset = 3;
for (int i = 0; i < mnx; i++) {
for (int j = 0; j < mny; j++) {
if (k < isOns.length) {
if (isOns[k]) {
float x = mRect.mx + i * dw;
float y = mRect.my + j * dh;
c.drawRect(x+ offset, y + offset, x + dw - offset, y + dh - offset, p);
}
k++;
} else {
return;
}
}
}
}
}
public static class Press {
public int x, y, finger;
public Press(int X, int Y, int Finger) {
x = X;
y = Y;
finger = Finger;
}
}
public static class TapPress {
private List<Press> mPress = new ArrayList<Press>();
public TapPress() {
}
public int getCount() {
return mPress.size();
}
public void press(int x, int y, int finger) {
mPress.add(new Press(x, y, finger));
}
public void release(int finger) {
Iterator<Press> it = mPress.iterator();
while (it.hasNext()) {
Press p = it.next();
if (p.finger == finger) {
it.remove();
}
}
}
public List<Press> getPressed() {
return mPress;
}
public Press getPressByFinger(int index) {
for (Press p : mPress) {
if (p.finger == index) {
return p;
}
}
return null;
}
}
public static class LabelsDrawer {
private Canvas mc;
private Paint mp;
private int count = 0;
private int size;
private List<String> mLabels;
public LabelsDrawer(Canvas c, Paint p, List<String> labels) {
mc = c;
mp = p;
mLabels = labels;
size = labels.size();
mp.setStrokeWidth(1);
mp.setStyle(Style.FILL_AND_STROKE);
}
public void next(float x, float y) {
if (count < size) {
mc.drawText(mLabels.get(count), x, y, mp);
count++;
}
}
public void close() {
mp.setStrokeWidth(ViewUtils.getDefaultStrokeWidth());
}
public boolean hasNext() {
return count < size;
}
}
}