[AT-SPI] Introduce TextControlAccessible 09/272309/2
authorArtur Świgoń <a.swigon@samsung.com>
Mon, 14 Mar 2022 09:39:30 +0000 (10:39 +0100)
committerArtur Świgoń <a.swigon@samsung.com>
Mon, 14 Mar 2022 09:44:01 +0000 (10:44 +0100)
TextEditorAccessible, TextFieldAccessible and TextLabelAccessible
contained a large amount of nearly identical code. They now have a new
common parent, TextControlAccessible (or EditableTextControlAccessible)
which contains common code.

Change-Id: I40eb67970780a6a320b514cf261a1df91f6dcf49

dali-toolkit/internal/controls/text-controls/common-text-utils.cpp
dali-toolkit/internal/controls/text-controls/common-text-utils.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/controls/text-controls/text-label-impl.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.h

index 696b44a..833b81b 100644 (file)
  * limitations under the License.
  */
 
+// EXTERNAL INCLUDES
 #include <dali/public-api/actors/layer.h>
 
+// INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
 #include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
 #include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/hidden-text.h>
 #include <dali-toolkit/internal/text/text-view.h>
 
 namespace Dali::Toolkit::Internal
@@ -151,4 +156,344 @@ void CommonTextUtils::RenderText(
   }
 }
 
+std::size_t TextControlAccessible::GetCharacterCount() const
+{
+  return GetWholeText().size();
+}
+
+std::size_t TextControlAccessible::GetCursorOffset() const
+{
+  return 0u;
+}
+
+Rect<> TextControlAccessible::GetRangeExtents(std::size_t startOffset, std::size_t endOffset, Accessibility::CoordinateType type)
+{
+  if(!ValidateRange(GetWholeText(), startOffset, endOffset))
+  {
+    return {0, 0, 0, 0};
+  }
+
+  auto rect    = GetTextController()->GetTextBoundingRectangle(startOffset, endOffset - 1);
+  auto extents = GetExtents(type);
+
+  rect.x += extents.x;
+  rect.y += extents.y;
+
+  return rect;
+}
+
+Accessibility::Range TextControlAccessible::GetRangeOfSelection(std::size_t selectionIndex) const
+{
+  // Since DALi supports only one selection, indices other than 0 are ignored
+  if(selectionIndex > 0)
+  {
+    return {};
+  }
+
+  auto indices     = GetTextController()->GetSelectionIndexes();
+  auto startOffset = static_cast<std::size_t>(indices.first);
+  auto endOffset   = static_cast<std::size_t>(indices.second);
+  auto text        = GetText(startOffset, endOffset);
+
+  return {startOffset, endOffset, text};
+}
+
+std::string TextControlAccessible::GetText(std::size_t startOffset, std::size_t endOffset) const
+{
+  auto text = GetWholeText();
+
+  if(!ValidateRange(text, startOffset, endOffset))
+  {
+    return {};
+  }
+
+  if(IsHiddenInput())
+  {
+    std::uint32_t substituteCharacterUtf32 = GetSubstituteCharacter();
+    std::string   substituteCharacterUtf8;
+    std::string   substituteText;
+
+    Toolkit::Text::Utf32ToUtf8(&substituteCharacterUtf32, 1, substituteCharacterUtf8);
+
+    while(substituteText.length() < endOffset - startOffset)
+    {
+      substituteText.append(substituteCharacterUtf8);
+    }
+
+    return substituteText;
+  }
+
+  return text.substr(startOffset, endOffset - startOffset);
+}
+
+Accessibility::Range TextControlAccessible::GetTextAtOffset(std::size_t offset, Accessibility::TextBoundary boundary) const
+{
+  Accessibility::Range range{};
+
+  if(IsHiddenInput())
+  {
+    // Returning empty object, as there is no possibility to parse the textfield
+    // when its content is hidden.
+    return range;
+  }
+
+  auto text     = GetWholeText();
+  auto textSize = text.size();
+
+  switch(boundary)
+  {
+    case Dali::Accessibility::TextBoundary::CHARACTER:
+    {
+      if(offset < textSize)
+      {
+        range.content     = text[offset];
+        range.startOffset = offset;
+        range.endOffset   = offset + 1;
+      }
+      break;
+    }
+
+    case Dali::Accessibility::TextBoundary::WORD:
+    case Dali::Accessibility::TextBoundary::LINE:
+    {
+      std::vector<char> breaks(textSize, '\0');
+
+      if(boundary == Dali::Accessibility::TextBoundary::WORD)
+      {
+        Accessibility::Accessible::FindWordSeparationsUtf8(reinterpret_cast<const utf8_t*>(text.c_str()), textSize, "", breaks.data());
+      }
+      else
+      {
+        Accessibility::Accessible::FindLineSeparationsUtf8(reinterpret_cast<const utf8_t*>(text.c_str()), textSize, "", breaks.data());
+      }
+
+      std::size_t index   = 0u;
+      std::size_t counter = 0u;
+
+      while(index < textSize && counter <= offset)
+      {
+        auto start = index;
+        if(breaks[index])
+        {
+          while(breaks[index])
+          {
+            index++;
+          }
+          counter++;
+        }
+        else
+        {
+          if(boundary == Dali::Accessibility::TextBoundary::WORD)
+          {
+            index++;
+          }
+          if(boundary == Dali::Accessibility::TextBoundary::LINE)
+          {
+            counter++;
+          }
+        }
+
+        if((counter > 0) && ((counter - 1) == offset))
+        {
+          range.content     = text.substr(start, index - start + 1);
+          range.startOffset = start;
+          range.endOffset   = index + 1;
+        }
+
+        if(boundary == Dali::Accessibility::TextBoundary::LINE)
+        {
+          index++;
+        }
+      }
+      break;
+    }
+
+    case Dali::Accessibility::TextBoundary::SENTENCE: // Not supported by default
+    case Dali::Accessibility::TextBoundary::PARAGRAPH: // Not supported by libunibreak library
+    default:
+    {
+      break;
+    }
+  }
+
+  return range;
+}
+
+bool TextControlAccessible::RemoveSelection(std::size_t selectionIndex)
+{
+  // Since DALi supports only one selection, indices other than 0 are ignored
+  if(selectionIndex > 0)
+  {
+    return false;
+  }
+
+  GetTextController()->SetSelection(0, 0);
+
+  return true;
+}
+
+bool TextControlAccessible::SetCursorOffset(std::size_t offset)
+{
+  return false;
+}
+
+bool TextControlAccessible::SetRangeOfSelection(std::size_t selectionIndex, std::size_t startOffset, std::size_t endOffset)
+{
+  // Since DALi supports only one selection, indices other than 0 are ignored
+  if(selectionIndex > 0)
+  {
+    return false;
+  }
+
+  // Lack of ValidateRange() is intentional
+
+  GetTextController()->SetSelection(startOffset, endOffset);
+
+  return true;
+}
+
+Accessibility::Hyperlink* TextControlAccessible::GetLink(std::int32_t linkIndex) const
+{
+  if(linkIndex < 0 || linkIndex >= GetLinkCount())
+  {
+    return nullptr;
+  }
+
+  auto anchor = GetTextAnchors()[linkIndex];
+
+  return Accessibility::Hyperlink::DownCast(Accessibility::Accessible::Get(anchor));
+}
+
+std::int32_t TextControlAccessible::GetLinkCount() const
+{
+  return static_cast<std::int32_t>(GetTextAnchors().size());
+}
+
+std::int32_t TextControlAccessible::GetLinkIndex(std::int32_t characterOffset) const
+{
+  return GetTextController()->GetAnchorIndex(static_cast<std::size_t>(characterOffset));
+}
+
+std::string TextControlAccessible::GetWholeText() const
+{
+  std::string text;
+
+  GetTextController()->GetText(text);
+
+  return text;
+}
+
+std::uint32_t TextControlAccessible::GetSubstituteCharacter() const
+{
+  return Toolkit::Text::STAR;
+}
+
+bool TextControlAccessible::IsHiddenInput() const
+{
+  return false;
+}
+
+bool TextControlAccessible::ValidateRange(const std::string& string, std::size_t begin, std::size_t end)
+{
+  auto size = string.size();
+
+  if(end <= begin || begin >= size || end > size)
+  {
+    return false;
+  }
+
+  // TODO: Check whether the range [begin, end) describes a valid substring:
+  // 1. It does not break multi-byte UTF-8 sequences.
+  // 2. It does not break graphemes (compound emojis, glyphs with combining characters etc.).
+
+  return true;
+}
+
+Accessibility::States EditableTextControlAccessible::CalculateStates()
+{
+  using Dali::Accessibility::State;
+
+  auto states       = DevelControl::ControlAccessible::CalculateStates();
+  auto focusControl = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl();
+
+  states[State::EDITABLE]  = true;
+  states[State::FOCUSABLE] = true;
+  states[State::FOCUSED]   = (Self() == focusControl);
+
+  return states;
+}
+
+std::size_t EditableTextControlAccessible::GetCursorOffset() const
+{
+  return GetTextController()->GetCursorPosition();
+}
+
+bool EditableTextControlAccessible::SetCursorOffset(std::size_t offset)
+{
+  if(offset > GetCharacterCount())
+  {
+    return false;
+  }
+
+  GetTextController()->ResetCursorPosition(offset);
+  RequestTextRelayout();
+
+  return true;
+}
+
+bool EditableTextControlAccessible::CopyText(std::size_t startPosition, std::size_t endPosition)
+{
+  auto text = GetWholeText();
+
+  if(!ValidateRange(text, startPosition, endPosition))
+  {
+    return false;
+  }
+
+  GetTextController()->CopyStringToClipboard(text.substr(startPosition, endPosition - startPosition));
+
+  return true;
+}
+
+bool EditableTextControlAccessible::CutText(std::size_t startPosition, std::size_t endPosition)
+{
+  if(!CopyText(startPosition, endPosition))
+  {
+    return false;
+  }
+
+  return DeleteText(startPosition, endPosition);
+}
+
+bool EditableTextControlAccessible::DeleteText(std::size_t startPosition, std::size_t endPosition)
+{
+  auto text = GetWholeText();
+
+  if(!ValidateRange(text, startPosition, endPosition))
+  {
+    return false;
+  }
+
+  return SetTextContents(text.erase(startPosition, endPosition - startPosition));
+}
+
+bool EditableTextControlAccessible::InsertText(std::size_t startPosition, std::string newText)
+{
+  auto text = GetWholeText();
+
+  if(!ValidateRange(text, startPosition, startPosition + 1))
+  {
+    return false;
+  }
+
+  return SetTextContents(text.insert(startPosition, std::move(newText)));
+}
+
+bool EditableTextControlAccessible::SetTextContents(std::string newContents)
+{
+  GetTextController()->SetText(std::move(newContents));
+
+  return true;
+}
+
 } // namespace Dali::Toolkit::Internal
