Implement scroll bar in the TextEditor 92/112892/16
authorsuhyung Eom <suhyung.eom@samsung.com>
Fri, 3 Feb 2017 07:07:01 +0000 (16:07 +0900)
committerAgnelo Vaz <agnelo.vaz@samsung.com>
Wed, 15 Mar 2017 14:29:51 +0000 (14:29 +0000)
Signed-off-by: suhyung Eom <suhyung.eom@samsung.com>
Change-Id: Id7a227f8fcbf5b2298b68c702c5f3c326dfe5754

automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp
dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h
dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp
dali-toolkit/internal/controls/text-controls/text-editor-impl.h
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/styles/1920x1080/dali-toolkit-default-theme.json
dali-toolkit/styles/480x800/dali-toolkit-default-theme.json
dali-toolkit/styles/720x1280/dali-toolkit-default-theme.json

index 4635def..e410fb1 100644 (file)
@@ -87,6 +87,9 @@ const char* const PROPERTY_NAME_INPUT_OUTLINE                        = "inputOut
 
 const char* const PROPERTY_NAME_SMOOTH_SCROLL                        = "smoothScroll";
 const char* const PROPERTY_NAME_SMOOTH_SCROLL_DURATION               = "smoothScrollDuration";
+const char* const PROPERTY_NAME_ENABLE_SCROLL_BAR                    = "enableScrollBar";
+const char* const PROPERTY_NAME_SCROLL_BAR_SHOW_DURATION             = "scrollBarShowDuration";
+const char* const PROPERTY_NAME_SCROLL_BAR_FADE_DURATION             = "scrollBarFadeDuration";
 
 const int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
 
@@ -330,6 +333,9 @@ int UtcDaliTextEditorGetPropertyP(void)
   DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_INPUT_OUTLINE ) == TextEditor::Property::INPUT_OUTLINE );
   DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_SMOOTH_SCROLL ) == DevelTextEditor::Property::SMOOTH_SCROLL );
   DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_SMOOTH_SCROLL_DURATION ) == DevelTextEditor::Property::SMOOTH_SCROLL_DURATION );
+  DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_ENABLE_SCROLL_BAR ) == DevelTextEditor::Property::ENABLE_SCROLL_BAR );
+  DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_SCROLL_BAR_SHOW_DURATION ) == DevelTextEditor::Property::SCROLL_BAR_SHOW_DURATION );
+  DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_SCROLL_BAR_FADE_DURATION ) == DevelTextEditor::Property::SCROLL_BAR_FADE_DURATION );
 
   END_TEST;
 }
