X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;ds=sidebyside;f=dali-toolkit%2Finternal%2Ftext%2Ftext-controller-impl-event-handler.cpp;h=1ed8c7f1144dee4f9dbc6ac5af58cbfc1b791a62;hb=HEAD;hp=995a8008e864297e89cfb0d71254a98ad755adfd;hpb=fa3f750c6878eb126034d7958458dc3a1f67924f;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/text/text-controller-impl-event-handler.cpp b/dali-toolkit/internal/text/text-controller-impl-event-handler.cpp deleted file mode 100644 index 995a800..0000000 --- a/dali-toolkit/internal/text/text-controller-impl-event-handler.cpp +++ /dev/null @@ -1,1009 +0,0 @@ -/* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// CLASS HEADER -#include - -// EXTERNAL INCLUDES -#include -#include - -// INTERNAL INCLUDES -#include -#include - -using namespace Dali; - -namespace -{ -#if defined(DEBUG_ENABLED) -Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS"); -#endif - -} // namespace - -namespace Dali -{ -namespace Toolkit -{ -namespace Text -{ -bool ControllerImplEventHandler::ProcessInputEvents(Controller::Impl& impl) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::ProcessInputEvents\n"); - - EventData*& eventData = impl.mEventData; - if(NULL == eventData) - { - // Nothing to do if there is no text input. - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::ProcessInputEvents no event data\n"); - return false; - } - - if(eventData->mDecorator) - { - for(std::vector::iterator iter = eventData->mEventQueue.begin(); - iter != eventData->mEventQueue.end(); - ++iter) - { - switch(iter->type) - { - case Event::CURSOR_KEY_EVENT: - { - OnCursorKeyEvent(impl, *iter); - break; - } - case Event::TAP_EVENT: - { - OnTapEvent(impl, *iter); - break; - } - case Event::LONG_PRESS_EVENT: - { - OnLongPressEvent(impl, *iter); - break; - } - case Event::PAN_EVENT: - { - OnPanEvent(impl, *iter); - break; - } - case Event::GRAB_HANDLE_EVENT: - case Event::LEFT_SELECTION_HANDLE_EVENT: - case Event::RIGHT_SELECTION_HANDLE_EVENT: // Fall through - { - OnHandleEvent(impl, *iter); - break; - } - case Event::SELECT: - { - OnSelectEvent(impl, *iter); - break; - } - case Event::SELECT_ALL: - { - OnSelectAllEvent(impl); - break; - } - case Event::SELECT_NONE: - { - OnSelectNoneEvent(impl); - break; - } - } - } - } - - if(eventData->mUpdateCursorPosition || - eventData->mUpdateHighlightBox) - { - impl.NotifyInputMethodContext(); - } - - // The cursor must also be repositioned after inserts into the model - if(eventData->mUpdateCursorPosition) - { - // Updates the cursor position and scrolls the text to make it visible. - CursorInfo cursorInfo; - // Calculate the cursor position from the new cursor index. - impl.GetCursorPosition(eventData->mPrimaryCursorPosition, cursorInfo); - - if(nullptr != impl.mEditableControlInterface) - { - impl.mEditableControlInterface->CursorMoved(eventData->mPrimaryCursorPosition); - } - - if(eventData->mUpdateCursorHookPosition) - { - // Update the cursor hook position. Used to move the cursor with the keys 'up' and 'down'. - eventData->mCursorHookPositionX = cursorInfo.primaryPosition.x; - eventData->mUpdateCursorHookPosition = false; - } - - // Scroll first the text after delete ... - if(eventData->mScrollAfterDelete) - { - impl.ScrollTextToMatchCursor(cursorInfo); - } - - // ... then, text can be scrolled to make the cursor visible. - if(eventData->mScrollAfterUpdatePosition) - { - const Vector2 currentCursorPosition(cursorInfo.primaryPosition.x, cursorInfo.lineOffset); - impl.ScrollToMakePositionVisible(currentCursorPosition, cursorInfo.lineHeight); - } - eventData->mScrollAfterUpdatePosition = false; - eventData->mScrollAfterDelete = false; - - impl.UpdateCursorPosition(cursorInfo); - - eventData->mDecoratorUpdated = true; - eventData->mUpdateCursorPosition = false; - eventData->mUpdateGrabHandlePosition = false; - } - - if(eventData->mUpdateHighlightBox || - eventData->mUpdateLeftSelectionPosition || - eventData->mUpdateRightSelectionPosition) - { - CursorInfo leftHandleInfo; - CursorInfo rightHandleInfo; - - if(eventData->mUpdateHighlightBox) - { - impl.GetCursorPosition(eventData->mLeftSelectionPosition, leftHandleInfo); - - impl.GetCursorPosition(eventData->mRightSelectionPosition, rightHandleInfo); - - if(eventData->mScrollAfterUpdatePosition && (eventData->mIsLeftHandleSelected ? eventData->mUpdateLeftSelectionPosition : eventData->mUpdateRightSelectionPosition)) - { - if(eventData->mIsLeftHandleSelected && eventData->mIsRightHandleSelected) - { - CursorInfo& infoLeft = leftHandleInfo; - - const Vector2 currentCursorPositionLeft(infoLeft.primaryPosition.x, infoLeft.lineOffset); - impl.ScrollToMakePositionVisible(currentCursorPositionLeft, infoLeft.lineHeight); - - CursorInfo& infoRight = rightHandleInfo; - - const Vector2 currentCursorPositionRight(infoRight.primaryPosition.x, infoRight.lineOffset); - impl.ScrollToMakePositionVisible(currentCursorPositionRight, infoRight.lineHeight); - } - else - { - CursorInfo& info = eventData->mIsLeftHandleSelected ? leftHandleInfo : rightHandleInfo; - - const Vector2 currentCursorPosition(info.primaryPosition.x, info.lineOffset); - impl.ScrollToMakePositionVisible(currentCursorPosition, info.lineHeight); - } - } - } - - if(eventData->mUpdateLeftSelectionPosition) - { - impl.UpdateSelectionHandle(LEFT_SELECTION_HANDLE, leftHandleInfo); - - impl.SetPopupButtons(); - eventData->mDecoratorUpdated = true; - eventData->mUpdateLeftSelectionPosition = false; - } - - if(eventData->mUpdateRightSelectionPosition) - { - impl.UpdateSelectionHandle(RIGHT_SELECTION_HANDLE, rightHandleInfo); - - impl.SetPopupButtons(); - eventData->mDecoratorUpdated = true; - eventData->mUpdateRightSelectionPosition = false; - } - - if(eventData->mUpdateHighlightBox) - { - impl.RepositionSelectionHandles(); - - eventData->mUpdateLeftSelectionPosition = false; - eventData->mUpdateRightSelectionPosition = false; - eventData->mUpdateHighlightBox = false; - eventData->mIsLeftHandleSelected = false; - eventData->mIsRightHandleSelected = false; - } - - eventData->mScrollAfterUpdatePosition = false; - } - - if(eventData->mUpdateInputStyle) - { - // Keep a copy of the current input style. - InputStyle currentInputStyle; - currentInputStyle.Copy(eventData->mInputStyle); - - // Set the default style first. - impl.RetrieveDefaultInputStyle(eventData->mInputStyle); - - // Get the character index from the cursor index. - const CharacterIndex styleIndex = (eventData->mPrimaryCursorPosition > 0u) ? eventData->mPrimaryCursorPosition - 1u : 0u; - - // Retrieve the style from the style runs stored in the logical model. - impl.mModel->mLogicalModel->RetrieveStyle(styleIndex, eventData->mInputStyle); - - // Compare if the input style has changed. - const bool hasInputStyleChanged = !currentInputStyle.Equal(eventData->mInputStyle); - - if(hasInputStyleChanged) - { - const InputStyle::Mask styleChangedMask = currentInputStyle.GetInputStyleChangeMask(eventData->mInputStyle); - // Queue the input style changed signal. - eventData->mInputStyleChangedQueue.PushBack(styleChangedMask); - } - - eventData->mUpdateInputStyle = false; - } - - eventData->mEventQueue.clear(); - - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::ProcessInputEvents\n"); - - const bool decoratorUpdated = eventData->mDecoratorUpdated; - eventData->mDecoratorUpdated = false; - - return decoratorUpdated; -} - -void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const Event& event) -{ - if(NULL == impl.mEventData || !impl.IsShowingRealText()) - { - // Nothing to do if there is no text input. - return; - } - - int keyCode = event.p1.mInt; - bool isShiftModifier = event.p2.mBool; - EventData& eventData = *impl.mEventData; - ModelPtr& model = impl.mModel; - LogicalModelPtr& logicalModel = model->mLogicalModel; - VisualModelPtr& visualModel = model->mVisualModel; - - CharacterIndex& primaryCursorPosition = eventData.mPrimaryCursorPosition; - CharacterIndex previousPrimaryCursorPosition = primaryCursorPosition; - - if(Dali::DALI_KEY_CURSOR_LEFT == keyCode) - { - if(primaryCursorPosition > 0u) - { - if(!isShiftModifier && eventData.mDecorator->IsHighlightVisible()) - { - primaryCursorPosition = std::min(eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition); - } - else - { - primaryCursorPosition = impl.CalculateNewCursorIndex(primaryCursorPosition - 1u); - } - } - } - else if(Dali::DALI_KEY_CURSOR_RIGHT == keyCode) - { - if(logicalModel->mText.Count() > primaryCursorPosition) - { - if(!isShiftModifier && eventData.mDecorator->IsHighlightVisible()) - { - primaryCursorPosition = std::max(eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition); - } - else - { - primaryCursorPosition = impl.CalculateNewCursorIndex(primaryCursorPosition); - } - } - } - else if(Dali::DALI_KEY_CURSOR_UP == keyCode && !isShiftModifier) - { - // Ignore Shift-Up for text selection for now. - - // Get first the line index of the current cursor position index. - CharacterIndex characterIndex = 0u; - - if(primaryCursorPosition > 0u) - { - characterIndex = primaryCursorPosition - 1u; - } - - const LineIndex lineIndex = visualModel->GetLineOfCharacter(characterIndex); - const LineIndex previousLineIndex = (lineIndex > 0 ? lineIndex - 1u : lineIndex); - - // Retrieve the cursor position info. - CursorInfo cursorInfo; - impl.GetCursorPosition(primaryCursorPosition, - cursorInfo); - - // Get the line above. - const LineRun& line = *(visualModel->mLines.Begin() + previousLineIndex); - - // Get the next hit 'y' point. - const float hitPointY = cursorInfo.lineOffset - 0.5f * (line.ascender - line.descender); - - // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index. - bool matchedCharacter = false; - primaryCursorPosition = Text::GetClosestCursorIndex(visualModel, - logicalModel, - impl.mMetrics, - eventData.mCursorHookPositionX, - hitPointY, - CharacterHitTest::TAP, - matchedCharacter); - } - else if(Dali::DALI_KEY_CURSOR_DOWN == keyCode && !isShiftModifier) - { - // Ignore Shift-Down for text selection for now. - - // Get first the line index of the current cursor position index. - CharacterIndex characterIndex = 0u; - - if(primaryCursorPosition > 0u) - { - characterIndex = primaryCursorPosition - 1u; - } - - const LineIndex lineIndex = visualModel->GetLineOfCharacter(characterIndex); - - if(lineIndex + 1u < visualModel->mLines.Count()) - { - // Retrieve the cursor position info. - CursorInfo cursorInfo; - impl.GetCursorPosition(primaryCursorPosition, cursorInfo); - - // Get the line below. - const LineRun& line = *(visualModel->mLines.Begin() + lineIndex + 1u); - - // Get the next hit 'y' point. - const float hitPointY = cursorInfo.lineOffset + cursorInfo.lineHeight + 0.5f * (line.ascender - line.descender); - - // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index. - bool matchedCharacter = false; - primaryCursorPosition = Text::GetClosestCursorIndex(visualModel, - logicalModel, - impl.mMetrics, - eventData.mCursorHookPositionX, - hitPointY, - CharacterHitTest::TAP, - matchedCharacter); - } - } - - if(!isShiftModifier && eventData.mState != EventData::SELECTING) - { - // Update selection position after moving the cursor - eventData.mLeftSelectionPosition = primaryCursorPosition; - eventData.mRightSelectionPosition = primaryCursorPosition; - } - - if(isShiftModifier && impl.IsShowingRealText() && eventData.mShiftSelectionFlag) - { - // Handle text selection - bool selecting = false; - - if(Dali::DALI_KEY_CURSOR_LEFT == keyCode || Dali::DALI_KEY_CURSOR_RIGHT == keyCode) - { - // Shift-Left/Right to select the text - int cursorPositionDelta = primaryCursorPosition - previousPrimaryCursorPosition; - if(cursorPositionDelta > 0 || eventData.mRightSelectionPosition > 0u) // Check the boundary - { - eventData.mRightSelectionPosition += cursorPositionDelta; - } - selecting = true; - } - else if(eventData.mLeftSelectionPosition != eventData.mRightSelectionPosition) - { - // Show no grab handles and text highlight if Shift-Up/Down pressed but no selected text - selecting = true; - } - - if(selecting) - { - // Notify the cursor position to the InputMethodContext. - if(eventData.mInputMethodContext) - { - eventData.mInputMethodContext.SetCursorPosition(primaryCursorPosition); - eventData.mInputMethodContext.NotifyCursorPosition(); - } - - impl.ChangeState(EventData::SELECTING); - - eventData.mUpdateLeftSelectionPosition = true; - eventData.mUpdateRightSelectionPosition = true; - eventData.mUpdateGrabHandlePosition = true; - eventData.mUpdateHighlightBox = true; - - // Hide the text selection popup if select the text using keyboard instead of moving grab handles - if(eventData.mGrabHandlePopupEnabled) - { - eventData.mDecorator->SetPopupActive(false); - } - } - } - else - { - // Handle normal cursor move - impl.ChangeState(EventData::EDITING); - eventData.mUpdateCursorPosition = true; - } - - eventData.mUpdateInputStyle = true; - eventData.mScrollAfterUpdatePosition = true; -} - -void ControllerImplEventHandler::OnTapEvent(Controller::Impl& impl, const Event& event) -{ - if(impl.mEventData) - { - const unsigned int tapCount = event.p1.mUint; - EventData& eventData = *impl.mEventData; - ModelPtr& model = impl.mModel; - LogicalModelPtr& logicalModel = model->mLogicalModel; - VisualModelPtr& visualModel = model->mVisualModel; - - if(1u == tapCount) - { - if(impl.IsShowingRealText()) - { - // Convert from control's coords to text's coords. - const float xPosition = event.p2.mFloat - model->mScrollPosition.x; - const float yPosition = event.p3.mFloat - model->mScrollPosition.y; - - // Keep the tap 'x' position. Used to move the cursor. - eventData.mCursorHookPositionX = xPosition; - - // Whether to touch point hits on a glyph. - bool matchedCharacter = false; - eventData.mPrimaryCursorPosition = Text::GetClosestCursorIndex(visualModel, - logicalModel, - impl.mMetrics, - xPosition, - yPosition, - CharacterHitTest::TAP, - matchedCharacter); - - // When the cursor position is changing, delay cursor blinking - eventData.mDecorator->DelayCursorBlink(); - } - else - { - eventData.mPrimaryCursorPosition = 0u; - } - - // Update selection position after tapping - eventData.mLeftSelectionPosition = eventData.mPrimaryCursorPosition; - eventData.mRightSelectionPosition = eventData.mPrimaryCursorPosition; - - eventData.mUpdateCursorPosition = true; - eventData.mUpdateGrabHandlePosition = true; - eventData.mScrollAfterUpdatePosition = true; - eventData.mUpdateInputStyle = true; - - // Notify the cursor position to the InputMethodContext. - if(eventData.mInputMethodContext) - { - eventData.mInputMethodContext.SetCursorPosition(eventData.mPrimaryCursorPosition); - eventData.mInputMethodContext.NotifyCursorPosition(); - } - } - else if(2u == tapCount) - { - if(eventData.mSelectionEnabled) - { - // Convert from control's coords to text's coords. - const float xPosition = event.p2.mFloat - model->mScrollPosition.x; - const float yPosition = event.p3.mFloat - model->mScrollPosition.y; - - // Calculates the logical position from the x,y coords. - impl.RepositionSelectionHandles(xPosition, yPosition, eventData.mDoubleTapAction); - } - } - } -} - -void ControllerImplEventHandler::OnPanEvent(Controller::Impl& impl, const Event& event) -{ - if(impl.mEventData) - { - EventData& eventData = *impl.mEventData; - DecoratorPtr& decorator = eventData.mDecorator; - - const bool isHorizontalScrollEnabled = decorator->IsHorizontalScrollEnabled(); - const bool isVerticalScrollEnabled = decorator->IsVerticalScrollEnabled(); - - if(!isHorizontalScrollEnabled && !isVerticalScrollEnabled) - { - // Nothing to do if scrolling is not enabled. - return; - } - - const GestureState state = static_cast(event.p1.mInt); - switch(state) - { - case GestureState::STARTED: - { - // Will remove the cursor, handles or text's popup, ... - impl.ChangeState(EventData::TEXT_PANNING); - break; - } - case GestureState::CONTINUING: - { - ModelPtr& model = impl.mModel; - - const Vector2& layoutSize = model->mVisualModel->GetLayoutSize(); - Vector2& scrollPosition = model->mScrollPosition; - const Vector2 currentScroll = scrollPosition; - - if(isHorizontalScrollEnabled) - { - const float displacementX = event.p2.mFloat; - scrollPosition.x += displacementX; - - impl.ClampHorizontalScroll(layoutSize); - } - - if(isVerticalScrollEnabled) - { - const float displacementY = event.p3.mFloat; - scrollPosition.y += displacementY; - - impl.ClampVerticalScroll(layoutSize); - } - - decorator->UpdatePositions(scrollPosition - 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, ... - impl.ChangeState(eventData.mPreviousState); - break; - } - default: - break; - } - } -} - -void ControllerImplEventHandler::OnLongPressEvent(Controller::Impl& impl, const Event& event) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::OnLongPressEvent\n"); - - if(impl.mEventData) - { - EventData& eventData = *impl.mEventData; - - if(!impl.IsShowingRealText() && (EventData::EDITING == eventData.mState)) - { - impl.ChangeState(EventData::EDITING_WITH_POPUP); - eventData.mDecoratorUpdated = true; - eventData.mUpdateInputStyle = true; - } - else - { - if(eventData.mSelectionEnabled) - { - ModelPtr& model = impl.mModel; - - // Convert from control's coords to text's coords. - const float xPosition = event.p2.mFloat - model->mScrollPosition.x; - const float yPosition = event.p3.mFloat - model->mScrollPosition.y; - - // Calculates the logical position from the x,y coords. - impl.RepositionSelectionHandles(xPosition, yPosition, eventData.mLongPressAction); - } - } - } -} - -void ControllerImplEventHandler::OnHandleEvent(Controller::Impl& impl, const Event& event) -{ - if(impl.mEventData) - { - const unsigned int state = event.p1.mUint; - const bool handleStopScrolling = (HANDLE_STOP_SCROLLING == state); - const bool isSmoothHandlePanEnabled = impl.mEventData->mDecorator->IsSmoothHandlePanEnabled(); - - if(HANDLE_PRESSED == state) - { - OnHandlePressed(impl, event, isSmoothHandlePanEnabled); - } // end ( HANDLE_PRESSED == state ) - else if((HANDLE_RELEASED == state) || - handleStopScrolling) - { - OnHandleReleased(impl, event, isSmoothHandlePanEnabled, handleStopScrolling); - } // end ( ( HANDLE_RELEASED == state ) || ( HANDLE_STOP_SCROLLING == state ) ) - else if(HANDLE_SCROLLING == state) - { - OnHandleScrolling(impl, event, isSmoothHandlePanEnabled); - } // end ( HANDLE_SCROLLING == state ) - } -} - -void ControllerImplEventHandler::OnSelectEvent(Controller::Impl& impl, const Event& event) -{ - if(impl.mEventData && impl.mEventData->mSelectionEnabled) - { - ModelPtr& model = impl.mModel; - const Vector2& scrollPosition = model->mScrollPosition; - - // Convert from control's coords to text's coords. - const float xPosition = event.p2.mFloat - scrollPosition.x; - const float yPosition = event.p3.mFloat - scrollPosition.y; - - // Calculates the logical position from the x,y coords. - impl.RepositionSelectionHandles(xPosition, yPosition, Controller::NoTextTap::HIGHLIGHT); - } -} - -void ControllerImplEventHandler::OnSelectAllEvent(Controller::Impl& impl) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "OnSelectAllEvent mEventData->mSelectionEnabled%s \n", impl.mEventData->mSelectionEnabled ? "true" : "false"); - - if(impl.mEventData) - { - EventData& eventData = *impl.mEventData; - if(eventData.mSelectionEnabled) - { - ModelPtr& model = impl.mModel; - const Vector2& scrollPosition = model->mScrollPosition; - - // Calculates the logical position from the start. - impl.RepositionSelectionHandles(0.f - scrollPosition.x, - 0.f - scrollPosition.y, - Controller::NoTextTap::HIGHLIGHT); - - eventData.mLeftSelectionPosition = 0u; - eventData.mRightSelectionPosition = model->mLogicalModel->mText.Count(); - } - } -} - -void ControllerImplEventHandler::OnSelectNoneEvent(Controller::Impl& impl) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "OnSelectNoneEvent mEventData->mSelectionEnabled%s \n", impl.mEventData->mSelectionEnabled ? "true" : "false"); - - if(impl.mEventData) - { - EventData& eventData = *impl.mEventData; - if(eventData.mSelectionEnabled && eventData.mState == EventData::SELECTING) - { - eventData.mPrimaryCursorPosition = 0u; - eventData.mLeftSelectionPosition = eventData.mRightSelectionPosition = eventData.mPrimaryCursorPosition; - impl.ChangeState(EventData::INACTIVE); - eventData.mUpdateCursorPosition = true; - eventData.mUpdateInputStyle = true; - eventData.mScrollAfterUpdatePosition = true; - } - } -} - -void ControllerImplEventHandler::OnHandlePressed(Controller::Impl& impl, const Event& event, const bool isSmoothHandlePanEnabled) -{ - ModelPtr& model = impl.mModel; - const Vector2& scrollPosition = model->mScrollPosition; - - // Convert from decorator's coords to text's coords. - const float xPosition = event.p2.mFloat - scrollPosition.x; - const float yPosition = event.p3.mFloat - scrollPosition.y; - - // Need to calculate the handle's new position. - bool matchedCharacter = false; - const CharacterIndex handleNewPosition = Text::GetClosestCursorIndex(model->mVisualModel, - model->mLogicalModel, - impl.mMetrics, - xPosition, - yPosition, - CharacterHitTest::SCROLL, - matchedCharacter); - - EventData& eventData = *impl.mEventData; - - if(Event::GRAB_HANDLE_EVENT == event.type) - { - impl.ChangeState(EventData::GRAB_HANDLE_PANNING); - - if(handleNewPosition != eventData.mPrimaryCursorPosition) - { - // Updates the cursor position if the handle's new position is different than the current one. - eventData.mUpdateCursorPosition = true; - // Does not update the grab handle position if the smooth panning is enabled. (The decorator does it smooth). - eventData.mUpdateGrabHandlePosition = !isSmoothHandlePanEnabled; - eventData.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. - eventData.mDecoratorUpdated = isSmoothHandlePanEnabled; - } - else if(Event::LEFT_SELECTION_HANDLE_EVENT == event.type) - { - impl.ChangeState(EventData::SELECTION_HANDLE_PANNING); - - if((handleNewPosition != eventData.mLeftSelectionPosition) && - (handleNewPosition != eventData.mRightSelectionPosition)) - { - // Updates the highlight box if the handle's new position is different than the current one. - eventData.mUpdateHighlightBox = true; - // Does not update the selection handle position if the smooth panning is enabled. (The decorator does it smooth). - eventData.mUpdateLeftSelectionPosition = !isSmoothHandlePanEnabled; - eventData.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. - eventData.mDecoratorUpdated = isSmoothHandlePanEnabled; - - // Will define the order to scroll the text to match the handle position. - eventData.mIsLeftHandleSelected = true; - eventData.mIsRightHandleSelected = false; - } - else if(Event::RIGHT_SELECTION_HANDLE_EVENT == event.type) - { - impl.ChangeState(EventData::SELECTION_HANDLE_PANNING); - - if((handleNewPosition != eventData.mRightSelectionPosition) && - (handleNewPosition != eventData.mLeftSelectionPosition)) - { - // Updates the highlight box if the handle's new position is different than the current one. - eventData.mUpdateHighlightBox = true; - // Does not update the selection handle position if the smooth panning is enabled. (The decorator does it smooth). - eventData.mUpdateRightSelectionPosition = !isSmoothHandlePanEnabled; - eventData.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. - eventData.mDecoratorUpdated = isSmoothHandlePanEnabled; - - // Will define the order to scroll the text to match the handle position. - eventData.mIsLeftHandleSelected = false; - eventData.mIsRightHandleSelected = true; - } -} - -void ControllerImplEventHandler::OnHandleReleased(Controller::Impl& impl, const Event& event, const bool isSmoothHandlePanEnabled, const bool handleStopScrolling) -{ - CharacterIndex handlePosition = 0u; - if(handleStopScrolling || isSmoothHandlePanEnabled) - { - ModelPtr& model = impl.mModel; - const Vector2& scrollPosition = model->mScrollPosition; - - // Convert from decorator's coords to text's coords. - const float xPosition = event.p2.mFloat - scrollPosition.x; - const float yPosition = event.p3.mFloat - scrollPosition.y; - - bool matchedCharacter = false; - handlePosition = Text::GetClosestCursorIndex(model->mVisualModel, - model->mLogicalModel, - impl.mMetrics, - xPosition, - yPosition, - CharacterHitTest::SCROLL, - matchedCharacter); - } - - EventData& eventData = *impl.mEventData; - - if(Event::GRAB_HANDLE_EVENT == event.type) - { - eventData.mUpdateCursorPosition = true; - eventData.mUpdateGrabHandlePosition = true; - eventData.mUpdateInputStyle = true; - - if(!impl.IsClipboardEmpty()) - { - impl.ChangeState(EventData::EDITING_WITH_PASTE_POPUP); // Moving grabhandle will show Paste Popup - } - - if(handleStopScrolling || isSmoothHandlePanEnabled) - { - eventData.mScrollAfterUpdatePosition = true; - eventData.mPrimaryCursorPosition = handlePosition; - } - } - else if(Event::LEFT_SELECTION_HANDLE_EVENT == event.type) - { - impl.ChangeState(EventData::SELECTING); - - eventData.mUpdateHighlightBox = true; - eventData.mUpdateLeftSelectionPosition = true; - eventData.mUpdateRightSelectionPosition = true; - - if(handleStopScrolling || isSmoothHandlePanEnabled) - { - eventData.mScrollAfterUpdatePosition = true; - - if((handlePosition != eventData.mRightSelectionPosition) && - (handlePosition != eventData.mLeftSelectionPosition)) - { - eventData.mLeftSelectionPosition = handlePosition; - } - } - } - else if(Event::RIGHT_SELECTION_HANDLE_EVENT == event.type) - { - impl.ChangeState(EventData::SELECTING); - - eventData.mUpdateHighlightBox = true; - eventData.mUpdateRightSelectionPosition = true; - eventData.mUpdateLeftSelectionPosition = true; - - if(handleStopScrolling || isSmoothHandlePanEnabled) - { - eventData.mScrollAfterUpdatePosition = true; - if((handlePosition != eventData.mRightSelectionPosition) && - (handlePosition != eventData.mLeftSelectionPosition)) - { - eventData.mRightSelectionPosition = handlePosition; - } - } - } - - eventData.mDecoratorUpdated = true; -} - -void ControllerImplEventHandler::OnHandleScrolling(Controller::Impl& impl, const Event& event, const bool isSmoothHandlePanEnabled) -{ - ModelPtr& model = impl.mModel; - Vector2& scrollPosition = model->mScrollPosition; - VisualModelPtr& visualModel = model->mVisualModel; - - const float xSpeed = event.p2.mFloat; - const float ySpeed = event.p3.mFloat; - const Vector2& layoutSize = visualModel->GetLayoutSize(); - const Vector2 currentScrollPosition = scrollPosition; - - scrollPosition.x += xSpeed; - scrollPosition.y += ySpeed; - - impl.ClampHorizontalScroll(layoutSize); - impl.ClampVerticalScroll(layoutSize); - - EventData& eventData = *impl.mEventData; - DecoratorPtr& decorator = eventData.mDecorator; - - bool endOfScroll = false; - if(Vector2::ZERO == (currentScrollPosition - scrollPosition)) - { - // Notify the decorator there is no more text to scroll. - // The decorator won't send more scroll events. - decorator->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) - { - impl.ChangeState(EventData::GRAB_HANDLE_PANNING); - - // Get the grab handle position in decorator coords. - Vector2 position = decorator->GetPosition(GRAB_HANDLE); - - if(decorator->IsHorizontalScrollEnabled()) - { - // Position the grag handle close to either the left or right edge. - position.x = scrollRightDirection ? 0.f : visualModel->mControlSize.width; - } - - if(decorator->IsVerticalScrollEnabled()) - { - position.x = eventData.mCursorHookPositionX; - - // Position the grag handle close to either the top or bottom edge. - position.y = scrollBottomDirection ? 0.f : visualModel->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(visualModel, - impl.mModel->mLogicalModel, - impl.mMetrics, - position.x - scrollPosition.x, - position.y - scrollPosition.y, - CharacterHitTest::SCROLL, - matchedCharacter); - - if(eventData.mPrimaryCursorPosition != handlePosition) - { - eventData.mUpdateCursorPosition = true; - eventData.mUpdateGrabHandlePosition = !isSmoothHandlePanEnabled; - eventData.mScrollAfterUpdatePosition = true; - eventData.mPrimaryCursorPosition = handlePosition; - } - eventData.mUpdateInputStyle = eventData.mUpdateCursorPosition; - - // Updates the decorator if the soft handle panning is enabled. - eventData.mDecoratorUpdated = isSmoothHandlePanEnabled; - } - else if(leftSelectionHandleEvent || rightSelectionHandleEvent) - { - impl.ChangeState(EventData::SELECTION_HANDLE_PANNING); - - // Get the selection handle position in decorator coords. - Vector2 position = decorator->GetPosition(leftSelectionHandleEvent ? Text::LEFT_SELECTION_HANDLE : Text::RIGHT_SELECTION_HANDLE); - - if(decorator->IsHorizontalScrollEnabled()) - { - // Position the selection handle close to either the left or right edge. - position.x = scrollRightDirection ? 0.f : visualModel->mControlSize.width; - } - - if(decorator->IsVerticalScrollEnabled()) - { - position.x = eventData.mCursorHookPositionX; - - // Position the grag handle close to either the top or bottom edge. - position.y = scrollBottomDirection ? 0.f : visualModel->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(visualModel, - impl.mModel->mLogicalModel, - impl.mMetrics, - position.x - scrollPosition.x, - position.y - scrollPosition.y, - CharacterHitTest::SCROLL, - matchedCharacter); - - if(leftSelectionHandleEvent) - { - const bool differentHandles = (eventData.mLeftSelectionPosition != handlePosition) && (eventData.mRightSelectionPosition != handlePosition); - - if(differentHandles || endOfScroll) - { - eventData.mUpdateHighlightBox = true; - eventData.mUpdateLeftSelectionPosition = !isSmoothHandlePanEnabled; - eventData.mUpdateRightSelectionPosition = isSmoothHandlePanEnabled; - eventData.mLeftSelectionPosition = handlePosition; - } - } - else - { - const bool differentHandles = (eventData.mRightSelectionPosition != handlePosition) && (eventData.mLeftSelectionPosition != handlePosition); - if(differentHandles || endOfScroll) - { - eventData.mUpdateHighlightBox = true; - eventData.mUpdateRightSelectionPosition = !isSmoothHandlePanEnabled; - eventData.mUpdateLeftSelectionPosition = isSmoothHandlePanEnabled; - eventData.mRightSelectionPosition = handlePosition; - } - } - - if(eventData.mUpdateLeftSelectionPosition || eventData.mUpdateRightSelectionPosition) - { - impl.RepositionSelectionHandles(); - - eventData.mScrollAfterUpdatePosition = !isSmoothHandlePanEnabled; - } - } - eventData.mDecoratorUpdated = true; -} - -} // namespace Text - -} // namespace Toolkit - -} // namespace Dali