index 212f162..f6a9a2f 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/atspi-interfaces/editable-text.h>
+#include <dali/devel-api/atspi-interfaces/hypertext.h>
+#include <dali/devel-api/atspi-interfaces/text.h>
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/common/vector-wrapper.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-accessible.h>
 #include <dali-toolkit/devel-api/controls/text-controls/text-anchor-devel.h>
 #include <dali-toolkit/internal/text/decorator/text-decorator.h>
 #include <dali-toolkit/internal/text/rendering/text-renderer.h>
 #include <dali-toolkit/internal/text/text-controller.h>
 #include <dali-toolkit/public-api/controls/control.h>
 #include <dali-toolkit/public-api/controls/text-controls/text-editor.h>
-#include <dali/public-api/actors/actor.h>
-
-#include <dali/public-api/common/vector-wrapper.h>
 
 namespace Dali::Toolkit::Internal
 {
@@ -70,6 +77,181 @@ public:
     std::vector<Toolkit::TextAnchor>& anchorActors);
 };
 
+class TextControlAccessible : public DevelControl::ControlAccessible,
+                              public virtual Dali::Accessibility::Text,
+                              public virtual Dali::Accessibility::Hypertext
+{
+public:
+  using DevelControl::ControlAccessible::ControlAccessible;
+
+  // Text
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetCharacterCount()
+   */
+  std::size_t GetCharacterCount() const override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetCursorOffset()
+   */
+  std::size_t GetCursorOffset() const override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetRangeExtents()
+   */
+  Rect<> GetRangeExtents(std::size_t startOffset, std::size_t endOffset, Accessibility::CoordinateType type) override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetRangeOfSelection()
+   */
+  Accessibility::Range GetRangeOfSelection(std::size_t selectionIndex) const override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetText()
+   */
+  std::string GetText(std::size_t startOffset, std::size_t endOffset) const override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetTextAtOffset()
+   */
+  Accessibility::Range GetTextAtOffset(std::size_t offset, Accessibility::TextBoundary boundary) const override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::RemoveSelection()
+   */
+  bool RemoveSelection(std::size_t selectionIndex) override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::SetCursorOffset()
+   */
+  bool SetCursorOffset(std::size_t offset) override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::SetRangeOfSelection()
+   */
+  bool SetRangeOfSelection(std::size_t selectionIndex, std::size_t startOffset, std::size_t endOffset) override;
+
+  // Hypertext
+
+  /**
+   * @copydoc Dali::Accessibility::Hypertext::GetLink()
+   */
+  Accessibility::Hyperlink* GetLink(std::int32_t linkIndex) const override;
+
+  /**
+   * @copydoc Dali::Accessibility::Hypertext::GetLinkCount()
+   */
+  std::int32_t GetLinkCount() const override;
+
+  /**
+   * @copydoc Dali::Accessibility::Hypertext::GetLinkIndex()
+   */
+  std::int32_t GetLinkIndex(std::int32_t characterOffset) const override;
+
+protected:
+  /**
+   * @brief Gets whole text.
+   *
+   * @return The text
+   */
+  std::string GetWholeText() const;
+
+  /**
+   * @brief Gets text anchors.
+   *
+   * @return Text anchors
+   */
+  virtual const std::vector<Toolkit::TextAnchor>& GetTextAnchors() const = 0;
+
+  /**
+   * @brief Gets text controller.
+   *
+   * @return The text controller
+   */
+  virtual Toolkit::Text::ControllerPtr GetTextController() const = 0;
+
+  /**
+   * @brief Get substitute character for hidden text.
+   *
+   * @return The substitute character (Unicode codepoint)
+   */
+  virtual std::uint32_t GetSubstituteCharacter() const;
+
+  /**
+   * @brief Checks whether text should be hidden (replaced with substitute characters).
+   *
+   * @return True if text should be hidden, false otherwise
+   */
+  virtual bool IsHiddenInput() const;
+
+  /**
+   * @brief Checks whether [startPosition, endPosition) is a valid, non-empty range within a given string.
+   *
+   * @param string Source string
+   * @param begin Start index (inclusive)
+   * @param end End index (exclusive)
+   * @return true if the range is valid, false otherwise
+   */
+  static bool ValidateRange(const std::string& string, std::size_t begin, std::size_t end);
+};
+
+class EditableTextControlAccessible : public TextControlAccessible,
+                                      public virtual Dali::Accessibility::EditableText
+{
+public:
+  using TextControlAccessible::TextControlAccessible;
+
+  /**
+   * @copydoc Dali::Toolkit::DevelControl::ControlAccessible::CalculateStates()
+   */
+  Accessibility::States CalculateStates() override;
+
+  // Text
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetCursorOffset()
+   */
+  std::size_t GetCursorOffset() const override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::SetCursorOffset()
+   */
+  bool SetCursorOffset(std::size_t offset) override;
+
+  // EditableText
+
+  /**
+   * @copydoc Dali::Accessibility::EditableText::CopyText()
+   */
+  bool CopyText(size_t startPosition, size_t endPosition) override;
+
+  /**
+   * @copydoc Dali::Accessibility::EditableText::CutText()
+   */
+  bool CutText(size_t startPosition, size_t endPosition) override;
+
+  /**
+   * @copydoc Dali::Accessibility::EditableText::DeleteText()
+   */
+  bool DeleteText(size_t startPosition, size_t endPosition) override;
+
+  /**
+   * @copydoc Dali::Accessibility::EditableText::InsertText()
+   */
+  bool InsertText(size_t startPosition, std::string text) override;
+
+  /**
+   * @copydoc Dali::Accessibility::EditableText::SetTextContents()
+   */
+  bool SetTextContents(std::string newContents) override;
+
+protected:
+  /**
+   * @brief Requests text relayout.
+   */
+  virtual void RequestTextRelayout() = 0;
+};
+
 } // namespace Dali::Toolkit::Internal
 
 #endif //DALI_TOOLKIT_INTERNAL_TEXT_CONTROLS_COMMON_TEXT_UTILS_H
