Merge "[dali-toolkit]: add texteditor scrolling functionality" into devel/master
authorjoogab yun <joogab.yun@samsung.com>
Fri, 30 Oct 2020 07:36:19 +0000 (07:36 +0000)
committerGerrit Code Review <gerrit@review>
Fri, 30 Oct 2020 07:36:19 +0000 (07:36 +0000)
automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp
dali-toolkit/internal/text/text-controller-event-handler.cpp
dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp
dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.cpp
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h

index d511883..49e630d 100644 (file)
@@ -2172,6 +2172,54 @@ int utcDaliTextEditorEvent07(void)
   //text is "c"
   DALI_TEST_EQUALS( "c", editor.GetProperty<std::string>( TextEditor::Property::TEXT ), TEST_LOCATION );
 
+  // select all text
+  DevelTextEditor::SelectWholeText(editor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Copy the selected text using logical keys
+  application.ProcessEvent( GenerateKey( "", "", "", Dali::DevelKey::DALI_KEY_CONTROL_LEFT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+  application.ProcessEvent( GenerateKey( "ؤ", "c", "ؤ", KEY_C_CODE, KEY_CONTROL_MODIFIER, 0, Integration::KeyEvent::DOWN, "c", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // select none
+  DevelTextEditor::SelectNone(editor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Paste the selected using logical keys
+  application.ProcessEvent( GenerateKey( "", "", "", Dali::DevelKey::DALI_KEY_CONTROL_LEFT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+  application.ProcessEvent( GenerateKey( "ر", "v", "ر", KEY_V_CODE, KEY_CONTROL_MODIFIER, 0, Integration::KeyEvent::DOWN, "v", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+
+  //text is "cc"
+  DALI_TEST_EQUALS( "cc", editor.GetProperty<std::string>( TextEditor::Property::TEXT ), TEST_LOCATION );
+
+  // select all using logical keys
+  application.ProcessEvent( GenerateKey( "", "", "", Dali::DevelKey::DALI_KEY_CONTROL_LEFT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+  application.ProcessEvent( GenerateKey( "ش", "a", "ش", KEY_A_CODE, KEY_CONTROL_MODIFIER, 0, Integration::KeyEvent::DOWN, "a", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // cut text using logical keys
+  application.ProcessEvent( GenerateKey( "", "", "", Dali::DevelKey::DALI_KEY_CONTROL_LEFT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+  application.ProcessEvent( GenerateKey( "ء", "x", "ء", KEY_X_CODE, KEY_CONTROL_MODIFIER, 0, Integration::KeyEvent::DOWN, "x", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  //text is ""
+  DALI_TEST_EQUALS( "", editor.GetProperty<std::string>( TextEditor::Property::TEXT ), TEST_LOCATION );
+
   END_TEST;
 }
 
index b9b260b..89ff0f9 100644 (file)
@@ -109,6 +109,9 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE
     int keyCode = keyEvent.GetKeyCode();
     const std::string& keyString = keyEvent.GetKeyString();
     const std::string keyName = keyEvent.GetKeyName();
+    // Key will produce same logical-key value when ctrl
+    // is down, regardless of language layout
+    const std::string logicalKey = keyEvent.GetLogicalKey();
 
     const bool isNullKey = ( 0 == keyCode ) && ( keyString.empty() );
 
@@ -182,25 +185,25 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE
     else if ( keyEvent.IsCtrlModifier() && !keyEvent.IsShiftModifier())
     {
       bool consumed = false;
-      if (keyName == KEY_C_NAME || keyName == KEY_INSERT_NAME)
+      if (keyName == KEY_C_NAME || keyName == KEY_INSERT_NAME || logicalKey == KEY_C_NAME || logicalKey == KEY_INSERT_NAME)
       {
         // Ctrl-C or Ctrl+Insert to copy the selected text
         controller.TextPopupButtonTouched( Toolkit::TextSelectionPopup::COPY );
         consumed = true;
       }
-      else if (keyName == KEY_V_NAME)
+      else if (keyName == KEY_V_NAME || logicalKey == KEY_V_NAME)
       {
         // Ctrl-V to paste the copied text
         controller.TextPopupButtonTouched( Toolkit::TextSelectionPopup::PASTE );
         consumed = true;
       }
-      else if (keyName == KEY_X_NAME)
+      else if (keyName == KEY_X_NAME || logicalKey == KEY_X_NAME)
       {
         // Ctrl-X to cut the selected text
         controller.TextPopupButtonTouched( Toolkit::TextSelectionPopup::CUT );
         consumed = true;
       }
-      else if (keyName == KEY_A_NAME)
+      else if (keyName == KEY_A_NAME || logicalKey == KEY_A_NAME)
       {
         // Ctrl-A to select All the text
         controller.TextPopupButtonTouched( Toolkit::TextSelectionPopup::SELECT_ALL );
index ea097e1..fead0e6 100644 (file)
@@ -94,25 +94,41 @@ AnimatedVectorImageVisual::AnimatedVectorImageVisual( VisualFactoryCache& factor
   mPlacementActor(),
   mPlayState( DevelImageVisual::PlayState::STOPPED ),
   mEventCallback( nullptr ),
-  mRendererAdded( false )
+  mRendererAdded( false ),
+  mCoreShutdown(false)
 {
   // the rasterized image is with pre-multiplied alpha format
   mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA;
 
   mVectorAnimationTask->UploadCompletedSignal().Connect( this, &AnimatedVectorImageVisual::OnUploadCompleted );
   mVectorAnimationTask->SetAnimationFinishedCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnAnimationFinished ) ) );
+
+  auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager();
+  vectorAnimationManager.AddObserver(*this);
 }
 
 AnimatedVectorImageVisual::~AnimatedVectorImageVisual()
 {
-  if( mEventCallback )
+  if( ! mCoreShutdown )
   {
-    mFactoryCache.GetVectorAnimationManager().UnregisterEventCallback( mEventCallback );
+    auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager();
+    vectorAnimationManager.RemoveObserver(*this);
+
+    if( mEventCallback )
+    {
+      mFactoryCache.GetVectorAnimationManager().UnregisterEventCallback( mEventCallback );
+    }
+
+    // Finalize animation task and disconnect the signal in the main thread
+    mVectorAnimationTask->UploadCompletedSignal().Disconnect( this, &AnimatedVectorImageVisual::OnUploadCompleted );
+    mVectorAnimationTask->Finalize();
   }
+}
 
-  // Finalize animation task and disconnect the signal in the main thread
-  mVectorAnimationTask->UploadCompletedSignal().Disconnect( this, &AnimatedVectorImageVisual::OnUploadCompleted );
-  mVectorAnimationTask->Finalize();
+void AnimatedVectorImageVisual::VectorAnimationManagerDestroyed()
+{
+  // Core is shutting down. Don't talk to the plugin any more.
+  mCoreShutdown = true;
 }
 
 void AnimatedVectorImageVisual::GetNaturalSize( Vector2& naturalSize )
@@ -500,10 +516,11 @@ void AnimatedVectorImageVisual::StopAnimation()
 
 void AnimatedVectorImageVisual::TriggerVectorRasterization()
 {
-  if( !mEventCallback )
+  if( !mEventCallback && !mCoreShutdown )
   {
     mEventCallback = MakeCallback( this, &AnimatedVectorImageVisual::OnProcessEvents );
-    mFactoryCache.GetVectorAnimationManager().RegisterEventCallback( mEventCallback );
+    auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager();
+    vectorAnimationManager.RegisterEventCallback( mEventCallback );
     Stage::GetCurrent().KeepRendering( 0.0f );  // Trigger event processing
   }
 }
index e09527a..6196e39 100644 (file)
@@ -30,6 +30,7 @@
 #include <dali-toolkit/internal/visuals/visual-url.h>
 #include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h>
 #include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h>
+#include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h>
 
 namespace Dali
 {
@@ -55,7 +56,7 @@ using AnimatedVectorImageVisualPtr = IntrusivePtr< AnimatedVectorImageVisual >;
  * | url                      | STRING           |
  *
  */
-class AnimatedVectorImageVisual: public Visual::Base, public ConnectionTracker
+class AnimatedVectorImageVisual: public Visual::Base, public ConnectionTracker, public VectorAnimationManager::LifecycleObserver
 {
 public:
 
@@ -97,6 +98,12 @@ public:  // from Visual
    */
   void DoCreateInstancePropertyMap( Property::Map& map ) const override;
 
+protected: // From VectorAnimationManager::LifecycleObserver:
+  /**
+   * @copydoc VectorAnimationManager::LifecycleObserver::VectorAnimationManagerDestroyed()
+   */
+  void VectorAnimationManagerDestroyed() override;
+
 protected:
 
   /**
@@ -221,6 +228,7 @@ private:
   DevelImageVisual::PlayState::Type            mPlayState;
   CallbackBase*                                mEventCallback;    // Not owned
   bool                                         mRendererAdded;
+  bool                                         mCoreShutdown;
 };
 
 } // namespace Internal
index 8e47d81..ad56227 100644 (file)
@@ -45,6 +45,7 @@ Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New( Debug::NoLogging,
 
 VectorAnimationManager::VectorAnimationManager()
 : mEventCallbacks(),
+  mLifecycleObservers(),
   mVectorAnimationThread( nullptr ),
   mProcessorRegistered( false )
 {
@@ -62,6 +63,26 @@ VectorAnimationManager::~VectorAnimationManager()
   {
     Adaptor::Get().UnregisterProcessor( *this );
   }
+
+  for( auto observer : mLifecycleObservers )
+  {
+    observer->VectorAnimationManagerDestroyed();
+  }
+}
+
+void VectorAnimationManager::AddObserver( VectorAnimationManager::LifecycleObserver& observer )
+{
+  DALI_ASSERT_DEBUG( mLifecycleObservers.end() == std::find( mLifecycleObservers.begin(), mLifecycleObservers.end(), &observer));
+  mLifecycleObservers.push_back( &observer );
+}
+
+void VectorAnimationManager::RemoveObserver( VectorAnimationManager::LifecycleObserver& observer)
+{
+  auto iterator=std::find(mLifecycleObservers.begin(), mLifecycleObservers.end(), &observer);
+  if( iterator != mLifecycleObservers.end() )
+  {
+    mLifecycleObservers.erase(iterator);
+  }
 }
 
 VectorAnimationThread& VectorAnimationManager::GetVectorAnimationThread()
index 510c07e..7fbc3ca 100644 (file)
@@ -43,6 +43,10 @@ class VectorAnimationThread;
 class VectorAnimationManager: public Integration::Processor
 {
 public:
+  struct LifecycleObserver
+  {
+    virtual void VectorAnimationManagerDestroyed() = 0;
+  };
 
   /**
    * @brief Constructor.
@@ -55,6 +59,18 @@ public:
   ~VectorAnimationManager() override;
 
   /**
+   * Add a lifecycle observer
+   * @param[in] observer The object watching this one
+   */
+  void AddObserver( LifecycleObserver& observer );
+
+  /**
+   * Remove a lifecycle observer
+   * @param[in] observer The object watching this one
+   */
+  void RemoveObserver( LifecycleObserver& observer );
+
+  /**
    * Get the vector animation thread.
    * @return A raw pointer pointing to the vector animation thread.
    */
@@ -93,6 +109,7 @@ private:
 private:
 
   std::vector< CallbackBase* >             mEventCallbacks;
+  std::vector<LifecycleObserver*>         mLifecycleObservers;
   std::unique_ptr< VectorAnimationThread > mVectorAnimationThread;
   bool                                     mProcessorRegistered;
 };