From 2dc32b0874ab8ae98b4f24a9fe9963f79006b0aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BE=AF=E6=AD=8C?= Date: Fri, 26 Jul 2024 16:33:18 +0800 Subject: [PATCH] add gestureoverlayview --- src/gui/drawables/animatedrotatedrawable.cc | 5 + src/gui/gesture/gesture.cc | 1 + src/gui/gesture/gesture.h | 2 +- src/gui/gesture/gesturelibraries.h | 2 + src/gui/gesture/gesturelibrary.h | 4 +- src/gui/gesture/gestureoverlayview.cc | 632 ++++++++++++++++++++ src/gui/gesture/gestureoverlayview.h | 153 +++++ src/gui/gesture/instance.h | 8 +- src/gui/gesture/learner.h | 2 +- 9 files changed, 800 insertions(+), 9 deletions(-) create mode 100644 src/gui/gesture/gestureoverlayview.cc create mode 100644 src/gui/gesture/gestureoverlayview.h diff --git a/src/gui/drawables/animatedrotatedrawable.cc b/src/gui/drawables/animatedrotatedrawable.cc index 8340aa9a..8e111b58 100755 --- a/src/gui/drawables/animatedrotatedrawable.cc +++ b/src/gui/drawables/animatedrotatedrawable.cc @@ -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 diff --git a/src/gui/gesture/gesture.cc b/src/gui/gesture/gesture.cc index 49b13ad5..45db8cc8 100644 --- a/src/gui/gesture/gesture.cc +++ b/src/gui/gesture/gesture.cc @@ -6,6 +6,7 @@ std::atomicGesture::sGestureCount(0); Gesture::Gesture() { mGestureID = GESTURE_ID_BASE + sGestureCount++; + mBoundingBox.set(0,0,0,0); } Gesture* Gesture::clone() { diff --git a/src/gui/gesture/gesture.h b/src/gui/gesture/gesture.h index 8c980488..b7cbad24 100644 --- a/src/gui/gesture/gesture.h +++ b/src/gui/gesture/gesture.h @@ -5,9 +5,9 @@ #include #include #include +#include namespace cdroid{ -class GestureStroke; typedef Cairo::RefPtr Bitmap; class Gesture:public Parcelable { private: diff --git a/src/gui/gesture/gesturelibraries.h b/src/gui/gesture/gesturelibraries.h index 07c35a9a..fc522b64 100644 --- a/src/gui/gesture/gesturelibraries.h +++ b/src/gui/gesture/gesturelibraries.h @@ -1,6 +1,8 @@ #ifndef __GESTURE_LIBRARIES_H__ #define __GESTURE_LIBRARIES_H__ #include +#include +#include namespace cdroid{ class Context; class GestureLibrary; diff --git a/src/gui/gesture/gesturelibrary.h b/src/gui/gesture/gesturelibrary.h index 2e69eeb6..487544b3 100644 --- a/src/gui/gesture/gesturelibrary.h +++ b/src/gui/gesture/gesturelibrary.h @@ -2,11 +2,11 @@ #define __GESTURE_LIBRARY_H__ #include #include +#include +#include #include #include namespace cdroid{ -class Learner; -class Gesture; class GestureLibrary { protected: GestureStore* mStore; diff --git a/src/gui/gesture/gestureoverlayview.cc b/src/gui/gesture/gestureoverlayview.cc new file mode 100644 index 00000000..8682b695 --- /dev/null +++ b/src/gui/gesture/gestureoverlayview.cc @@ -0,0 +1,632 @@ +#if 0 +#include +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 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 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 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 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 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 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 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 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 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 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 diff --git a/src/gui/gesture/gestureoverlayview.h b/src/gui/gesture/gestureoverlayview.h new file mode 100644 index 00000000..255b5d94 --- /dev/null +++ b/src/gui/gesture/gestureoverlayview.h @@ -0,0 +1,153 @@ +#include + +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 mStrokeBuffer; + + // TODO: Make this a list of WeakReferences + std::vector mOnGestureListeners; + // TODO: Make this a list of WeakReferences + std::vector mOnGesturePerformedListeners; + // TODO: Make this a list of WeakReferences + std::vector 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& 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*/ + diff --git a/src/gui/gesture/instance.h b/src/gui/gesture/instance.h index db7eb11c..586c2d33 100644 --- a/src/gui/gesture/instance.h +++ b/src/gui/gesture/instance.h @@ -2,10 +2,10 @@ #define __GESTURE_INSTANCE_H__ #include #include +#include +#include +#include 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 vector; - // the label can be null const std::string label; - // the id of the instance long id; friend class Learner; diff --git a/src/gui/gesture/learner.h b/src/gui/gesture/learner.h index 7e5bde5f..1aabe109 100644 --- a/src/gui/gesture/learner.h +++ b/src/gui/gesture/learner.h @@ -1,10 +1,10 @@ #ifndef __LEARNER_H__ #define __LEARNER_H__ +#include #include #include namespace cdroid{ class Instance; - class Learner { private: std::vector mInstances;