blob: 51ca04d3dd9e55e85004d0c48ffbe0fe12f0435c [file] [log] [blame]
/*
* Copyright (c) 2016, The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.android.gallery3d.app;
import android.content.Context;
import android.graphics.Rect;
import android.view.GestureDetector;
import android.view.MotionEvent;
public class GestureController {
private static final int GESTURE_THRESHOLD = 20;
private GestureDetector mGestureDetector;
private GestureControlListener mGestureControlListener;
private Rect mFullRect = new Rect();
private Rect mBrightnessRect = new Rect();
private Rect mVolumeRect = new Rect();
private Type mType = Type.NONE;
private MotionEvent mStartEvent;
public GestureController(Context context, GestureControlListener gestureControlListener) {
mGestureControlListener = gestureControlListener;
mGestureDetector =
new GestureDetector(context, new GestureListener(gestureControlListener));
}
public interface GestureControlListener {
void onGestureDone(boolean notStart);
/**
* change current windows brightness by add adjustPercent.
*
* @param adjustPercent: -1.0f ~ 1.0f, increase if adjustPercent > 0,
* decrease if adjustPercent < 0;
*/
void adjustBrightness(double adjustPercent);
/**
* change volume level by add adjustPercent.
*
* @param adjustPercent: -1.0f ~ 1.0f, increase if adjustPercent > 0,
* decrease if adjustPercent < 0;
*/
void adjustVolumeLevel(double adjustPercent);
/**
* change video position by add adjustPercent.
*
* @param adjustPercent: -1.0f ~ 1.0f, increase if adjustPercent > 0,
* decrease if adjustPercent < 0;
* @param forwardDirection: true if direction is forward.
*/
void adjustVideoPosition(double adjustPercent, boolean forwardDirection);
}
private enum Type {
NONE,
BRIGHTNESS,
VOLUME,
SEEK,
}
public void setRect(Rect rect) {
this.setRect(rect.left, rect.top, rect.right, rect.bottom);
}
public void setRect(int l, int t, int r, int b) {
mFullRect.left = l;
mFullRect.top = t;
mFullRect.right = r;
mFullRect.bottom = b;
mBrightnessRect.left = l;
mBrightnessRect.top = t;
mBrightnessRect.right = r / 2;
mBrightnessRect.bottom = b;
mVolumeRect.left = l / 2;
mVolumeRect.top = t;
mVolumeRect.right = r;
mVolumeRect.bottom = b;
}
private class GestureListener extends GestureDetector.SimpleOnGestureListener {
private GestureControlListener mGestureControlListener;
public GestureListener(GestureControlListener controlListener) {
mGestureControlListener = controlListener;
}
@Override
public boolean onScroll(MotionEvent start, MotionEvent end,
float distanceX, float distanceY) {
if (mGestureControlListener == null) {
return super.onScroll(start, end, distanceX, distanceY);
}
// function depends on start position. (volume or brightness or play position.)
double yDistance = end.getY() - start.getY();
double xDistance = end.getX() - start.getX();
if (mType == Type.BRIGHTNESS) {
// use half of BrightnessRect's height to calc percent.
if (mBrightnessRect.height() != 0) {
double percent = yDistance / (mBrightnessRect.height() / 2.0f) * -1.0f;
mGestureControlListener.adjustBrightness(percent);
}
} else if (mType == Type.VOLUME) {
// use half of VolumeRect's height to calc percent.
if (mVolumeRect.height() != 0) {
double percent = yDistance / (mVolumeRect.height() / 2.0f) * -1.0f;
mGestureControlListener.adjustVolumeLevel(percent);
}
} else if (mType == Type.SEEK) {
if (mFullRect.width() != 0) {
double percent = xDistance / mFullRect.width();
mGestureControlListener.adjustVideoPosition(percent, distanceX < 0);
}
}
return true;
}
}
private boolean isEventValid(MotionEvent event) {
// this gesture just worked on single pointer.
return (mGestureDetector != null && event.getPointerCount() == 1);
}
public boolean onTouchEvent(MotionEvent event) {
if (!isEventValid(event)) {
return false;
}
// decide which process is needed.
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mStartEvent = event.copy();
break;
case MotionEvent.ACTION_MOVE:
if (mType == Type.NONE && mStartEvent != null) {
mType = calcControllerType(mStartEvent, event);
}
break;
case MotionEvent.ACTION_UP:
if (mGestureControlListener != null) {
if (mType == Type.NONE) {
mGestureControlListener.onGestureDone(true);
} else {
mGestureControlListener.onGestureDone(false);
}
}
mType = Type.NONE;
mStartEvent = null;
break;
default:
break;
}
return mGestureDetector.onTouchEvent(event);
}
private Type calcControllerType(MotionEvent startEvent, MotionEvent currentEvent) {
float startX = startEvent.getX();
float startY = startEvent.getY();
float currentX = currentEvent.getX();
float currentY = currentEvent.getY();
if (Math.abs(currentX - startX) >= GESTURE_THRESHOLD) {
return Type.SEEK;
} else if (Math.abs(currentY - startY) >= GESTURE_THRESHOLD) {
if (mBrightnessRect.contains((int) startX, (int) startY)) {
return Type.BRIGHTNESS;
} else if (mVolumeRect.contains((int) startX, (int) startY)) {
return Type.VOLUME;
}
}
return Type.NONE;
}
}