Select the whole text of TextField. 39/202939/7
authorHuayong Xu <huayong.xu@samsung.com>
Mon, 8 Apr 2019 05:53:19 +0000 (13:53 +0800)
committerVíctor Cebollada <v.cebollada@samsung.com>
Mon, 15 Apr 2019 14:25:19 +0000 (14:25 +0000)
In some cases, the whole text of text-field need be selected,
and grab_handle and its popup need be disabled.

Change-Id: I5c1b5d5287509adf6357f25050c1831215f43f08
Signed-off-by: Huayong Xu <huayong.xu@samsung.com>
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp
dali-toolkit/devel-api/controls/text-controls/text-field-devel.cpp
dali-toolkit/devel-api/controls/text-controls/text-field-devel.h
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.h
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h

index d37a1db..95f7697 100755 (executable)
@@ -23,6 +23,7 @@
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/dali-toolkit.h>
 #include <toolkit-text-utils.h>
+#include <dali-toolkit/internal/controls/text-controls/text-field-impl.h>
 #include <dali-toolkit/internal/text/text-controller.h>
 #include <dali-toolkit/internal/text/text-control-interface.h>
 #include <dali-toolkit/internal/text/text-editable-control-interface.h>
@@ -1002,3 +1003,45 @@ int UtcDaliTextControllerCheckInputFontPointSizeChanged(void)
 
   END_TEST;
 }
+
+int UtcDaliTextControllerSelectEvent(void)
+{
+  tet_infoline(" UtcDaliTextControllerSelectEvent");
+  ToolkitTestApplication application;
+
+  // Creates a text controller.
+  ControllerPtr controller = Controller::New();
+
+  // Configures the text controller similarly to the text-field.
+  ConfigureTextField( controller );
+
+  // Set the text
+  const std::string text("Hello World!");
+  controller->SetText( text );
+
+  // Select the whole text.
+  controller->SelectEvent( 0.f, 0.f, false );
+
+  // Perform a relayout
+  const Size size( Dali::Stage::GetCurrent().GetSize() );
+  controller->Relayout(size);
+
+  // Get the implementation of the text controller
+  Controller::Impl& mImpl = Controller::Impl::GetImplementation( *controller.Get() );
+
+  // Check if the whole text is selected or not.
+  std::string retrieved_text;
+  mImpl.RetrieveSelection( retrieved_text, false );
+  DALI_TEST_EQUALS( "Hello", retrieved_text, TEST_LOCATION );
+
+  // Select the whole text.
+  controller->SelectEvent( 0.f, 0.f, true );
+
+  // Perform a relayout
+  controller->Relayout( size );
+
+  mImpl.RetrieveSelection( retrieved_text, false );
+  DALI_TEST_EQUALS( text, retrieved_text, TEST_LOCATION );
+
+  END_TEST;
+}
index 893d26a..4c126be 100755 (executable)
@@ -102,6 +102,7 @@ const char* const PROPERTY_NAME_ELLIPSIS                             = "ellipsis
 const char* const PROPERTY_NAME_ENABLE_SHIFT_SELECTION               = "enableShiftSelection";
 const char* const PROPERTY_NAME_ENABLE_GRAB_HANDLE                   = "enableGrabHandle";
 const char* const PROPERTY_NAME_MATCH_SYSTEM_LANGUAGE_DIRECTION      = "matchSystemLanguageDirection";
+const char* const PROPERTY_NAME_ENABLE_GRAB_HANDLE_POPUP             = "enableGrabHandlePopup";
 
 const Vector4 PLACEHOLDER_TEXT_COLOR( 0.8f, 0.8f, 0.8f, 0.8f );
 const Dali::Vector4 LIGHT_BLUE( 0.75f, 0.96f, 1.f, 1.f ); // The text highlight color.
@@ -539,6 +540,7 @@ int UtcDaliTextFieldGetPropertyP(void)
   DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_ENABLE_SHIFT_SELECTION ) == DevelTextField::Property::ENABLE_SHIFT_SELECTION );
   DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_ENABLE_GRAB_HANDLE ) == DevelTextField::Property::ENABLE_GRAB_HANDLE );
   DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_MATCH_SYSTEM_LANGUAGE_DIRECTION ) == DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION );
+  DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_ENABLE_GRAB_HANDLE_POPUP ) == DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP );
 
   END_TEST;
 }
