From: Victor Cebollada Date: Tue, 22 Sep 2015 14:50:28 +0000 (+0100) Subject: Fix cursor position issues. X-Git-Tag: dali_1.1.6~6^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=54623dab45ae809727d7265ef4c5c75ccf346b91 Fix cursor position issues. * Fixes the Test Case broken in a previous patch. * Fixes the scroll position after deleting the last characters. * Fixes minor cursor position issues caused in a previous patch. The previous patch: https://review.tizen.org/gerrit/#/c/48450/ Change-Id: I127c0bedccdd6a8c3923f877f07a36eecbf5c7e1 Signed-off-by: Victor Cebollada --- diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp index 521c191..ef8f86d 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp @@ -705,8 +705,8 @@ int utcDaliTextFieldEvent02(void) // Send some taps and check the cursor positions. // Try to tap at the beginning. - application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, Vector2( 3.f, 25.0f ) ) ); - application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, Vector2( 3.f, 25.0f ) ) ); + application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, Vector2( 1.f, 25.0f ) ) ); + application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, Vector2( 1.f, 25.0f ) ) ); // Render and notify application.SendNotification(); @@ -718,8 +718,8 @@ int utcDaliTextFieldEvent02(void) DALI_TEST_EQUALS( position2, position4, TEST_LOCATION ); // Should be in the same position2. // Tap away from the start position. - application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, Vector2( 13.f, 25.0f ) ) ); - application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, Vector2( 13.0f, 25.0f ) ) ); + application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, Vector2( 16.f, 25.0f ) ) ); + application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, Vector2( 16.0f, 25.0f ) ) ); // Render and notify application.SendNotification(); @@ -738,7 +738,12 @@ int utcDaliTextFieldEvent02(void) application.SendNotification(); application.Render(); - // Should not be renderer. + // Cursor position should be the same than position2. + Vector3 position6 = cursor.GetCurrentPosition(); + + DALI_TEST_EQUALS( position2, position6, TEST_LOCATION );// Should be in the same position2. + + // Should not be a renderer. DALI_TEST_EQUALS( offscreenRoot.GetChildCount(), 1u, TEST_LOCATION ); // The camera actor only. END_TEST; diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp index 153b34c..be24d2b 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -442,7 +442,10 @@ void TextLabel::OnInitialize() // Enable the text ellipsis. LayoutEngine& engine = mController->GetLayoutEngine(); + engine.SetTextEllipsisEnabled( true ); + engine.SetCursorWidth( 0u ); // Do not layout space for the cursor. + self.OnStageSignal().Connect( this, &TextLabel::OnStageConnect ); } diff --git a/dali-toolkit/internal/text/decorator/text-decorator.cpp b/dali-toolkit/internal/text/decorator/text-decorator.cpp index 6541b77..8d55300 100644 --- a/dali-toolkit/internal/text/decorator/text-decorator.cpp +++ b/dali-toolkit/internal/text/decorator/text-decorator.cpp @@ -308,13 +308,11 @@ struct Decorator::Impl : public ConnectionTracker if( mPrimaryCursor ) { const CursorImpl& cursor = mCursor[PRIMARY_CURSOR]; - mPrimaryCursorVisible = ( cursor.position.x <= size.width ) && ( cursor.position.x >= 0.f ); + mPrimaryCursorVisible = ( cursor.position.x + mCursorWidth <= size.width ) && ( cursor.position.x >= 0.f ); if( mPrimaryCursorVisible ) { - const Vector2& position = cursor.position; - - mPrimaryCursor.SetPosition( position.x, - position.y ); + mPrimaryCursor.SetPosition( cursor.position.x, + cursor.position.y ); mPrimaryCursor.SetSize( Size( mCursorWidth, cursor.cursorHeight ) ); } mPrimaryCursor.SetVisible( mPrimaryCursorVisible && mCursorBlinkStatus ); @@ -322,7 +320,7 @@ struct Decorator::Impl : public ConnectionTracker if( mSecondaryCursor ) { const CursorImpl& cursor = mCursor[SECONDARY_CURSOR]; - mSecondaryCursorVisible = ( cursor.position.x <= size.width ) && ( cursor.position.x >= 0.f ); + mSecondaryCursorVisible = ( cursor.position.x + mCursorWidth <= size.width ) && ( cursor.position.x >= 0.f ); if( mSecondaryCursorVisible ) { mSecondaryCursor.SetPosition( cursor.position.x, @@ -336,9 +334,7 @@ struct Decorator::Impl : public ConnectionTracker HandleImpl& grabHandle = mHandle[GRAB_HANDLE]; if( grabHandle.active ) { - const Vector2& position = grabHandle.position; - - const bool isVisible = ( position.x <= size.width ) && ( position.x >= 0.f ); + const bool isVisible = ( grabHandle.position.x + floor( 0.5f * mCursorWidth ) <= size.width ) && ( grabHandle.position.x >= 0.f ); if( isVisible ) { @@ -350,7 +346,11 @@ struct Decorator::Impl : public ConnectionTracker // Sets the grab handle image according if it's pressed, flipped, etc. SetHandleImage( GRAB_HANDLE ); } - grabHandle.actor.SetVisible( isVisible ); + + if( grabHandle.actor ) + { + grabHandle.actor.SetVisible( isVisible ); + } } else if( grabHandle.actor ) { @@ -362,11 +362,8 @@ struct Decorator::Impl : public ConnectionTracker HandleImpl& secondary = mHandle[ RIGHT_SELECTION_HANDLE ]; if( primary.active || secondary.active ) { - const Vector2& primaryPosition = primary.position; - const Vector2& secondaryPosition = secondary.position; - - const bool isPrimaryVisible = ( primaryPosition.x <= size.width ) && ( primaryPosition.x >= 0.f ); - const bool isSecondaryVisible = ( secondaryPosition.x <= size.width ) && ( secondaryPosition.x >= 0.f ); + const bool isPrimaryVisible = ( primary.position.x <= size.width ) && ( primary.position.x >= 0.f ); + const bool isSecondaryVisible = ( secondary.position.x <= size.width ) && ( secondary.position.x >= 0.f ); if( isPrimaryVisible || isSecondaryVisible ) { @@ -392,8 +389,15 @@ struct Decorator::Impl : public ConnectionTracker SetSelectionHandleMarkerSize( secondary ); } } - primary.actor.SetVisible( isPrimaryVisible ); - secondary.actor.SetVisible( isSecondaryVisible ); + + if( primary.actor ) + { + primary.actor.SetVisible( isPrimaryVisible ); + } + if( secondary.actor ) + { + secondary.actor.SetVisible( isSecondaryVisible ); + } CreateHighlight(); UpdateHighlight(); @@ -802,7 +806,7 @@ struct Decorator::Impl : public ConnectionTracker // The SetGrabHandleImage() method will change the orientation. const float yLocalPosition = grabHandle.verticallyFlipped ? grabHandle.position.y : grabHandle.position.y + grabHandle.lineHeight; - grabHandle.actor.SetPosition( grabHandle.position.x - floor( 0.5f * mCursorWidth ), + grabHandle.actor.SetPosition( grabHandle.position.x + floor( 0.5f * mCursorWidth ), yLocalPosition ); // TODO : Fix for multiline. } diff --git a/dali-toolkit/internal/text/layouts/layout-engine.cpp b/dali-toolkit/internal/text/layouts/layout-engine.cpp index 9062b07..54a957c 100644 --- a/dali-toolkit/internal/text/layouts/layout-engine.cpp +++ b/dali-toolkit/internal/text/layouts/layout-engine.cpp @@ -451,7 +451,6 @@ struct LayoutEngine::Impl const GlyphInfo& glyph = *glyphsBuffer; float penX = ( 0.f > glyph.xBearing ) ? -glyph.xBearing : 0.f; - penX += mCursorWidth; // Added to give some space to the cursor. for( GlyphIndex i = 0u; i < numberOfGlyphs; ++i ) { @@ -672,7 +671,6 @@ struct LayoutEngine::Impl const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + *( layoutParameters.charactersToGlyphsBuffer + characterVisualIndex ) ); float penX = ( 0.f > glyph.xBearing ) ? -glyph.xBearing : 0.f; - penX += mCursorWidth; // Added to give some space to the cursor. Vector2* glyphPositionsBuffer = glyphPositions.Begin(); diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index 795a929..412a317 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -200,62 +200,81 @@ bool Controller::Impl::ProcessInputEvents() if( mEventData->mUpdateCursorPosition ) { // Updates the cursor position and scrolls the text to make it visible. - - UpdateCursorPosition(); + CursorInfo cursorInfo; + GetCursorPosition( mEventData->mPrimaryCursorPosition, + cursorInfo ); if( mEventData->mScrollAfterUpdatePosition ) { - const Vector2& primaryCursorPosition = mEventData->mDecorator->GetPosition( PRIMARY_CURSOR ); - - ScrollToMakePositionVisible( primaryCursorPosition ); + ScrollToMakePositionVisible( cursorInfo.primaryPosition ); mEventData->mScrollAfterUpdatePosition = false; } + else if( mEventData->mScrollAfterDelete ) + { + ScrollTextToMatchCursor( cursorInfo ); + mEventData->mScrollAfterDelete = false; + } + + UpdateCursorPosition( cursorInfo ); mEventData->mDecoratorUpdated = true; mEventData->mUpdateCursorPosition = false; } - else if( mEventData->mScrollAfterDelete ) - { - ScrollTextToMatchCursor(); - mEventData->mDecoratorUpdated = true; - mEventData->mScrollAfterDelete = false; - } else { bool leftScroll = false; bool rightScroll = false; + CursorInfo leftHandleInfo; + CursorInfo rightHandleInfo; + if( mEventData->mUpdateLeftSelectionPosition ) { - UpdateSelectionHandle( LEFT_SELECTION_HANDLE ); + GetCursorPosition( mEventData->mLeftSelectionPosition, + leftHandleInfo ); if( mEventData->mScrollAfterUpdatePosition ) { - const Vector2& leftHandlePosition = mEventData->mDecorator->GetPosition( LEFT_SELECTION_HANDLE ); - - ScrollToMakePositionVisible( leftHandlePosition ); + ScrollToMakePositionVisible( leftHandleInfo.primaryPosition ); leftScroll = true; } - - SetPopupButtons(); - mEventData->mDecoratorUpdated = true; - mEventData->mUpdateLeftSelectionPosition = false; } if( mEventData->mUpdateRightSelectionPosition ) { - UpdateSelectionHandle( RIGHT_SELECTION_HANDLE ); + GetCursorPosition( mEventData->mRightSelectionPosition, + rightHandleInfo ); if( mEventData->mScrollAfterUpdatePosition ) { - const Vector2& rightHandlePosition = mEventData->mDecorator->GetPosition( RIGHT_SELECTION_HANDLE ); - - ScrollToMakePositionVisible( rightHandlePosition ); + ScrollToMakePositionVisible( rightHandleInfo.primaryPosition ); rightScroll = true; } + } + + if( mEventData->mUpdateLeftSelectionPosition ) + { + UpdateSelectionHandle( LEFT_SELECTION_HANDLE, + leftHandleInfo ); SetPopupButtons(); mEventData->mDecoratorUpdated = true; + } + + if( mEventData->mUpdateRightSelectionPosition ) + { + UpdateSelectionHandle( RIGHT_SELECTION_HANDLE, + rightHandleInfo ); + + SetPopupButtons(); + mEventData->mDecoratorUpdated = true; + } + + if( mEventData->mUpdateLeftSelectionPosition || mEventData->mUpdateRightSelectionPosition ) + { + RepositionSelectionHandles(); + + mEventData->mUpdateLeftSelectionPosition = false; mEventData->mUpdateRightSelectionPosition = false; } @@ -646,9 +665,6 @@ void Controller::Impl::OnHandleEvent( const Event& event ) { mEventData->mLeftSelectionPosition = handleNewPosition; - RepositionSelectionHandles( mEventData->mLeftSelectionPosition, - mEventData->mRightSelectionPosition ); - mEventData->mUpdateLeftSelectionPosition = true; } } @@ -661,9 +677,6 @@ void Controller::Impl::OnHandleEvent( const Event& event ) { mEventData->mRightSelectionPosition = handleNewPosition; - RepositionSelectionHandles( mEventData->mLeftSelectionPosition, - mEventData->mRightSelectionPosition ); - mEventData->mUpdateRightSelectionPosition = true; } } @@ -705,9 +718,6 @@ void Controller::Impl::OnHandleEvent( const Event& event ) if( mEventData->mUpdateLeftSelectionPosition ) { mEventData->mLeftSelectionPosition = handlePosition; - - RepositionSelectionHandles( mEventData->mLeftSelectionPosition, - mEventData->mRightSelectionPosition ); } } } @@ -722,8 +732,6 @@ void Controller::Impl::OnHandleEvent( const Event& event ) if( mEventData->mUpdateRightSelectionPosition ) { mEventData->mRightSelectionPosition = handlePosition; - RepositionSelectionHandles( mEventData->mLeftSelectionPosition, - mEventData->mRightSelectionPosition ); } } } @@ -811,8 +819,7 @@ void Controller::Impl::OnHandleEvent( const Event& event ) if( mEventData->mUpdateLeftSelectionPosition || mEventData->mUpdateRightSelectionPosition ) { - RepositionSelectionHandles( mEventData->mLeftSelectionPosition, - mEventData->mRightSelectionPosition ); + RepositionSelectionHandles(); mEventData->mScrollAfterUpdatePosition = true; } @@ -835,17 +842,14 @@ void Controller::Impl::OnSelectEvent( const Event& event ) const float xPosition = event.p2.mFloat - mEventData->mScrollPosition.x - mAlignmentOffset.x; const float yPosition = event.p3.mFloat - mEventData->mScrollPosition.y - mAlignmentOffset.y; - const CharacterIndex leftPosition = mEventData->mLeftSelectionPosition; - const CharacterIndex rightPosition = mEventData->mRightSelectionPosition; - + // Calculates the logical position from the x,y coords. RepositionSelectionHandles( xPosition, yPosition ); - mEventData->mUpdateLeftSelectionPosition = leftPosition != mEventData->mLeftSelectionPosition; - mEventData->mUpdateRightSelectionPosition = rightPosition != mEventData->mRightSelectionPosition; + mEventData->mUpdateLeftSelectionPosition = true; + mEventData->mUpdateRightSelectionPosition = true; - mEventData->mScrollAfterUpdatePosition = ( ( mEventData->mUpdateLeftSelectionPosition || mEventData->mUpdateRightSelectionPosition ) && - ( mEventData->mLeftSelectionPosition != mEventData->mRightSelectionPosition ) ); + mEventData->mScrollAfterUpdatePosition = ( mEventData->mLeftSelectionPosition != mEventData->mRightSelectionPosition ); } } @@ -859,8 +863,8 @@ void Controller::Impl::OnSelectAllEvent() if( mEventData->mSelectionEnabled ) { - RepositionSelectionHandles( 0u, - mLogicalModel->mText.Count() ); + mEventData->mLeftSelectionPosition = 0u; + mEventData->mRightSelectionPosition = mLogicalModel->mText.Count(); mEventData->mScrollAfterUpdatePosition = true; mEventData->mUpdateLeftSelectionPosition = true; @@ -903,8 +907,12 @@ void Controller::Impl::RetrieveSelection( std::string& selectedText, bool delete // Scroll after delete. mEventData->mPrimaryCursorPosition = handlesCrossed ? mEventData->mRightSelectionPosition : mEventData->mLeftSelectionPosition; mEventData->mScrollAfterDelete = true; - mEventData->mDecoratorUpdated = true; } + // Udpade the cursor position and the decorator. + // Scroll after the position is updated if is not scrolling after delete. + mEventData->mUpdateCursorPosition = true; + mEventData->mScrollAfterUpdatePosition = !mEventData->mScrollAfterDelete; + mEventData->mDecoratorUpdated = true; } } @@ -946,8 +954,11 @@ void Controller::Impl::GetTextFromClipboard( unsigned int itemIndex, std::string } } -void Controller::Impl::RepositionSelectionHandles( CharacterIndex selectionStart, CharacterIndex selectionEnd ) +void Controller::Impl::RepositionSelectionHandles() { + CharacterIndex selectionStart = mEventData->mLeftSelectionPosition; + CharacterIndex selectionEnd = mEventData->mRightSelectionPosition; + if( selectionStart == selectionEnd ) { // Nothing to select if handles are in the same place. @@ -956,9 +967,6 @@ void Controller::Impl::RepositionSelectionHandles( CharacterIndex selectionStart mEventData->mDecorator->ClearHighlights(); - mEventData->mLeftSelectionPosition = selectionStart; - mEventData->mRightSelectionPosition = selectionEnd; - const GlyphIndex* const charactersToGlyphBuffer = mVisualModel->mCharactersToGlyph.Begin(); const Length* const glyphsPerCharacterBuffer = mVisualModel->mGlyphsPerCharacter.Begin(); const GlyphInfo* const glyphsBuffer = mVisualModel->mGlyphs.Begin(); @@ -1130,7 +1138,8 @@ void Controller::Impl::RepositionSelectionHandles( float visualX, float visualY return; } - RepositionSelectionHandles( selectionStart, selectionEnd ); + mEventData->mLeftSelectionPosition = selectionStart; + mEventData->mRightSelectionPosition = selectionEnd; } void Controller::Impl::SetPopupButtons() @@ -1519,23 +1528,64 @@ void Controller::Impl::GetCursorPosition( CharacterIndex logical, { // TODO: Check for multiline with \n, etc... - // Check if the logical position is the first or the last one of the text. - const bool isFirstPosition = 0u == logical; - const bool isLastPosition = mLogicalModel->mText.Count() == logical; - - if( isFirstPosition && isLastPosition ) + const Length numberOfCharacters = mLogicalModel->mText.Count(); + if( !IsShowingRealText() ) { - // There is zero characters. Get the default font's line height. + // Do not want to use the place-holder text to set the cursor position. + + // Use the line's height of the font's family set to set the cursor's size. + // If there is no font's family set, use the default font. + // Use the current alignment to place the cursor at the beginning, center or end of the box. + cursorInfo.lineHeight = GetDefaultFontLineHeight(); cursorInfo.primaryCursorHeight = cursorInfo.lineHeight; - cursorInfo.primaryPosition.x = 0.f; - cursorInfo.primaryPosition.y = 0.f; + switch( mLayoutEngine.GetHorizontalAlignment() ) + { + case LayoutEngine::HORIZONTAL_ALIGN_BEGIN: + { + cursorInfo.primaryPosition.x = 0.f; + break; + } + case LayoutEngine::HORIZONTAL_ALIGN_CENTER: + { + cursorInfo.primaryPosition.x = floorf( 0.5f * mVisualModel->mControlSize.width ); + break; + } + case LayoutEngine::HORIZONTAL_ALIGN_END: + { + cursorInfo.primaryPosition.x = mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth(); + break; + } + } + + switch( mLayoutEngine.GetVerticalAlignment() ) + { + case LayoutEngine::VERTICAL_ALIGN_TOP: + { + cursorInfo.primaryPosition.y = 0.f; + break; + } + case LayoutEngine::VERTICAL_ALIGN_CENTER: + { + cursorInfo.primaryPosition.y = floorf( 0.5f * ( mVisualModel->mControlSize.height - cursorInfo.lineHeight ) ); + break; + } + case LayoutEngine::VERTICAL_ALIGN_BOTTOM: + { + cursorInfo.primaryPosition.y = mVisualModel->mControlSize.height - cursorInfo.lineHeight; + break; + } + } // Nothing else to do. return; } + // Check if the logical position is the first or the last one of the text. + const bool isFirstPosition = 0u == logical; + const bool isLastPosition = numberOfCharacters == logical; + // 'logical' is the logical 'cursor' index. // Get the next and current logical 'character' index. const CharacterIndex nextCharacterIndex = logical; @@ -1755,7 +1805,7 @@ CharacterIndex Controller::Impl::CalculateNewCursorIndex( CharacterIndex index ) return cursorIndex; } -void Controller::Impl::UpdateCursorPosition() +void Controller::Impl::UpdateCursorPosition( const CursorInfo& cursorInfo ) { DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::UpdateCursorPosition %p\n", this ); if( NULL == mEventData ) @@ -1765,121 +1815,58 @@ void Controller::Impl::UpdateCursorPosition() return; } - if( IsShowingPlaceholderText() || ( 0u == mLogicalModel->mText.Count() ) ) - { - // Do not want to use the place-holder text to set the cursor position. - - // Use the line's height of the font's family set to set the cursor's size. - // If there is no font's family set, use the default font. - // Use the current alignment to place the cursor at the beginning, center or end of the box. - - float lineHeight = 0.f; - - FontId defaultFontId = 0u; - if( NULL == mFontDefaults ) - { - TextAbstraction::FontDescription fontDescription; - defaultFontId = mFontClient.GetFontId( fontDescription ); - } - else - { - defaultFontId = mFontDefaults->GetFontId( mFontClient ); - } - - Text::FontMetrics fontMetrics; - mMetrics->GetFontMetrics( defaultFontId, fontMetrics ); - - lineHeight = fontMetrics.ascender - fontMetrics.descender; - - - Vector2 cursorPosition; + const Vector2 offset = mEventData->mScrollPosition + ( IsShowingRealText() ? mAlignmentOffset : Vector2::ZERO ); + const Vector2 cursorPosition = cursorInfo.primaryPosition + offset; - switch( mLayoutEngine.GetHorizontalAlignment() ) - { - case LayoutEngine::HORIZONTAL_ALIGN_BEGIN: - { - cursorPosition.x = 0.f; - break; - } - case LayoutEngine::HORIZONTAL_ALIGN_CENTER: - { - cursorPosition.x = floor( 0.5f * mVisualModel->mControlSize.width ); - break; - } - case LayoutEngine::HORIZONTAL_ALIGN_END: - { - cursorPosition.x = mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth(); - break; - } - } + // Sets the cursor position. + mEventData->mDecorator->SetPosition( PRIMARY_CURSOR, + cursorPosition.x, + cursorPosition.y, + cursorInfo.primaryCursorHeight, + cursorInfo.lineHeight ); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Primary cursor position: %f,%f\n", cursorPosition.x, cursorPosition.y ); - switch( mLayoutEngine.GetVerticalAlignment() ) - { - case LayoutEngine::VERTICAL_ALIGN_TOP: - { - cursorPosition.y = 0.f; - break; - } - case LayoutEngine::VERTICAL_ALIGN_CENTER: - { - cursorPosition.y = floorf( 0.5f * ( mVisualModel->mControlSize.height - lineHeight ) ); - break; - } - case LayoutEngine::VERTICAL_ALIGN_BOTTOM: - { - cursorPosition.y = mVisualModel->mControlSize.height - lineHeight; - break; - } - } + // Sets the grab handle position. + mEventData->mDecorator->SetPosition( GRAB_HANDLE, + cursorPosition.x, + cursorPosition.y, + cursorInfo.lineHeight ); - mEventData->mDecorator->SetPosition( PRIMARY_CURSOR, - cursorPosition.x, - cursorPosition.y, - lineHeight, - lineHeight ); - } - else + if( cursorInfo.isSecondaryCursor ) { - CursorInfo cursorInfo; - GetCursorPosition( mEventData->mPrimaryCursorPosition, - cursorInfo ); - - const Vector2 offset = mEventData->mScrollPosition + mAlignmentOffset; - const Vector2 cursorPosition = cursorInfo.primaryPosition + offset; - - // Sets the cursor position. - mEventData->mDecorator->SetPosition( PRIMARY_CURSOR, - cursorPosition.x, - cursorPosition.y, - cursorInfo.primaryCursorHeight, - cursorInfo.lineHeight ); - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Primary cursor position: %f,%f\n", cursorPosition.x, cursorPosition.y ); - - // Sets the grab handle position. - mEventData->mDecorator->SetPosition( GRAB_HANDLE, - cursorPosition.x, - cursorPosition.y, + mEventData->mDecorator->SetPosition( SECONDARY_CURSOR, + cursorInfo.secondaryPosition.x + offset.x, + cursorInfo.secondaryPosition.y + offset.y, + cursorInfo.secondaryCursorHeight, cursorInfo.lineHeight ); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Secondary cursor position: %f,%f\n", cursorInfo.secondaryPosition.x + offset.x, cursorInfo.secondaryPosition.y + offset.y ); + } + // Set which cursors are active according the state. + if( ( EventData::EDITING == mEventData->mState ) || + ( EventData::EDITING_WITH_POPUP == mEventData->mState ) || + ( EventData::EDITING_WITH_GRAB_HANDLE == mEventData->mState ) || + ( EventData::GRAB_HANDLE_PANNING == mEventData->mState ) ) + { if( cursorInfo.isSecondaryCursor ) { mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_BOTH ); - mEventData->mDecorator->SetPosition( SECONDARY_CURSOR, - cursorInfo.secondaryPosition.x + offset.x, - cursorInfo.secondaryPosition.y + offset.y, - cursorInfo.secondaryCursorHeight, - cursorInfo.lineHeight ); - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Secondary cursor position: %f,%f\n", cursorInfo.secondaryPosition.x + offset.x, cursorInfo.secondaryPosition.y + offset.y ); } else { mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY ); } } + else + { + mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE ); + } + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::UpdateCursorPosition\n" ); } -void Controller::Impl::UpdateSelectionHandle( HandleType handleType ) +void Controller::Impl::UpdateSelectionHandle( HandleType handleType, + const CursorInfo& cursorInfo ) { if( ( LEFT_SELECTION_HANDLE != handleType ) && ( RIGHT_SELECTION_HANDLE != handleType ) ) @@ -1887,15 +1874,7 @@ void Controller::Impl::UpdateSelectionHandle( HandleType handleType ) return; } - const bool leftSelectionHandle = LEFT_SELECTION_HANDLE == handleType; - const CharacterIndex index = leftSelectionHandle ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition; - - CursorInfo cursorInfo; - GetCursorPosition( index, - cursorInfo ); - - const Vector2 offset = mEventData->mScrollPosition + mAlignmentOffset; - const Vector2 cursorPosition = cursorInfo.primaryPosition + offset; + const Vector2 cursorPosition = cursorInfo.primaryPosition + mEventData->mScrollPosition + mAlignmentOffset; // Sets the grab handle position. mEventData->mDecorator->SetPosition( handleType, @@ -1912,6 +1891,7 @@ void Controller::Impl::UpdateSelectionHandle( HandleType handleType ) void Controller::Impl::ClampHorizontalScroll( const Vector2& actualSize ) { // Clamp between -space & 0 (and the text alignment). + if( actualSize.width > mVisualModel->mControlSize.width ) { const float space = ( actualSize.width - mVisualModel->mControlSize.width ) + mAlignmentOffset.x; @@ -1945,89 +1925,33 @@ void Controller::Impl::ClampVerticalScroll( const Vector2& actualSize ) void Controller::Impl::ScrollToMakePositionVisible( const Vector2& position ) { - Vector2 offset; - bool updateDecorator = false; - if( position.x < 0.f ) - { - offset.x = -position.x; - mEventData->mScrollPosition.x += offset.x; - updateDecorator = true; - } - else if( position.x > mVisualModel->mControlSize.width ) + // position is in actor's coords. + const float positionEnd = position.x + ( mEventData->mDecorator ? mEventData->mDecorator->GetCursorWidth() : 0.f ); + + // Transform the position to decorator coords. + const float offset = mEventData->mScrollPosition.x + mAlignmentOffset.x; + const float decoratorPositionBegin = position.x + offset; + const float decoratorPositionEnd = positionEnd + offset; + + if( decoratorPositionBegin < 0.f ) { - offset.x = mVisualModel->mControlSize.width - position.x; - mEventData->mScrollPosition.x += offset.x; - updateDecorator = true; + mEventData->mScrollPosition.x = -position.x - mAlignmentOffset.x; } - - if( updateDecorator && mEventData->mDecorator ) + else if( decoratorPositionEnd > mVisualModel->mControlSize.width ) { - mEventData->mDecorator->UpdatePositions( offset ); + mEventData->mScrollPosition.x = mVisualModel->mControlSize.width - positionEnd - mAlignmentOffset.x; } - - // TODO : calculate the vertical scroll. } -void Controller::Impl::ScrollTextToMatchCursor() +void Controller::Impl::ScrollTextToMatchCursor( const CursorInfo& cursorInfo ) { // Get the current cursor position in decorator coords. const Vector2& currentCursorPosition = mEventData->mDecorator->GetPosition( PRIMARY_CURSOR ); - // Calculate the new cursor position. - CursorInfo cursorInfo; - GetCursorPosition( mEventData->mPrimaryCursorPosition, - cursorInfo ); - // Calculate the offset to match the cursor position before the character was deleted. mEventData->mScrollPosition.x = currentCursorPosition.x - cursorInfo.primaryPosition.x - mAlignmentOffset.x; ClampHorizontalScroll( mVisualModel->GetActualSize() ); - - const Vector2 offset = mEventData->mScrollPosition + mAlignmentOffset; - const Vector2 cursorPosition = cursorInfo.primaryPosition + offset; - - // Sets the cursor position. - mEventData->mDecorator->SetPosition( PRIMARY_CURSOR, - cursorPosition.x, - cursorPosition.y, - cursorInfo.primaryCursorHeight, - cursorInfo.lineHeight ); - - // Sets the grab handle position. - mEventData->mDecorator->SetPosition( GRAB_HANDLE, - cursorPosition.x, - cursorPosition.y, - cursorInfo.lineHeight ); - - if( cursorInfo.isSecondaryCursor ) - { - mEventData->mDecorator->SetPosition( SECONDARY_CURSOR, - cursorInfo.secondaryPosition.x + offset.x, - cursorInfo.secondaryPosition.y + offset.y, - cursorInfo.secondaryCursorHeight, - cursorInfo.lineHeight ); - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Secondary cursor position: %f,%f\n", cursorInfo.secondaryPosition.x + offset.x, cursorInfo.secondaryPosition.y + offset.y ); - } - - // Set which cursors are active according the state. - if( ( EventData::EDITING == mEventData->mState ) || - ( EventData::EDITING_WITH_POPUP == mEventData->mState ) || - ( EventData::EDITING_WITH_GRAB_HANDLE == mEventData->mState ) || - ( EventData::GRAB_HANDLE_PANNING == mEventData->mState ) ) - { - if( cursorInfo.isSecondaryCursor ) - { - mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_BOTH ); - } - else - { - mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY ); - } - } - else - { - mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE ); - } } void Controller::Impl::RequestRelayout() diff --git a/dali-toolkit/internal/text/text-controller-impl.h b/dali-toolkit/internal/text/text-controller-impl.h index 8ada007..41d8f6b 100644 --- a/dali-toolkit/internal/text/text-controller-impl.h +++ b/dali-toolkit/internal/text/text-controller-impl.h @@ -390,7 +390,7 @@ struct Controller::Impl void GetTextFromClipboard( unsigned int itemIndex, std::string& retreivedString ); - void RepositionSelectionHandles( CharacterIndex selectionStart, CharacterIndex selectionEnd ); + void RepositionSelectionHandles(); void RepositionSelectionHandles( float visualX, float visualY ); void SetPopupButtons(); @@ -438,18 +438,23 @@ struct Controller::Impl /** * @brief Updates the cursor position. * - * Retrieves the x,y position of the cursor logical position and sets it into the decorator. + * Sets the cursor's position into the decorator. It transforms the cursor's position into decorator's coords. * It sets the position of the secondary cursor if it's a valid one. * Sets which cursors are active. + * + * @param[in] cursorInfo Contains the selection handle position in Actor's coords. + * */ - void UpdateCursorPosition(); + void UpdateCursorPosition( const CursorInfo& cursorInfo ); /** - * @brief Updates the position of the given selection handle. + * @brief Updates the position of the given selection handle. It transforms the handle's position into decorator's coords. * * @param[in] handleType One of the selection handles. + * @param[in] cursorInfo Contains the selection handle position in Actor's coords. */ - void UpdateSelectionHandle( HandleType handleType ); + void UpdateSelectionHandle( HandleType handleType, + const CursorInfo& cursorInfo ); /** * @biref Clamps the horizontal scrolling to get the control always filled with text. @@ -482,7 +487,7 @@ struct Controller::Impl * * This method is called after deleting text. */ - void ScrollTextToMatchCursor(); + void ScrollTextToMatchCursor( const CursorInfo& cursorInfo); ControlInterface& mControlInterface; ///< Reference to the text controller. LogicalModelPtr mLogicalModel; ///< Pointer to the logical model. diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 6b1e31f..89f0123 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -725,7 +725,9 @@ bool Controller::Relayout( const Size& size ) return glyphsRemoved; } - if( size != mImpl->mVisualModel->mControlSize ) + const bool newSize = ( size != mImpl->mVisualModel->mControlSize ); + + if( newSize ) { DALI_LOG_INFO( gLogFilter, Debug::Verbose, "new size (previous size %f,%f)\n", mImpl->mVisualModel->mControlSize.width, mImpl->mVisualModel->mControlSize.height ); @@ -751,9 +753,9 @@ bool Controller::Relayout( const Size& size ) // Do not re-do any operation until something changes. mImpl->mOperationsPending = NO_OPERATION; - // Keep the current offset and alignment as it will be used to update the decorator's positions. + // Keep the current offset and alignment as it will be used to update the decorator's positions (if the size changes). Vector2 offset; - if( mImpl->mEventData ) + if( newSize && mImpl->mEventData ) { offset = mImpl->mAlignmentOffset + mImpl->mEventData->mScrollPosition; } @@ -763,11 +765,14 @@ bool Controller::Relayout( const Size& size ) if( mImpl->mEventData ) { - // If there is a nex size, the scroll position needs to be clamped. - mImpl->ClampHorizontalScroll( layoutSize ); + if( newSize ) + { + // If there is a new size, the scroll position needs to be clamped. + mImpl->ClampHorizontalScroll( layoutSize ); - // Update the decorator's positions. - mImpl->mEventData->mDecorator->UpdatePositions( mImpl->mAlignmentOffset + mImpl->mEventData->mScrollPosition - offset ); + // Update the decorator's positions is needed if there is a new size. + mImpl->mEventData->mDecorator->UpdatePositions( mImpl->mAlignmentOffset + mImpl->mEventData->mScrollPosition - offset ); + } // Move the cursor, grab handle etc. updated = mImpl->ProcessInputEvents() || updated; @@ -922,11 +927,8 @@ void Controller::TextDeletedEvent() REORDER ); // Queue a cursor reposition event; this must wait until after DoRelayout() - if( 0u == mImpl->mLogicalModel->mText.Count() ) - { - mImpl->mEventData->mUpdateCursorPosition = true; - } - else + mImpl->mEventData->mUpdateCursorPosition = true; + if( 0u != mImpl->mLogicalModel->mText.Count() ) { mImpl->mEventData->mScrollAfterDelete = true; } @@ -1179,8 +1181,7 @@ void Controller::CalculateTextAlignment( const Size& size ) } case LayoutEngine::HORIZONTAL_ALIGN_CENTER: { - const int intOffset = static_cast( 0.5f * ( size.width - actualSize.width ) ); // try to avoid pixel alignment. - mImpl->mAlignmentOffset.x = static_cast( intOffset ); + mImpl->mAlignmentOffset.x = floorf( 0.5f * ( size.width - actualSize.width ) ); // try to avoid pixel alignment. break; } case LayoutEngine::HORIZONTAL_ALIGN_END: @@ -1200,8 +1201,7 @@ void Controller::CalculateTextAlignment( const Size& size ) } case LayoutEngine::VERTICAL_ALIGN_CENTER: { - const int intOffset = static_cast( 0.5f * ( size.height - actualSize.height ) ); // try to avoid pixel alignment. - mImpl->mAlignmentOffset.y = static_cast( intOffset ); + mImpl->mAlignmentOffset.y = floorf( 0.5f * ( size.height - actualSize.height ) ); // try to avoid pixel alignment. break; } case LayoutEngine::VERTICAL_ALIGN_BOTTOM: