mirror of
https://gitee.com/houstudio/Cdroid.git
synced 2024-12-02 04:07:42 +08:00
add gestureoverlayview
This commit is contained in:
parent
529ac6b6d2
commit
2dc32b0874
@ -175,6 +175,7 @@ void AnimatedRotateDrawable::draw(Canvas& canvas) {
|
||||
const float radians=M_PI*2.f*mCurrentDegrees/360.f;
|
||||
const float fsin=sin(radians);
|
||||
const float fcos=cos(radians);
|
||||
const bool filteredBitmap = drawable->isFilterBitmap();
|
||||
#if 0//Anti clockwise
|
||||
Matrix mtx(fcos,-fsin, fsin,fcos,
|
||||
sdot(-fsin,py,1-fcos,px), sdot(fsin,px,1-fcos,py));
|
||||
@ -184,9 +185,13 @@ void AnimatedRotateDrawable::draw(Canvas& canvas) {
|
||||
canvas.save();
|
||||
canvas.translate(bounds.left,bounds.top);
|
||||
canvas.transform(mtx);
|
||||
if(!filteredBitmap)
|
||||
drawable->setFilterBitmap(true);
|
||||
drawable->setBounds(0,0,w,h);
|
||||
drawable->draw(canvas);
|
||||
drawable->setBounds(bounds);
|
||||
if(!filteredBitmap)
|
||||
drawable->setFilterBitmap(false);
|
||||
canvas.translate(-bounds.left,-bounds.top);
|
||||
canvas.restore();
|
||||
#endif
|
||||
|
@ -6,6 +6,7 @@ std::atomic<int>Gesture::sGestureCount(0);
|
||||
|
||||
Gesture::Gesture() {
|
||||
mGestureID = GESTURE_ID_BASE + sGestureCount++;
|
||||
mBoundingBox.set(0,0,0,0);
|
||||
}
|
||||
|
||||
Gesture* Gesture::clone() {
|
||||
|
@ -5,9 +5,9 @@
|
||||
#include <core/rect.h>
|
||||
#include <core/path.h>
|
||||
#include <core/parcelable.h>
|
||||
#include <gesture/gesturestroke.h>
|
||||
|
||||
namespace cdroid{
|
||||
class GestureStroke;
|
||||
typedef Cairo::RefPtr<Cairo::ImageSurface> Bitmap;
|
||||
class Gesture:public Parcelable {
|
||||
private:
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef __GESTURE_LIBRARIES_H__
|
||||
#define __GESTURE_LIBRARIES_H__
|
||||
#include <string>
|
||||
#include <gesture/instance.h>
|
||||
#include <gesture/gesturelibrary.h>
|
||||
namespace cdroid{
|
||||
class Context;
|
||||
class GestureLibrary;
|
||||
|
@ -2,11 +2,11 @@
|
||||
#define __GESTURE_LIBRARY_H__
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <gesture/learner.h>
|
||||
#include <gesture/gesture.h>
|
||||
#include <gesture/prediction.h>
|
||||
#include <gesture/gesturestore.h>
|
||||
namespace cdroid{
|
||||
class Learner;
|
||||
class Gesture;
|
||||
class GestureLibrary {
|
||||
protected:
|
||||
GestureStore* mStore;
|
||||
|
632
src/gui/gesture/gestureoverlayview.cc
Normal file
632
src/gui/gesture/gestureoverlayview.cc
Normal file
@ -0,0 +1,632 @@
|
||||
#if 0
|
||||
#include <gesture/gestureoverlayview.h>
|
||||
namespace cdroid{
|
||||
//private final AccelerateDecelerateInterpolator mInterpolator =new AccelerateDecelerateInterpolator();
|
||||
//private final FadeOutRunnable mFadingOut = new FadeOutRunnable();
|
||||
|
||||
GestureOverlayView::GestureOverlayView(Context* context,const AttributeSet& attrs) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
|
||||
final TypedArray a = context.obtainStyledAttributes(
|
||||
attrs, R.styleable.GestureOverlayView, defStyleAttr, defStyleRes);
|
||||
|
||||
mGestureStrokeWidth = a.getFloat(R.styleable.GestureOverlayView_gestureStrokeWidth,
|
||||
mGestureStrokeWidth);
|
||||
mInvalidateExtraBorder = Math.max(1, ((int) mGestureStrokeWidth) - 1);
|
||||
mCertainGestureColor = a.getColor(R.styleable.GestureOverlayView_gestureColor,
|
||||
mCertainGestureColor);
|
||||
mUncertainGestureColor = a.getColor(R.styleable.GestureOverlayView_uncertainGestureColor,
|
||||
mUncertainGestureColor);
|
||||
mFadeDuration = a.getInt(R.styleable.GestureOverlayView_fadeDuration, (int) mFadeDuration);
|
||||
mFadeOffset = a.getInt(R.styleable.GestureOverlayView_fadeOffset, (int) mFadeOffset);
|
||||
mGestureStrokeType = a.getInt(R.styleable.GestureOverlayView_gestureStrokeType,
|
||||
mGestureStrokeType);
|
||||
mGestureStrokeLengthThreshold = a.getFloat(
|
||||
R.styleable.GestureOverlayView_gestureStrokeLengthThreshold,
|
||||
mGestureStrokeLengthThreshold);
|
||||
mGestureStrokeAngleThreshold = a.getFloat(
|
||||
R.styleable.GestureOverlayView_gestureStrokeAngleThreshold,
|
||||
mGestureStrokeAngleThreshold);
|
||||
mGestureStrokeSquarenessTreshold = a.getFloat(
|
||||
R.styleable.GestureOverlayView_gestureStrokeSquarenessThreshold,
|
||||
mGestureStrokeSquarenessTreshold);
|
||||
mInterceptEvents = a.getBoolean(R.styleable.GestureOverlayView_eventsInterceptionEnabled,
|
||||
mInterceptEvents);
|
||||
mFadeEnabled = a.getBoolean(R.styleable.GestureOverlayView_fadeEnabled,
|
||||
mFadeEnabled);
|
||||
mOrientation = a.getInt(R.styleable.GestureOverlayView_orientation, mOrientation);
|
||||
|
||||
a.recycle();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
void GestureOverlayView::init() {
|
||||
setWillNotDraw(false);
|
||||
|
||||
final Paint gesturePaint = mGesturePaint;
|
||||
gesturePaint.setAntiAlias(GESTURE_RENDERING_ANTIALIAS);
|
||||
gesturePaint.setColor(mCertainGestureColor);
|
||||
gesturePaint.setStyle(Paint.Style.STROKE);
|
||||
gesturePaint.setStrokeJoin(Paint.Join.ROUND);
|
||||
gesturePaint.setStrokeCap(Paint.Cap.ROUND);
|
||||
gesturePaint.setStrokeWidth(mGestureStrokeWidth);
|
||||
gesturePaint.setDither(DITHER_FLAG);
|
||||
|
||||
mCurrentColor = mCertainGestureColor;
|
||||
setPaintAlpha(255);
|
||||
}
|
||||
|
||||
std::vector<GesturePoint> GestureOverlayView::getCurrentStroke() const{
|
||||
return mStrokeBuffer;
|
||||
}
|
||||
|
||||
int GestureOverlayView::getOrientation() const{
|
||||
return mOrientation;
|
||||
}
|
||||
|
||||
void GestureOverlayView::setOrientation(int orientation) {
|
||||
mOrientation = orientation;
|
||||
}
|
||||
|
||||
void GestureOverlayView::setGestureColor(int color) {
|
||||
mCertainGestureColor = color;
|
||||
}
|
||||
|
||||
void GestureOverlayView::setUncertainGestureColor(int color) {
|
||||
mUncertainGestureColor = color;
|
||||
}
|
||||
|
||||
int GestureOverlayView::getUncertainGestureColor() const{
|
||||
return mUncertainGestureColor;
|
||||
}
|
||||
|
||||
int GestureOverlayView::getGestureColor() const{
|
||||
return mCertainGestureColor;
|
||||
}
|
||||
|
||||
float GestureOverlayView::getGestureStrokeWidth() const{
|
||||
return mGestureStrokeWidth;
|
||||
}
|
||||
|
||||
void GestureOverlayView::setGestureStrokeWidth(float gestureStrokeWidth) {
|
||||
mGestureStrokeWidth = gestureStrokeWidth;
|
||||
mInvalidateExtraBorder = Math.max(1, ((int) gestureStrokeWidth) - 1);
|
||||
mGesturePaint.setStrokeWidth(gestureStrokeWidth);
|
||||
}
|
||||
|
||||
int GestureOverlayView::getGestureStrokeType() const{
|
||||
return mGestureStrokeType;
|
||||
}
|
||||
|
||||
void GestureOverlayView::setGestureStrokeType(int gestureStrokeType) {
|
||||
mGestureStrokeType = gestureStrokeType;
|
||||
}
|
||||
|
||||
float GestureOverlayView::getGestureStrokeLengthThreshold() const{
|
||||
return mGestureStrokeLengthThreshold;
|
||||
}
|
||||
|
||||
void GestureOverlayView::setGestureStrokeLengthThreshold(float gestureStrokeLengthThreshold) {
|
||||
mGestureStrokeLengthThreshold = gestureStrokeLengthThreshold;
|
||||
}
|
||||
|
||||
float GestureOverlayView::getGestureStrokeSquarenessTreshold() {
|
||||
return mGestureStrokeSquarenessTreshold;
|
||||
}
|
||||
|
||||
void GestureOverlayView::setGestureStrokeSquarenessTreshold(float gestureStrokeSquarenessTreshold) {
|
||||
mGestureStrokeSquarenessTreshold = gestureStrokeSquarenessTreshold;
|
||||
}
|
||||
|
||||
float GestureOverlayView::getGestureStrokeAngleThreshold() const{
|
||||
return mGestureStrokeAngleThreshold;
|
||||
}
|
||||
|
||||
void GestureOverlayView::setGestureStrokeAngleThreshold(float gestureStrokeAngleThreshold) {
|
||||
mGestureStrokeAngleThreshold = gestureStrokeAngleThreshold;
|
||||
}
|
||||
|
||||
bool GestureOverlayView::isEventsInterceptionEnabled() const{
|
||||
return mInterceptEvents;
|
||||
}
|
||||
|
||||
void GestureOverlayView::setEventsInterceptionEnabled(bool enabled) {
|
||||
mInterceptEvents = enabled;
|
||||
}
|
||||
|
||||
bool GestureOverlayView::isFadeEnabled() const{
|
||||
return mFadeEnabled;
|
||||
}
|
||||
|
||||
void GestureOverlayView::setFadeEnabled(bool fadeEnabled) {
|
||||
mFadeEnabled = fadeEnabled;
|
||||
}
|
||||
|
||||
Gesture* GestureOverlayView::getGesture() {
|
||||
return mCurrentGesture;
|
||||
}
|
||||
|
||||
void GestureOverlayView::setGesture(Gesture* gesture) {
|
||||
if (mCurrentGesture != null) {
|
||||
clear(false);
|
||||
}
|
||||
|
||||
setCurrentColor(mCertainGestureColor);
|
||||
mCurrentGesture = gesture;
|
||||
|
||||
final Path path = mCurrentGesture.toPath();
|
||||
RectF bounds;
|
||||
path.computeBounds(bounds, true);
|
||||
|
||||
// TODO: The path should also be scaled to fit inside this view
|
||||
mPath.rewind();
|
||||
mPath.addPath(path, -bounds.left + (getWidth() - bounds.width()) / 2.0f,
|
||||
-bounds.top + (getHeight() - bounds.height()) / 2.0f);
|
||||
|
||||
mResetGesture = true;
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
Path GestureOverlayView::getGesturePath() {
|
||||
return mPath;
|
||||
}
|
||||
|
||||
Path GestureOverlayView::getGesturePath(Path path) {
|
||||
path.set(mPath);
|
||||
return path;
|
||||
}
|
||||
|
||||
bool GestureOverlayView::isGestureVisible() const{
|
||||
return mGestureVisible;
|
||||
}
|
||||
|
||||
void GestureOverlayView::setGestureVisible(bool visible) {
|
||||
mGestureVisible = visible;
|
||||
}
|
||||
|
||||
long GestureOverlayView::getFadeOffset() const{
|
||||
return mFadeOffset;
|
||||
}
|
||||
|
||||
void GestureOverlayView::setFadeOffset(long fadeOffset) {
|
||||
mFadeOffset = fadeOffset;
|
||||
}
|
||||
|
||||
void GestureOverlayView::addOnGestureListener(OnGestureListener listener) {
|
||||
mOnGestureListeners.push_back(listener);
|
||||
}
|
||||
|
||||
void GestureOverlayView::removeOnGestureListener(OnGestureListener listener) {
|
||||
mOnGestureListeners.remove(listener);
|
||||
}
|
||||
|
||||
void GestureOverlayView::removeAllOnGestureListeners() {
|
||||
mOnGestureListeners.clear();
|
||||
}
|
||||
|
||||
void GestureOverlayView::addOnGesturePerformedListener(OnGesturePerformedListener listener) {
|
||||
mOnGesturePerformedListeners.add(listener);
|
||||
if (mOnGesturePerformedListeners.size() > 0) {
|
||||
mHandleGestureActions = true;
|
||||
}
|
||||
}
|
||||
|
||||
void GestureOverlayView::removeOnGesturePerformedListener(OnGesturePerformedListener listener) {
|
||||
mOnGesturePerformedListeners.remove(listener);
|
||||
if (mOnGesturePerformedListeners.size() <= 0) {
|
||||
mHandleGestureActions = false;
|
||||
}
|
||||
}
|
||||
|
||||
void GestureOverlayView::removeAllOnGesturePerformedListeners() {
|
||||
mOnGesturePerformedListeners.clear();
|
||||
mHandleGestureActions = false;
|
||||
}
|
||||
|
||||
void GestureOverlayView::addOnGesturingListener(OnGesturingListener listener) {
|
||||
mOnGesturingListeners.add(listener);
|
||||
}
|
||||
|
||||
void GestureOverlayView::removeOnGesturingListener(OnGesturingListener listener) {
|
||||
mOnGesturingListeners.remove(listener);
|
||||
}
|
||||
|
||||
void GestureOverlayView::removeAllOnGesturingListeners() {
|
||||
mOnGesturingListeners.clear();
|
||||
}
|
||||
|
||||
bool GestureOverlayView::isGesturing() const{
|
||||
return mIsGesturing;
|
||||
}
|
||||
|
||||
void GestureOverlayView::setCurrentColor(int color) {
|
||||
mCurrentColor = color;
|
||||
if (mFadingHasStarted) {
|
||||
setPaintAlpha((int) (255 * mFadingAlpha));
|
||||
} else {
|
||||
setPaintAlpha(255);
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void GestureOverlayView::draw(Canvas& canvas) {
|
||||
FrameLayout::draw(canvas);
|
||||
if ((mCurrentGesture != nullptr) && mGestureVisible) {
|
||||
canvas.drawPath(mPath, mGesturePaint);
|
||||
}
|
||||
}
|
||||
|
||||
void GestureOverlayView::setPaintAlpha(int alpha) {
|
||||
alpha += alpha >> 7;
|
||||
const int baseAlpha = mCurrentColor >>> 24;
|
||||
const int useAlpha = baseAlpha * alpha >> 8;
|
||||
mGesturePaint.setColor((mCurrentColor << 8 >>> 8) | (useAlpha << 24));
|
||||
}
|
||||
|
||||
void GestureOverlayView::clear(bool animated) {
|
||||
clear(animated, false, true);
|
||||
}
|
||||
|
||||
void GestureOverlayView::clear(bool animated, bool fireActionPerformed, bool immediate) {
|
||||
setPaintAlpha(255);
|
||||
removeCallbacks(mFadingOut);
|
||||
mResetGesture = false;
|
||||
mFadingOut.fireActionPerformed = fireActionPerformed;
|
||||
mFadingOut.resetMultipleStrokes = false;
|
||||
|
||||
if (animated && mCurrentGesture != null) {
|
||||
mFadingAlpha = 1.0f;
|
||||
mIsFadingOut = true;
|
||||
mFadingHasStarted = false;
|
||||
mFadingStart = AnimationUtils.currentAnimationTimeMillis() + mFadeOffset;
|
||||
|
||||
postDelayed(mFadingOut, mFadeOffset);
|
||||
} else {
|
||||
mFadingAlpha = 1.0f;
|
||||
mIsFadingOut = false;
|
||||
mFadingHasStarted = false;
|
||||
|
||||
if (immediate) {
|
||||
mCurrentGesture = null;
|
||||
mPath.rewind();
|
||||
invalidate();
|
||||
} else if (fireActionPerformed) {
|
||||
postDelayed(mFadingOut, mFadeOffset);
|
||||
} else if (mGestureStrokeType == GESTURE_STROKE_TYPE_MULTIPLE) {
|
||||
mFadingOut.resetMultipleStrokes = true;
|
||||
postDelayed(mFadingOut, mFadeOffset);
|
||||
} else {
|
||||
mCurrentGesture = null;
|
||||
mPath.rewind();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GestureOverlayView::cancelClearAnimation() {
|
||||
setPaintAlpha(255);
|
||||
mIsFadingOut = false;
|
||||
mFadingHasStarted = false;
|
||||
removeCallbacks(mFadingOut);
|
||||
mPath.rewind();
|
||||
mCurrentGesture = null;
|
||||
}
|
||||
|
||||
void GestureOverlayView::cancelGesture() {
|
||||
mIsListeningForGestures = false;
|
||||
|
||||
// add the stroke to the current gesture
|
||||
mCurrentGesture.addStroke(new GestureStroke(mStrokeBuffer));
|
||||
|
||||
// pass the event to handlers
|
||||
const long now = SystemClock.uptimeMillis();
|
||||
MotionEvent* event = MotionEvent::obtain(now, now, MotionEvent::ACTION_CANCEL, 0.0f, 0.0f, 0);
|
||||
|
||||
std::vector<OnGestureListener> listeners = mOnGestureListeners;
|
||||
int count = listeners.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
listeners.get(i).onGestureCancelled(this, event);
|
||||
}
|
||||
|
||||
event->recycle();
|
||||
|
||||
clear(false);
|
||||
mIsGesturing = false;
|
||||
mPreviousWasGesturing = false;
|
||||
mStrokeBuffer.clear();
|
||||
|
||||
std::vector<OnGesturingListener> otherListeners = mOnGesturingListeners;
|
||||
count = otherListeners.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
otherListeners.get(i).onGesturingEnded(this);
|
||||
}
|
||||
}
|
||||
|
||||
void GestureOverlayView::onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
cancelClearAnimation();
|
||||
}
|
||||
|
||||
bool GestureOverlayView::dispatchTouchEvent(MotionEvent& event) {
|
||||
if (isEnabled()) {
|
||||
const bool cancelDispatch = (mIsGesturing || (mCurrentGesture &&
|
||||
mCurrentGesture.getStrokesCount() > 0 && mPreviousWasGesturing)) &&
|
||||
mInterceptEvents;
|
||||
|
||||
processEvent(event);
|
||||
if (cancelDispatch) {
|
||||
event.setAction(MotionEvent::ACTION_CANCEL);
|
||||
}
|
||||
FrameLayout::dispatchTouchEvent(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
return FrameLayout::dispatchTouchEvent(event);
|
||||
}
|
||||
|
||||
bool GestureOverlayView::processEvent(MotionEvent& event) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent::ACTION_DOWN:
|
||||
touchDown(event);
|
||||
invalidate();
|
||||
return true;
|
||||
case MotionEvent::ACTION_MOVE:
|
||||
if (mIsListeningForGestures) {
|
||||
Rect rect = touchMove(event);
|
||||
if (rect != null) {
|
||||
invalidate(rect);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case MotionEvent::ACTION_UP:
|
||||
if (mIsListeningForGestures) {
|
||||
touchUp(event, false);
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case MotionEvent::ACTION_CANCEL:
|
||||
if (mIsListeningForGestures) {
|
||||
touchUp(event, true);
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GestureOverlayView::touchDown(MotionEvent& event) {
|
||||
mIsListeningForGestures = true;
|
||||
|
||||
float x = event.getX();
|
||||
float y = event.getY();
|
||||
|
||||
mX = x;
|
||||
mY = y;
|
||||
|
||||
mTotalLength = 0;
|
||||
mIsGesturing = false;
|
||||
|
||||
if (mGestureStrokeType == GESTURE_STROKE_TYPE_SINGLE || mResetGesture) {
|
||||
if (mHandleGestureActions) setCurrentColor(mUncertainGestureColor);
|
||||
mResetGesture = false;
|
||||
mCurrentGesture = null;
|
||||
mPath.rewind();
|
||||
} else if (mCurrentGesture == null || mCurrentGesture.getStrokesCount() == 0) {
|
||||
if (mHandleGestureActions) setCurrentColor(mUncertainGestureColor);
|
||||
}
|
||||
|
||||
// if there is fading out going on, stop it.
|
||||
if (mFadingHasStarted) {
|
||||
cancelClearAnimation();
|
||||
} else if (mIsFadingOut) {
|
||||
setPaintAlpha(255);
|
||||
mIsFadingOut = false;
|
||||
mFadingHasStarted = false;
|
||||
removeCallbacks(mFadingOut);
|
||||
}
|
||||
|
||||
if (mCurrentGesture == null) {
|
||||
mCurrentGesture = new Gesture();
|
||||
}
|
||||
|
||||
mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
|
||||
mPath.moveTo(x, y);
|
||||
|
||||
const int border = mInvalidateExtraBorder;
|
||||
mInvalidRect.set((int) x - border, (int) y - border, (int) x + border, (int) y + border);
|
||||
|
||||
mCurveEndX = x;
|
||||
mCurveEndY = y;
|
||||
|
||||
// pass the event to handlers
|
||||
std::vector<OnGestureListener> listeners = mOnGestureListeners;
|
||||
const int count = listeners.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
listeners.at(i).onGestureStarted(this, event);
|
||||
}
|
||||
}
|
||||
|
||||
Rect GestureOverlayView::touchMove(MotionEvent& event) {
|
||||
Rect areaToRefresh = null;
|
||||
|
||||
const float x = event.getX();
|
||||
const float y = event.getY();
|
||||
|
||||
const float previousX = mX;
|
||||
const float previousY = mY;
|
||||
|
||||
const float dx = std::abs(x - previousX);
|
||||
const float dy = std::abs(y - previousY);
|
||||
|
||||
if (dx >= GestureStroke.TOUCH_TOLERANCE || dy >= GestureStroke.TOUCH_TOLERANCE) {
|
||||
areaToRefresh = mInvalidRect;
|
||||
|
||||
// start with the curve end
|
||||
final int border = mInvalidateExtraBorder;
|
||||
areaToRefresh.set((int) mCurveEndX - border, (int) mCurveEndY - border,
|
||||
(int) mCurveEndX + border, (int) mCurveEndY + border);
|
||||
|
||||
float cX = mCurveEndX = (x + previousX) / 2;
|
||||
float cY = mCurveEndY = (y + previousY) / 2;
|
||||
|
||||
mPath.quadTo(previousX, previousY, cX, cY);
|
||||
|
||||
// union with the control point of the new curve
|
||||
areaToRefresh.union((int) previousX - border, (int) previousY - border,
|
||||
(int) previousX + border, (int) previousY + border);
|
||||
|
||||
// union with the end point of the new curve
|
||||
areaToRefresh.union((int) cX - border, (int) cY - border,
|
||||
(int) cX + border, (int) cY + border);
|
||||
|
||||
mX = x;
|
||||
mY = y;
|
||||
|
||||
mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
|
||||
|
||||
if (mHandleGestureActions && !mIsGesturing) {
|
||||
mTotalLength += (float) Math.hypot(dx, dy);
|
||||
|
||||
if (mTotalLength > mGestureStrokeLengthThreshold) {
|
||||
final OrientedBoundingBox box =
|
||||
GestureUtils.computeOrientedBoundingBox(mStrokeBuffer);
|
||||
|
||||
float angle = Math.abs(box.orientation);
|
||||
if (angle > 90) {
|
||||
angle = 180 - angle;
|
||||
}
|
||||
|
||||
if (box.squareness > mGestureStrokeSquarenessTreshold ||
|
||||
(mOrientation == ORIENTATION_VERTICAL ?
|
||||
angle < mGestureStrokeAngleThreshold :
|
||||
angle > mGestureStrokeAngleThreshold)) {
|
||||
|
||||
mIsGesturing = true;
|
||||
setCurrentColor(mCertainGestureColor);
|
||||
|
||||
final std::vector<OnGesturingListener> listeners = mOnGesturingListeners;
|
||||
int count = listeners.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
listeners.get(i).onGesturingStarted(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pass the event to handlers
|
||||
final std::vector<OnGestureListener> listeners = mOnGestureListeners;
|
||||
final int count = listeners.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
listeners.get(i).onGesture(this, event);
|
||||
}
|
||||
}
|
||||
|
||||
return areaToRefresh;
|
||||
}
|
||||
|
||||
void GestureOverlayView::touchUp(MotionEvent& event, bool cancel) {
|
||||
mIsListeningForGestures = false;
|
||||
|
||||
// A gesture wasn't started or was cancelled
|
||||
if (mCurrentGesture != null) {
|
||||
// add the stroke to the current gesture
|
||||
mCurrentGesture.addStroke(new GestureStroke(mStrokeBuffer));
|
||||
|
||||
if (!cancel) {
|
||||
// pass the event to handlers
|
||||
final std::vector<OnGestureListener> listeners = mOnGestureListeners;
|
||||
int count = listeners.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
listeners.get(i).onGestureEnded(this, event);
|
||||
}
|
||||
|
||||
clear(mHandleGestureActions && mFadeEnabled, mHandleGestureActions && mIsGesturing,
|
||||
false);
|
||||
} else {
|
||||
cancelGesture(event);
|
||||
|
||||
}
|
||||
} else {
|
||||
cancelGesture(event);
|
||||
}
|
||||
|
||||
mStrokeBuffer.clear();
|
||||
mPreviousWasGesturing = mIsGesturing;
|
||||
mIsGesturing = false;
|
||||
|
||||
std::vector<OnGesturingListener> listeners = mOnGesturingListeners;
|
||||
const int count = listeners.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
listeners.get(i).onGesturingEnded(this);
|
||||
}
|
||||
}
|
||||
|
||||
void GestureOverlayView::cancelGesture(MotionEvent& event) {
|
||||
// pass the event to handlers
|
||||
std::vector<OnGestureListener> listeners = mOnGestureListeners;
|
||||
const int count = listeners.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
listeners.get(i).onGestureCancelled(this, event);
|
||||
}
|
||||
|
||||
clear(false);
|
||||
}
|
||||
|
||||
void GestureOverlayView::fireOnGesturePerformed() {
|
||||
std::vector<OnGesturePerformedListener> actionListeners = mOnGesturePerformedListeners;
|
||||
const int count = actionListeners.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
actionListeners.get(i).onGesturePerformed(GestureOverlayView.this, mCurrentGesture);
|
||||
}
|
||||
}
|
||||
|
||||
class FadeOutRunnable implements Runnable {
|
||||
bool fireActionPerformed;
|
||||
bool resetMultipleStrokes;
|
||||
|
||||
void run() {
|
||||
if (mIsFadingOut) {
|
||||
final long now = AnimationUtils.currentAnimationTimeMillis();
|
||||
final long duration = now - mFadingStart;
|
||||
|
||||
if (duration > mFadeDuration) {
|
||||
if (fireActionPerformed) {
|
||||
fireOnGesturePerformed();
|
||||
}
|
||||
|
||||
mPreviousWasGesturing = false;
|
||||
mIsFadingOut = false;
|
||||
mFadingHasStarted = false;
|
||||
mPath.rewind();
|
||||
mCurrentGesture = null;
|
||||
setPaintAlpha(255);
|
||||
} else {
|
||||
mFadingHasStarted = true;
|
||||
float interpolatedTime = Math.max(0.0f,
|
||||
Math.min(1.0f, duration / (float) mFadeDuration));
|
||||
mFadingAlpha = 1.0f - mInterpolator.getInterpolation(interpolatedTime);
|
||||
setPaintAlpha((int) (255 * mFadingAlpha));
|
||||
postDelayed(this, FADE_ANIMATION_RATE);
|
||||
}
|
||||
} else if (resetMultipleStrokes) {
|
||||
mResetGesture = true;
|
||||
} else {
|
||||
fireOnGesturePerformed();
|
||||
|
||||
mFadingHasStarted = false;
|
||||
mPath.rewind();
|
||||
mCurrentGesture = null;
|
||||
mPreviousWasGesturing = false;
|
||||
setPaintAlpha(255);
|
||||
}
|
||||
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}/*endof namespace*/
|
||||
#endif
|
153
src/gui/gesture/gestureoverlayview.h
Normal file
153
src/gui/gesture/gestureoverlayview.h
Normal file
@ -0,0 +1,153 @@
|
||||
#include <wiget/framelayout.h>
|
||||
|
||||
namespace cdroid{
|
||||
class GestureOverlayView:public FrameLayout {
|
||||
public:
|
||||
static constexpr int GESTURE_STROKE_TYPE_SINGLE = 0;
|
||||
static constexpr int GESTURE_STROKE_TYPE_MULTIPLE = 1;
|
||||
|
||||
static constexpr int ORIENTATION_HORIZONTAL = 0;
|
||||
static constexpr int ORIENTATION_VERTICAL = 1;
|
||||
public:
|
||||
static interface OnGesturingListener {
|
||||
void onGesturingStarted(GestureOverlayView overlay);
|
||||
|
||||
void onGesturingEnded(GestureOverlayView overlay);
|
||||
};
|
||||
|
||||
interface OnGestureListener {
|
||||
void onGestureStarted(GestureOverlayView overlay, MotionEvent event);
|
||||
|
||||
void onGesture(GestureOverlayView overlay, MotionEvent event);
|
||||
|
||||
void onGestureEnded(GestureOverlayView overlay, MotionEvent event);
|
||||
|
||||
void onGestureCancelled(GestureOverlayView overlay, MotionEvent event);
|
||||
};
|
||||
|
||||
interface OnGesturePerformedListener {
|
||||
void onGesturePerformed(GestureOverlayView overlay, Gesture gesture);
|
||||
};
|
||||
private:
|
||||
static constexpr int FADE_ANIMATION_RATE = 16;
|
||||
static constexpr bool GESTURE_RENDERING_ANTIALIAS = true;
|
||||
static constexpr bool DITHER_FLAG = true;
|
||||
|
||||
long mFadeDuration = 150;
|
||||
long mFadeOffset = 420;
|
||||
long mFadingStart;
|
||||
bool mFadingHasStarted;
|
||||
bool mFadeEnabled = true;
|
||||
|
||||
int mCurrentColor;
|
||||
int mCertainGestureColor = 0xFFFFFF00;
|
||||
int mUncertainGestureColor = 0x48FFFF00;
|
||||
float mGestureStrokeWidth = 12.0f;
|
||||
int mInvalidateExtraBorder = 10;
|
||||
|
||||
int mGestureStrokeType = GESTURE_STROKE_TYPE_SINGLE;
|
||||
float mGestureStrokeLengthThreshold = 50.0f;
|
||||
float mGestureStrokeSquarenessTreshold = 0.275f;
|
||||
float mGestureStrokeAngleThreshold = 40.0f;
|
||||
|
||||
int mOrientation = ORIENTATION_VERTICAL;
|
||||
|
||||
final Rect mInvalidRect = new Rect();
|
||||
final Path mPath = new Path();
|
||||
bool mGestureVisible = true;
|
||||
|
||||
float mX;
|
||||
float mY;
|
||||
|
||||
float mCurveEndX;
|
||||
float mCurveEndY;
|
||||
|
||||
float mTotalLength;
|
||||
bool mIsGesturing = false;
|
||||
bool mPreviousWasGesturing = false;
|
||||
bool mInterceptEvents = true;
|
||||
bool mIsListeningForGestures;
|
||||
bool mResetGesture;
|
||||
|
||||
// current gesture
|
||||
Gesture* mCurrentGesture;
|
||||
std::vector<GesturePoint> mStrokeBuffer;
|
||||
|
||||
// TODO: Make this a list of WeakReferences
|
||||
std::vector<OnGestureListener> mOnGestureListeners;
|
||||
// TODO: Make this a list of WeakReferences
|
||||
std::vector<OnGesturePerformedListener> mOnGesturePerformedListeners;
|
||||
// TODO: Make this a list of WeakReferences
|
||||
std::vector<OnGesturingListener> mOnGesturingListeners;
|
||||
|
||||
bool mHandleGestureActions;
|
||||
|
||||
// fading out effect
|
||||
bool mIsFadingOut = false;
|
||||
float mFadingAlpha = 1.0f;
|
||||
AccelerateDecelerateInterpolator*mInterpolator;// =new AccelerateDecelerateInterpolator();
|
||||
|
||||
FadeOutRunnable mFadingOut;// = new FadeOutRunnable();
|
||||
private:
|
||||
void init();
|
||||
void setCurrentColor(int color);
|
||||
void setPaintAlpha(int alpha);
|
||||
void clear(bool animated, bool fireActionPerformed, bool immediate);
|
||||
bool processEvent(MotionEvent& event);
|
||||
void touchDown(MotionEvent& event);
|
||||
Rect touchMove(MotionEvent& event);
|
||||
void touchUp(MotionEvent& event, bool cancel);
|
||||
void cancelGesture(MotionEvent& event);
|
||||
void fireOnGesturePerformed();
|
||||
protected:
|
||||
void onDetachedFromWindow()override;
|
||||
publc:
|
||||
GestureOverlayView(Context* context,const AttributeSet& attrs);
|
||||
const std::vector<GesturePoint>& getCurrentStroke() const;
|
||||
|
||||
int getOrientation() const;
|
||||
void setOrientation(int orientation);
|
||||
void setGestureColor(int color);
|
||||
void setUncertainGestureColor(int color);
|
||||
int getUncertainGestureColor()const;
|
||||
int getGestureColor()const;
|
||||
float getGestureStrokeWidth()const;
|
||||
void setGestureStrokeWidth(float gestureStrokeWidth);
|
||||
int getGestureStrokeType()const;
|
||||
void setGestureStrokeType(int gestureStrokeType);
|
||||
float getGestureStrokeLengthThreshold()const;
|
||||
void setGestureStrokeLengthThreshold(float gestureStrokeLengthThreshold);
|
||||
float getGestureStrokeSquarenessTreshold()const;
|
||||
void setGestureStrokeSquarenessTreshold(float gestureStrokeSquarenessTreshold);
|
||||
float getGestureStrokeAngleThreshold()const;
|
||||
void setGestureStrokeAngleThreshold(float gestureStrokeAngleThreshold);
|
||||
bool isEventsInterceptionEnabled()const;
|
||||
void setEventsInterceptionEnabled(bool enabled);
|
||||
bool isFadeEnabled()const;
|
||||
void setFadeEnabled(bool fadeEnabled);
|
||||
Gesture getGesture()const;
|
||||
void setGesture(Gesture gesture);
|
||||
Path getGesturePath();
|
||||
Path getGesturePath(Path path);
|
||||
bool isGestureVisible()const;
|
||||
void setGestureVisible(bool visible);
|
||||
long getFadeOffset()const;
|
||||
void setFadeOffset(long fadeOffset);
|
||||
void addOnGestureListener(OnGestureListener listener);
|
||||
void removeOnGestureListener(OnGestureListener listener);
|
||||
void removeAllOnGestureListeners();
|
||||
void addOnGesturePerformedListener(OnGesturePerformedListener listener);
|
||||
void removeOnGesturePerformedListener(OnGesturePerformedListener listener);
|
||||
void removeAllOnGesturePerformedListeners();
|
||||
void addOnGesturingListener(OnGesturingListener listener);
|
||||
void removeOnGesturingListener(OnGesturingListener listener);
|
||||
void removeAllOnGesturingListeners();
|
||||
bool isGesturing()const;
|
||||
void draw(Canvas canvas);
|
||||
void clear(bool animated);
|
||||
void cancelClearAnimation();
|
||||
void cancelGesture();
|
||||
bool dispatchTouchEvent(MotionEvent& event)override;
|
||||
};
|
||||
}/*endof namespace*/
|
||||
|
@ -2,10 +2,10 @@
|
||||
#define __GESTURE_INSTANCE_H__
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <gesture/learner.h>
|
||||
#include <gesture/instancelearner.h>
|
||||
#include <gesture/gesturestore.h>
|
||||
namespace cdroid{
|
||||
class Gesture;
|
||||
class Learner;
|
||||
class InstanceLearner;
|
||||
class Instance {
|
||||
private:
|
||||
static constexpr int SEQUENCE_SAMPLE_SIZE = 16;
|
||||
@ -18,10 +18,8 @@ private:
|
||||
protected:
|
||||
// the feature vector
|
||||
std::vector<float> vector;
|
||||
|
||||
// the label can be null
|
||||
const std::string label;
|
||||
|
||||
// the id of the instance
|
||||
long id;
|
||||
friend class Learner;
|
||||
|
@ -1,10 +1,10 @@
|
||||
#ifndef __LEARNER_H__
|
||||
#define __LEARNER_H__
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <gesture/prediction.h>
|
||||
namespace cdroid{
|
||||
class Instance;
|
||||
|
||||
class Learner {
|
||||
private:
|
||||
std::vector<Instance*> mInstances;
|
||||
|
Loading…
Reference in New Issue
Block a user