Removed some redundant methods from TextController & Moved some code to other files
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-controller-text-updater.cpp
index c22e207..0bcb97f 100644 (file)
@@ -26,6 +26,7 @@
 #include <dali-toolkit/internal/text/character-set-conversion.h>
 #include <dali-toolkit/internal/text/markup-processor.h>
 #include <dali-toolkit/internal/text/text-controller-impl.h>
+#include <dali-toolkit/internal/text/text-controller-placeholder-handler.h>
 #include <dali-toolkit/internal/text/text-editable-control-interface.h>
 
 namespace
@@ -55,7 +56,7 @@ void Controller::TextUpdater::SetText(Controller& controller, const std::string&
   ResetText(controller);
 
   // Remove the style.
-  controller.ClearStyleData();
+  impl.ClearStyleData();
 
   CharacterIndex lastCursorIndex = 0u;
 
@@ -69,6 +70,11 @@ void Controller::TextUpdater::SetText(Controller& controller, const std::string&
        (EventData::EDITING_WITH_GRAB_HANDLE == eventData->mState) ||
        (EventData::EDITING_WITH_PASTE_POPUP == eventData->mState))
     {
+      if((impl.mSelectableControlInterface != nullptr) && (EventData::SELECTING == eventData->mState))
+      {
+        impl.mSelectableControlInterface->SelectionChanged(eventData->mLeftSelectionPosition, eventData->mRightSelectionPosition, eventData->mPrimaryCursorPosition, eventData->mPrimaryCursorPosition);
+      }
+
       impl.ChangeState(EventData::EDITING);
     }
   }
@@ -81,7 +87,10 @@ void Controller::TextUpdater::SetText(Controller& controller, const std::string&
 
     MarkupProcessData markupProcessData(logicalModel->mColorRuns,
                                         logicalModel->mFontDescriptionRuns,
-                                        logicalModel->mEmbeddedItems);
+                                        logicalModel->mEmbeddedItems,
+                                        logicalModel->mAnchors,
+                                        logicalModel->mUnderlinedCharacterRuns,
+                                        logicalModel->mBackgroundColorRuns);
 
     Length         textSize = 0u;
     const uint8_t* utf8     = NULL;
@@ -133,14 +142,16 @@ void Controller::TextUpdater::SetText(Controller& controller, const std::string&
   }
   else
   {
-    controller.ShowPlaceholderText();
+    PlaceholderHandler::ShowPlaceholderText(impl);
   }
 
+  unsigned int oldCursorPos = (nullptr != eventData ? eventData->mPrimaryCursorPosition : 0);
+
   // Resets the cursor position.
   controller.ResetCursorPosition(lastCursorIndex);
 
   // Scrolls the text to make the cursor visible.
-  controller.ResetScrollPosition();
+  impl.ResetScrollPosition();
 
   impl.RequestRelayout();
 
@@ -153,7 +164,8 @@ void Controller::TextUpdater::SetText(Controller& controller, const std::string&
   // Do this last since it provides callbacks into application code.
   if(NULL != impl.mEditableControlInterface)
   {
-    impl.mEditableControlInterface->TextChanged();
+    impl.mEditableControlInterface->CursorPositionChanged(oldCursorPos, lastCursorIndex);
+    impl.mEditableControlInterface->TextChanged(true);
   }
 }
 
@@ -169,9 +181,10 @@ void Controller::TextUpdater::InsertText(Controller& controller, const std::stri
     return;
   }
 
-  bool removedPrevious  = false;
-  bool removedSelected  = false;
-  bool maxLengthReached = false;
+  bool         removedPrevious  = false;
+  bool         removedSelected  = false;
+  bool         maxLengthReached = false;
+  unsigned int oldCursorPos     = eventData->mPrimaryCursorPosition;
 
   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::InsertText %p %s (%s) mPrimaryCursorPosition %d mPreEditFlag %d mPreEditStartPosition %d mPreEditLength %d\n", &controller, text.c_str(), (COMMIT == type ? "COMMIT" : "PRE_EDIT"), eventData->mPrimaryCursorPosition, eventData->mPreEditFlag, eventData->mPreEditStartPosition, eventData->mPreEditLength);
 