@@ -608,6 +614,16 @@ int UtcDaliTextEditorSetPropertyP(void)
   editor.SetProperty( DevelTextEditor::Property::SMOOTH_SCROLL_DURATION, 0.2f );
   DALI_TEST_EQUALS( editor.GetProperty<float>( DevelTextEditor::Property::SMOOTH_SCROLL_DURATION ), 0.2f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
 
+  // Check the scroll bar property
+  DALI_TEST_EQUALS( editor.GetProperty<bool>( DevelTextEditor::Property::ENABLE_SCROLL_BAR ), false, TEST_LOCATION );
+  editor.SetProperty( DevelTextEditor::Property::ENABLE_SCROLL_BAR, true );
+  DALI_TEST_EQUALS( editor.GetProperty<bool>( DevelTextEditor::Property::ENABLE_SCROLL_BAR ), true, TEST_LOCATION );
+
+  editor.SetProperty( DevelTextEditor::Property::SCROLL_BAR_SHOW_DURATION, 0.3f );
+  DALI_TEST_EQUALS( editor.GetProperty<float>( DevelTextEditor::Property::SCROLL_BAR_SHOW_DURATION ), 0.3f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+  editor.SetProperty( DevelTextEditor::Property::SCROLL_BAR_FADE_DURATION, 0.2f );
+  DALI_TEST_EQUALS( editor.GetProperty<float>( DevelTextEditor::Property::SCROLL_BAR_FADE_DURATION ), 0.2f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
   END_TEST;
 }
 
@@ -1555,6 +1571,9 @@ int utcDaliTextEditorEvent05(void)
   editor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
   editor.SetProperty( DevelTextEditor::Property::SMOOTH_SCROLL, true );
   editor.SetProperty( DevelTextEditor::Property::SMOOTH_SCROLL_DURATION, 0.2f );
+  editor.SetProperty( DevelTextEditor::Property::ENABLE_SCROLL_BAR, true );
+  editor.SetProperty( DevelTextEditor::Property::SCROLL_BAR_SHOW_DURATION, 0.3f );
+  editor.SetProperty( DevelTextEditor::Property::SCROLL_BAR_FADE_DURATION, 0.2f );
 
   // Avoid a crash when core load gl resources.
   application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
@@ -1602,6 +1621,9 @@ int utcDaliTextEditorEvent05(void)
   }
   DALI_TEST_EQUALS( editor.GetProperty<float>( DevelTextEditor::Property::SMOOTH_SCROLL_DURATION ), 0.1f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_EQUALS( editor.GetProperty<bool>( DevelTextEditor::Property::SMOOTH_SCROLL ), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( editor.GetProperty<bool>( DevelTextEditor::Property::ENABLE_SCROLL_BAR ), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( editor.GetProperty<float>( DevelTextEditor::Property::SCROLL_BAR_SHOW_DURATION ), 0.3f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+  DALI_TEST_EQUALS( editor.GetProperty<float>( DevelTextEditor::Property::SCROLL_BAR_FADE_DURATION ), 0.2f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
 
   // Press Escape to increase coverage
   application.ProcessEvent( GenerateKey( "", "", DALI_KEY_ESCAPE, 0, 0, Integration::KeyEvent::Up ) );
index d842559..fa90103 100644 (file)
@@ -85,7 +85,25 @@ namespace Property
        * @brief name "smoothScrollDuration", type float
        * @details Sets the duration of smooth scroll animation
        */
-      SMOOTH_SCROLL_DURATION
+      SMOOTH_SCROLL_DURATION,
+
+      /**
+       * @brief name "enableScrollBar", type bool
+       * @details Enable or disable the scroll bar
+       */
+      ENABLE_SCROLL_BAR,
+
+      /**
+       * @brief name "scrollBarShowDuration", type float
+       * @details Sets the duration of scroll bar to show
+       */
+      SCROLL_BAR_SHOW_DURATION,
+
+      /**
+       * @brief name "scrollBarFadeDuration", type float
+       * @details Sets the duration of scroll bar to fade out
+       */
+      SCROLL_BAR_FADE_DURATION
   };
 } // namespace Property
 
@@ -95,4 +113,4 @@ namespace Property
 
 } // namespace Dali
 
-#endif // DALI_TOOLKIT_TEXT_EDITOR_DEVEL_H
\ No newline at end of file
+#endif // DALI_TOOLKIT_TEXT_EDITOR_DEVEL_H
index a5aa7ff..5e2de42 100644 (file)
@@ -74,6 +74,11 @@ const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
 };
 const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] );
 
+const char* const SCROLL_BAR_POSITION("sourcePosition");
+const char* const SCROLL_BAR_POSITION_MIN("sourcePositionMin");
+const char* const SCROLL_BAR_POSITION_MAX("sourcePositionMax");
+const char* const SCROLL_BAR_CONTENT_SIZE("sourceContentSize");
+
 // Type registration
 BaseHandle Create()
 {
@@ -125,6 +130,9 @@ DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "outline",
 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputOutline",                         MAP,       INPUT_OUTLINE                        )
 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "smoothScroll",                   BOOLEAN,   SMOOTH_SCROLL                        )
 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "smoothScrollDuration",           FLOAT,     SMOOTH_SCROLL_DURATION               )
+DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "enableScrollBar",                BOOLEAN,   ENABLE_SCROLL_BAR                    )
+DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "scrollBarShowDuration",          FLOAT,     SCROLL_BAR_SHOW_DURATION             )
+DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "scrollBarFadeDuration",          FLOAT,     SCROLL_BAR_FADE_DURATION             )
 
 DALI_SIGNAL_REGISTRATION( Toolkit, TextEditor, "textChanged",        SIGNAL_TEXT_CHANGED )
 DALI_SIGNAL_REGISTRATION( Toolkit, TextEditor, "inputStyleChanged",  SIGNAL_INPUT_STYLE_CHANGED )
@@ -613,6 +621,30 @@ void TextEditor::SetProperty( BaseObject* object, Property::Index index, const P
         }
         break;
       }
+      case Toolkit::DevelTextEditor::Property::ENABLE_SCROLL_BAR:
+      {
+        const bool enable = value.Get< bool >();
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor SHOW_SCROLL_BAR %d\n", enable );
+
+        impl.mScrollBarEnabled = enable;
+        break;
+      }
+      case Toolkit::DevelTextEditor::Property::SCROLL_BAR_SHOW_DURATION:
+      {
+        const float duration = value.Get< float >();
+        DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor SCROLL_BAR_SHOW_DURATION %f\n", duration );
+
+        impl.mAnimationPeriod.delaySeconds = duration;
+        break;
+      }
+      case Toolkit::DevelTextEditor::Property::SCROLL_BAR_FADE_DURATION:
+      {
+        const float duration = value.Get< float >();
+        DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor SCROLL_BAR_FADE_DURATION %f\n", duration );
+
+        impl.mAnimationPeriod.durationSeconds = duration;
+        break;
+      }
     } // switch
   } // texteditor
 }
@@ -924,6 +956,21 @@ Property::Value TextEditor::GetProperty( BaseObject* object, Property::Index ind
         value = impl.mScrollAnimationDuration;
         break;
       }
+      case Toolkit::DevelTextEditor::Property::ENABLE_SCROLL_BAR:
+      {
+        value = impl.mScrollBarEnabled;
+        break;
+      }
+      case Toolkit::DevelTextEditor::Property::SCROLL_BAR_SHOW_DURATION:
+      {
+        value = impl.mAnimationPeriod.delaySeconds;
+        break;
+      }
+      case Toolkit::DevelTextEditor::Property::SCROLL_BAR_FADE_DURATION:
+      {
+        value = impl.mAnimationPeriod.durationSeconds;
+        break;
+      }
     } //switch
   }
 
@@ -1157,6 +1204,7 @@ void TextEditor::RenderText( Text::Controller::UpdateTextType updateTextType )
 
     ApplyScrollPosition();
   }
+  UpdateScrollBar();
 }
 
 void TextEditor::OnKeyInputFocusGained()
@@ -1340,6 +1388,73 @@ void TextEditor::AddDecoration( Actor& actor, bool needsClipping )
   }
 }
 