@@ -993,6 +995,11 @@ int UtcDaliTextFieldSetPropertyP(void)
   field.SetProperty( Actor::Property::LAYOUT_DIRECTION, LayoutDirection::RIGHT_TO_LEFT );
   DALI_TEST_EQUALS( field.GetProperty<int>( Actor::Property::LAYOUT_DIRECTION ), static_cast<int>( LayoutDirection::RIGHT_TO_LEFT ), TEST_LOCATION );
 
+  // Test the ENABLE_GRAB_HANDLE_POPUP property
+  DALI_TEST_CHECK( field.GetProperty<bool>( DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP ) );
+  field.SetProperty( DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP, false );
+  DALI_TEST_CHECK( !field.GetProperty<bool>( DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP ) );
+
   application.SendNotification();
   application.Render();
 
@@ -2927,7 +2934,6 @@ int utcDaliTextFieldLayoutDirectionCoverage(void)
   END_TEST;
 }
 
-
 int UtcDaliTextFieldGetInputMethodContext(void)
 {
   ToolkitTestApplication application;
@@ -2939,3 +2945,54 @@ int UtcDaliTextFieldGetInputMethodContext(void)
   END_TEST;
 }
 
+int UtcDaliTextFieldSelectWholeText(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextFieldSelectWholeText ");
+
+  TextField textField = TextField::New();
+
+  Stage::GetCurrent().Add( textField );
+
+  textField.SetSize( 300.f, 50.f );
+  textField.SetParentOrigin( ParentOrigin::TOP_LEFT );
+  textField.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+
+  // Avoid a crash when core load gl resources.
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( 1u, textField.GetChildCount(), TEST_LOCATION );
+
+  DevelTextField::SelectWholeText( textField );
+
+  application.SendNotification();
+  application.Render();
+
+  // Nothing should have been selected. The number of children is still 1
+  DALI_TEST_EQUALS( 1u, textField.GetChildCount(), TEST_LOCATION );
+
+  textField.SetProperty( TextField::Property::TEXT, "Hello world" );
+
+  application.SendNotification();
+  application.Render();
+
+  DevelTextField::SelectWholeText( textField );
+
+  application.SendNotification();
+  application.Render();
+
+  // Should be 2 children, the stencil and the layer
+  DALI_TEST_EQUALS( 2u, textField.GetChildCount(), TEST_LOCATION );
+
+  // The offscreen root actor should have two actors: the renderer and the highlight actor.
+  Actor stencil = textField.GetChildAt( 0u );
+
+  // The highlight actor is drawn first, so is the first actor in the list
+  Renderer highlight = stencil.GetChildAt( 0u ).GetRendererAt( 0u );
+  DALI_TEST_CHECK( highlight );
+
+  END_TEST;
+}
index f9b739c..a53ef4a 100755 (executable)
@@ -33,6 +33,11 @@ InputMethodContext GetInputMethodContext( TextField textField )
   return GetImpl( textField ).GetInputMethodContext();
 }
 
+void SelectWholeText( TextField textField )
+{
+  GetImpl( textField ).SelectWholeText();
+}
+
 } // namespace DevelText
 
 } // namespace Toolkit
index cef786a..5e92a92 100755 (executable)
@@ -107,7 +107,14 @@ namespace Property
        * @details Name "matchSystemLanguageDirection", type (Property::BOOLEAN), Read/Write
        * @note The default value is false
        */
-      MATCH_SYSTEM_LANGUAGE_DIRECTION = ELLIPSIS + 3
+      MATCH_SYSTEM_LANGUAGE_DIRECTION = ELLIPSIS + 3,
+
+      /**
+        * @brief Enables the grab handle popup for text selection.
+        * @details Name "enableGrabHandlePopup", type Property::BOOLEAN.
+        * @note The default value is true, which means the grab handle popup is enabled by default.
+        */
+      ENABLE_GRAB_HANDLE_POPUP = ELLIPSIS + 4
 
   };
 } // namespace Property
@@ -120,6 +127,14 @@ namespace Property
  */
 DALI_TOOLKIT_API InputMethodContext GetInputMethodContext( TextField textField );
 
+/**
+ * @brief Select the whole text of TextField.
+ *
+ * @param[in] textField The instance of TextField.
+ * @return InputMethodContext instance.
+ */
+DALI_TOOLKIT_API void SelectWholeText( TextField textField );
+
 } // namespace DevelText
 
 } // namespace Toolkit