@@ -253,7 +266,8 @@ void Controller::TextUpdater::InsertText(Controller& controller, const std::stri
     const Length numberOfCharactersInModel = logicalModel->mText.Count();
 
     // Restrict new text to fit within Maximum characters setting.
-    Length maxSizeOfNewText = std::min((impl.mMaximumNumberOfCharacters - numberOfCharactersInModel), characterCount);
+    Length temp_length      = (impl.mMaximumNumberOfCharacters > numberOfCharactersInModel ? impl.mMaximumNumberOfCharacters - numberOfCharactersInModel : 0);
+    Length maxSizeOfNewText = std::min(temp_length, characterCount);
     maxLengthReached        = (characterCount > maxSizeOfNewText);
 
     // The cursor position.
@@ -377,6 +391,11 @@ void Controller::TextUpdater::InsertText(Controller& controller, const std::stri
       textUpdateInfo.mNumberOfCharactersToAdd += maxSizeOfNewText;
     }
 
+    if(impl.mMarkupProcessorEnabled)
+    {
+      InsertTextAnchor(controller, maxSizeOfNewText, cursorIndex);
+    }
+
     // Update the cursor index.
     cursorIndex += maxSizeOfNewText;
 
@@ -387,7 +406,7 @@ void Controller::TextUpdater::InsertText(Controller& controller, const std::stri
      impl.IsPlaceholderAvailable())
   {
     // Show place-holder if empty after removing the pre-edit text
-    controller.ShowPlaceholderText();
+    PlaceholderHandler::ShowPlaceholderText(impl);
     eventData->mUpdateCursorPosition = true;
     impl.ClearPreEditFlag();
   }
@@ -409,6 +428,11 @@ void Controller::TextUpdater::InsertText(Controller& controller, const std::stri
     }
   }
 
+  if(nullptr != impl.mEditableControlInterface)
+  {
+    impl.mEditableControlInterface->CursorPositionChanged(oldCursorPos, eventData->mPrimaryCursorPosition);
+  }
+
   if(maxLengthReached)
   {
     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "MaxLengthReached (%d)\n", logicalModel->mText.Count());
@@ -433,7 +457,7 @@ void Controller::TextUpdater::PasteText(Controller& controller, const std::strin
   if(NULL != impl.mEditableControlInterface)
   {
     // Do this last since it provides callbacks into application code
-    impl.mEditableControlInterface->TextChanged();
+    impl.mEditableControlInterface->TextChanged(true);
   }
 }
 