+void TextEditor::UpdateScrollBar()
+{
+  using namespace Dali;
+
+  float scrollPosition;
+  float controlSize;
+  float layoutSize;
+  bool latestScrolled;
+
+  if ( !mScrollBarEnabled )
+  {
+    return;
+  }
+  latestScrolled = mController->GetTextScrollInfo( scrollPosition, controlSize, layoutSize );
+  if ( !latestScrolled || controlSize > layoutSize)
+  {
+    return;
+  }
+
+  CustomActor self = Self();
+  if( !mScrollBar )
+  {
+    mScrollBar = Toolkit::ScrollBar::New( Toolkit::ScrollBar::Vertical );
+    mScrollBar.SetIndicatorHeightPolicy( Toolkit::ScrollBar::Variable );
+    mScrollBar.SetParentOrigin( ParentOrigin::TOP_RIGHT );
+    mScrollBar.SetAnchorPoint( AnchorPoint::TOP_RIGHT );
+    mScrollBar.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
+    mScrollBar.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::WIDTH );
+
+    // Register the scroll position property
+    Property::Index propertyScrollPosition = self.RegisterProperty( SCROLL_BAR_POSITION, scrollPosition );
+    // Register the minimum scroll position property
+    Property::Index propertyMinScrollPosition = self.RegisterProperty( SCROLL_BAR_POSITION_MIN, 0.0f );
+    // Register the maximum scroll position property
+    Property::Index propertyMaxScrollPosition = self.RegisterProperty( SCROLL_BAR_POSITION_MAX, (layoutSize - controlSize) );
+    // Register the scroll content size property
+    Property::Index propertyScrollContentSize = self.RegisterProperty( SCROLL_BAR_CONTENT_SIZE, layoutSize );
+
+    mScrollBar.SetScrollPropertySource(self, propertyScrollPosition, propertyMinScrollPosition, propertyMaxScrollPosition, propertyScrollContentSize);
+
+    self.Add( mScrollBar );
+  }
+  else
+  {
+    Property::Index propertyScrollPosition = self.GetPropertyIndex( SCROLL_BAR_POSITION );
+    Property::Index propertyMaxScrollPosition = self.GetPropertyIndex( SCROLL_BAR_POSITION_MAX );
+    Property::Index propertyScrollContentSize = self.GetPropertyIndex( SCROLL_BAR_CONTENT_SIZE );
+
+    self.SetProperty( propertyScrollPosition, scrollPosition );
+    self.SetProperty( propertyMaxScrollPosition, (layoutSize - controlSize) );
+    self.SetProperty( propertyScrollContentSize, layoutSize );
+  }
+
+  Actor indicator = mScrollBar.GetScrollIndicator();
+  if( mAnimation )
+  {
+    mAnimation.Stop(); // Cancel any animation
+  }
+  else
+  {
+    mAnimation = Animation::New( mAnimationPeriod.durationSeconds );
+  }
+  indicator.SetOpacity(1.0f);
+  mAnimation.AnimateTo( Property( indicator, Actor::Property::COLOR_ALPHA ), 0.0f, AlphaFunction::EASE_IN, mAnimationPeriod );
+  mAnimation.Play();
+}
+
 void TextEditor::OnStageConnect( Dali::Actor actor )
 {
   if ( mHasBeenStaged )
@@ -1448,12 +1563,14 @@ void TextEditor::ApplyScrollPosition()
 
 TextEditor::TextEditor()
 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
+  mAnimationPeriod( 0.0f, 0.0f ),
   mIdleCallback( NULL ),
   mAlignmentOffset( 0.f ),
   mScrollAnimationDuration( 0.f ),
   mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
   mHasBeenStaged( false ),
-  mScrollAnimationEnabled( false )
+  mScrollAnimationEnabled( false ),
+  mScrollBarEnabled( false )
 {
 }
 
index 40f5e03..cc864f1 100644 (file)
 
 // EXTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/clipboard-event-notifier.h>
+#include <dali/public-api/animation/animation.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/public-api/controls/scroll-bar/scroll-bar.h>
 #include <dali-toolkit/public-api/controls/text-controls/text-editor.h>
 #include <dali-toolkit/internal/text/decorator/text-decorator.h>
 #include <dali-toolkit/internal/text/text-control-interface.h>
@@ -213,6 +215,13 @@ private: // Implementation
   void KeyboardStatusChanged( bool keyboardShown );
 
   /**
+   * @brief update scroll bar position
+   *
+   * If text scroll is occurred, create or update scroll bar position
+   */
+  void UpdateScrollBar();
+
+  /**
    * @brief Callback when TextEditor is touched
    *
    * @param[in] actor TextEditor touched
@@ -257,7 +266,6 @@ private: // Implementation
   void OnStageConnect( Dali::Actor actor );
 
 private: // Data
-
   // Signals
   Toolkit::TextEditor::TextChangedSignalType mTextChangedSignal;
   Toolkit::TextEditor::InputStyleChangedSignalType mInputStyleChangedSignal;
@@ -268,6 +276,9 @@ private: // Data
   Text::DecoratorPtr mDecorator;
   Text::TextVerticalScrollerPtr mTextVerticalScroller;
   Toolkit::Control mStencil;
+  Toolkit::ScrollBar mScrollBar;
+  Dali::Animation mAnimation;                                              ///< Scroll indicator Show/Hide Animation.
+  Dali::TimePeriod mAnimationPeriod;
   std::vector<Actor> mClippingDecorationActors;   ///< Decoration actors which need clipping.
 
   Actor mRenderableActor;
@@ -278,6 +289,7 @@ private: // Data
   int mRenderingBackend;
   bool mHasBeenStaged:1;
   bool mScrollAnimationEnabled:1;
+  bool mScrollBarEnabled:1;
 };
 
 } // namespace Internal
index ca201d3..047eb4b 100644 (file)
@@ -1498,6 +1498,18 @@ float Controller::GetScrollAmountByUserInput()
   return scrollAmount;
 }
 
+bool Controller::GetTextScrollInfo( float& scrollPosition, float& controlHeight, float& layoutHeight )
+{
+  const Vector2& layout = mImpl->mModel->mVisualModel->GetLayoutSize();
+  bool isScrolled;
+
+  controlHeight = mImpl->mModel->mVisualModel->mControlSize.height;
+  layoutHeight = layout.height;
+  scrollPosition = mImpl->mModel->mScrollPosition.y;
+  isScrolled = !Equals( mImpl->mModel->mScrollPosition.y, mImpl->mModel->mScrollPositionLast.y, Math::MACHINE_EPSILON_1 );
+  return isScrolled;
+}
+
 // public : Relayout.
 
 Controller::UpdateTextType Controller::Relayout( const Size& size )
index 4bb6f7c..9612b1a 100644 (file)
@@ -837,6 +837,18 @@ public: // Queries & retrieves.
    */
   float GetScrollAmountByUserInput();
 
+  /**
+   * @brief Get latest scroll amount, control size and layout size
+   *
+   * This method is used to get information of control's scroll
+   * @param[out] scrollPosition The current scrolled position
+   * @param[out] controlHeight The size of a UI control
+   * @param[out] layoutHeight The size of a bounding box to layout text within.
+   *
+   * @return Whether the text scroll position is changed or not after last update.
+   */
+  bool GetTextScrollInfo( float& scrollPosition, float& controlHeight, float& layoutHeight );
+
 public: // Relayout.
 
   /**
index bd48ca7..8179db5 100644 (file)
       "selectionHighlightColor":[0.75,0.96,1.0,1.0],
       "grabHandleImage" : "{DALI_STYLE_IMAGE_DIR}cursor_handler_drop_center.png",
       "selectionHandleImageLeft" : {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_left.png" },
-      "selectionHandleImageRight": {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_right.png" }
+      "selectionHandleImageRight": {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_right.png" },
+      "enableScrollBar":true,
+      "scrollBarShowDuration":0.8,
+      "scrollBarFadeDuration":0.5
     },
     "ProgressBar":
     {
index 43b99ea..95d2d01 100644 (file)
       "selectionHighlightColor":[0.75,0.96,1.0,1.0],
       "grabHandleImage" : "{DALI_STYLE_IMAGE_DIR}cursor_handler_drop_center.png",
       "selectionHandleImageLeft" : {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_left.png" },
-      "selectionHandleImageRight": {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_right.png" }
+      "selectionHandleImageRight": {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_right.png" },
+      "enableScrollBar":true,
+      "scrollBarShowDuration":0.8,
+      "scrollBarFadeDuration":0.5
     },
     "Popup":
     {
index aa735b3..fdd8182 100644 (file)
       "selectionHighlightColor":[0.75,0.96,1.0,1.0],
       "grabHandleImage" : "{DALI_STYLE_IMAGE_DIR}cursor_handler_drop_center.png",
       "selectionHandleImageLeft" : {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_left.png" },
-      "selectionHandleImageRight": {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_right.png" }
+      "selectionHandleImageRight": {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_right.png" },
+      "enableScrollBar":true,
+      "scrollBarShowDuration":0.8,
+      "scrollBarFadeDuration":0.5
     },
     "Popup":
     {