334 lines
8.4 KiB
C#
334 lines
8.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
using Android.App;
|
|
using Android.Content;
|
|
using Android.Content.PM;
|
|
using Android.Graphics;
|
|
using Android.Graphics.Drawables;
|
|
using Android.OS;
|
|
using Android.Runtime;
|
|
using Android.Util;
|
|
using Android.Views;
|
|
using Android.Widget;
|
|
using keepass2android;
|
|
using KeePassLib;
|
|
using KeePassLib.Utility;
|
|
using Object = Java.Lang.Object;
|
|
|
|
namespace keepass2android
|
|
{
|
|
|
|
public class ZoomableImageView : ImageView
|
|
{
|
|
|
|
private class ScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener
|
|
{
|
|
|
|
private ZoomableImageView parent;
|
|
|
|
public ScaleListener(ZoomableImageView parent)
|
|
{
|
|
this.parent = parent;
|
|
}
|
|
|
|
public override bool OnScaleBegin(ScaleGestureDetector detector)
|
|
{
|
|
parent.mode = ZOOM;
|
|
return true;
|
|
}
|
|
|
|
|
|
public override bool OnScale(ScaleGestureDetector detector)
|
|
{
|
|
float scaleFactor = detector.ScaleFactor;
|
|
float newScale = parent.saveScale * scaleFactor;
|
|
if (newScale < parent.maxScale && newScale > parent.minScale)
|
|
{
|
|
parent.saveScale = newScale;
|
|
float width = parent.Width;
|
|
float height = parent.Height;
|
|
parent.right = (parent.originalBitmapWidth * parent.saveScale) - width;
|
|
parent.bottom = (parent.originalBitmapHeight * parent.saveScale) - height;
|
|
|
|
float scaledBitmapWidth = parent.originalBitmapWidth * parent.saveScale;
|
|
float scaledBitmapHeight = parent.originalBitmapHeight * parent.saveScale;
|
|
|
|
if (scaledBitmapWidth <= width || scaledBitmapHeight <= height)
|
|
{
|
|
parent.matrix.PostScale(scaleFactor, scaleFactor, width / 2, height / 2);
|
|
}
|
|
else
|
|
{
|
|
parent.matrix.PostScale(scaleFactor, scaleFactor, detector.FocusX, detector.FocusY);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
const int NONE = 0;
|
|
const int DRAG = 1;
|
|
const int ZOOM = 2;
|
|
const int CLICK = 3;
|
|
|
|
private int mode = NONE;
|
|
|
|
private Matrix matrix = new Matrix();
|
|
|
|
private PointF last = new PointF();
|
|
private PointF start = new PointF();
|
|
private float minScale = 1.0f;
|
|
private float maxScale = 100.0f;
|
|
private float[] m;
|
|
|
|
private float redundantXSpace, redundantYSpace;
|
|
private float saveScale = 1f;
|
|
private float right, bottom, originalBitmapWidth, originalBitmapHeight;
|
|
|
|
private ScaleGestureDetector mScaleDetector;
|
|
protected ZoomableImageView(IntPtr javaReference, JniHandleOwnership transfer)
|
|
: base(javaReference, transfer)
|
|
{
|
|
}
|
|
public ZoomableImageView(Context context)
|
|
: base(context)
|
|
{
|
|
|
|
init(context);
|
|
}
|
|
|
|
public ZoomableImageView(Context context, IAttributeSet attrs)
|
|
: base(context, attrs)
|
|
{
|
|
init(context);
|
|
}
|
|
|
|
public ZoomableImageView(Context context, IAttributeSet attrs, int defStyleAttr)
|
|
: base(context, attrs, defStyleAttr)
|
|
{
|
|
init(context);
|
|
}
|
|
|
|
private void init(Context context)
|
|
{
|
|
base.Clickable = true;
|
|
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener(this));
|
|
m = new float[9];
|
|
ImageMatrix = matrix;
|
|
SetScaleType(ScaleType.Matrix);
|
|
}
|
|
|
|
|
|
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
|
{
|
|
base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
|
|
int bmHeight = getBmHeight();
|
|
int bmWidth = getBmWidth();
|
|
|
|
float width = MeasuredWidth;
|
|
float height = MeasuredHeight;
|
|
//Fit to screen.
|
|
float scale = width > height ? height / bmHeight : width / bmWidth;
|
|
|
|
matrix.SetScale(scale, scale);
|
|
saveScale = 1f;
|
|
|
|
originalBitmapWidth = scale * bmWidth;
|
|
originalBitmapHeight = scale * bmHeight;
|
|
|
|
// Center the image
|
|
redundantYSpace = (height - originalBitmapHeight);
|
|
redundantXSpace = (width - originalBitmapWidth);
|
|
|
|
matrix.PostTranslate(redundantXSpace / 2, redundantYSpace / 2);
|
|
|
|
ImageMatrix = matrix;
|
|
}
|
|
|
|
|
|
public override bool OnTouchEvent(MotionEvent event_)
|
|
{
|
|
mScaleDetector.OnTouchEvent(event_);
|
|
|
|
matrix.GetValues(m);
|
|
float x = m[Matrix.MtransX];
|
|
float y = m[Matrix.MtransY];
|
|
PointF curr = new PointF(event_.GetX(), event_.GetY());
|
|
Log.Debug("TOUCH", event_.Action.ToString(), " mode=" + mode);
|
|
switch (event_.Action)
|
|
{
|
|
//when one finger is touching
|
|
//set the mode to DRAG
|
|
case MotionEventActions.Down:
|
|
last.Set(event_.GetX(), event_.GetY());
|
|
start.Set(last);
|
|
mode = DRAG;
|
|
break;
|
|
//when two fingers are touching
|
|
//set the mode to ZOOM
|
|
case MotionEventActions.Pointer2Down:
|
|
case MotionEventActions.PointerDown:
|
|
last.Set(event_.GetX(), event_.GetY());
|
|
start.Set(last);
|
|
mode = ZOOM;
|
|
break;
|
|
//when a finger moves
|
|
//If mode is applicable move image
|
|
case MotionEventActions.Move:
|
|
//if the mode is ZOOM or
|
|
//if the mode is DRAG and already zoomed
|
|
if (mode == ZOOM || (mode == DRAG && saveScale > minScale))
|
|
{
|
|
float deltaX = curr.X - last.X;// x difference
|
|
float deltaY = curr.Y - last.Y;// y difference
|
|
float scaleWidth = (float)System.Math.Round(originalBitmapWidth * saveScale);// width after applying current scale
|
|
float scaleHeight = (float)System.Math.Round(originalBitmapHeight * saveScale);// height after applying current scale
|
|
|
|
bool limitX = false;
|
|
bool limitY = false;
|
|
|
|
//if scaleWidth is smaller than the views width
|
|
//in other words if the image width fits in the view
|
|
//limit left and right movement
|
|
if (scaleWidth < Width && scaleHeight < Height)
|
|
{
|
|
// don't do anything
|
|
}
|
|
else if (scaleWidth < Width)
|
|
{
|
|
deltaX = 0;
|
|
limitY = true;
|
|
}
|
|
//if scaleHeight is smaller than the views height
|
|
//in other words if the image height fits in the view
|
|
//limit up and down movement
|
|
else if (scaleHeight < Height)
|
|
{
|
|
deltaY = 0;
|
|
limitX = true;
|
|
}
|
|
//if the image doesnt fit in the width or height
|
|
//limit both up and down and left and right
|
|
else
|
|
{
|
|
limitX = true;
|
|
limitY = true;
|
|
}
|
|
|
|
if (limitY)
|
|
{
|
|
if (y + deltaY > 0)
|
|
{
|
|
deltaY = -y;
|
|
}
|
|
else if (y + deltaY < -bottom)
|
|
{
|
|
deltaY = -(y + bottom);
|
|
}
|
|
|
|
}
|
|
|
|
if (limitX)
|
|
{
|
|
if (x + deltaX > 0)
|
|
{
|
|
deltaX = -x;
|
|
}
|
|
else if (x + deltaX < -right)
|
|
{
|
|
deltaX = -(x + right);
|
|
}
|
|
|
|
}
|
|
//move the image with the matrix
|
|
matrix.PostTranslate(deltaX, deltaY);
|
|
//set the last touch location to the current
|
|
last.Set(curr.X, curr.Y);
|
|
}
|
|
break;
|
|
//first finger is lifted
|
|
case MotionEventActions.Up:
|
|
mode = NONE;
|
|
int xDiff = (int)System.Math.Abs(curr.X - start.X);
|
|
int yDiff = (int)System.Math.Abs(curr.Y - start.Y);
|
|
if (xDiff < CLICK && yDiff < CLICK)
|
|
PerformClick();
|
|
break;
|
|
// second finger is lifted
|
|
case MotionEventActions.Pointer2Up:
|
|
case MotionEventActions.PointerUp:
|
|
mode = NONE;
|
|
break;
|
|
}
|
|
ImageMatrix = matrix;
|
|
Invalidate();
|
|
return true;
|
|
}
|
|
|
|
public void setMaxZoom(float x)
|
|
{
|
|
maxScale = x;
|
|
}
|
|
|
|
private int getBmWidth()
|
|
{
|
|
Drawable drawable = Drawable;
|
|
if (drawable != null)
|
|
{
|
|
return drawable.IntrinsicWidth;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
private int getBmHeight()
|
|
{
|
|
Drawable drawable = Drawable;
|
|
if (drawable != null)
|
|
{
|
|
return drawable.IntrinsicHeight;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
[Activity(Label = "@string/app_name", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden,
|
|
Theme = "@style/Kp2aTheme_ActionBar")]
|
|
public class ImageViewActivity : LockCloseActivity
|
|
{
|
|
private ActivityDesign _activityDesign;
|
|
|
|
public ImageViewActivity()
|
|
{
|
|
_activityDesign = new ActivityDesign(this);
|
|
}
|
|
|
|
protected override void OnResume()
|
|
{
|
|
base.OnResume();
|
|
_activityDesign.ReapplyTheme();
|
|
}
|
|
|
|
protected override void OnCreate(Bundle savedInstanceState)
|
|
{
|
|
_activityDesign.ApplyTheme();
|
|
base.OnCreate(savedInstanceState);
|
|
SetContentView(Resource.Layout.ImageViewActivity);
|
|
|
|
ElementAndDatabaseId fullId = new ElementAndDatabaseId(Intent.GetStringExtra("EntryId"));
|
|
|
|
var uuid = new PwUuid(MemUtil.HexStringToByteArray(fullId.ElementIdString));
|
|
string key = Intent.GetStringExtra("EntryKey");
|
|
var binary = App.Kp2a.GetDatabase(fullId.DatabaseId).EntriesById[uuid].Binaries.Get(key);
|
|
SupportActionBar.Title = key;
|
|
byte[] pbdata = binary.ReadData();
|
|
|
|
var bmp = BitmapFactory.DecodeByteArray(pbdata,0,pbdata.Length);
|
|
|
|
FindViewById<ImageView>(Resource.Id.imageView).SetImageBitmap(bmp);
|
|
|
|
}
|
|
}
|
|
} |