- // Nothing to do if scrolling is not enabled.
- return;
- }
-
- const GestureState state = static_cast<GestureState>( event.p1.mInt );
- switch( state )
- {
- case GestureState::STARTED:
- {
- // Will remove the cursor, handles or text's popup, ...
- ChangeState( EventData::TEXT_PANNING );
- break;
- }
- case GestureState::CONTINUING:
- {
- const Vector2& layoutSize = mModel->mVisualModel->GetLayoutSize();
- const Vector2 currentScroll = mModel->mScrollPosition;
-
- if( isHorizontalScrollEnabled )
- {
- const float displacementX = event.p2.mFloat;
- mModel->mScrollPosition.x += displacementX;
-
- ClampHorizontalScroll( layoutSize );
- }
-
- if( isVerticalScrollEnabled )
- {
- const float displacementY = event.p3.mFloat;
- mModel->mScrollPosition.y += displacementY;
-
- ClampVerticalScroll( layoutSize );
- }
-
- mEventData->mDecorator->UpdatePositions( mModel->mScrollPosition - currentScroll );
- break;
- }
- case GestureState::FINISHED:
- case GestureState::CANCELLED: // FALLTHROUGH
- {
- // Will go back to the previous state to show the cursor, handles, the text's popup, ...
- ChangeState( mEventData->mPreviousState );
- break;
- }
- default:
- break;
- }
-}
-
-void Controller::Impl::OnLongPressEvent( const Event& event )
-{
- DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::OnLongPressEvent\n" );
-
- if( !IsShowingRealText() && ( EventData::EDITING == mEventData->mState ) )
- {
- ChangeState( EventData::EDITING_WITH_POPUP );
- mEventData->mDecoratorUpdated = true;
- mEventData->mUpdateInputStyle = true;
- }
- else
- {
- if( mEventData->mSelectionEnabled )
- {
- // Convert from control's coords to text's coords.
- const float xPosition = event.p2.mFloat - mModel->mScrollPosition.x;
- const float yPosition = event.p3.mFloat - mModel->mScrollPosition.y;
-
- // Calculates the logical position from the x,y coords.
- RepositionSelectionHandles( xPosition,
- yPosition,
- mEventData->mLongPressAction );
- }
- }
-}
-
-void Controller::Impl::OnHandleEvent( const Event& event )
-{
- if( NULL == mEventData )
- {
- // Nothing to do if there is no text input.
- return;
- }
-
- const unsigned int state = event.p1.mUint;
- const bool handleStopScrolling = ( HANDLE_STOP_SCROLLING == state );
- const bool isSmoothHandlePanEnabled = mEventData->mDecorator->IsSmoothHandlePanEnabled();
-
- if( HANDLE_PRESSED == state )
- {
- // Convert from decorator's coords to text's coords.
- const float xPosition = event.p2.mFloat - mModel->mScrollPosition.x;
- const float yPosition = event.p3.mFloat - mModel->mScrollPosition.y;
-
- // Need to calculate the handle's new position.
- bool matchedCharacter = false;
- const CharacterIndex handleNewPosition = Text::GetClosestCursorIndex( mModel->mVisualModel,
- mModel->mLogicalModel,
- mMetrics,
- xPosition,
- yPosition,
- CharacterHitTest::SCROLL,
- matchedCharacter );
-
- if( Event::GRAB_HANDLE_EVENT == event.type )
- {
- ChangeState ( EventData::GRAB_HANDLE_PANNING );
-
- if( handleNewPosition != mEventData->mPrimaryCursorPosition )
- {
- // Updates the cursor position if the handle's new position is different than the current one.
- mEventData->mUpdateCursorPosition = true;
- // Does not update the grab handle position if the smooth panning is enabled. (The decorator does it smooth).
- mEventData->mUpdateGrabHandlePosition = !isSmoothHandlePanEnabled;
- mEventData->mPrimaryCursorPosition = handleNewPosition;
- }
-
- // Updates the decorator if the soft handle panning is enabled. It triggers a relayout in the decorator and the new position of the handle is set.
- mEventData->mDecoratorUpdated = isSmoothHandlePanEnabled;
- }
- else if( Event::LEFT_SELECTION_HANDLE_EVENT == event.type )
- {
- ChangeState ( EventData::SELECTION_HANDLE_PANNING );
-
- if( ( handleNewPosition != mEventData->mLeftSelectionPosition ) &&
- ( handleNewPosition != mEventData->mRightSelectionPosition ) )
- {
- // Updates the highlight box if the handle's new position is different than the current one.
- mEventData->mUpdateHighlightBox = true;
- // Does not update the selection handle position if the smooth panning is enabled. (The decorator does it smooth).
- mEventData->mUpdateLeftSelectionPosition = !isSmoothHandlePanEnabled;
- mEventData->mLeftSelectionPosition = handleNewPosition;
- }
-
- // Updates the decorator if the soft handle panning is enabled. It triggers a relayout in the decorator and the new position of the handle is set.
- mEventData->mDecoratorUpdated = isSmoothHandlePanEnabled;
-
- // Will define the order to scroll the text to match the handle position.
- mEventData->mIsLeftHandleSelected = true;
- mEventData->mIsRightHandleSelected = false;
- }
- else if( Event::RIGHT_SELECTION_HANDLE_EVENT == event.type )
- {
- ChangeState ( EventData::SELECTION_HANDLE_PANNING );
-
- if( ( handleNewPosition != mEventData->mRightSelectionPosition ) &&
- ( handleNewPosition != mEventData->mLeftSelectionPosition ) )
- {
- // Updates the highlight box if the handle's new position is different than the current one.
- mEventData->mUpdateHighlightBox = true;
- // Does not update the selection handle position if the smooth panning is enabled. (The decorator does it smooth).
- mEventData->mUpdateRightSelectionPosition = !isSmoothHandlePanEnabled;
- mEventData->mRightSelectionPosition = handleNewPosition;
- }
-
- // Updates the decorator if the soft handle panning is enabled. It triggers a relayout in the decorator and the new position of the handle is set.
- mEventData->mDecoratorUpdated = isSmoothHandlePanEnabled;
-
- // Will define the order to scroll the text to match the handle position.
- mEventData->mIsLeftHandleSelected = false;
- mEventData->mIsRightHandleSelected = true;
- }
- } // end ( HANDLE_PRESSED == state )
- else if( ( HANDLE_RELEASED == state ) ||
- handleStopScrolling )
- {
- CharacterIndex handlePosition = 0u;
- if( handleStopScrolling || isSmoothHandlePanEnabled )
- {
- // Convert from decorator's coords to text's coords.
- const float xPosition = event.p2.mFloat - mModel->mScrollPosition.x;
- const float yPosition = event.p3.mFloat - mModel->mScrollPosition.y;
-
- bool matchedCharacter = false;
- handlePosition = Text::GetClosestCursorIndex( mModel->mVisualModel,
- mModel->mLogicalModel,
- mMetrics,
- xPosition,
- yPosition,
- CharacterHitTest::SCROLL,
- matchedCharacter );
- }
-
- if( Event::GRAB_HANDLE_EVENT == event.type )
- {
- mEventData->mUpdateCursorPosition = true;
- mEventData->mUpdateGrabHandlePosition = true;
- mEventData->mUpdateInputStyle = true;
-
- if( !IsClipboardEmpty() )
- {
- ChangeState( EventData::EDITING_WITH_PASTE_POPUP ); // Moving grabhandle will show Paste Popup
- }
-
- if( handleStopScrolling || isSmoothHandlePanEnabled )
- {
- mEventData->mScrollAfterUpdatePosition = true;
- mEventData->mPrimaryCursorPosition = handlePosition;
- }
- }
- else if( Event::LEFT_SELECTION_HANDLE_EVENT == event.type )
- {
- ChangeState( EventData::SELECTING );
-
- mEventData->mUpdateHighlightBox = true;
- mEventData->mUpdateLeftSelectionPosition = true;
- mEventData->mUpdateRightSelectionPosition = true;
-
- if( handleStopScrolling || isSmoothHandlePanEnabled )
- {
- mEventData->mScrollAfterUpdatePosition = true;
-
- if( ( handlePosition != mEventData->mRightSelectionPosition ) &&
- ( handlePosition != mEventData->mLeftSelectionPosition ) )
- {
- mEventData->mLeftSelectionPosition = handlePosition;
- }
- }
- }
- else if( Event::RIGHT_SELECTION_HANDLE_EVENT == event.type )
- {
- ChangeState( EventData::SELECTING );
-
- mEventData->mUpdateHighlightBox = true;
- mEventData->mUpdateRightSelectionPosition = true;
- mEventData->mUpdateLeftSelectionPosition = true;
-
- if( handleStopScrolling || isSmoothHandlePanEnabled )
- {
- mEventData->mScrollAfterUpdatePosition = true;
- if( ( handlePosition != mEventData->mRightSelectionPosition ) &&
- ( handlePosition != mEventData->mLeftSelectionPosition ) )
- {
- mEventData->mRightSelectionPosition = handlePosition;
- }
- }
- }
-
- mEventData->mDecoratorUpdated = true;
- } // end ( ( HANDLE_RELEASED == state ) || ( HANDLE_STOP_SCROLLING == state ) )
- else if( HANDLE_SCROLLING == state )
- {
- const float xSpeed = event.p2.mFloat;
- const float ySpeed = event.p3.mFloat;
- const Vector2& layoutSize = mModel->mVisualModel->GetLayoutSize();
- const Vector2 currentScrollPosition = mModel->mScrollPosition;
-
- mModel->mScrollPosition.x += xSpeed;
- mModel->mScrollPosition.y += ySpeed;
-
- ClampHorizontalScroll( layoutSize );
- ClampVerticalScroll( layoutSize );
-
- bool endOfScroll = false;
- if( Vector2::ZERO == ( currentScrollPosition - mModel->mScrollPosition ) )
- {
- // Notify the decorator there is no more text to scroll.
- // The decorator won't send more scroll events.
- mEventData->mDecorator->NotifyEndOfScroll();
- // Still need to set the position of the handle.
- endOfScroll = true;
- }
-
- // Set the position of the handle.
- const bool scrollRightDirection = xSpeed > 0.f;
- const bool scrollBottomDirection = ySpeed > 0.f;
- const bool leftSelectionHandleEvent = Event::LEFT_SELECTION_HANDLE_EVENT == event.type;
- const bool rightSelectionHandleEvent = Event::RIGHT_SELECTION_HANDLE_EVENT == event.type;
-
- if( Event::GRAB_HANDLE_EVENT == event.type )
- {
- ChangeState( EventData::GRAB_HANDLE_PANNING );
-
- // Get the grab handle position in decorator coords.
- Vector2 position = mEventData->mDecorator->GetPosition( GRAB_HANDLE );
-
- if( mEventData->mDecorator->IsHorizontalScrollEnabled() )
- {
- // Position the grag handle close to either the left or right edge.
- position.x = scrollRightDirection ? 0.f : mModel->mVisualModel->mControlSize.width;
- }
-
- if( mEventData->mDecorator->IsVerticalScrollEnabled() )
- {
- position.x = mEventData->mCursorHookPositionX;
-
- // Position the grag handle close to either the top or bottom edge.
- position.y = scrollBottomDirection ? 0.f : mModel->mVisualModel->mControlSize.height;
- }
-
- // Get the new handle position.
- // The grab handle's position is in decorator's coords. Need to transforms to text's coords.
- bool matchedCharacter = false;
- const CharacterIndex handlePosition = Text::GetClosestCursorIndex( mModel->mVisualModel,
- mModel->mLogicalModel,
- mMetrics,
- position.x - mModel->mScrollPosition.x,
- position.y - mModel->mScrollPosition.y,
- CharacterHitTest::SCROLL,
- matchedCharacter );
-
- if( mEventData->mPrimaryCursorPosition != handlePosition )
- {
- mEventData->mUpdateCursorPosition = true;
- mEventData->mUpdateGrabHandlePosition = !isSmoothHandlePanEnabled;
- mEventData->mScrollAfterUpdatePosition = true;
- mEventData->mPrimaryCursorPosition = handlePosition;
- }
- mEventData->mUpdateInputStyle = mEventData->mUpdateCursorPosition;
-
- // Updates the decorator if the soft handle panning is enabled.
- mEventData->mDecoratorUpdated = isSmoothHandlePanEnabled;
- }
- else if( leftSelectionHandleEvent || rightSelectionHandleEvent )
- {
- ChangeState( EventData::SELECTION_HANDLE_PANNING );
-
- // Get the selection handle position in decorator coords.
- Vector2 position = mEventData->mDecorator->GetPosition( leftSelectionHandleEvent ? Text::LEFT_SELECTION_HANDLE : Text::RIGHT_SELECTION_HANDLE );
-
- if( mEventData->mDecorator->IsHorizontalScrollEnabled() )
- {
- // Position the selection handle close to either the left or right edge.
- position.x = scrollRightDirection ? 0.f : mModel->mVisualModel->mControlSize.width;
- }
-
- if( mEventData->mDecorator->IsVerticalScrollEnabled() )
- {
- position.x = mEventData->mCursorHookPositionX;
-
- // Position the grag handle close to either the top or bottom edge.
- position.y = scrollBottomDirection ? 0.f : mModel->mVisualModel->mControlSize.height;
- }
-
- // Get the new handle position.
- // The selection handle's position is in decorator's coords. Need to transform to text's coords.
- bool matchedCharacter = false;
- const CharacterIndex handlePosition = Text::GetClosestCursorIndex( mModel->mVisualModel,
- mModel->mLogicalModel,
- mMetrics,
- position.x - mModel->mScrollPosition.x,
- position.y - mModel->mScrollPosition.y,
- CharacterHitTest::SCROLL,
- matchedCharacter );
-
- if( leftSelectionHandleEvent )
- {
- const bool differentHandles = ( mEventData->mLeftSelectionPosition != handlePosition ) && ( mEventData->mRightSelectionPosition != handlePosition );
-
- if( differentHandles || endOfScroll )
- {
- mEventData->mUpdateHighlightBox = true;
- mEventData->mUpdateLeftSelectionPosition = !isSmoothHandlePanEnabled;
- mEventData->mUpdateRightSelectionPosition = isSmoothHandlePanEnabled;
- mEventData->mLeftSelectionPosition = handlePosition;
- }
- }
- else
- {
- const bool differentHandles = ( mEventData->mRightSelectionPosition != handlePosition ) && ( mEventData->mLeftSelectionPosition != handlePosition );
- if( differentHandles || endOfScroll )
- {
- mEventData->mUpdateHighlightBox = true;
- mEventData->mUpdateRightSelectionPosition = !isSmoothHandlePanEnabled;
- mEventData->mUpdateLeftSelectionPosition = isSmoothHandlePanEnabled;
- mEventData->mRightSelectionPosition = handlePosition;
- }
- }
-
- if( mEventData->mUpdateLeftSelectionPosition || mEventData->mUpdateRightSelectionPosition )
- {
- RepositionSelectionHandles();
-
- mEventData->mScrollAfterUpdatePosition = !isSmoothHandlePanEnabled;
- }
- }
- mEventData->mDecoratorUpdated = true;
- } // end ( HANDLE_SCROLLING == state )
-}
-
-void Controller::Impl::OnSelectEvent( const Event& event )
-{
- if( NULL == mEventData )
- {
- // Nothing to do if there is no text.
- return;
- }
-
- if( mEventData->mSelectionEnabled )
- {
- // Convert from control's coords to text's coords.
- const float xPosition = event.p2.mFloat - mModel->mScrollPosition.x;
- const float yPosition = event.p3.mFloat - mModel->mScrollPosition.y;
-
- // Calculates the logical position from the x,y coords.
- RepositionSelectionHandles( xPosition,
- yPosition,
- Controller::NoTextTap::HIGHLIGHT );
- }
-}
-
-void Controller::Impl::OnSelectAllEvent()
-{
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "OnSelectAllEvent mEventData->mSelectionEnabled%s \n", mEventData->mSelectionEnabled?"true":"false");
-
- if( NULL == mEventData )
- {
- // Nothing to do if there is no text.
- return;
- }
-
- if( mEventData->mSelectionEnabled )
- {
- // Calculates the logical position from the start.
- RepositionSelectionHandles( 0.f - mModel->mScrollPosition.x,
- 0.f - mModel->mScrollPosition.y,
- Controller::NoTextTap::HIGHLIGHT );
-
- mEventData->mLeftSelectionPosition = 0u;
- mEventData->mRightSelectionPosition = mModel->mLogicalModel->mText.Count();
- }
-}
-
-void Controller::Impl::OnSelectNoneEvent()
-{
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "OnSelectNoneEvent mEventData->mSelectionEnabled%s \n", mEventData->mSelectionEnabled?"true":"false");
-
- if( NULL == mEventData )
- {
- // Nothing to do if there is no text.
- return;
- }
-
- if( mEventData->mSelectionEnabled && mEventData->mState == EventData::SELECTING)
- {
- mEventData->mPrimaryCursorPosition = 0u;
- mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition = mEventData->mPrimaryCursorPosition;
- ChangeState( EventData::INACTIVE );
- mEventData->mUpdateCursorPosition = true;
- mEventData->mUpdateInputStyle = true;
- mEventData->mScrollAfterUpdatePosition = true;
- }
-}
-
-void Controller::Impl::SetTextSelectionRange(const uint32_t *pStart, const uint32_t *pEnd)
-{
- if( nullptr == mEventData )
- {
- // Nothing to do if there is no text.
- return;
- }
-
- if( mEventData->mSelectionEnabled && (pStart || pEnd))
- {
- uint32_t length = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
-
- if (pStart)
- {
- mEventData->mLeftSelectionPosition = std::min(*pStart, length);
- }
- if (pEnd)
- {
- mEventData->mRightSelectionPosition = std::min(*pEnd, length);
- }
-
- if (mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition)
- {
- ChangeState( EventData::EDITING );
- mEventData->mPrimaryCursorPosition = mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition;
- mEventData->mUpdateCursorPosition = true;
- }
- else
- {
- ChangeState( EventData::SELECTING );
- mEventData->mUpdateHighlightBox = true;
- }
- }
-}
-
-Uint32Pair Controller::Impl::GetTextSelectionRange() const
-{
- Uint32Pair range;
-
- if( mEventData )
- {
- range.first = mEventData->mLeftSelectionPosition;
- range.second = mEventData->mRightSelectionPosition;
- }
-
- return range;
-}
-
-void Controller::Impl::RetrieveSelection( std::string& selectedText, bool deleteAfterRetrieval )
-{
- if( mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition )
- {
- // Nothing to select if handles are in the same place.
- selectedText.clear();