index 5707e48..d931401 100644 (file)
@@ -33,7 +33,6 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/control-devel.h>
-#include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
 #include <dali-toolkit/devel-api/text/rendering-backend.h>
 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
 #include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
@@ -1350,313 +1349,29 @@ TextEditor::~TextEditor()
 
 std::string TextEditor::TextEditorAccessible::GetName() const
 {
-  auto self = Toolkit::TextEditor::DownCast(Self());
-  return self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
-}
-
-std::string TextEditor::TextEditorAccessible::GetText(size_t startOffset, size_t endOffset) const
-{
-  if(endOffset <= startOffset)
-  {
-    return {};
-  }
-
-  auto self = Toolkit::TextEditor::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
-
-  if(startOffset > text.size() || endOffset > text.size())
-  {
-    return {};
-  }
-
-  return text.substr(startOffset, endOffset - startOffset);
-}
-
-size_t TextEditor::TextEditorAccessible::GetCharacterCount() const
-{
-  auto self = Toolkit::TextEditor::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
-
-  return text.size();
-}
-
-size_t TextEditor::TextEditorAccessible::GetCursorOffset() const
-{
-  auto slf = Toolkit::TextEditor::DownCast(Self());
-  return Dali::Toolkit::GetImpl(slf).GetTextController()->GetCursorPosition();
-}
-
-bool TextEditor::TextEditorAccessible::SetCursorOffset(size_t offset)
-{
-  auto slf = Toolkit::TextEditor::DownCast(Self());
-  auto txt = slf.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
-  if(offset > txt.size())
-  {
-    return false;
-  }
-
-  auto& slfImpl = Dali::Toolkit::GetImpl(slf);
-  slfImpl.GetTextController()->ResetCursorPosition(offset);
-  slfImpl.RequestTextRelayout();
-
-  return true;
-}
-
-Dali::Accessibility::Range TextEditor::TextEditorAccessible::GetTextAtOffset(size_t offset, Dali::Accessibility::TextBoundary boundary) const
-{
-  auto self     = Toolkit::TextEditor::DownCast(Self());
-  auto text     = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
-  auto textSize = text.size();
-
-  auto range = Dali::Accessibility::Range{};
-
-  switch(boundary)
-  {
-    case Dali::Accessibility::TextBoundary::CHARACTER:
-    {
-      if(offset < textSize)
-      {
-        range.content     = text[offset];
-        range.startOffset = offset;
-        range.endOffset   = offset + 1;
-      }
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::WORD:
-    case Dali::Accessibility::TextBoundary::LINE:
-    {
-      auto textString = text.c_str();
-      auto breaks     = std::vector<char>(textSize, 0);
-
-      if(boundary == Dali::Accessibility::TextBoundary::WORD)
-      {
-        Accessibility::Accessible::FindWordSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
-      }
-      else
-      {
-        Accessibility::Accessible::FindLineSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
-      }
-
-      auto index   = 0u;
-      auto counter = 0u;
-      while(index < textSize && counter <= offset)
-      {
-        auto start = index;
-        if(breaks[index])
-        {
-          while(breaks[index])
-          {
-            index++;
-          }
-          counter++;
-        }
-        else
-        {
-          if(boundary == Dali::Accessibility::TextBoundary::WORD)
-          {
-            index++;
-          }
-          if(boundary == Dali::Accessibility::TextBoundary::LINE)
-          {
-            counter++;
-          }
-        }
-
-        if((counter > 0) && ((counter - 1) == offset))
-        {
-          range.content     = text.substr(start, index - start + 1);
-          range.startOffset = start;
-          range.endOffset   = index + 1;
-        }
-
-        if(boundary == Dali::Accessibility::TextBoundary::LINE)
-        {
-          index++;
-        }
-      }
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::SENTENCE:
-    {
-      /* not supported by default */
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::PARAGRAPH:
-    {
-      /* Paragraph is not supported by libunibreak library */
-      break;
-    }
-    default:
-      break;
-  }
-
-  return range;
-}
-
-Dali::Accessibility::Range TextEditor::TextEditorAccessible::GetRangeOfSelection(size_t selectionIndex) const
-{
-  // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionIndex > 0)
-  {
-    return {};
-  }
-
-  auto        self       = Toolkit::TextEditor::DownCast(Self());
-  auto        controller = Dali::Toolkit::GetImpl(self).GetTextController();
-  std::string value{};
-  controller->RetrieveSelection(value);
-  auto indices = controller->GetSelectionIndexes();
-
-  return {static_cast<size_t>(indices.first), static_cast<size_t>(indices.second), value};
-}
-
-bool TextEditor::TextEditorAccessible::RemoveSelection(size_t selectionIndex)
-{
-  // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionIndex > 0)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextEditor::DownCast(Self());
-  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(0, 0);
-  return true;
-}
-
-bool TextEditor::TextEditorAccessible::SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset)
-{
-  // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionIndex > 0)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextEditor::DownCast(Self());
-  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(startOffset, endOffset);
-  return true;
-}
-
-Rect<> TextEditor::TextEditorAccessible::GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type)
-{
-  if (endOffset <= startOffset || endOffset <= 0)
-  {
-    return {0, 0, 0, 0};
-  }
-
-  auto self = Toolkit::TextEditor::DownCast(Self());
-  auto rect = Dali::Toolkit::GetImpl(self).GetTextController()->GetTextBoundingRectangle(startOffset, endOffset - 1);
-
-  auto componentExtents = this->GetExtents(type);
-
-  rect.x += componentExtents.x;
-  rect.y += componentExtents.y;
-
-  return rect;
-}
-
-bool TextEditor::TextEditorAccessible::CopyText(size_t startPosition, size_t endPosition)
-{
-  if(endPosition <= startPosition)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextEditor::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
-  Dali::Toolkit::GetImpl(self).GetTextController()->CopyStringToClipboard(text.substr(startPosition, endPosition - startPosition));
-
-  return true;
-}
-
-bool TextEditor::TextEditorAccessible::CutText(size_t startPosition, size_t endPosition)
-{
-  if(endPosition <= startPosition)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextEditor::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
-  Dali::Toolkit::GetImpl(self).GetTextController()->CopyStringToClipboard(text.substr(startPosition, endPosition - startPosition));
-
-  self.SetProperty(Toolkit::TextEditor::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition));
-
-  return true;
+  return GetWholeText();
 }
 
