Add exception handling in text-controller
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-controller-impl.cpp
index 279f23b..045fb8a 100644 (file)
@@ -85,7 +85,7 @@ namespace Text
 EventData::EventData(DecoratorPtr decorator, InputMethodContext& inputMethodContext)
 : mDecorator(decorator),
   mInputMethodContext(inputMethodContext),
-  mPlaceholderFont(NULL),
+  mPlaceholderFont(nullptr),
   mPlaceholderTextActive(),
   mPlaceholderTextInactive(),
   mPlaceholderTextColor(0.8f, 0.8f, 0.8f, 0.8f), // This color has been published in the Public API (placeholder-properties.h).
@@ -507,10 +507,14 @@ void Controller::Impl::ClearGlyphModelData(CharacterIndex startIndex, CharacterI
     mModel->mVisualModel->mCharactersPerGlyph.Erase(charactersPerGlyphBuffer + mTextUpdateInfo.mStartGlyphIndex,
                                                     charactersPerGlyphBuffer + endGlyphIndexPlusOne);
 
-    // Clear the positions buffer.
-    Vector2* positionsBuffer = mModel->mVisualModel->mGlyphPositions.Begin();
-    mModel->mVisualModel->mGlyphPositions.Erase(positionsBuffer + mTextUpdateInfo.mStartGlyphIndex,
-                                                positionsBuffer + endGlyphIndexPlusOne);
+    // Should pass if mGlyphPositions has already been cleared in Controller::Relayouter::Relayout
+    if(0u != mModel->mVisualModel->mGlyphPositions.Count())
+    {
+      // Clear the positions buffer.
+      Vector2* positionsBuffer = mModel->mVisualModel->mGlyphPositions.Begin();
+      mModel->mVisualModel->mGlyphPositions.Erase(positionsBuffer + mTextUpdateInfo.mStartGlyphIndex,
+                                                  positionsBuffer + endGlyphIndexPlusOne);
+    }
   }
 
   if(NO_OPERATION != (LAYOUT & operations))
@@ -1209,7 +1213,9 @@ void Controller::Impl::SetTextSelectionRange(const uint32_t* pStart, const uint3
 
   if(mEventData->mSelectionEnabled && (pStart || pEnd))
   {
-    uint32_t length = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
+    uint32_t length   = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
+    uint32_t oldStart = mEventData->mLeftSelectionPosition;
+    uint32_t oldEnd   = mEventData->mRightSelectionPosition;
 
     if(pStart)
     {
@@ -1233,6 +1239,11 @@ void Controller::Impl::SetTextSelectionRange(const uint32_t* pStart, const uint3
       mEventData->mUpdateLeftSelectionPosition  = true;
       mEventData->mUpdateRightSelectionPosition = true;
     }
+
+    if(mSelectableControlInterface != nullptr)
+    {
+      mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition);
+    }
   }
 }
 
@@ -1245,7 +1256,7 @@ CharacterIndex Controller::Impl::GetPrimaryCursorPosition() const
   return mEventData->mPrimaryCursorPosition;
 }
 
-bool Controller::Impl::SetPrimaryCursorPosition(CharacterIndex index)
+bool Controller::Impl::SetPrimaryCursorPosition(CharacterIndex index, bool focused)
 {
   if(nullptr == mEventData)
   {
@@ -1253,18 +1264,38 @@ bool Controller::Impl::SetPrimaryCursorPosition(CharacterIndex index)
     return false;
   }
 
-  if(mEventData->mPrimaryCursorPosition == index)
+  if(mEventData->mPrimaryCursorPosition == index && mEventData->mState != EventData::SELECTING)
   {
     // Nothing for same cursor position.
     return false;
   }
 
   uint32_t length                    = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
+  uint32_t oldCursorPos              = mEventData->mPrimaryCursorPosition;
   mEventData->mPrimaryCursorPosition = std::min(index, length);
-  ChangeState(EventData::EDITING);
-  mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition = mEventData->mPrimaryCursorPosition;
-  mEventData->mUpdateCursorPosition                                        = true;
-  ScrollTextToMatchCursor();
+  // If there is no focus, only the value is updated.
+  if(focused)
+  {
+    bool     wasInSelectingState = mEventData->mState == EventData::SELECTING;
+    uint32_t oldStart            = mEventData->mLeftSelectionPosition;
+    uint32_t oldEnd              = mEventData->mRightSelectionPosition;
+    ChangeState(EventData::EDITING);
+    mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition = mEventData->mPrimaryCursorPosition;
+    mEventData->mUpdateCursorPosition                                        = true;
+
+    if(mSelectableControlInterface != nullptr && wasInSelectingState)
+    {
+      mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition);
+    }
+
+    ScrollTextToMatchCursor();
+  }
+
+  if(nullptr != mEditableControlInterface)
+  {
+    mEditableControlInterface->CursorPositionChanged(oldCursorPos, mEventData->mPrimaryCursorPosition);
+  }
+
   return true;
 }
 
@@ -1373,9 +1404,17 @@ void Controller::Impl::RetrieveSelection(std::string& selectedText, bool deleteA
 
 void Controller::Impl::SetSelection(int start, int end)
 {
+  uint32_t oldStart = mEventData->mLeftSelectionPosition;
+  uint32_t oldEnd   = mEventData->mRightSelectionPosition;
+
   mEventData->mLeftSelectionPosition  = start;
   mEventData->mRightSelectionPosition = end;
   mEventData->mUpdateCursorPosition   = true;
+
+  if(mSelectableControlInterface != nullptr)
+  {
+    mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, start, end);
+  }
 }
 
 std::pair<int, int> Controller::Impl::GetSelectionIndexes() const