X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=base%2Fdali-toolkit%2Finternal%2Fcontrols%2Ftext-input%2Ftext-input-impl.cpp;h=cbda7fb578b81f50cf5795c278d69c15c39c20e8;hp=d2c6c863123d4b4f2fab508fc23c139ea9fc58a3;hb=7e315a440bad7033d19fefa8f9952d625ee6f076;hpb=9fd41afd0f3485f39fe161c28efdc88e1aa737f6 diff --git a/base/dali-toolkit/internal/controls/text-input/text-input-impl.cpp b/base/dali-toolkit/internal/controls/text-input/text-input-impl.cpp index d2c6c86..cbda7fb 100644 --- a/base/dali-toolkit/internal/controls/text-input/text-input-impl.cpp +++ b/base/dali-toolkit/internal/controls/text-input/text-input-impl.cpp @@ -15,21 +15,28 @@ * */ -#include - +// CLASS HEADER #include -#include -#include -#include -#include - -#include +// EXTERNAL INCLUDES #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include -using namespace std; using namespace Dali; // Local Data @@ -354,16 +361,20 @@ std::string TextInput::GetMarkupText() const return markupString; } +void TextInput::ShowPlaceholderText( const MarkupProcessor::StyledTextArray& stylePlaceHolderText ) +{ + mDisplayedTextView.SetText( stylePlaceHolderText ); + mPlaceHolderSet = true; + mDisplayedTextView.SetScrollPosition( Vector2( 0.0f,0.0f ) ); +} + void TextInput::SetPlaceholderText( const std::string& placeHolderText ) { // Get the placeholder styled text array from the markup string. MarkupProcessor::GetStyledTextArray( placeHolderText, mStyledPlaceHolderText, IsMarkupProcessingEnabled() ); - if( mStyledText.empty() ) { - // Set the placeholder text only if the styled text is empty. - mDisplayedTextView.SetText( mStyledPlaceHolderText ); - mPlaceHolderSet = true; + ShowPlaceholderText( mStyledPlaceHolderText ); } } @@ -403,9 +414,7 @@ void TextInput::SetText(const std::string& initialText) if( mStyledText.empty() ) { - // If the initial text is empty, set the placeholder text. - mDisplayedTextView.SetText( mStyledPlaceHolderText ); - mPlaceHolderSet = true; + ShowPlaceholderText( mStyledPlaceHolderText ); } else { @@ -529,24 +538,24 @@ const Vector4& TextInput::GetMaterialDiffuseColor() const // Signals -Toolkit::TextInput::InputSignalV2& TextInput::InputStartedSignal() +Toolkit::TextInput::InputSignalType& TextInput::InputStartedSignal() { - return mInputStartedSignalV2; + return mInputStartedSignal; } -Toolkit::TextInput::InputSignalV2& TextInput::InputFinishedSignal() +Toolkit::TextInput::InputSignalType& TextInput::InputFinishedSignal() { - return mInputFinishedSignalV2; + return mInputFinishedSignal; } -Toolkit::TextInput::InputSignalV2& TextInput::CutAndPasteToolBarDisplayedSignal() +Toolkit::TextInput::InputSignalType& TextInput::CutAndPasteToolBarDisplayedSignal() { - return mCutAndPasteToolBarDisplayedV2; + return mCutAndPasteToolBarDisplayed; } -Toolkit::TextInput::StyleChangedSignalV2& TextInput::StyleChangedSignal() +Toolkit::TextInput::StyleChangedSignalType& TextInput::StyleChangedSignal() { - return mStyleChangedSignalV2; + return mStyleChangedSignal; } Toolkit::TextInput::TextModifiedSignalType& TextInput::TextModifiedSignal() @@ -554,14 +563,14 @@ Toolkit::TextInput::TextModifiedSignalType& TextInput::TextModifiedSignal() return mTextModifiedSignal; } -Toolkit::TextInput::MaxInputCharactersReachedSignalV2& TextInput::MaxInputCharactersReachedSignal() +Toolkit::TextInput::MaxInputCharactersReachedSignalType& TextInput::MaxInputCharactersReachedSignal() { - return mMaxInputCharactersReachedSignalV2; + return mMaxInputCharactersReachedSignal; } -Toolkit::TextInput::InputTextExceedBoundariesSignalV2& TextInput::InputTextExceedBoundariesSignal() +Toolkit::TextInput::InputTextExceedBoundariesSignalType& TextInput::InputTextExceedBoundariesSignal() { - return mInputTextExceedBoundariesSignalV2; + return mInputTextExceedBoundariesSignal; } bool TextInput::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) @@ -1021,7 +1030,7 @@ void TextInput::OnKeyInputFocusGained() StartCursorBlinkTimer(); Toolkit::TextInput handle( GetOwner() ); - mInputStartedSignalV2.Emit( handle ); + mInputStartedSignal.Emit( handle ); ImfManager imfManager = ImfManager::Get(); @@ -1033,7 +1042,7 @@ void TextInput::OnKeyInputFocusGained() imfManager.Activate(); // When window gain lost focus, the imf manager is deactivated. Thus when window gain focus again, the imf manager must be activated. - imfManager.SetRestoreAferFocusLost( true ); + imfManager.SetRestoreAfterFocusLost( true ); imfManager.SetCursorPosition( mCursorPosition ); imfManager.NotifyCursorPosition(); @@ -1067,7 +1076,7 @@ void TextInput::OnKeyInputFocusLost() if ( imfManager ) { // The text editing is finished. Therefore the imf manager don't have restore activation. - imfManager.SetRestoreAferFocusLost( false ); + imfManager.SetRestoreAfterFocusLost( false ); // Notify that the text editing finish. imfManager.Deactivate(); @@ -1078,7 +1087,7 @@ void TextInput::OnKeyInputFocusLost() VirtualKeyboard::LanguageChangedSignal().Disconnect( this, &TextInput::SetTextDirection ); Toolkit::TextInput handle( GetOwner() ); - mInputFinishedSignalV2.Emit( handle ); + mInputFinishedSignal.Emit( handle ); mEditModeActive = false; mPreEditFlag = false; RemoveHighlight(); @@ -1197,7 +1206,7 @@ float TextInput::GetHeightForWidth( float width ) // Private Internal methods -void TextInput::OnHandlePan(Actor actor, PanGesture gesture) +void TextInput::OnHandlePan(Actor actor, const PanGesture& gesture) { switch (gesture.state) { @@ -1322,7 +1331,7 @@ bool TextInput::OnHandleTwoTouched(Dali::Actor actor, const TouchEvent& touch) return false; } -void TextInput::OnDoubleTap(Dali::Actor actor, Dali::TapGesture tap) +void TextInput::OnDoubleTap(Dali::Actor actor, const Dali::TapGesture& tap) { // If text exists then select nearest word. if ( !mStyledText.empty()) @@ -1387,7 +1396,7 @@ void TextInput::OnDoubleTap(Dali::Actor actor, Dali::TapGesture tap) } // TODO: Change the function name to be more general. -void TextInput::OnTextTap(Dali::Actor actor, Dali::TapGesture tap) +void TextInput::OnTextTap(Dali::Actor actor, const Dali::TapGesture& tap) { DALI_LOG_INFO( gLogFilter, Debug::General, "OnTap mPreEditFlag[%s] mEditOnTouch[%s] mEditModeActive[%s] ", (mPreEditFlag)?"true":"false" , (mEditOnTouch)?"true":"false" @@ -1485,7 +1494,19 @@ void TextInput::OnTextTap(Dali::Actor actor, Dali::TapGesture tap) // otherwise the Grab handle will be shown when selecting. if ( createGrabHandle && IsGrabHandleEnabled() ) { - const Vector3 cursorPosition = GetActualPositionFromCharacterPosition(mCursorPosition); + Vector3 altPosition; // Alternate (i.e. opposite direction) cursor position. + bool altPositionValid; // Alternate cursor validity flag. + bool directionRTL; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) + Vector3 cursorPosition = GetActualPositionFromCharacterPosition( mCursorPosition, directionRTL, altPosition, altPositionValid ); + + if( altPositionValid ) + { + // Check which of the positions is the closest. + if( fabsf( altPosition.x - tap.localPoint.x ) < fabsf( cursorPosition.x - tap.localPoint.x ) ) + { + cursorPosition = altPosition; + } + } CreateGrabHandle(); @@ -1497,7 +1518,7 @@ void TextInput::OnTextTap(Dali::Actor actor, Dali::TapGesture tap) } } -void TextInput::OnLongPress(Dali::Actor actor, Dali::LongPressGesture longPress) +void TextInput::OnLongPress(Dali::Actor actor, const Dali::LongPressGesture& longPress) { DALI_LOG_INFO( gLogFilter, Debug::General, "OnLongPress\n" ); @@ -1745,7 +1766,6 @@ bool TextInput::OnKeyDownEvent(const KeyEvent& event) { // Some text is selected so erase it before adding space. DeleteHighlightedText( true ); - update = true; } mCursorPosition = mCursorPosition + InsertAt(Text(keyString), mCursorPosition, 0); @@ -1840,6 +1860,64 @@ bool TextInput::OnKeyUpEvent(const KeyEvent& event) return false; } +void TextInput::ChooseRtlSelectionHandlePosition( const Vector3& cursorPositionOne, + const Vector3& cursorPositionTwo, + bool altPositionValidOne, + bool altPositionValidTwo, + const Vector3& altPositionOne, + const Vector3& altPositionTwo ) +{ + // TODO VCC Valid for one line. + // Try to place the selection handles. TODO think in something better. Probably need to know the direction of the paragraph. + if( cursorPositionOne != cursorPositionTwo ) + { + if( cursorPositionOne.x < cursorPositionTwo.x ) + { + mSelectionHandleOneActualPosition = cursorPositionOne; + mSelectionHandleTwoActualPosition = cursorPositionTwo; + } + else + { + mSelectionHandleOneActualPosition = cursorPositionTwo; + mSelectionHandleTwoActualPosition = cursorPositionOne; + } + } + else + { + mSelectionHandleOneActualPosition = cursorPositionOne; + if( altPositionValidOne ) + { + if( altPositionOne.x < mSelectionHandleOneActualPosition.x ) + { + mSelectionHandleOneActualPosition = altPositionOne; + } + } + if( altPositionValidTwo ) + { + if( altPositionTwo.x < mSelectionHandleOneActualPosition.x ) + { + mSelectionHandleOneActualPosition = altPositionTwo; + } + } + + mSelectionHandleTwoActualPosition = cursorPositionTwo; + if( altPositionValidTwo ) + { + if( altPositionTwo.x > mSelectionHandleTwoActualPosition.x ) + { + mSelectionHandleTwoActualPosition = altPositionTwo; + } + } + if( altPositionValidOne ) + { + if( altPositionOne.x > mSelectionHandleTwoActualPosition.x ) + { + mSelectionHandleTwoActualPosition = altPositionOne; + } + } + } +} + void TextInput::OnTextViewScrolled( Toolkit::TextView textView, Vector2 scrollPosition ) { // Updates the stored scroll position. @@ -1852,7 +1930,20 @@ void TextInput::OnTextViewScrolled( Toolkit::TextView textView, Vector2 scrollPo if( mGrabHandle || mCursor ) { cursorSize.height = GetRowRectFromCharacterPosition( mCursorPosition ).height; - const Vector3 cursorPosition = GetActualPositionFromCharacterPosition(mCursorPosition); + + Vector3 altPosition; // Alternate (i.e. opposite direction) cursor position. + bool altPositionValid; // Alternate cursor validity flag. + bool directionRTL; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) + Vector3 cursorPosition = GetActualPositionFromCharacterPosition( mCursorPosition, directionRTL, altPosition, altPositionValid ); + + if( altPositionValid ) + { + // Check which of the positions is the closest. + if( fabsf( altPosition.x - mActualGrabHandlePosition.x ) < fabsf( cursorPosition.x - mActualGrabHandlePosition.x ) ) + { + cursorPosition = altPosition; + } + } mIsCursorInScrollArea = mIsGrabHandleInScrollArea = IsPositionInsideBoundaries( cursorPosition, cursorSize, controlSize ); @@ -1874,16 +1965,29 @@ void TextInput::OnTextViewScrolled( Toolkit::TextView textView, Vector2 scrollPo // Updates the selection handles and highlighted text position and visibility. if( mSelectionHandleOne && mSelectionHandleTwo ) { - const Vector3 cursorPositionOne = GetActualPositionFromCharacterPosition(mSelectionHandleOnePosition); - const Vector3 cursorPositionTwo = GetActualPositionFromCharacterPosition(mSelectionHandleTwoPosition); + Vector3 altPositionOne; // Alternate (i.e. opposite direction) cursor position. + bool altPositionValidOne; // Alternate cursor validity flag. + bool directionRTLOne; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) + Vector3 cursorPositionOne = GetActualPositionFromCharacterPosition( mSelectionHandleOnePosition, directionRTLOne, altPositionOne, altPositionValidOne ); + + Vector3 altPositionTwo; // Alternate (i.e. opposite direction) cursor position. + bool altPositionValidTwo; // Alternate cursor validity flag. + bool directionRTLTwo; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) + Vector3 cursorPositionTwo = GetActualPositionFromCharacterPosition( mSelectionHandleTwoPosition, directionRTLTwo, altPositionTwo, altPositionValidTwo ); + + // VCC TODO: This method is a hack for one line. + ChooseRtlSelectionHandlePosition( cursorPositionOne, + cursorPositionTwo, + altPositionValidOne, + altPositionValidTwo, + altPositionOne, + altPositionTwo ); + cursorSize.height = ( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + mSelectionHandleOnePosition ) ).mSize.height; const bool isSelectionHandleOneVisible = IsPositionInsideBoundaries( cursorPositionOne, cursorSize, controlSize ); cursorSize.height = ( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + mSelectionHandleTwoPosition ) ).mSize.height; const bool isSelectionHandleTwoVisible = IsPositionInsideBoundaries( cursorPositionTwo, cursorSize, controlSize ); - mSelectionHandleOneActualPosition = cursorPositionOne.GetVectorXY(); - mSelectionHandleTwoActualPosition = cursorPositionTwo.GetVectorXY(); - mSelectionHandleOne.SetVisible( isSelectionHandleOneVisible ); mSelectionHandleTwo.SetVisible( isSelectionHandleTwoVisible ); mSelectionHandleOne.SetPosition( mSelectionHandleOneActualPosition + UI_OFFSET + mSelectionHandleOneOffset ); @@ -2271,9 +2375,7 @@ ImfManager::ImfCallbackData TextInput::ImfEventReceived( Dali::ImfManager& imfMa if( mStyledText.empty() ) { - // Styled text is empty, so set the placeholder text. - mDisplayedTextView.SetText( mStyledPlaceHolderText ); - mPlaceHolderSet = true; + ShowPlaceholderText( mStyledPlaceHolderText ); } } break; @@ -2330,14 +2432,13 @@ bool TextInput::PreEditReceived(const std::string& keyString, std::size_t cursor if( mStyledText.empty() ) { - // Styled text is empty, so set the placeholder text. - mDisplayedTextView.SetText( mStyledPlaceHolderText ); - mPlaceHolderSet = true; + ShowPlaceholderText( mStyledPlaceHolderText ); } else { mDisplayedTextView.RemoveTextFrom( mPreEditStartPosition, numberOfCharactersToReplace ); } + GetTextLayoutInfo(); EmitTextModified(); } @@ -2558,13 +2659,12 @@ void TextInput::DeleteHighlightedText( bool inheritStyle ) mStyledText.erase( start, end ); // erase range of characters - // Remove text from TextView. + // Remove text from TextView and update place holder text if required + // Set the placeholder text only if the styled text is empty. if( mStyledText.empty() ) { - // Styled text is empty, so set the placeholder text. - mDisplayedTextView.SetText( mStyledPlaceHolderText ); - mPlaceHolderSet = true; + ShowPlaceholderText( mStyledPlaceHolderText ); } else { @@ -2691,9 +2791,7 @@ void TextInput::DeleteCharacter( std::size_t positionToDelete ) if( mStyledText.empty() ) { - // Styled text is empty, so set the placeholder text. - mDisplayedTextView.SetText( mStyledPlaceHolderText ); - mPlaceHolderSet = true; + ShowPlaceholderText( mStyledPlaceHolderText ); } else { @@ -3230,8 +3328,23 @@ void TextInput::CreateSelectionHandles( std::size_t start, std::size_t end, Dali // update table as text may have changed. GetTextLayoutInfo(); - mSelectionHandleOneActualPosition = GetActualPositionFromCharacterPosition( mSelectionHandleOnePosition ); - mSelectionHandleTwoActualPosition = GetActualPositionFromCharacterPosition( mSelectionHandleTwoPosition ); + Vector3 altPositionOne; // Alternate (i.e. opposite direction) cursor position. + bool altPositionValidOne; // Alternate cursor validity flag. + bool directionRTLOne; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) + Vector3 cursorPositionOne = GetActualPositionFromCharacterPosition( mSelectionHandleOnePosition, directionRTLOne, altPositionOne, altPositionValidOne ); + + Vector3 altPositionTwo; // Alternate (i.e. opposite direction) cursor position. + bool altPositionValidTwo; // Alternate cursor validity flag. + bool directionRTLTwo; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) + Vector3 cursorPositionTwo = GetActualPositionFromCharacterPosition( mSelectionHandleTwoPosition, directionRTLTwo, altPositionTwo, altPositionValidTwo ); + + // VCC TODO: This method is a hack for one line. + ChooseRtlSelectionHandlePosition( cursorPositionOne, + cursorPositionTwo, + altPositionValidOne, + altPositionValidTwo, + altPositionOne, + altPositionTwo ); mSelectionHandleOne.SetPosition( mSelectionHandleOneActualPosition + UI_OFFSET + mSelectionHandleOneOffset ); mSelectionHandleTwo.SetPosition( mSelectionHandleTwoActualPosition + UI_OFFSET + mSelectionHandleTwoOffset ); @@ -3275,7 +3388,18 @@ Vector3 TextInput::MoveSelectionHandle( SelectionHandleId handleId, const Vector std::size_t newHandlePosition = 0; ReturnClosestIndex( actualSelectionHandlePosition.GetVectorXY(), newHandlePosition ); - actualHandlePosition = GetActualPositionFromCharacterPosition( newHandlePosition ); + Vector3 altPosition; // Alternate (i.e. opposite direction) cursor position. + bool altPositionValid; // Alternate cursor validity flag. + bool directionRTL; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) + actualHandlePosition = GetActualPositionFromCharacterPosition( newHandlePosition, directionRTL, altPosition, altPositionValid ); + if( altPositionValid ) + { + // Check which of the positions is the closest. + if( fabsf( altPosition.x - actualSelectionHandlePosition.x ) < fabsf( actualHandlePosition.x - actualSelectionHandlePosition.x ) ) + { + actualHandlePosition = altPosition; + } + } bool handleVisible = true; @@ -3374,41 +3498,34 @@ void TextInput::SetSelectionHandlePosition(SelectionHandleId handleId) } } -void TextInput::GetVisualTextSelection(std::vector& selectedVisualText, std::size_t startSelection, std::size_t endSelection) +void TextInput::GetVisualTextSelection( std::vector& selectedVisualText, std::size_t startSelection, std::size_t endSelection ) { - std::vector::iterator it = mTextLayoutInfo.mCharacterLogicalToVisualMap.begin(); - std::vector::iterator startSelectionIt = mTextLayoutInfo.mCharacterLogicalToVisualMap.begin() + std::min(startSelection, endSelection); - std::vector::iterator endSelectionIt = mTextLayoutInfo.mCharacterLogicalToVisualMap.begin() + std::max(startSelection, endSelection); - std::vector::iterator end = mTextLayoutInfo.mCharacterLogicalToVisualMap.end(); - - selectedVisualText.resize( mTextLayoutInfo.mCharacterLogicalToVisualMap.size() ); + selectedVisualText.resize( mTextLayoutInfo.mCharacterLogicalToVisualMap.size(), false ); - // Deselect text prior to startSelectionIt - for(;it!=startSelectionIt;++it) - { - selectedVisualText[*it] = false; - } + // VCC Set true/false in logical order. TODO : It needs to be checked. - // Select text from startSelectionIt -> endSelectionIt - for(;it!=endSelectionIt;++it) + if( startSelection > endSelection ) { - selectedVisualText[*it] = true; + std::swap( startSelection, endSelection ); } - - // Deselect text after endSelection - for(;it!=end;++it) + std::size_t index = 0u; + for( std::vector::iterator it = selectedVisualText.begin(), endIt = selectedVisualText.end(); it != endIt; ++it, ++index ) { - selectedVisualText[*it] = false; + if( ( index < startSelection ) || ( endSelection <= index ) ) + { + *it = false; + } + else + { + *it = true; + } } - - selectedVisualText.resize( mTextLayoutInfo.mCharacterLogicalToVisualMap.size(), false ); } // Calculate the dimensions of the quads they will make the highlight mesh TextInput::HighlightInfo TextInput::CalculateHighlightInfo() { // At the moment there is no public API to modify the block alignment option. - const bool blockAlignEnabled = true; mNewHighlightInfo.mQuadList.clear(); // clear last quad information. @@ -3419,9 +3536,9 @@ TextInput::HighlightInfo TextInput::CalculateHighlightInfo() // Get vector of flags representing characters that are selected (true) vs unselected (false). std::vector selectedVisualText; - GetVisualTextSelection(selectedVisualText, mSelectionHandleOnePosition, mSelectionHandleTwoPosition); - std::vector::iterator selectedIt(selectedVisualText.begin()); - std::vector::iterator selectedEndIt(selectedVisualText.end()); + GetVisualTextSelection( selectedVisualText, mSelectionHandleOnePosition, mSelectionHandleTwoPosition ); + std::vector::iterator selectedIt = selectedVisualText.begin(); + std::vector::iterator selectedEndIt = selectedVisualText.end(); SelectionState selectionState = SelectionNone; ///< Current selection status of cursor over entire text. float rowLeft = 0.0f; @@ -3438,28 +3555,28 @@ TextInput::HighlightInfo TextInput::CalculateHighlightInfo() // selectionState: None when not in selection, Started when in selection, and Ended when reached end of selection. Toolkit::TextView::CharacterLayoutInfo& charInfo(*it); - bool charSelected( false ); + bool charSelected = false; if( selectedIt != selectedEndIt ) { charSelected = *selectedIt++; } - if(selectionState == SelectionNone) + if( selectionState == SelectionNone ) { - if(charSelected) + if( charSelected ) { selectionState = SelectionStarted; rowLeft = charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x; rowRight = rowLeft + charInfo.mSize.width; } } - else if(selectionState == SelectionStarted) + else if( selectionState == SelectionStarted ) { // break selection on: // 1. new line causing selection break. (\n or wordwrap) // 2. character not selected. - if(charInfo.mPosition.y - lastIt->mPosition.y > CHARACTER_THRESHOLD || - !charSelected) + if( !charSelected || + ( charInfo.mPosition.y - lastIt->mPosition.y > CHARACTER_THRESHOLD ) ) { // finished selection. // TODO: TextView should have a table of visual rows, and each character a reference to the row @@ -3477,7 +3594,7 @@ TextInput::HighlightInfo TextInput::CalculateHighlightInfo() float rowTop = rowBottom - rowSize.height; // Still selected, and block-align mode then set rowRight to max, so it can be clamped afterwards - if(charSelected && blockAlignEnabled) + if(charSelected) { rowRight = std::numeric_limits::max(); } @@ -3489,7 +3606,7 @@ TextInput::HighlightInfo TextInput::CalculateHighlightInfo() if( charSelected ) { // if block-align mode then set rowLeft to min, so it can be clamped afterwards - rowLeft = blockAlignEnabled ? 0.0f : charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x; + rowLeft = 0.0f; rowRight = ( charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x ) + charInfo.mSize.width; selectionState = SelectionStarted; } @@ -3534,8 +3651,6 @@ TextInput::HighlightInfo TextInput::CalculateHighlightInfo() mNewHighlightInfo.Clamp2D( topLeft, bottomRight ); // For block-align align Further Clamp quads to max left and right extents - if(blockAlignEnabled) - { // BlockAlign: Will adjust highlight to block: // i.e. // H[ello] (top row right = max of all rows right) @@ -3550,8 +3665,66 @@ TextInput::HighlightInfo TextInput::CalculateHighlightInfo() // [is some] // [text] // (common in regular text editors/web browser selection) - mNewHighlightInfo.Clamp2D( Vector2(maxRowLeft, topLeft.y), Vector2(maxRowRight, bottomRight.y ) ); + + // Finally clamp quads again so they don't exceed the boundry of the control. + const Vector3& controlSize = GetControlSize(); + mNewHighlightInfo.Clamp2D( Vector2::ZERO, Vector2(controlSize.x, controlSize.y) ); + } // end if + + return mNewHighlightInfo; +} + +// VCC TODO: two methods are not needed. this one is a quick hack to fix PLMs. Should implement one which support both directions. +// This method creates one quad per character so different selection boxes for a mix of LTR and RTL languages are created. +TextInput::HighlightInfo TextInput::CalculateHighlightInfoRtl() +{ + // At the moment there is no public API to modify the block alignment option. + + mNewHighlightInfo.mQuadList.clear(); // clear last quad information. + + if ( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() && !mTextLayoutInfo.mCharacterLogicalToVisualMap.empty() ) + { + Toolkit::TextView::CharacterLayoutInfoContainer::iterator it = mTextLayoutInfo.mCharacterLayoutInfoTable.begin(); + Toolkit::TextView::CharacterLayoutInfoContainer::iterator end = mTextLayoutInfo.mCharacterLayoutInfoTable.end(); + + // Get vector of flags representing characters that are selected (true) vs unselected (false). + std::vector selectedVisualText; + GetVisualTextSelection( selectedVisualText, mSelectionHandleOnePosition, mSelectionHandleTwoPosition ); + std::vector::iterator selectedIt = selectedVisualText.begin(); + std::vector::iterator selectedEndIt = selectedVisualText.end(); + + // SelectionState selectionState = SelectionNone; ///< Current selection status of cursor over entire text. + float rowLeft = 0.0f; + float rowRight = 0.0f; + + // VCC TODO this is valid for one line. + Vector2 min, max; + const Size rowSize = GetRowRectFromCharacterPosition( 0, min, max ); + + // Scan through entire text. + while(it != end) + { + // selectionState: None when not in selection, Started when in selection, and Ended when reached end of selection. + + Toolkit::TextView::CharacterLayoutInfo& charInfo(*it); + bool charSelected = false; + if( selectedIt != selectedEndIt ) + { + charSelected = *selectedIt++; + } + + if( charSelected ) + { + rowLeft = charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x; + rowRight = rowLeft + charInfo.mSize.width; + + float rowBottom = charInfo.mPosition.y - mTextLayoutInfo.mScrollOffset.y; + float rowTop = rowBottom - rowSize.height; + mNewHighlightInfo.AddQuad( rowLeft, rowTop, rowRight, rowBottom ); + } + + ++it; } // Finally clamp quads again so they don't exceed the boundry of the control. @@ -3592,7 +3765,7 @@ void TextInput::UpdateHighlight() if ( mHighlightMeshActor ) { // vertex and triangle buffers should always be present if MeshActor is alive. - HighlightInfo newHighlightInfo = CalculateHighlightInfo(); + HighlightInfo newHighlightInfo = CalculateHighlightInfoRtl(); MeshData::VertexContainer vertices; Dali::MeshData::FaceIndices faceIndices; @@ -4003,7 +4176,7 @@ bool TextInput::ReturnClosestIndex(const Vector2& source, std::size_t& closestIn ++closestIndex; } } - else if( closestIndex == numeric_limits::max() ) // -1 RTL (after last arabic character on line) + else if( closestIndex == std::numeric_limits::max() ) // -1 RTL (after last arabic character on line) { closestIndex = mTextLayoutInfo.mCharacterVisualToLogicalMap.size(); } @@ -4357,6 +4530,7 @@ Vector3 TextInput::GetActualPositionFromCharacterPosition( std::size_t character cursorPosition.x -= mTextLayoutInfo.mScrollOffset.x; cursorPosition.y -= mTextLayoutInfo.mScrollOffset.y; + if( alternatePositionValid ) { alternatePosition.x -= mTextLayoutInfo.mScrollOffset.x; @@ -4723,6 +4897,7 @@ bool TextInput::CopySelectedTextToClipboard() */ MarkupProcessor::StyledTextArray selectedText(mCurrentCopySelecton.begin(),mCurrentCopySelecton.end()); MarkupProcessor::GetPlainString( selectedText, stringToStore ); + bool success = mClipboard.SetItem( stringToStore ); return success; } @@ -5095,9 +5270,8 @@ std::size_t TextInput::DoInsertAt( const Text& text, const std::size_t position, if( textToInsert.empty() && emptyTextView ) { // No character has been added and the text-view was empty. - // Set the placeholder text. - mDisplayedTextView.SetText( mStyledPlaceHolderText ); - mPlaceHolderSet = true; + // Show the placeholder text. + ShowPlaceholderText( mStyledPlaceHolderText ); } else { @@ -5333,7 +5507,7 @@ void TextInput::EmitStyleChangedSignal() { // emit signal if input style changes. Toolkit::TextInput handle( GetOwner() ); - mStyleChangedSignalV2.Emit( handle, mInputStyle ); + mStyleChangedSignal.Emit( handle, mInputStyle ); } void TextInput::EmitTextModified() @@ -5350,7 +5524,7 @@ void TextInput::EmitMaxInputCharactersReachedSignal() DALI_LOG_INFO(gLogFilter, Debug::General, "EmitMaxInputCharactersReachedSignal \n"); Toolkit::TextInput handle( GetOwner() ); - mMaxInputCharactersReachedSignalV2.Emit( handle ); + mMaxInputCharactersReachedSignal.Emit( handle ); } void TextInput::EmitInputTextExceedsBoundariesSignal() @@ -5358,7 +5532,7 @@ void TextInput::EmitInputTextExceedsBoundariesSignal() // Emit a signal when the input text exceeds the boundaries of the text input. Toolkit::TextInput handle( GetOwner() ); - mInputTextExceedBoundariesSignalV2.Emit( handle ); + mInputTextExceedBoundariesSignal.Emit( handle ); } } // namespace Internal