@@ -461,8 +485,8 @@ bool Controller::TextUpdater::RemoveText(
   if(!impl.IsShowingPlaceholderText())
   {
     // Delete at current cursor position
-    Vector<Character>& currentText    = logicalModel->mText;
-    CharacterIndex&    oldCursorIndex = eventData->mPrimaryCursorPosition;
+    Vector<Character>& currentText         = logicalModel->mText;
+    CharacterIndex&    previousCursorIndex = eventData->mPrimaryCursorPosition;
 
     CharacterIndex cursorIndex = 0;
 
@@ -547,8 +571,18 @@ bool Controller::TextUpdater::RemoveText(
 
       currentText.Erase(first, last);
 
+      if(impl.mMarkupProcessorEnabled)
+      {
+        RemoveTextAnchor(controller, cursorOffset, numberOfCharacters, previousCursorIndex);
+      }
+
+      if(nullptr != impl.mEditableControlInterface)
+      {
+        impl.mEditableControlInterface->CursorPositionChanged(previousCursorIndex, cursorIndex);
+      }
+
       // Cursor position retreat
-      oldCursorIndex = cursorIndex;
+      previousCursorIndex = cursorIndex;
 
       eventData->mScrollAfterDelete = true;
 
@@ -574,12 +608,30 @@ bool Controller::TextUpdater::RemoveSelectedText(Controller& controller)
   if(EventData::SELECTING == impl.mEventData->mState)
   {
     std::string removedString;
+    uint32_t    oldSelStart = impl.mEventData->mLeftSelectionPosition;
+    uint32_t    oldSelEnd   = impl.mEventData->mRightSelectionPosition;
+
     impl.RetrieveSelection(removedString, true);
 
     if(!removedString.empty())
     {
       textRemoved = true;
       impl.ChangeState(EventData::EDITING);
+
+      if(impl.mMarkupProcessorEnabled)
+      {
+        int             cursorOffset        = -1;
+        int             numberOfCharacters  = removedString.length();
+        CharacterIndex& cursorIndex         = impl.mEventData->mPrimaryCursorPosition;
+        CharacterIndex  previousCursorIndex = cursorIndex + numberOfCharacters;
+
+        RemoveTextAnchor(controller, cursorOffset, numberOfCharacters, previousCursorIndex);
+      }
+
+      if(impl.mSelectableControlInterface != nullptr)
+      {
+        impl.mSelectableControlInterface->SelectionChanged(oldSelStart, oldSelEnd, impl.mEventData->mPrimaryCursorPosition, impl.mEventData->mPrimaryCursorPosition);
+      }
     }
   }
 
@@ -597,6 +649,9 @@ void Controller::TextUpdater::ResetText(Controller& controller)
   // Reset the embedded images buffer.
   logicalModel->ClearEmbeddedImages();
 
+  // Reset the anchors buffer.
+  logicalModel->ClearAnchors();
+
   // We have cleared everything including the placeholder-text
   impl.PlaceholderCleared();
 
@@ -617,6 +672,128 @@ void Controller::TextUpdater::ResetText(Controller& controller)
   impl.mOperationsPending = ALL_OPERATIONS;
 }
 
+void Controller::TextUpdater::InsertTextAnchor(Controller& controller, int numberOfCharacters, CharacterIndex previousCursorIndex)
+{
+  Controller::Impl& impl         = *controller.mImpl;
+  ModelPtr&         model        = impl.mModel;
+  LogicalModelPtr&  logicalModel = model->mLogicalModel;
+
+  for(auto& anchor : logicalModel->mAnchors)
+  {
+    if(anchor.endIndex < previousCursorIndex) //      [anchor]  CUR
+    {
+      continue;
+    }
+    if(anchor.startIndex < previousCursorIndex) //      [anCURr]
+    {
+      anchor.endIndex += numberOfCharacters;
+    }
+    else // CUR  [anchor]
+    {
+      anchor.startIndex += numberOfCharacters;
+      anchor.endIndex += numberOfCharacters;
+    }
+    DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::InsertTextAnchor[%p] Anchor[%s] start[%d] end[%d]\n", &controller, anchor.href, anchor.startIndex, anchor.endIndex);
+  }
+}
+
+void Controller::TextUpdater::RemoveTextAnchor(Controller& controller, int cursorOffset, int numberOfCharacters, CharacterIndex previousCursorIndex)
+{
+  Controller::Impl&        impl         = *controller.mImpl;
+  ModelPtr&                model        = impl.mModel;
+  LogicalModelPtr&         logicalModel = model->mLogicalModel;
+  Vector<Anchor>::Iterator it           = logicalModel->mAnchors.Begin();
+
+  while(it != logicalModel->mAnchors.End())
+  {
+    Anchor& anchor = *it;
+
+    if(anchor.endIndex <= previousCursorIndex && cursorOffset == 0) // [anchor]    CUR >>
+    {
+      // Nothing happens.
+    }
+    else if(anchor.endIndex <= previousCursorIndex && cursorOffset == -1) // [anchor] << CUR
+    {
+      int endIndex = anchor.endIndex;
+      int offset   = previousCursorIndex - endIndex;
+      int index    = endIndex - (numberOfCharacters - offset);
+
+      if(index < endIndex)
+      {
+        endIndex = index;
+      }
+
+      if((int)anchor.startIndex >= endIndex)
+      {
+        if(anchor.href)
+        {
+          delete[] anchor.href;
+        }
+        it = logicalModel->mAnchors.Erase(it);
+        continue;
+      }
+      else
+      {
+        anchor.endIndex = endIndex;
+      }
+    }
+    else if(anchor.startIndex >= previousCursorIndex && cursorOffset == -1) // << CUR    [anchor]
+    {
+      anchor.startIndex -= numberOfCharacters;
+      anchor.endIndex -= numberOfCharacters;
+    }
+    else if(anchor.startIndex >= previousCursorIndex && cursorOffset == 0) //    CUR >> [anchor]
+    {
+      int startIndex = anchor.startIndex;
+      int endIndex   = anchor.endIndex;
+      int index      = previousCursorIndex + numberOfCharacters - 1;
+
+      if(startIndex > index)
+      {
+        anchor.startIndex -= numberOfCharacters;
+        anchor.endIndex -= numberOfCharacters;
+      }
+      else if(endIndex > index + 1)
+      {
+        anchor.endIndex -= numberOfCharacters;
+      }
+      else
+      {
+        if(anchor.href)
+        {
+          delete[] anchor.href;
+        }
+        it = logicalModel->mAnchors.Erase(it);
+        continue;
+      }
+    }
+    else if(cursorOffset == -1) // [<< CUR]
+    {
+      int startIndex = anchor.startIndex;
+      int index      = previousCursorIndex - numberOfCharacters;
+
+      if(startIndex >= index)
+      {
+        anchor.startIndex = index;
+      }
+      anchor.endIndex -= numberOfCharacters;
+    }
+    else if(cursorOffset == 0) // [CUR >>]
+    {
+      anchor.endIndex -= numberOfCharacters;
+    }
+    else
+    {
+      // When this condition is reached, someting is wrong.
+      DALI_LOG_ERROR("Controller::RemoveTextAnchor[%p] Invaild state cursorOffset[%d]\n", &controller, cursorOffset);
+    }
+
+    DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::RemoveTextAnchor[%p] Anchor[%s] start[%d] end[%d]\n", &controller, anchor.href, anchor.startIndex, anchor.endIndex);
+
+    it++;
+  }
+}
+
 } // namespace Text
 
 } // namespace Toolkit