-bool TextEditor::TextEditorAccessible::DeleteText(size_t startPosition, size_t endPosition)
+const std::vector<Toolkit::TextAnchor>& TextEditor::TextEditorAccessible::GetTextAnchors() const
 {
-  if(endPosition <= startPosition)
-  {
-    return false;
-  }
-
   auto self = Toolkit::TextEditor::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
-
-  self.SetProperty(Toolkit::TextEditor::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition));
 
-  return true;
+  return Toolkit::GetImpl(self).mAnchorActors;
 }
 
-Dali::Accessibility::States TextEditor::TextEditorAccessible::CalculateStates()
-{
-  using namespace Dali::Accessibility;
-
-  auto states              = DevelControl::ControlAccessible::CalculateStates();
-  states[State::EDITABLE]  = true;
-  states[State::FOCUSABLE] = true;
-
-  Toolkit::Control focusControl = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl();
-  if(Self() == focusControl)
-  {
-    states[State::FOCUSED] = true;
-  }
-
-  return states;
-}
-
-bool TextEditor::TextEditorAccessible::InsertText(size_t startPosition, std::string text)
-{
-  auto self         = Toolkit::TextEditor::DownCast(Self());
-  auto insertedText = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
-
-  insertedText.insert(startPosition, text);
-
-  self.SetProperty(Toolkit::TextEditor::Property::TEXT, std::move(insertedText));
-
-  return true;
-}
-
-bool TextEditor::TextEditorAccessible::SetTextContents(std::string newContents)
+Toolkit::Text::ControllerPtr TextEditor::TextEditorAccessible::GetTextController() const
 {
   auto self = Toolkit::TextEditor::DownCast(Self());
-  self.SetProperty(Toolkit::TextEditor::Property::TEXT, std::move(newContents));
-  return true;
-}
 
-int32_t TextEditor::TextEditorAccessible::GetLinkCount() const
-{
-  auto self = Toolkit::TextEditor::DownCast(Self());
-  return Dali::Toolkit::GetImpl(self).mAnchorActors.size();
+  return Toolkit::GetImpl(self).GetTextController();
 }
 
-Accessibility::Hyperlink* TextEditor::TextEditorAccessible::GetLink(int32_t linkIndex) const
+void TextEditor::TextEditorAccessible::RequestTextRelayout()
 {
-  if(linkIndex < 0 || linkIndex >= GetLinkCount())
-  {
-    return nullptr;
-  }
-  auto self        = Toolkit::TextEditor::DownCast(Self());
-  auto anchorActor = Dali::Toolkit::GetImpl(self).mAnchorActors[linkIndex];
-  return dynamic_cast<Accessibility::Hyperlink*>(Dali::Accessibility::Accessible::Get(anchorActor));
-}
+  auto  self     = Toolkit::TextEditor::DownCast(Self());
+  auto& selfImpl = Toolkit::GetImpl(self);
 
-int32_t TextEditor::TextEditorAccessible::GetLinkIndex(int32_t characterOffset) const
-{
-  auto self       = Toolkit::TextEditor::DownCast(Self());
-  auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
-  return controller->GetAnchorIndex(static_cast<size_t>(characterOffset));
+  selfImpl.RequestTextRelayout();
 }
 
 } // namespace Internal
index e72f19e..de10dd4 100644 (file)
@@ -32,6 +32,7 @@
 #include <dali-toolkit/devel-api/controls/scroll-bar/scroll-bar.h>
 #include <dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h>
 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
+#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
 #include <dali-toolkit/internal/text/decorator/text-decorator.h>
 #include <dali-toolkit/internal/text/rendering/text-renderer.h>
 #include <dali-toolkit/internal/text/text-anchor-control-interface.h>
@@ -577,107 +578,31 @@ private: // Data
   /**
    * @brief This structure is to connect TextEditor with Accessible functions.
    */
