package com.bosi.chineseclass.views.paint;
import java.util.ArrayList;
import com.firstpeople.paintpad.interfaces.PaintViewCallBack;
import com.firstpeople.paintpad.interfaces.Shapable;
import com.firstpeople.paintpad.interfaces.ShapesInterface;
import com.firstpeople.paintpad.interfaces.ToolInterface;
import com.firstpeople.paintpad.interfaces.UndoCommand;
import com.firstpeople.paintpad.painttools.Eraser;
import com.firstpeople.paintpad.painttools.PlainPen;
import com.firstpeople.paintpad.painttools.BlurPen;
import com.firstpeople.paintpad.painttools.EmbossPen;
import com.firstpeople.paintpad.shapes.Circle;
import com.firstpeople.paintpad.shapes.Curv;
import com.firstpeople.paintpad.shapes.Line;
import com.firstpeople.paintpad.shapes.Oval;
import com.firstpeople.paintpad.shapes.Rectangle;
import com.firstpeople.paintpad.shapes.Square;
import com.firstpeople.paintpad.utils.BitMapUtils;
import com.firstpeople.paintpad.utils.PaintConstants.ERASER_SIZE;
import com.firstpeople.paintpad.utils.PaintConstants.PEN_SIZE;
import com.firstpeople.paintpad.utils.PaintConstants.PEN_TYPE;
import com.firstpeople.paintpad.utils.PaintConstants.SHAP;
import static com.firstpeople.paintpad.utils.PaintConstants.*;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class PaintView extends View implements UndoCommand {
boolean canvasIsCreated = false;
private Canvas mCanvas = null;
private ToolInterface mCurrentPainter = null;
private Bitmap mBitmap = null;
private Bitmap mOrgBitMap = null;
private int mBitmapWidth = 0;
private int mBitmapHeight = 0;
private int mBackGroundColor = DEFAULT.BACKGROUND_COLOR;
private Paint mBitmapPaint = null;
private paintPadUndoStack mUndoStack = null;
private int mPenColor = DEFAULT.PEN_COLOR;;
private int mPenSize = PEN_SIZE.SIZE_1 ;
private int mEraserSize = ERASER_SIZE.SIZE_1;
int mPaintType = PEN_TYPE.PLAIN_PEN;
private PaintViewCallBack mCallBack = null;
private int mCurrentShapeType = 0;
private ShapesInterface mCurrentShape = null;
private Paint.Style mStyle = Paint.Style.STROKE;
private boolean isTouchUp = false;
private int mStackedSize = UNDO_STACK_SIZE;
public PaintView(Context context) {
this(context, null);
}
public PaintView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PaintView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
/**
* ��ʼ��
*/
private void init() {
mCanvas = new Canvas();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mUndoStack = new paintPadUndoStack(this, mStackedSize);
mPaintType = PEN_TYPE.PLAIN_PEN;
mCurrentShapeType = SHAP.CURV;
creatNewPen();
}
public void setCallBack(PaintViewCallBack callBack) {
mCallBack = callBack;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
isTouchUp = false;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mCanvas.setBitmap(mBitmap);
creatNewPen();
mCurrentPainter.touchDown(x, y);
mUndoStack.clearRedo();
mCallBack.onTouchDown();
invalidate();
break;
case MotionEvent.ACTION_MOVE:
mCurrentPainter.touchMove(x, y);
if (mPaintType == PEN_TYPE.ERASER) {
mCurrentPainter.draw(mCanvas);
}
invalidate();
break;
case MotionEvent.ACTION_UP:
if (mCurrentPainter.hasDraw()) {
mUndoStack.push(mCurrentPainter);
if (mCallBack != null) {
// ����undo\redo����ʵ
mCallBack.onHasDraw();
}
}
mCurrentPainter.touchUp(x, y);
mCurrentPainter.draw(mCanvas);
invalidate();
isTouchUp = true;
break;
}
return true;
}
/**
*/
private void setShape() {
if (mCurrentPainter instanceof Shapable) {
switch (mCurrentShapeType) {
case SHAP.CURV:
mCurrentShape = new Curv((Shapable) mCurrentPainter);
break;
case SHAP.LINE:
mCurrentShape = new Line((Shapable) mCurrentPainter);
break;
case SHAP.SQUARE:
mCurrentShape = new Square((Shapable) mCurrentPainter);
break;
case SHAP.RECT:
mCurrentShape = new Rectangle((Shapable) mCurrentPainter);
break;
case SHAP.CIRCLE:
mCurrentShape = new Circle((Shapable) mCurrentPainter);
break;
case SHAP.OVAL:
mCurrentShape = new Oval((Shapable) mCurrentPainter);
break;
default:
break;
}
((Shapable) mCurrentPainter).setShap(mCurrentShape);
}
}
@Override
public void onDraw(Canvas cv) {
cv.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
if (!isTouchUp) {
if (mPaintType != PEN_TYPE.ERASER) {
mCurrentPainter.draw(cv);
}
}
}
/**
*/
void creatNewPen() {
ToolInterface tool = null;
switch (mPaintType) {
case PEN_TYPE.PLAIN_PEN:
tool = new PlainPen(mPenSize, mPenColor, mStyle);
break;
case PEN_TYPE.ERASER:
tool = new Eraser(mEraserSize);
break;
case PEN_TYPE.BLUR:
tool = new BlurPen(mPenSize, mPenColor, mStyle);
break;
case PEN_TYPE.EMBOSS:
tool = new EmbossPen(mPenSize, mPenColor, mStyle);
break;
default:
break;
}
mCurrentPainter = tool;
setShape();
}
/**
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (!canvasIsCreated) {
mBitmapWidth = w;
mBitmapHeight = h;
creatCanvasBitmap(w, h);
canvasIsCreated = true;
}
}
/**
*/
public void setForeBitMap(Bitmap bitmap) {
if (bitmap != null) {
recycleMBitmap();
recycleOrgBitmap();
}
mBitmap = BitMapUtils.duplicateBitmap(bitmap, getWidth(), getHeight());
mOrgBitMap = BitMapUtils.duplicateBitmap(mBitmap);
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
bitmap = null;
}
invalidate();
}
/**
* ����ԭʼͼƬ
*/
private void recycleOrgBitmap() {
if (mOrgBitMap != null && !mOrgBitMap.isRecycled()) {
mOrgBitMap.recycle();
mOrgBitMap = null;
}
}
/**
* ����ͼƬ
*/
private void recycleMBitmap() {
if (mBitmap != null && !mBitmap.isRecycled()) {
mBitmap.recycle();
mBitmap = null;
}
}
/**
*/
public Bitmap getSnapShoot() {
setDrawingCacheEnabled(true);
buildDrawingCache(true);
Bitmap bitmap = getDrawingCache(true);
Bitmap bmp = BitMapUtils.duplicateBitmap(bitmap);
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
bitmap = null;
}
setDrawingCacheEnabled(false);
return bmp;
}
/**
*/
public void clearAll() {
recycleMBitmap();
recycleOrgBitmap();
mUndoStack.clearAll();
creatCanvasBitmap(mBitmapWidth, mBitmapHeight);
invalidate();
}
/**
*/
private void creatCanvasBitmap(int w, int h) {
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas.setBitmap(mBitmap);
}
/**
*/
public void setCurrentPainterType(int type) {
switch (type) {
case PEN_TYPE.BLUR:
case PEN_TYPE.PLAIN_PEN:
case PEN_TYPE.EMBOSS:
case PEN_TYPE.ERASER:
mPaintType = type;
break;
default:
mPaintType = PEN_TYPE.PLAIN_PEN;
break;
}
}
/**
* �ı䵱ǰ��Shap
*/
public void setCurrentShapType(int type) {
switch (type) {
case SHAP.CURV:
case SHAP.LINE:
case SHAP.RECT:
case SHAP.CIRCLE:
case SHAP.OVAL:
case SHAP.SQUARE:
mCurrentShapeType = type;
break;
default:
mCurrentShapeType = SHAP.CURV;
break;
}
}
public int getCurrentPainter() {
return mPaintType;
}
/**
*/
public void setPenSize(int size) {
mPenSize = size;
}
/**
*/
public void setEraserSize(int size) {
mEraserSize = size;
}
/**
*/
public int getPenSize() {
return mPenSize;
}
/**
*/
public void resetState() {
setCurrentPainterType(PEN_TYPE.PLAIN_PEN);
setPenColor(DEFAULT.PEN_COLOR);
setBackGroundColor(DEFAULT.BACKGROUND_COLOR);
mUndoStack.clearAll();
}
/**
*/
public void setBackGroundColor(int color) {
mBackGroundColor = color;
invalidate();
}
/**
*/
public int getBackGroundColor() {
return mBackGroundColor;
}
/**
*/
public void setPenColor(int color) {
mPenColor = color;
}
/**
*/
public int getPenColor() {
return mPenColor;
}
/**
*/
protected void setTempForeBitmap(Bitmap tempForeBitmap) {
if (null != tempForeBitmap) {
recycleMBitmap();
mBitmap = BitMapUtils.duplicateBitmap(tempForeBitmap);
if (null != mBitmap && null != mCanvas) {
mCanvas.setBitmap(mBitmap);
invalidate();
}
}
}
public void setPenStyle(Style style) {
mStyle = style;
}
public byte[] getBitmapArry() {
return BitMapUtils.bitampToByteArray(mBitmap);
}
@Override
public void undo() {
if (null != mUndoStack) {
mUndoStack.undo();
}
}
@Override
public void redo() {
if (null != mUndoStack) {
mUndoStack.redo();
}
}
@Override
public boolean canUndo() {
return mUndoStack.canUndo();
}
@Override
public boolean canRedo() {
return mUndoStack.canRedo();
}
@Override
public String toString() {
return "mPaint" + mCurrentPainter + mUndoStack;
}
/*
* ===================================�ڲ��ʼ=================================
*/
public class paintPadUndoStack {
private int m_stackSize = 0;
private PaintView mPaintView = null;
private ArrayList<ToolInterface> mUndoStack = new ArrayList<ToolInterface>();
private ArrayList<ToolInterface> mRedoStack = new ArrayList<ToolInterface>();
private ArrayList<ToolInterface> mOldActionStack = new ArrayList<ToolInterface>();
public paintPadUndoStack(PaintView paintView, int stackSize) {
mPaintView = paintView;
m_stackSize = stackSize;
}
/**
*/
public void push(ToolInterface penTool) {
if (null != penTool) {
if (mUndoStack.size() == m_stackSize && m_stackSize > 0) {
ToolInterface removedTool = mUndoStack.get(0);
mOldActionStack.add(removedTool);
mUndoStack.remove(0);
}
mUndoStack.add(penTool);
}
}
/**
*/
public void clearAll() {
mRedoStack.clear();
mUndoStack.clear();
mOldActionStack.clear();
}
/**
* undo
*/
public void undo() {
if (canUndo() && null != mPaintView) {
ToolInterface removedTool = mUndoStack
.get(mUndoStack.size() - 1);
mRedoStack.add(removedTool);
mUndoStack.remove(mUndoStack.size() - 1);
if (null != mOrgBitMap) {
// Set the temporary fore bitmap to canvas.
mPaintView.setTempForeBitmap(mPaintView.mOrgBitMap);
} else {
mPaintView.creatCanvasBitmap(mPaintView.mBitmapWidth,
mPaintView.mBitmapHeight);
}
Canvas canvas = mPaintView.mCanvas;
// First draw the removed tools from undo stack.
for (ToolInterface paintTool : mOldActionStack) {
paintTool.draw(canvas);
}
for (ToolInterface paintTool : mUndoStack) {
paintTool.draw(canvas);
}
mPaintView.invalidate();
}
}
/**
* redo
*/
public void redo() {
if (canRedo() && null != mPaintView) {
ToolInterface removedTool = mRedoStack
.get(mRedoStack.size() - 1);
mUndoStack.add(removedTool);
mRedoStack.remove(mRedoStack.size() - 1);
if (null != mOrgBitMap) {
// Set the temporary fore bitmap to canvas.
mPaintView.setTempForeBitmap(mPaintView.mOrgBitMap);
} else {
// Create a new bitmap and set to canvas.
mPaintView.creatCanvasBitmap(mPaintView.mBitmapWidth,
mPaintView.mBitmapHeight);
}
Canvas canvas = mPaintView.mCanvas;
// First draw the removed tools from undo stack.
for (ToolInterface sketchPadTool : mOldActionStack) {
sketchPadTool.draw(canvas);
}
for (ToolInterface sketchPadTool : mUndoStack) {
sketchPadTool.draw(canvas);
}
mPaintView.invalidate();
}
}
public boolean canUndo() {
return (mUndoStack.size() > 0);
}
public boolean canRedo() {
return (mRedoStack.size() > 0);
}
public void clearRedo() {
mRedoStack.clear();
}
@Override
public String toString() {
return "canUndo" + canUndo();
}
}
}