Auto Scrolling Text Label 96/57796/43
authorAgnelo Vaz <agnelo.vaz@samsung.com>
Thu, 14 Jan 2016 15:44:21 +0000 (15:44 +0000)
committerAgnelo Vaz <agnelo.vaz@samsung.com>
Fri, 13 May 2016 10:55:55 +0000 (11:55 +0100)
Single line horizontal scrolling

Direction of scrolling dependent on direction of text, LTR or RTL

Speed of scrolling, gap before wrapping and number of loops can be set by Property system.

Change-Id: I6abba8c0d3f3838bdd143b315687b13cb680e2f7
Signed-off-by: Agnelo Vaz <agnelo.vaz@samsung.com>
18 files changed:
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.h
dali-toolkit/internal/file.list
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp
dali-toolkit/internal/text/text-controller-impl.h
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/text/text-scroller-interface.cpp [new file with mode: 0644]
dali-toolkit/internal/text/text-scroller-interface.h [new file with mode: 0644]
dali-toolkit/internal/text/text-scroller.cpp [new file with mode: 0644]
dali-toolkit/internal/text/text-scroller.h [new file with mode: 0644]
dali-toolkit/internal/text/text-view-interface.h
dali-toolkit/internal/text/visual-model-impl.h
dali-toolkit/public-api/controls/text-controls/text-label.h
dali-toolkit/styles/480x800/dali-toolkit-default-theme.json
dali-toolkit/styles/720x1280/dali-toolkit-default-theme.json

index 9378648..08f085d 100644 (file)
@@ -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<bool>( 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<bool>( TextLabel::Property::ENABLE_AUTO_SCROLL ) );
+  label.SetProperty( TextLabel::Property::ENABLE_AUTO_SCROLL, true );
+  DALI_TEST_CHECK( label.GetProperty<bool>( TextLabel::Property::ENABLE_AUTO_SCROLL ) );
+  label.SetProperty( TextLabel::Property::AUTO_SCROLL_SPEED, SCROLL_SPEED );
+  DALI_TEST_EQUALS( SCROLL_SPEED, label.GetProperty<int>( TextLabel::Property::AUTO_SCROLL_SPEED ), TEST_LOCATION );
+  label.SetProperty( TextLabel::Property::AUTO_SCROLL_LOOP_COUNT, SCROLL_LOOPS );
+  DALI_TEST_EQUALS( SCROLL_LOOPS, label.GetProperty<int>( TextLabel::Property::AUTO_SCROLL_LOOP_COUNT ), TEST_LOCATION );
+  label.SetProperty( TextLabel::Property::AUTO_SCROLL_GAP, SCROLL_GAP );
+  DALI_TEST_EQUALS( SCROLL_GAP, label.GetProperty<float>( 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;
+}
index e7bac78..6d46758 100644 (file)
@@ -28,6 +28,7 @@
 #include <dali-toolkit/internal/text/rendering/text-backend.h>
 #include <dali-toolkit/internal/text/text-font-style.h>
 #include <dali-toolkit/internal/text/text-view.h>
+#include <dali-toolkit/internal/text/text-definitions.h>
 #include <dali-toolkit/internal/styling/style-manager-impl.h>
 
 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<bool>();
+          // 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<int>() );
+        break;
+      }
+      case Toolkit::TextLabel::Property::AUTO_SCROLL_LOOP_COUNT:
+      {
+        if( !impl.mTextScroller )
+        {
+          impl.mTextScroller = Text::TextScroller::New( impl );
+        }
+        impl.mTextScroller->SetLoopCount( value.Get<int>() );
+        break;
+      }
+      case Toolkit::TextLabel::Property::AUTO_SCROLL_GAP:
+      {
+        if( !impl.mTextScroller )
+        {
+          impl.mTextScroller = Text::TextScroller::New( impl );
+        }
+        impl.mTextScroller->SetGap( value.Get<float>() );
+        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 ),
index ae88beb..c2dd485 100644 (file)
@@ -22,7 +22,9 @@
 #include <dali-toolkit/public-api/controls/control-impl.h>
 #include <dali-toolkit/public-api/controls/text-controls/text-label.h>
 #include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/text-scroller-interface.h>
 #include <dali-toolkit/internal/text/rendering/text-renderer.h>
+#include <dali-toolkit/internal/text/text-scroller.h>
 
 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;
index cd24d24..d043b79 100644 (file)
@@ -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 \
index a5da5a4..ac9110e 100644 (file)
@@ -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;
 }
 
index 2db0faa..32ab39b 100644 (file)
@@ -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();
index ce8a291..5c1ed0c 100644 (file)
@@ -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
index 3a211e1..36c293e 100644 (file)
@@ -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<OperationsMask>( 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<OperationsMask>( 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;
 }
index 6a83374..5a96349 100644 (file)
@@ -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 (file)
index 0000000..ee85ef9
--- /dev/null
@@ -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 <dali-toolkit/internal/text/text-scroller-interface.h>
+
+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 (file)
index 0000000..31a0819
--- /dev/null
@@ -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 (file)
index 0000000..5b7b99b
--- /dev/null
@@ -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 <dali-toolkit/internal/text/text-scroller.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/rendering/geometry.h>
+#include <dali/devel-api/rendering/renderer.h>
+#include <dali/devel-api/rendering/sampler.h>
+#include <dali/devel-api/rendering/shader.h>
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/stage.h>
+#include <dali/public-api/images/frame-buffer-image.h>
+#include <dali/public-api/render-tasks/render-task-list.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/text-scroller-interface.h>
+
+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 (file)
index 0000000..aefecdf
--- /dev/null
@@ -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 <dali/public-api/actors/camera-actor.h>
+#include <dali/public-api/animation/animation.h>
+#include <dali/public-api/render-tasks/render-task.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/text-definitions.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+class TextScroller;
+class ScrollerInterface;
+
+typedef IntrusivePtr<TextScroller> 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__
+
index f5f1c49..eaa191d 100644 (file)
@@ -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;
 
index 88e3930..7c1accb 100644 (file)
@@ -332,7 +332,6 @@ public:
 
   bool                   mUnderlineEnabled:1;   ///< Underline enabled flag
   bool                   mUnderlineColorSet:1;  ///< Has the underline color been explicitly set?
-
 };
 
 } // namespace Text
index 317918e..7153d3a 100644 (file)
@@ -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
     };
   };
 
index 4ecc335..725a71a 100644 (file)
   {
     "textlabel":
     {
-      "pointSize":18
+      "pointSize":18,
+      "enableAutoScroll":false,
+      "autoScrollLoopCount":2,
+      "autoScrollGap":50,
+      "autoScrollSpeed":80
     },
 
     "textlabelFontSize0":
index ffe9326..3297e51 100644 (file)
   {
     "textlabel":
     {
-      "pointSize":18
+      "pointSize":18,
+      "enableAutoScroll":false,
+      "autoScrollLoopCount":2,
+      "autoScrollGap":50,
+      "autoScrollSpeed":80
     },
 
     "textlabelFontSize0":