-  class TextEditorAccessible : public DevelControl::ControlAccessible,
-                               public virtual Dali::Accessibility::EditableText,
-                               public virtual Dali::Accessibility::Hypertext
+  class TextEditorAccessible : public EditableTextControlAccessible
   {
   public:
-    using DevelControl::ControlAccessible::ControlAccessible;
+    using EditableTextControlAccessible::EditableTextControlAccessible;
 
     /**
      * @copydoc Dali::Accessibility::Accessible::GetName()
      */
     std::string GetName() const override;
 
+  protected:
     /**
-     * @copydoc Dali::Accessibility::Text::GetText()
+     * @copydoc Dali::Toolkit::Internal::TextControlAccessible::GetTextAnchors()
      */
-    std::string GetText(size_t startOffset, size_t endOffset) const override;
+    const std::vector<Toolkit::TextAnchor>& GetTextAnchors() const override;
 
     /**
-     * @copydoc Dali::Accessibility::Text::GetCharacterCount()
+     * @copydoc Dali::Toolkit::Internal::TextControlAccessible::GetTextController()
      */
-    size_t GetCharacterCount() const override;
+    Toolkit::Text::ControllerPtr GetTextController() const override;
 
     /**
-     * @copydoc Dali::Accessibility::Text::GetCursorOffset()
+     * @copydoc Dali::Toolkit::Internal::EditableTextControlAccessible::RequestTextRelayout()
      */
-    size_t GetCursorOffset() const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::SetCursorOffset()
-     */
-    bool SetCursorOffset(size_t offset) override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetTextAtOffset()
-     */
-    Accessibility::Range GetTextAtOffset(size_t offset, Accessibility::TextBoundary boundary) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetRangeOfSelection()
-     */
-    Accessibility::Range GetRangeOfSelection(size_t selectionIndex) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::RemoveSelection()
-     */
-    bool RemoveSelection(size_t selectionIndex) override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::SetRangeOfSelection()
-     */
-    bool SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset) override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetRangeExtents()
-     */
-    Rect<> GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type) override;
-
-    /**
-     * @copydoc Dali::Accessibility::EditableText::CopyText()
-     */
-    bool CopyText(size_t startPosition, size_t endPosition) override;
-
-    /**
-     * @copydoc Dali::Accessibility::EditableText::CutText()
-     */
-    bool CutText(size_t startPosition, size_t endPosition) override;
-
-    /**
-     * @copydoc Dali::Accessibility::Accessible::GetStates()
-     */
-    Accessibility::States CalculateStates() override;
-
-    /**
-     * @copydoc Dali::Accessibility::EditableText::InsertText()
-     */
-    bool InsertText(size_t startPosition, std::string text) override;
-
-    /**
-     * @copydoc Dali::Accessibility::EditableText::SetTextContents()
-     */
-    bool SetTextContents(std::string newContents) override;
-
-    /**
-     * @copydoc Dali::Accessibility::EditableText::DeleteText()
-     */
-    bool DeleteText(size_t startPosition, size_t endPosition) override;
-
-    /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLink()
-     */
-    Accessibility::Hyperlink* GetLink(int32_t linkIndex) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLinkIndex()
-     */
-    int32_t GetLinkIndex(int32_t characterOffset) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLinkCount()
-     */
-    int32_t GetLinkCount() const override;
+    void RequestTextRelayout() override;
   };
 };
 
index c48f814..8effb28 100644 (file)
@@ -33,7 +33,6 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/controls/text-controls/text-field-devel.h>
-#include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
 #include <dali-toolkit/devel-api/text/rendering-backend.h>
 #include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
 #include <dali-toolkit/internal/controls/text-controls/text-field-property-handler.h>
@@ -206,28 +205,6 @@ Toolkit::TextField::InputStyle::Mask ConvertInputStyle(Text::InputStyle::Mask in
   return fieldInputStyleMask;
 }
 
-bool IsHiddenInput(Toolkit::TextField textField)
-{
-  Property::Map hiddenInputSettings = textField.GetProperty<Property::Map>(Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS);
-  auto          mode                = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::MODE);
-  if(mode && (mode->Get<int>() != Toolkit::HiddenInput::Mode::HIDE_NONE))
-  {
-    return true;
-  }
-  return false;
-}
-
-char GetSubstituteCharacter(Toolkit::TextField textField)
-{
-  Property::Map hiddenInputSettings = textField.GetProperty<Property::Map>(Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS);
-  auto          substChar           = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::SUBSTITUTE_CHARACTER);
-  if(substChar)
-  {
-    return static_cast<char>(substChar->Get<int>());
-  }
-  return STAR;
-}
-
 } // namespace
 
 Toolkit::TextField TextField::New()
