X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Ftext-controller.cpp;h=219d8e568765b8c6c2e4bfc219f584a0326fbf6e;hb=cc82bd9b187cda8fe2c8336b73fd1fa9376cfebd;hp=3981ce15b6ceec359d1f43a7224ef0406838bee5;hpb=40a47ee7e802afa836ba45f481b87d0bd28e34fa;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 3981ce1..219d8e5 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -109,7 +109,8 @@ struct Controller::TextInput { INACTIVE, SELECTING, - EDITING + EDITING, + EDITING_WITH_POPUP }; TextInput( LogicalModelPtr logicalModel, @@ -123,9 +124,9 @@ struct Controller::TextInput mSecondaryCursorPosition( 0u ), mDecoratorUpdated( false ), mCursorBlinkEnabled( true ), - mGrabHandleEnabled( false ), - mGrabHandlePopupEnabled( false ), - mSelectionEnabled( false ), + mGrabHandleEnabled( true ), + mGrabHandlePopupEnabled( true ), + mSelectionEnabled( true ), mHorizontalScrollingEnabled( true ), mVerticalScrollingEnabled( false ), mUpdateCursorPosition( false ) @@ -253,6 +254,8 @@ struct Controller::TextInput 2u == tapCount ) { ChangeState( SELECTING ); + + RepositionSelectionHandles( event.p2.mFloat, event.p3.mFloat ); } } @@ -323,13 +326,46 @@ struct Controller::TextInput GetClosestCursorPosition( mPrimaryCursorPosition, xPosition, yPosition, height ); mDecorator->SetPosition( PRIMARY_CURSOR, xPosition, yPosition, height ); - mDecorator->HidePopup(); + //mDecorator->HidePopup(); + ChangeState ( EDITING ); mDecoratorUpdated = true; } else if ( mGrabHandlePopupEnabled && GRAB_HANDLE_RELEASED == state ) { - mDecorator->ShowPopup(); + //mDecorator->ShowPopup(); + ChangeState ( EDITING_WITH_POPUP ); + mDecoratorUpdated = true; + } + } + + void RepositionSelectionHandles( float visualX, float visualY ) + { + // TODO - Find which word was selected + + const Vector& glyphs = mVisualModel->mGlyphs; + const Vector::SizeType glyphCount = glyphs.Count(); + + const Vector& positions = mVisualModel->mGlyphPositions; + const Vector::SizeType positionCount = positions.Count(); + + // Guard against glyphs which did not fit inside the layout + const Vector::SizeType count = (positionCount < glyphCount) ? positionCount : glyphCount; + + if( count ) + { + float primaryX = positions[0].x; + float secondaryX = positions[count-1].x + glyphs[count-1].width; + + // TODO - multi-line selection + const Vector& lines = mVisualModel->mLines; + float height = lines.Count() ? lines[0].lineSize.height : 0.0f; + + mDecorator->SetPosition( PRIMARY_SELECTION_HANDLE, primaryX, 0.0f, height ); + mDecorator->SetPosition( SECONDARY_SELECTION_HANDLE, secondaryX, 0.0f, height ); + + mDecorator->ClearHighlights(); + mDecorator->AddHighlight( primaryX, 0.0f, secondaryX, height ); } } @@ -345,7 +381,7 @@ struct Controller::TextInput mDecorator->StopCursorBlink(); mDecorator->SetGrabHandleActive( false ); mDecorator->SetSelectionActive( false ); - mDecorator->HidePopup(); + mDecorator->SetPopupActive( false ); mDecoratorUpdated = true; } else if ( SELECTING == mState ) @@ -367,6 +403,28 @@ struct Controller::TextInput { mDecorator->SetGrabHandleActive( true ); } + if( mGrabHandlePopupEnabled ) + { + mDecorator->SetPopupActive( false ); + } + mDecorator->SetSelectionActive( false ); + mDecoratorUpdated = true; + } + else if( EDITING_WITH_POPUP == mState ) + { + mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY ); + if( mCursorBlinkEnabled ) + { + mDecorator->StartCursorBlink(); + } + if( mGrabHandleEnabled ) + { + mDecorator->SetGrabHandleActive( true ); + } + if( mGrabHandlePopupEnabled ) + { + mDecorator->SetPopupActive( true ); + } mDecorator->SetSelectionActive( false ); mDecoratorUpdated = true; } @@ -383,11 +441,11 @@ struct Controller::TextInput totalHeight += lines[lineIndex].lineSize.height; if( y < totalHeight ) { - break; + return lineIndex; } } - return lineIndex; + return lineIndex-1; } void GetClosestCursorPosition( CharacterIndex& logical, float& visualX, float& visualY, float& height ) @@ -483,7 +541,7 @@ struct Controller::TextInput float visualX( 0.0f ); float visualY( 0.0f ); - LineIndex lineIndex( 0u ); + float height( 0.0f ); const Vector& lineRuns = mVisualModel->mLines; if( cursorGlyph > 0 ) @@ -495,17 +553,19 @@ struct Controller::TextInput visualX += mVisualModel->mGlyphs[ cursorGlyph ].width; // Find the line height - for( GlyphIndex lastGlyph = 0; lineIndex < lineRuns.Count(); ++lineIndex ) + GlyphIndex lastGlyph( 0 ); + for( LineIndex lineIndex = 0u; lineIndex < lineRuns.Count(); ++lineIndex ) { lastGlyph = (lineRuns[lineIndex].glyphIndex + lineRuns[lineIndex].numberOfGlyphs); if( cursorGlyph < lastGlyph ) { + height = lineRuns[lineIndex].lineSize.height; break; } } } - mDecorator->SetPosition( PRIMARY_CURSOR, visualX, visualY, lineRuns[lineIndex].lineSize.height ); + mDecorator->SetPosition( PRIMARY_CURSOR, visualX, visualY, height ); mDecoratorUpdated = true; } @@ -590,6 +650,10 @@ struct Controller::Impl mFontClient = TextAbstraction::FontClient::Get(); mView.SetVisualModel( mVisualModel ); + + // Set the shadow properties to default + mVisualModel->SetShadowOffset( Vector2::ZERO ); + mVisualModel->SetShadowColor( Vector4::ZERO ); } ~Impl() @@ -677,6 +741,18 @@ void Controller::SetDefaultFontFamily( const std::string& defaultFontFamily ) mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID mImpl->mOperationsPending = ALL_OPERATIONS; mImpl->mRecalculateNaturalSize = true; + + // Clear the font-specific data + mImpl->mLogicalModel->mFontRuns.Clear(); + mImpl->mVisualModel->mGlyphs.Clear(); + mImpl->mVisualModel->mGlyphsToCharacters.Clear(); + mImpl->mVisualModel->mCharactersToGlyph.Clear(); + mImpl->mVisualModel->mCharactersPerGlyph.Clear(); + mImpl->mVisualModel->mGlyphsPerCharacter.Clear(); + mImpl->mVisualModel->mGlyphPositions.Clear(); + mImpl->mVisualModel->mLines.Clear(); + + RequestRelayout(); } const std::string& Controller::GetDefaultFontFamily() const @@ -700,6 +776,18 @@ void Controller::SetDefaultFontStyle( const std::string& defaultFontStyle ) mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID mImpl->mOperationsPending = ALL_OPERATIONS; mImpl->mRecalculateNaturalSize = true; + + // Clear the font-specific data + mImpl->mLogicalModel->mFontRuns.Clear(); + mImpl->mVisualModel->mGlyphs.Clear(); + mImpl->mVisualModel->mGlyphsToCharacters.Clear(); + mImpl->mVisualModel->mCharactersToGlyph.Clear(); + mImpl->mVisualModel->mCharactersPerGlyph.Clear(); + mImpl->mVisualModel->mGlyphsPerCharacter.Clear(); + mImpl->mVisualModel->mGlyphPositions.Clear(); + mImpl->mVisualModel->mLines.Clear(); + + RequestRelayout(); } const std::string& Controller::GetDefaultFontStyle() const @@ -723,6 +811,18 @@ void Controller::SetDefaultPointSize( float pointSize ) mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID mImpl->mOperationsPending = ALL_OPERATIONS; mImpl->mRecalculateNaturalSize = true; + + // Clear the font-specific data + mImpl->mLogicalModel->mFontRuns.Clear(); + mImpl->mVisualModel->mGlyphs.Clear(); + mImpl->mVisualModel->mGlyphsToCharacters.Clear(); + mImpl->mVisualModel->mCharactersToGlyph.Clear(); + mImpl->mVisualModel->mCharactersPerGlyph.Clear(); + mImpl->mVisualModel->mGlyphsPerCharacter.Clear(); + mImpl->mVisualModel->mGlyphPositions.Clear(); + mImpl->mVisualModel->mLines.Clear(); + + RequestRelayout(); } float Controller::GetDefaultPointSize() const @@ -749,6 +849,26 @@ void Controller::GetDefaultFonts( Vector& fonts, Length numberOfCharact } } +const Vector2& Controller::GetShadowOffset() const +{ + return mImpl->mVisualModel->GetShadowOffset(); +} + +const Vector4& Controller::GetShadowColor() const +{ + return mImpl->mVisualModel->GetShadowColor(); +} + +void Controller::SetShadowOffset( const Vector2& shadowOffset ) +{ + mImpl->mVisualModel->SetShadowOffset( shadowOffset ); +} + +void Controller::SetShadowColor( const Vector4& shadowColor ) +{ + mImpl->mVisualModel->SetShadowColor( shadowColor ); +} + void Controller::EnableTextInput( DecoratorPtr decorator ) { if( !mImpl->mTextInput ) @@ -1270,6 +1390,10 @@ void Controller::UpdateModel( OperationsMask operationsRequired ) glyphs, glyphsToCharactersMap, charactersPerGlyph ); + + // Create the 'number of glyphs' per character and the glyph to character conversion tables. + mImpl->mVisualModel->CreateGlyphsPerCharacterTable( numberOfCharacters ); + mImpl->mVisualModel->CreateCharacterToGlyphTable( numberOfCharacters ); } const Length numberOfGlyphs = glyphs.Count(); @@ -1278,13 +1402,6 @@ void Controller::UpdateModel( OperationsMask operationsRequired ) { mImpl->mFontClient.GetGlyphMetrics( glyphs.Begin(), numberOfGlyphs ); } - - if( 0u != numberOfGlyphs ) - { - // Create the glyph to character conversion table and the 'number of glyphs' per character. - mImpl->mVisualModel->CreateCharacterToGlyphTable(numberOfCharacters ); - mImpl->mVisualModel->CreateGlyphsPerCharacterTable( numberOfCharacters ); - } } bool Controller::DoRelayout( const Size& size, @@ -1419,49 +1536,66 @@ bool Controller::DoRelayout( const Size& size, void Controller::CalculateTextAlignment( const Size& size ) { - // TODO : Calculate the vertical offset. - // Get the direction of the first character. const CharacterDirection firstParagraphDirection = mImpl->mLogicalModel->GetCharacterDirection( 0u ); const Size& actualSize = mImpl->mVisualModel->GetActualSize(); // If the first paragraph is right to left swap ALIGN_BEGIN and ALIGN_END; - LayoutEngine::Alignment alignment = mImpl->mLayoutEngine.GetAlignment(); + LayoutEngine::HorizontalAlignment horizontalAlignment = mImpl->mLayoutEngine.GetHorizontalAlignment(); if( firstParagraphDirection && - ( LayoutEngine::ALIGN_CENTER != alignment ) ) + ( LayoutEngine::HORIZONTAL_ALIGN_CENTER != horizontalAlignment ) ) { - if( LayoutEngine::ALIGN_BEGIN == alignment ) + if( LayoutEngine::HORIZONTAL_ALIGN_BEGIN == horizontalAlignment ) { - alignment = LayoutEngine::ALIGN_END; + horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_END; } else { - alignment = LayoutEngine::ALIGN_BEGIN; + horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_BEGIN; } } - switch( alignment ) + switch( horizontalAlignment ) { - case LayoutEngine::ALIGN_BEGIN: + case LayoutEngine::HORIZONTAL_ALIGN_BEGIN: { - mImpl->mAlignmentOffset = Vector2::ZERO; + mImpl->mAlignmentOffset.x = 0.f; break; } - case LayoutEngine::ALIGN_CENTER: + case LayoutEngine::HORIZONTAL_ALIGN_CENTER: { - mImpl->mAlignmentOffset.y = 0.f; const int intOffset = static_cast( 0.5f * ( size.width - actualSize.width ) ); // try to avoid pixel alignment. mImpl->mAlignmentOffset.x = static_cast( intOffset ); break; } - case LayoutEngine::ALIGN_END: + case LayoutEngine::HORIZONTAL_ALIGN_END: { - mImpl->mAlignmentOffset.y = 0.f; mImpl->mAlignmentOffset.x = size.width - actualSize.width; break; } } + + const LayoutEngine::VerticalAlignment verticalAlignment = mImpl->mLayoutEngine.GetVerticalAlignment(); + switch( verticalAlignment ) + { + case LayoutEngine::VERTICAL_ALIGN_TOP: + { + mImpl->mAlignmentOffset.y = 0.f; + break; + } + 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 ); + break; + } + case LayoutEngine::VERTICAL_ALIGN_BOTTOM: + { + mImpl->mAlignmentOffset.y = size.height - actualSize.height; + break; + } + } } View& Controller::GetView() @@ -1546,6 +1680,8 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent ) mImpl->mModifyEvents.push_back( event ); } + mImpl->mTextInput->ChangeState( TextInput::EDITING ); // todo Confirm this is the best place to change the state of + RequestRelayout(); }