From: Victor Cebollada Date: Wed, 15 Apr 2015 12:56:53 +0000 (+0100) Subject: Cursor Scrolling. X-Git-Tag: dali_1.0.40~9^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=e1ccc59ca19a05c71c035839115e20d480385289 Cursor Scrolling. Change-Id: Ief97436d85ea16e4af852468785e40bdecb1a160 Signed-off-by: Victor Cebollada --- diff --git a/dali-toolkit/internal/text/decorator/text-decorator.cpp b/dali-toolkit/internal/text/decorator/text-decorator.cpp index 32e3bec..2098a5f 100644 --- a/dali-toolkit/internal/text/decorator/text-decorator.cpp +++ b/dali-toolkit/internal/text/decorator/text-decorator.cpp @@ -83,10 +83,14 @@ const Dali::Vector3 DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE( 1.5f, 1.5f, 1.0f ); const unsigned int CURSOR_BLINK_INTERVAL = 500u; // Cursor blink interval const float TO_MILLISECONDS = 1000.f; -const float TO_SECONDS = 1.f / 1000.f; +const float TO_SECONDS = 1.f / TO_MILLISECONDS; const float DISPLAYED_HIGHLIGHT_Z_OFFSET( -0.05f ); +const float SCROLL_THRESHOLD = 10.f; +const float SCROLL_SPEED = 15.f; +const unsigned int SCROLL_TICK_INTERVAL = 50u; + /** * structure to hold coordinates of each quad, which will make up the mesh. */ @@ -151,6 +155,15 @@ namespace Text struct Decorator::Impl : public ConnectionTracker { + enum ScrollDirection + { + SCROLL_NONE, + SCROLL_RIGHT, + SCROLL_LEFT, + SCROLL_TOP, + SCROLL_BOTTOM + }; + struct CursorImpl { CursorImpl() @@ -197,6 +210,10 @@ struct Decorator::Impl : public ConnectionTracker mCursorBlinkDuration( 0.0f ), mGrabDisplacementX( 0.0f ), mGrabDisplacementY( 0.0f ), + mScrollDirection( SCROLL_NONE ), + mScrollThreshold( SCROLL_THRESHOLD ), + mScrollSpeed( SCROLL_SPEED ), + mScrollInterval( SCROLL_TICK_INTERVAL ), mActiveGrabHandle( false ), mActiveSelection( false ), mActiveCopyPastePopup( false ), @@ -690,12 +707,38 @@ struct Decorator::Impl : public ConnectionTracker if( Gesture::Started == gesture.state || Gesture::Continuing == gesture.state ) { - mObserver.GrabHandleEvent( GRAB_HANDLE_PRESSED, x, y ); + if( x < mScrollThreshold ) + { + mScrollDirection = SCROLL_RIGHT; + mGrabDisplacementX -= x; + mCursor[PRIMARY_CURSOR].position.x = 0.f; + StartScrollTimer(); + } + else if( x > mTextControlParent.GetControlSize().width - mScrollThreshold ) + { + mScrollDirection = SCROLL_LEFT; + mGrabDisplacementX += ( mTextControlParent.GetControlSize().width - x ); + mCursor[PRIMARY_CURSOR].position.x = mTextControlParent.GetControlSize().width; + StartScrollTimer(); + } + else + { + StopScrollTimer(); + mObserver.GrabHandleEvent( GRAB_HANDLE_PRESSED, x, y ); + } } else if( Gesture::Finished == gesture.state || Gesture::Cancelled == gesture.state ) { - mObserver.GrabHandleEvent( GRAB_HANDLE_RELEASED, x, y ); + if( mScrollTimer && mScrollTimer.IsRunning() ) + { + StopScrollTimer(); + mObserver.GrabHandleEvent( GRAB_HANDLE_STOP_SCROLLING, x, y ); + } + else + { + mObserver.GrabHandleEvent( GRAB_HANDLE_RELEASED, x, y ); + } } } } @@ -810,12 +853,86 @@ struct Decorator::Impl : public ConnectionTracker requiredPopupPosition.x = requiredPopupPosition.x + xOffSetToKeepWithinBounds; } + void SetScrollThreshold( float threshold ) + { + mScrollThreshold = threshold; + } + + float GetScrollThreshold() const + { + return mScrollThreshold; + } + + void SetScrollSpeed( float speed ) + { + mScrollSpeed = speed; + } + + float GetScrollSpeed() const + { + return mScrollSpeed; + } + + void SetScrollTickInterval( float seconds ) + { + mScrollInterval = static_cast( seconds * TO_MILLISECONDS ); + } + + float GetScrollTickInterval() const + { + return static_cast( mScrollInterval ) * TO_SECONDS; + } + + /** + * Creates and starts a timer to scroll the text when handles are close to the edges of the text. + * + * It only starts the timer if it's already created. + */ + void StartScrollTimer() + { + if( !mScrollTimer ) + { + mScrollTimer = Timer::New( mScrollInterval ); + mScrollTimer.TickSignal().Connect( this, &Decorator::Impl::OnScrollTimerTick ); + } + + if( !mScrollTimer.IsRunning() ) + { + mScrollTimer.Start(); + } + } + + /** + * Stops the timer used to scroll the text. + */ + void StopScrollTimer() + { + if( mScrollTimer ) + { + mScrollTimer.Stop(); + } + } + + /** + * Callback called by the timer used to scroll the text. + * + * It calculates and sets a new scroll position. + */ + bool OnScrollTimerTick() + { + mObserver.GrabHandleEvent( GRAB_HANDLE_SCROLLING, + mScrollDirection == SCROLL_RIGHT ? mScrollSpeed : -mScrollSpeed, + 0.f ); + return true; + } + Internal::Control& mTextControlParent; Observer& mObserver; TapGestureDetector mTapDetector; PanGestureDetector mPanGestureDetector; Timer mCursorBlinkTimer; ///< Timer to signal cursor to blink + Timer mScrollTimer; ///< Timer used to scroll the text when the grab handle is moved close to the edges. Layer mActiveLayer; ///< Layer for active handles and alike that ensures they are above all else. ImageActor mPrimaryCursor; @@ -843,6 +960,10 @@ struct Decorator::Impl : public ConnectionTracker float mCursorBlinkDuration; float mGrabDisplacementX; float mGrabDisplacementY; + ScrollDirection mScrollDirection; ///< The direction of the scroll. + float mScrollThreshold; ///< Defines a square area inside the control, close to the edge. A cursor entering this area will trigger scroll events. + float mScrollSpeed; ///< Distance the text scrolls during a scroll interval. + unsigned int mScrollInterval; ///< Time in milliseconds of a scroll interval. bool mActiveGrabHandle : 1; bool mActiveSelection : 1; @@ -1059,6 +1180,38 @@ bool Decorator::IsPopupActive() const return mImpl->mActiveCopyPastePopup ; } +/** Scroll **/ + +void Decorator::SetScrollThreshold( float threshold ) +{ + mImpl->SetScrollThreshold( threshold ); +} + +float Decorator::GetScrollThreshold() const +{ + return mImpl->GetScrollThreshold(); +} + +void Decorator::SetScrollSpeed( float speed ) +{ + mImpl->SetScrollSpeed( speed ); +} + +float Decorator::GetScrollSpeed() const +{ + return mImpl->GetScrollSpeed(); +} + +void Decorator::SetScrollTickInterval( float seconds ) +{ + mImpl->SetScrollTickInterval( seconds ); +} + +float Decorator::GetScrollTickInterval() const +{ + return mImpl->GetScrollTickInterval(); +} + Decorator::~Decorator() { delete mImpl; diff --git a/dali-toolkit/internal/text/decorator/text-decorator.h b/dali-toolkit/internal/text/decorator/text-decorator.h index 14e1212..588d224 100644 --- a/dali-toolkit/internal/text/decorator/text-decorator.h +++ b/dali-toolkit/internal/text/decorator/text-decorator.h @@ -66,7 +66,9 @@ enum GrabHandleState { GRAB_HANDLE_TAPPED, GRAB_HANDLE_PRESSED, - GRAB_HANDLE_RELEASED + GRAB_HANDLE_RELEASED, + GRAB_HANDLE_SCROLLING, + GRAB_HANDLE_STOP_SCROLLING }; // The set the selection-handle positions etc. @@ -386,6 +388,53 @@ public: */ bool IsPopupActive() const; + /** + * @brief Sets the scroll threshold. + * + * It defines a square area inside the control, close to the edge. + * When the cursor enters this area, the decorator starts to send scroll events. + * + * @param[in] threshold The scroll threshold. + */ + void SetScrollThreshold( float threshold ); + + /** + * @brief Retrieves the scroll threshold. + * + * @retunr The scroll threshold. + */ + float GetScrollThreshold() const; + + /** + * @brief Sets the scroll speed. + * + * Is the distance the text is going to be scrolled during a scroll interval. + * + * @param[in] speed The scroll speed. + */ + void SetScrollSpeed( float speed ); + + /** + * @brief Retrieves the scroll speed. + * + * @return The scroll speed. + */ + float GetScrollSpeed() const; + + /** + * @brief Sets the scroll interval. + * + * @param[in] seconds The scroll interval in seconds. + */ + void SetScrollTickInterval( float seconds ); + + /** + * @brief Retrieves the scroll interval. + * + * @return The scroll interval. + */ + float GetScrollTickInterval() const; + protected: /** diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index 1b68f13..74d9abf 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -353,12 +353,33 @@ void Controller::Impl::OnGrabHandleEvent( const Event& event ) } } else if( mEventData->mGrabHandlePopupEnabled && - ( GRAB_HANDLE_RELEASED == state ) ) + ( ( GRAB_HANDLE_RELEASED == state ) || + ( GRAB_HANDLE_STOP_SCROLLING == state ) ) ) { //mDecorator->ShowPopup(); ChangeState ( EventData::EDITING_WITH_POPUP ); mEventData->mUpdateCursorPosition = true; mEventData->mDecoratorUpdated = true; + + if( GRAB_HANDLE_STOP_SCROLLING == state ) + { + // The event.p2 and event.p3 are in decorator coords. Need to transforms to text coords. + const float xPosition = event.p2.mFloat - mEventData->mScrollPosition.x - mAlignmentOffset.x; + const float yPosition = event.p3.mFloat - mEventData->mScrollPosition.y - mAlignmentOffset.y; + + mEventData->mPrimaryCursorPosition = GetClosestCursorIndex( xPosition, yPosition ); + + mEventData->mScrollAfterUpdateCursorPosition = true; + } + } + else if( GRAB_HANDLE_SCROLLING == state ) + { + const float xSpeed = event.p2.mFloat; + const Vector2& actualSize = mVisualModel->GetActualSize(); + + mEventData->mScrollPosition.x += xSpeed; + + ClampHorizontalScroll( actualSize ); } } @@ -908,7 +929,7 @@ void Controller::Impl::ScrollToMakeCursorVisible() mEventData->mDecorator->UpdatePositions( offset ); } - // TODO : calculate the Y scroll. + // TODO : calculate the vertical scroll. } void Controller::Impl::RequestRelayout()