/*
* Copyright (C) 2012 Simon Robinson
*
* This file is part of Com-Me.
*
* Com-Me is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Com-Me is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
* Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Com-Me.
* If not, see <http://www.gnu.org/licenses/>.
*/
package ac.robinson.mediatablet.view;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.ListIterator;
import java.util.Random;
import java.util.UUID;
import java.util.Vector;
import ac.robinson.mediatablet.MediaTablet;
import ac.robinson.mediatablet.R;
import ac.robinson.mediatablet.provider.HomesteadItem;
import ac.robinson.mediatablet.provider.HomesteadManager;
import ac.robinson.util.BitmapUtilities;
import ac.robinson.util.DebugUtilities;
import ac.robinson.util.ImageCacheUtilities;
import ac.robinson.util.UIUtilities;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.LightingColorFilter;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.SoundEffectConstants;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import com.larvalabs.svgandroid.SVG;
import com.larvalabs.svgandroid.SVGParser;
public class HomesteadSurfaceView extends SurfaceView implements SurfaceHolder.Callback, View.OnTouchListener {
private HomesteadTouchListener mTouchListener;
private boolean mAddMode = false;
// for drawing the correct panorama images
private final int IMAGES_TO_DRAW = 6; // *caution* odd numbers change home alignment (like changing panorama image)
private final boolean DRAW_DEBUG_DATA = false;
private boolean mPanoramaLoaded;
private int mPanoramaImageIndex;
private float mX, mY, mCurrentDrawX, mScreenCentreX, mCurrentTouchX, mCurrentTouchY;
private int mPanoramaImageSize;
private float mPanoramaHalfImageSize;
private int mPanoramaImageCount;
private int mScreenWidth, mScreenHeight, mScreenHalfWidth, mBitmapWidth, mBitmapHeight;
private Paint mPaint = BitmapUtilities.getPaint(Color.BLACK, 1); // debugging
// was SoftReference, but it is cleared too aggressively - now we clear manually when out of sight
private static final HashMap<String, LoadingBitmap> mTileCache = new HashMap<String, LoadingBitmap>();
private static final ArrayList<String> mTilesToLoad = new ArrayList<String>();
private SurfaceDrawThread mDrawThread;
private SurfaceLoadThread mLoadThread;
public static final int TRANSITION_STARTING = 0;
public static final int TRANSITION_RUNNING = 1;
public static final int TRANSITION_NONE = 2;
// the default icons to show when fading in images
private LoadingBitmap mPanoramaLoadingIcon;
private LoadingBitmap mHomesteadLoadingIcon;
// for drawing and tracking the homesteads
private final Vector<HomesteadItem> mHomesteadItems = new Vector<HomesteadItem>();
private HomesteadItem mCurrentTouchHomestead = null;
private HomesteadItem mNewHomestead = null;
private int mHomesteadIconSize, mHomesteadHalfIconWidth, mHomesteadHalfIconHeight;
private ColorFilter mHomesteadSelectedFilter;
// for gesture detection and scrolling friction
private float mSpeed = 0;
private float mScroll = 0;
// TODO: move to MediaTablet.java
private static final int SWIPE_MIN_DISTANCE = 200;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 300;
private final int screenDensity = getResources().getDisplayMetrics().densityDpi;
private final int REL_SWIPE_MIN_DISTANCE = (int) (SWIPE_MIN_DISTANCE * screenDensity / 160.0f);
private final int REL_SWIPE_MAX_OFF_PATH = (int) (SWIPE_MAX_OFF_PATH * screenDensity / 160.0f);
private final int REL_SWIPE_THRESHOLD_VELOCITY = (int) (SWIPE_THRESHOLD_VELOCITY * screenDensity / 160.0f);
private GestureDetector mGestureDetector;
// internal id used for storing cached background images - if this is changed, panorama images will be regenerated
public static final String BACKGROUND_IMAGE_NAME = "panorama";
private static final String HOMESTEAD_DEFAULT_NAME = "homestead";
private static final String HOMESTEAD_ADD_NEW_NAME = "add-homestead";
public static String getBackgroundCacheFileName(int imageNumber) {
return BACKGROUND_IMAGE_NAME + "-" + imageNumber;
}
private class LoadingBitmap {
public int mTransitionState = TRANSITION_STARTING;
public long mStartTimeMillis;
public int mFrom = 0;
public int mTo = 255;
public int mAlpha;
public final int mDuration = MediaTablet.ANIMATION_FADE_TRANSITION_DURATION;
public final Paint mEndPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
public final Bitmap mBitmap;
public LoadingBitmap(Bitmap loadingTile) {
mBitmap = loadingTile;
}
}
public HomesteadSurfaceView(Context context) {
super(context);
initialiseView(context);
}
public HomesteadSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
initialiseView(context);
}
public HomesteadSurfaceView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialiseView(context);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// setWillNotDraw(false); // don't do this - documentation say we should but it breaks the view
if (!mPanoramaLoaded) {
loadImages();
}
if (!mDrawThread.isAlive()) {
mDrawThread = new SurfaceDrawThread(this);
}
mDrawThread.setRunning(true);
mDrawThread.start();
if (!mLoadThread.isAlive()) {
mLoadThread = new SurfaceLoadThread(this);
}
mLoadThread.setRunning(true);
mLoadThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
onDetachedFromWindow(); // note: not guaranteed to be called
}
private void initialiseView(Context context) {
mPanoramaLoaded = false;
mX = 0;
mY = 0;
mCurrentDrawX = 0;
mCurrentTouchX = 0;
mCurrentTouchY = 0;
mDrawThread = new SurfaceDrawThread(this);
mLoadThread = new SurfaceLoadThread(this);
mGestureDetector = new GestureDetector(context, new HomesteadViewGestureDetector());
setOnTouchListener(this);
getHolder().addCallback(this);
setFocusable(true);
}
public boolean imagesLoaded() {
return mPanoramaLoaded;
}
public void requestLoadImages() {
// TODO: ignore repeat requests
loadImages();
}
public static void forceImageReload() {
// TODO: delete only those images that exist; this is a hack
for (int i = 0; i < 100; i++) {
File imageFile = new File(MediaTablet.DIRECTORY_THUMBS, getBackgroundCacheFileName(i));
if ((imageFile).exists()) {
imageFile.delete();
}
}
}
private void loadImages() {
Context context = getContext();
SharedPreferences panoramaSettings = context.getSharedPreferences(MediaTablet.APPLICATION_NAME,
Context.MODE_PRIVATE);
String panoramaPath = panoramaSettings.getString(context.getString(R.string.key_panorama_file), null);
if (panoramaPath == null) {
mPanoramaLoaded = false;
return;
}
int panoramaWidth = panoramaSettings.getInt(context.getString(R.string.key_panorama_width), -1);
int panoramaHeight = panoramaSettings.getInt(context.getString(R.string.key_panorama_height), -1);
boolean createCachedImages = panoramaWidth <= 0 || panoramaHeight <= 0
|| !(new File(MediaTablet.DIRECTORY_THUMBS, getBackgroundCacheFileName(0))).exists(); // TODO: test all?
boolean useSample = context.getString(R.string.sample_panorama_identifier).equals(panoramaPath);
if (createCachedImages && !useSample && !new File(panoramaPath).exists()) {
mPanoramaLoaded = false;
return;
}
mScreenWidth = getWidth();
mScreenHeight = getHeight();
mScreenHalfWidth = (int) (mScreenWidth / 2.0);
mBitmapWidth = mScreenHeight;
mBitmapHeight = mScreenHeight;
if (createCachedImages) {
Options imageDimensions;
if (useSample) {
imageDimensions = BitmapUtilities.getImageDimensions(getResources(), R.drawable.sample_panorama);
} else {
imageDimensions = BitmapUtilities.getImageDimensions(panoramaPath);
}
panoramaWidth = imageDimensions.outWidth;
panoramaHeight = imageDimensions.outHeight;
SharedPreferences.Editor prefsEditor = panoramaSettings.edit();
prefsEditor.putInt(context.getString(R.string.key_panorama_width), panoramaWidth);
prefsEditor.putInt(context.getString(R.string.key_panorama_height), panoramaHeight);
prefsEditor.apply();
}
mPanoramaImageCount = (panoramaWidth / panoramaHeight) + 1;
mPanoramaImageSize = mPanoramaImageCount * mBitmapWidth;
mPanoramaHalfImageSize = mPanoramaImageSize / 2f;
mPanoramaImageIndex = 0;
mPanoramaLoadingIcon = new LoadingBitmap(Bitmap.createBitmap(mBitmapWidth, mBitmapHeight,
ImageCacheUtilities.mBitmapFactoryOptions.inPreferredConfig));
mPanoramaLoadingIcon.mBitmap.eraseColor(Color.BLACK);
if (createCachedImages) {
if (MediaTablet.DEBUG) {
Log.d(DebugUtilities.getLogTag(this), "Panorama images not found - regenerating cache");
}
// TODO: move everything from here to a background thread?
Drawable panoramaDrawable = null;
boolean panoramaFailed = false;
try {
if (useSample) {
panoramaDrawable = getResources().getDrawable(R.drawable.sample_panorama);
} else {
panoramaDrawable = Drawable.createFromPath(panoramaPath);
}
} catch (Throwable t) {
UIUtilities.showToast(getContext(), R.string.error_loading_panorama);
panoramaFailed = true;
}
if (!panoramaFailed && panoramaDrawable != null) {
Bitmap tiledBitmap = null;
Canvas tiledBitmapCanvas = null;
for (int i = 0, n = panoramaWidth; i < n; i += panoramaHeight) {
if (tiledBitmap == null) {
tiledBitmap = Bitmap.createBitmap(mBitmapWidth, mBitmapHeight,
ImageCacheUtilities.mBitmapFactoryOptions.inPreferredConfig);
tiledBitmapCanvas = new Canvas(tiledBitmap);
if (panoramaHeight != mBitmapHeight) {
tiledBitmapCanvas.scale(mBitmapWidth / (float) panoramaHeight, mBitmapHeight
/ (float) panoramaHeight, 0, 0);
}
}
tiledBitmapCanvas.drawColor(Color.BLACK);
panoramaDrawable.setBounds(-i, 0, panoramaWidth - i, panoramaHeight);
panoramaDrawable.draw(tiledBitmapCanvas); // see: http://stackoverflow.com/a/3705169
saveCachedImage(tiledBitmap, getBackgroundCacheFileName(i / panoramaHeight),
MediaTablet.ICON_CACHE_TYPE);
}
tiledBitmapCanvas = null;
if (tiledBitmap != null) {
tiledBitmap.recycle();
}
tiledBitmap = null;
panoramaDrawable = null;
}
}
Resources resources = getResources();
mHomesteadIconSize = resources.getDimensionPixelSize(R.dimen.homestead_icon_total_size);
if (createCachedImages) {
Bitmap iconBitmap = Bitmap.createBitmap(mHomesteadIconSize, mHomesteadIconSize,
ImageCacheUtilities.mBitmapFactoryOptions.inPreferredConfig);
Canvas iconBitmapCanvas = new Canvas(iconBitmap);
int iconSize = resources.getDimensionPixelSize(R.dimen.homestead_icon_size);
int iconStart = Math.round((mHomesteadIconSize - iconSize) / 2f);
Rect drawRect = new Rect(iconStart, iconStart, iconStart + iconSize, iconStart + iconSize);
// using SVG so that we don't need resolution-specific icons
SVG audioSVG = SVGParser.getSVGFromResource(resources, R.raw.ic_homestead);
iconBitmapCanvas.drawPicture(audioSVG.getPicture(), drawRect);
saveCachedImage(iconBitmap, HOMESTEAD_DEFAULT_NAME, Bitmap.CompressFormat.PNG);
audioSVG = SVGParser.getSVGFromResource(resources, R.raw.ic_homestead_new);
iconBitmapCanvas.drawPicture(audioSVG.getPicture(), drawRect);
saveCachedImage(iconBitmap, HOMESTEAD_ADD_NEW_NAME, Bitmap.CompressFormat.PNG);
}
mHomesteadLoadingIcon = new LoadingBitmap(mLoadThread.loadIcon(HOMESTEAD_DEFAULT_NAME, false));
mHomesteadHalfIconWidth = mHomesteadIconSize / 2;
mHomesteadHalfIconHeight = mHomesteadIconSize / 2;
mHomesteadSelectedFilter = new LightingColorFilter(context.getResources().getColor(R.color.icon_selected), 1);
float startPosition = panoramaSettings.getFloat(context.getString(R.string.key_panorama_position), 1);
mX = (startPosition <= 0 ? startPosition : -(new Random().nextInt(mPanoramaImageSize)));
mY = 0;
mSpeed = 0;
context = null;
mPanoramaLoaded = true;
}
public void saveCachedImage(Bitmap bitmap, String fileName, Bitmap.CompressFormat fileFormat) {
File outputImageFile = new File(MediaTablet.DIRECTORY_THUMBS, fileName);
boolean success = false;
if (bitmap != null && MediaTablet.DIRECTORY_THUMBS != null) {
success = BitmapUtilities.saveBitmap(bitmap, fileFormat, MediaTablet.ICON_CACHE_QUALITY, outputImageFile);
}
if (MediaTablet.DEBUG) {
if (bitmap == null || !success) {
Log.e(DebugUtilities.getLogTag(this), "Failed to save cache image " + outputImageFile);
}
}
}
public void onDetachedFromWindow() {
Context context = getContext();
SharedPreferences panoramaSettings = context.getSharedPreferences(MediaTablet.APPLICATION_NAME,
Context.MODE_PRIVATE);
SharedPreferences.Editor prefsEditor = panoramaSettings.edit();
prefsEditor.putFloat(context.getString(R.string.key_panorama_position), mX);
prefsEditor.apply();
mDrawThread.setRunning(false);
mLoadThread.setRunning(false);
boolean retry = true;
while (retry) {
try {
mDrawThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
retry = true;
while (retry) {
try {
mLoadThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
mTileCache.clear();
mTilesToLoad.clear();
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
if (!mPanoramaLoaded) {
return;
}
mX = mX + mSpeed + mScroll;
mX = (mX - mPanoramaImageSize) % mPanoramaImageSize;
mPanoramaImageIndex = (int) ((-mX + mBitmapWidth) / mBitmapWidth);
mCurrentDrawX = (mX + (mPanoramaImageIndex * mBitmapWidth)) - mBitmapWidth * (IMAGES_TO_DRAW / 2);
mPanoramaImageIndex %= mPanoramaImageCount;
// draw the tiles (fading in as they load)
for (int i = (mPanoramaImageIndex + mPanoramaImageCount - IMAGES_TO_DRAW) % mPanoramaImageCount, n = 0; n < mPanoramaImageCount; i = (i + 1)
% mPanoramaImageCount) {
if (n <= IMAGES_TO_DRAW) {
drawLoadingBitmap(canvas, loadBitmap(getBackgroundCacheFileName(i), false), null, false, mCurrentDrawX,
mY);
mCurrentDrawX += mBitmapWidth;
} else {
mTileCache.remove(getBackgroundCacheFileName(i)); // try to save some memory
}
n += 1;
}
float hDiff = 0;
float hXPos;
mScreenCentreX = -(mX + (mBitmapWidth * (IMAGES_TO_DRAW / 2)) - mPanoramaImageSize - mScreenHalfWidth)
% mPanoramaImageSize;
for (HomesteadItem h : mHomesteadItems) {
hDiff = getXPointDifference(mScreenCentreX, h.getXPosition());
if (Math.abs(hDiff) <= mScreenHalfWidth + mHomesteadHalfIconWidth) {
hXPos = mScreenHalfWidth - hDiff - mHomesteadHalfIconWidth; // TODO: fix buggy horizontal positioning
if (mAddMode && h.equals(mNewHomestead)) { // default add homestead icon
drawLoadingBitmap(canvas, loadBitmap(HOMESTEAD_ADD_NEW_NAME, true), mHomesteadSelectedFilter, true,
hXPos, h.getYPosition() - mHomesteadHalfIconHeight);
} else {
drawLoadingBitmap(canvas, loadBitmap(h.getCacheId(), true),
h.getSelected() ? mHomesteadSelectedFilter : h.getColourFilter(), // should we combine?
true, hXPos, h.getYPosition() - mHomesteadHalfIconHeight);
}
}
}
if (DRAW_DEBUG_DATA) {
drawDebugData(canvas);
}
}
private float getXPointDifference(float p1, float p2) {
return ((p1 + mPanoramaHalfImageSize - p2) % mPanoramaImageSize) - mPanoramaHalfImageSize;
}
private void drawDebugData(Canvas canvas) {
canvas.drawText("MX: " + mX + " " + mY, 10, 20, mPaint);
canvas.drawText("TouchPos: " + mCurrentTouchX + " " + mCurrentTouchY, 10, 40, mPaint);
canvas.drawText("DrawMX: " + mCurrentDrawX, 10, 60, mPaint);
canvas.drawText("Index: " + mPanoramaImageIndex + ", centre: " + mScreenCentreX, 10, 80, mPaint);
canvas.drawText("TouchPoint: (" + getTouchedXPoint() + "," + getTouchedYPoint() + ")", 10, 100, mPaint);
if (getSelectedHomestead() != null) {
canvas.drawText(getSelectedHomestead().getInternalId(), 10, 120, mPaint);
} else {
canvas.drawText("null", 10, 120, mPaint);
}
}
private LoadingBitmap loadBitmap(String bitmapFile, boolean isHomestead) {
LoadingBitmap bitmap = mTileCache.get(bitmapFile);
if (bitmap != null) {
return bitmap;
} else {
mTileCache.remove(bitmapFile); // not loaded yet (or removed) - load into cache
}
mTilesToLoad.remove(bitmapFile);
mTilesToLoad.add(0, bitmapFile); // start or end?
return (isHomestead ? mHomesteadLoadingIcon : mPanoramaLoadingIcon);
}
private void drawLoadingBitmap(Canvas canvas, LoadingBitmap loadingBitmap, ColorFilter filter, boolean isHomestead,
float xPosition, float yPosition) {
boolean done = true;
switch (loadingBitmap.mTransitionState) {
case TRANSITION_STARTING:
loadingBitmap.mStartTimeMillis = SystemClock.uptimeMillis();
done = false;
loadingBitmap.mTransitionState = TRANSITION_RUNNING;
break;
case TRANSITION_RUNNING:
if (loadingBitmap.mStartTimeMillis >= 0) {
float normalized = (float) (SystemClock.uptimeMillis() - loadingBitmap.mStartTimeMillis)
/ loadingBitmap.mDuration;
done = normalized >= 1.0f;
loadingBitmap.mAlpha = (int) (loadingBitmap.mFrom + (loadingBitmap.mTo - loadingBitmap.mFrom)
* Math.min(normalized, 1.0f));
if (done) {
loadingBitmap.mTransitionState = TRANSITION_NONE;
}
}
break;
}
final Paint paint = loadingBitmap.mEndPaint;
final int alpha = loadingBitmap.mAlpha;
if (isHomestead) {
paint.setAlpha(255 - alpha);
canvas.drawBitmap(mHomesteadLoadingIcon.mBitmap, xPosition, yPosition, paint);
paint.setAlpha(0xFF);
}
if (alpha > 0) {
paint.setAlpha(alpha);
paint.setColorFilter(filter);
canvas.drawBitmap(loadingBitmap.mBitmap, xPosition, yPosition, paint);
paint.setColorFilter(null);
paint.setAlpha(0xFF);
}
}
public void refreshHomesteads() {
HomesteadManager.loadHomesteads(getContext().getContentResolver(), mHomesteadItems);
}
public void setScrollSpeed(int scroll) {
if (scroll != 0 && Integer.signum(scroll) != Integer.signum(Math.round(mSpeed))) {
mSpeed = -mSpeed;
}
mScroll = scroll;
}
public float getCurrentXPosition() {
return mX;
}
public void setCurrentXPosition(float newPosition) {
if (newPosition <= 0) {
mX = newPosition;
}
}
public void registerTouchListener(HomesteadTouchListener touchListener) {
mTouchListener = touchListener;
}
public void setEditMode(boolean editMode) {
mAddMode = editMode;
}
public HomesteadItem getTemporaryHomestead() {
return mNewHomestead;
}
public void updatePhysics() {
// TODO: add proper physics here...
mSpeed *= 0.95; // was 0.981;
}
public String getIconToLoad() {
if (mTilesToLoad.size() > 0) {
return mTilesToLoad.get(0);
}
return null;
}
public void addLoadedTile(String iconFile, Bitmap loadedIcon) {
// don't let load failures block other requests
if (loadedIcon != null) {
LoadingBitmap b = new LoadingBitmap(loadedIcon);
mTileCache.put(iconFile, b);
}
mTilesToLoad.remove(iconFile);
}
private int getTouchedXPoint() {
return !mPanoramaLoaded ? 0
: (int) (-mX - (mBitmapWidth * (IMAGES_TO_DRAW / 2)) + mPanoramaImageSize + mCurrentTouchX)
% mPanoramaImageSize;
}
private int getTouchedYPoint() {
return !mPanoramaLoaded ? 0 : (int) (-mY + mCurrentTouchY);
}
public HomesteadItem getSelectedHomestead() {
return mCurrentTouchHomestead;
}
private HomesteadItem getTouchedHomestead() {
int touchedX = getTouchedXPoint();
int touchedY = getTouchedYPoint();
// for (HomesteadItem h : mHomesteadItems) { //instead, reverse the list to get items in correct draw order
for (ListIterator<HomesteadItem> it = mHomesteadItems.listIterator(mHomesteadItems.size()); it.hasPrevious();) {
final HomesteadItem h = it.previous();
if (Math.abs(getXPointDifference(touchedX, h.getXPosition())) <= mHomesteadHalfIconWidth) {
int hY = h.getYPosition();
if (touchedY >= hY - mHomesteadHalfIconHeight && touchedY <= hY + mHomesteadHalfIconHeight) {
return h;
}
}
}
return null;
}
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mSpeed = 0; // stop the gravity scroll
mCurrentTouchX = event.getX();
mCurrentTouchY = event.getY();
mCurrentTouchHomestead = getTouchedHomestead();
for (HomesteadItem h : mHomesteadItems) {
h.setSelected(false);
}
if (mCurrentTouchHomestead != null) {
if (mCurrentTouchHomestead != mNewHomestead && mNewHomestead != null) {
mHomesteadItems.remove(mNewHomestead);
mNewHomestead = null;
}
mCurrentTouchHomestead.setSelected(true);
}
return true;
case MotionEvent.ACTION_MOVE:
mX = mX + event.getX() - mCurrentTouchX;
mX = (mX - mPanoramaImageSize) % mPanoramaImageSize;
mCurrentTouchX = event.getX();
mCurrentTouchY = event.getY();
return true;
case MotionEvent.ACTION_UP:
mCurrentTouchX = event.getX();
mCurrentTouchY = event.getY();
if (mCurrentTouchHomestead != null) {
// to check for finger movement during swipes
if (mCurrentTouchHomestead == getTouchedHomestead() && mTouchListener != null) {
playSoundEffect(SoundEffectConstants.CLICK); // play the default button click (respects prefs)
mTouchListener.homesteadTouched(mCurrentTouchHomestead);
}
if (!mAddMode) {
mCurrentTouchHomestead.setSelected(false);
}
}
mCurrentTouchHomestead = null;
return true;
}
return false;
}
private class HomesteadViewGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onDoubleTap(MotionEvent e) {
if (mAddMode) {
// TODO: stop them double tapping on an existing homestead
if (mCurrentTouchHomestead != null) {
mCurrentTouchHomestead.setSelected(false);
}
if (mNewHomestead == null) {
mNewHomestead = new HomesteadItem(UUID.randomUUID().toString(), getTouchedXPoint(),
getTouchedYPoint());
mHomesteadItems.add(mNewHomestead);
} else {
mNewHomestead.setXPosition(getTouchedXPoint());
mNewHomestead.setYPosition(getTouchedYPoint());
}
mCurrentTouchHomestead = mNewHomestead;
mCurrentTouchHomestead.setSelected(true);
return true;
}
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
try {
if (Math.abs(e1.getY() - e2.getY()) > REL_SWIPE_MAX_OFF_PATH) {
return false;
}
if (Math.abs(velocityX) > REL_SWIPE_THRESHOLD_VELOCITY) {
if (e1.getX() - e2.getX() > REL_SWIPE_MIN_DISTANCE) { // right to left swipe
mSpeed = velocityX / 50;
return true;
} else if (e2.getX() - e1.getX() > REL_SWIPE_MIN_DISTANCE) { // left to right swipe
mSpeed = velocityX / 50;
return true;
}
}
} catch (Exception e) {
}
return false;
}
}
public interface HomesteadTouchListener {
void homesteadTouched(HomesteadItem touchedHomestead);
}
}