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=9e29628b07ab27b2e62946ac209bab99818442e5;hp=f05ffdaa705ddfdfe199d3480800600087935474;hb=079795bcb6a8aab48e5e4252a86f524e6749fcbb;hpb=479e5481d99bd73d0c1858583868f04e71425577 diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index f05ffda..9e29628 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -136,7 +136,8 @@ EventData::EventData( DecoratorPtr decorator ) mUpdateLeftSelectionPosition( false ), mUpdateRightSelectionPosition( false ), mScrollAfterUpdatePosition( false ), - mScrollAfterDelete( false ) + mScrollAfterDelete( false ), + mAllTextSelected( false ) {} EventData::~EventData() @@ -170,6 +171,11 @@ bool Controller::Impl::ProcessInputEvents() OnTapEvent( *iter ); break; } + case Event::LONG_PRESS_EVENT: + { + OnLongPressEvent( *iter ); + break; + } case Event::PAN_EVENT: { OnPanEvent( *iter ); @@ -237,6 +243,7 @@ bool Controller::Impl::ProcessInputEvents() leftScroll = true; } + SetPopupButtons(); mEventData->mDecoratorUpdated = true; mEventData->mUpdateLeftSelectionPosition = false; } @@ -253,6 +260,7 @@ bool Controller::Impl::ProcessInputEvents() rightScroll = true; } + SetPopupButtons(); mEventData->mDecoratorUpdated = true; mEventData->mUpdateRightSelectionPosition = false; } @@ -536,6 +544,15 @@ void Controller::Impl::OnPanEvent( const Event& event ) } } +void Controller::Impl::OnLongPressEvent( const Event& event ) +{ + if ( EventData::EDITING == mEventData->mState ) + { + ChangeState ( EventData::EDITING_WITH_POPUP ); + mEventData->mDecoratorUpdated = true; + } +} + void Controller::Impl::OnHandleEvent( const Event& event ) { if( NULL == mEventData ) @@ -569,7 +586,8 @@ void Controller::Impl::OnHandleEvent( const Event& event ) { ChangeState ( EventData::SELECTION_HANDLE_PANNING ); - if( handleNewPosition != mEventData->mLeftSelectionPosition ) + if( ( handleNewPosition != mEventData->mLeftSelectionPosition ) && + ( handleNewPosition != mEventData->mRightSelectionPosition ) ) { mEventData->mLeftSelectionPosition = handleNewPosition; @@ -583,7 +601,8 @@ void Controller::Impl::OnHandleEvent( const Event& event ) { ChangeState ( EventData::SELECTION_HANDLE_PANNING ); - if( handleNewPosition != mEventData->mRightSelectionPosition ) + if( ( handleNewPosition != mEventData->mRightSelectionPosition ) && + ( handleNewPosition != mEventData->mLeftSelectionPosition ) ) { mEventData->mRightSelectionPosition = handleNewPosition; @@ -625,12 +644,13 @@ void Controller::Impl::OnHandleEvent( const Event& event ) if( handleStopScrolling ) { - mEventData->mUpdateLeftSelectionPosition = mEventData->mLeftSelectionPosition != handlePosition; + mEventData->mUpdateLeftSelectionPosition = ( mEventData->mLeftSelectionPosition != handlePosition ) && ( mEventData->mRightSelectionPosition != handlePosition); mEventData->mScrollAfterUpdatePosition = mEventData->mUpdateLeftSelectionPosition; - mEventData->mLeftSelectionPosition = handlePosition; if( mEventData->mUpdateLeftSelectionPosition ) { + mEventData->mLeftSelectionPosition = handlePosition; + RepositionSelectionHandles( mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition ); } @@ -642,12 +662,12 @@ void Controller::Impl::OnHandleEvent( const Event& event ) if( handleStopScrolling ) { - mEventData->mUpdateRightSelectionPosition = mEventData->mRightSelectionPosition != handlePosition; + mEventData->mUpdateRightSelectionPosition = ( mEventData->mRightSelectionPosition != handlePosition ) && ( mEventData->mLeftSelectionPosition != handlePosition ); mEventData->mScrollAfterUpdatePosition = mEventData->mUpdateRightSelectionPosition; - mEventData->mRightSelectionPosition = handlePosition; if( mEventData->mUpdateRightSelectionPosition ) { + mEventData->mRightSelectionPosition = handlePosition; RepositionSelectionHandles( mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition ); } @@ -660,50 +680,80 @@ void Controller::Impl::OnHandleEvent( const Event& event ) { const float xSpeed = event.p2.mFloat; const Vector2& actualSize = mVisualModel->GetActualSize(); + const Vector2 currentScrollPosition = mEventData->mScrollPosition; mEventData->mScrollPosition.x += xSpeed; ClampHorizontalScroll( actualSize ); - 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 ) + if( Vector2::ZERO == ( currentScrollPosition - mEventData->mScrollPosition ) ) { - ChangeState( EventData::GRAB_HANDLE_PANNING ); + // Notify the decorator there is no more text to scroll. + // The decorator won't send more scroll events. + mEventData->mDecorator->NotifyEndOfScroll(); } - else if( leftSelectionHandleEvent || rightSelectionHandleEvent ) + else { - // TODO: This is recalculating the selection box every time the text is scrolled with the selection handles. - // Think if something can be done to save power. + const bool scrollRightDirection = xSpeed > 0.f; + const bool leftSelectionHandleEvent = Event::LEFT_SELECTION_HANDLE_EVENT == event.type; + const bool rightSelectionHandleEvent = Event::RIGHT_SELECTION_HANDLE_EVENT == event.type; - ChangeState( EventData::SELECTION_HANDLE_PANNING ); + if( Event::GRAB_HANDLE_EVENT == event.type ) + { + ChangeState( EventData::GRAB_HANDLE_PANNING ); - const Vector2& position = mEventData->mDecorator->GetPosition( leftSelectionHandleEvent ? Text::LEFT_SELECTION_HANDLE : Text::RIGHT_SELECTION_HANDLE ); + Vector2 position = mEventData->mDecorator->GetPosition( GRAB_HANDLE ); - // Get the new handle position. - // The selection handle's position is in decorator coords. Need to transforms to text coords. - const CharacterIndex handlePosition = GetClosestCursorIndex( position.x - mEventData->mScrollPosition.x - mAlignmentOffset.x, - position.y - mEventData->mScrollPosition.y - mAlignmentOffset.y ); + // Position the grag handle close to either the left or right edge. + position.x = scrollRightDirection ? 0.f : mControlSize.width; - if( leftSelectionHandleEvent ) - { - mEventData->mUpdateLeftSelectionPosition = handlePosition != mEventData->mLeftSelectionPosition; - mEventData->mLeftSelectionPosition = handlePosition; + // Get the new handle position. + // The grab handle's position is in decorator coords. Need to transforms to text coords. + const CharacterIndex handlePosition = GetClosestCursorIndex( position.x - mEventData->mScrollPosition.x - mAlignmentOffset.x, + position.y - mEventData->mScrollPosition.y - mAlignmentOffset.y ); + + mEventData->mUpdateCursorPosition = mEventData->mPrimaryCursorPosition != handlePosition; + mEventData->mScrollAfterUpdatePosition = mEventData->mUpdateCursorPosition; + mEventData->mPrimaryCursorPosition = handlePosition; } - else + else if( leftSelectionHandleEvent || rightSelectionHandleEvent ) { - mEventData->mUpdateRightSelectionPosition = handlePosition != mEventData->mRightSelectionPosition; - mEventData->mRightSelectionPosition = handlePosition; - } + // TODO: This is recalculating the selection box every time the text is scrolled with the selection handles. + // Think if something can be done to save power. - if( mEventData->mUpdateLeftSelectionPosition || mEventData->mUpdateRightSelectionPosition ) - { - RepositionSelectionHandles( mEventData->mLeftSelectionPosition, - mEventData->mRightSelectionPosition ); + ChangeState( EventData::SELECTION_HANDLE_PANNING ); + + Vector2 position = mEventData->mDecorator->GetPosition( leftSelectionHandleEvent ? Text::LEFT_SELECTION_HANDLE : Text::RIGHT_SELECTION_HANDLE ); + + // Position the selection handle close to either the left or right edge. + position.x = scrollRightDirection ? 0.f : mControlSize.width; + + // Get the new handle position. + // The selection handle's position is in decorator coords. Need to transforms to text coords. + const CharacterIndex handlePosition = GetClosestCursorIndex( position.x - mEventData->mScrollPosition.x - mAlignmentOffset.x, + position.y - mEventData->mScrollPosition.y - mAlignmentOffset.y ); + + if( leftSelectionHandleEvent ) + { + mEventData->mUpdateLeftSelectionPosition = handlePosition != mEventData->mLeftSelectionPosition; + mEventData->mLeftSelectionPosition = handlePosition; + } + else + { + mEventData->mUpdateRightSelectionPosition = handlePosition != mEventData->mRightSelectionPosition; + mEventData->mRightSelectionPosition = handlePosition; + } + + if( mEventData->mUpdateLeftSelectionPosition || mEventData->mUpdateRightSelectionPosition ) + { + RepositionSelectionHandles( mEventData->mLeftSelectionPosition, + mEventData->mRightSelectionPosition ); + + mEventData->mScrollAfterUpdatePosition = true; + } } + mEventData->mDecoratorUpdated = true; } - mEventData->mDecoratorUpdated = true; } // end ( HANDLE_SCROLLING == state ) } @@ -721,12 +771,17 @@ 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; + RepositionSelectionHandles( xPosition, yPosition ); - mEventData->mScrollAfterUpdatePosition = true; - mEventData->mUpdateLeftSelectionPosition = true; - mEventData->mUpdateRightSelectionPosition = true; + mEventData->mUpdateLeftSelectionPosition = leftPosition != mEventData->mLeftSelectionPosition; + mEventData->mUpdateRightSelectionPosition = rightPosition != mEventData->mRightSelectionPosition; + + mEventData->mScrollAfterUpdatePosition = ( ( mEventData->mUpdateLeftSelectionPosition || mEventData->mUpdateRightSelectionPosition ) && + ( mEventData->mLeftSelectionPosition != mEventData->mRightSelectionPosition ) ); } } @@ -749,7 +804,7 @@ void Controller::Impl::OnSelectAllEvent() } } -void Controller::Impl::RetreiveSelection( std::string& selectedText, bool deleteAfterRetreival ) +void Controller::Impl::RetrieveSelection( std::string& selectedText, bool deleteAfterRetreival ) { if( mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition ) { @@ -785,6 +840,22 @@ void Controller::Impl::RetreiveSelection( std::string& selectedText, bool delete } } +void Controller::Impl::ShowClipboard() +{ + if ( mClipboard ) + { + mClipboard.ShowClipboard(); + } +} + +void Controller::Impl::HideClipboard() +{ + if ( mClipboard ) + { + mClipboard.HideClipboard(); + } +} + bool Controller::Impl::CopyStringToClipboard( std::string& source ) { //Send string to clipboard @@ -794,7 +865,7 @@ bool Controller::Impl::CopyStringToClipboard( std::string& source ) void Controller::Impl::SendSelectionToClipboard( bool deleteAfterSending ) { std::string selectedText; - RetreiveSelection( selectedText, deleteAfterSending ); + RetrieveSelection( selectedText, deleteAfterSending ); CopyStringToClipboard( selectedText ); ChangeState( EventData::EDITING ); } @@ -912,6 +983,50 @@ void Controller::Impl::RepositionSelectionHandles( float visualX, float visualY RepositionSelectionHandles( selectionStart, selectionEnd ); } +void Controller::Impl::SetPopupButtons() +{ + /** + * Sets the Popup buttons to be shown depending on State. + * + * If SELECTING : CUT & COPY + ( PASTE & CLIPBOARD if content available to paste ) + * + * If EDITING_WITH_POPUP : SELECT & SELECT_ALL + */ + + TextSelectionPopup::Buttons buttonsToShow = TextSelectionPopup::NONE; + + if ( ( EventData::SELECTING == mEventData->mState ) || ( EventData::SELECTION_CHANGED == mEventData->mState ) ) + { + buttonsToShow = TextSelectionPopup::Buttons( TextSelectionPopup::CUT | TextSelectionPopup::COPY ); + + if ( !IsClipboardEmpty() ) + { + buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) ); + buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::CLIPBOARD ) ); + } + + if ( !mEventData->mAllTextSelected ) + { + buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::SELECT_ALL ) ); + } + } + else if ( EventData::EDITING_WITH_POPUP == mEventData->mState ) + { + if ( mLogicalModel->mText.Count() && !IsShowingPlaceholderText()) + { + buttonsToShow = TextSelectionPopup::Buttons( TextSelectionPopup::SELECT | TextSelectionPopup::SELECT_ALL ); + } + + if ( !IsClipboardEmpty() ) + { + buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) ); + buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::CLIPBOARD ) ); + } + } + + mEventData->mDecorator->SetEnabledPopupButtons( buttonsToShow ); +} + void Controller::Impl::ChangeState( EventData::State newState ) { if( NULL == mEventData ) @@ -933,6 +1048,7 @@ void Controller::Impl::ChangeState( EventData::State newState ) mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false ); mEventData->mDecorator->SetPopupActive( false ); mEventData->mDecoratorUpdated = true; + HideClipboard(); } else if ( EventData::SELECTING == mEventData->mState ) { @@ -943,13 +1059,7 @@ void Controller::Impl::ChangeState( EventData::State newState ) mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true ); if( mEventData->mGrabHandlePopupEnabled ) { - TextSelectionPopup::Buttons buttonsToShow = TextSelectionPopup::Buttons( TextSelectionPopup::CUT | TextSelectionPopup::COPY ); - if ( !IsClipboardEmpty() ) - { - buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) ); - } - - mEventData->mDecorator->SetEnabledPopupButtons( buttonsToShow ); + SetPopupButtons(); mEventData->mDecorator->SetPopupActive( true ); } mEventData->mDecoratorUpdated = true; @@ -958,13 +1068,8 @@ void Controller::Impl::ChangeState( EventData::State newState ) { if( mEventData->mGrabHandlePopupEnabled ) { - TextSelectionPopup::Buttons buttonsToShow = TextSelectionPopup::Buttons( TextSelectionPopup::CUT | TextSelectionPopup::COPY ); - if ( !IsClipboardEmpty() ) - { - buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) ); - } + SetPopupButtons(); mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE ); - mEventData->mDecorator->SetEnabledPopupButtons( buttonsToShow ); mEventData->mDecorator->SetPopupActive( true ); } mEventData->mDecoratorUpdated = true; @@ -985,6 +1090,7 @@ void Controller::Impl::ChangeState( EventData::State newState ) mEventData->mDecorator->SetPopupActive( false ); } mEventData->mDecoratorUpdated = true; + HideClipboard(); } else if( EventData::EDITING_WITH_POPUP == mEventData->mState ) { @@ -1004,16 +1110,10 @@ void Controller::Impl::ChangeState( EventData::State newState ) } if( mEventData->mGrabHandlePopupEnabled ) { - TextSelectionPopup::Buttons buttonsToShow = TextSelectionPopup::Buttons( TextSelectionPopup::SELECT | TextSelectionPopup::SELECT_ALL ); - - if ( !IsClipboardEmpty() ) - { - buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) ); - } - - mEventData->mDecorator->SetEnabledPopupButtons( buttonsToShow ); + SetPopupButtons(); mEventData->mDecorator->SetPopupActive( true ); } + HideClipboard(); mEventData->mDecoratorUpdated = true; } else if ( EventData::SELECTION_HANDLE_PANNING == mEventData->mState ) @@ -1145,6 +1245,7 @@ CharacterIndex Controller::Impl::GetClosestCursorIndex( float visualX, // Get the glyphs per character table. const Length* const glyphsPerCharacterBuffer = mVisualModel->mGlyphsPerCharacter.Begin(); + const Length* const charactersPerGlyphBuffer = mVisualModel->mCharactersPerGlyph.Begin(); // If the vector is void, there is no right to left characters. const bool hasRightToLeftCharacters = NULL != visualToLogicalBuffer; @@ -1163,9 +1264,11 @@ CharacterIndex Controller::Impl::GetClosestCursorIndex( float visualX, // The character in logical order. const CharacterIndex characterLogicalOrderIndex = hasRightToLeftCharacters ? *( visualToLogicalBuffer + visualIndex ) : visualIndex; + // Get the script of the character. + const Script script = mLogicalModel->GetScript( characterLogicalOrderIndex ); + // The first glyph for that character in logical order. const GlyphIndex glyphLogicalOrderIndex = *( charactersToGlyphBuffer + characterLogicalOrderIndex ); - // The number of glyphs for that character const Length numberOfGlyphs = *( glyphsPerCharacterBuffer + characterLogicalOrderIndex ); @@ -1179,12 +1282,25 @@ CharacterIndex Controller::Impl::GetClosestCursorIndex( float visualX, const Vector2& position = *( positionsBuffer + glyphLogicalOrderIndex ); - // Find the mid-point of the area containing the glyph - const float glyphCenter = -glyphMetrics.xBearing + position.x + 0.5f * glyphMetrics.advance; + // Prevents to jump the whole Latin ligatures like fi, ff, ... + const Length numberOfCharactersInLigature = ( TextAbstraction::LATIN == script ) ? *( charactersPerGlyphBuffer + glyphLogicalOrderIndex ) : 1u; + const float glyphAdvance = glyphMetrics.advance / static_cast( numberOfCharactersInLigature ); + + for( GlyphIndex index = 0u; !matched && ( index < numberOfCharactersInLigature ); ++index ) + { + // Find the mid-point of the area containing the glyph + const float glyphCenter = -glyphMetrics.xBearing + position.x + ( static_cast( index ) + 0.5f ) * glyphAdvance; + + if( visualX < glyphCenter ) + { + visualIndex += index; + matched = true; + break; + } + } - if( visualX < glyphCenter ) + if( matched ) { - matched = true; break; } } @@ -1198,6 +1314,7 @@ CharacterIndex Controller::Impl::GetClosestCursorIndex( float visualX, logicalIndex = hasRightToLeftCharacters ? *( visualToLogicalCursorBuffer + visualIndex ) : visualIndex; DALI_LOG_INFO( gLogFilter, Debug::Verbose, "%p closest visualIndex %d logicalIndex %d\n", this, visualIndex, logicalIndex ); + return logicalIndex; } @@ -1231,7 +1348,7 @@ void Controller::Impl::GetCursorPosition( CharacterIndex logical, cursorInfo.lineHeight = fontMetrics.ascender - fontMetrics.descender; cursorInfo.primaryCursorHeight = cursorInfo.lineHeight; - cursorInfo.primaryPosition.x = 0.f; + cursorInfo.primaryPosition.x = 1.f; cursorInfo.primaryPosition.y = 0.f; // Nothing else to do. @@ -1580,6 +1697,11 @@ void Controller::Impl::UpdateSelectionHandle( HandleType handleType ) cursorPosition.x, cursorPosition.y, cursorInfo.lineHeight ); + + // If selection handle at start of the text and other at end of the text then all text is selected. + const CharacterIndex startOfSelection = std::min( mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition ); + const CharacterIndex endOfSelection = std::max ( mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition ); + mEventData->mAllTextSelected = ( startOfSelection == 0 ) && ( endOfSelection == mLogicalModel->mText.Count() ); } void Controller::Impl::ClampHorizontalScroll( const Vector2& actualSize ) @@ -1655,41 +1777,51 @@ void Controller::Impl::ScrollTextToMatchCursor() 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 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, + // 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::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 ); + } } void Controller::Impl::RequestRelayout()