@@ -1193,338 +1170,57 @@ Vector<Vector2> TextField::GetTextPosition(const uint32_t startIndex, const uint
 
 std::string TextField::TextFieldAccessible::GetName() const
 {
-  auto self = Toolkit::TextField::DownCast(Self());
-  if(IsHiddenInput(self))
-  {
-    return {};
-  }
-
-  return self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-}
-
-std::string TextField::TextFieldAccessible::GetText(size_t startOffset, size_t endOffset) const
-{
-  if(endOffset <= startOffset)
+  if(IsHiddenInput())
   {
     return {};
   }
 
-  auto self = Toolkit::TextField::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-
-  if(startOffset > text.size() || endOffset > text.size())
-  {
-    return {};
-  }
-  if(IsHiddenInput(self))
-  {
-    return std::string(endOffset - startOffset, GetSubstituteCharacter(self));
-  }
-  return text.substr(startOffset, endOffset - startOffset);
+  return GetWholeText();
 }
 
-size_t TextField::TextFieldAccessible::GetCharacterCount() const
+const std::vector<Toolkit::TextAnchor>& TextField::TextFieldAccessible::GetTextAnchors() const
 {
   auto self = Toolkit::TextField::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
 
-  return text.size();
+  return Toolkit::GetImpl(self).mAnchorActors;
 }
 
-size_t TextField::TextFieldAccessible::GetCursorOffset() const
+Toolkit::Text::ControllerPtr TextField::TextFieldAccessible::GetTextController() const
 {
   auto self = Toolkit::TextField::DownCast(Self());
-  return Dali::Toolkit::GetImpl(self).GetTextController()->GetCursorPosition();
-}
 
-bool TextField::TextFieldAccessible::SetCursorOffset(size_t offset)
-{
-  auto self = Toolkit::TextField::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-  if(offset > text.size())
-  {
-    return false;
-  }
-
-  auto& selfImpl = Dali::Toolkit::GetImpl(self);
-  selfImpl.GetTextController()->ResetCursorPosition(offset);
-  selfImpl.RequestTextRelayout();
-
-  return true;
+  return Toolkit::GetImpl(self).GetTextController();
 }
 
-Dali::Accessibility::Range TextField::TextFieldAccessible::GetTextAtOffset(
-  size_t offset, Dali::Accessibility::TextBoundary boundary) const
+std::uint32_t TextField::TextFieldAccessible::GetSubstituteCharacter() const
 {
-  auto self  = Toolkit::TextField::DownCast(Self());
-  auto range = Dali::Accessibility::Range{};
-
-  if(IsHiddenInput(self))
-  {
-    // Returning empty object, as there is no possibility to parse the textfield
-    // when its content is hidden.
-    return range;
-  }
-
-  auto text     = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-  auto textSize = text.size();
-
-  switch(boundary)
-  {
-    case Dali::Accessibility::TextBoundary::CHARACTER:
-    {
-      if(offset < textSize)
-      {
-        range.content     = text[offset];
-        range.startOffset = offset;
-        range.endOffset   = offset + 1;
-      }
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::WORD:
-    case Dali::Accessibility::TextBoundary::LINE:
-    {
-      auto textString = text.c_str();
-      auto breaks     = std::vector<char>(textSize, 0);
-
-      if(boundary == Dali::Accessibility::TextBoundary::WORD)
-      {
-        Accessibility::Accessible::FindWordSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
-      }
-      else
-      {
-        Accessibility::Accessible::FindLineSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
-      }
-
-      auto index   = 0u;
-      auto counter = 0u;
-      while(index < textSize && counter <= offset)
-      {
-        auto start = index;
-        if(breaks[index])
-        {
-          while(breaks[index])
-          {
-            index++;
-          }
-          counter++;
-        }
-        else
-        {
-          if(boundary == Dali::Accessibility::TextBoundary::WORD)
-          {
-            index++;
-          }
-          if(boundary == Dali::Accessibility::TextBoundary::LINE)
-          {
-            counter++;
-          }
-        }
-
-        if((counter > 0) && ((counter - 1) == offset))
-        {
-          range.content     = text.substr(start, index - start + 1);
-          range.startOffset = start;
-          range.endOffset   = index + 1;
-        }
-
-        if(boundary == Dali::Accessibility::TextBoundary::LINE)
-        {
-          index++;
-        }
-      }
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::SENTENCE:
-    {
-      /* not supported by default */
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::PARAGRAPH:
-    {
-      /* Paragraph is not supported by libunibreak library */
-      break;
-    }
-    default:
-      break;
-  }
-
-  return range;
-}
-
-Dali::Accessibility::Range TextField::TextFieldAccessible::GetRangeOfSelection(size_t selectionIndex) const
-{
-  // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionIndex > 0)
-  {
-    return {};
-  }
-
-  auto self       = Toolkit::TextField::DownCast(Self());
-  auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
-  auto indices    = controller->GetSelectionIndexes();
-
-  auto startOffset = static_cast<size_t>(indices.first);
-  auto endOffset   = static_cast<size_t>(indices.second);
-
-  if(IsHiddenInput(self))
-  {
-    return {startOffset, endOffset, std::string(endOffset - startOffset, GetSubstituteCharacter(self))};
-  }
-
-  std::string value{};
-  controller->RetrieveSelection(value);
-  return {startOffset, endOffset, value};
-}
+  auto self                = Toolkit::TextField::DownCast(Self());
+  auto hiddenInputSettings = self.GetProperty<Property::Map>(Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS);
+  auto substChar           = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::SUBSTITUTE_CHARACTER);
 
-bool TextField::TextFieldAccessible::RemoveSelection(size_t selectionIndex)
-{
-  // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionIndex > 0)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextField::DownCast(Self());
-  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(0, 0);
-  return true;
-}
-
-bool TextField::TextFieldAccessible::SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset)
-{
-  // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionIndex > 0)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextField::DownCast(Self());
-  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(startOffset, endOffset);
-  return true;
-}
-
-Rect<> TextField::TextFieldAccessible::GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type)
-{
-  if (endOffset <= startOffset || endOffset <= 0)
-  {
-    return {0, 0, 0, 0};
-  }
-
-  auto self = Toolkit::TextField::DownCast(Self());
-  auto rect = Dali::Toolkit::GetImpl(self).GetTextController()->GetTextBoundingRectangle(startOffset, endOffset - 1);
-
-  auto componentExtents = this->GetExtents(type);
-
-  rect.x += componentExtents.x;
-  rect.y += componentExtents.y;
-
-  return rect;
-}
-
-bool TextField::TextFieldAccessible::CopyText(size_t startPosition, size_t endPosition)
-{
-  if(endPosition <= startPosition)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextField::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-  Dali::Toolkit::GetImpl(self).GetTextController()->CopyStringToClipboard(text.substr(startPosition, endPosition - startPosition));
-
-  return true;
-}
-
-bool TextField::TextFieldAccessible::CutText(size_t startPosition, size_t endPosition)
-{
-  if(endPosition <= startPosition)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextField::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-  Dali::Toolkit::GetImpl(self).GetTextController()->CopyStringToClipboard(text.substr(startPosition, endPosition - startPosition));
-
-  self.SetProperty(Toolkit::TextField::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition));
-
-  return true;
-}
-
-bool TextField::TextFieldAccessible::DeleteText(size_t startPosition, size_t endPosition)
-{
-  if(endPosition <= startPosition)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextField::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-
-  self.SetProperty(Toolkit::TextField::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition));
-
-  return true;
-}
-
-Dali::Accessibility::States TextField::TextFieldAccessible::CalculateStates()
-{
-  using namespace Dali::Accessibility;
-
-  auto states = DevelControl::ControlAccessible::CalculateStates();
-
-  states[State::EDITABLE]  = true;
-  states[State::FOCUSABLE] = true;
-
-  Toolkit::Control focusControl = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl();
-  if(Self() == focusControl)
+  if(substChar)
   {
-    states[State::FOCUSED] = true;
+    return static_cast<std::uint32_t>(substChar->Get<int>());
   }
 
-  return states;
-}
-
-bool TextField::TextFieldAccessible::InsertText(size_t startPosition, std::string text)
-{
-  auto self         = Toolkit::TextField::DownCast(Self());
-  auto insertedText = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-
-  insertedText.insert(startPosition, text);
-
-  self.SetProperty(Toolkit::TextField::Property::TEXT, std::move(insertedText));
-
-  return true;
+  return TextControlAccessible::GetSubstituteCharacter();
 }
 
-bool TextField::TextFieldAccessible::SetTextContents(std::string newContents)
+bool TextField::TextFieldAccessible::IsHiddenInput() const
 {
-  auto self = Toolkit::TextField::DownCast(Self());
-  self.SetProperty(Toolkit::TextField::Property::TEXT, std::move(newContents));
-  return true;
-}
+  auto self                = Toolkit::TextField::DownCast(Self());
+  auto hiddenInputSettings = self.GetProperty<Property::Map>(Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS);
+  auto mode                = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::MODE);
 
-int32_t TextField::TextFieldAccessible::GetLinkCount() const
-{
-  auto self = Toolkit::TextField::DownCast(Self());
-  return Dali::Toolkit::GetImpl(self).mAnchorActors.size();
+  return (mode && (mode->Get<int>() != Toolkit::HiddenInput::Mode::HIDE_NONE));
 }
 
-Accessibility::Hyperlink* TextField::TextFieldAccessible::GetLink(int32_t linkIndex) const
+void TextField::TextFieldAccessible::RequestTextRelayout()
 {
-  if(linkIndex < 0 || linkIndex >= GetLinkCount())
-  {
-    return nullptr;
-  }
-  auto self        = Toolkit::TextField::DownCast(Self());
-  auto anchorActor = Dali::Toolkit::GetImpl(self).mAnchorActors[linkIndex];
-  return dynamic_cast<Accessibility::Hyperlink*>(Dali::Accessibility::Accessible::Get(anchorActor));
-}
+  auto  self     = Toolkit::TextField::DownCast(Self());
+  auto& selfImpl = Toolkit::GetImpl(self);
 
