Merge "Text selection refactoring" into devel/master
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Thu, 17 Sep 2020 18:03:38 +0000 (18:03 +0000)
committerGerrit Code Review <gerrit@review>
Thu, 17 Sep 2020 18:03:38 +0000 (18:03 +0000)
13 files changed:
automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp
dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h
dali-toolkit/devel-api/controls/text-controls/text-field-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/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-impl.h
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/text/text-selectable-control-interface.h [new file with mode: 0644]

index fd1fb32..6bf3ef9 100644 (file)
@@ -2860,3 +2860,30 @@ int utcDaliTextEditorMaxCharactersReached(void)
 
   END_TEST;
 }
+
+int UtcDaliTextEditorSelectRange(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("utcDaliTextEditorSelectRange");
+
+  TextEditor textEditor = TextEditor::New();
+  DALI_TEST_CHECK( textEditor );
+
+  application.GetScene().Add( textEditor );
+
+  // Avoid a crash when core load gl resources.
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+  application.SendNotification();
+  application.Render();
+
+  textEditor.SetProperty( TextEditor::Property::TEXT, "Hello world" );
+
+  textEditor.SetProperty( DevelTextEditor::Property::SELECTED_TEXT_START, 0 );
+  textEditor.SetProperty( DevelTextEditor::Property::SELECTED_TEXT_END, 5 );
+
+  DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT_START ).Get<int>(), 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT_END ).Get<int>(), 5, TEST_LOCATION );
+
+  END_TEST;
+}
\ No newline at end of file
index a759941..7b68239 100644 (file)
@@ -2958,3 +2958,50 @@ int UtcDaliTextFieldSelectNone(void)
 
   END_TEST;
 }
+
+int UtcDaliTextFieldSelectRange(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextFieldSelectRange ");
+
+  TextField textField = TextField::New();
+
+  application.GetScene().Add( textField );
+
+  textField.SetProperty( Actor::Property::SIZE, Vector2( 300.f, 50.f ) );
+  textField.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+  textField.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+
+  // Avoid a crash when core load gl resources.
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+  application.SendNotification();
+  application.Render();
+
+  textField.SetProperty( TextField::Property::TEXT, "Hello world" );
+
+  application.SendNotification();
+  application.Render();
+
+  textField.SetProperty( DevelTextField::Property::SELECTED_TEXT_START , 0);
+  textField.SetProperty( DevelTextField::Property::SELECTED_TEXT_END , 5);
+
+  // Hello is selected
+  std::string selectedText = textField.GetProperty( DevelTextField::Property::SELECTED_TEXT ).Get<std::string>();
+  DALI_TEST_EQUALS( "Hello", selectedText, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_START ).Get<int>(), 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_END ).Get<int>(), 5, TEST_LOCATION );
+
+  textField.SetProperty( DevelTextField::Property::SELECTED_TEXT_START , 6);
+  textField.SetProperty( DevelTextField::Property::SELECTED_TEXT_END , 11);
+
+  // world is selected
+  selectedText = textField.GetProperty( DevelTextField::Property::SELECTED_TEXT ).Get<std::string>();
+  DALI_TEST_EQUALS( "world", selectedText, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_START ).Get<int>(), 6, TEST_LOCATION );
+  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_END ).Get<int>(), 11, TEST_LOCATION );
+
+  END_TEST;
+}
index bd01101..ac2bc6d 100644 (file)
@@ -122,10 +122,22 @@ enum Type
   RENDERING_BACKEND,
 
   /**
-       * @brief The maximum number of characters that can be inserted.
-       * @details Name "maxLength", type Property::INTEGER.
-       */
+   * @brief The maximum number of characters that can be inserted.
+   * @details Name "maxLength", type Property::INTEGER.
+   */
   MAX_LENGTH,
+
+  /**
+   * @brief The selected text start position.
+   * @details Name "selectedTextStart", type Property::INTEGER.
+   */
+  SELECTED_TEXT_START,
+
+  /**
+   * @brief The selected text range end position.
+   * @details Name "selectedTextEnd", type Property::INTEGER.
+   */
+  SELECTED_TEXT_END,
 };
 
 } // namespace Property