index 5270ea9..bf953ec 100755 (executable)
@@ -133,6 +133,7 @@ DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "ellipsis",
 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "enableShiftSelection",           BOOLEAN,   ENABLE_SHIFT_SELECTION               )
 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "enableGrabHandle",               BOOLEAN,   ENABLE_GRAB_HANDLE                   )
 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "matchSystemLanguageDirection",   BOOLEAN,   MATCH_SYSTEM_LANGUAGE_DIRECTION      )
+DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "enableGrabHandlePopup",          BOOLEAN,   ENABLE_GRAB_HANDLE_POPUP             )
 
 DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "textChanged",        SIGNAL_TEXT_CHANGED )
 DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "maxLengthReached",   SIGNAL_MAX_LENGTH_REACHED )
@@ -764,6 +765,17 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
         }
         break;
       }
+      case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP:
+      {
+        if (impl.mController)
+        {
+          const bool grabHandlePopupEnabled = value.Get<bool>();
+          DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p ENABLE_GRAB_HANDLE_POPUP %d\n", impl.mController.Get(), grabHandlePopupEnabled);
+
+          impl.mController->SetGrabHandlePopupEnabled(grabHandlePopupEnabled);
+          break;
+        }
+      }
     } // switch
   } // textfield
 }
@@ -1171,12 +1183,29 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
         }
         break;
       }
+      case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP:
+      {
+        if (impl.mController)
+        {
+          value = impl.mController->IsGrabHandlePopupEnabled();
+        }
+        break;
+      }
     } //switch
   }
 
   return value;
 }
 
