Merge "Makes the LTR/RTL alignment of text follow the system language by default...
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / text-controls / text-field-impl.cpp
index 9ad7a84..f98093e 100644 (file)
@@ -21,7 +21,6 @@
 // EXTERNAL INCLUDES
 #include <dali/devel-api/actors/actor-devel.h>
 #include <dali/devel-api/adaptor-framework/key-devel.h>
-#include <dali/devel-api/adaptor-framework/window-devel.h>
 #include <dali/devel-api/common/stage.h>
 #include <dali/devel-api/object/property-helper-devel.h>
 #include <dali/integration-api/debug.h>
@@ -137,10 +136,14 @@ DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "selectedTextEnd"
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "enableEditing",                    BOOLEAN,   ENABLE_EDITING                      )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "fontSizeScale",                    FLOAT,     FONT_SIZE_SCALE                     )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "primaryCursorPosition",            INTEGER,   PRIMARY_CURSOR_POSITION             )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "grabHandleColor",                  VECTOR4,   GRAB_HANDLE_COLOR                   )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "inputFilter",                      MAP,       INPUT_FILTER                        )
 
 DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "textChanged",       SIGNAL_TEXT_CHANGED       )
 DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "maxLengthReached",  SIGNAL_MAX_LENGTH_REACHED )
 DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "inputStyleChanged", SIGNAL_INPUT_STYLE_CHANGED)
+DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "anchorClicked",     SIGNAL_ANCHOR_CLICKED     )
+DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "inputFiltered",     SIGNAL_INPUT_FILTERED     )
 
 DALI_TYPE_REGISTRATION_END()
 // clang-format on
@@ -692,7 +695,7 @@ void TextField::SetProperty(BaseObject* object, Property::Index index, const Pro
       }
       case Toolkit::DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION:
       {
-        impl.mController->SetMatchSystemLanguageDirection(value.Get<bool>());
+        impl.mController->SetMatchLayoutDirection(value.Get<bool>() ? DevelText::MatchLayoutDirection::LOCALE : DevelText::MatchLayoutDirection::CONTENTS);
         break;
       }
       case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP:
@@ -754,6 +757,24 @@ void TextField::SetProperty(BaseObject* object, Property::Index index, const Pro
         }
         break;
       }
+      case Toolkit::DevelTextField::Property::GRAB_HANDLE_COLOR:
+      {
+        const Vector4 color = value.Get<Vector4>();
+        DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p GRAB_HANDLE_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a);
+
+        impl.mDecorator->SetHandleColor(color);
+        impl.RequestTextRelayout();
+        break;
+      }
+      case Toolkit::DevelTextField::Property::INPUT_FILTER:
+      {
+        const Property::Map* map = value.GetMap();
+        if(map)
+        {
+          impl.mController->SetInputFilterOption(*map);
+        }
+        break;
+      }
     } // switch
   }   // textfield
 }
@@ -1059,7 +1080,7 @@ Property::Value TextField::GetProperty(BaseObject* object, Property::Index index
       }
       case Toolkit::DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION:
       {
-        value = impl.mController->IsMatchSystemLanguageDirection();
+        value = impl.mController->GetMatchLayoutDirection() != DevelText::MatchLayoutDirection::CONTENTS;
         break;
       }
       case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP:
@@ -1104,6 +1125,18 @@ Property::Value TextField::GetProperty(BaseObject* object, Property::Index index
         value = static_cast<int>(impl.mController->GetPrimaryCursorPosition());
         break;
       }
+      case Toolkit::DevelTextField::Property::GRAB_HANDLE_COLOR:
+      {
+        value = impl.mDecorator->GetHandleColor();
+        break;
+      }
+      case Toolkit::DevelTextField::Property::INPUT_FILTER:
+      {
+        Property::Map map;
+        impl.mController->GetInputFilterOption(map);
+        value = map;
+        break;
+      }
     } //switch
   }
 
@@ -1180,6 +1213,22 @@ bool TextField::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface*
   {
     field.InputStyleChangedSignal().Connect(tracker, functor);
   }