index 8e2e006..922632b 100644 (file)
@@ -131,7 +131,20 @@ enum
        */
   RENDERING_BACKEND = ELLIPSIS + 7,
 
+  /**
+   * @brief The selected text start position.
+   * @details Name "selectedTextStart", type Property::INTEGER.
+   */
+  SELECTED_TEXT_START,
+
+  /**
+   * @brief The selected text range end position.
+   * @details Name "selectedTextEnd", type Property::INTEGER.
+   */
+  SELECTED_TEXT_END,
+
 };
+
 } // namespace Property
 
 /**
index 7576bc1..e6a2804 100644 (file)
@@ -139,6 +139,8 @@ DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "enableGrabHandle",
 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "matchSystemLanguageDirection",   BOOLEAN,   MATCH_SYSTEM_LANGUAGE_DIRECTION      )
 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "renderingBackend",               INTEGER,   RENDERING_BACKEND                    )
 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "maxLength",                      INTEGER,   MAX_LENGTH                           )
+DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectedTextStart",              INTEGER,   SELECTED_TEXT_START                  )
+DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectedTextEnd",                INTEGER,   SELECTED_TEXT_END                    )
 
 DALI_SIGNAL_REGISTRATION( Toolkit, TextEditor, "textChanged",        SIGNAL_TEXT_CHANGED )
 DALI_SIGNAL_REGISTRATION( Toolkit, TextEditor, "inputStyleChanged",  SIGNAL_INPUT_STYLE_CHANGED )
@@ -784,6 +786,26 @@ void TextEditor::SetProperty( BaseObject* object, Property::Index index, const P
         }
         break;
       }
+      case Toolkit::DevelTextEditor::Property::SELECTED_TEXT_START:
+      {
+        if( impl.mController )
+        {
+          uint32_t start = static_cast<uint32_t>(value.Get< int >());
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p SELECTED_TEXT_START %d\n", impl.mController.Get(), start );
+          impl.SetTextSelectionRange( &start, nullptr );
+        }
+        break;
+      }
+      case Toolkit::DevelTextEditor::Property::SELECTED_TEXT_END:
+      {
+        if( impl.mController )
+        {
+          uint32_t end = static_cast<uint32_t>(value.Get< int >());
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p SELECTED_TEXT_END %d\n", impl.mController.Get(), end );
+          impl.SetTextSelectionRange( nullptr, &end );
+        }
+        break;
+      }
     } // switch
   } // texteditor
 }
@@ -1192,6 +1214,18 @@ Property::Value TextEditor::GetProperty( BaseObject* object, Property::Index ind
         }
         break;
       }
+      case Toolkit::DevelTextEditor::Property::SELECTED_TEXT_START:
+      {
+        Uint32Pair range = impl.GetTextSelectionRange();
+        value = static_cast<int>(range.first);
+        break;
+      }
+      case Toolkit::DevelTextEditor::Property::SELECTED_TEXT_END:
+      {
+        Uint32Pair range = impl.GetTextSelectionRange();
+        value = static_cast<int>(range.second);
+        break;
+      }
     } //switch
   }
 
@@ -1259,7 +1293,7 @@ void TextEditor::OnInitialize()
 {
   Actor self = Self();
 
-  mController = Text::Controller::New( this, this );
+  mController = Text::Controller::New( this, this, this);
 
   mDecorator = Text::Decorator::New( *mController,
                                      *mController );
@@ -1708,6 +1742,25 @@ void TextEditor::AddDecoration( Actor& actor, bool needsClipping )
   }
 }
 
+void TextEditor::SetTextSelectionRange(const uint32_t *start, const uint32_t *end)
+{
+  if( mController && mController->IsShowingRealText() )
+  {
+    mController->SetTextSelectionRange( start, end );
+    SetKeyInputFocus();
+  }
+}
+
+Uint32Pair TextEditor::GetTextSelectionRange() const
+{
+  Uint32Pair range(0, 0);
+  if( mController && mController->IsShowingRealText() )
+  {
+    range = mController->GetTextSelectionRange();
+  }
+  return range;
+}
+
 void TextEditor::UpdateScrollBar()
 {
   using namespace Dali;
index d51ba2a..236cb7f 100755 (executable)
@@ -31,6 +31,7 @@
 #include <dali-toolkit/internal/text/decorator/text-decorator.h>
 #include <dali-toolkit/internal/text/text-control-interface.h>
 #include <dali-toolkit/internal/text/text-editable-control-interface.h>
+#include <dali-toolkit/internal/text/text-selectable-control-interface.h>
 #include <dali-toolkit/internal/text/text-controller.h>
 #include <dali-toolkit/internal/text/text-vertical-scroller.h>
 #include <dali-toolkit/internal/text/rendering/text-renderer.h>
@@ -46,7 +47,7 @@ namespace Internal
 /**
  * @brief A control which renders a long text string with styles.
  */
