Fix RemoveText issue in text controller
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-controller-text-updater.cpp
index caf44f7..4d0ba8f 100644 (file)
@@ -24,6 +24,8 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/characters-helper-functions.h>
+#include <dali-toolkit/internal/text/emoji-helper.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>
@@ -91,7 +93,9 @@ void Controller::TextUpdater::SetText(Controller& controller, const std::string&
                                         logicalModel->mAnchors,
                                         logicalModel->mUnderlinedCharacterRuns,
                                         logicalModel->mBackgroundColorRuns,
-                                        logicalModel->mStrikethroughCharacterRuns);
+                                        logicalModel->mStrikethroughCharacterRuns,
+                                        logicalModel->mBoundedParagraphRuns,
+                                        logicalModel->mCharacterSpacingCharacterRuns);
 
     Length         textSize = 0u;
     const uint8_t* utf8     = NULL;
@@ -469,6 +473,7 @@ bool Controller::TextUpdater::RemoveText(
   UpdateInputStyleType type)
 {
   bool removed = false;
+  bool removeAll = false;
 
   Controller::Impl& impl      = *controller.mImpl;
   EventData*&       eventData = impl.mEventData;
@@ -480,6 +485,7 @@ bool Controller::TextUpdater::RemoveText(
 
   ModelPtr&        model        = impl.mModel;
   LogicalModelPtr& logicalModel = model->mLogicalModel;
+  VisualModelPtr&  visualModel  = model->mVisualModel;
 
   DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::RemoveText %p mText.Count() %d cursor %d cursorOffset %d numberOfCharacters %d\n", &controller, logicalModel->mText.Count(), eventData->mPrimaryCursorPosition, cursorOffset, numberOfCharacters);
 
@@ -497,14 +503,38 @@ bool Controller::TextUpdater::RemoveText(
       cursorIndex = eventData->mPrimaryCursorPosition + cursorOffset;
     }
 
+    //Handle Emoji clustering for cursor handling
+    // Deletion case: this is handling the deletion cases when the cursor is before or after Emoji
+    //  - Before: when use delete key and cursor is before Emoji (cursorOffset = -1)
+    //  - After: when use backspace key and cursor is after Emoji (cursorOffset = 0)
+
+    const Script script = logicalModel->GetScript(cursorIndex);
+    if((numberOfCharacters == 1u) &&
+       (IsOneOfEmojiScripts(script)))
+    {
+      //TODO: Use this clustering for Emoji cases only. This needs more testing to generalize to all scripts.
+      CharacterRun emojiClusteredCharacters = RetrieveClusteredCharactersOfCharacterIndex(visualModel, logicalModel, cursorIndex);
+      Length       actualNumberOfCharacters = emojiClusteredCharacters.numberOfCharacters;
+
+      //Set cursorIndex at the first characterIndex of clustred Emoji
+      cursorIndex = emojiClusteredCharacters.characterIndex;
+
+      numberOfCharacters = actualNumberOfCharacters;
+    }
+
     if((cursorIndex + numberOfCharacters) > currentText.Count())
     {
       numberOfCharacters = currentText.Count() - cursorIndex;
     }
 
+    if((cursorIndex == 0) && (currentText.Count() - numberOfCharacters == 0))
+    {
+      removeAll = true;
+    }
+
     TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo;
 
-    if(eventData->mPreEditFlag || // If the preedit flag is enabled, it means two (or more) of them came together i.e. when two keys have been pressed at the same time.
+    if(eventData->mPreEditFlag || removeAll || // If the preedit flag is enabled, it means two (or more) of them came together i.e. when two keys have been pressed at the same time.
        ((cursorIndex + numberOfCharacters) <= textUpdateInfo.mPreviousNumberOfCharacters))
     {
       // Mark the paragraphs to be updated.
@@ -550,7 +580,7 @@ bool Controller::TextUpdater::RemoveText(
 
       // If the number of current text and the number of characters to be deleted are same,
       // it means all texts should be removed and all Preedit variables should be initialized.
-      if((currentText.Count() - numberOfCharacters == 0) && (cursorIndex == 0))
+      if(removeAll)
       {
         impl.ClearPreEditFlag();
         textUpdateInfo.mNumberOfCharactersToAdd = 0;
@@ -593,6 +623,7 @@ bool Controller::TextUpdater::RemoveText(
       }
 
       DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::RemoveText %p removed %d\n", &controller, numberOfCharacters);
+      removeAll = false;
       removed = true;
     }
   }