+  else if(0 == strcmp(signalName.c_str(), SIGNAL_ANCHOR_CLICKED))
+  {
+    if(field)
+    {
+      Internal::TextField& fieldImpl(GetImpl(field));
+      fieldImpl.AnchorClickedSignal().Connect(tracker, functor);
+    }
+  }
+  else if(0 == strcmp(signalName.c_str(), SIGNAL_INPUT_FILTERED))
+  {
+    if(field)
+    {
+      Internal::TextField& fieldImpl(GetImpl(field));
+      fieldImpl.InputFilteredSignal().Connect(tracker, functor);
+    }
+  }
   else
   {
     // signalName does not match any signal
@@ -1204,11 +1253,21 @@ Toolkit::TextField::InputStyleChangedSignalType& TextField::InputStyleChangedSig
   return mInputStyleChangedSignal;
 }
 
+DevelTextField::AnchorClickedSignalType& TextField::AnchorClickedSignal()
+{
+  return mAnchorClickedSignal;
+}
+
+DevelTextField::InputFilteredSignalType& TextField::InputFilteredSignal()
+{
+  return mInputFilteredSignal;
+}
+
 void TextField::OnInitialize()
 {
   Actor self = Self();
 
-  mController = Text::Controller::New(this, this, this);
+  mController = Text::Controller::New(this, 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;
@@ -1241,6 +1300,8 @@ void TextField::OnInitialize()
   Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(stage.GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
   mController->SetLayoutDirection(layoutDirection);
 
+  self.LayoutDirectionChangedSignal().Connect(this, &TextField::OnLayoutDirectionChanged);
+
   // Forward input events to controller
   EnableGestureDetection(static_cast<GestureType::Value>(GestureType::TAP | GestureType::PAN | GestureType::LONG_PRESS));
   GetTapGestureDetector().SetMaximumTapsRequired(2);
@@ -1335,7 +1396,7 @@ float TextField::GetHeightForWidth(float width)
 
 void TextField::ResizeActor(Actor& actor, const Vector2& size)
 {
-  if (actor.GetProperty<Vector3>(Dali::Actor::Property::SIZE).GetVectorXY() != size)
+  if(actor.GetProperty<Vector3>(Dali::Actor::Property::SIZE).GetVectorXY() != size)
   {
     actor.SetProperty(Actor::Property::SIZE, size);
   }
@@ -1353,15 +1414,8 @@ void TextField::OnRelayout(const Vector2& size, RelayoutContainer& container)
   Vector2 contentSize(size.x - (padding.start + padding.end), size.y - (padding.top + padding.bottom));
 
   // Support Right-To-Left of padding
-  Dali::LayoutDirection::Type layoutDirection;
-  if(mController->IsMatchSystemLanguageDirection())
-  {
-    layoutDirection = static_cast<Dali::LayoutDirection::Type>(DevelWindow::Get(self).GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
-  }
-  else
-  {
-    layoutDirection = static_cast<Dali::LayoutDirection::Type>(self.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
-  }
+  Dali::LayoutDirection::Type layoutDirection = mController->GetLayoutDirection(self);
+
   if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
   {
     std::swap(padding.start, padding.end);
@@ -1378,6 +1432,12 @@ void TextField::OnRelayout(const Vector2& size, RelayoutContainer& container)
     ResizeActor(mActiveLayer, contentSize);
   }
 
+  // If there is text changed, callback is called.
+  if(mTextChanged)
+  {
+    EmitTextChangedSignal();
+  }
+
   const Text::Controller::UpdateTextType updateTextType = mController->Relayout(contentSize, layoutDirection);
 
   if((Text::Controller::NONE_UPDATED != updateTextType) ||
@@ -1419,7 +1479,7 @@ void TextField::OnRelayout(const Vector2& size, RelayoutContainer& container)
   }
 }
 
-Text::ControllerPtr TextField::getController()
+Text::ControllerPtr TextField::GetTextController()
 {
   return mController;
 }
@@ -1598,6 +1658,7 @@ void TextField::OnTap(const TapGesture& gesture)
   padding                   = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
   const Vector2& localPoint = gesture.GetLocalPoint();
   mController->TapEvent(gesture.GetNumberOfTaps(), localPoint.x - padding.start, localPoint.y - padding.top);
+  mController->AnchorEvent(localPoint.x - padding.start, localPoint.y - padding.top);
 
   SetKeyInputFocus();
 }
@@ -1679,18 +1740,31 @@ void TextField::TextDeleted(unsigned int position, unsigned int length, const st
   }
 }
 
-void TextField::CaretMoved(unsigned int position)
+void TextField::CursorMoved(unsigned int position)
 {
   if(Accessibility::IsUp())
   {
-    Control::Impl::GetAccessibilityObject(Self())->EmitTextCaretMoved(position);
+    Control::Impl::GetAccessibilityObject(Self())->EmitTextCursorMoved(position);
   }
 }
 
-void TextField::TextChanged()
+void TextField::TextChanged(bool immediate)
+{
+  if(immediate) // Emits TextChangedSignal immediately
+  {
+    EmitTextChangedSignal();
+  }
+  else
+  {
+    mTextChanged = true;
+  }
+}
+
+void TextField::EmitTextChangedSignal()
 {
   Dali::Toolkit::TextField handle(GetOwner());
   mTextChangedSignal.Emit(handle);
+  mTextChanged = false;
 }
 
 void TextField::MaxLengthReached()
@@ -1749,6 +1823,18 @@ void TextField::InputStyleChanged(Text::InputStyle::Mask inputStyleMask)
   mInputStyleChangedSignal.Emit(handle, fieldInputStyleMask);
 }
 
+void TextField::AnchorClicked(const std::string& href)
+{
+  Dali::Toolkit::TextField handle(GetOwner());
+  mAnchorClickedSignal.Emit(handle, href.c_str(), href.length());
+}
+
+void TextField::InputFiltered(Toolkit::InputFilter::Property::Type type)
+{
+  Dali::Toolkit::TextField handle(GetOwner());
+  mInputFilteredSignal.Emit(handle, type);
+}
+
 void TextField::AddDecoration(Actor& actor, bool needsClipping)
 {
   if(actor)
@@ -1767,6 +1853,18 @@ void TextField::AddDecoration(Actor& actor, bool needsClipping)
   }
 }
 
+void TextField::GetControlBackgroundColor(Vector4& color) const
+{
+  Property::Value propValue = Self().GetProperty(Toolkit::Control::Property::BACKGROUND);
+  Property::Map*  resultMap = propValue.GetMap();
+
+  Property::Value* colorValue = nullptr;
+  if(resultMap && (colorValue = resultMap->Find(ColorVisual::Property::MIX_COLOR)))
+  {
+    colorValue->Get(color);
+  }
+}
+
 void TextField::OnSceneConnect(Dali::Actor actor)
 {
   if(mHasBeenStaged)
@@ -1852,6 +1950,11 @@ bool TextField::OnTouched(Actor actor, const TouchEvent& touch)
   return false;
 }
 
+void TextField::OnLayoutDirectionChanged(Actor actor, LayoutDirection::Type type)
+{
+  mController->ChangedLayoutDirection();
+}
+
 void TextField::OnIdleSignal()
 {
   // Emits the change of input style signals.
@@ -1867,7 +1970,8 @@ TextField::TextField()
   mAlignmentOffset(0.f),
   mRenderingBackend(DEFAULT_RENDERING_BACKEND),
   mExceedPolicy(Dali::Toolkit::TextField::EXCEED_POLICY_CLIP),
-  mHasBeenStaged(false)
+  mHasBeenStaged(false),
+  mTextChanged(false)
 {
 }
 
@@ -1883,60 +1987,64 @@ TextField::~TextField()
 
 std::string TextField::AccessibleImpl::GetName()
 {
-  auto slf = Toolkit::TextField::DownCast(self);
-  return slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
+  auto self = Toolkit::TextField::DownCast(Self());
+  return self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
 }
 
-std::string TextField::AccessibleImpl::GetText(size_t startOffset,
-                                               size_t endOffset)
+std::string TextField::AccessibleImpl::GetText(size_t startOffset, size_t endOffset)
 {
   if(endOffset <= startOffset)
+  {
     return {};
+  }
 
-  auto slf = Toolkit::TextField::DownCast(self);
-  auto txt =
-    slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
+  auto self = Toolkit::TextField::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
 
-  if(startOffset > txt.size() || endOffset > txt.size())
+  if(startOffset > text.size() || endOffset > text.size())
+  {
     return {};
+  }
 
-  return txt.substr(startOffset, endOffset - startOffset);
+  return text.substr(startOffset, endOffset - startOffset);
 }
 
 size_t TextField::AccessibleImpl::GetCharacterCount()
 {
-  auto slf = Toolkit::TextField::DownCast(self);
-  auto txt =
-    slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
+  auto self = Toolkit::TextField::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
 
-  return txt.size();
+  return text.size();
 }
 
-size_t TextField::AccessibleImpl::GetCaretOffset()
+size_t TextField::AccessibleImpl::GetCursorOffset()
 {
-  auto slf = Toolkit::TextField::DownCast(self);
-  return Dali::Toolkit::GetImpl(slf).getController()->GetCursorPosition();
+  auto self = Toolkit::TextField::DownCast(Self());
+  return Dali::Toolkit::GetImpl(self).GetTextController()->GetCursorPosition();
 }
 
-bool TextField::AccessibleImpl::SetCaretOffset(size_t offset)
+bool TextField::AccessibleImpl::SetCursorOffset(size_t offset)
 {
-  auto slf = Toolkit::TextField::DownCast(self);
-  auto txt = slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-  if(offset > txt.size())
+  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();
 
-  auto& slfImpl = Dali::Toolkit::GetImpl(slf);
-  slfImpl.getController()->ResetCursorPosition(offset);
-  slfImpl.RequestTextRelayout();
   return true;
 }
 
 Dali::Accessibility::Range TextField::AccessibleImpl::GetTextAtOffset(
   size_t offset, Dali::Accessibility::TextBoundary boundary)
 {
-  auto slf      = Toolkit::TextField::DownCast(self);
-  auto txt      = slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-  auto txt_size = txt.size();
+  auto self = Toolkit::TextField::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
+  auto textSize = text.size();
 
   auto range = Dali::Accessibility::Range{};
 
@@ -1944,62 +2052,78 @@ Dali::Accessibility::Range TextField::AccessibleImpl::GetTextAtOffset(
   {
     case Dali::Accessibility::TextBoundary::CHARACTER:
     {
-      if(offset < txt_size)
+      if(offset < textSize)
       {
-        range.content     = txt[offset];
+        range.content     = text[offset];
         range.startOffset = offset;
         range.endOffset   = offset + 1;
       }
+      break;
     }
-    break;
     case Dali::Accessibility::TextBoundary::WORD:
     case Dali::Accessibility::TextBoundary::LINE:
     {
-      auto txt_c_string = txt.c_str();
-      auto breaks       = std::vector<char>(txt_size, 0);
+      auto textString = text.c_str();
+      auto breaks = std::vector<char>(textSize, 0);
+
       if(boundary == Dali::Accessibility::TextBoundary::WORD)
-        Accessibility::Accessible::FindWordSeparationsUtf8((const utf8_t*)txt_c_string, txt_size, "", breaks.data());
+      {
+        Accessibility::Accessible::FindWordSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
+      }
       else
-        Accessibility::Accessible::FindLineSeparationsUtf8((const utf8_t*)txt_c_string, txt_size, "", breaks.data());
+      {
+        Accessibility::Accessible::FindLineSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
+      }
+
       auto index   = 0u;
       auto counter = 0u;
-      while(index < txt_size && counter <= offset)
+      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     = txt.substr(start, index - start + 1);
+          range.content     = text.substr(start, index - start + 1);
           range.startOffset = start;
           range.endOffset   = index + 1;
         }
+
         if(boundary == Dali::Accessibility::TextBoundary::LINE)
+        {
           index++;
+        }
       }
+      break;
     }
-    break;
     case Dali::Accessibility::TextBoundary::SENTENCE:
     {
-      /* not supported by efl */
+      /* not supported by default */
+      break;
     }
-    break;
     case Dali::Accessibility::TextBoundary::PARAGRAPH:
     {
       /* Paragraph is not supported by libunibreak library */
+      break;
     }
-    break;
     default:
       break;
   }
@@ -2007,72 +2131,90 @@ Dali::Accessibility::Range TextField::AccessibleImpl::GetTextAtOffset(
   return range;
 }
 
-Dali::Accessibility::Range
-TextField::AccessibleImpl::GetSelection(size_t selectionNum)
+Dali::Accessibility::Range TextField::AccessibleImpl::GetRangeOfSelection(size_t selectionIndex)
 {
   // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionNum > 0)
+  if(selectionIndex > 0)
+  {
     return {};
+  }
 
-  auto        slf  = Toolkit::TextField::DownCast(self);
-  auto        ctrl = Dali::Toolkit::GetImpl(slf).getController();
-  std::string ret;
-  ctrl->RetrieveSelection(ret);
-  auto r = ctrl->GetSelectionIndexes();
+  auto self  = Toolkit::TextField::DownCast(Self());
+  auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
+  std::string value{};
+  controller->RetrieveSelection(value);
+  auto indices = controller->GetSelectionIndexes();
 
-  return {static_cast<size_t>(r.first), static_cast<size_t>(r.second), ret};
+  return {static_cast<size_t>(indices.first), static_cast<size_t>(indices.second), value};
 }
 
-bool TextField::AccessibleImpl::RemoveSelection(size_t selectionNum)
+bool TextField::AccessibleImpl::RemoveSelection(size_t selectionIndex)
 {
   // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionNum > 0)
+  if(selectionIndex > 0)
+  {
     return false;
+  }
 
-  auto slf = Toolkit::TextField::DownCast(self);
-  Dali::Toolkit::GetImpl(slf).getController()->SetSelection(0, 0);
+  auto self = Toolkit::TextField::DownCast(Self());
+  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(0, 0);
   return true;
 }
 
-bool TextField::AccessibleImpl::SetSelection(size_t selectionNum,
-                                             size_t startOffset,
-                                             size_t endOffset)
+bool TextField::AccessibleImpl::SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset)
 {
   // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionNum > 0)
+  if(selectionIndex > 0)
+  {
     return false;
+  }
 
-  auto slf = Toolkit::TextField::DownCast(self);
-  Dali::Toolkit::GetImpl(slf).getController()->SetSelection(startOffset,
-                                                            endOffset);
+  auto self = Toolkit::TextField::DownCast(Self());
+  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(startOffset, endOffset);
   return true;
 }
 
-bool TextField::AccessibleImpl::CopyText(size_t startPosition,
-                                         size_t endPosition)
+bool TextField::AccessibleImpl::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::AccessibleImpl::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));
 
