From: Adeel Kazmi Date: Fri, 13 May 2016 14:34:48 +0000 (-0700) Subject: Merge "Auto Scrolling Text Label" into devel/master X-Git-Tag: dali_1.1.35~10 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=00fdaec1c1d0ae69756e720ac5d3bc3acc5bd2a9;hp=5e6cbdae47a886e55e1d607a061adbf2adea9537 Merge "Auto Scrolling Text Label" into devel/master --- diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp index 9378648..08f085d 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp @@ -51,6 +51,10 @@ const char* const PROPERTY_NAME_UNDERLINE_ENABLED = "underlineEnabled"; const char* const PROPERTY_NAME_UNDERLINE_COLOR = "underlineColor"; const char* const PROPERTY_NAME_UNDERLINE_HEIGHT = "underlineHeight"; const char* const PROPERTY_NAME_ENABLE_MARKUP = "enableMarkup"; +const char* const PROPERTY_NAME_ENABLE_AUTO_SCROLL = "enableAutoScroll"; +const char* const PROPERTY_NAME_ENABLE_AUTO_SCROLL_SPEED = "autoScrollSpeed"; +const char* const PROPERTY_NAME_ENABLE_AUTO_SCROLL_LOOPS = "autoScrollLoopCount"; +const char* const PROPERTY_NAME_ENABLE_AUTO_SCROLL_GAP = "autoScrollGap"; const int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND; @@ -152,6 +156,10 @@ int UtcDaliToolkitTextLabelGetPropertyP(void) DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_UNDERLINE_COLOR ) == TextLabel::Property::UNDERLINE_COLOR ); DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_UNDERLINE_HEIGHT) == TextLabel::Property::UNDERLINE_HEIGHT ); DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_ENABLE_MARKUP) == TextLabel::Property::ENABLE_MARKUP ); + DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_ENABLE_AUTO_SCROLL ) == TextLabel::Property::ENABLE_AUTO_SCROLL ); + DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_ENABLE_AUTO_SCROLL_SPEED ) == TextLabel::Property::AUTO_SCROLL_SPEED ); + DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_ENABLE_AUTO_SCROLL_LOOPS ) == TextLabel::Property::AUTO_SCROLL_LOOP_COUNT ); + DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_ENABLE_AUTO_SCROLL_GAP ) == TextLabel::Property::AUTO_SCROLL_GAP ); END_TEST; } @@ -218,6 +226,20 @@ int UtcDaliToolkitTextLabelSetPropertyP(void) label.SetProperty( TextLabel::Property::ENABLE_MARKUP, true ); DALI_TEST_CHECK( label.GetProperty( TextLabel::Property::ENABLE_MARKUP ) ); + // Check autoscroll properties + const int SCROLL_SPEED = 80; + const int SCROLL_LOOPS = 4; + const float SCROLL_GAP = 50.0f; + label.SetProperty( TextLabel::Property::MULTI_LINE, false ); // Autoscroll only supported in single line + DALI_TEST_CHECK( !label.GetProperty( TextLabel::Property::ENABLE_AUTO_SCROLL ) ); + label.SetProperty( TextLabel::Property::ENABLE_AUTO_SCROLL, true ); + DALI_TEST_CHECK( label.GetProperty( TextLabel::Property::ENABLE_AUTO_SCROLL ) ); + label.SetProperty( TextLabel::Property::AUTO_SCROLL_SPEED, SCROLL_SPEED ); + DALI_TEST_EQUALS( SCROLL_SPEED, label.GetProperty( TextLabel::Property::AUTO_SCROLL_SPEED ), TEST_LOCATION ); + label.SetProperty( TextLabel::Property::AUTO_SCROLL_LOOP_COUNT, SCROLL_LOOPS ); + DALI_TEST_EQUALS( SCROLL_LOOPS, label.GetProperty( TextLabel::Property::AUTO_SCROLL_LOOP_COUNT ), TEST_LOCATION ); + label.SetProperty( TextLabel::Property::AUTO_SCROLL_GAP, SCROLL_GAP ); + DALI_TEST_EQUALS( SCROLL_GAP, label.GetProperty( TextLabel::Property::AUTO_SCROLL_GAP ), TEST_LOCATION ); END_TEST; } @@ -321,3 +343,32 @@ int UtcDaliToolkitTextLabelVectorBasedP(void) END_TEST; } +int UtcDaliToolkitTextlabelScrollingP(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliToolkitTextLabelScrollingP"); + TextLabel label = TextLabel::New("Some text to scroll"); + DALI_TEST_CHECK( label ); + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + Stage::GetCurrent().Add( label ); + // Turn on all the effects + label.SetProperty( TextLabel::Property::MULTI_LINE, false ); + label.SetProperty( TextLabel::Property::AUTO_SCROLL_GAP, 50.0f ); + label.SetProperty( TextLabel::Property::AUTO_SCROLL_LOOP_COUNT, 3 ); + label.SetProperty( TextLabel::Property::AUTO_SCROLL_SPEED, 80.0f); + + try + { + // Render some text with the shared atlas backend + label.SetProperty( TextLabel::Property::ENABLE_AUTO_SCROLL, true ); + application.SendNotification(); + application.Render(); + } + catch( ... ) + { + tet_result(TET_FAIL); + } + + 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 e7bac78..6d46758 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include using Dali::Toolkit::Text::LayoutEngine; @@ -50,8 +51,8 @@ namespace namespace { -#if defined(DEBUG_ENABLED) - Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS"); +#if defined ( DEBUG_ENABLED ) + Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS"); #endif const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] = @@ -79,24 +80,30 @@ BaseHandle Create() // Setup properties, signals and actions using the type-registry. DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextLabel, Toolkit::Control, Create ); -DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "renderingBackend", INTEGER, RENDERING_BACKEND ) -DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "text", STRING, TEXT ) -DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "fontFamily", STRING, FONT_FAMILY ) -DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "fontStyle", STRING, FONT_STYLE ) -DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "pointSize", FLOAT, POINT_SIZE ) -DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "multiLine", BOOLEAN, MULTI_LINE ) -DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "horizontalAlignment", STRING, HORIZONTAL_ALIGNMENT ) -DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "verticalAlignment", STRING, VERTICAL_ALIGNMENT ) -DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "textColor", VECTOR4, TEXT_COLOR ) -DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "shadowOffset", VECTOR2, SHADOW_OFFSET ) -DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "shadowColor", VECTOR4, SHADOW_COLOR ) -DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "underlineEnabled", BOOLEAN, UNDERLINE_ENABLED ) -DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "underlineColor", VECTOR4, UNDERLINE_COLOR ) -DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "underlineHeight", FLOAT, UNDERLINE_HEIGHT ) -DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "enableMarkup", BOOLEAN, ENABLE_MARKUP ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "renderingBackend", INTEGER, RENDERING_BACKEND ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "text", STRING, TEXT ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "fontFamily", STRING, FONT_FAMILY ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "fontStyle", STRING, FONT_STYLE ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "pointSize", FLOAT, POINT_SIZE ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "multiLine", BOOLEAN, MULTI_LINE ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "horizontalAlignment", STRING, HORIZONTAL_ALIGNMENT ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "verticalAlignment", STRING, VERTICAL_ALIGNMENT ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "textColor", VECTOR4, TEXT_COLOR ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "shadowOffset", VECTOR2, SHADOW_OFFSET ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "shadowColor", VECTOR4, SHADOW_COLOR ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "underlineEnabled", BOOLEAN, UNDERLINE_ENABLED ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "underlineColor", VECTOR4, UNDERLINE_COLOR ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "underlineHeight", FLOAT, UNDERLINE_HEIGHT ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "enableMarkup", BOOLEAN, ENABLE_MARKUP ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "enableAutoScroll", BOOLEAN, ENABLE_AUTO_SCROLL ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "autoScrollSpeed", INTEGER, AUTO_SCROLL_SPEED ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "autoScrollLoopCount", INTEGER, AUTO_SCROLL_LOOP_COUNT ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "autoScrollGap", FLOAT, AUTO_SCROLL_GAP ) DALI_TYPE_REGISTRATION_END() + + } // namespace Toolkit::TextLabel TextLabel::New() @@ -161,7 +168,7 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr { const std::string fontFamily = value.Get< std::string >(); - DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::SetProperty Property::FONT_FAMILY newFont(%s)\n", fontFamily.c_str() ); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextLabel::SetProperty Property::FONT_FAMILY newFont(%s)\n", fontFamily.c_str() ); impl.mController->SetDefaultFontFamily( fontFamily ); } break; @@ -312,6 +319,59 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr } break; } + case Toolkit::TextLabel::Property::ENABLE_AUTO_SCROLL: + { + if( impl.mController ) + { + const bool enableAutoScroll = value.Get(); + // If request to auto scroll is the same as current state then do nothing. + if ( enableAutoScroll != impl.mController->IsAutoScrollEnabled() ) + { + // If request is disable (false) and auto scrolling is enabled then need to stop it + if ( enableAutoScroll == false ) + { + if( impl.mTextScroller ) + { + impl.mTextScroller->SetLoopCount( 0 ); // Causes the current animation to finish playing (0) + } + } + // If request is enable (true) then start autoscroll as not already running + else + { + impl.mController->GetLayoutEngine().SetTextEllipsisEnabled( false ); + impl.mController->SetAutoScrollEnabled( enableAutoScroll ); + } + } + } + break; + } + case Toolkit::TextLabel::Property::AUTO_SCROLL_SPEED: + { + if( !impl.mTextScroller ) + { + impl.mTextScroller = Text::TextScroller::New( impl ); + } + impl.mTextScroller->SetSpeed( value.Get() ); + break; + } + case Toolkit::TextLabel::Property::AUTO_SCROLL_LOOP_COUNT: + { + if( !impl.mTextScroller ) + { + impl.mTextScroller = Text::TextScroller::New( impl ); + } + impl.mTextScroller->SetLoopCount( value.Get() ); + break; + } + case Toolkit::TextLabel::Property::AUTO_SCROLL_GAP: + { + if( !impl.mTextScroller ) + { + impl.mTextScroller = Text::TextScroller::New( impl ); + } + impl.mTextScroller->SetGap( value.Get() ); + break; + } } } } @@ -455,6 +515,44 @@ Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index inde } break; } + case Toolkit::TextLabel::Property::ENABLE_AUTO_SCROLL: + { + if( impl.mController ) + { + value = impl.mController->IsAutoScrollEnabled(); + } + break; + } + case Toolkit::TextLabel::Property::AUTO_SCROLL_SPEED: + { + TextLabel& impl( GetImpl( label ) ); + if ( impl.mTextScroller ) + { + value = impl.mTextScroller->GetSpeed(); + } + break; + } + case Toolkit::TextLabel::Property::AUTO_SCROLL_LOOP_COUNT: + { + if( impl.mController ) + { + TextLabel& impl( GetImpl( label ) ); + if ( impl.mTextScroller ) + { + value = impl.mTextScroller->GetLoopCount(); + } + } + break; + } + case Toolkit::TextLabel::Property::AUTO_SCROLL_GAP: + { + TextLabel& impl( GetImpl( label ) ); + if ( impl.mTextScroller ) + { + value = impl.mTextScroller->GetGap(); + } + break; + } } } @@ -478,7 +576,7 @@ void TextLabel::OnInitialize() // Enable the text ellipsis. LayoutEngine& engine = mController->GetLayoutEngine(); - engine.SetTextEllipsisEnabled( true ); + engine.SetTextEllipsisEnabled( true ); // If false then text larger than control will overflow engine.SetCursorWidth( 0u ); // Do not layout space for the cursor. self.OnStageSignal().Connect( this, &TextLabel::OnStageConnect ); @@ -530,6 +628,8 @@ float TextLabel::GetHeightForWidth( float width ) void TextLabel::OnRelayout( const Vector2& size, RelayoutContainer& container ) { + DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::OnRelayout\n" ); + if( mController->Relayout( size ) || !mRenderer ) { @@ -548,8 +648,11 @@ void TextLabel::RequestTextRelayout() void TextLabel::RenderText() { + DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::RenderText IsAutoScrollEnabled[%s] [%p]\n", ( mController->IsAutoScrollEnabled())?"true":"false", this ); + Actor self = Self(); Actor renderableActor; + if( mRenderer ) { renderableActor = mRenderer->Render( mController->GetView(), DepthIndex::TEXT ); @@ -568,9 +671,37 @@ void TextLabel::RenderText() self.Add( renderableActor ); } mRenderableActor = renderableActor; + + if ( mController->IsAutoScrollEnabled() ) + { + SetUpAutoScrolling(); + } } } +void TextLabel::SetUpAutoScrolling() +{ + const Size& controlSize = mController->GetView().GetControlSize(); + const Size& offScreenSize = GetNaturalSize().GetVectorXY(); // As relayout of text may not be done at this point natural size is used to get size. Single line scrolling only. + const Vector2& alignmentOffset = mController->GetAlignmentOffset(); + const Text::CharacterDirection direction = mController->GetAutoScrollDirection(); + + DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::SetUpAutoScrolling alignmentOffset[%f] offScreenSize[%f]\n", alignmentOffset.x, offScreenSize.width); + + if ( !mTextScroller ) + { + DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::SetUpAutoScrolling Creating default TextScoller\n"); + + // If speed, loopCount or gap not set via property system then will need to create a TextScroller with defaults + mTextScroller = Text::TextScroller::New( *this ); + } + mTextScroller->SetParameters( mRenderableActor, controlSize, offScreenSize, direction, alignmentOffset ); + + Actor self = Self(); + self.Add( mTextScroller->GetScrollingText() ); + self.Add( mTextScroller->GetSourceCamera() ); +} + void TextLabel::OnStageConnect( Dali::Actor actor ) { if ( mHasBeenStaged ) @@ -606,6 +737,15 @@ void TextLabel::MaxLengthReached() // Pure Virtual from TextController Interface, only needed when inputting text } +void TextLabel::ScrollingFinished() +{ + // Pure Virtual from TextScroller Interface + DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::ScrollingFinished\n"); + mController->SetAutoScrollEnabled( false ); + mController->GetLayoutEngine().SetTextEllipsisEnabled( true ); + RequestTextRelayout(); +} + TextLabel::TextLabel() : Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ), mRenderingBackend( DEFAULT_RENDERING_BACKEND ), diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.h b/dali-toolkit/internal/controls/text-controls/text-label-impl.h index ae88beb..c2dd485 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.h @@ -22,7 +22,9 @@ #include #include #include +#include #include +#include namespace Dali { @@ -36,7 +38,7 @@ namespace Internal /** * @brief A control which renders a short text string. */ -class TextLabel : public Control, public Text::ControlInterface +class TextLabel : public Control, public Text::ControlInterface, public Text::ScrollerInterface { public: @@ -117,6 +119,13 @@ private: // From Control */ virtual void MaxLengthReached(); +private: // from TextScroller + + /** + * @copydoc Text::ScrollerInterface::ScrollingFinished() + */ + virtual void ScrollingFinished(); + private: // Implementation /** @@ -143,10 +152,16 @@ private: */ void RenderText(); + /** + * @brief Set up Autoscrolling + */ + void SetUpAutoScrolling(); + private: // Data Text::ControllerPtr mController; Text::RendererPtr mRenderer; + Text::TextScrollerPtr mTextScroller; Actor mRenderableActor; int mRenderingBackend; bool mHasBeenStaged:1; diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index cd24d24..d043b79 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -106,6 +106,8 @@ toolkit_src_files = \ $(toolkit_src_dir)/text/text-controller-impl.cpp \ $(toolkit_src_dir)/text/text-font-style.cpp \ $(toolkit_src_dir)/text/text-io.cpp \ + $(toolkit_src_dir)/text/text-scroller.cpp \ + $(toolkit_src_dir)/text/text-scroller-interface.cpp \ $(toolkit_src_dir)/text/text-view.cpp \ $(toolkit_src_dir)/text/text-view-interface.cpp \ $(toolkit_src_dir)/text/visual-model-impl.cpp \ diff --git a/dali-toolkit/internal/text/layouts/layout-engine.cpp b/dali-toolkit/internal/text/layouts/layout-engine.cpp index a5da5a4..ac9110e 100644 --- a/dali-toolkit/internal/text/layouts/layout-engine.cpp +++ b/dali-toolkit/internal/text/layouts/layout-engine.cpp @@ -1242,11 +1242,13 @@ void LayoutEngine::SetLayout( Layout layout ) LayoutEngine::Layout LayoutEngine::GetLayout() const { + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "GetLayout[%d]\n", mImpl->mLayout); return mImpl->mLayout; } void LayoutEngine::SetTextEllipsisEnabled( bool enabled ) { + DALI_LOG_INFO( gLogFilter, Debug::General, "-->LayoutEngine::SetTextEllipsisEnabled[%s]\n", (enabled)?"true":"false" ); mImpl->mEllipsisEnabled = enabled; } diff --git a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp index 2db0faa..32ab39b 100644 --- a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp @@ -38,7 +38,7 @@ using namespace Dali::Toolkit::Text; namespace { #if defined(DEBUG_ENABLED) - Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_RENDERING"); + Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_RENDERING"); #endif const float ZERO( 0.0f ); @@ -433,6 +433,9 @@ struct AtlasRenderer::Impl renderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, depthIndex - 1 ); containerActor.Add( shadowActor ); containerActor.Add( actor ); +#if defined(DEBUG_ENABLED) + containerActor.SetName("TextContainer"); +#endif actor = containerActor; } } @@ -504,7 +507,6 @@ struct AtlasRenderer::Impl // Keep all of the origins aligned actor.SetParentOrigin( ParentOrigin::TOP_LEFT ); actor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - actor.SetSize( actorSize ); actor.RegisterProperty("uOffset", Vector2::ZERO ); return actor; @@ -738,6 +740,8 @@ Text::RendererPtr AtlasRenderer::New() Actor AtlasRenderer::Render( Text::ViewInterface& view, int depth ) { + DALI_LOG_INFO( gLogFilter, Debug::General, "Text::AtlasRenderer::Render()\n" ); + UnparentAndReset( mImpl->mActor ); Length numberOfGlyphs = view.GetNumberOfGlyphs(); diff --git a/dali-toolkit/internal/text/text-controller-impl.h b/dali-toolkit/internal/text/text-controller-impl.h index ce8a291..5c1ed0c 100644 --- a/dali-toolkit/internal/text/text-controller-impl.h +++ b/dali-toolkit/internal/text/text-controller-impl.h @@ -301,7 +301,9 @@ struct Controller::Impl mMaximumNumberOfCharacters( 50u ), mRecalculateNaturalSize( true ), mMarkupProcessorEnabled( false ), - mClipboardHideEnabled( true ) + mClipboardHideEnabled( true ), + mAutoScrollEnabled( false ), + mAutoScrollDirectionRTL( false ) { mLogicalModel = LogicalModel::New(); mVisualModel = VisualModel::New(); @@ -658,7 +660,10 @@ public: bool mRecalculateNaturalSize:1; ///< Whether the natural size needs to be recalculated. bool mMarkupProcessorEnabled:1; ///< Whether the mark-up procesor is enabled. - bool mClipboardHideEnabled:1; ///< Whether the ClipboardHide function work or not + bool mClipboardHideEnabled:1; ///< Whether the ClipboardHide function work or not + bool mAutoScrollEnabled:1; ///< Whether auto text scrolling is enabled. + CharacterDirection mAutoScrollDirectionRTL:1; ///< Direction of auto scrolling, true if rtl + }; } // namespace Text diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 3a211e1..36c293e 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -132,6 +132,55 @@ bool Controller::IsMarkupProcessorEnabled() const return mImpl->mMarkupProcessorEnabled; } +void Controller::SetAutoScrollEnabled( bool enable ) +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled[%s] SingleBox[%s]-> [%p]\n", (enable)?"true":"false", ( mImpl->mLayoutEngine.GetLayout() == LayoutEngine::SINGLE_LINE_BOX)?"true":"false", this ); + + if ( mImpl->mLayoutEngine.GetLayout() == LayoutEngine::SINGLE_LINE_BOX ) + { + if ( enable ) + { + DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled for SINGLE_LINE_BOX\n" ); + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | + LAYOUT | + ALIGN | + UPDATE_ACTUAL_SIZE | + UPDATE_DIRECTION | + REORDER ); + + } + else + { + DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled Disabling autoscroll\n"); + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | + LAYOUT | + ALIGN | + UPDATE_ACTUAL_SIZE | + REORDER ); + } + + mImpl->mAutoScrollEnabled = enable; + mImpl->RequestRelayout(); + } + else + { + DALI_LOG_WARNING( "Attempted AutoScrolling on a non SINGLE_LINE_BOX, request ignored" ); + mImpl->mAutoScrollEnabled = false; + } +} + +bool Controller::IsAutoScrollEnabled() const +{ + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::IsAutoScrollEnabled[%s]\n", (mImpl->mAutoScrollEnabled)?"true":"false" ); + + return mImpl->mAutoScrollEnabled; +} + +CharacterDirection Controller::GetAutoScrollDirection() const +{ + return mImpl->mAutoScrollDirectionRTL; +} + void Controller::SetText( const std::string& text ) { DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SetText\n" ); @@ -473,7 +522,7 @@ float Controller::GetDefaultPointSize() const void Controller::UpdateAfterFontChange( const std::string& newDefaultFont ) { - DALI_LOG_INFO( gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange"); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::UpdateAfterFontChange"); if( !mImpl->mFontDefaults->familyDefined ) // If user defined font then should not update when system font changes { @@ -1173,7 +1222,7 @@ float Controller::GetHeightForWidth( float width ) bool Controller::Relayout( const Size& size ) { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::Relayout %p size %f,%f\n", this, size.width, size.height ); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::Relayout %p size %f,%f, autoScroll[%s]\n", this, size.width, size.height, (mImpl->mAutoScrollEnabled)?"true":"false" ); if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) ) { @@ -1432,6 +1481,8 @@ bool Controller::DoRelayout( const Size& size, if( NO_OPERATION != ( LAYOUT & operations ) ) { + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::DoRelayout LAYOUT & operations\n"); + // Some vectors with data needed to layout and reorder may be void // after the first time the text has been laid out. // Fill the vectors again. @@ -1500,8 +1551,14 @@ bool Controller::DoRelayout( const Size& size, mImpl->mVisualModel->mLines, layoutSize ); + if( viewUpdated ) { + if ( NO_OPERATION != ( UPDATE_DIRECTION & operations ) ) + { + mImpl->mAutoScrollDirectionRTL = false; + } + // Reorder the lines if( NO_OPERATION != ( REORDER & operations ) ) { @@ -1532,6 +1589,14 @@ bool Controller::DoRelayout( const Size& size, requestedNumberOfCharacters, glyphPositions ); + if ( ( NO_OPERATION != ( UPDATE_DIRECTION & operations ) ) && ( numberOfLines > 0 ) ) + { + const LineRun* const firstline = mImpl->mVisualModel->mLines.Begin(); + if ( firstline ) + { + mImpl->mAutoScrollDirectionRTL = firstline->direction; + } + } } } // REORDER @@ -1562,7 +1627,11 @@ bool Controller::DoRelayout( const Size& size, viewUpdated = true; } - +#if defined(DEBUG_ENABLED) + std::string currentText; + GetText( currentText ); + DALI_LOG_INFO( gLogFilter, Debug::Concise, "Controller::DoRelayout [%p] mImpl->mAutoScrollDirectionRTL[%s] [%s]\n", this, (mImpl->mAutoScrollDirectionRTL)?"true":"false", currentText.c_str() ); +#endif DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::DoRelayout, view updated %s\n", ( viewUpdated ? "true" : "false" ) ); return viewUpdated; } diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index 6a83374..5a96349 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -86,6 +86,7 @@ public: REORDER = 0x0400, ALIGN = 0x0800, COLOR = 0x1000, + UPDATE_DIRECTION = 0x2000, ALL_OPERATIONS = 0xFFFF }; @@ -149,6 +150,30 @@ public: bool IsMarkupProcessorEnabled() const; /** + * @brief Enables/disables the auto text scrolling + * + * By default is disabled. + * + * @param[in] enable Whether to enable the auto scrolling + */ + void SetAutoScrollEnabled( bool enable ); + + /** + * @brief Retrieves whether auto text scrolling is enabled. + * + * By default is disabled. + * + * @return @e true if auto scrolling is enabled, otherwise returns @e false. + */ + bool IsAutoScrollEnabled() const; + + /** + * @brief Get direction of the text from the first line of text, + * @return bool rtl (right to left) is true + */ + CharacterDirection GetAutoScrollDirection() const; + + /** * @brief Replaces any text previously set. * * @note This will be converted into UTF-32 when stored in the text model. diff --git a/dali-toolkit/internal/text/text-scroller-interface.cpp b/dali-toolkit/internal/text/text-scroller-interface.cpp new file mode 100644 index 0000000..ee85ef9 --- /dev/null +++ b/dali-toolkit/internal/text/text-scroller-interface.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +ScrollerInterface::ScrollerInterface() +{ +} + +ScrollerInterface::~ScrollerInterface() +{ +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/text-scroller-interface.h b/dali-toolkit/internal/text/text-scroller-interface.h new file mode 100644 index 0000000..31a0819 --- /dev/null +++ b/dali-toolkit/internal/text/text-scroller-interface.h @@ -0,0 +1,61 @@ +#ifndef __DALI_TOOLKIT_TEXT_SCROLLER_INTERFACE_H__ +#define __DALI_TOOLKIT_TEXT_SCROLLER_INTERFACE_H__ + +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +namespace Dali +{ + +class Actor; + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief An interface used by the text-controls which implement auto-scrolling + */ +class ScrollerInterface +{ +public: + + /** + * @brief Constructor. + */ + ScrollerInterface(); + + /** + * @brief Virtual destructor. + */ + virtual ~ScrollerInterface(); + + /** + * @brief Called when the scrolling finishes + */ + virtual void ScrollingFinished() = 0; +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_SCROLLER_INTERFACE_H__ diff --git a/dali-toolkit/internal/text/text-scroller.cpp b/dali-toolkit/internal/text/text-scroller.cpp new file mode 100644 index 0000000..5b7b99b --- /dev/null +++ b/dali-toolkit/internal/text/text-scroller.cpp @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace +{ + +#if defined ( DEBUG_ENABLED ) + Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_SCROLLING"); +#endif + +const int MINIMUM_SCROLL_SPEED = 1; // Speed should be set by Property system. + +const char* VERTEX_SHADER_SCROLL = DALI_COMPOSE_SHADER( + attribute mediump vec2 aPosition;\n + varying highp vec2 vTexCoord;\n + varying highp float vRatio;\n + uniform mediump mat4 uMvpMatrix;\n + uniform mediump vec3 uSize;\n + uniform mediump float uDelta;\n + uniform mediump vec2 uTextureSize; + uniform mediump float uGap;\n + uniform mediump float uRtl;\n + \n + void main()\n + {\n + {\n + mediump vec4 vertexPosition = vec4(aPosition*uSize.xy, 0.0, 1.0);\n + float smallTextPadding = max(uSize.x - uTextureSize.x, 0. );\n + float gap = max( uGap, smallTextPadding );\n + vTexCoord.x = ( uDelta + ( uRtl * ( uTextureSize.x - uSize.x ) ) + ( aPosition.x * uSize.x ) )/ ( uTextureSize.x+gap );\n + vTexCoord.y = aPosition.y;\n + vRatio = uTextureSize.x / ( uTextureSize.x + gap );\n + gl_Position = uMvpMatrix * vertexPosition;\n + }\n + }\n +); + +const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER( + varying mediump vec2 vTexCoord;\n + varying highp float vRatio;\n + uniform sampler2D sTexture;\n + \n + void main()\n + {\n + mediump vec2 texCoord;\n + texCoord.y = vTexCoord.y;\n + texCoord.x = fract( vTexCoord.x ) / vRatio;\n + if ( texCoord.x > 1.0 )\n + discard;\n + \n + gl_FragColor = texture2D( sTexture, texCoord );\n + }\n +); + +/** + * @brief Create and set up a camera for the render task to use + * + * @param[in] sizeOfTarget size of the source camera to look at + * @param[out] offscreenCamera custom camera + */ +void CreateCameraActor( const Size& sizeOfTarget, CameraActor& offscreenCamera ) +{ + offscreenCamera = CameraActor::New(); + offscreenCamera.SetOrthographicProjection( sizeOfTarget ); + offscreenCamera.SetInvertYAxis( true ); +} + +/** + * @brief Create a render task + * + * @param[in] sourceActor actor to be used as source + * @param[in] cameraActor camera looking at source + * @param[in] offscreenTarget resulting image from render task + * @param[out] renderTask render task that has been setup + */ +void CreateRenderTask( Actor sourceActor, CameraActor cameraActor , FrameBufferImage offscreenTarget, RenderTask& renderTask ) +{ + Stage stage = Stage::GetCurrent(); + RenderTaskList taskList = stage.GetRenderTaskList(); + renderTask = taskList.CreateTask(); + renderTask.SetSourceActor( sourceActor ); + renderTask.SetExclusive( true ); + renderTask.SetInputEnabled( false ); + renderTask.SetClearEnabled( true ); + renderTask.SetCameraActor( cameraActor ); + renderTask.SetTargetFrameBuffer( offscreenTarget ); + renderTask.SetClearColor( Color::TRANSPARENT ); + renderTask.SetCullMode( false ); +} + +/** + * @brief Create quad geometry for the mesh + * + * @param[out] geometry quad geometry that can be used for a mesh + */ +void CreateGeometry( Geometry& geometry ) +{ + struct QuadVertex { Vector2 position; }; + + QuadVertex quadVertexData[4] = + { + { Vector2( 0.0f, 0.0f) }, + { Vector2( 1.0f, 0.0f) }, + { Vector2( 0.0f, 1.0f) }, + { Vector2( 1.0f, 1.0f) }, + }; + + const unsigned short indices[6] = + { + 3,1,0,0,2,3 + }; + + Property::Map quadVertexFormat; + quadVertexFormat["aPosition"] = Property::VECTOR2; + PropertyBuffer quadVertices = PropertyBuffer::New( quadVertexFormat ); + quadVertices.SetData(quadVertexData, 4 ); + + geometry = Geometry::New(); + geometry.AddVertexBuffer( quadVertices ); + geometry.SetIndexBuffer( indices, sizeof(indices)/sizeof(indices[0]) ); +} + + +/** + * @brief Create a renderer + * + * @param[in] frameBufferImage texture to be used + * @param[out] renderer mesh renderer using the supplied texture + */ +void CreateRenderer( FrameBufferImage frameBufferImage, Dali::Renderer& renderer ) +{ + Shader shader = Shader::New( VERTEX_SHADER_SCROLL , FRAGMENT_SHADER, Shader::HINT_NONE ); + + Sampler sampler = Sampler::New(); + sampler.SetFilterMode(FilterMode::NEAREST, FilterMode::NEAREST ); + + TextureSet textureSet = TextureSet::New(); + textureSet.SetImage( 0u, frameBufferImage ); + textureSet.SetSampler( 0u, sampler ); + + Geometry meshGeometry; + CreateGeometry( meshGeometry ); + + renderer = Renderer::New( meshGeometry, shader ); + renderer.SetTextures( textureSet ); +} + +} // namespace + +namespace Text +{ + +TextScrollerPtr TextScroller::New( ScrollerInterface& scrollerInterface ) +{ + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::New\n" ); + + TextScrollerPtr textScroller( new TextScroller( scrollerInterface) ); + return textScroller; +} + +void TextScroller::SetGap( float gap ) +{ + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetGap gap[%f]\n", gap ); + mWrapGap = gap; +} + +float TextScroller::GetGap() const +{ + return mWrapGap; +} + +void TextScroller::SetSpeed( int scrollSpeed ) +{ + mScrollSpeed = std::max( MINIMUM_SCROLL_SPEED, scrollSpeed ); +} + +int TextScroller::GetSpeed() const +{ + return mScrollSpeed; +} + +void TextScroller::SetLoopCount( int loopCount ) +{ + if ( loopCount > 0 ) + { + mLoopCount = loopCount; + } + + if ( mScrollAnimation && mScrollAnimation.GetState() == Animation::PLAYING ) + { + if ( loopCount == 0 ) // Request to stop looping + { + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetLoopCount Single loop forced\n" ); + mScrollAnimation.SetLoopCount( 1 ); // As animation already playing this allows the current animation to finish instead of trying to stop mid-way + } + } + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetLoopCount [%d] Status[%s]\n", mLoopCount, (loopCount)?"looping":"stop" ); +} + +int TextScroller::GetLoopCount() const +{ + return mLoopCount; +} + +Actor TextScroller::GetSourceCamera() const +{ + return mOffscreenCameraActor; +} + +Actor TextScroller::GetScrollingText() const +{ + return mScrollingTextActor; +} + +TextScroller::TextScroller( ScrollerInterface& scrollerInterface ) : mScrollerInterface( scrollerInterface ), + mScrollDeltaIndex( Property::INVALID_INDEX ), + mScrollSpeed( MINIMUM_SCROLL_SPEED ), + mLoopCount( 1 ), + mWrapGap( 0.0f ) +{ + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller Default Constructor\n" ); +} + +TextScroller::~TextScroller() +{ + CleanUp(); +} + +void TextScroller::SetParameters( Actor sourceActor, const Size& controlSize, const Size& offScreenSize, CharacterDirection direction, const Vector2 alignmentOffset ) +{ + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters controlSize[%f,%f] offscreenSize[%f,%f] direction[%d] alignmentOffset[%f,%f]\n", + controlSize.x, controlSize.y, offScreenSize.x, offScreenSize.y, direction, alignmentOffset.x, alignmentOffset.y ); + + FrameBufferImage offscreenRenderTargetForText = FrameBufferImage::New( offScreenSize.width, offScreenSize.height, Pixel::RGBA8888, Dali::Image::UNUSED ); + Renderer renderer; + + CreateCameraActor( offScreenSize, mOffscreenCameraActor ); + CreateRenderer( offscreenRenderTargetForText, renderer ); + CreateRenderTask( sourceActor, mOffscreenCameraActor, offscreenRenderTargetForText, mRenderTask ); + + // Reposition camera to match alignment of target, RTL text has direction=true + if ( direction ) + { + mOffscreenCameraActor.SetX( alignmentOffset.x + offScreenSize.width*0.5f ); + } + else + { + mOffscreenCameraActor.SetX( offScreenSize.width * 0.5f ); + } + + mOffscreenCameraActor.SetY( offScreenSize.height * 0.5f ); + + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters mWrapGap[%f]\n", mWrapGap ) + + mScrollingTextActor = Actor::New(); + mScrollingTextActor.AddRenderer( renderer ); + mScrollingTextActor.RegisterProperty( "uTextureSize", offScreenSize ); + mScrollingTextActor.RegisterProperty( "uRtl", ((direction)?1.0f:0.0f) ); + mScrollingTextActor.RegisterProperty( "uGap", mWrapGap ); + mScrollingTextActor.SetSize( controlSize.width, std::min( offScreenSize.height, controlSize.height ) ); + mScrollDeltaIndex = mScrollingTextActor.RegisterProperty( "uDelta", 0.0f ); + + float scrollAmount = std::max( offScreenSize.width + mWrapGap, controlSize.width ); + float scrollDuration = scrollAmount / mScrollSpeed; + + if ( direction ) + { + scrollAmount = -scrollAmount; // reverse direction of scrollung + } + + StartScrolling( scrollAmount, scrollDuration, mLoopCount ); +} + +void TextScroller::AutoScrollAnimationFinished( Dali::Animation& animation ) +{ + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::AutoScrollAnimationFinished\n" ); + CleanUp(); + mScrollerInterface.ScrollingFinished(); +} + +void TextScroller::StartScrolling( float scrollAmount, float scrollDuration, int loopCount ) +{ + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::StartScrolling scrollAmount[%f] scrollDuration[%f], loop[%d] speed[%d]\n", scrollAmount, scrollDuration, loopCount, mScrollSpeed ); + + mScrollAnimation = Animation::New( scrollDuration ); + mScrollAnimation.AnimateTo( Property( mScrollingTextActor, mScrollDeltaIndex ), scrollAmount ); + mScrollAnimation.SetEndAction( Animation::Discard ); + mScrollAnimation.SetLoopCount( loopCount ); + mScrollAnimation.FinishedSignal().Connect( this, &TextScroller::AutoScrollAnimationFinished ); + mScrollAnimation.Play(); +} + +void TextScroller::CleanUp() +{ + if ( Stage::IsInstalled() ) + { + Stage stage = Stage::GetCurrent(); + RenderTaskList taskList = stage.GetRenderTaskList(); + UnparentAndReset( mScrollingTextActor ); + UnparentAndReset( mOffscreenCameraActor ); + taskList.RemoveTask( mRenderTask ); + } +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/text-scroller.h b/dali-toolkit/internal/text/text-scroller.h new file mode 100644 index 0000000..aefecdf --- /dev/null +++ b/dali-toolkit/internal/text/text-scroller.h @@ -0,0 +1,177 @@ +#ifndef __DALI_TOOLKIT_TEXT_SCROLLER_H__ +#define __DALI_TOOLKIT_TEXT_SCROLLER_H__ + +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +class TextScroller; +class ScrollerInterface; + +typedef IntrusivePtr TextScrollerPtr; + +/** + * @brief A helper class for scrolling text + */ +class TextScroller : public RefObject, public ConnectionTracker +{ +public: + + /** + * @brief Text Scrolling helper, used to automatically scroll text, SetParameters should be called before scrolling is needed. + * CleanUp removes the Scrolling actors from stage whilst keeping the Scroller object alive and preserving Speed, Gap and Loop count. + * + * @param[in] scrollerInterface scroller interface + */ + static TextScrollerPtr New( ScrollerInterface& scrollerInterface ); + + /** + * @brief Set parameters relating to source required for scrolling + * + * @param[in] sourceActor source actor to be scrolled + * @param[in] controlSize size of the control to scroll within + * @param[in] offScreenSize size of the sourceActor + * @param[in] direction text direction true for right to left text + * @param[in] alignmentOffset alignment of source text + * + */ + void SetParameters( Actor sourceActor, const Size& controlSize, const Size& offScreenSize, CharacterDirection direction, const Vector2 alignmentOffset ); + + /** + * @brief Set the gap distance to elapse before the text wraps around + * @param[in] gap distance to elapse + */ + void SetGap( float gap ); + + /** + * @brief Get the distance before scrolling waps + * @return gap distance to elapse + */ + float GetGap() const; + + /** + * @brief Set speed the text should scroll + * @param[in] scrollSpeed pixels per second + */ + void SetSpeed( int scrollSpeed ); + + /** + * @brief Get the speed of text scrolling + * @return speed in pixels per second + */ + int GetSpeed() const; + + /** + * @brief Set the number of times the text scrolling should loop, can stop current scrolling by passing in 0; + * @param[in] loopCount number of times the scrolled text should loop, 0 to stop scrolling + */ + void SetLoopCount( int loopCount ); + + /** + * @brief Get the number of loops + * @return int number of loops + */ + int GetLoopCount() const; + + /** + * @brief Get the camera used to look at source, should be added to the parent of target actor. + * @return camera Actor + */ + Actor GetSourceCamera() const; + + /** + * @brief Get the resulting scrolling text actor, add to target actor which will show scrolling text + * @return mesh Actor + */ + Actor GetScrollingText() const; + +private: // Implementation + + /** + * Constructor + */ + TextScroller( ScrollerInterface& scrollerInterface ); + + /** + * Destructor + */ + ~TextScroller(); + + // Undefined + TextScroller( const TextScroller& handle ); + + // Undefined + TextScroller& operator=( const TextScroller& handle ); + + /** + * @brief Callback for end of animation + * @param[in] animation Animation handle + */ + void AutoScrollAnimationFinished( Dali::Animation& animation ); + + /** + * @brief variables required to set up scrolling animation + * @param[in] scrollAmount distance to animate text for the given duration + * @param[in] scrollDuration duration of aninmation + * @param[in] loopCount number of times to loop the scrolling text + */ + void StartScrolling( float scrollAmount, float scrollDuration, int loopCount ); + + /** + * @brief When scrolling ended, the actors are cleaned up so no longer staged. + */ + void CleanUp(); + +private: + + RenderTask mRenderTask; // Renders full text to a FrameBuffer which is then scrolled. + CameraActor mOffscreenCameraActor; // Camera used by render task + Actor mScrollingTextActor; // Actor used to show scrolling text + ScrollerInterface& mScrollerInterface; // Interface implemented by control that requires scrolling + Property::Index mScrollDeltaIndex; // Property used by shader to represent distance to scroll + Animation mScrollAnimation; // Animation used to update the mScrollDeltaIndex + + int mScrollSpeed; ///< Speed which text should automatically scroll at + int mLoopCount; ///< Number of time the text should scroll + float mWrapGap; ///< Gap before text wraps around when scrolling + +}; // TextScroller class + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_SCROLLER_H__ + diff --git a/dali-toolkit/internal/text/text-view-interface.h b/dali-toolkit/internal/text/text-view-interface.h index f5f1c49..eaa191d 100644 --- a/dali-toolkit/internal/text/text-view-interface.h +++ b/dali-toolkit/internal/text/text-view-interface.h @@ -36,7 +36,7 @@ namespace Text struct GlyphRun; /** - * @brief Abstract interface to provide the information necessary displaying text. + * @brief Abstract interface to provide the information necessary to display text. * * This includes: * - The font & glyph IDs needed to get bitmaps etc. from TextAbstraction @@ -60,7 +60,7 @@ public: /** * @brief Retrieves the target size of the UI control. * - * @return The text's size. + * @return The control's size. */ virtual const Vector2& GetControlSize() const = 0; diff --git a/dali-toolkit/internal/text/visual-model-impl.h b/dali-toolkit/internal/text/visual-model-impl.h index 88e3930..7c1accb 100644 --- a/dali-toolkit/internal/text/visual-model-impl.h +++ b/dali-toolkit/internal/text/visual-model-impl.h @@ -332,7 +332,6 @@ public: bool mUnderlineEnabled:1; ///< Underline enabled flag bool mUnderlineColorSet:1; ///< Has the underline color been explicitly set? - }; } // namespace Text diff --git a/dali-toolkit/public-api/controls/text-controls/text-label.h b/dali-toolkit/public-api/controls/text-controls/text-label.h index 317918e..7153d3a 100644 --- a/dali-toolkit/public-api/controls/text-controls/text-label.h +++ b/dali-toolkit/public-api/controls/text-controls/text-label.h @@ -78,7 +78,11 @@ public: UNDERLINE_ENABLED, ///< name "underlineEnabled", The underline enabled flag, type BOOLEAN @SINCE_1_0.0 UNDERLINE_COLOR, ///< name "underlineColor", The color of the underline, type VECTOR4 @SINCE_1_0.0 UNDERLINE_HEIGHT, ///< name "underlineHeight", Overrides the underline height from font metrics, type FLOAT @SINCE_1_0.0 - ENABLE_MARKUP ///< name "enableMarkup", Whether the mark-up processing is enabled. type BOOLEAN @SINCE_1_0.0 + ENABLE_MARKUP, ///< name "enableMarkup", Whether the mark-up processing is enabled. type BOOLEAN @SINCE_1_0.0 + ENABLE_AUTO_SCROLL, ///< name "enableAutoScroll", Whether to start auto text scrolling type BOOLEAN @SINCE_1_1.35 + AUTO_SCROLL_SPEED, ///< name "autoScrollSpeed", Speed at which text should auto scroll type INT @SINCE_1_1.35 + AUTO_SCROLL_LOOP_COUNT, ///< name "autoScrollLoopCount", Number of times the text should scroll (loop) type INT @SINCE_1_1.35 + AUTO_SCROLL_GAP ///< name "autoScrollGap", Gap before text wraps around when scrolling type FLOAT @SINCE_1_1.35 }; }; diff --git a/dali-toolkit/styles/480x800/dali-toolkit-default-theme.json b/dali-toolkit/styles/480x800/dali-toolkit-default-theme.json index 4ecc335..725a71a 100644 --- a/dali-toolkit/styles/480x800/dali-toolkit-default-theme.json +++ b/dali-toolkit/styles/480x800/dali-toolkit-default-theme.json @@ -30,7 +30,11 @@ { "textlabel": { - "pointSize":18 + "pointSize":18, + "enableAutoScroll":false, + "autoScrollLoopCount":2, + "autoScrollGap":50, + "autoScrollSpeed":80 }, "textlabelFontSize0": diff --git a/dali-toolkit/styles/720x1280/dali-toolkit-default-theme.json b/dali-toolkit/styles/720x1280/dali-toolkit-default-theme.json index ffe9326..3297e51 100644 --- a/dali-toolkit/styles/720x1280/dali-toolkit-default-theme.json +++ b/dali-toolkit/styles/720x1280/dali-toolkit-default-theme.json @@ -30,7 +30,11 @@ { "textlabel": { - "pointSize":18 + "pointSize":18, + "enableAutoScroll":false, + "autoScrollLoopCount":2, + "autoScrollGap":50, + "autoScrollSpeed":80 }, "textlabelFontSize0":