-int32_t TextField::TextFieldAccessible::GetLinkIndex(int32_t characterOffset) const
-{
-  auto self       = Toolkit::TextField::DownCast(Self());
-  auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
-  return controller->GetAnchorIndex(static_cast<size_t>(characterOffset));
+  selfImpl.RequestTextRelayout();
 }
 
 } // namespace Internal
index 47783e3..223fa71 100644 (file)
@@ -29,6 +29,7 @@
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/controls/text-controls/text-field-devel.h>
 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
+#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
 #include <dali-toolkit/internal/text/decorator/text-decorator.h>
 #include <dali-toolkit/internal/text/rendering/text-renderer.h>
 #include <dali-toolkit/internal/text/text-anchor-control-interface.h>
@@ -526,107 +527,41 @@ protected:
   /**
    * @brief This structure is to connect TextField with Accessible functions.
    */
-  class TextFieldAccessible : public DevelControl::ControlAccessible,
-                              public virtual Dali::Accessibility::EditableText,
-                              public virtual Dali::Accessibility::Hypertext
+  class TextFieldAccessible : public EditableTextControlAccessible
   {
   public:
-    using DevelControl::ControlAccessible::ControlAccessible;
+    using EditableTextControlAccessible::EditableTextControlAccessible;
 
     /**
      * @copydoc Dali::Accessibility::Accessible::GetName()
      */
     std::string GetName() const override;
 
+  protected:
     /**
-     * @copydoc Dali::Accessibility::Text::GetText()
+     * @copydoc Dali::Toolkit::Internal::TextControlAccessible::GetTextAnchors()
      */
-    std::string GetText(size_t startOffset, size_t endOffset) const override;
+    const std::vector<Toolkit::TextAnchor>& GetTextAnchors() const override;
 
     /**
-     * @copydoc Dali::Accessibility::Text::GetCharacterCount()
+     * @copydoc Dali::Toolkit::Internal::TextControlAccessible::GetTextController()
      */
-    size_t GetCharacterCount() const override;
+    Toolkit::Text::ControllerPtr GetTextController() const override;
 
     /**
-     * @copydoc Dali::Accessibility::Text::GetCursorOffset()
+     * @copydoc Dali::Toolkit::Internal::TextControlAccessible::GetSubstituteCharacter()
      */
-    size_t GetCursorOffset() const override;
+    std::uint32_t GetSubstituteCharacter() const override;
 
     /**
-     * @copydoc Dali::Accessibility::Text::SetCursorOffset()
+     * @copydoc Dali::Toolkit::Internal::TextControlAccessible::IsHiddenInput()
      */
-    bool SetCursorOffset(size_t offset) override;
+    bool IsHiddenInput() const override;
 
     /**
-     * @copydoc Dali::Accessibility::Text::GetTextAtOffset()
+     * @copydoc Dali::Toolkit::Internal::EditableTextControlAccessible::RequestTextRelayout()
      */
-    Accessibility::Range GetTextAtOffset(size_t offset, Accessibility::TextBoundary boundary) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetRangeOfSelection()
-     */
-    Accessibility::Range GetRangeOfSelection(size_t selectionIndex) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::RemoveSelection()
-     */
-    bool RemoveSelection(size_t selectionIndex) override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::SetRangeOfSelection()
-     */
-    bool SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset) override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetRangeExtents()
-     */
-    Rect<> GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type) override;
-
-    /**
-     * @copydoc Dali::Accessibility::EditableText::CopyText()
-     */
-    bool CopyText(size_t startPosition, size_t endPosition) override;
-
-    /**
-     * @copydoc Dali::Accessibility::EditableText::CutText()
-     */
-    bool CutText(size_t startPosition, size_t endPosition) override;
-
-    /**
-     * @copydoc Dali::Accessibility::Accessible::GetStates()
-     */
-    Accessibility::States CalculateStates() override;
-
-    /**
-     * @copydoc Dali::Accessibility::EditableText::InsertText()
-     */
-    bool InsertText(size_t startPosition, std::string text) override;
-
-    /**
-     * @copydoc Dali::Accessibility::EditableText::SetTextContents()
-     */
-    bool SetTextContents(std::string newContents) override;
-
-    /**
-     * @copydoc Dali::Accessibility::EditableText::DeleteText()
-     */
-    bool DeleteText(size_t startPosition, size_t endPosition) override;
-
-    /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLink()
-     */
-    Accessibility::Hyperlink* GetLink(int32_t linkIndex) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLinkIndex()
-     */
-    int32_t GetLinkIndex(int32_t characterOffset) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLinkCount()
-     */
-    int32_t GetLinkCount() const override;
+    void RequestTextRelayout() override;
   };
 };
 
index ee4ce64..21a0285 100644 (file)
@@ -1199,8 +1199,7 @@ Vector<Vector2> TextLabel::GetTextPosition(const uint32_t startIndex, const uint
 
 std::string TextLabel::TextLabelAccessible::GetNameRaw() const
 {
-  auto self = Toolkit::TextLabel::DownCast(Self());
-  return self.GetProperty(Toolkit::TextLabel::Property::TEXT).Get<std::string>();
+  return GetWholeText();
 }
 
 Property::Index TextLabel::TextLabelAccessible::GetNamePropertyIndex()
@@ -1208,216 +1207,18 @@ Property::Index TextLabel::TextLabelAccessible::GetNamePropertyIndex()
   return Toolkit::TextLabel::Property::TEXT;
 }
 
-std::string TextLabel::TextLabelAccessible::GetText(size_t startOffset, size_t endOffset) const
+const std::vector<Toolkit::TextAnchor>& TextLabel::TextLabelAccessible::GetTextAnchors() const
 {
-  if(endOffset <= startOffset)
-  {
-    return {};
-  }
-
   auto self = Toolkit::TextLabel::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextLabel::Property::TEXT).Get<std::string>();
-
-  if(startOffset > text.size() || endOffset > text.size())
-  {
-    return {};
-  }
 
-  return text.substr(startOffset, endOffset - startOffset);
+  return Toolkit::GetImpl(self).mAnchorActors;
 }
 
-size_t TextLabel::TextLabelAccessible::GetCharacterCount() const
+Toolkit::Text::ControllerPtr TextLabel::TextLabelAccessible::GetTextController() const
 {
   auto self = Toolkit::TextLabel::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextLabel::Property::TEXT).Get<std::string>();
 
