X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Ftext-controller-impl.cpp;h=2c59665530f3db844e6fd1a9b1435b6646a39edd;hb=refs%2Fchanges%2F10%2F41310%2F12;hp=c50b753d4ca872e4a59a92a38359fba21f64a9fa;hpb=61cdd0ef6c35b82605b7313845e5dc84b707074f;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index c50b753..2c59665 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -20,6 +20,7 @@ // EXTERNAL INCLUDES #include +#include // INTERNAL INCLUDES #include @@ -35,6 +36,10 @@ namespace { +#if defined(DEBUG_ENABLED) + Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS"); +#endif + /** * @brief Some characters can be shaped in more than one glyph. * This struct is used to retrieve metrics from these group of glyphs. @@ -123,14 +128,15 @@ EventData::EventData( DecoratorPtr decorator ) mDecoratorUpdated( false ), mCursorBlinkEnabled( true ), mGrabHandleEnabled( true ), - mGrabHandlePopupEnabled( false ), + mGrabHandlePopupEnabled( true ), mSelectionEnabled( false ), mHorizontalScrollingEnabled( true ), mVerticalScrollingEnabled( false ), mUpdateCursorPosition( false ), mUpdateLeftSelectionPosition( false ), mUpdateRightSelectionPosition( false ), - mScrollAfterUpdateCursorPosition( false ) + mScrollAfterUpdateCursorPosition( false ), + mScrollAfterDelete( false ) {} EventData::~EventData() @@ -138,14 +144,14 @@ EventData::~EventData() bool Controller::Impl::ProcessInputEvents() { + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::ProcessInputEvents\n" ); if( NULL == mEventData ) { // Nothing to do if there is no text input. + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::ProcessInputEvents no event data\n" ); return false; } - mEventData->mDecoratorUpdated = false; - if( mEventData->mDecorator ) { for( std::vector::iterator iter = mEventData->mEventQueue.begin(); @@ -154,16 +160,6 @@ bool Controller::Impl::ProcessInputEvents() { switch( iter->type ) { - case Event::KEYBOARD_FOCUS_GAIN_EVENT: - { - OnKeyboardFocus( true ); - break; - } - case Event::KEYBOARD_FOCUS_LOST_EVENT: - { - OnKeyboardFocus( false ); - break; - } case Event::CURSOR_KEY_EVENT: { OnCursorKeyEvent( *iter ); @@ -206,6 +202,12 @@ bool Controller::Impl::ProcessInputEvents() mEventData->mDecoratorUpdated = true; mEventData->mUpdateCursorPosition = false; } + else if( mEventData->mScrollAfterDelete ) + { + ScrollTextToMatchCursor(); + mEventData->mDecoratorUpdated = true; + mEventData->mScrollAfterDelete = false; + } else if( mEventData->mUpdateLeftSelectionPosition ) { UpdateSelectionHandle( LEFT_SELECTION_HANDLE ); @@ -235,7 +237,11 @@ bool Controller::Impl::ProcessInputEvents() mEventData->mEventQueue.clear(); - return mEventData->mDecoratorUpdated; + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::ProcessInputEvents\n" ); + + bool decoratorUpdated = mEventData->mDecoratorUpdated; + mEventData->mDecoratorUpdated = false; + return decoratorUpdated; } void Controller::Impl::UpdateModel( OperationsMask operationsRequired ) @@ -398,24 +404,6 @@ void Controller::Impl::GetDefaultFonts( Vector& fonts, Length numberOfC } } -void Controller::Impl::OnKeyboardFocus( bool hasFocus ) -{ - if( NULL == mEventData ) - { - // Nothing to do if there is no text input. - return; - } - - if( !hasFocus ) - { - ChangeState( EventData::INACTIVE ); - } - else - { - ChangeState( EventData::EDITING ); - } -} - void Controller::Impl::OnCursorKeyEvent( const Event& event ) { if( NULL == mEventData ) @@ -544,7 +532,7 @@ void Controller::Impl::OnHandleEvent( const Event& event ) if( Event::GRAB_HANDLE_EVENT == event.type ) { - ChangeState ( EventData::EDITING ); + ChangeState ( EventData::GRAB_HANDLE_PANNING ); if( handleNewPosition != mEventData->mPrimaryCursorPosition ) { @@ -554,6 +542,8 @@ void Controller::Impl::OnHandleEvent( const Event& event ) } else if( Event::LEFT_SELECTION_HANDLE_EVENT == event.type ) { + ChangeState ( EventData::SELECTION_HANDLE_PANNING ); + if( handleNewPosition != mEventData->mLeftSelectionPosition ) { mEventData->mLeftSelectionPosition = handleNewPosition; @@ -562,6 +552,8 @@ void Controller::Impl::OnHandleEvent( const Event& event ) } else if( Event::RIGHT_SELECTION_HANDLE_EVENT == event.type ) { + ChangeState ( EventData::SELECTION_HANDLE_PANNING ); + if( handleNewPosition != mEventData->mRightSelectionPosition ) { mEventData->mRightSelectionPosition = handleNewPosition; @@ -572,14 +564,12 @@ void Controller::Impl::OnHandleEvent( const Event& event ) else if( ( HANDLE_RELEASED == state ) || ( HANDLE_STOP_SCROLLING == state ) ) { - if( mEventData->mGrabHandlePopupEnabled ) - { - ChangeState( EventData::EDITING_WITH_POPUP ); - } if( Event::GRAB_HANDLE_EVENT == event.type ) { mEventData->mUpdateCursorPosition = true; + ChangeState( EventData::EDITING_WITH_POPUP ); + if( HANDLE_STOP_SCROLLING == state ) { // The event.p2 and event.p3 are in decorator coords. Need to transforms to text coords. @@ -591,6 +581,10 @@ void Controller::Impl::OnHandleEvent( const Event& event ) mEventData->mScrollAfterUpdateCursorPosition = true; } } + else if( Event::LEFT_SELECTION_HANDLE_EVENT == event.type || Event::RIGHT_SELECTION_HANDLE_EVENT ) + { + ChangeState( EventData::SELECTING ); + } mEventData->mDecoratorUpdated = true; } else if( HANDLE_SCROLLING == state ) @@ -602,7 +596,16 @@ void Controller::Impl::OnHandleEvent( const Event& event ) ClampHorizontalScroll( actualSize ); - mEventData->mDecoratorUpdated = true; + if( Event::GRAB_HANDLE_EVENT == event.type ) + { + ChangeState( EventData::GRAB_HANDLE_PANNING ); + } + else if( Event::LEFT_SELECTION_HANDLE_EVENT == event.type || Event::RIGHT_SELECTION_HANDLE_EVENT ) + { + ChangeState( EventData::SELECTION_HANDLE_PANNING ); + } + + mEventData->mDecoratorUpdated = true; } } @@ -671,6 +674,10 @@ void Controller::Impl::ChangeState( EventData::State newState ) mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false ); mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true ); mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true ); + if( mEventData->mGrabHandlePopupEnabled ) + { + mEventData->mDecorator->SetPopupActive( true ); + } mEventData->mDecoratorUpdated = true; } else if( EventData::EDITING == mEventData->mState ) @@ -684,6 +691,10 @@ void Controller::Impl::ChangeState( EventData::State newState ) mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false ); mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false ); mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false ); + if( mEventData->mGrabHandlePopupEnabled ) + { + mEventData->mDecorator->SetPopupActive( false ); + } mEventData->mDecoratorUpdated = true; } else if( EventData::EDITING_WITH_POPUP == mEventData->mState ) @@ -693,11 +704,14 @@ void Controller::Impl::ChangeState( EventData::State newState ) { mEventData->mDecorator->StartCursorBlink(); } - mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false ); if( mEventData->mSelectionEnabled ) { - mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true ); - mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true ); + mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false ); + mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false ); + } + else + { + mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true ); } if( mEventData->mGrabHandlePopupEnabled ) { @@ -705,6 +719,35 @@ void Controller::Impl::ChangeState( EventData::State newState ) } mEventData->mDecoratorUpdated = true; } + else if ( EventData::SELECTION_HANDLE_PANNING == mEventData->mState ) + { + mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE ); + mEventData->mDecorator->StopCursorBlink(); + mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false ); + mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true ); + mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true ); + if( mEventData->mGrabHandlePopupEnabled ) + { + mEventData->mDecorator->SetPopupActive( false ); + } + mEventData->mDecoratorUpdated = true; + } + else if ( EventData::GRAB_HANDLE_PANNING == mEventData->mState ) + { + mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY ); + if( mEventData->mCursorBlinkEnabled ) + { + mEventData->mDecorator->StartCursorBlink(); + } + mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true ); + mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false ); + mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false ); + if( mEventData->mGrabHandlePopupEnabled ) + { + mEventData->mDecorator->SetPopupActive( false ); + } + mEventData->mDecoratorUpdated = true; + } } } @@ -1052,45 +1095,126 @@ CharacterIndex Controller::Impl::CalculateNewCursorIndex( CharacterIndex index ) void Controller::Impl::UpdateCursorPosition() { + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::UpdateCursorPosition %p\n", this ); if( NULL == mEventData ) { // Nothing to do if there is no text input. + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::UpdateCursorPosition no event data\n" ); return; } - CursorInfo cursorInfo; - GetCursorPosition( mEventData->mPrimaryCursorPosition, - cursorInfo ); + if( IsShowingPlaceholderText() ) + { + // Do not want to use the place-holder text to set the cursor position. - const Vector2 offset = mEventData->mScrollPosition + mAlignmentOffset; - const Vector2 cursorPosition = cursorInfo.primaryPosition + offset; + // 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. - // Sets the cursor position. - mEventData->mDecorator->SetPosition( PRIMARY_CURSOR, - cursorPosition.x, - cursorPosition.y, - cursorInfo.primaryCursorHeight, - cursorInfo.lineHeight ); + float lineHeight = 0.f; - // Sets the grab handle position. - mEventData->mDecorator->SetPosition( GRAB_HANDLE, - cursorPosition.x, - cursorPosition.y, - cursorInfo.lineHeight ); + FontId defaultFontId = 0u; + if( NULL == mFontDefaults ) + { + defaultFontId = mFontClient.GetFontId( EMPTY_STRING, + EMPTY_STRING ); + } + else + { + defaultFontId = mFontDefaults->GetFontId( mFontClient ); + } - 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 ); + Text::FontMetrics fontMetrics; + mFontClient.GetFontMetrics( defaultFontId, fontMetrics ); + + lineHeight = fontMetrics.ascender - fontMetrics.descender; + + + Vector2 cursorPosition; + + switch( mLayoutEngine.GetHorizontalAlignment() ) + { + case LayoutEngine::HORIZONTAL_ALIGN_BEGIN: + { + cursorPosition.x = 1.f; + break; + } + case LayoutEngine::HORIZONTAL_ALIGN_CENTER: + { + cursorPosition.x = floor( 0.5f * mControlSize.width ); + break; + } + case LayoutEngine::HORIZONTAL_ALIGN_END: + { + cursorPosition.x = mControlSize.width; + break; + } + } + + switch( mLayoutEngine.GetVerticalAlignment() ) + { + case LayoutEngine::VERTICAL_ALIGN_TOP: + { + cursorPosition.y = 0.f; + break; + } + case LayoutEngine::VERTICAL_ALIGN_CENTER: + { + cursorPosition.y = floorf( 0.5f * ( mControlSize.height - lineHeight ) ); + break; + } + case LayoutEngine::VERTICAL_ALIGN_BOTTOM: + { + cursorPosition.y = mControlSize.height - lineHeight; + break; + } + } + + mEventData->mDecorator->SetPosition( PRIMARY_CURSOR, + cursorPosition.x, + cursorPosition.y, + lineHeight, + lineHeight ); } else { - mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY ); + 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, + cursorInfo.lineHeight ); + + 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 ); + } } + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::UpdateCursorPosition\n" ); } void Controller::Impl::UpdateSelectionHandle( HandleType handleType ) @@ -1185,6 +1309,57 @@ void Controller::Impl::ScrollToMakeCursorVisible() // TODO : calculate the vertical scroll. } +void Controller::Impl::ScrollTextToMatchCursor() +{ + // 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() ); + bool updateCursorPosition = true; + + const Vector2 offset = mEventData->mScrollPosition + mAlignmentOffset; + const Vector2 cursorPosition = cursorInfo.primaryPosition + offset; + + if( updateCursorPosition ) + { + // 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->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 ); + } + } +} + void Controller::Impl::RequestRelayout() { mControlInterface.RequestTextRelayout();