X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Ftext-controller-impl.cpp;h=b0aa82e1372af2ef5e9e61d20b50026663bf0578;hp=c39d5e85d94313ed43b191f64fde4b7dab732a88;hb=8a647e87a01c5c78451653c1264a9eea81ac9b20;hpb=746c9a68c411a98ba9e853609775a1519ae5bcd9 diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp old mode 100755 new mode 100644 index c39d5e8..b0aa82e --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 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. @@ -19,7 +19,6 @@ #include // EXTERNAL INCLUDES -#include #include #include #include @@ -34,7 +33,9 @@ #include #include #include +#include #include +#include using namespace Dali; @@ -53,7 +54,7 @@ struct SelectionBoxInfo }; #if defined(DEBUG_ENABLED) - Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS"); +Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS"); #endif const float MAX_FLOAT = std::numeric_limits::max(); @@ -159,7 +160,8 @@ EventData::EventData( DecoratorPtr decorator, InputMethodContext& inputMethodCon mIsPlaceholderElideEnabled( false ), mPlaceholderEllipsisFlag( false ), mShiftSelectionFlag( true ), - mUpdateAlignment( false ) + mUpdateAlignment( false ), + mEditingEnabled( true ) { } @@ -221,6 +223,11 @@ bool Controller::Impl::ProcessInputEvents() OnSelectAllEvent(); break; } + case Event::SELECT_NONE: + { + OnSelectNoneEvent(); + break; + } } } } @@ -240,6 +247,11 @@ bool Controller::Impl::ProcessInputEvents() GetCursorPosition( mEventData->mPrimaryCursorPosition, cursorInfo ); + if( NULL != mEditableControlInterface ) + { + mEditableControlInterface->CaretMoved( mEventData->mPrimaryCursorPosition ); + } + if( mEventData->mUpdateCursorHookPosition ) { // Update the cursor hook position. Used to move the cursor with the keys 'up' and 'down'. @@ -1086,16 +1098,16 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired ) mEventData->mPreEditFlag && ( 0u != mModel->mVisualModel->mCharactersToGlyph.Count() ) ) { - Vector< Dali::InputMethodContext::PreeditAttributeData > attrs; + Dali::InputMethodContext::PreEditAttributeDataContainer attrs; mEventData->mInputMethodContext.GetPreeditStyle( attrs ); Dali::InputMethodContext::PreeditStyle type = Dali::InputMethodContext::PreeditStyle::NONE; // Check the type of preedit and run it. - for( Vector::Iterator it = attrs.Begin(), endIt = attrs.End(); it != endIt; it++ ) + for( Dali::InputMethodContext::PreEditAttributeDataContainer::Iterator it = attrs.Begin(), endIt = attrs.End(); it != endIt; it++ ) { Dali::InputMethodContext::PreeditAttributeData attrData = *it; DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::UpdateModel PreeditStyle type : %d start %d end %d \n", attrData.preeditType, attrData.startIndex, attrData.endIndex ); - type = attrData.preeditType; + type = attrData.preeditType; // Check the number of commit characters for the start position. unsigned int numberOfCommit = mEventData->mPrimaryCursorPosition - mEventData->mPreEditLength; @@ -1108,7 +1120,7 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired ) // Add the underline for the pre-edit text. GlyphRun underlineRun; underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; - underlineRun.numberOfGlyphs = attrData.endIndex - attrData.startIndex; + underlineRun.numberOfGlyphs = numberOfIndices; mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun ); break; } @@ -1152,7 +1164,7 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired ) GlyphRun underlineRun; underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; - underlineRun.numberOfGlyphs = attrData.endIndex - attrData.startIndex; + underlineRun.numberOfGlyphs = numberOfIndices; mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun ); break; } @@ -1167,7 +1179,7 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired ) GlyphRun underlineRun; underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; - underlineRun.numberOfGlyphs = attrData.endIndex - attrData.startIndex; + underlineRun.numberOfGlyphs = numberOfIndices; mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun ); break; } @@ -1182,7 +1194,7 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired ) GlyphRun underlineRun; underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; - underlineRun.numberOfGlyphs = attrData.endIndex - attrData.startIndex; + underlineRun.numberOfGlyphs = numberOfIndices; mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun ); break; } @@ -1197,7 +1209,7 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired ) GlyphRun underlineRun; underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; - underlineRun.numberOfGlyphs = attrData.endIndex - attrData.startIndex; + underlineRun.numberOfGlyphs = numberOfIndices; mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun ); break; } @@ -1335,683 +1347,104 @@ float Controller::Impl::GetDefaultFontLineHeight() void Controller::Impl::OnCursorKeyEvent( const Event& event ) { - if( NULL == mEventData || !IsShowingRealText() ) - { - // Nothing to do if there is no text input. - return; - } - - int keyCode = event.p1.mInt; - bool isShiftModifier = event.p2.mBool; - - CharacterIndex previousPrimaryCursorPosition = mEventData->mPrimaryCursorPosition; - - if( Dali::DALI_KEY_CURSOR_LEFT == keyCode ) - { - if( mEventData->mPrimaryCursorPosition > 0u ) - { - if ( !isShiftModifier && mEventData->mDecorator->IsHighlightVisible() ) - { - mEventData->mPrimaryCursorPosition = std::min(mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition); - } - else - { - mEventData->mPrimaryCursorPosition = CalculateNewCursorIndex( mEventData->mPrimaryCursorPosition - 1u ); - } - } - } - else if( Dali::DALI_KEY_CURSOR_RIGHT == keyCode ) - { - if( mModel->mLogicalModel->mText.Count() > mEventData->mPrimaryCursorPosition ) - { - if ( !isShiftModifier && mEventData->mDecorator->IsHighlightVisible() ) - { - mEventData->mPrimaryCursorPosition = std::max(mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition); - } - else - { - mEventData->mPrimaryCursorPosition = CalculateNewCursorIndex( mEventData->mPrimaryCursorPosition ); - } - } - } - 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( mEventData->mPrimaryCursorPosition > 0u ) - { - characterIndex = mEventData->mPrimaryCursorPosition - 1u; - } - - const LineIndex lineIndex = mModel->mVisualModel->GetLineOfCharacter( characterIndex ); - const LineIndex previousLineIndex = ( lineIndex > 0 ? lineIndex - 1u : lineIndex ); - - // Retrieve the cursor position info. - CursorInfo cursorInfo; - GetCursorPosition( mEventData->mPrimaryCursorPosition, - cursorInfo ); - - // Get the line above. - const LineRun& line = *( mModel->mVisualModel->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; - mEventData->mPrimaryCursorPosition = Text::GetClosestCursorIndex( mModel->mVisualModel, - mModel->mLogicalModel, - mMetrics, - mEventData->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( mEventData->mPrimaryCursorPosition > 0u ) - { - characterIndex = mEventData->mPrimaryCursorPosition - 1u; - } - - const LineIndex lineIndex = mModel->mVisualModel->GetLineOfCharacter( characterIndex ); - - if( lineIndex + 1u < mModel->mVisualModel->mLines.Count() ) - { - // Retrieve the cursor position info. - CursorInfo cursorInfo; - GetCursorPosition( mEventData->mPrimaryCursorPosition, - cursorInfo ); - - // Get the line below. - const LineRun& line = *( mModel->mVisualModel->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; - mEventData->mPrimaryCursorPosition = Text::GetClosestCursorIndex( mModel->mVisualModel, - mModel->mLogicalModel, - mMetrics, - mEventData->mCursorHookPositionX, - hitPointY, - CharacterHitTest::TAP, - matchedCharacter ); - } - } - - if ( !isShiftModifier && mEventData->mState != EventData::SELECTING ) - { - // Update selection position after moving the cursor - mEventData->mLeftSelectionPosition = mEventData->mPrimaryCursorPosition; - mEventData->mRightSelectionPosition = mEventData->mPrimaryCursorPosition; - } - - if ( isShiftModifier && IsShowingRealText() && mEventData->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 = mEventData->mPrimaryCursorPosition - previousPrimaryCursorPosition; - if ( cursorPositionDelta > 0 || mEventData->mRightSelectionPosition > 0u ) // Check the boundary - { - mEventData->mRightSelectionPosition += cursorPositionDelta; - } - selecting = true; - } - else if ( mEventData->mLeftSelectionPosition != mEventData->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( mEventData->mInputMethodContext ) - { - mEventData->mInputMethodContext.SetCursorPosition( mEventData->mPrimaryCursorPosition ); - mEventData->mInputMethodContext.NotifyCursorPosition(); - } - - ChangeState( EventData::SELECTING ); - - mEventData->mUpdateLeftSelectionPosition = true; - mEventData->mUpdateRightSelectionPosition = true; - mEventData->mUpdateGrabHandlePosition = true; - mEventData->mUpdateHighlightBox = true; - - // Hide the text selection popup if select the text using keyboard instead of moving grab handles - if( mEventData->mGrabHandlePopupEnabled ) - { - mEventData->mDecorator->SetPopupActive( false ); - } - } - } - else - { - // Handle normal cursor move - ChangeState( EventData::EDITING ); - mEventData->mUpdateCursorPosition = true; - } - - mEventData->mUpdateInputStyle = true; - mEventData->mScrollAfterUpdatePosition = true; + ControllerImplEventHandler::OnCursorKeyEvent(*this, event); } void Controller::Impl::OnTapEvent( const Event& event ) { - if( NULL != mEventData ) - { - const unsigned int tapCount = event.p1.mUint; - - if( 1u == tapCount ) - { - if( IsShowingRealText() ) - { - // 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; - - // Keep the tap 'x' position. Used to move the cursor. - mEventData->mCursorHookPositionX = xPosition; - - // Whether to touch point hits on a glyph. - bool matchedCharacter = false; - mEventData->mPrimaryCursorPosition = Text::GetClosestCursorIndex( mModel->mVisualModel, - mModel->mLogicalModel, - mMetrics, - xPosition, - yPosition, - CharacterHitTest::TAP, - matchedCharacter ); - - // When the cursor position is changing, delay cursor blinking - mEventData->mDecorator->DelayCursorBlink(); - } - else - { - mEventData->mPrimaryCursorPosition = 0u; - } - - // Update selection position after tapping - mEventData->mLeftSelectionPosition = mEventData->mPrimaryCursorPosition; - mEventData->mRightSelectionPosition = mEventData->mPrimaryCursorPosition; - - mEventData->mUpdateCursorPosition = true; - mEventData->mUpdateGrabHandlePosition = true; - mEventData->mScrollAfterUpdatePosition = true; - mEventData->mUpdateInputStyle = true; - - // Notify the cursor position to the InputMethodContext. - if( mEventData->mInputMethodContext ) - { - mEventData->mInputMethodContext.SetCursorPosition( mEventData->mPrimaryCursorPosition ); - mEventData->mInputMethodContext.NotifyCursorPosition(); - } - } - else if( 2u == tapCount ) - { - 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->mDoubleTapAction ); - } - } - } + ControllerImplEventHandler::OnTapEvent(*this, event); } void Controller::Impl::OnPanEvent( const Event& event ) { - if( NULL == mEventData ) - { - // Nothing to do if there is no text input. - return; - } - - const bool isHorizontalScrollEnabled = mEventData->mDecorator->IsHorizontalScrollEnabled(); - const bool isVerticalScrollEnabled = mEventData->mDecorator->IsVerticalScrollEnabled(); - - if( !isHorizontalScrollEnabled && !isVerticalScrollEnabled ) - { - // Nothing to do if scrolling is not enabled. - return; - } - - const int state = event.p1.mInt; - - switch( state ) - { - case Gesture::Started: - { - // Will remove the cursor, handles or text's popup, ... - ChangeState( EventData::TEXT_PANNING ); - break; - } - case Gesture::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; + ControllerImplEventHandler::OnPanEvent(*this, event); +} - ClampVerticalScroll( layoutSize ); - } +void Controller::Impl::OnLongPressEvent( const Event& event ) +{ + ControllerImplEventHandler::OnLongPressEvent(*this, event); +} - mEventData->mDecorator->UpdatePositions( mModel->mScrollPosition - currentScroll ); - break; - } - case Gesture::Finished: - case Gesture::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::OnHandleEvent( const Event& event ) +{ + ControllerImplEventHandler::OnHandleEvent(*this, event); } -void Controller::Impl::OnLongPressEvent( const Event& event ) +void Controller::Impl::OnSelectEvent( const Event& event ) { - DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::OnLongPressEvent\n" ); + ControllerImplEventHandler::OnSelectEvent(*this, event); +} - 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; +void Controller::Impl::OnSelectAllEvent() +{ + ControllerImplEventHandler::OnSelectAllEvent(*this); +} - // Calculates the logical position from the x,y coords. - RepositionSelectionHandles( xPosition, - yPosition, - mEventData->mLongPressAction ); - } - } +void Controller::Impl::OnSelectNoneEvent() +{ + ControllerImplEventHandler::OnSelectNoneEvent(*this); } -void Controller::Impl::OnHandleEvent( const Event& event ) +void Controller::Impl::SetTextSelectionRange(const uint32_t *pStart, const uint32_t *pEnd) { - if( NULL == mEventData ) + if( nullptr == mEventData ) { - // Nothing to do if there is no text input. + // Nothing to do if there is no text. 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 ) + if( mEventData->mSelectionEnabled && (pStart || pEnd)) { - // 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 ); + uint32_t length = static_cast(mModel->mLogicalModel->mText.Count()); - if( Event::GRAB_HANDLE_EVENT == event.type ) + if (pStart) { - 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; + mEventData->mLeftSelectionPosition = std::min(*pStart, length); } - } // end ( HANDLE_PRESSED == state ) - else if( ( HANDLE_RELEASED == state ) || - handleStopScrolling ) - { - CharacterIndex handlePosition = 0u; - if( handleStopScrolling || isSmoothHandlePanEnabled ) + if (pEnd) { - // 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 ); + mEventData->mRightSelectionPosition = std::min(*pEnd, length); } - if( Event::GRAB_HANDLE_EVENT == event.type ) + if (mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition) { + ChangeState( EventData::EDITING ); + mEventData->mPrimaryCursorPosition = mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition; 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 ) + else { 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 ) +Uint32Pair Controller::Impl::GetTextSelectionRange() const { - if( NULL == mEventData ) - { - // Nothing to do if there is no text. - return; - } + Uint32Pair range; - if( mEventData->mSelectionEnabled ) + if( mEventData ) { - // 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 ); + range.first = mEventData->mLeftSelectionPosition; + range.second = mEventData->mRightSelectionPosition; } + + return range; } -void Controller::Impl::OnSelectAllEvent() +bool Controller::Impl::IsEditable() const { - 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; - } + return mEventData && mEventData->mEditingEnabled; +} - if( mEventData->mSelectionEnabled ) +void Controller::Impl::SetEditable( bool editable ) +{ + if( mEventData) { - // 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(); + mEventData->mEditingEnabled = editable; } } @@ -2092,6 +1525,18 @@ void Controller::Impl::RetrieveSelection( std::string& selectedText, bool delete } } +void Controller::Impl::SetSelection( int start, int end ) +{ + mEventData->mLeftSelectionPosition = start; + mEventData->mRightSelectionPosition = end; + mEventData->mUpdateCursorPosition = true; +} + +std::pair< int, int > Controller::Impl::GetSelectionIndexes() const +{ + return { mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition }; +} + void Controller::Impl::ShowClipboard() { if( mClipboard ) @@ -2113,7 +1558,7 @@ void Controller::Impl::SetClipboardHideEnable(bool enable) mClipboardHideEnabled = enable; } -bool Controller::Impl::CopyStringToClipboard( std::string& source ) +bool Controller::Impl::CopyStringToClipboard( const std::string& source ) { //Send string to clipboard return ( mClipboard && mClipboard.SetItem( source ) ); @@ -2620,15 +2065,23 @@ void Controller::Impl::SetPopupButtons() * If EDITING_WITH_POPUP : SELECT & SELECT_ALL */ + bool isEditable = IsEditable(); TextSelectionPopup::Buttons buttonsToShow = TextSelectionPopup::NONE; if( EventData::SELECTING == mEventData->mState ) { - buttonsToShow = TextSelectionPopup::Buttons( TextSelectionPopup::CUT | TextSelectionPopup::COPY ); + buttonsToShow = TextSelectionPopup::Buttons( TextSelectionPopup::COPY ); + if(isEditable) + { + buttonsToShow = TextSelectionPopup::Buttons( buttonsToShow | TextSelectionPopup::CUT ); + } if( !IsClipboardEmpty() ) { - buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) ); + if(isEditable) + { + buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) ); + } buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::CLIPBOARD ) ); } @@ -2646,7 +2099,10 @@ void Controller::Impl::SetPopupButtons() if( !IsClipboardEmpty() ) { - buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) ); + if(isEditable) + { + buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) ); + } buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::CLIPBOARD ) ); } } @@ -2654,7 +2110,10 @@ void Controller::Impl::SetPopupButtons() { if ( !IsClipboardEmpty() ) { - buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) ); + if(isEditable) + { + buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) ); + } buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::CLIPBOARD ) ); } } @@ -3359,7 +2818,7 @@ Actor Controller::Impl::CreateBackgroundActor() quadVertexFormat[ "aPosition" ] = Property::VECTOR2; quadVertexFormat[ "aColor" ] = Property::VECTOR4; - PropertyBuffer quadVertices = PropertyBuffer::New( quadVertexFormat ); + VertexBuffer quadVertices = VertexBuffer::New( quadVertexFormat ); quadVertices.SetData( &mesh.mVertices[ 0 ], mesh.mVertices.Size() ); Geometry quadGeometry = Geometry::New(); @@ -3376,11 +2835,11 @@ Actor Controller::Impl::CreateBackgroundActor() renderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT ); actor = Actor::New(); - actor.SetName( "TextBackgroundColorActor" ); - actor.SetParentOrigin( ParentOrigin::TOP_LEFT ); - actor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - actor.SetSize( textSize ); - actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); + actor.SetProperty( Dali::Actor::Property::NAME, "TextBackgroundColorActor" ); + actor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT ); + actor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT ); + actor.SetProperty( Actor::Property::SIZE, textSize ); + actor.SetProperty( Actor::Property::COLOR_MODE, USE_OWN_MULTIPLY_PARENT_COLOR ); actor.AddRenderer( renderer ); } }