package info.guardianproject.securereaderinterface.views;
import info.guardianproject.securereader.MediaDownloader.MediaDownloaderCallback;
import info.guardianproject.securereaderinterface.App;
import info.guardianproject.securereaderinterface.models.OnMediaOrientationListener;
import info.guardianproject.securereaderinterface.uiutil.UIHelpers;
//import java.io.File;
import info.guardianproject.iocipher.File;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.FrameLayout;
import android.widget.ImageView;
import info.guardianproject.securereaderinterface.R;
import com.tinymission.rss.MediaContent;
public class ImageMediaContentView extends FrameLayout implements MediaDownloaderCallback, OnTouchListener
{
private static final String TAG = "IMAGEVIEWERMATRIX";
// Image Matrix
Matrix matrix = new Matrix();
// Saved Matrix
Matrix savedMatrix = new Matrix();
// Initial Matrix
Matrix baseMatrix = new Matrix();
// We can be in one of these 3 states
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
static final float MAX_SCALE = 10f;
// For Zooming
float startFingerSpacing = 0f;
float endFingerSpacing = 0f;
PointF startFingerSpacingMidPoint = new PointF();
// For Dragging
PointF startPoint = new PointF();
Bitmap realBmp;
private float mMinScaleX;
private float mMinScaleY;
private ImageView mImageView;
private MediaContent mMediaContent;
private OnMediaOrientationListener mOrientationListener;
private boolean mEnableInteraction;
public ImageMediaContentView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
initView(context);
}
public ImageMediaContentView(Context context, AttributeSet attrs)
{
super(context, attrs);
initView(context);
}
public ImageMediaContentView(Context context)
{
super(context);
initView(context);
}
private void initView(Context context)
{
View.inflate(context, R.layout.image_view, this);
mImageView = (ImageView) findViewById(R.id.content);
}
public void setMediaContent(MediaContent mediaContent, boolean enableInteraction)
{
mMediaContent = mediaContent;
mEnableInteraction = enableInteraction;
App.getInstance().socialReader.loadMediaContent(mMediaContent, this);
}
/**
* Sets a listener that will be notified when media has been downloaded and
* it is known whether this media is in landscape or portrait mode.
*
* @param listener
*/
public void setOnMediaOrientationListener(OnMediaOrientationListener listener)
{
this.mOrientationListener = listener;
}
@Override
public boolean onTouch(View v, MotionEvent event)
{
ImageView view = (ImageView) v;
switch (event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
// Save the Start point. We have a single finger so it is drag
startPoint.set(event.getX(), event.getY());
mode = DRAG;
Log.d(TAG, "mode=DRAG");
break;
case MotionEvent.ACTION_POINTER_DOWN:
// Get the spacing of the fingers, 2 fingers
float sx = event.getX(0) - event.getX(1);
float sy = event.getY(0) - event.getY(1);
startFingerSpacing = (float) Math.sqrt(sx * sx + sy * sy);
Log.d(TAG, "Start Finger Spacing=" + startFingerSpacing);
if (startFingerSpacing > 10f)
{
float xsum = event.getX(0) + event.getX(1);
float ysum = event.getY(0) + event.getY(1);
startFingerSpacingMidPoint.set(xsum / 2, ysum / 2);
mode = ZOOM;
Log.d(TAG, "mode=ZOOM");
}
break;
case MotionEvent.ACTION_UP:
// Nothing
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
Log.d(TAG, "mode=NONE");
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG)
{
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - startPoint.x, event.getY() - startPoint.y);
view.setImageMatrix(matrix);
putOnScreen();
}
else if (mode == ZOOM)
{
// Get the spacing of the fingers, 2 fingers
float ex = event.getX(0) - event.getX(1);
float ey = event.getY(0) - event.getY(1);
endFingerSpacing = (float) Math.sqrt(ex * ex + ey * ey);
Log.d(TAG, "End Finger Spacing=" + endFingerSpacing);
if (endFingerSpacing > 10f)
{
matrix.set(savedMatrix);
// Ratio of spacing.. If it was 5 and goes to 10 the image
// is 2x as big
float scale = endFingerSpacing / startFingerSpacing;
// Scale from the midpoint
matrix.postScale(scale, scale, startFingerSpacingMidPoint.x, startFingerSpacingMidPoint.y);
float[] matrixValues = new float[9];
matrix.getValues(matrixValues);
Log.v(TAG, "Total Scale: " + matrixValues[0]);
Log.v(TAG, "" + matrixValues[0] + " " + matrixValues[1] + " " + matrixValues[2] + " " + matrixValues[3] + " " + matrixValues[4] + " "
+ matrixValues[5] + " " + matrixValues[6] + " " + matrixValues[7] + " " + matrixValues[8]);
if (matrixValues[0] > MAX_SCALE)
{
matrix.set(savedMatrix);
}
else if (matrixValues[Matrix.MSCALE_X] < mMinScaleX || matrixValues[Matrix.MSCALE_Y] < mMinScaleY)
{
matrix.set(null);
}
view.setImageMatrix(matrix);
putOnScreen();
}
}
break;
}
return true; // indicate event was handled
}
public void putOnScreen()
{
// Get Rectangle of Tranformed Image
Matrix currentDisplayMatrix = new Matrix();
currentDisplayMatrix.set(baseMatrix);
currentDisplayMatrix.postConcat(matrix);
RectF theRect = new RectF(0, 0, realBmp.getWidth(), realBmp.getHeight());
currentDisplayMatrix.mapRect(theRect);
Log.v(TAG, theRect.width() + " " + theRect.height());
float deltaX = 0, deltaY = 0;
if (theRect.width() < mImageView.getWidth())
{
deltaX = (mImageView.getWidth() - theRect.width()) / 2 - theRect.left;
}
else if (theRect.left > 0)
{
deltaX = -theRect.left;
deltaX = Math.min(deltaX, 0);
}
else if (theRect.right < mImageView.getWidth())
{
deltaX = mImageView.getWidth() - theRect.right;
}
if (theRect.height() < mImageView.getHeight())
{
deltaY = (mImageView.getHeight() - theRect.height()) / 2 - theRect.top;
}
else if (theRect.top > 0)
{
deltaY = -theRect.top;
deltaY = Math.min(deltaY, 0);
}
else if (theRect.bottom < mImageView.getHeight())
{
deltaY = mImageView.getHeight() - theRect.bottom;
}
Log.v(TAG, "Deltas:" + deltaX + " " + deltaY);
currentDisplayMatrix.postTranslate(deltaX, deltaY);
mImageView.setImageMatrix(currentDisplayMatrix);
mImageView.invalidate();
}
@Override
public void mediaDownloaded(final File mediaFile)
{
realBmp = UIHelpers.scaleToMaxGLSize(getContext(), mediaFile, 0, 0);
rescaleImage();
if (mOrientationListener != null)
{
boolean isPortrait = (realBmp != null) && (realBmp.getHeight() > realBmp.getWidth());
mOrientationListener.onMediaOrientation(ImageMediaContentView.this, isPortrait ? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
: ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
{
super.onLayout(changed, left, top, right, bottom);
if (changed)
rescaleImage();
}
private void rescaleImage()
{
int width = mImageView.getWidth();
int height = mImageView.getHeight();
if (width == 0 || height == 0 || realBmp == null)
return;
matrix = new Matrix();
// Get the image's rect
RectF drawableRect = new RectF(0, 0, realBmp.getWidth(), realBmp.getHeight());
// Get the image view's rect
RectF viewRect = new RectF(0, 0, mImageView.getWidth(), mImageView.getHeight());
// draw the image in the view
matrix.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.CENTER);
float[] values = new float[9];
matrix.getValues(values);
float scaleX = values[Matrix.MSCALE_X];
float scaleY = values[Matrix.MSCALE_Y];
mMinScaleX = scaleX;
mMinScaleY = scaleY;
matrix.set(null);
matrix.setScale(scaleX, scaleY);
Log.v(TAG, "Display Width: " + width);
Log.v(TAG, "Display Height: " + height);
Log.v(TAG, "BMP Width: " + realBmp.getWidth());
Log.v(TAG, "BMP Height: " + realBmp.getHeight());
mImageView.setImageBitmap(realBmp);
mImageView.setImageMatrix(matrix);
baseMatrix.set(matrix);
savedMatrix.set(matrix);
matrix.set(null);
if (mEnableInteraction)
mImageView.setOnTouchListener(this);
else
mImageView.setOnTouchListener(null);
putOnScreen();
}
@Override
public void mediaDownloadedNonVFS(java.io.File mediaFile) {
// TODO Auto-generated method stub
// Not being used for image content at the moment
}
// public void onClick(View v)
// {
// if (v == zoomIn)
// {
// float scale = 1.5f;
//
// PointF midpoint = new PointF(view.getWidth() / 2, view.getHeight() / 2);
// matrix.postScale(scale, scale, midpoint.x, midpoint.y);
// view.setImageMatrix(matrix);
// putOnScreen();
//
// }
// else if (v == zoomOut)
// {
// float scale = 0.75f;
//
// PointF midpoint = new PointF(view.getWidth() / 2, view.getHeight() / 2);
// matrix.postScale(scale, scale, midpoint.x, midpoint.y);
// view.setImageMatrix(matrix);
// putOnScreen();
//
// }
// }
}