-  return text.size();
-}
-
-size_t TextLabel::TextLabelAccessible::GetCursorOffset() const
-{
-  return {};
-}
-
-bool TextLabel::TextLabelAccessible::SetCursorOffset(size_t offset)
-{
-  return {};
-}
-
-Dali::Accessibility::Range TextLabel::TextLabelAccessible::GetTextAtOffset(size_t offset, Dali::Accessibility::TextBoundary boundary) const
-{
-  auto self     = Toolkit::TextLabel::DownCast(Self());
-  auto text     = self.GetProperty(Toolkit::TextLabel::Property::TEXT).Get<std::string>();
-  auto textSize = text.size();
-
-  auto range = Dali::Accessibility::Range{};
-
-  switch(boundary)
-  {
-    case Dali::Accessibility::TextBoundary::CHARACTER:
-    {
-      if(offset < textSize)
-      {
-        range.content     = text[offset];
-        range.startOffset = offset;
-        range.endOffset   = offset + 1;
-      }
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::WORD:
-    case Dali::Accessibility::TextBoundary::LINE:
-    {
-      auto textString = text.c_str();
-      auto breaks     = std::vector<char>(textSize, 0);
-
-      if(boundary == Dali::Accessibility::TextBoundary::WORD)
-      {
-        Accessibility::Accessible::FindWordSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
-      }
-      else
-      {
-        Accessibility::Accessible::FindLineSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
-      }
-
-      auto index   = 0u;
-      auto counter = 0u;
-      while(index < textSize && counter <= offset)
-      {
-        auto start = index;
-        if(breaks[index])
-        {
-          while(breaks[index])
-          {
-            index++;
-          }
-          counter++;
-        }
-        else
-        {
-          if(boundary == Dali::Accessibility::TextBoundary::WORD)
-          {
-            index++;
-          }
-          if(boundary == Dali::Accessibility::TextBoundary::LINE)
-          {
-            counter++;
-          }
-        }
-
-        if((counter > 0) && ((counter - 1) == offset))
-        {
-          range.content     = text.substr(start, index - start + 1);
-          range.startOffset = start;
-          range.endOffset   = index + 1;
-        }
-
-        if(boundary == Dali::Accessibility::TextBoundary::LINE)
-        {
-          index++;
-        }
-      }
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::SENTENCE:
-    {
-      /* not supported by default */
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::PARAGRAPH:
-    {
-      /* Paragraph is not supported by libunibreak library */
-      break;
-    }
-    default:
-      break;
-  }
-
-  return range;
-}
-
-Dali::Accessibility::Range TextLabel::TextLabelAccessible::GetRangeOfSelection(size_t selectionIndex) const
-{
-  // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionIndex > 0)
-  {
-    return {};
-  }
-
-  auto        self       = Toolkit::TextLabel::DownCast(Self());
-  auto        controller = Dali::Toolkit::GetImpl(self).GetTextController();
-  std::string value{};
-  controller->RetrieveSelection(value);
-  auto indices = controller->GetSelectionIndexes();
-
-  return {static_cast<size_t>(indices.first), static_cast<size_t>(indices.second), value};
-}
-
-bool TextLabel::TextLabelAccessible::RemoveSelection(size_t selectionIndex)
-{
-  // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionIndex > 0)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextLabel::DownCast(Self());
-  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(0, 0);
-  return true;
-}
-
-bool TextLabel::TextLabelAccessible::SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset)
-{
-  // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionIndex > 0)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextLabel::DownCast(Self());
-  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(startOffset, endOffset);
-  return true;
-}
-
-Rect<> TextLabel::TextLabelAccessible::GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type)
-{
-  if (endOffset <= startOffset || endOffset <= 0)
-  {
-    return {0, 0, 0, 0};
-  }
-
-  auto self = Toolkit::TextLabel::DownCast(Self());
-  auto rect = Dali::Toolkit::GetImpl(self).GetTextController()->GetTextBoundingRectangle(startOffset, endOffset - 1);
-
-  auto componentExtents = this->GetExtents(type);
-
-  rect.x += componentExtents.x;
-  rect.y += componentExtents.y;
-
-  return rect;
-}
-
-int32_t TextLabel::TextLabelAccessible::GetLinkCount() const
-{
-  auto self = Toolkit::TextLabel::DownCast(Self());
-  return Dali::Toolkit::GetImpl(self).mAnchorActors.size();
-}
-
-Accessibility::Hyperlink* TextLabel::TextLabelAccessible::GetLink(int32_t linkIndex) const
-{
-  if(linkIndex < 0 || linkIndex >= GetLinkCount())
-  {
-    return nullptr;
-  }
-  auto self        = Toolkit::TextLabel::DownCast(Self());
-  auto anchorActor = Dali::Toolkit::GetImpl(self).mAnchorActors[linkIndex];
-  return dynamic_cast<Accessibility::Hyperlink*>(Dali::Accessibility::Accessible::Get(anchorActor));
-}
-
-int32_t TextLabel::TextLabelAccessible::GetLinkIndex(int32_t characterOffset) const
-{
-  auto self       = Toolkit::TextLabel::DownCast(Self());
-  auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
-  return controller->GetAnchorIndex(static_cast<size_t>(characterOffset));
+  return Toolkit::GetImpl(self).GetTextController();
 }
 
 } // namespace Internal
index 4c2ca97..fb78d60 100644 (file)
@@ -25,6 +25,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
+#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
 #include <dali-toolkit/internal/text/rendering/text-renderer.h>
 #include <dali-toolkit/internal/text/text-anchor-control-interface.h>
 #include <dali-toolkit/internal/text/text-control-interface.h>
@@ -246,57 +247,10 @@ protected:
   /**
    * @brief This structure is to connect TextLabel with Accessible functions.
    */
-  class TextLabelAccessible : public DevelControl::ControlAccessible,
-                              public virtual Dali::Accessibility::Text,
-                              public virtual Dali::Accessibility::Hypertext
+  class TextLabelAccessible : public TextControlAccessible
   {
   public:
-    using DevelControl::ControlAccessible::ControlAccessible;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetText()
-     */
-    std::string GetText(size_t startOffset, size_t endOffset) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetCharacterCount()
-     */
-    size_t GetCharacterCount() const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetCursorOffset()
-     */
-    size_t GetCursorOffset() const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::SetCursorOffset()
-     */
-    bool SetCursorOffset(size_t offset) override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetTextAtOffset()
-     */
-    Accessibility::Range GetTextAtOffset(size_t offset, Accessibility::TextBoundary boundary) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetRangeOfSelection()
-     */
-    Accessibility::Range GetRangeOfSelection(size_t selectionIndex) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::RemoveSelection()
-     */
-    bool RemoveSelection(size_t selectionIndex) override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::SetRangeOfSelection()
-     */
-    bool SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset) override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetRangeExtents()
-     */
-    Rect<> GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type) override;
+    using TextControlAccessible::TextControlAccessible;
 
     /**
      * @copydoc Dali::Accessibility::Text::GetNameRaw()
@@ -308,20 +262,16 @@ protected:
      */
     Property::Index GetNamePropertyIndex() override;
 
+  protected:
     /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLink()
-     */
-    Accessibility::Hyperlink* GetLink(int32_t linkIndex) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLinkIndex()
+     * @copydoc Dali::Toolkit::Internal::TextControlAccessible::GetTextAnchors()
      */
-    int32_t GetLinkIndex(int32_t characterOffset) const override;
+    const std::vector<Toolkit::TextAnchor>& GetTextAnchors() const override;
 
     /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLinkCount()
+     * @copydoc Dali::Toolkit::Internal::TextControlAccessible::GetTextController()
      */
-    int32_t GetLinkCount() const override;
+    Toolkit::Text::ControllerPtr GetTextController() const override;
   };
 };