-class TextEditor : public Control, public Text::ControlInterface, public Text::EditableControlInterface
+class TextEditor : public Control, public Text::ControlInterface, public Text::EditableControlInterface, public Text::SelectableControlInterface
 {
 public:
 
@@ -202,6 +203,19 @@ private: // From Control
    */
   void AddDecoration( Actor& actor, bool needsClipping ) override;
 
+
+// From SelectableControlInterface
+public:
+  /**
+   * @copydoc Text::SelectableControlInterface::SetTextSelectionRange()
+   */
+  void SetTextSelectionRange(const uint32_t *start, const uint32_t *end) override;
+
+  /**
+   * @copydoc Text::SelectableControlInterface::GetTextSelectionRange()
+   */
+  Uint32Pair GetTextSelectionRange() const override;
+
 private: // Implementation
 
   /**
index dfe68d1..f4726f7 100644 (file)
@@ -134,6 +134,8 @@ DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "enableGrabHandlePopup",
 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "textBackground",                 VECTOR4,   BACKGROUND                           )
 DALI_DEVEL_PROPERTY_REGISTRATION_READ_ONLY( Toolkit, TextField, "selectedText",         STRING,    SELECTED_TEXT                        )
 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "renderingBackend",               INTEGER,   RENDERING_BACKEND                    )
+DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "selectedTextStart",              INTEGER,   SELECTED_TEXT_START                  )
+DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "selectedTextEnd",                INTEGER,   SELECTED_TEXT_END                    )
 
 DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "textChanged",        SIGNAL_TEXT_CHANGED )
 DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "maxLengthReached",   SIGNAL_MAX_LENGTH_REACHED )
@@ -806,6 +808,26 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
         }
         break;
       }
+      case Toolkit::DevelTextField::Property::SELECTED_TEXT_START:
+      {
+        if( impl.mController )
+        {
+          uint32_t start = static_cast<uint32_t>(value.Get< int >());
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p SELECTED_TEXT_START %d\n", impl.mController.Get(), start );
+          impl.SetTextSelectionRange( &start, nullptr );
+        }
+        break;
+      }
+      case Toolkit::DevelTextField::Property::SELECTED_TEXT_END:
+      {
+        if( impl.mController )
+        {
+          uint32_t end = static_cast<uint32_t>(value.Get< int >());
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p SELECTED_TEXT_END %d\n", impl.mController.Get(), end );
+          impl.SetTextSelectionRange( nullptr, &end );
+        }
+        break;
+      }
     } // switch
   } // textfield
 }
@@ -1229,6 +1251,18 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
         }
         break;
       }
+      case Toolkit::DevelTextField::Property::SELECTED_TEXT_START:
+      {
+        Uint32Pair range = impl.GetTextSelectionRange( );
+        value = static_cast<int>(range.first);
+        break;
+      }
+      case Toolkit::DevelTextField::Property::SELECTED_TEXT_END:
+      {
+        Uint32Pair range = impl.GetTextSelectionRange( );
+        value = static_cast<int>(range.second);
+        break;
+      }
     } //switch
   }
 
@@ -1253,6 +1287,26 @@ void TextField::SelectNone()
   }
 }
 
+void TextField::SetTextSelectionRange(const uint32_t *start, const uint32_t *end)
+{
+  if( mController && mController->IsShowingRealText() )
+  {
+    mController->SetTextSelectionRange( start, end );
+    SetKeyInputFocus();
+  }
+}
+
+Uint32Pair TextField::GetTextSelectionRange() const
+{
+  Uint32Pair range;
+  if( mController && mController->IsShowingRealText() )
+  {
+    range = mController->GetTextSelectionRange();
+  }
+  return range;
+}
+
+
 InputMethodContext TextField::GetInputMethodContext()
 {
   return mInputMethodContext;
@@ -1305,7 +1359,7 @@ void TextField::OnInitialize()
 {
   Actor self = Self();
 
-  mController = Text::Controller::New( this, this );
+  mController = Text::Controller::New( this, this ,this);
 
   // When using the vector-based rendering, the size of the GLyphs are different
   TextAbstraction::GlyphType glyphType = (DevelText::RENDERING_VECTOR_BASED == mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH;
index f7b6e56..c5723bd 100755 (executable)
@@ -28,6 +28,7 @@
 #include <dali-toolkit/internal/text/decorator/text-decorator.h>
 #include <dali-toolkit/internal/text/text-control-interface.h>
 #include <dali-toolkit/internal/text/text-editable-control-interface.h>
+#include <dali-toolkit/internal/text/text-selectable-control-interface.h>
 #include <dali-toolkit/internal/text/text-controller.h>
 #include <dali-toolkit/internal/text/rendering/text-renderer.h>
 
@@ -42,7 +43,7 @@ namespace Internal
 /**
  * @brief A control which renders a short text string.
  */
-class TextField : public Control, public Text::ControlInterface, public Text::EditableControlInterface
+class TextField : public Control, public Text::ControlInterface, public Text::EditableControlInterface, public Text::SelectableControlInterface
 {
 public:
 
@@ -107,7 +108,7 @@ public:
    */
   void SelectWholeText();
 
-    /**
+  /**
    * @brief Called to unselect the whole texts.
    */
   void SelectNone();
@@ -203,6 +204,19 @@ private: // From Control
    */
   void AddDecoration( Actor& actor, bool needsClipping ) override;
 
+
+// From SelectableControlInterface
+public:
+  /**
+   * @copydoc Text::SelectableControlInterface::SetTextSelectionRange()
+   */
+  void SetTextSelectionRange(const uint32_t *start, const uint32_t *end) override;
+
+  /**
+   * @copydoc Text::SelectableControlInterface::GetTextSelectionRange()
+   */
+  Uint32Pair GetTextSelectionRange() const override;
+
 private: // Implementation
 
   /**
index 0a8fe4b..9144ae3 100644 (file)
@@ -2040,6 +2040,54 @@ void Controller::Impl::OnSelectNoneEvent()
   }
 }
 
+void Controller::Impl::SetTextSelectionRange(const uint32_t *pStart, const uint32_t *pEnd)
+{
+  if( nullptr == mEventData )
+  {
+    // Nothing to do if there is no text.
+    return;
+  }
+
+  if( mEventData->mSelectionEnabled && (pStart || pEnd))
+  {
+    uint32_t length = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
+
+    if (pStart)
+    {
+      mEventData->mLeftSelectionPosition = std::min(*pStart, length);
+    }
+    if (pEnd)
+    {
+      mEventData->mRightSelectionPosition = std::min(*pEnd, length);
+    }
+
+    if (mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition)
+    {
+      ChangeState( EventData::EDITING );
+      mEventData->mPrimaryCursorPosition = mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition;
+      mEventData->mUpdateCursorPosition = true;
+    }
+    else
+    {
+      ChangeState( EventData::SELECTING );
+      mEventData->mUpdateHighlightBox = true;
+    }
+  }
+}
+
+Uint32Pair Controller::Impl::GetTextSelectionRange() const
+{
+  Uint32Pair range;
+
+  if( mEventData )
+  {
+    range.first = mEventData->mLeftSelectionPosition;
+    range.second = mEventData->mRightSelectionPosition;
+  }
+
+  return range;
+}
+
 void Controller::Impl::RetrieveSelection( std::string& selectedText, bool deleteAfterRetrieval )
 {
   if( mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition )
index 981e498..bb03be4 100755 (executable)
@@ -48,6 +48,8 @@ const float DEFAULT_TEXTFIT_STEP = 1.f;
 struct CursorInfo;
 struct FontDefaults;
 
+class SelectableControlInterface;
+
 struct Event
 {
   // Used to queue input events until DoRelayout()
@@ -308,9 +310,11 @@ struct OutlineDefaults
 struct Controller::Impl
 {
   Impl( ControlInterface* controlInterface,
-        EditableControlInterface* editableControlInterface )
+        EditableControlInterface* editableControlInterface,
+        SelectableControlInterface* selectableControlInterface )
   : mControlInterface( controlInterface ),
     mEditableControlInterface( editableControlInterface ),
+    mSelectableControlInterface( selectableControlInterface ),
     mModel(),
     mFontDefaults( NULL ),
     mUnderlineDefaults( NULL ),
@@ -623,6 +627,16 @@ struct Controller::Impl
   void OnSelectNoneEvent();
 
   /**
+   * @copydoc Text::SelectableControlInterface::SetTextSelectionRange()
+   */
+  void SetTextSelectionRange(const uint32_t *pStart, const uint32_t *pEndf);
+
+  /**
+   * @copydoc Text::SelectableControlInterface::GetTextSelectionRange()
+   */
+  Uint32Pair GetTextSelectionRange() const;
+
+  /**
    * @brief Retrieves the selected text. It removes the text if the @p deleteAfterRetrieval parameter is @e true.
    *
    * @param[out] selectedText The selected text encoded in utf8.
@@ -757,6 +771,7 @@ public:
 
   ControlInterface* mControlInterface;     ///< Reference to the text controller.
   EditableControlInterface* mEditableControlInterface; ///< Reference to the editable text controller.
+  SelectableControlInterface* mSelectableControlInterface; ///< Reference to the selectable text controller.
   ModelPtr mModel;                         ///< Pointer to the text's model.
   FontDefaults* mFontDefaults;             ///< Avoid allocating this when the user does not specify a font.
   UnderlineDefaults* mUnderlineDefaults;   ///< Avoid allocating this when the user does not specify underline parameters.
index 48036ad..9b46fe2 100755 (executable)
@@ -143,10 +143,12 @@ ControllerPtr Controller::New( ControlInterface* controlInterface )
 }
 
 ControllerPtr Controller::New( ControlInterface* controlInterface,
-                               EditableControlInterface* editableControlInterface )
+                               EditableControlInterface* editableControlInterface,
+                               SelectableControlInterface* selectableControlInterface )
 {
   return ControllerPtr( new Controller( controlInterface,
-                                        editableControlInterface ) );
+                                        editableControlInterface,
+                                        selectableControlInterface ) );
 }
 
 // public : Configure the text controller.
@@ -3193,6 +3195,24 @@ void Controller::SelectEvent( float x, float y, SelectionType selectType )
   }
 }
 
+void Controller::SetTextSelectionRange(const uint32_t *start, const uint32_t *end)
+{
+  if( mImpl->mEventData )
+  {
+    mImpl->mEventData->mCheckScrollAmount = true;
+    mImpl->mEventData->mIsLeftHandleSelected = true;
+    mImpl->mEventData->mIsRightHandleSelected = true;
+    mImpl->SetTextSelectionRange(start, end);
+    mImpl->RequestRelayout();
+    KeyboardFocusGainEvent();
+  }
+}
+
+Uint32Pair Controller::GetTextSelectionRange() const
+{
+  return mImpl->GetTextSelectionRange();
+}
+
 InputMethodContext::CallbackData Controller::OnInputMethodContextEvent( InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent )
 {
   // Whether the text needs to be relaid-out.
@@ -4448,19 +4468,21 @@ Actor Controller::CreateBackgroundActor()
 Controller::Controller()
 : mImpl( NULL )
 {
-  mImpl = new Controller::Impl( NULL, NULL );
+  mImpl = new Controller::Impl( nullptr, nullptr, nullptr );
 }
 
 Controller::Controller( ControlInterface* controlInterface )
 {
-  mImpl = new Controller::Impl( controlInterface, NULL );
+  mImpl = new Controller::Impl( controlInterface, NULL, NULL );
 }
 
 Controller::Controller( ControlInterface* controlInterface,
-                        EditableControlInterface* editableControlInterface )
+                        EditableControlInterface* editableControlInterface,
+                        SelectableControlInterface* selectableControlInterface )
 {
   mImpl = new Controller::Impl( controlInterface,
-                                editableControlInterface );
+                                editableControlInterface,
+                                selectableControlInterface );
 }
 
 // The copy constructor and operator are left unimplemented.
index 4d40f41..2661270 100755 (executable)
@@ -31,6 +31,7 @@
 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
 #include <dali-toolkit/internal/text/hidden-text.h>
 #include <dali-toolkit/internal/text/text-model-interface.h>
+#include <dali-toolkit/internal/text/text-selectable-control-interface.h>
 
 namespace Dali
 {
@@ -187,11 +188,13 @@ public: // Constructor.
    *
    * @param[in] controlInterface The control's interface.
    * @param[in] editableControlInterface The editable control's interface.
+   * @param[in] selectableControlInterface The selectable control's interface.
    *
    * @return A pointer to a new Controller.
    */
   static ControllerPtr New( ControlInterface* controlInterface,
-                            EditableControlInterface* editableControlInterface );
+                            EditableControlInterface* editableControlInterface,
+                            SelectableControlInterface* selectableControlInterface );
 
 public: // Configure the text controller.
 
@@ -1493,6 +1496,16 @@ public: // Text-input Event Queuing.
   void SelectEvent( float x, float y, SelectionType selection );
 
   /**
+   * @copydoc Text::SelectableControlInterface::SetTextSelectionRange()
+   */
+  void SetTextSelectionRange(const uint32_t *start, const uint32_t *end);
+
+  /**
+   * @copydoc Text::SelectableControlInterface::GetTextSelectionRange()
+   */
+  Uint32Pair GetTextSelectionRange() const;
+
+  /**
    * @brief Event received from input method context
    *
    * @param[in] inputMethodContext The input method context.
@@ -1698,7 +1711,8 @@ private: // Private contructors & copy operator.
    * @brief Private constructor.
    */
   Controller( ControlInterface* controlInterface,
-              EditableControlInterface* editableControlInterface );
+              EditableControlInterface* editableControlInterface,
+              SelectableControlInterface* selectableControlInterface );
 
   // Undefined
   Controller( const Controller& handle );