+void TextField::SelectWholeText()
+{
+  if( mController && mController->IsShowingRealText() )
+  {
+    mController->SelectEvent( 0.f, 0.f, true );
+    SetKeyInputFocus();
+  }
+}
+
 InputMethodContext TextField::GetInputMethodContext()
 {
   return mInputMethodContext;
index 495f789..3b1062e 100755 (executable)
@@ -102,6 +102,11 @@ public:
    */
   Toolkit::TextField::InputStyleChangedSignalType& InputStyleChangedSignal();
 
+  /**
+   * @brief Called to select the whole texts.
+   */
+  void SelectWholeText();
+
 private: // From Control
 
   /**
index acf6291..09395d0 100755 (executable)
@@ -1847,15 +1847,13 @@ void Controller::Impl::OnSelectAllEvent()
 
   if( mEventData->mSelectionEnabled )
   {
-    ChangeState( EventData::SELECTING );
+    // Calculates the logical position from the start.
+    RepositionSelectionHandles( 0.f - mModel->mScrollPosition.x,
+                                0.f - mModel->mScrollPosition.y,
+                                Controller::NoTextTap::HIGHLIGHT );
 
     mEventData->mLeftSelectionPosition = 0u;
     mEventData->mRightSelectionPosition = mModel->mLogicalModel->mText.Count();
-
-    mEventData->mScrollAfterUpdatePosition = true;
-    mEventData->mUpdateLeftSelectionPosition = true;
-    mEventData->mUpdateRightSelectionPosition = true;
-    mEventData->mUpdateHighlightBox = true;
   }
 }
 
index 58bf52a..e0c63c8 100755 (executable)
@@ -435,6 +435,11 @@ void Controller::SetLayoutDirection( Dali::LayoutDirection::Type layoutDirection
   mImpl->mLayoutDirection = layoutDirection;
 }
 
+bool Controller::IsShowingRealText() const
+{
+  return mImpl->IsShowingRealText();
+}
+
 
 void Controller::SetLineWrapMode( Text::LineWrap::Mode lineWrapMode )
 {
@@ -522,6 +527,16 @@ bool Controller::IsGrabHandleEnabled() const
   return mImpl->mEventData->mGrabHandleEnabled;
 }
 
+void Controller::SetGrabHandlePopupEnabled(bool enabled)
+{
+  mImpl->mEventData->mGrabHandlePopupEnabled = enabled;
+}
+
+bool Controller::IsGrabHandlePopupEnabled() const
+{
+  return mImpl->mEventData->mGrabHandlePopupEnabled;
+}
+
 // public : Update
 
 void Controller::SetText( const std::string& text )
@@ -2814,6 +2829,32 @@ void Controller::LongPressEvent( Gesture::State state, float x, float y  )
   }
 }
 
+void Controller::SelectEvent( float x, float y, bool selectAll )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SelectEvent\n" );
+
+  if( NULL != mImpl->mEventData )
+  {
+    if( selectAll )
+    {
+      Event event( Event::SELECT_ALL );
+      mImpl->mEventData->mEventQueue.push_back( event );
+    }
+    else
+    {
+      Event event( Event::SELECT );
+      event.p2.mFloat = x;
+      event.p3.mFloat = y;
+      mImpl->mEventData->mEventQueue.push_back( event );
+    }
+
+    mImpl->mEventData->mCheckScrollAmount = true;
+    mImpl->mEventData->mIsLeftHandleSelected = true;
+    mImpl->mEventData->mIsRightHandleSelected = true;
+    mImpl->RequestRelayout();
+  }
+}
+
 InputMethodContext::CallbackData Controller::OnInputMethodContextEvent( InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent )
 {
   // Whether the text needs to be relaid-out.
@@ -3862,32 +3903,6 @@ void Controller::TextDeletedEvent()
   mImpl->mOperationsPending = ALL_OPERATIONS;
 }
 
-void Controller::SelectEvent( float x, float y, bool selectAll )
-{
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SelectEvent\n" );
-
-  if( NULL != mImpl->mEventData )
-  {
-    if( selectAll )
-    {
-      Event event( Event::SELECT_ALL );
-      mImpl->mEventData->mEventQueue.push_back( event );
-    }
-    else
-    {
-      Event event( Event::SELECT );
-      event.p2.mFloat = x;
-      event.p3.mFloat = y;
-      mImpl->mEventData->mEventQueue.push_back( event );
-    }
-
-    mImpl->mEventData->mCheckScrollAmount = true;
-    mImpl->mEventData->mIsLeftHandleSelected = true;
-    mImpl->mEventData->mIsRightHandleSelected = true;
-    mImpl->RequestRelayout();
-  }
-}
-
 bool Controller::DeleteEvent( int keyCode )
 {
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::KeyEvent %p KeyCode : %d \n", this, keyCode );
index 592b19d..f105e0c 100755 (executable)
@@ -421,6 +421,20 @@ public: // Configure the text controller.
   bool IsGrabHandleEnabled() const;
 
   /**
+   * @brief Enable or disable the grab handles for text selection.
+   *
+   * @param[in] enabled Whether to enable the grab handles
+   */
+  void SetGrabHandlePopupEnabled( bool enabled );
+
+  /**
+   * @brief Returns whether the grab handles are enabled.
+   *
+   * @return True if the grab handles are enabled
+   */
+  bool IsGrabHandlePopupEnabled() const;
+
+  /**
    * @brief Sets input type to password
    *
    * @note The string is displayed hidden character
@@ -1261,6 +1275,11 @@ public: // Queries & retrieves.
    */
   void SetLayoutDirection( Dali::LayoutDirection::Type layoutDirection );
 
+  /**
+   * @brief Retrieves if showing real text or not.
+   * @return The value of showing real text.
+   */
+  bool IsShowingRealText() const;
 
 public: // Relayout.
 
@@ -1341,6 +1360,17 @@ public: // Text-input Event Queuing.
   void LongPressEvent( Gesture::State state, float x, float y );
 
   /**
+   * @brief Creates a selection event.
+   *
+   * It could be called from the TapEvent (double tap) or when the text selection popup's sellect all button is pressed.
+   *
+   * @param[in] x The x position relative to the top-left of the parent control.
+   * @param[in] y The y position relative to the top-left of the parent control.
+   * @param[in] selectAll Whether the whole text is selected.
+   */
+  void SelectEvent( float x, float y, bool selectAll );
+
+  /**
    * @brief Event received from input method context
    *
    * @param[in] inputMethodContext The input method context.
@@ -1475,17 +1505,6 @@ private: // Events.
   void TextDeletedEvent();
 
   /**
-   * @brief Creates a selection event.
-   *
-   * It could be called from the TapEvent (double tap) or when the text selection popup's sellect all button is pressed.
-   *
-   * @param[in] x The x position relative to the top-left of the parent control.
-   * @param[in] y The y position relative to the top-left of the parent control.
-   * @param[in] selectAll Whether the whole text is selected.
-   */
-  void SelectEvent( float x, float y, bool selectAll );
-
-  /**
    * @brief Helper to KeyEvent() to handle the backspace or delete key case.
    *
    * @param[in] keyCode The keycode for the key pressed