-  auto slf = Toolkit::TextField::DownCast(self);
-  auto txt = slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-  Dali::Toolkit::GetImpl(slf).getController()->CopyStringToClipboard(txt.substr(startPosition, endPosition - startPosition));
+  self.SetProperty(Toolkit::TextField::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition));
 
   return true;
 }
 
-bool TextField::AccessibleImpl::CutText(size_t startPosition,
-                                        size_t endPosition)
+bool TextField::AccessibleImpl::DeleteText(size_t startPosition, size_t endPosition)
 {
   if(endPosition <= startPosition)
+  {
     return false;
+  }
 
-  auto slf = Toolkit::TextField::DownCast(self);
-  auto txt = slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-  Dali::Toolkit::GetImpl(slf).getController()->CopyStringToClipboard(txt.substr(startPosition, endPosition - startPosition));
+  auto self = Toolkit::TextField::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
 
-  slf.SetProperty(Toolkit::TextField::Property::TEXT,
-                  txt.substr(0, startPosition) + txt.substr(endPosition - startPosition, txt.size()));
+  self.SetProperty(Toolkit::TextField::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition));
 
   return true;
 }
@@ -2081,13 +2223,13 @@ Dali::Accessibility::States TextField::AccessibleImpl::CalculateStates()
 {
   using namespace Dali::Accessibility;
 
-  auto states = Control::Impl::AccessibleImpl::CalculateStates();
+  auto states = DevelControl::AccessibleImpl::CalculateStates();
 
   states[State::EDITABLE]  = true;
   states[State::FOCUSABLE] = true;
 
   Toolkit::Control focusControl = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl();
-  if(self == focusControl)
+  if(mSelf == focusControl)
   {
     states[State::FOCUSED] = true;
   }
@@ -2095,6 +2237,25 @@ Dali::Accessibility::States TextField::AccessibleImpl::CalculateStates()
   return states;
 }
 
+bool TextField::AccessibleImpl::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;
+}
+
+bool TextField::AccessibleImpl::SetTextContents(std::string newContents)
+{
+  auto self = Toolkit::TextField::DownCast(Self());
+  self.SetProperty(Toolkit::TextField::Property::TEXT, std::move(newContents));
+  return true;
+}
+
 } // namespace Internal
 
 } // namespace Toolkit