diff --git a/dali-toolkit/internal/text/text-selectable-control-interface.h b/dali-toolkit/internal/text/text-selectable-control-interface.h
new file mode 100644 (file)
index 0000000..fe70abb
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef DALI_TOOLKIT_TEXT_SELECTABLE_CONTROL_INTERFACE_H
+#define DALI_TOOLKIT_TEXT_SELECTABLE_CONTROL_INTERFACE_H
+
+/*
+ * Copyright (c) 2020 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
+{
+
+namespace Toolkit
+{
+
+using  Uint32Pair = std::pair<uint32_t,uint32_t>;
+namespace Text
+{
+
+/**
+ * @brief An interface that the Text::Controller used for text selection functionality.
+ */
+class SelectableControlInterface
+{
+public:
+
+  /**
+   * @brief Virtual destructor.
+   */
+  virtual ~SelectableControlInterface() = default;
+
+  /**
+   * @brief Called to set the selection postions in the texts.
+   * @param start start selection position (pass NULL to ignore).
+   * @param end end selection position (pass NULL to ignore).
+   */
+  virtual void SetTextSelectionRange(const uint32_t *start, const uint32_t *end) = 0;
+
+  /**
+   * @brief Called to return the selection postions in the texts.
+   * @return pair contains start and end positions.
+   */
+  virtual Uint32Pair GetTextSelectionRange() const = 0;
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_SELECTABLE_CONTROL_INTERFACE_H