package com.aviary.android.feather.widget;
import it.sephiroth.android.library.imagezoom.ImageViewTouch;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import com.aviary.android.feather.library.graphics.drawable.IBitmapDrawable;
// TODO: Auto-generated Javadoc
/**
* The Class ImageViewTouchAndDraw.
*/
public class ImageViewTouchAndDraw extends ImageViewTouch {
/**
* The Enum TouchMode.
*/
public static enum TouchMode {
/** The IMAGE. */
IMAGE,
/** The DRAW. */
DRAW
};
/**
* The listener interface for receiving onDrawStart events. The class that is interested in processing a onDrawStart event
* implements this interface, and the object created with that class is registered with a component using the component's
* <code>addOnDrawStartListener<code> method. When
* the onDrawStart event occurs, that object's appropriate
* method is invoked.
*
* @see OnDrawStartEvent
*/
public static interface OnDrawStartListener {
/**
* On draw start.
*/
void onDrawStart();
};
public static interface OnDrawPathListener {
void onStart();
void onMoveTo( float x, float y );
void onLineTo( float x, float y );
void onQuadTo( float x, float y, float x1, float y1 );
void onEnd();
}
/** The m paint. */
protected Paint mPaint;
/** The tmp path. */
protected Path tmpPath = new Path();
/** The m canvas. */
protected Canvas mCanvas;
/** The m touch mode. */
protected TouchMode mTouchMode = TouchMode.DRAW;
/** The m y. */
protected float mX, mY;
/** The m identity matrix. */
protected Matrix mIdentityMatrix = new Matrix();
/** The m inverted matrix. */
protected Matrix mInvertedMatrix = new Matrix();
/** The m copy. */
protected Bitmap mCopy;
/** The Constant TOUCH_TOLERANCE. */
protected static final float TOUCH_TOLERANCE = 4;
/** The m draw listener. */
private OnDrawStartListener mDrawListener;
private OnDrawPathListener mDrawPathListener;
/**
* Instantiates a new image view touch and draw.
*
* @param context
* the context
* @param attrs
* the attrs
*/
public ImageViewTouchAndDraw( Context context, AttributeSet attrs ) {
super( context, attrs );
}
/**
* Sets the on draw start listener.
*
* @param listener
* the new on draw start listener
*/
public void setOnDrawStartListener( OnDrawStartListener listener ) {
mDrawListener = listener;
}
public void setOnDrawPathListener( OnDrawPathListener listener ) {
mDrawPathListener = listener;
}
/*
* (non-Javadoc)
*
* @see it.sephiroth.android.library.imagezoom.ImageViewTouch#init()
*/
@Override
protected void init() {
super.init();
mPaint = new Paint( Paint.ANTI_ALIAS_FLAG );
mPaint.setDither( true );
mPaint.setFilterBitmap( false );
mPaint.setColor( 0xFFFF0000 );
mPaint.setStyle( Paint.Style.STROKE );
mPaint.setStrokeJoin( Paint.Join.ROUND );
mPaint.setStrokeCap( Paint.Cap.ROUND );
mPaint.setStrokeWidth( 10.0f );
tmpPath = new Path();
}
/**
* Gets the draw mode.
*
* @return the draw mode
*/
public TouchMode getDrawMode() {
return mTouchMode;
}
/**
* Sets the draw mode.
*
* @param mode
* the new draw mode
*/
public void setDrawMode( TouchMode mode ) {
if ( mode != mTouchMode ) {
mTouchMode = mode;
onDrawModeChanged();
}
}
/**
* On draw mode changed.
*/
protected void onDrawModeChanged() {
if ( mTouchMode == TouchMode.DRAW ) {
Matrix m1 = new Matrix( getImageMatrix() );
mInvertedMatrix.reset();
float[] v1 = getMatrixValues( m1 );
m1.invert( m1 );
float[] v2 = getMatrixValues( m1 );
mInvertedMatrix.postTranslate( -v1[Matrix.MTRANS_X], -v1[Matrix.MTRANS_Y] );
mInvertedMatrix.postScale( v2[Matrix.MSCALE_X], v2[Matrix.MSCALE_Y] );
mCanvas.setMatrix( mInvertedMatrix );
}
}
/**
* Gets the paint.
*
* @return the paint
*/
public Paint getPaint() {
return mPaint;
}
/**
* Sets the paint.
*
* @param paint
* the new paint
*/
public void setPaint( Paint paint ) {
mPaint.set( paint );
}
/*
* (non-Javadoc)
*
* @see android.widget.ImageView#onDraw(android.graphics.Canvas)
*/
@Override
protected void onDraw( Canvas canvas ) {
super.onDraw( canvas );
// canvas.drawPath( tmpPath, mPaint );
if ( mCopy != null ) {
final int saveCount = canvas.getSaveCount();
canvas.save();
canvas.drawBitmap( mCopy, getImageMatrix(), null );
canvas.restoreToCount( saveCount );
}
}
/**
* Commit.
*
* @param canvas
* the canvas
*/
public void commit( Canvas canvas ) {
canvas.drawBitmap( ( (IBitmapDrawable) getDrawable() ).getBitmap(), new Matrix(), null );
canvas.drawBitmap( mCopy, new Matrix(), null );
}
/*
* (non-Javadoc)
*
* @see it.sephiroth.android.library.imagezoom.ImageViewTouch#onBitmapChanged(android.graphics.drawable.Drawable)
*/
@Override
protected void onBitmapChanged( Drawable drawable ) {
super.onBitmapChanged( drawable );
if ( mCopy != null ) {
mCopy.recycle();
mCopy = null;
}
if ( drawable != null && ( drawable instanceof IBitmapDrawable ) ) {
final Bitmap bitmap = ( (IBitmapDrawable) drawable ).getBitmap();
mCopy = Bitmap.createBitmap( bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888 );
mCanvas = new Canvas( mCopy );
mCanvas.drawColor( 0 );
onDrawModeChanged();
}
}
/**
* Touch_start.
*
* @param x
* the x
* @param y
* the y
*/
private void touch_start( float x, float y ) {
tmpPath.reset();
tmpPath.moveTo( x, y );
mX = x;
mY = y;
if ( mDrawListener != null ) mDrawListener.onDrawStart();
if ( mDrawPathListener != null ) {
mDrawPathListener.onStart();
float[] pts = new float[] { x, y };
mInvertedMatrix.mapPoints( pts );
mDrawPathListener.onMoveTo( pts[0], pts[1] );
}
}
/**
* Touch_move.
*
* @param x
* the x
* @param y
* the y
*/
private void touch_move( float x, float y ) {
float dx = Math.abs( x - mX );
float dy = Math.abs( y - mY );
if ( dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE ) {
float x1 = ( x + mX ) / 2;
float y1 = ( y + mY ) / 2;
tmpPath.quadTo( mX, mY, x1, y1 );
mCanvas.drawPath( tmpPath, mPaint );
tmpPath.reset();
tmpPath.moveTo( x1, y1 );
if ( mDrawPathListener != null ) {
float[] pts = new float[] { mX, mY, x1, y1 };
mInvertedMatrix.mapPoints( pts );
mDrawPathListener.onQuadTo( pts[0], pts[1], pts[2], pts[3] );
}
mX = x;
mY = y;
}
}
/**
* Touch_up.
*/
private void touch_up() {
// mCanvas.drawPath( tmpPath, mPaint );
tmpPath.reset();
if ( mDrawPathListener != null ) {
mDrawPathListener.onEnd();
}
}
/**
* Gets the matrix values.
*
* @param m
* the m
* @return the matrix values
*/
public static float[] getMatrixValues( Matrix m ) {
float[] values = new float[9];
m.getValues( values );
return values;
}
/*
* (non-Javadoc)
*
* @see it.sephiroth.android.library.imagezoom.ImageViewTouch#onTouchEvent(android.view.MotionEvent)
*/
@Override
public boolean onTouchEvent( MotionEvent event ) {
if ( mTouchMode == TouchMode.DRAW && event.getPointerCount() == 1 ) {
float x = event.getX();
float y = event.getY();
switch ( event.getAction() ) {
case MotionEvent.ACTION_DOWN:
touch_start( x, y );
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move( x, y );
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
} else {
if ( mTouchMode == TouchMode.IMAGE )
return super.onTouchEvent( event );
else
return false;
}
}
/**
* Gets the overlay bitmap.
*
* @return the overlay bitmap
*/
public Bitmap getOverlayBitmap() {
return mCopy;
}
}